#ifndef __SPHELPER_HH_INCLUDED__ #define __SPHELPER_HH_INCLUDED__ #ifndef SR_LOCALIZED_DESCRIPTION #define SR_LOCALIZED_DESCRIPTION L"Description" #endif #ifndef REG_MUI_STRING_TRUNCATE #define REG_MUI_STRING_TRUNCATE 0x00000001 #endif #ifndef SPERR_NOT_FOUND #define FACILITY_SAPI FACILITY_ITF #define SAPI_ERROR_BASE 0x5000 #define MAKE_SAPI_HRESULT(sev, err) MAKE_HRESULT(sev, FACILITY_SAPI, err) #define MAKE_SAPI_ERROR(err) MAKE_SAPI_HRESULT(SEVERITY_ERROR, err + SAPI_ERROR_BASE) #define SPERR_NOT_FOUND MAKE_SAPI_ERROR(0x03a) #endif inline void SpHexFromUlong(WCHAR * psz, ULONG ul) { // If for some reason we cannot convert a number, set it to 0 if (_ultow(ul, psz, 16)) { psz[0] = L'0'; psz[1] = 0; } } inline HRESULT SpGetTokenFromId( const WCHAR * pszTokenId, ISpObjectToken ** ppToken, BOOL fCreateIfNotExist = FALSE) { HRESULT hr; ISpObjectToken * cpToken; hr = CoCreateInstance(CLSID_SpObjectToken, NULL, CLSCTX_INPROC_SERVER, IID_ISpObjectToken, (void**)&cpToken); if (SUCCEEDED(hr)) { hr = cpToken->SetId(NULL, pszTokenId, fCreateIfNotExist); if (SUCCEEDED(hr)) { *ppToken = cpToken; } else cpToken->Release(); } return hr; } inline HRESULT SpGetCategoryFromId( const WCHAR * pszCategoryId, ISpObjectTokenCategory ** ppCategory, BOOL fCreateIfNotExist = FALSE) { HRESULT hr; ISpObjectTokenCategory * cpTokenCategory; hr = CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER, IID_ISpObjectTokenCategory, (void**)&cpTokenCategory ); if (SUCCEEDED(hr)) { hr = cpTokenCategory->SetId(pszCategoryId, fCreateIfNotExist); if (SUCCEEDED(hr)) { *ppCategory = cpTokenCategory; } else cpTokenCategory->Release(); } return hr; } HRESULT SpEnumTokens( const WCHAR * pszCategoryId, const WCHAR * pszReqAttribs, const WCHAR * pszOptAttribs, IEnumSpObjectTokens ** ppEnum) { HRESULT hr = S_OK; ISpObjectTokenCategory * cpCategory; hr = SpGetCategoryFromId(pszCategoryId, &cpCategory); if (SUCCEEDED(hr)) { hr = cpCategory->EnumTokens( pszReqAttribs, pszOptAttribs, ppEnum); cpCategory->Release(); } return hr; } inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescription, LANGID Language = GetUserDefaultUILanguage()) { WCHAR szLangId[10]; HRESULT hr = S_OK; #if _SAPI_VER >= 0x053 WCHAR* pRegKeyPath = 0; WCHAR* pszTemp = 0; HKEY Handle = NULL; // Windows Vista does not encourage localized strings in the registry // When running on Windows Vista query the localized engine name from a resource dll OSVERSIONINFO ver; ver.dwOSVersionInfoSize = sizeof( ver ); if (ppszDescription == NULL) { return E_POINTER; } *ppszDescription = NULL; if( ( ::GetVersionEx( &ver ) == TRUE ) && ( ver.dwMajorVersion >= 6 ) ) { // If we reach this code we are running under Windows Vista HMODULE hmodAdvapi32Dll = NULL; typedef HRESULT (WINAPI* LPFN_RegLoadMUIStringW)(HKEY, LPCWSTR, LPWSTR, DWORD, LPDWORD, DWORD, LPCWSTR); LPFN_RegLoadMUIStringW pfnRegLoadMUIStringW = NULL; // Delay bind with RegLoadMUIStringW since this function is not supported on previous versions of advapi32.dll // RegLoadMUIStringW is supported only on advapi32.dll that ships with Windows Vista and above // Calling RegLoadMUIStringW directly makes the loader try to resolve the function reference at load time which breaks, // hence we manually load advapi32.dll, query for the function pointer and invoke it. hmodAdvapi32Dll = ::LoadLibrary(TEXT("advapi32.dll")); if(hmodAdvapi32Dll) { pfnRegLoadMUIStringW = (LPFN_RegLoadMUIStringW) ::GetProcAddress(hmodAdvapi32Dll, "RegLoadMUIStringW"); if (!pfnRegLoadMUIStringW) { // This should not happen in Vista // _ASSERT (pfnRegLoadMUIStringW); hr = TYPE_E_DLLFUNCTIONNOTFOUND; } } else { hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); } if (SUCCEEDED(hr)) { hr = pObjToken->GetId(&pszTemp); } if (SUCCEEDED(hr)) { LONG lErrorCode = ERROR_SUCCESS; pRegKeyPath = wcschr(pszTemp, L'\\'); // Find the first occurance of '\\' in the absolute registry key path if(pRegKeyPath) { *pRegKeyPath = L'\0'; pRegKeyPath++; // pRegKeyPath now points to the path to the recognizer token under the HKLM or HKCR hive *ppszDescription = 0; // Open the registry key for read and get the handle if (wcsncmp(pszTemp, L"HKEY_LOCAL_MACHINE", MAX_PATH) == 0) { lErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pRegKeyPath, 0, KEY_QUERY_VALUE, &Handle); } else if (wcsncmp(pszTemp, L"HKEY_CURRENT_USER", MAX_PATH) == 0) { lErrorCode = RegOpenKeyExW(HKEY_CURRENT_USER, pRegKeyPath, 0, KEY_QUERY_VALUE, &Handle); } else { lErrorCode = ERROR_BAD_ARGUMENTS; } // Use MUI RegLoadMUIStringW API to load the localized string if(ERROR_SUCCESS == lErrorCode) { *ppszDescription = (WCHAR*) CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR)); // This should be enough memory to allocate the localized Engine Name lErrorCode = (*pfnRegLoadMUIStringW) (Handle, SR_LOCALIZED_DESCRIPTION, *ppszDescription, MAX_PATH * sizeof(WCHAR), NULL, REG_MUI_STRING_TRUNCATE, NULL); } } else { // pRegKeyPath should never be 0 if we are querying for relative hkey path lErrorCode = ERROR_BAD_ARGUMENTS; } hr = HRESULT_FROM_WIN32(lErrorCode); } // Close registry key handle if(Handle) { RegCloseKey(Handle); } // Free memory allocated to locals if(pszTemp) { CoTaskMemFree(pszTemp); } if (hmodAdvapi32Dll) { ::FreeLibrary(hmodAdvapi32Dll); } } else { hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); } // If running on OSes released before Windows Vista query the localized string from the registry // If RegLoadMUIStringW failed to retrieved the localized Engine name retrieve the localized string from the fallback (Default) attribute #else hr = E_FAIL; #endif // _SAPI_VER >= 0x053 if (FAILED(hr)) { // Free memory allocated above if necessary if (*ppszDescription != NULL) { CoTaskMemFree(*ppszDescription); *ppszDescription = NULL; } SpHexFromUlong(szLangId, Language); hr = pObjToken->GetStringValue(szLangId, ppszDescription); if (hr == SPERR_NOT_FOUND) { hr = pObjToken->GetStringValue(NULL, ppszDescription); } } return hr; } #endif