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