windows-nt/Source/XPSP1/NT/admin/activec/designer/vb98ctls/include/wcutil.h

750 lines
26 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//=--------------------------------------------------------------------------=
// WCUtil.H
//=--------------------------------------------------------------------------=
// Copyright (c) 1987-1998, Microsoft Corp.
// All Rights Reserved
// Information Contained Herein Is Proprietary and Confidential.
//=--------------------------------------------------------------------------=
//
// Utitlity Routines for the WebClass Designer
//
#ifndef _WCUTIL_H_
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_ANSIFromWideStr(WCHAR * pwszWideStr, char **ppszAnsi)
//
// Converts null terminated WCHAR string to null terminated ANSI string.
// Allocates ANSI string using new operator. If successful, caller must free
// ANSI string with delete operator.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_ANSIFromWideStr(WCHAR *pwszWideStr, char **ppszAnsi)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_ANSIFromWideStr"));
HRESULT hr = S_OK;
*ppszAnsi = NULL;
int cchWideStr = (int)::wcslen(pwszWideStr);
int cchConverted = 0;
// get required buffer length
int cchAnsi = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pwszWideStr, // address of wide-character string
cchWideStr, // number of characters in string
NULL, // address of buffer for new string
0, // size of buffer
NULL, // address of default for unmappable characters
NULL // address of flag set when default char. used
);
CSF_CHECK(0 != cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// allocate a buffer for the ANSI string
*ppszAnsi = new char [cchAnsi + 1];
CSF_CHECK(NULL != *ppszAnsi, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
// now convert the string and copy it to the buffer
cchConverted = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pwszWideStr, // address of wide-character string
cchWideStr, // number of characters in string
*ppszAnsi, // address of buffer for new string
cchAnsi, // size of buffer
NULL, // address of default for unmappable characters
NULL // address of flag set when default char. used
);
CSF_CHECK(cchConverted == cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// add terminating null byte
*( (*ppszAnsi) + cchAnsi ) = '\0';
CLEANUP:
if (FAILED(hr))
{
if (NULL != *ppszAnsi)
{
delete [] *ppszAnsi;
*ppszAnsi = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_ANSIFromWideStr hr = %08.8X"), hr);
return hr;
}
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_ANSIFromWideStr(WCHAR * pwszWideStr, char **ppszAnsi)
//
// Converts null terminated WCHAR string to null terminated ANSI string.
// Allocates ANSI string using new operator. If successful, caller must free
// ANSI string with delete operator.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_ANSIFromWideStrLen(WCHAR *pwszWideStr, int cchWideStr, char **ppszAnsi)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_ANSIFromWideStr"));
HRESULT hr = S_OK;
*ppszAnsi = NULL;
int cchConverted = 0;
// get required buffer length
int cchAnsi = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pwszWideStr, // address of wide-character string
cchWideStr, // number of characters in string
NULL, // address of buffer for new string
0, // size of buffer
NULL, // address of default for unmappable characters
NULL // address of flag set when default char. used
);
CSF_CHECK(0 != cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// allocate a buffer for the ANSI string
*ppszAnsi = new char [cchAnsi + 1];
CSF_CHECK(NULL != *ppszAnsi, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
// now convert the string and copy it to the buffer
cchConverted = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pwszWideStr, // address of wide-character string
cchWideStr, // number of characters in string
*ppszAnsi, // address of buffer for new string
cchAnsi, // size of buffer
NULL, // address of default for unmappable characters
NULL // address of flag set when default char. used
);
CSF_CHECK(cchConverted == cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// add terminating null byte
*( (*ppszAnsi) + cchAnsi ) = '\0';
CLEANUP:
if (FAILED(hr))
{
if (NULL != *ppszAnsi)
{
delete [] *ppszAnsi;
*ppszAnsi = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_ANSIFromWideStr hr = %08.8X"), hr);
return hr;
}
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_WideStrFromANSI(char *pszAnsi, WCHAR **ppwszWideStr))
//
// Converts null terminated ANSI string to a null terminated WCHAR string.
// Allocates WCHAR string buffer using the new operator. If successful, caller
// must free WCHAR string using the delete operator.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_WideStrFromANSI(char *pszAnsi, WCHAR **ppwszWideStr)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_WideStrFromANSI"));
HRESULT hr = S_OK;
*ppwszWideStr = NULL;
int cchANSI = ::strlen(pszAnsi);
int cchConverted = 0;
// get required buffer length
int cchWideStr = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pszAnsi, // address of multibyte string
cchANSI, // number of characters in string
NULL, // address of buffer for new string
0 // size of buffer
);
CSF_CHECK(0 != cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// allocate a buffer for the WCHAR *
*ppwszWideStr = new WCHAR[cchWideStr + 1];
CSF_CHECK(NULL != *ppwszWideStr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
// now convert the string and copy it to the buffer
cchConverted = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pszAnsi, // address of multibyte string
cchANSI, // number of characters in string
*ppwszWideStr, // address of buffer for new string
cchWideStr // size of buffer
);
CSF_CHECK(cchConverted == cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// add terminating null character
*( (*ppwszWideStr) + cchWideStr ) = L'\0';
CLEANUP:
if (FAILED(hr))
{
if (NULL != *ppwszWideStr)
{
delete [] *ppwszWideStr;
*ppwszWideStr = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_WideStrFromANSI hr = %08.8X"), hr);
return hr;
}
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_WideStrFromANSIExtra(char *pszAnsi, WCHAR **ppwszWideStr))
//
// Converts null terminated ANSI string to a null terminated WCHAR string.
// Allocates WCHAR string buffer using the new operator. If successful, caller
// must free WCHAR string using the delete operator.
//
// User can also specify the number of extra bytes to add the returned buffer. The
// actual size of the buffer is returned as well.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_WideStrFromANSIExtra
(
HANDLE hHeap,
char *pszAnsi,
int cchANSI,
WCHAR **ppwszWideStr,
DWORD cbExtra,
DWORD* pcbBufferSize,
DWORD* pcchConverted
)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_WideStrFromANSI"));
HRESULT hr = S_OK;
*ppwszWideStr = NULL;
int cchConverted = 0;
DWORD cbBufferSize = 0;
// get required buffer length
int cchWideStr = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pszAnsi, // address of multibyte string
cchANSI, // number of characters in string
NULL, // address of buffer for new string
0 // size of buffer
);
CSF_CHECK(0 != cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
cbBufferSize = (cchWideStr + 1 + cbExtra) * sizeof(WCHAR);
// allocate a buffer for the WCHAR *
*ppwszWideStr = (LPWSTR) HeapAlloc(hHeap, NULL, cbBufferSize);
CSF_CHECK(NULL != *ppwszWideStr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
// now convert the string and copy it to the buffer
cchConverted = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pszAnsi, // address of multibyte string
cchANSI, // number of characters in string
*ppwszWideStr, // address of buffer for new string
cchWideStr // size of buffer
);
CSF_CHECK(cchConverted == cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// add terminating null character
*( (*ppwszWideStr) + cchWideStr ) = L'\0';
*pcbBufferSize = cbBufferSize;
*pcchConverted = cchConverted;
CLEANUP:
if (FAILED(hr))
{
if (NULL != *ppwszWideStr)
{
delete [] *ppwszWideStr;
*ppwszWideStr = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_WideStrFromANSI hr = %08.8X"), hr);
return hr;
}
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_WideStrFromANSILen(char *pszAnsi, int nLen, WCHAR **ppwszWideStr))
//
// Converts length specifed ANSI string to a null terminated WCHAR string.
// Allocates WCHAR string buffer using the new operator. If successful, caller
// must free WCHAR string using the delete operator.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_WideStrFromANSILen(char *pszAnsi, int nLen, WCHAR **ppwszWideStr)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_WideStrFromANSI"));
HRESULT hr = S_OK;
*ppwszWideStr = NULL;
int cchConverted = 0;
if(nLen == 0)
{
*ppwszWideStr = NULL;
return S_OK;
}
// get required buffer length
int cchWideStr = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pszAnsi, // address of multibyte string
nLen, // number of characters in string
NULL, // address of buffer for new string
0 // size of buffer
);
CSF_CHECK(0 != cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// allocate a buffer for the WCHAR *
*ppwszWideStr = new WCHAR[cchWideStr + 1];
CSF_CHECK(NULL != *ppwszWideStr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
// now convert the string and copy it to the buffer
cchConverted = ::MultiByteToWideChar(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
pszAnsi, // address of multibyte string
nLen, // number of characters in string
*ppwszWideStr, // address of buffer for new string
cchWideStr // size of buffer
);
CSF_CHECK(cchConverted == cchWideStr, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// add terminating null character
*( (*ppwszWideStr) + cchWideStr ) = L'\0';
CLEANUP:
if (FAILED(hr))
{
if (NULL != *ppwszWideStr)
{
delete [] *ppwszWideStr;
*ppwszWideStr = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_WideStrFromANSI hr = %08.8X"), hr);
return hr;
}
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_ANSIFromBSTR(BSTR bstr, char **ppszAnsi)
//
// Converts BSTR to null terminated ANSI string. Allocates ANSI string using
// new operator. If successful, caller must free ANSI string with delete
// operator.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_ANSIFromBSTR(BSTR bstr, char **ppszAnsi)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_ANSIFromBSTR"));
HRESULT hr = S_OK;
*ppszAnsi = NULL;
int cchBstr = (int)::SysStringLen(bstr);
int cchConverted = 0;
// get required buffer length
int cchAnsi = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
bstr, // address of wide-character string
cchBstr, // number of characters in string
NULL, // address of buffer for new string
0, // size of buffer
NULL, // address of default for unmappable characters
NULL // address of flag set when default char. used
);
CSF_CHECK(0 != cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// allocate a buffer for the ANSI string
*ppszAnsi = new char [cchAnsi + 1];
CSF_CHECK(NULL != *ppszAnsi, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
// now convert the string and copy it to the buffer
cchConverted = ::WideCharToMultiByte(CP_ACP, // code page - ANSI code page
0, // performance and mapping flags
bstr, // address of wide-character string
cchBstr, // number of characters in string
*ppszAnsi, // address of buffer for new string
cchAnsi, // size of buffer
NULL, // address of default for unmappable characters
NULL // address of flag set when default char. used
);
CSF_CHECK(cchConverted == cchAnsi, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// add terminating null byte
*( (*ppszAnsi) + cchAnsi ) = '\0';
CLEANUP:
if (FAILED(hr))
{
if (NULL != *ppszAnsi)
{
delete [] *ppszAnsi;
*ppszAnsi = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_ANSIFromBSTR hr = %08.8X"), hr);
return hr;
}
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_BSTRFromANSI(char *pszAnsi, BSTR *pbstr))
//
// Converts null terminated ANSI string to a null terminated BSTR. Allocates
// BSTR. If successful, caller must free BSTR using ::SysFreeString().
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_BSTRFromANSI(char *pszAnsi, BSTR *pbstr)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_BSTRFromANSI"));
HRESULT hr = S_OK;
WCHAR *pwszWideStr = NULL;
// convert to a wide string first
hr = WCU_WideStrFromANSI(pszAnsi, &pwszWideStr);
CSF_CHECK(SUCCEEDED(hr), hr, CSF_TRACE_INTERNAL_ERRORS);
// allocate a BSTR and copy it
*pbstr = ::SysAllocStringLen(pwszWideStr, ::wcslen(pwszWideStr));
CSF_CHECK(NULL != *pbstr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
CLEANUP:
if (NULL != pwszWideStr)
{
delete [] pwszWideStr;
}
if (FAILED(hr))
{
if (NULL != *pbstr)
{
::SysFreeString(*pbstr);
*pbstr = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_BSTRFromANSI hr = %08.8X"), hr);
return hr;
}
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCU_BSTRFromANSILen(char *pszAnsi, int nLen, BSTR *pbstr))
//
// Converts len specified ANSI string to a null terminated BSTR. Allocates
// BSTR. If successful, caller must free BSTR using ::SysFreeString().
//
//=--------------------------------------------------------------------------=
inline HRESULT WCU_BSTRFromANSILen(char *pszAnsi, int nLen, BSTR *pbstr)
{
CSF_TRACE(CSF_TRACE_ENTER_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Entered WCU_BSTRFromANSI"));
HRESULT hr = S_OK;
WCHAR *pwszWideStr = NULL;
if(nLen == 0)
{
*pbstr = SysAllocString(L"\0");
CSF_CHECK(*pbstr != NULL, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
return S_OK;
}
// convert to a wide string first
hr = WCU_WideStrFromANSILen(pszAnsi, nLen, &pwszWideStr);
CSF_CHECK(SUCCEEDED(hr), hr, CSF_TRACE_INTERNAL_ERRORS);
// allocate a BSTR and copy it
*pbstr = ::SysAllocStringLen(pwszWideStr, nLen);
CSF_CHECK(NULL != *pbstr, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
CLEANUP:
if (NULL != pwszWideStr)
{
delete [] pwszWideStr;
}
if (FAILED(hr))
{
if (NULL != *pbstr)
{
::SysFreeString(*pbstr);
*pbstr = NULL;
}
}
CSF_TRACE(CSF_TRACE_LEAVE_INTERNAL_FUNC)(CSF_TRACE_CONTEXT, TEXT("Leaving WCU_BSTRFromANSI hr = %08.8X"), hr);
return hr;
}
inline HRESULT GetIISVersion
(
DWORD* pdwMajor,
DWORD* pdwMinor
)
{
HRESULT hr = S_OK;
TCHAR *pszRegIISParamsKey = { TEXT("SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters") };
TCHAR *pszRegASPParamsKey = { TEXT("SYSTEM\\CurrentControlSet\\Services\\W3SVC\\ASP") };
HKEY hKey = NULL;
long lRet = 0;
DWORD dwType = 0;
DWORD cbSize = sizeof(DWORD);
lRet = ::RegOpenKey(HKEY_LOCAL_MACHINE,
pszRegIISParamsKey,
&hKey);
CSF_CHECK(lRet == ERROR_SUCCESS, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// Now, we can get the size of the value...
lRet = ::RegQueryValueEx(hKey, "MajorVersion", NULL, &dwType, (BYTE*) pdwMajor, &cbSize);
CSF_CHECK(lRet == ERROR_SUCCESS, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// Now, we can get the size of the value...
lRet = ::RegQueryValueEx(hKey, "MinorVersion", NULL, &dwType, (BYTE*) pdwMinor, &cbSize);
CSF_CHECK(lRet == ERROR_SUCCESS, E_UNEXPECTED, CSF_TRACE_EXTERNAL_ERRORS);
// Uggghh! IIS 3.0 never update the registry verison, so we need to check for
// ASP if 1 or 2 was specified...
if(*pdwMajor < 3)
{
::RegCloseKey(hKey);
lRet = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE,
pszRegASPParamsKey,
0,
KEY_QUERY_VALUE,
&hKey);
if(lRet == ERROR_SUCCESS)
{
// We found the ASP key so this must be version 3.0...
*pdwMajor = 3;
*pdwMinor = 0;
}
}
CLEANUP:
if(hKey != NULL)
::RegCloseKey(hKey);
return hr;
}
// TODO: Do we want this this way?
// Maybe just substract 2? No We ain't dynamic casue
// of the tlb anyhow.
inline DWORD IISVersionToASPVersion(DWORD dwIIS)
{
DWORD dwASP = 0;
if(dwIIS == 3)
{
dwASP = 1;
}
else if(dwIIS == 4)
{
dwASP = 2;
}
return dwASP;
}
// Listed from most to least
static WCHAR g_wszMostUniqueCharset[] = {L"~`\\_/{}|[]^!@#$%*():;"};
//----------------------------------------------------------------------------------------
// PickMostUniqueChar
//----------------------------------------------------------------------------------------
// Selects the most unique char in the specified string. We use this to pick the most unique
// char in the user supplied tag prefix. This optimizes searching for those tags
//----------------------------------------------------------------------------------------
inline HRESULT PickMostUniqueChar
(
LPWSTR pwszPrefix, // [in] String to find unique char in
WORD* pwIndex // [out] Index of the most unique char
)
{
LPWSTR pwszRet = NULL;
ASSERT(wcslen(pwszPrefix) < 0xFFFF);
// See if the string contains any of our unique chars
//
pwszRet = wcspbrk(pwszPrefix, g_wszMostUniqueCharset);
if(pwszRet != NULL)
{
*pwIndex = (WORD)(pwszRet - pwszPrefix);
}
else
{
// If not, just use first char in the string
//
*pwIndex = 0;
}
return S_OK;
}
/***
*wchar_t *wcsistr(string1, string2) - search for string2 in string1
* (wide strings)
*
*Purpose:
* finds the first occurrence of string2 in string1 (wide strings)
*
*Entry:
* wchar_t *string1 - string to search in
* wchar_t *string2 - string to search for
*
*Exit:
* returns a pointer to the first occurrence of string2 in
* string1, or NULL if string2 does not occur in string1
*
*Uses:
*
*Exceptions:
*
*******************************************************************************/
//=--------------------------------------------------------------------------=
//
// wchar_t *WCU_wcsistr(string1, string2)
//
// Purpose:
// Finds the first occurrence of string2 in string1 (wide strings.
// Not case sensitive.
// This is a direct copy of C runtime source code from VC5. The only
// addition is the use of the Win32 API CharUpperBuffW() to do a locale
// sensitive conversion of characters to upper case before comparing
// them.
//
// Entry:
// wchar_t *string1 - string to search in
// wchar_t *string2 - string to search for
//
// Exit:
// returns a pointer to the first occurrence of string2 in
// string1, or NULL if string2 does not occur in string1
//
//=--------------------------------------------------------------------------=
inline wchar_t * __cdecl WCU_wcsistr
(
const wchar_t * wcs1,
const wchar_t * wcs2
)
{
wchar_t *cp = (wchar_t *) wcs1;
wchar_t *s1, *s2;
wchar_t c1, c2;
while (*cp)
{
s1 = cp;
s2 = (wchar_t *) wcs2;
// while there are characters left in both strings
while ( *s1 && *s2 )
{
// if the characters are not equal
if (*s1 - *s2)
{
// convert them to uppercase
c1 = *s1;
c2 = *s2;
if ( (CharUpperBuffW(&c1, (DWORD)1) != (DWORD)1) ||
(CharUpperBuffW(&c2, (DWORD)1) != (DWORD)1) )
{
break;
}
// if the upper case characters are not equal then the string
// is not there
if (c1 - c2)
break;
}
s1++, s2++;
}
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
#define _WCUTIL_H_
#endif // _WCUTIL_H_