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)
9 /* INCLUDES *******************************************************************/
16 /* GLOBALS ********************************************************************/
19 static BOOL g_ApphelpInitialized
= FALSE
;
20 static PVOID g_pApphelpCheckRunAppEx
;
21 static PVOID g_pSdbPackAppCompatData
;
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
);
28 #define APPHELP_VALID_RESULT 0x10000
29 #define APPHELP_RESULT_NOTFOUND 0x20000
30 #define APPHELP_RESULT_FOUND 0x40000
33 /* FUNCTIONS ******************************************************************/
37 IsShimInfrastructureDisabled(VOID
)
41 KEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
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
);
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!
57 if (g_ShimsEnabled
== -1)
59 /* Open the safe mode key */
60 Status
= NtOpenKey(&KeyHandle
, KEY_QUERY_VALUE
, &OptionKeyAttributes
);
61 if (NT_SUCCESS(Status
))
63 /* Check if this is safemode */
64 Status
= NtQueryValueKey(KeyHandle
,
66 KeyValuePartialInformation
,
71 if ((NT_SUCCESS(Status
)) &&
72 (KeyInfo
.Type
== REG_DWORD
) &&
73 (KeyInfo
.DataLength
== sizeof(ULONG
)) &&
74 (KeyInfo
.Data
[0] == TRUE
))
76 /* It is, so disable shims! */
77 g_ShimsEnabled
= TRUE
;
81 /* Open the app compatibility engine settings key */
82 Status
= NtOpenKey(&KeyHandle
, KEY_QUERY_VALUE
, &AppCompatKeyAttributes
);
83 if (NT_SUCCESS(Status
))
85 /* Check if the app compat engine is turned off */
86 Status
= NtQueryValueKey(KeyHandle
,
88 KeyValuePartialInformation
,
93 if ((NT_SUCCESS(Status
)) &&
94 (KeyInfo
.Type
== REG_DWORD
) &&
95 (KeyInfo
.DataLength
== sizeof(ULONG
)) &&
96 (KeyInfo
.Data
[0] == TRUE
))
98 /* It is, so disable shims! */
99 g_ShimsEnabled
= TRUE
;
103 /* Finally, open the app compatibility policy key */
104 Status
= NtOpenKey(&KeyHandle
, KEY_QUERY_VALUE
, &PolicyKeyAttributes
);
105 if (NT_SUCCESS(Status
))
107 /* Check if the system policy disables app compat */
108 Status
= NtQueryValueKey(KeyHandle
,
110 KeyValuePartialInformation
,
115 if ((NT_SUCCESS(Status
)) &&
116 (KeyInfo
.Type
== REG_DWORD
) &&
117 (KeyInfo
.DataLength
== sizeof(ULONG
)) &&
118 (KeyInfo
.Data
[0] == TRUE
))
120 /* It does, so disable shims! */
121 g_ShimsEnabled
= TRUE
;
125 /* No keys are set, so enable shims! */
126 g_ShimsEnabled
= FALSE
;
135 /* Return if shims are disabled or not ("Enabled == 1" means disabled!) */
136 return g_ShimsEnabled
? TRUE
: FALSE
;
144 BaseCheckAppcompatCache(IN PWCHAR ApplicationName
,
145 IN HANDLE FileHandle
,
146 IN PWCHAR Environment
,
149 DPRINT("BaseCheckAppcompatCache is UNIMPLEMENTED\n");
151 if (Reason
) *Reason
= 0;
153 // We don't know this app.
159 BaseInitApphelp(VOID
)
161 WCHAR Buffer
[MAX_PATH
*2];
162 UNICODE_STRING DllPath
= {0};
163 PVOID ApphelpAddress
;
164 PVOID pApphelpCheckRunAppEx
= NULL
, pSdbPackAppCompatData
= NULL
;
166 RtlInitEmptyUnicodeString(&DllPath
, Buffer
, sizeof(Buffer
));
167 RtlCopyUnicodeString(&DllPath
, &BaseWindowsDirectory
);
168 RtlAppendUnicodeToString(&DllPath
, L
"\\system32\\apphelp.dll");
170 if (NT_SUCCESS(LdrLoadDll(NULL
, NULL
, &DllPath
, &ApphelpAddress
)))
172 ANSI_STRING ProcName
;
174 RtlInitAnsiString(&ProcName
, "ApphelpCheckRunAppEx");
175 if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress
, &ProcName
, 0, &pApphelpCheckRunAppEx
)))
176 pApphelpCheckRunAppEx
= NULL
;
178 RtlInitAnsiString(&ProcName
, "SdbPackAppCompatData");
179 if (!NT_SUCCESS(LdrGetProcedureAddress(ApphelpAddress
, &ProcName
, 0, &pSdbPackAppCompatData
)))
180 pSdbPackAppCompatData
= NULL
;
183 if (InterlockedCompareExchangePointer(&g_pApphelpCheckRunAppEx
, RtlEncodeSystemPointer(pApphelpCheckRunAppEx
), NULL
) == NULL
)
185 g_pSdbPackAppCompatData
= RtlEncodeSystemPointer(pSdbPackAppCompatData
);
194 BaseCheckRunApp(IN HANDLE FileHandle
,
195 IN PWCHAR ApplicationName
,
196 IN PWCHAR Environment
,
199 IN PVOID
* SdbQueryAppCompatData
,
200 IN PULONG SdbQueryAppCompatDataSize
,
202 IN PULONG SxsDataSize
,
203 OUT PULONG FusionFlags
)
208 BOOL Continue
, NeedCleanup
= FALSE
;
209 tApphelpCheckRunAppEx pApphelpCheckRunAppEx
;
210 tSdbPackAppCompatData pSdbPackAppCompatData
;
211 PVOID QueryResult
= NULL
;
212 ULONG QueryResultSize
= 0;
214 if (!g_ApphelpInitialized
)
217 g_ApphelpInitialized
= TRUE
;
220 pApphelpCheckRunAppEx
= RtlDecodeSystemPointer(g_pApphelpCheckRunAppEx
);
221 pSdbPackAppCompatData
= RtlDecodeSystemPointer(g_pSdbPackAppCompatData
);
223 if (!pApphelpCheckRunAppEx
|| !pSdbPackAppCompatData
)
229 Continue
= pApphelpCheckRunAppEx(FileHandle
, NULL
, NULL
, ApplicationName
, Environment
, ExeType
, &Reason
,
230 &QueryResult
, &QueryResultSize
, SxsData
, SxsDataSize
, FusionFlags
, &Flags1
, &Flags2
);
237 if ((Reason
& (APPHELP_VALID_RESULT
|APPHELP_RESULT_FOUND
)) == (APPHELP_VALID_RESULT
|APPHELP_RESULT_FOUND
))
239 if (!pSdbPackAppCompatData(NULL
, QueryResult
, SdbQueryAppCompatData
, SdbQueryAppCompatDataSize
))
241 DPRINT1("SdbPackAppCompatData returned a failure!\n");
252 RtlFreeHeap(RtlGetProcessHeap(), 0, QueryResult
);
256 BasepFreeAppCompatData(*SdbQueryAppCompatData
, *SxsData
);
257 *SdbQueryAppCompatData
= NULL
;
258 if (SdbQueryAppCompatDataSize
)
259 *SdbQueryAppCompatDataSize
= 0;
273 BasepCheckBadapp(IN HANDLE FileHandle
,
274 IN PWCHAR ApplicationName
,
275 IN PWCHAR Environment
,
277 IN PVOID
* SdbQueryAppCompatData
,
278 IN PULONG SdbQueryAppCompatDataSize
,
280 IN PULONG SxsDataSize
,
281 OUT PULONG FusionFlags
)
283 NTSTATUS Status
= STATUS_SUCCESS
;
286 /* Is shimming enabled by group policy? */
287 if (IsShimInfrastructureDisabled())
289 /* Nothing to worry about */
290 Status
= STATUS_SUCCESS
;
294 /* It is, check if we know about this app */
295 if (!BaseCheckAppcompatCache(ApplicationName
,
300 if (!BaseCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
301 SdbQueryAppCompatData
, SdbQueryAppCompatDataSize
, SxsData
, SxsDataSize
, FusionFlags
))
303 Status
= STATUS_ACCESS_DENIED
;
308 /* Return caller the status */
317 BaseDumpAppcompatCache(VOID
)
327 BaseFlushAppcompatCache(VOID
)
337 BasepFreeAppCompatData(IN PVOID AppCompatData
,
338 IN PVOID AppCompatSxsData
)
340 /* Free the input pointers if present */
341 if (AppCompatData
) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData
);
342 if (AppCompatSxsData
) RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatSxsData
);
350 BaseUpdateAppcompatCache(ULONG Unknown1
,
362 BaseCleanupAppcompatCache(VOID
)
365 return STATUS_NOT_IMPLEMENTED
;
373 BaseCleanupAppcompatCacheSupport(PVOID pUnknown
)
376 return STATUS_NOT_IMPLEMENTED
;
384 BaseInitAppcompatCache(VOID
)
395 BaseInitAppcompatCacheSupport(VOID
)
406 GetComPlusPackageInstallStatus(VOID
)
417 SetComPlusPackageInstallStatus(LPVOID lpInfo
)
428 SetTermsrvAppInstallMode(IN BOOL bInstallMode
)
438 TermsrvAppInstallMode(VOID
)