[KERNEL32] Fix IsShimInfrastructureDisabled. CORE-13352
[reactos.git] / reactos / dll / win32 / kernel32 / client / appcache.c
1 /*
2 * PROJECT: ReactOS Win32 Base API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/kernel32/client/appcache.c
5 * PURPOSE: Application Compatibility Cache
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <k32.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18 ULONG g_ShimsDisabled = -1;
19 static BOOL g_ApphelpInitialized = FALSE;
20 static PVOID g_pApphelpCheckRunAppEx;
21 static PVOID g_pSdbPackAppCompatData;
22
23 typedef BOOL (WINAPI *tApphelpCheckRunAppEx)(HANDLE FileHandle, PVOID Unk1, PVOID Unk2, PWCHAR ApplicationName, PVOID Environment, USHORT ExeType, PULONG Reason,
24 PVOID* SdbQueryAppCompatData, PULONG SdbQueryAppCompatDataSize, PVOID* SxsData, PULONG SxsDataSize,
25 PULONG FusionFlags, PULONG64 SomeFlag1, PULONG SomeFlag2);
26 typedef BOOL (WINAPI *tSdbPackAppCompatData)(PVOID hsdb, PVOID pQueryResult, PVOID* ppData, DWORD *dwSize);
27
28 #define APPHELP_VALID_RESULT 0x10000
29 #define APPHELP_RESULT_NOTFOUND 0x20000
30 #define APPHELP_RESULT_FOUND 0x40000
31
32
33 /* FUNCTIONS ******************************************************************/
34
35 BOOLEAN
36 WINAPI
37 IsShimInfrastructureDisabled(VOID)
38 {
39 HANDLE KeyHandle;
40 NTSTATUS Status;
41 KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
42 ULONG ResultLength;
43 UNICODE_STRING OptionKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\SafeBoot\\Option");
44 UNICODE_STRING AppCompatKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\AppCompatibility");
45 UNICODE_STRING PolicyKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\Software\\Policies\\Microsoft\\Windows\\AppCompat");
46 UNICODE_STRING OptionValue = RTL_CONSTANT_STRING(L"OptionValue");
47 UNICODE_STRING DisableAppCompat = RTL_CONSTANT_STRING(L"DisableAppCompat");
48 UNICODE_STRING DisableEngine = RTL_CONSTANT_STRING(L"DisableEngine");
49 OBJECT_ATTRIBUTES OptionKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&OptionKey, OBJ_CASE_INSENSITIVE);
50 OBJECT_ATTRIBUTES AppCompatKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&AppCompatKey, OBJ_CASE_INSENSITIVE);
51 OBJECT_ATTRIBUTES PolicyKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&PolicyKey, OBJ_CASE_INSENSITIVE);
52
53 /*
54 * This is a TROOLEAN, -1 means we haven't yet figured it out.
55 * 0 means shims are enabled, and 1 means shims are disabled!
56 */
57 if (g_ShimsDisabled == -1)
58 {
59 ULONG DisableShims = FALSE;
60
61 /* Open the safe mode key */
62 Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &OptionKeyAttributes);
63 if (NT_SUCCESS(Status))
64 {
65 /* Check if this is safemode */
66 Status = NtQueryValueKey(KeyHandle,
67 &OptionValue,
68 KeyValuePartialInformation,
69 &KeyInfo,
70 sizeof(KeyInfo),
71 &ResultLength);
72 NtClose(KeyHandle);
73 if ((NT_SUCCESS(Status)) &&
74 (KeyInfo.Type == REG_DWORD) &&
75 (KeyInfo.DataLength == sizeof(ULONG)) &&
76 (KeyInfo.Data[0] == TRUE))
77 {
78 /* It is, so disable shims! */
79 DisableShims = TRUE;
80 }
81 }
82
83 if (!DisableShims)
84 {
85 /* Open the app compatibility engine settings key */
86 Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &AppCompatKeyAttributes);
87 if (NT_SUCCESS(Status))
88 {
89 /* Check if the app compat engine is turned off */
90 Status = NtQueryValueKey(KeyHandle,
91 &DisableAppCompat,
92 KeyValuePartialInformation,
93 &KeyInfo,
94 sizeof(KeyInfo),
95 &ResultLength);
96 NtClose(KeyHandle);
97 if ((NT_SUCCESS(Status)) &&
98 (KeyInfo.Type == REG_DWORD) &&
99 (KeyInfo.DataLength == sizeof(ULONG)) &&
100 (KeyInfo.Data[0] == TRUE))
101 {
102 /* It is, so disable shims! */
103 DisableShims = TRUE;
104 }
105 }
106 }
107 if (!DisableShims)
108 {
109 /* Finally, open the app compatibility policy key */
110 Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &PolicyKeyAttributes);
111 if (NT_SUCCESS(Status))
112 {
113 /* Check if the system policy disables app compat */
114 Status = NtQueryValueKey(KeyHandle,
115 &DisableEngine,
116 KeyValuePartialInformation,
117 &KeyInfo,
118 sizeof(KeyInfo),
119 &ResultLength);
120 NtClose(KeyHandle);
121 if ((NT_SUCCESS(Status)) &&
122 (KeyInfo.Type == REG_DWORD) &&
123 (KeyInfo.DataLength == sizeof(ULONG)) &&
124 (KeyInfo.Data[0] == TRUE))
125 {
126 /* It does, so disable shims! */
127 DisableShims = TRUE;
128 }
129 }
130 }
131 g_ShimsDisabled = DisableShims;
132 }
133
134 /* Return if shims are disabled or not ("Enabled == 1" means disabled!) */
135 return g_ShimsDisabled ? TRUE : FALSE;
136 }
137
138 /*
139 * @unimplemented
140 */
141 BOOL
142 WINAPI
143 BaseCheckAppcompatCache(IN PWCHAR ApplicationName,
144 IN HANDLE FileHandle,
145 IN PWCHAR Environment,
146 OUT PULONG Reason)
147 {
148 DPRINT("BaseCheckAppcompatCache is UNIMPLEMENTED\n");
149
150 if (Reason) *Reason = 0;
151
152 // We don't know this app.
153 return FALSE;
154 }
155
156 static
157 VOID
158 BaseInitApphelp(VOID)
159 {
160 WCHAR Buffer[MAX_PATH*2];
161 UNICODE_STRING DllPath = {0};
162 PVOID ApphelpAddress;
163 PVOID pApphelpCheckRunAppEx = NULL, pSdbPackAppCompatData = NULL;
164
165 RtlInitEmptyUnicodeString(&DllPath, Buffer, sizeof(Buffer));
166 RtlCopyUnicodeString(&DllPath, &BaseWindowsDirectory);
167 RtlAppendUnicodeToString(&DllPath, L"\\system32\\apphelp.dll");
168
169 if (NT_SUCCESS(LdrLoadDll(NULL, NULL, &DllPath, &ApphelpAddress)))
170 {
171 ANSI_STRING ProcName;
172
173 RtlInitAnsiString(&ProcName, "ApphelpCheckRunAppEx");
174 if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress, &ProcName, 0, &pApphelpCheckRunAppEx)))
175 pApphelpCheckRunAppEx = NULL;
176
177 RtlInitAnsiString(&ProcName, "SdbPackAppCompatData");
178 if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress, &ProcName, 0, &pSdbPackAppCompatData)))
179 pSdbPackAppCompatData = NULL;
180 }
181
182 if (InterlockedCompareExchangePointer(&g_pApphelpCheckRunAppEx, RtlEncodeSystemPointer(pApphelpCheckRunAppEx), NULL) == NULL)
183 {
184 g_pSdbPackAppCompatData = RtlEncodeSystemPointer(pSdbPackAppCompatData);
185 }
186 }
187
188 /*
189 *
190 */
191 BOOL
192 WINAPI
193 BaseCheckRunApp(IN HANDLE FileHandle,
194 IN PWCHAR ApplicationName,
195 IN PWCHAR Environment,
196 IN USHORT ExeType,
197 IN PULONG pReason,
198 IN PVOID* SdbQueryAppCompatData,
199 IN PULONG SdbQueryAppCompatDataSize,
200 IN PVOID* SxsData,
201 IN PULONG SxsDataSize,
202 OUT PULONG FusionFlags)
203 {
204 ULONG Reason = 0;
205 ULONG64 Flags1 = 0;
206 ULONG Flags2 = 0;
207 BOOL Continue, NeedCleanup = FALSE;
208 tApphelpCheckRunAppEx pApphelpCheckRunAppEx;
209 tSdbPackAppCompatData pSdbPackAppCompatData;
210 PVOID QueryResult = NULL;
211 ULONG QueryResultSize = 0;
212
213 if (!g_ApphelpInitialized)
214 {
215 BaseInitApphelp();
216 g_ApphelpInitialized = TRUE;
217 }
218
219 pApphelpCheckRunAppEx = RtlDecodeSystemPointer(g_pApphelpCheckRunAppEx);
220 pSdbPackAppCompatData = RtlDecodeSystemPointer(g_pSdbPackAppCompatData);
221
222 if (!pApphelpCheckRunAppEx || !pSdbPackAppCompatData)
223 return TRUE;
224
225 if (pReason)
226 Reason = *pReason;
227
228 Continue = pApphelpCheckRunAppEx(FileHandle, NULL, NULL, ApplicationName, Environment, ExeType, &Reason,
229 &QueryResult, &QueryResultSize, SxsData, SxsDataSize, FusionFlags, &Flags1, &Flags2);
230
231 if (pReason)
232 *pReason = Reason;
233
234 if (Continue)
235 {
236 if ((Reason & (APPHELP_VALID_RESULT|APPHELP_RESULT_FOUND)) == (APPHELP_VALID_RESULT|APPHELP_RESULT_FOUND))
237 {
238 if (!pSdbPackAppCompatData(NULL, QueryResult, SdbQueryAppCompatData, SdbQueryAppCompatDataSize))
239 {
240 DPRINT1("SdbPackAppCompatData returned a failure!\n");
241 NeedCleanup = TRUE;
242 }
243 }
244 else
245 {
246 NeedCleanup = TRUE;
247 }
248 }
249
250 if (QueryResult)
251 RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult);
252
253 if (NeedCleanup)
254 {
255 BasepFreeAppCompatData(*SdbQueryAppCompatData, *SxsData);
256 *SdbQueryAppCompatData = NULL;
257 if (SdbQueryAppCompatDataSize)
258 *SdbQueryAppCompatDataSize = 0;
259 *SxsData = NULL;
260 if (SxsDataSize)
261 *SxsDataSize = 0;
262 }
263
264 return Continue;
265 }
266
267 /*
268 * @implemented
269 */
270 NTSTATUS
271 WINAPI
272 BasepCheckBadapp(IN HANDLE FileHandle,
273 IN PWCHAR ApplicationName,
274 IN PWCHAR Environment,
275 IN USHORT ExeType,
276 IN PVOID* SdbQueryAppCompatData,
277 IN PULONG SdbQueryAppCompatDataSize,
278 IN PVOID* SxsData,
279 IN PULONG SxsDataSize,
280 OUT PULONG FusionFlags)
281 {
282 NTSTATUS Status = STATUS_SUCCESS;
283 ULONG Reason = 0;
284
285 /* Is shimming enabled by group policy? */
286 if (IsShimInfrastructureDisabled())
287 {
288 /* Nothing to worry about */
289 Status = STATUS_SUCCESS;
290 }
291 else
292 {
293 /* It is, check if we know about this app */
294 if (!BaseCheckAppcompatCache(ApplicationName,
295 FileHandle,
296 Environment,
297 &Reason))
298 {
299 if (!BaseCheckRunApp(FileHandle, ApplicationName, Environment, ExeType, &Reason,
300 SdbQueryAppCompatData, SdbQueryAppCompatDataSize, SxsData, SxsDataSize, FusionFlags))
301 {
302 Status = STATUS_ACCESS_DENIED;
303 }
304 }
305 }
306
307 /* Return caller the status */
308 return Status;
309 }
310
311 /*
312 * @unimplemented
313 */
314 VOID
315 WINAPI
316 BaseDumpAppcompatCache(VOID)
317 {
318 STUB;
319 }
320
321 /*
322 * @unimplemented
323 */
324 VOID
325 WINAPI
326 BaseFlushAppcompatCache(VOID)
327 {
328 STUB;
329 }
330
331 /*
332 * @implemented
333 */
334 VOID
335 WINAPI
336 BasepFreeAppCompatData(IN PVOID AppCompatData,
337 IN PVOID AppCompatSxsData)
338 {
339 /* Free the input pointers if present */
340 if (AppCompatData) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData);
341 if (AppCompatSxsData) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatSxsData);
342 }
343
344 /*
345 * @unimplemented
346 */
347 VOID
348 WINAPI
349 BaseUpdateAppcompatCache(ULONG Unknown1,
350 ULONG Unknown2,
351 ULONG Unknown3)
352 {
353 STUB;
354 }
355
356 /*
357 * @unimplemented
358 */
359 NTSTATUS
360 WINAPI
361 BaseCleanupAppcompatCache(VOID)
362 {
363 STUB;
364 return STATUS_NOT_IMPLEMENTED;
365 }
366
367 /*
368 * @unimplemented
369 */
370 NTSTATUS
371 WINAPI
372 BaseCleanupAppcompatCacheSupport(PVOID pUnknown)
373 {
374 STUB;
375 return STATUS_NOT_IMPLEMENTED;
376 }
377
378 /*
379 * @unimplemented
380 */
381 BOOL
382 WINAPI
383 BaseInitAppcompatCache(VOID)
384 {
385 STUB;
386 return FALSE;
387 }
388
389 /*
390 * @unimplemented
391 */
392 BOOL
393 WINAPI
394 BaseInitAppcompatCacheSupport(VOID)
395 {
396 STUB;
397 return FALSE;
398 }
399
400 /*
401 * @unimplemented
402 */
403 PVOID
404 WINAPI
405 GetComPlusPackageInstallStatus(VOID)
406 {
407 STUB;
408 return NULL;
409 }
410
411 /*
412 * @unimplemented
413 */
414 BOOL
415 WINAPI
416 SetComPlusPackageInstallStatus(LPVOID lpInfo)
417 {
418 STUB;
419 return FALSE;
420 }
421
422 /*
423 * @unimplemented
424 */
425 VOID
426 WINAPI
427 SetTermsrvAppInstallMode(IN BOOL bInstallMode)
428 {
429 STUB;
430 }
431
432 /*
433 * @unimplemented
434 */
435 BOOL
436 WINAPI
437 TermsrvAppInstallMode(VOID)
438 {
439 STUB;
440 return FALSE;
441 }