1 #ifndef __SPHELPER_HH_INCLUDED__
2 #define __SPHELPER_HH_INCLUDED__
3
4 #ifndef SR_LOCALIZED_DESCRIPTION
5 #define SR_LOCALIZED_DESCRIPTION L"Description"
6 #endif
7
8 #ifndef REG_MUI_STRING_TRUNCATE
9 #define REG_MUI_STRING_TRUNCATE 0x00000001
10 #endif
11
12 #ifndef SPERR_NOT_FOUND
13 #define FACILITY_SAPI FACILITY_ITF
14 #define SAPI_ERROR_BASE 0x5000
15 #define MAKE_SAPI_HRESULT(sev, err) MAKE_HRESULT(sev, FACILITY_SAPI, err)
16 #define MAKE_SAPI_ERROR(err) MAKE_SAPI_HRESULT(SEVERITY_ERROR, err + SAPI_ERROR_BASE)
17 #define SPERR_NOT_FOUND MAKE_SAPI_ERROR(0x03a)
18 #endif
19
20 #ifdef _SAPI_VER
21 #undef _SAPI_VER
22 #endif
23 #define _SAPI_VER 0x053
24
SpHexFromUlong(WCHAR * psz,ULONG ul)25 inline void SpHexFromUlong(WCHAR * psz, ULONG ul)
26 {
27 // If for some reason we cannot convert a number, set it to 0
28
29 if (_ultow(ul, psz, 16))
30 {
31 psz[0] = L'0';
32 psz[1] = 0;
33 }
34 }
35
SpGetTokenFromId(const WCHAR * pszTokenId,ISpObjectToken ** ppToken,BOOL fCreateIfNotExist=FALSE)36 inline HRESULT SpGetTokenFromId(
37 const WCHAR * pszTokenId,
38 ISpObjectToken ** ppToken,
39 BOOL fCreateIfNotExist = FALSE)
40 {
41 HRESULT hr;
42 ISpObjectToken * cpToken;
43 hr = CoCreateInstance(CLSID_SpObjectToken, NULL, CLSCTX_INPROC_SERVER,
44 IID_ISpObjectToken, (void**)&cpToken);
45
46 if (SUCCEEDED(hr))
47 {
48 hr = cpToken->SetId(NULL, pszTokenId, fCreateIfNotExist);
49 if (SUCCEEDED(hr))
50 {
51 *ppToken = cpToken;
52 }
53 else
54 cpToken->Release();
55 }
56
57 return hr;
58 }
59
SpGetCategoryFromId(const WCHAR * pszCategoryId,ISpObjectTokenCategory ** ppCategory,BOOL fCreateIfNotExist=FALSE)60 inline HRESULT SpGetCategoryFromId(
61 const WCHAR * pszCategoryId,
62 ISpObjectTokenCategory ** ppCategory,
63 BOOL fCreateIfNotExist = FALSE)
64 {
65 HRESULT hr;
66
67 ISpObjectTokenCategory * cpTokenCategory;
68 hr = CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
69 IID_ISpObjectTokenCategory, (void**)&cpTokenCategory );
70
71 if (SUCCEEDED(hr))
72 {
73 hr = cpTokenCategory->SetId(pszCategoryId, fCreateIfNotExist);
74 if (SUCCEEDED(hr))
75 {
76 *ppCategory = cpTokenCategory;
77 }
78 else
79 cpTokenCategory->Release();
80 }
81
82 return hr;
83 }
84
SpEnumTokens(const WCHAR * pszCategoryId,const WCHAR * pszReqAttribs,const WCHAR * pszOptAttribs,IEnumSpObjectTokens ** ppEnum)85 HRESULT SpEnumTokens(
86 const WCHAR * pszCategoryId,
87 const WCHAR * pszReqAttribs,
88 const WCHAR * pszOptAttribs,
89 IEnumSpObjectTokens ** ppEnum)
90 {
91 HRESULT hr = S_OK;
92
93 ISpObjectTokenCategory * cpCategory;
94 hr = SpGetCategoryFromId(pszCategoryId, &cpCategory);
95
96 if (SUCCEEDED(hr))
97 {
98 hr = cpCategory->EnumTokens(
99 pszReqAttribs,
100 pszOptAttribs,
101 ppEnum);
102 cpCategory->Release();
103 }
104
105 return hr;
106 }
107
SpGetDescription(ISpObjectToken * pObjToken,WCHAR ** ppszDescription,LANGID Language=GetUserDefaultUILanguage ())108 inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescription, LANGID Language = GetUserDefaultUILanguage())
109 {
110 WCHAR szLangId[10];
111 HRESULT hr = S_OK;
112
113 if (ppszDescription == NULL)
114 {
115 return E_POINTER;
116 }
117 *ppszDescription = NULL;
118
119 #if _SAPI_VER >= 0x053
120 WCHAR* pRegKeyPath = 0;
121 WCHAR* pszTemp = 0;
122 HKEY Handle = NULL;
123
124 // Windows Vista does not encourage localized strings in the registry
125 // When running on Windows Vista query the localized engine name from a resource dll
126 OSVERSIONINFO ver;
127 ver.dwOSVersionInfoSize = sizeof( ver );
128
129 if( ( ::GetVersionEx( &ver ) == TRUE ) && ( ver.dwMajorVersion >= 6 ) )
130 {
131 // If we reach this code we are running under Windows Vista
132 HMODULE hmodAdvapi32Dll = NULL;
133 typedef HRESULT (WINAPI* LPFN_RegLoadMUIStringW)(HKEY, LPCWSTR, LPWSTR, DWORD, LPDWORD, DWORD, LPCWSTR);
134 LPFN_RegLoadMUIStringW pfnRegLoadMUIStringW = NULL;
135
136 // Delay bind with RegLoadMUIStringW since this function is not supported on previous versions of advapi32.dll
137 // RegLoadMUIStringW is supported only on advapi32.dll that ships with Windows Vista and above
138 // Calling RegLoadMUIStringW directly makes the loader try to resolve the function reference at load time which breaks,
139 // hence we manually load advapi32.dll, query for the function pointer and invoke it.
140 hmodAdvapi32Dll = ::LoadLibrary(TEXT("advapi32.dll"));
141 if(hmodAdvapi32Dll)
142 {
143 pfnRegLoadMUIStringW = (LPFN_RegLoadMUIStringW) ::GetProcAddress(hmodAdvapi32Dll, "RegLoadMUIStringW");
144 if (!pfnRegLoadMUIStringW)
145 {
146 // This should not happen in Vista
147 // _ASSERT (pfnRegLoadMUIStringW);
148 hr = TYPE_E_DLLFUNCTIONNOTFOUND;
149 }
150 }
151 else
152 {
153 hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
154 }
155
156 if (SUCCEEDED(hr))
157 {
158 hr = pObjToken->GetId(&pszTemp);
159 }
160
161 if (SUCCEEDED(hr))
162 {
163 LONG lErrorCode = ERROR_SUCCESS;
164
165 pRegKeyPath = wcschr(pszTemp, L'\\'); // Find the first occurrence of '\\' in the absolute registry key path
166 if(pRegKeyPath)
167 {
168 *pRegKeyPath = L'\0';
169 pRegKeyPath++; // pRegKeyPath now points to the path to the recognizer token under the HKLM or HKCR hive
170 *ppszDescription = 0;
171
172 // Open the registry key for read and get the handle
173 if (wcsncmp(pszTemp, L"HKEY_LOCAL_MACHINE", MAX_PATH) == 0)
174 {
175 lErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pRegKeyPath, 0, KEY_QUERY_VALUE, &Handle);
176 }
177 else if (wcsncmp(pszTemp, L"HKEY_CURRENT_USER", MAX_PATH) == 0)
178 {
179 lErrorCode = RegOpenKeyExW(HKEY_CURRENT_USER, pRegKeyPath, 0, KEY_QUERY_VALUE, &Handle);
180 }
181 else
182 {
183 lErrorCode = ERROR_BAD_ARGUMENTS;
184 }
185
186 // Use MUI RegLoadMUIStringW API to load the localized string
187 if(ERROR_SUCCESS == lErrorCode)
188 {
189 *ppszDescription = (WCHAR*) CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR)); // This should be enough memory to allocate the localized Engine Name
190 lErrorCode = (*pfnRegLoadMUIStringW) (Handle, SR_LOCALIZED_DESCRIPTION, *ppszDescription, MAX_PATH * sizeof(WCHAR), NULL, REG_MUI_STRING_TRUNCATE, NULL);
191 }
192 }
193 else
194 {
195 // pRegKeyPath should never be 0 if we are querying for relative hkey path
196 lErrorCode = ERROR_BAD_ARGUMENTS;
197 }
198
199 hr = HRESULT_FROM_WIN32(lErrorCode);
200 }
201
202 // Close registry key handle
203 if(Handle)
204 {
205 RegCloseKey(Handle);
206 }
207 // Free memory allocated to locals
208 if(pszTemp)
209 {
210 CoTaskMemFree(pszTemp);
211 }
212 if (hmodAdvapi32Dll)
213 {
214 ::FreeLibrary(hmodAdvapi32Dll);
215 }
216 }
217 else
218 {
219 hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
220 }
221
222 // If running on OSes released before Windows Vista query the localized string from the registry
223 // If RegLoadMUIStringW failed to retrieved the localized Engine name retrieve the localized string from the fallback (Default) attribute
224 #else
225 hr = E_FAIL;
226 #endif // _SAPI_VER >= 0x053
227 if (FAILED(hr))
228 {
229 // Free memory allocated above if necessary
230 if (*ppszDescription != NULL)
231 {
232 CoTaskMemFree(*ppszDescription);
233 *ppszDescription = NULL;
234 }
235
236 SpHexFromUlong(szLangId, Language);
237 hr = pObjToken->GetStringValue(szLangId, ppszDescription);
238 if (hr == SPERR_NOT_FOUND)
239 {
240 hr = pObjToken->GetStringValue(NULL, ppszDescription);
241 }
242 }
243
244 return hr;
245 }
246
247 #endif
248