//=--------------------------------------------------------------------------= // 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_