750 lines
26 KiB
C
750 lines
26 KiB
C
//=--------------------------------------------------------------------------=
|
|
// 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_
|