2 * PROJECT: apphelp_apitest
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Tests showing shim artifacts in the environment
5 * COPYRIGHT: Copyright 2016,2017 Mark Jansen (mark.jansen@reactos.org)
9 #define WIN32_NO_STATUS
22 #include "wine/test.h"
24 #include <pseh/pseh2.h>
26 #include "apphelp_apitest.h"
37 BOOL(WINAPI
*pSdbGetMatchingExe
)(HSDB hsdb
, LPCWSTR szPath
, LPCWSTR szModuleName
, LPCWSTR pszEnvironment
, DWORD dwFlags
, PSDBQUERYRESULT_VISTA pQueryResult
);
38 HSDB (WINAPI
*pSdbInitDatabase
)(DWORD dwFlags
, LPCWSTR pszDatabasePath
);
39 void (WINAPI
*pSdbReleaseDatabase
)(HSDB hsdb
);
40 BOOL (WINAPI
*pSdbTagRefToTagID
)(HSDB hsdb
, TAGREF trWhich
, PDB
* ppdb
, TAGID
* ptiWhich
);
41 TAG (WINAPI
*pSdbGetTagFromTagID
)(PDB pdb
, TAGID tiWhich
);
42 TAGREF (WINAPI
*pSdbGetLayerTagRef
)(HSDB hsdb
, LPCWSTR layerName
);
45 /* TODO: Investigate ApphelpCheckRunApp, for some reason there is not AppCompatData generated... */
47 BOOL (WINAPI
*pApphelpCheckRunAppEx_w7
)(HANDLE FileHandle
, PVOID Unk1
, PVOID Unk2
, PWCHAR ApplicationName
, PVOID Environment
, USHORT ExeType
, PULONG Reason
,
48 PVOID
* SdbQueryAppCompatData
, PULONG SdbQueryAppCompatDataSize
, PVOID
* SxsData
, PULONG SxsDataSize
,
49 PULONG FusionFlags
, PULONG64 SomeFlag1
, PULONG SomeFlag2
);
51 BOOL (WINAPI
*pApphelpCheckRunAppEx_w10
)(HANDLE FileHandle
, PVOID Unk1
, PVOID Unk2
, PWCHAR ApplicationName
, PVOID Environment
, PVOID Unk3
, USHORT ExeType
, PULONG Reason
,
52 PVOID
* SdbQueryAppCompatData
, PULONG SdbQueryAppCompatDataSize
, PVOID
* SxsData
, PULONG SxsDataSize
,
53 PULONG FusionFlags
, PULONG64 SomeFlag1
, PULONG SomeFlag2
);
56 BOOL (WINAPI
*pSdbPackAppCompatData
)(HSDB hsdb
, PSDBQUERYRESULT_VISTA pQueryResult
, PVOID
* ppData
, DWORD
*dwSize
);
57 BOOL (WINAPI
*pSdbUnpackAppCompatData
)(HSDB hsdb
, LPCWSTR pszImageName
, PVOID pData
, PSDBQUERYRESULT_VISTA pQueryResult
);
58 DWORD (WINAPI
*pSdbGetAppCompatDataSize
)(PVOID pData
);
61 static HSDB g_LayerDB
;
62 static DWORD g_ShimDataSize
;
63 static DWORD g_ModuleVersion
;
64 static const SDBQUERYRESULT_VISTA empty_result
= { { 0 } };
65 static const SDBQUERYRESULT_VISTA almost_empty
= { { 0 }, { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, SHIMREG_DISABLE_LAYER
, 0 };
68 #define SHIMDATA_MAGIC 0xAC0DEDAB
69 #define MAX_LAYER_LENGTH 256
72 typedef struct ShimData_Win2k3
78 TAGREF atrExes
[SDB_MAX_EXES_2k3
];
79 TAGREF atrLayers
[SDB_MAX_LAYERS
];
83 GUID rgGuidDB
[SDB_MAX_SDBS
];
88 typedef struct ShimData_Win7
93 SDBQUERYRESULT_VISTA Query
;
94 WCHAR szLayer
[MAX_LAYER_LENGTH
];
95 DWORD unknown
; // 0x14c
98 typedef struct ShimData_Win10_v1
104 SDBQUERYRESULT_VISTA Query
;
105 WCHAR szLayer
[MAX_LAYER_LENGTH
];
106 char padding1
[0x200];
107 char padding2
[0x404]; // Contains some data at the start
110 WCHAR processname
[MAX_PATH
];
111 WCHAR szLayerEnv
[MAX_LAYER_LENGTH
];
112 WCHAR unk4
[MAX_LAYER_LENGTH
];
116 typedef struct ShimData_Win10_v2
122 SDBQUERYRESULT_VISTA Query
;
123 WCHAR szLayer
[MAX_LAYER_LENGTH
];
124 char padding1
[0x200];
125 char padding2
[0x2ae + 0x54 + 0x2a + 0x16 + 0x16];
128 WCHAR processname
[MAX_PATH
-2];
129 WCHAR szLayerEnv
[MAX_LAYER_LENGTH
];
130 WCHAR unk5
[MAX_LAYER_LENGTH
];
134 typedef struct ShimData_QueryOffset
148 } ShimData_QueryOffset
;
151 C_ASSERT(sizeof(ShimData_Win2k3
) == 392);
152 C_ASSERT(sizeof(ShimData_Win7
) == 1500);
153 C_ASSERT(sizeof(ShimData_Win10_v1
) == 4712);
154 C_ASSERT(sizeof(ShimData_Win10_v2
) == 3976);
156 C_ASSERT(offsetof(ShimData_Win10_v2
, dwSize
) == 0);
157 C_ASSERT(offsetof(ShimData_Win2k3
, dwSize
) == 68);
158 C_ASSERT(offsetof(ShimData_Win7
, dwSize
) == 520);
159 C_ASSERT(offsetof(ShimData_Win10_v1
, dwSize
) == 520);
161 C_ASSERT(offsetof(ShimData_Win10_v2
, dwMagic
) == 4);
162 C_ASSERT(offsetof(ShimData_Win2k3
, dwMagic
) == 72);
163 C_ASSERT(offsetof(ShimData_Win7
, dwMagic
) == 524);
164 C_ASSERT(offsetof(ShimData_Win10_v1
, dwMagic
) == 524);
166 C_ASSERT(offsetof(ShimData_QueryOffset
, dwSize_10_v2
) == 0);
167 C_ASSERT(offsetof(ShimData_QueryOffset
, dwSize_2k3
) == 68);
168 C_ASSERT(offsetof(ShimData_QueryOffset
, dwSize_7_10
) == 520);
170 C_ASSERT(offsetof(ShimData_QueryOffset
, dwMagic_10_v2
) == 4);
171 C_ASSERT(offsetof(ShimData_QueryOffset
, dwMagic_2k3
) == 72);
172 C_ASSERT(offsetof(ShimData_QueryOffset
, dwMagic_7_10
) == 524);
176 #define SDB_DATABASE_MAIN_SHIM 0x80030000
178 #define SDBGMEF_IGNORE_ENVIRONMENT 0x1
181 typedef struct test_RemoteShimInfo
183 ULARGE_INTEGER AppCompatFlags
;
184 ULARGE_INTEGER AppCompatFlagsUser
;
188 } test_RemoteShimInfo
;
191 static BOOL
readproc(HANDLE proc
, LPVOID address
, PVOID target
, DWORD size
)
194 if (ReadProcessMemory(proc
, address
, target
, size
, &dwRead
))
196 ok(dwRead
== size
, "Expected to read %u bytes, got %lu\n", size
, dwRead
);
197 return dwRead
== size
;
199 ok(0, "RPM failed with %u\n", GetLastError());
203 static BOOL
get_shiminfo(HANDLE proc
, test_RemoteShimInfo
* info
)
205 PROCESS_BASIC_INFORMATION pbi
= { 0 };
207 NTSTATUS status
= NtQueryInformationProcess(proc
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), &sizeOut
);
208 ok(NT_SUCCESS(status
), "Expected NtQI to succeed, but failed with: %x\n", status
);
209 memset(info
, 0, sizeof(*info
));
210 if (NT_SUCCESS(status
))
213 if (readproc(proc
, pbi
.PebBaseAddress
, &peb
, sizeof(peb
)))
215 MEMORY_BASIC_INFORMATION mbi
= { 0 };
218 info
->AppCompatFlags
= peb
.AppCompatFlags
;
219 info
->AppCompatFlagsUser
= peb
.AppCompatFlagsUser
;
220 info
->AppCompatInfo
= peb
.AppCompatInfo
;
221 if (peb
.pShimData
== NULL
)
224 dwRead
= VirtualQueryEx(proc
, (LPCVOID
)peb
.pShimData
, &mbi
, sizeof(mbi
));
225 ok(dwRead
== sizeof(mbi
), "Expected VQE to return %u, got %lu\n", sizeof(mbi
), dwRead
);
226 if (dwRead
== sizeof(mbi
) || peb
.pShimData
== NULL
)
228 info
->ShimDataSize
= mbi
.RegionSize
;
229 info
->pShimData
= malloc(mbi
.RegionSize
);
230 if (readproc(proc
, peb
.pShimData
, info
->pShimData
, mbi
.RegionSize
))
232 free(info
->pShimData
);
233 info
->pShimData
= NULL
;
240 static HANDLE
create_proc(BOOL suspended
)
242 static char proc_name
[MAX_PATH
] = { 0 };
243 STARTUPINFOA si
= {sizeof(si
)};
244 PROCESS_INFORMATION pi
;
248 GetModuleFileNameA(NULL
, proc_name
, MAX_PATH
);
251 res
= CreateProcessA(NULL
, proc_name
, NULL
, NULL
, TRUE
, suspended
? CREATE_SUSPENDED
: 0, NULL
, NULL
, &si
, &pi
);
254 CloseHandle(pi
.hThread
);
258 static void create_environ(const char* layers
[], size_t num
)
260 char buf
[256] = { 0 };
262 for (n
= 0; n
< num
; ++n
)
266 strcat(buf
, layers
[n
]);
268 SetEnvironmentVariableA("__COMPAT_LAYER", buf
);
271 static void ValidateShim(TAGREF trLayer
, const char* name
)
273 HSDB hsdb
= pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM
, NULL
);
274 ok(hsdb
!= NULL
, "Expected a valid handle\n");
278 TAGID tagid
= 0xdeadbeef;
279 WCHAR nameW
[256] = { 0 };
282 mbstowcs(nameW
, name
, strlen(name
));
284 ret
= pSdbTagRefToTagID(hsdb
, trLayer
, &pdb
, &tagid
);
285 ok(ret
== TRUE
, "Expected pSdbTagRefToTagID to succeed\n");
289 ok(pdb
!= NULL
, "Expected pdb to be a valid pointer\n");
290 ok(tagid
!= 0 && tagid
!= 0xdeadbeef, "Expected tagid to be a valid tag id, was: 0x%x\n", tagid
);
291 tag
= pSdbGetTagFromTagID(pdb
, tagid
);
292 ok(tag
== 0x700b, "Expected tag to be 0x700b, was 0x%x\n", (DWORD
)tag
);
295 pSdbReleaseDatabase(hsdb
);
300 static void Validate_ShimData_Win2k3(PVOID data
, size_t count
, const char* layers
[])
303 ShimData_Win2k3
* pShimData
= (ShimData_Win2k3
*)data
;
305 ok(!lstrcmpW(pShimData
->szModule
, L
"ShimEng.dll"), "Expected pShimData->Module to be %s, was %s\n", wine_dbgstr_w(L
"ShimEng.dll"), wine_dbgstr_w(pShimData
->szModule
));
306 ok(pShimData
->dwMagic
== SHIMDATA_MAGIC
, "Expected pShimData->dwMagic to be 0x%x, was 0x%x\n", SHIMDATA_MAGIC
, pShimData
->dwMagic
);
307 ok(pShimData
->dwSize
== sizeof(ShimData_Win2k3
), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win2k3
), pShimData
->dwSize
);
308 ok(pShimData
->dwCustomSDBMap
== 1, "Expected pShimData->dwCustomSDBMap to be 1, was %u\n", pShimData
->dwCustomSDBMap
);
311 static void Validate_ShimData_Win7(PVOID data
, WCHAR szApphelp
[256], size_t count
, const char* layers
[])
314 ShimData_Win7
* pShimData
= (ShimData_Win7
*)data
;
316 ok(!lstrcmpW(pShimData
->szModule
, szApphelp
), "Expected pShimData->Module to be %s, was %s\n",
317 wine_dbgstr_w(szApphelp
), wine_dbgstr_w(pShimData
->szModule
));
318 ok(pShimData
->dwMagic
== SHIMDATA_MAGIC
, "Expected pShimData->dwMagic to be 0x%x, was 0x%x\n",
319 SHIMDATA_MAGIC
, pShimData
->dwMagic
);
320 ok(pShimData
->dwSize
== sizeof(ShimData_Win7
), "Expected pShimData->dwSize to be %u, was %u\n",
321 sizeof(ShimData_Win7
), pShimData
->dwSize
);
322 if (pShimData
->Query
.dwLayerCount
!= min(count
, SDB_MAX_LAYERS
))
325 GetEnvironmentVariableA("__COMPAT_LAYER", buf
, _countof(buf
));
326 trace("At test: %s\n", buf
);
328 ok(pShimData
->Query
.dwLayerCount
== min(count
, SDB_MAX_LAYERS
),
329 "Expected LayerCount to be %u, was %u\n", min(count
, SDB_MAX_LAYERS
), pShimData
->Query
.dwLayerCount
);
330 for (n
= 0; n
< SDB_MAX_LAYERS
; ++n
)
334 ok(pShimData
->Query
.atrLayers
[n
] != 0, "Expected to find a valid layer in index %u / %u\n", n
, count
);
335 ValidateShim(pShimData
->Query
.atrLayers
[n
], layers
[n
]);
338 ok(pShimData
->Query
.atrLayers
[n
] == 0, "Expected to find an empty layer in index %u / %u\n", n
, count
);
340 ok(pShimData
->unknown
== 0x14c, "Expected pShimData->unknown to be 0x14c, was 0x%x\n", pShimData
->unknown
);
343 static void Validate_ShimData_Win10_v2(PVOID data
, WCHAR szApphelp
[256], size_t count
, const char* layers
[])
346 ShimData_Win10_v2
* pShimData
= (ShimData_Win10_v2
*)data
;
348 if (pShimData
->dwMagic
!= SHIMDATA_MAGIC
)
350 skip("Yet another unknown shimdata variant...\n");
354 ok(pShimData
->dwSize
== sizeof(ShimData_Win10_v2
), "Expected pShimData->dwSize to be %u, was %u\n",
355 sizeof(ShimData_Win10_v2
), pShimData
->dwSize
);
356 if (pShimData
->Query
.dwLayerCount
!= min(count
, SDB_MAX_LAYERS
))
359 GetEnvironmentVariableA("__COMPAT_LAYER", buf
, _countof(buf
));
360 trace("At test: %s\n", buf
);
362 ok(pShimData
->Query
.dwLayerCount
== min(count
, SDB_MAX_LAYERS
),
363 "Expected LayerCount to be %u, was %u\n", min(count
, SDB_MAX_LAYERS
), pShimData
->Query
.dwLayerCount
);
364 for (n
= 0; n
< SDB_MAX_LAYERS
; ++n
)
368 ok(pShimData
->Query
.atrLayers
[n
] != 0, "Expected to find a valid layer in index %u / %u\n", n
, count
);
369 ValidateShim(pShimData
->Query
.atrLayers
[n
], layers
[n
]);
372 ok(pShimData
->Query
.atrLayers
[n
] == 0, "Expected to find an empty layer in index %u / %u\n", n
, count
);
377 static void Validate_ShimData_Win10(PVOID data
, WCHAR szApphelp
[256], size_t count
, const char* layers
[])
380 ShimData_Win10_v1
* pShimData
= (ShimData_Win10_v1
*)data
;
382 if (pShimData
->dwMagic
!= SHIMDATA_MAGIC
)
384 Validate_ShimData_Win10_v2(data
, szApphelp
, count
, layers
);
389 ok(!lstrcmpiW(pShimData
->szModule
, szApphelp
), "Expected pShimData->Module to be %s, was %s\n",
390 wine_dbgstr_w(szApphelp
), wine_dbgstr_w(pShimData
->szModule
));
391 ok(pShimData
->dwSize
== sizeof(ShimData_Win10_v1
), "Expected pShimData->dwSize to be %u, was %u\n",
392 sizeof(ShimData_Win10_v1
), pShimData
->dwSize
);
393 if (pShimData
->Query
.dwLayerCount
!= min(count
, SDB_MAX_LAYERS
))
396 GetEnvironmentVariableA("__COMPAT_LAYER", buf
, _countof(buf
));
397 trace("At test: %s\n", buf
);
399 ok(pShimData
->Query
.dwLayerCount
== min(count
, SDB_MAX_LAYERS
),
400 "Expected LayerCount to be %u, was %u\n", min(count
, SDB_MAX_LAYERS
), pShimData
->Query
.dwLayerCount
);
401 for (n
= 0; n
< SDB_MAX_LAYERS
; ++n
)
405 ok(pShimData
->Query
.atrLayers
[n
] != 0, "Expected to find a valid layer in index %u / %u\n", n
, count
);
406 ValidateShim(pShimData
->Query
.atrLayers
[n
], layers
[n
]);
409 ok(pShimData
->Query
.atrLayers
[n
] == 0, "Expected to find an empty layer in index %u / %u\n", n
, count
);
413 static void Validate_EmptyShimData_Win10(PVOID data
)
415 ShimData_Win10_v1
* pShimData
= (ShimData_Win10_v1
*)data
;
416 ok(pShimData
!= NULL
, "Expected pShimData\n");
420 if (pShimData
->dwMagic
!= SHIMDATA_MAGIC
)
422 ShimData_Win10_v2
* pShimData2
= (ShimData_Win10_v2
*)data
;
423 if (pShimData2
->dwMagic
!= SHIMDATA_MAGIC
)
425 skip("Unknown shimdata (win10)\n");
429 ok(!lstrcmpiW(pShimData2
->szLayer
, L
""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData2
->szLayer
));
430 ok(pShimData2
->dwSize
== sizeof(ShimData_Win10_v2
), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win10_v2
), pShimData2
->dwSize
);
431 ok(!memcmp(&pShimData2
->Query
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
435 ok(!lstrcmpiW(pShimData
->szModule
, L
""), "Expected pShimData->Module to be '', was %s\n", wine_dbgstr_w(pShimData
->szModule
));
436 ok(!lstrcmpiW(pShimData
->szLayer
, L
""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData
->szLayer
));
437 ok(pShimData
->dwSize
== sizeof(ShimData_Win10_v1
), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win10_v1
), pShimData
->dwSize
);
438 ok(!memcmp(&pShimData
->Query
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
442 static void Test_layers(WCHAR szApphelp
[256])
444 static const char* layers
[] = {
445 "256Color", "NT4SP5", "DisableNXHideUI", "DisableNXShowUI",
446 "WIN2000SP3", "640X480", /*"DISABLEDWM",*/ "HIGHDPIAWARE",
447 /*"RUNASADMIN",*/ "DISABLETHEMES" /*, "Layer_Win95VersionLie"*/ };
451 test_RemoteShimInfo info
;
454 for (n
= 0; n
<= (sizeof(layers
) / sizeof(layers
[0])); ++n
)
456 create_environ(layers
, n
);
458 proc
= create_proc(TRUE
);
459 res
= get_shiminfo(proc
, &info
);
460 TerminateProcess(proc
, 0);
465 ok(0, "Unable to get process info (%u)!\n", n
);
471 ok(info
.AppCompatFlags
.QuadPart
== 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlags
.QuadPart
));
472 ok(info
.AppCompatFlagsUser
.QuadPart
== 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlagsUser
.QuadPart
));
473 ok(info
.AppCompatInfo
== NULL
, "Expected AppCompatInfo to be NULL, was: %p\n", info
.AppCompatInfo
);
474 if (g_WinVersion
< WINVER_WIN10
)
476 ok(info
.pShimData
== NULL
, "Expected pShimData to be NULL, was: %p\n", info
.pShimData
);
480 Validate_EmptyShimData_Win10(info
.pShimData
);
485 ok(info
.AppCompatFlags
.QuadPart
== 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlags
.QuadPart
));
486 ok(info
.AppCompatFlagsUser
.QuadPart
== 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlagsUser
.QuadPart
));
487 ok(info
.AppCompatInfo
== NULL
, "Expected AppCompatInfo to be NULL, was: %p\n", info
.AppCompatInfo
);
488 ok(info
.pShimData
!= NULL
, "Expected pShimData to be valid, was NULL\n");
489 ok(info
.ShimDataSize
== g_ShimDataSize
, "Expected ShimDataSize to be %u, was: %u\n", g_ShimDataSize
, info
.ShimDataSize
);
492 if (g_WinVersion
< WINVER_VISTA
)
493 Validate_ShimData_Win2k3(info
.pShimData
, n
, layers
);
494 else if (g_WinVersion
< WINVER_WIN10
)
495 Validate_ShimData_Win7(info
.pShimData
, szApphelp
, n
, layers
);
497 Validate_ShimData_Win10(info
.pShimData
, szApphelp
, n
, layers
);
500 free(info
.pShimData
);
506 [Warn][SdbGetMatchingExe ] __COMPAT_LAYER name cannot exceed 256 characters.
507 [Info][SdbpGetPermLayersInternal] Failed to read value info from Key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" Status 0xc0000034
508 [Info][SdbpGetPermLayersInternal] Failed to read value info from Key "\REGISTRY\USER\S-1-5-21-4051718696-421402927-393408651-2638\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" Status 0xc0000034
509 [Warn][SdbpEnumUserSdb ] Failed to open key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\NotepadReplacer.exe" Status 0xc0000034
511 static void Test_repeatlayer(WCHAR szApphelp
[256])
513 static const char* layers
[] = {
514 "256Color", "256Color", "256Color", "256Color",
515 "256Color", "256Color", "256Color", "256Color" };
518 test_RemoteShimInfo info
;
521 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color 256Color 256Color 256Color 256Color 256Color 256Color 256Color");
524 proc
= create_proc(TRUE
);
525 res
= get_shiminfo(proc
, &info
);
526 TerminateProcess(proc
, 0);
531 ok(info
.AppCompatFlags
.QuadPart
== 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlags
.QuadPart
));
532 ok(info
.AppCompatFlagsUser
.QuadPart
== 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlagsUser
.QuadPart
));
533 ok(info
.AppCompatInfo
== 0, "Expected AppCompatInfo to be 0, was: %p\n", info
.AppCompatInfo
);
534 ok(info
.pShimData
!= NULL
, "Expected pShimData to be valid, was NULL\n");
535 ok(info
.ShimDataSize
== g_ShimDataSize
, "Expected ShimDataSize to be %u, was: %u\n", g_ShimDataSize
, info
.ShimDataSize
);
538 /* Win10 only 'loads' one layer */
539 if (g_WinVersion
< WINVER_VISTA
)
540 Validate_ShimData_Win2k3(info
.pShimData
, SDB_MAX_LAYERS
, layers
);
541 else if (g_WinVersion
< WINVER_WIN10
)
542 Validate_ShimData_Win7(info
.pShimData
, szApphelp
, SDB_MAX_LAYERS
, layers
);
544 Validate_ShimData_Win10(info
.pShimData
, szApphelp
, 1, layers
);
549 ok(0, "Unable to get process info!\n");
555 TAGREF
find_layer(const char* szLayerStart
, const char* szLayerEnd
)
557 char layer
[100] = { 0 };
558 WCHAR layerW
[100] = { 0 };
559 strncpy(layer
, szLayerStart
, szLayerEnd
- szLayerStart
);
563 g_LayerDB
= pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM
, 0);
566 mbstowcs(layerW
, layer
, strlen(layer
));
567 return pSdbGetLayerTagRef(g_LayerDB
, layerW
);
570 static void expect_layeronly_imp(SDBQUERYRESULT_VISTA
* result
, const char* layers
, DWORD flags
)
572 DWORD dwLayerCount
= 0, n
;
573 TAGREF atrLayers
[SDB_MAX_LAYERS
] = { 0 };
575 const char* layer
= layers
, *nextlayer
;
576 while (layer
&& *layer
)
578 nextlayer
= strchr(layer
, ' ');
579 atrLayers
[dwLayerCount
++] = find_layer(layer
, nextlayer
? nextlayer
: (layer
+ strlen(layer
)));
580 layer
= nextlayer
? (nextlayer
+1) : NULL
;
583 if (g_ModuleVersion
< WINVER_VISTA
)
585 SDBQUERYRESULT_2k3
* result2
= (SDBQUERYRESULT_2k3
*)result
;
588 winetest_ok(!memcmp(&result2
->atrExes
, &empty_result
.atrExes
, sizeof(result2
->atrExes
)), "Expected atrExes to be empty\n");
589 winetest_ok(!memcmp(&result2
->atrLayers
[dwLayerCount
], &empty_result
.atrLayers
[dwLayerCount
], sizeof(result2
->atrLayers
) - dwLayerCount
* sizeof(result2
->atrLayers
[0])), "Expected atrLayers[+1] to be empty\n");
590 for (n
= 0; n
< dwLayerCount
; ++n
)
592 winetest_ok(result2
->atrLayers
[n
] == atrLayers
[n
], "Expected atrLayers[%u] to be %x, was %x\n",
593 n
, atrLayers
[n
], result2
->atrLayers
[n
]);
595 winetest_ok(result2
->dwLayerFlags
== 0, "Expected dwLayerFlags to be 0, was %u\n", result2
->dwLayerFlags
);
596 winetest_ok(result2
->trApphelp
== 0, "Expected trApphelp to be 0, was %u\n", result2
->trApphelp
);
597 winetest_ok(result2
->dwExeCount
== 0, "Expected dwExeCount to be 0, was %u\n", result2
->dwExeCount
);
598 winetest_ok(result2
->dwLayerCount
== dwLayerCount
, "Expected dwLayerCount to be %u, was %u\n", dwLayerCount
, result2
->dwLayerCount
);
599 winetest_ok(!memcmp(&result2
->guidID
, &empty_result
.guidID
, sizeof(result2
->guidID
)), "Expected guidID to be empty\n");
600 winetest_ok(result2
->dwFlags
== flags
, "Expected dwFlags to be 0x%x, was 0x%x\n", flags
, result2
->dwFlags
);
601 winetest_ok(result2
->dwCustomSDBMap
== 1, "Expected dwCustomSDBMap to be 1, was %u\n", result2
->dwCustomSDBMap
);
602 winetest_ok(!memcmp(&result2
->rgGuidDB
[1], &empty_result
.rgGuidDB
[1], sizeof(result2
->rgGuidDB
) - sizeof(result2
->rgGuidDB
[0])), "Expected rgGuidDB[+1] to be empty\n");
606 winetest_ok(!memcmp(&result
->atrExes
, &empty_result
.atrExes
, sizeof(empty_result
.atrExes
)), "Expected atrExes to be empty\n");
607 winetest_ok(!memcmp(&result
->adwExeFlags
, &empty_result
.adwExeFlags
, sizeof(empty_result
.adwExeFlags
)), "Expected adwExeFlags to be empty\n");
608 winetest_ok(!memcmp(&result
->atrLayers
[dwLayerCount
], &empty_result
.atrLayers
[dwLayerCount
], sizeof(empty_result
.atrLayers
) - dwLayerCount
* sizeof(empty_result
.atrLayers
[0])), "Expected atrLayers[+1] to be empty\n");
609 for (n
= 0; n
< dwLayerCount
; ++n
)
611 winetest_ok(result
->atrLayers
[n
] == atrLayers
[n
], "Expected atrLayers[%u] to be %x, was %x\n",
612 n
, atrLayers
[n
], result
->atrLayers
[n
]);
614 winetest_ok(result
->dwLayerFlags
== 0, "Expected dwLayerFlags to be 0, was %u\n", result
->dwLayerFlags
);
615 winetest_ok(result
->trApphelp
== 0, "Expected trApphelp to be 0, was %u\n", result
->trApphelp
);
616 winetest_ok(result
->dwExeCount
== 0, "Expected dwExeCount to be 0, was %u\n", result
->dwExeCount
);
617 winetest_ok(result
->dwLayerCount
== dwLayerCount
, "Expected dwLayerCount to be %u, was %u\n", dwLayerCount
, result
->dwLayerCount
);
618 winetest_ok(!memcmp(&result
->guidID
, &empty_result
.guidID
, sizeof(empty_result
.guidID
)), "Expected guidID to be empty\n");
619 winetest_ok(result
->dwFlags
== flags
, "Expected dwFlags to be 0x%x, was 0x%x\n", flags
, result
->dwFlags
);
620 winetest_ok(result
->dwCustomSDBMap
== 1, "Expected dwCustomSDBMap to be 1, was %u\n", result
->dwCustomSDBMap
);
621 winetest_ok(!memcmp(&result
->rgGuidDB
[1], &empty_result
.rgGuidDB
[1], sizeof(empty_result
.rgGuidDB
) - sizeof(empty_result
.rgGuidDB
[0])), "Expected rgGuidDB[+1] to be empty\n");
625 static void Test_Shimdata(SDBQUERYRESULT_VISTA
* result
, const WCHAR
* szLayer
)
633 ret
= pSdbPackAppCompatData(g_LayerDB
, result
, &pData
, &dwSize
);
634 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
638 ShimData_Win2k3
* pWin2k3
;
639 ShimData_Win7
* pWin7
;
640 ShimData_Win10_v1
* pWin10
;
641 ShimData_Win10_v2
* pWin10_v2
;
642 SDBQUERYRESULT_VISTA result2
= { { 0 } };
644 DWORD res
= pSdbGetAppCompatDataSize(pData
);
648 case sizeof(ShimData_Win2k3
):
649 pWin2k3
= (ShimData_Win2k3
*)pData
;
650 ok_hex(pWin2k3
->dwMagic
, SHIMDATA_MAGIC
);
651 ok_int(pWin2k3
->dwSize
, dwSize
);
652 ok(pWin2k3
->dwCustomSDBMap
== 1, "Expected pWin2k3->dwCustomSDBMap to equal 1, was %u for %s\n", pWin2k3
->dwCustomSDBMap
, wine_dbgstr_w(szLayer
));
653 //ok(!memcmp(&pWin2k3->Query, result, sizeof(SDBQUERYRESULT_2k3)), "Expected pWin2k3->Query to equal result\n");
654 //ok_wstr(pWin7->szLayer, szLayer);
656 case sizeof(ShimData_Win7
):
657 pWin7
= (ShimData_Win7
*)pData
;
658 ok_hex(pWin7
->dwMagic
, SHIMDATA_MAGIC
);
659 ok_int(pWin7
->dwSize
, dwSize
);
660 ok(!memcmp(&pWin7
->Query
, result
, sizeof(*result
)), "Expected pWin7->Query to equal result\n");
661 ok_wstr(pWin7
->szLayer
, szLayer
);
663 case sizeof(ShimData_Win10_v1
):
664 pWin10
= (ShimData_Win10_v1
*)pData
;
665 ok_hex(pWin10
->dwMagic
, SHIMDATA_MAGIC
);
666 ok_int(pWin10
->dwSize
, dwSize
);
667 ok(!memcmp(&pWin10
->Query
, result
, sizeof(*result
)), "Expected pWin10->Query to equal result\n");
668 ok_wstr(pWin10
->szLayerEnv
, szLayer
);
669 ok_wstr(pWin10
->szLayer
, L
"");
671 case sizeof(ShimData_Win10_v2
):
672 pWin10_v2
= (ShimData_Win10_v2
*)pData
;
673 ok_hex(pWin10_v2
->dwMagic
, SHIMDATA_MAGIC
);
674 ok_int(pWin10_v2
->dwSize
, dwSize
);
675 ok(!memcmp(&pWin10_v2
->Query
, result
, sizeof(*result
)), "Expected pWin10->Query to equal result\n");
676 ok_wstr(pWin10_v2
->szLayerEnv
, szLayer
);
677 ok_wstr(pWin10_v2
->szLayer
, L
"");
680 skip("Unknown size %d\n", dwSize
);
684 ret
= pSdbUnpackAppCompatData(g_LayerDB
, NULL
, pData
, &result2
);
685 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
686 /* TODO: For some reason 2k3 does not seem to output the database GUIDs,
687 investigate when we have support for multible db's! */
688 if (dwSize
== sizeof(ShimData_Win2k3
))
690 SDBQUERYRESULT_2k3
* input
= (SDBQUERYRESULT_2k3
*)result
;
691 SDBQUERYRESULT_2k3
* output
= (SDBQUERYRESULT_2k3
*)&result2
;
692 const GUID rgGuidDB0
= {0x11111111, 0x1111, 0x1111, {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}};
694 // Check expected data.
695 ok(input
->dwLayerCount
== 1,
696 "Expected input->dwLayerCount to be 1, was %u for %s\n",
697 input
->dwLayerCount
, wine_dbgstr_w(szLayer
));
698 ok(input
->dwCustomSDBMap
== 1,
699 "Expected input->dwCustomSDBMap to be 1, was %u for %s\n",
700 input
->dwCustomSDBMap
, wine_dbgstr_w(szLayer
));
701 ok(IsEqualGUID(&input
->rgGuidDB
[0], &rgGuidDB0
),
702 "Expected input->rgGuidDB[0] to be %s, was %s for %s\n",
703 wine_dbgstr_guid(&rgGuidDB0
), wine_dbgstr_guid(&input
->rgGuidDB
[0]), wine_dbgstr_w(szLayer
));
705 // Check missing data.
706 ok(output
->dwLayerCount
== 0,
707 "Expected output->dwLayerCount to be 0, was %u for %s\n",
708 output
->dwLayerCount
, wine_dbgstr_w(szLayer
));
709 ok(output
->dwCustomSDBMap
== 0,
710 "Expected output->dwCustomSDBMap to be 0, was %u for %s\n",
711 output
->dwCustomSDBMap
, wine_dbgstr_w(szLayer
));
712 ok(IsEqualGUID(&output
->rgGuidDB
[0], &empty_result
.rgGuidDB
[0]),
713 "Expected output->rgGuidDB[0] to be empty, was %s for %s\n",
714 wine_dbgstr_guid(&output
->rgGuidDB
[0]), wine_dbgstr_w(szLayer
));
716 // Fake it for now, so the memcmp works.
717 output
->dwLayerCount
= input
->dwLayerCount
;
718 output
->dwCustomSDBMap
= input
->dwCustomSDBMap
;
719 output
->rgGuidDB
[0] = input
->rgGuidDB
[0];
721 ok(!memcmp(&result2
, result
, sizeof(*result
)), "Expected result2 to equal result for %s\n", wine_dbgstr_w(szLayer
));
723 RtlFreeHeap(GetProcessHeap(), 0, pData
);
728 #define expect_layeronly (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_layeronly_imp
731 static void Test_GetMatchingExe(void)
734 SDBQUERYRESULT_VISTA result
= { { 0 } };
735 WCHAR self
[MAX_PATH
];
736 DWORD flags
= (g_WinVersion
< WINVER_VISTA
) ? 0 : ((g_WinVersion
< WINVER_WIN10
) ? 1 : 0x21);
738 GetModuleFileNameW(NULL
, self
, MAX_PATH
);
739 SetEnvironmentVariableA("__COMPAT_LAYER", NULL
);
741 /* szPath cannot be NULL! */
742 ret
= pSdbGetMatchingExe(NULL
, L
"", NULL
, NULL
, 0, &result
);
743 ok(ret
== FALSE
, "Expected ret to be FALSE\n");
744 ok(!memcmp(&result
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
746 result
= empty_result
;
748 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
749 ok(ret
== FALSE
, "Expected ret to be FALSE\n");
750 ok(!memcmp(&result
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
752 result
= empty_result
;
753 SetEnvironmentVariableA("__COMPAT_LAYER", "Some_invalid_layer_name");
755 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
756 ok(ret
== FALSE
, "Expected ret to be FALSE\n");
757 if (g_WinVersion
< WINVER_WIN10
)
758 ok(!memcmp(&result
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
760 ok(!memcmp(&result
, &almost_empty
, sizeof(almost_empty
)), "Expected result to be almost empty\n");
762 result
= empty_result
;
763 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
765 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
766 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
767 expect_layeronly(&result
, "256Color", flags
);
769 Test_Shimdata(&result
, L
"256Color");
771 result
= empty_result
;
772 SetEnvironmentVariableA("__COMPAT_LAYER", "640X480");
774 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
775 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
776 expect_layeronly(&result
, "640X480", flags
);
778 Test_Shimdata(&result
, L
"640X480");
780 /* HIGHDPIAWARE does not exist in 2k3 */
781 if (g_WinVersion
> WINVER_2003
)
783 result
= empty_result
;
784 SetEnvironmentVariableA("__COMPAT_LAYER", "HIGHDPIAWARE");
786 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
787 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
788 expect_layeronly(&result
, "HIGHDPIAWARE", flags
);
790 Test_Shimdata(&result
, L
"HIGHDPIAWARE");
792 result
= empty_result
;
793 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color HIGHDPIAWARE 640X480");
795 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
796 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
797 expect_layeronly(&result
, "256Color HIGHDPIAWARE 640X480", flags
);
799 Test_Shimdata(&result
, L
"256Color HIGHDPIAWARE 640X480");
804 HANDLE
xOpenFile(WCHAR
* ApplicationName
)
806 UNICODE_STRING FileName
;
807 OBJECT_ATTRIBUTES ObjectAttributes
;
808 IO_STATUS_BLOCK IoStatusBlock
;
812 if (!RtlDosPathNameToNtPathName_U(ApplicationName
, &FileName
, NULL
, NULL
))
814 skip("Unable to translate %s to Nt path\n", wine_dbgstr_w(ApplicationName
));
819 InitializeObjectAttributes(&ObjectAttributes
, &FileName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
820 Status
= NtOpenFile(&FileHandle
,
822 FILE_READ_ATTRIBUTES
|
827 FILE_SHARE_READ
| FILE_SHARE_DELETE
,
828 FILE_SYNCHRONOUS_IO_NONALERT
|
829 FILE_NON_DIRECTORY_FILE
);
831 RtlFreeUnicodeString(&FileName
);
833 if (!NT_SUCCESS(Status
))
840 #define RESET_CHECKRUNAPP_VARS()\
842 if (AppCompatData && AppCompatData != &Query) { RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData); } \
843 ExeType = IMAGE_FILE_MACHINE_I386; \
844 SxsDataSize = FusionFlags = Reason = 0; \
846 memset(&Query, 0, sizeof(Query)); \
847 AppCompatData = &Query; \
848 AppCompatDataSize = 123456; \
851 #define CHECK_BASICS()\
854 ok(AppCompatData != NULL && AppCompatData != &Query, "Expected the pointer to be valid\n"); \
855 ok_hex(AppCompatDataSize, sizeof(SDBQUERYRESULT_VISTA)); \
856 ok(SxsData == NULL, "Expected the pointer to be NULL\n"); \
857 ok_hex(SxsDataSize, 0); \
858 ok_hex(FusionFlags, 0); \
861 /* W10 does not seem to use the flags at all, so with this macro we can still test it below 10. */
862 #define CHECKREASON(value, w10dum) (g_ModuleVersion < WINVER_WIN10 ? value : w10dum)
865 static BOOL
call_ApphelpCheckRunApp(HANDLE FileHandle
, PWCHAR ApplicationName
, PVOID Environment
, USHORT ExeType
,
866 PULONG Reason
, PVOID
* SdbQueryAppCompatData
, PULONG SdbQueryAppCompatDataSize
,
867 PVOID
* SxsData
, PULONG SxsDataSize
, PULONG FusionFlags
)
869 ULONG64 SomeFlag1
= 0;
872 if (pApphelpCheckRunAppEx_w7
)
874 return pApphelpCheckRunAppEx_w7(FileHandle
, NULL
, NULL
, ApplicationName
, Environment
, ExeType
, Reason
,
875 SdbQueryAppCompatData
, SdbQueryAppCompatDataSize
, SxsData
, SxsDataSize
,
876 FusionFlags
, &SomeFlag1
, &SomeFlag2
);
879 if (pApphelpCheckRunAppEx_w10
)
881 return pApphelpCheckRunAppEx_w10(FileHandle
, NULL
, NULL
, ApplicationName
, Environment
, NULL
, ExeType
, Reason
,
882 SdbQueryAppCompatData
, SdbQueryAppCompatDataSize
, SxsData
, SxsDataSize
,
883 FusionFlags
, &SomeFlag1
, &SomeFlag2
);
893 static void Test_ApphelpCheckRunApp(WCHAR szApphelp
[256])
896 HANDLE FileHandle
= NULL
;
897 WCHAR ApplicationName
[MAX_PATH
], EmptyName
[1] = { 0 };
898 DWORD expect_flags
= (g_WinVersion
< WINVER_WIN10
) ? 1 : 0x21;
901 PVOID AppCompatData
= NULL
, SxsData
, DuplicatedEnv
, Environment
;
902 ULONG AppCompatDataSize
, SxsDataSize
, FusionFlags
;
904 SDBQUERYRESULT_VISTA Query
;
906 /* this are the only interesting bits (with the exception of '1', which is there to invoke the 'default' case) */
907 const int kTestBits
= 0x70503;
909 if (!pApphelpCheckRunAppEx_w7
&& !pApphelpCheckRunAppEx_w10
)
911 skip("No usable ApphelpCheckRunAppEx\n");
915 GetModuleFileNameW(NULL
, ApplicationName
, MAX_PATH
);
917 FileHandle
= xOpenFile(ApplicationName
);
918 SetEnvironmentVariableA("__COMPAT_LAYER", NULL
);
919 if (!CreateEnvironmentBlock(&DuplicatedEnv
, NULL
, TRUE
))
920 DuplicatedEnv
= NULL
;
921 ok(DuplicatedEnv
!= NULL
, "Invalid env (%u)\n", GetLastError());
923 /* First with the environment without __COMPAT_LAYER */
924 RESET_CHECKRUNAPP_VARS();
926 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, DuplicatedEnv
, ExeType
, &Reason
,
927 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
930 ok_hex(Reason
, CHECKREASON(0x30000, 0));
931 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
933 /* We need this to be set for tests later on. */
934 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
936 if (g_ModuleVersion
< WINVER_WIN10
)
938 /* Showing that when an environment is passed in, that is used instead of the current.
939 In Win10 this behavior is no longer observed */
941 RESET_CHECKRUNAPP_VARS();
943 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, DuplicatedEnv
, ExeType
, &Reason
,
944 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
947 ok_hex(Reason
, CHECKREASON(0x30000, 0));
948 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
951 for (n
= 0; n
< 32; ++n
)
953 ULONG ExpectedReason
;
954 if (!(kTestBits
& (1<<n
)))
956 RESET_CHECKRUNAPP_VARS();
957 ExpectedReason
= Reason
= (1 << n
);
958 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, DuplicatedEnv
, ExeType
, &Reason
,
959 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
962 if (ExpectedReason
== 2)
964 else if (ExpectedReason
== 0x100)
965 ExpectedReason
= 0x30000;
967 ExpectedReason
|= 0x30000;
968 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
969 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
972 if (g_ModuleVersion
< WINVER_WIN10
)
974 /* Now, using a NULL env, showing that the current environment is used.
975 W10 does no longer do this, so we skip this test here. */
978 RESET_CHECKRUNAPP_VARS();
980 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
981 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
984 ok_hex(Reason
, CHECKREASON(0x50000, 0));
985 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
986 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
988 for (n
= 0; n
< 32; ++n
)
990 ULONG ExpectedReason
;
991 RESET_CHECKRUNAPP_VARS();
992 if (!(kTestBits
& (1<<n
)))
994 ExpectedReason
= Reason
= (1 << n
);
995 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
996 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
999 if (ExpectedReason
== 2)
1001 else if (ExpectedReason
== 0x100)
1002 ExpectedReason
= 0x50000;
1003 else if (ExpectedReason
== 0x400)
1004 ExpectedReason
= 0x30400;
1006 ExpectedReason
|= 0x50000;
1007 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1008 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1010 if (ExpectedReason
!= 0x30400)
1011 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1013 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1018 /* Passing in an environment with __COMPAT_LAYER set */
1019 Environment
= GetEnvironmentStringsW();
1021 RESET_CHECKRUNAPP_VARS();
1023 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1024 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1027 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1028 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1029 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1031 for (n
= 0; n
< 32; ++n
)
1033 ULONG ExpectedReason
;
1034 if (!(kTestBits
& (1<<n
)))
1036 RESET_CHECKRUNAPP_VARS();
1037 ExpectedReason
= Reason
= (1 << n
);
1038 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1039 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1042 if (ExpectedReason
== 2)
1044 else if (ExpectedReason
== 0x100)
1045 ExpectedReason
= 0x50000;
1046 else if (ExpectedReason
== 0x400)
1047 ExpectedReason
= 0x30400;
1049 ExpectedReason
|= 0x50000;
1050 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1051 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1053 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1054 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1056 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1060 /* NULL file handle still works */
1061 RESET_CHECKRUNAPP_VARS();
1063 ret
= call_ApphelpCheckRunApp(NULL
, ApplicationName
, Environment
, ExeType
, &Reason
,
1064 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1067 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1068 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1069 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1071 for (n
= 0; n
< 32; ++n
)
1073 ULONG ExpectedReason
;
1074 RESET_CHECKRUNAPP_VARS();
1075 if (!(kTestBits
& (1<<n
)))
1077 ExpectedReason
= Reason
= (1 << n
);
1078 ret
= call_ApphelpCheckRunApp(NULL
, ApplicationName
, Environment
, ExeType
, &Reason
,
1079 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1082 if (ExpectedReason
== 2)
1084 else if (ExpectedReason
== 0x100)
1085 ExpectedReason
= 0x50000;
1086 else if (ExpectedReason
== 0x400)
1087 ExpectedReason
= 0x30400;
1089 ExpectedReason
|= 0x50000;
1090 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1091 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1093 /* W10 does not use the flags anymore? */
1094 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1095 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1097 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1102 /* INVALID_HANDLE_VALUE file handle results in failure (according to flags!), but still results in AppCompatData */
1103 RESET_CHECKRUNAPP_VARS();
1105 ret
= call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE
, ApplicationName
, Environment
, ExeType
, &Reason
,
1106 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1110 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1111 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1113 for (n
= 0; n
< 32; ++n
)
1115 ULONG ExpectedReason
;
1116 if (!(kTestBits
& (1<<n
)))
1118 RESET_CHECKRUNAPP_VARS();
1119 ExpectedReason
= Reason
= (1 << n
);
1120 ret
= call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE
, NULL
, Environment
, ExeType
, &Reason
,
1121 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1124 if (ExpectedReason
== 0x100)
1126 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1127 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1129 if (ExpectedReason
!= 0x400 && g_ModuleVersion
< WINVER_WIN7
)
1130 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1132 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1136 /* NULL filename crashes, showing this in the log before going down:
1137 [Err ][SdbpGetLongFileName ] Failed to get NT path name for ""
1138 [Err ][SdbpCreateSearchDBContext] Unable to parse executable path for "".
1139 [Err ][SdbGetMatchingExe ] Failed to create search DB context.
1141 RESET_CHECKRUNAPP_VARS();
1143 ret
= call_ApphelpCheckRunApp(FileHandle
, EmptyName
, Environment
, ExeType
, &Reason
,
1144 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1147 ok_hex(Reason
, CHECKREASON(0x30000, 0));
1148 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1149 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1151 /* 0 ExeType = don't care? */
1152 RESET_CHECKRUNAPP_VARS();
1155 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1156 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1159 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1160 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1161 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1163 for (n
= 0; n
< 32; ++n
)
1165 ULONG ExpectedReason
;
1166 if (!(kTestBits
& (1<<n
)))
1168 RESET_CHECKRUNAPP_VARS();
1170 ExpectedReason
= Reason
= (1 << n
);
1171 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1172 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1175 if (ExpectedReason
== 2)
1177 else if (ExpectedReason
== 0x100)
1178 ExpectedReason
= 0x50000;
1179 else if (ExpectedReason
== 0x400)
1180 ExpectedReason
= 0x30400;
1182 ExpectedReason
|= 0x50000;
1183 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1184 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1186 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1187 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1189 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1194 RESET_CHECKRUNAPP_VARS();
1195 ExeType
= IMAGE_FILE_MACHINE_POWERPCFP
;
1197 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1198 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1201 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1202 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1203 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1205 for (n
= 0; n
< 32; ++n
)
1207 ULONG ExpectedReason
;
1208 if (!(kTestBits
& (1<<n
)))
1210 RESET_CHECKRUNAPP_VARS();
1211 ExeType
= IMAGE_FILE_MACHINE_POWERPCFP
;
1212 ExpectedReason
= Reason
= (1 << n
);
1213 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1214 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1217 if (ExpectedReason
== 2)
1219 else if (ExpectedReason
== 0x100)
1220 ExpectedReason
= 0x50000;
1221 else if (ExpectedReason
== 0x400)
1222 ExpectedReason
= 0x30400;
1224 ExpectedReason
|= 0x50000;
1225 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1226 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1228 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1229 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1231 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1236 if (AppCompatData
&& AppCompatData
!= &Query
)
1237 RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData
);
1239 FreeEnvironmentStringsW(Environment
);
1240 DestroyEnvironmentBlock(DuplicatedEnv
);
1241 NtClose(FileHandle
);
1247 WCHAR szApphelp
[MAX_PATH
];
1248 ShimData_QueryOffset QueryOffset
;
1250 NTSTATUS ExceptionStatus
= STATUS_SUCCESS
;
1252 //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "127");
1253 //SetEnvironmentVariable("SHIMENG_DEBUG_LEVEL", "127");
1255 silence_debug_output();
1257 hdll
= LoadLibraryA("apphelp.dll");
1261 g_WinVersion
= get_host_winver();
1262 g_ModuleVersion
= get_module_version(hdll
);
1263 trace("Detected host: 0x%x, module: 0x%x\n", g_WinVersion
, g_ModuleVersion
);
1265 GetModuleFileNameW(hdll
, szApphelp
, _countof(szApphelp
));
1268 pSdbGetMatchingExe
= (void*)GetProcAddress(hdll
, "SdbGetMatchingExe");
1269 pSdbInitDatabase
= (void*)GetProcAddress(hdll
, "SdbInitDatabase");
1270 pSdbReleaseDatabase
= (void*)GetProcAddress(hdll
, "SdbReleaseDatabase");
1271 pSdbTagRefToTagID
= (void*)GetProcAddress(hdll
, "SdbTagRefToTagID");
1272 pSdbGetTagFromTagID
= (void*)GetProcAddress(hdll
, "SdbGetTagFromTagID");
1273 pSdbGetLayerTagRef
= (void*)GetProcAddress(hdll
, "SdbGetLayerTagRef");
1275 switch (g_ModuleVersion
)
1278 pApphelpCheckRunAppEx_w7
= (void*)GetProcAddress(hdll
, "ApphelpCheckRunAppEx");
1281 pApphelpCheckRunAppEx_w10
= (void*)GetProcAddress(hdll
, "ApphelpCheckRunAppEx");
1284 skip("Unknown apphelp.dll version %x, cannot determine which ApphelpCheckRunApp(Ex) function to use\n", g_ModuleVersion
);
1288 pSdbPackAppCompatData
= (void*)GetProcAddress(hdll
, "SdbPackAppCompatData");
1289 pSdbUnpackAppCompatData
= (void*)GetProcAddress(hdll
, "SdbUnpackAppCompatData");
1290 pSdbGetAppCompatDataSize
= (void*)GetProcAddress(hdll
, "SdbGetAppCompatDataSize");
1293 memset(&QueryOffset
, 0, sizeof(QueryOffset
));
1294 QueryOffset
.dwMagic_2k3
= QueryOffset
.dwMagic_7_10
= QueryOffset
.dwMagic_10_v2
= SHIMDATA_MAGIC
;
1295 QueryOffset
.dwSize_2k3
= 1;
1296 QueryOffset
.dwSize_7_10
= 2;
1297 QueryOffset
.dwSize_10_v2
= 3;
1299 g_ShimDataSize
= g_WinVersion
< WINVER_WIN10
? 4096 : 8192;
1302 ShimDataType
= pSdbGetAppCompatDataSize(&QueryOffset
);
1304 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1306 ExceptionStatus
= _SEH2_GetExceptionCode();
1310 ok(ExceptionStatus
== STATUS_SUCCESS
, "Exception 0x%08x, expected 0x%08x\n", ExceptionStatus
, STATUS_SUCCESS
);
1311 if (ExceptionStatus
!= STATUS_SUCCESS
)
1313 skip("SdbGetAppCompatDataSize not functional\n");
1317 /* New version of Win10.. */
1318 if (g_WinVersion
== WINVER_WIN10
&& ShimDataType
== 3)
1319 g_ShimDataSize
= 4096;
1321 if (g_WinVersion
== g_ModuleVersion
)
1323 Test_layers(szApphelp
);
1324 Test_repeatlayer(szApphelp
);
1328 skip("Tests requiring process launch, reported OS version (0x%x) does not match apphelp version (0x%x)\n", g_WinVersion
, g_ModuleVersion
);
1332 Test_GetMatchingExe();
1335 Test_ApphelpCheckRunApp(szApphelp
);
1337 pSdbReleaseDatabase(g_LayerDB
);