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 "apphelp_apitest.h"
35 BOOL(WINAPI
*pSdbGetMatchingExe
)(HSDB hsdb
, LPCWSTR szPath
, LPCWSTR szModuleName
, LPCWSTR pszEnvironment
, DWORD dwFlags
, PSDBQUERYRESULT_VISTA pQueryResult
);
36 HSDB (WINAPI
*pSdbInitDatabase
)(DWORD dwFlags
, LPCWSTR pszDatabasePath
);
37 void (WINAPI
*pSdbReleaseDatabase
)(HSDB hsdb
);
38 BOOL (WINAPI
*pSdbTagRefToTagID
)(HSDB hsdb
, TAGREF trWhich
, PDB
* ppdb
, TAGID
* ptiWhich
);
39 TAG (WINAPI
*pSdbGetTagFromTagID
)(PDB pdb
, TAGID tiWhich
);
40 TAGREF (WINAPI
*pSdbGetLayerTagRef
)(HSDB hsdb
, LPCWSTR layerName
);
43 /* TODO: Investigate ApphelpCheckRunApp, for some reason there is not AppCompatData generated... */
45 BOOL (WINAPI
*pApphelpCheckRunAppEx_w7
)(HANDLE FileHandle
, PVOID Unk1
, PVOID Unk2
, PWCHAR ApplicationName
, PVOID Environment
, USHORT ExeType
, PULONG Reason
,
46 PVOID
* SdbQueryAppCompatData
, PULONG SdbQueryAppCompatDataSize
, PVOID
* SxsData
, PULONG SxsDataSize
,
47 PULONG FusionFlags
, PULONG64 SomeFlag1
, PULONG SomeFlag2
);
49 BOOL (WINAPI
*pApphelpCheckRunAppEx_w10
)(HANDLE FileHandle
, PVOID Unk1
, PVOID Unk2
, PWCHAR ApplicationName
, PVOID Environment
, PVOID Unk3
, USHORT ExeType
, PULONG Reason
,
50 PVOID
* SdbQueryAppCompatData
, PULONG SdbQueryAppCompatDataSize
, PVOID
* SxsData
, PULONG SxsDataSize
,
51 PULONG FusionFlags
, PULONG64 SomeFlag1
, PULONG SomeFlag2
);
54 BOOL (WINAPI
*pSdbPackAppCompatData
)(HSDB hsdb
, PSDBQUERYRESULT_VISTA pQueryResult
, PVOID
* ppData
, DWORD
*dwSize
);
55 BOOL (WINAPI
*pSdbUnpackAppCompatData
)(HSDB hsdb
, LPCWSTR pszImageName
, PVOID pData
, PSDBQUERYRESULT_VISTA pQueryResult
);
56 DWORD (WINAPI
*pSdbGetAppCompatDataSize
)(PVOID pData
);
59 static HSDB g_LayerDB
;
60 static DWORD g_ShimDataSize
;
61 static DWORD g_ModuleVersion
;
62 static const SDBQUERYRESULT_VISTA empty_result
= { { 0 } };
63 static const SDBQUERYRESULT_VISTA almost_empty
= { { 0 }, { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, SHIMREG_DISABLE_LAYER
, 0 };
66 #define SHIMDATA_MAGIC 0xAC0DEDAB
67 #define MAX_LAYER_LENGTH 256
70 typedef struct ShimData_Win2k3
76 TAGREF atrExes
[SDB_MAX_EXES_2k3
];
77 TAGREF atrLayers
[SDB_MAX_LAYERS
];
81 GUID rgGuidDB
[SDB_MAX_SDBS
];
86 typedef struct ShimData_Win7
91 SDBQUERYRESULT_VISTA Query
;
92 WCHAR szLayer
[MAX_LAYER_LENGTH
];
93 DWORD unknown
; // 0x14c
96 typedef struct ShimData_Win10_v1
102 SDBQUERYRESULT_VISTA Query
;
103 WCHAR szLayer
[MAX_LAYER_LENGTH
];
104 char padding1
[0x200];
105 char padding2
[0x404]; // Contains some data at the start
108 WCHAR processname
[MAX_PATH
];
109 WCHAR szLayerEnv
[MAX_LAYER_LENGTH
];
110 WCHAR unk4
[MAX_LAYER_LENGTH
];
114 typedef struct ShimData_Win10_v2
120 SDBQUERYRESULT_VISTA Query
;
121 WCHAR szLayer
[MAX_LAYER_LENGTH
];
122 char padding1
[0x200];
123 char padding2
[0x2ae + 0x54 + 0x2a + 0x16 + 0x16];
126 WCHAR processname
[MAX_PATH
-2];
127 WCHAR szLayerEnv
[MAX_LAYER_LENGTH
];
128 WCHAR unk5
[MAX_LAYER_LENGTH
];
132 typedef struct ShimData_QueryOffset
146 } ShimData_QueryOffset
;
149 C_ASSERT(sizeof(ShimData_Win2k3
) == 392);
150 C_ASSERT(sizeof(ShimData_Win7
) == 1500);
151 C_ASSERT(sizeof(ShimData_Win10_v1
) == 4712);
152 C_ASSERT(sizeof(ShimData_Win10_v2
) == 3976);
154 C_ASSERT(offsetof(ShimData_Win10_v2
, dwSize
) == 0);
155 C_ASSERT(offsetof(ShimData_Win2k3
, dwSize
) == 68);
156 C_ASSERT(offsetof(ShimData_Win7
, dwSize
) == 520);
157 C_ASSERT(offsetof(ShimData_Win10_v1
, dwSize
) == 520);
159 C_ASSERT(offsetof(ShimData_Win10_v2
, dwMagic
) == 4);
160 C_ASSERT(offsetof(ShimData_Win2k3
, dwMagic
) == 72);
161 C_ASSERT(offsetof(ShimData_Win7
, dwMagic
) == 524);
162 C_ASSERT(offsetof(ShimData_Win10_v1
, dwMagic
) == 524);
164 C_ASSERT(offsetof(ShimData_QueryOffset
, dwSize_10_v2
) == 0);
165 C_ASSERT(offsetof(ShimData_QueryOffset
, dwSize_2k3
) == 68);
166 C_ASSERT(offsetof(ShimData_QueryOffset
, dwSize_7_10
) == 520);
168 C_ASSERT(offsetof(ShimData_QueryOffset
, dwMagic_10_v2
) == 4);
169 C_ASSERT(offsetof(ShimData_QueryOffset
, dwMagic_2k3
) == 72);
170 C_ASSERT(offsetof(ShimData_QueryOffset
, dwMagic_7_10
) == 524);
174 #define SDB_DATABASE_MAIN_SHIM 0x80030000
176 #define SDBGMEF_IGNORE_ENVIRONMENT 0x1
179 typedef struct test_RemoteShimInfo
181 ULARGE_INTEGER AppCompatFlags
;
182 ULARGE_INTEGER AppCompatFlagsUser
;
186 } test_RemoteShimInfo
;
189 static BOOL
readproc(HANDLE proc
, LPVOID address
, PVOID target
, DWORD size
)
192 if (ReadProcessMemory(proc
, address
, target
, size
, &dwRead
))
194 ok(dwRead
== size
, "Expected to read %u bytes, got %lu\n", size
, dwRead
);
195 return dwRead
== size
;
197 ok(0, "RPM failed with %u\n", GetLastError());
201 static BOOL
get_shiminfo(HANDLE proc
, test_RemoteShimInfo
* info
)
203 PROCESS_BASIC_INFORMATION pbi
= { 0 };
205 NTSTATUS status
= NtQueryInformationProcess(proc
, ProcessBasicInformation
, &pbi
, sizeof(pbi
), &sizeOut
);
206 ok(NT_SUCCESS(status
), "Expected NtQI to succeed, but failed with: %x\n", status
);
207 memset(info
, 0, sizeof(*info
));
208 if (NT_SUCCESS(status
))
211 if (readproc(proc
, pbi
.PebBaseAddress
, &peb
, sizeof(peb
)))
213 MEMORY_BASIC_INFORMATION mbi
= { 0 };
216 info
->AppCompatFlags
= peb
.AppCompatFlags
;
217 info
->AppCompatFlagsUser
= peb
.AppCompatFlagsUser
;
218 info
->AppCompatInfo
= peb
.AppCompatInfo
;
219 if (peb
.pShimData
== NULL
)
222 dwRead
= VirtualQueryEx(proc
, (LPCVOID
)peb
.pShimData
, &mbi
, sizeof(mbi
));
223 ok(dwRead
== sizeof(mbi
), "Expected VQE to return %u, got %lu\n", sizeof(mbi
), dwRead
);
224 if (dwRead
== sizeof(mbi
) || peb
.pShimData
== NULL
)
226 info
->ShimDataSize
= mbi
.RegionSize
;
227 info
->pShimData
= malloc(mbi
.RegionSize
);
228 if (readproc(proc
, peb
.pShimData
, info
->pShimData
, mbi
.RegionSize
))
230 free(info
->pShimData
);
231 info
->pShimData
= NULL
;
238 static HANDLE
create_proc(BOOL suspended
)
240 static char proc_name
[MAX_PATH
] = { 0 };
241 STARTUPINFOA si
= {sizeof(si
)};
242 PROCESS_INFORMATION pi
;
246 GetModuleFileNameA(NULL
, proc_name
, MAX_PATH
);
249 res
= CreateProcessA(NULL
, proc_name
, NULL
, NULL
, TRUE
, suspended
? CREATE_SUSPENDED
: 0, NULL
, NULL
, &si
, &pi
);
252 CloseHandle(pi
.hThread
);
256 static void create_environ(const char* layers
[], size_t num
)
258 char buf
[256] = { 0 };
260 for (n
= 0; n
< num
; ++n
)
264 strcat(buf
, layers
[n
]);
266 SetEnvironmentVariableA("__COMPAT_LAYER", buf
);
269 static void ValidateShim(TAGREF trLayer
, const char* name
)
271 HSDB hsdb
= pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM
, NULL
);
272 ok(hsdb
!= NULL
, "Expected a valid handle\n");
276 TAGID tagid
= 0xdeadbeef;
277 WCHAR nameW
[256] = { 0 };
280 mbstowcs(nameW
, name
, strlen(name
));
282 ret
= pSdbTagRefToTagID(hsdb
, trLayer
, &pdb
, &tagid
);
283 ok(ret
== TRUE
, "Expected pSdbTagRefToTagID to succeed\n");
287 ok(pdb
!= NULL
, "Expected pdb to be a valid pointer\n");
288 ok(tagid
!= 0 && tagid
!= 0xdeadbeef, "Expected tagid to be a valid tag id, was: 0x%x\n", tagid
);
289 tag
= pSdbGetTagFromTagID(pdb
, tagid
);
290 ok(tag
== 0x700b, "Expected tag to be 0x700b, was 0x%x\n", (DWORD
)tag
);
293 pSdbReleaseDatabase(hsdb
);
298 static void Validate_ShimData_Win2k3(PVOID data
, size_t count
, const char* layers
[])
301 ShimData_Win2k3
* pShimData
= (ShimData_Win2k3
*)data
;
303 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
));
304 ok(pShimData
->dwMagic
== SHIMDATA_MAGIC
, "Expected pShimData->dwMagic to be 0x%x, was 0x%x\n", SHIMDATA_MAGIC
, pShimData
->dwMagic
);
305 ok(pShimData
->dwSize
== sizeof(ShimData_Win2k3
), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win2k3
), pShimData
->dwSize
);
306 ok(pShimData
->dwCustomSDBMap
== 1, "Expected pShimData->dwCustomSDBMap to be 1, was %u\n", pShimData
->dwCustomSDBMap
);
309 static void Validate_ShimData_Win7(PVOID data
, WCHAR szApphelp
[256], size_t count
, const char* layers
[])
312 ShimData_Win7
* pShimData
= (ShimData_Win7
*)data
;
314 ok(!lstrcmpW(pShimData
->szModule
, szApphelp
), "Expected pShimData->Module to be %s, was %s\n",
315 wine_dbgstr_w(szApphelp
), wine_dbgstr_w(pShimData
->szModule
));
316 ok(pShimData
->dwMagic
== SHIMDATA_MAGIC
, "Expected pShimData->dwMagic to be 0x%x, was 0x%x\n",
317 SHIMDATA_MAGIC
, pShimData
->dwMagic
);
318 ok(pShimData
->dwSize
== sizeof(ShimData_Win7
), "Expected pShimData->dwSize to be %u, was %u\n",
319 sizeof(ShimData_Win7
), pShimData
->dwSize
);
320 if (pShimData
->Query
.dwLayerCount
!= min(count
, SDB_MAX_LAYERS
))
323 GetEnvironmentVariableA("__COMPAT_LAYER", buf
, _countof(buf
));
324 trace("At test: %s\n", buf
);
326 ok(pShimData
->Query
.dwLayerCount
== min(count
, SDB_MAX_LAYERS
),
327 "Expected LayerCount to be %u, was %u\n", min(count
, SDB_MAX_LAYERS
), pShimData
->Query
.dwLayerCount
);
328 for (n
= 0; n
< SDB_MAX_LAYERS
; ++n
)
332 ok(pShimData
->Query
.atrLayers
[n
] != 0, "Expected to find a valid layer in index %u / %u\n", n
, count
);
333 ValidateShim(pShimData
->Query
.atrLayers
[n
], layers
[n
]);
336 ok(pShimData
->Query
.atrLayers
[n
] == 0, "Expected to find an empty layer in index %u / %u\n", n
, count
);
338 ok(pShimData
->unknown
== 0x14c, "Expected pShimData->unknown to be 0x14c, was 0x%x\n", pShimData
->unknown
);
341 static void Validate_ShimData_Win10_v2(PVOID data
, WCHAR szApphelp
[256], size_t count
, const char* layers
[])
344 ShimData_Win10_v2
* pShimData
= (ShimData_Win10_v2
*)data
;
346 if (pShimData
->dwMagic
!= SHIMDATA_MAGIC
)
348 skip("Yet another unknown shimdata variant...\n");
352 ok(pShimData
->dwSize
== sizeof(ShimData_Win10_v2
), "Expected pShimData->dwSize to be %u, was %u\n",
353 sizeof(ShimData_Win10_v2
), pShimData
->dwSize
);
354 if (pShimData
->Query
.dwLayerCount
!= min(count
, SDB_MAX_LAYERS
))
357 GetEnvironmentVariableA("__COMPAT_LAYER", buf
, _countof(buf
));
358 trace("At test: %s\n", buf
);
360 ok(pShimData
->Query
.dwLayerCount
== min(count
, SDB_MAX_LAYERS
),
361 "Expected LayerCount to be %u, was %u\n", min(count
, SDB_MAX_LAYERS
), pShimData
->Query
.dwLayerCount
);
362 for (n
= 0; n
< SDB_MAX_LAYERS
; ++n
)
366 ok(pShimData
->Query
.atrLayers
[n
] != 0, "Expected to find a valid layer in index %u / %u\n", n
, count
);
367 ValidateShim(pShimData
->Query
.atrLayers
[n
], layers
[n
]);
370 ok(pShimData
->Query
.atrLayers
[n
] == 0, "Expected to find an empty layer in index %u / %u\n", n
, count
);
375 static void Validate_ShimData_Win10(PVOID data
, WCHAR szApphelp
[256], size_t count
, const char* layers
[])
378 ShimData_Win10_v1
* pShimData
= (ShimData_Win10_v1
*)data
;
380 if (pShimData
->dwMagic
!= SHIMDATA_MAGIC
)
382 Validate_ShimData_Win10_v2(data
, szApphelp
, count
, layers
);
387 ok(!lstrcmpiW(pShimData
->szModule
, szApphelp
), "Expected pShimData->Module to be %s, was %s\n",
388 wine_dbgstr_w(szApphelp
), wine_dbgstr_w(pShimData
->szModule
));
389 ok(pShimData
->dwSize
== sizeof(ShimData_Win10_v1
), "Expected pShimData->dwSize to be %u, was %u\n",
390 sizeof(ShimData_Win10_v1
), pShimData
->dwSize
);
391 if (pShimData
->Query
.dwLayerCount
!= min(count
, SDB_MAX_LAYERS
))
394 GetEnvironmentVariableA("__COMPAT_LAYER", buf
, _countof(buf
));
395 trace("At test: %s\n", buf
);
397 ok(pShimData
->Query
.dwLayerCount
== min(count
, SDB_MAX_LAYERS
),
398 "Expected LayerCount to be %u, was %u\n", min(count
, SDB_MAX_LAYERS
), pShimData
->Query
.dwLayerCount
);
399 for (n
= 0; n
< SDB_MAX_LAYERS
; ++n
)
403 ok(pShimData
->Query
.atrLayers
[n
] != 0, "Expected to find a valid layer in index %u / %u\n", n
, count
);
404 ValidateShim(pShimData
->Query
.atrLayers
[n
], layers
[n
]);
407 ok(pShimData
->Query
.atrLayers
[n
] == 0, "Expected to find an empty layer in index %u / %u\n", n
, count
);
411 static void Validate_EmptyShimData_Win10(PVOID data
)
413 ShimData_Win10_v1
* pShimData
= (ShimData_Win10_v1
*)data
;
414 ok(pShimData
!= NULL
, "Expected pShimData\n");
418 if (pShimData
->dwMagic
!= SHIMDATA_MAGIC
)
420 ShimData_Win10_v2
* pShimData2
= (ShimData_Win10_v2
*)data
;
421 if (pShimData2
->dwMagic
!= SHIMDATA_MAGIC
)
423 skip("Unknown shimdata (win10)\n");
427 ok(!lstrcmpiW(pShimData2
->szLayer
, L
""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData2
->szLayer
));
428 ok(pShimData2
->dwSize
== sizeof(ShimData_Win10_v2
), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win10_v2
), pShimData2
->dwSize
);
429 ok(!memcmp(&pShimData2
->Query
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
433 ok(!lstrcmpiW(pShimData
->szModule
, L
""), "Expected pShimData->Module to be '', was %s\n", wine_dbgstr_w(pShimData
->szModule
));
434 ok(!lstrcmpiW(pShimData
->szLayer
, L
""), "Expected pShimData->szLayer to be '', was %s\n", wine_dbgstr_w(pShimData
->szLayer
));
435 ok(pShimData
->dwSize
== sizeof(ShimData_Win10_v1
), "Expected pShimData->dwSize to be %u, was %u\n", sizeof(ShimData_Win10_v1
), pShimData
->dwSize
);
436 ok(!memcmp(&pShimData
->Query
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
440 static void Test_layers(WCHAR szApphelp
[256])
442 static const char* layers
[] = {
443 "256Color", "NT4SP5", "DisableNXHideUI", "DisableNXShowUI",
444 "WIN2000SP3", "640X480", /*"DISABLEDWM",*/ "HIGHDPIAWARE",
445 /*"RUNASADMIN",*/ "DISABLETHEMES" /*, "Layer_Win95VersionLie"*/ };
449 test_RemoteShimInfo info
;
452 for (n
= 0; n
<= (sizeof(layers
) / sizeof(layers
[0])); ++n
)
454 create_environ(layers
, n
);
456 proc
= create_proc(TRUE
);
457 res
= get_shiminfo(proc
, &info
);
458 TerminateProcess(proc
, 0);
463 ok(0, "Unable to get process info (%u)!\n", n
);
469 ok(info
.AppCompatFlags
.QuadPart
== 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlags
.QuadPart
));
470 ok(info
.AppCompatFlagsUser
.QuadPart
== 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlagsUser
.QuadPart
));
471 ok(info
.AppCompatInfo
== NULL
, "Expected AppCompatInfo to be NULL, was: %p\n", info
.AppCompatInfo
);
472 if (g_WinVersion
< WINVER_WIN10
)
474 ok(info
.pShimData
== NULL
, "Expected pShimData to be NULL, was: %p\n", info
.pShimData
);
478 Validate_EmptyShimData_Win10(info
.pShimData
);
483 ok(info
.AppCompatFlags
.QuadPart
== 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlags
.QuadPart
));
484 ok(info
.AppCompatFlagsUser
.QuadPart
== 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlagsUser
.QuadPart
));
485 ok(info
.AppCompatInfo
== NULL
, "Expected AppCompatInfo to be NULL, was: %p\n", info
.AppCompatInfo
);
486 ok(info
.pShimData
!= NULL
, "Expected pShimData to be valid, was NULL\n");
487 ok(info
.ShimDataSize
== g_ShimDataSize
, "Expected ShimDataSize to be %u, was: %u\n", g_ShimDataSize
, info
.ShimDataSize
);
490 if (g_WinVersion
< WINVER_VISTA
)
491 Validate_ShimData_Win2k3(info
.pShimData
, n
, layers
);
492 else if (g_WinVersion
< WINVER_WIN10
)
493 Validate_ShimData_Win7(info
.pShimData
, szApphelp
, n
, layers
);
495 Validate_ShimData_Win10(info
.pShimData
, szApphelp
, n
, layers
);
498 free(info
.pShimData
);
504 [Warn][SdbGetMatchingExe ] __COMPAT_LAYER name cannot exceed 256 characters.
505 [Info][SdbpGetPermLayersInternal] Failed to read value info from Key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers" Status 0xc0000034
506 [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
507 [Warn][SdbpEnumUserSdb ] Failed to open key "\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\NotepadReplacer.exe" Status 0xc0000034
509 static void Test_repeatlayer(WCHAR szApphelp
[256])
511 static const char* layers
[] = {
512 "256Color", "256Color", "256Color", "256Color",
513 "256Color", "256Color", "256Color", "256Color" };
516 test_RemoteShimInfo info
;
519 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color 256Color 256Color 256Color 256Color 256Color 256Color 256Color");
522 proc
= create_proc(TRUE
);
523 res
= get_shiminfo(proc
, &info
);
524 TerminateProcess(proc
, 0);
529 ok(info
.AppCompatFlags
.QuadPart
== 0, "Expected AppCompatFlags to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlags
.QuadPart
));
530 ok(info
.AppCompatFlagsUser
.QuadPart
== 0, "Expected AppCompatFlagsUser to be 0, was: %s\n", wine_dbgstr_longlong(info
.AppCompatFlagsUser
.QuadPart
));
531 ok(info
.AppCompatInfo
== 0, "Expected AppCompatInfo to be 0, was: %p\n", info
.AppCompatInfo
);
532 ok(info
.pShimData
!= NULL
, "Expected pShimData to be valid, was NULL\n");
533 ok(info
.ShimDataSize
== g_ShimDataSize
, "Expected ShimDataSize to be %u, was: %u\n", g_ShimDataSize
, info
.ShimDataSize
);
536 /* Win10 only 'loads' one layer */
537 if (g_WinVersion
< WINVER_VISTA
)
538 Validate_ShimData_Win2k3(info
.pShimData
, SDB_MAX_LAYERS
, layers
);
539 else if (g_WinVersion
< WINVER_WIN10
)
540 Validate_ShimData_Win7(info
.pShimData
, szApphelp
, SDB_MAX_LAYERS
, layers
);
542 Validate_ShimData_Win10(info
.pShimData
, szApphelp
, 1, layers
);
547 ok(0, "Unable to get process info!\n");
553 TAGREF
find_layer(const char* szLayerStart
, const char* szLayerEnd
)
555 char layer
[100] = { 0 };
556 WCHAR layerW
[100] = { 0 };
557 strncpy(layer
, szLayerStart
, szLayerEnd
- szLayerStart
);
561 g_LayerDB
= pSdbInitDatabase(SDB_DATABASE_MAIN_SHIM
, 0);
564 mbstowcs(layerW
, layer
, strlen(layer
));
565 return pSdbGetLayerTagRef(g_LayerDB
, layerW
);
568 static void expect_layeronly_imp(SDBQUERYRESULT_VISTA
* result
, const char* layers
, DWORD flags
)
570 DWORD dwLayerCount
= 0, n
;
571 TAGREF atrLayers
[SDB_MAX_LAYERS
] = { 0 };
573 const char* layer
= layers
, *nextlayer
;
574 while (layer
&& *layer
)
576 nextlayer
= strchr(layer
, ' ');
577 atrLayers
[dwLayerCount
++] = find_layer(layer
, nextlayer
? nextlayer
: (layer
+ strlen(layer
)));
578 layer
= nextlayer
? (nextlayer
+1) : NULL
;
581 if (g_ModuleVersion
< WINVER_VISTA
)
583 SDBQUERYRESULT_2k3
* result2
= (SDBQUERYRESULT_2k3
*)result
;
586 winetest_ok(!memcmp(&result2
->atrExes
, &empty_result
.atrExes
, sizeof(result2
->atrExes
)), "Expected atrExes to be empty\n");
587 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");
588 for (n
= 0; n
< dwLayerCount
; ++n
)
590 winetest_ok(result2
->atrLayers
[n
] == atrLayers
[n
], "Expected atrLayers[%u] to be %x, was %x\n",
591 n
, atrLayers
[n
], result2
->atrLayers
[n
]);
593 winetest_ok(result2
->dwLayerFlags
== 0, "Expected dwLayerFlags to be 0, was %u\n", result2
->dwLayerFlags
);
594 winetest_ok(result2
->trApphelp
== 0, "Expected trApphelp to be 0, was %u\n", result2
->trApphelp
);
595 winetest_ok(result2
->dwExeCount
== 0, "Expected dwExeCount to be 0, was %u\n", result2
->dwExeCount
);
596 winetest_ok(result2
->dwLayerCount
== dwLayerCount
, "Expected dwLayerCount to be %u, was %u\n", dwLayerCount
, result2
->dwLayerCount
);
597 winetest_ok(!memcmp(&result2
->guidID
, &empty_result
.guidID
, sizeof(result2
->guidID
)), "Expected guidID to be empty\n");
598 winetest_ok(result2
->dwFlags
== flags
, "Expected dwFlags to be 0x%x, was 0x%x\n", flags
, result2
->dwFlags
);
599 winetest_ok(result2
->dwCustomSDBMap
== 1, "Expected dwCustomSDBMap to be 1, was %u\n", result2
->dwCustomSDBMap
);
600 winetest_ok(!memcmp(&result2
->rgGuidDB
[1], &empty_result
.rgGuidDB
[1], sizeof(result2
->rgGuidDB
) - sizeof(result2
->rgGuidDB
[0])), "Expected rgGuidDB[+1] to be empty\n");
604 winetest_ok(!memcmp(&result
->atrExes
, &empty_result
.atrExes
, sizeof(empty_result
.atrExes
)), "Expected atrExes to be empty\n");
605 winetest_ok(!memcmp(&result
->adwExeFlags
, &empty_result
.adwExeFlags
, sizeof(empty_result
.adwExeFlags
)), "Expected adwExeFlags to be empty\n");
606 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");
607 for (n
= 0; n
< dwLayerCount
; ++n
)
609 winetest_ok(result
->atrLayers
[n
] == atrLayers
[n
], "Expected atrLayers[%u] to be %x, was %x\n",
610 n
, atrLayers
[n
], result
->atrLayers
[n
]);
612 winetest_ok(result
->dwLayerFlags
== 0, "Expected dwLayerFlags to be 0, was %u\n", result
->dwLayerFlags
);
613 winetest_ok(result
->trApphelp
== 0, "Expected trApphelp to be 0, was %u\n", result
->trApphelp
);
614 winetest_ok(result
->dwExeCount
== 0, "Expected dwExeCount to be 0, was %u\n", result
->dwExeCount
);
615 winetest_ok(result
->dwLayerCount
== dwLayerCount
, "Expected dwLayerCount to be %u, was %u\n", dwLayerCount
, result
->dwLayerCount
);
616 winetest_ok(!memcmp(&result
->guidID
, &empty_result
.guidID
, sizeof(empty_result
.guidID
)), "Expected guidID to be empty\n");
617 winetest_ok(result
->dwFlags
== flags
, "Expected dwFlags to be 0x%x, was 0x%x\n", flags
, result
->dwFlags
);
618 winetest_ok(result
->dwCustomSDBMap
== 1, "Expected dwCustomSDBMap to be 1, was %u\n", result
->dwCustomSDBMap
);
619 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");
623 static void Test_Shimdata(SDBQUERYRESULT_VISTA
* result
, const WCHAR
* szLayer
)
631 ret
= pSdbPackAppCompatData(g_LayerDB
, result
, &pData
, &dwSize
);
632 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
636 ShimData_Win2k3
* pWin2k3
;
637 ShimData_Win7
* pWin7
;
638 ShimData_Win10_v1
* pWin10
;
639 ShimData_Win10_v2
* pWin10_v2
;
640 SDBQUERYRESULT_VISTA result2
= { { 0 } };
642 DWORD res
= pSdbGetAppCompatDataSize(pData
);
646 case sizeof(ShimData_Win2k3
):
647 pWin2k3
= (ShimData_Win2k3
*)pData
;
648 ok_hex(pWin2k3
->dwMagic
, SHIMDATA_MAGIC
);
649 ok_int(pWin2k3
->dwSize
, dwSize
);
650 ok(pWin2k3
->dwCustomSDBMap
== 1, "Expected pWin2k3->dwCustomSDBMap to equal 1, was %u for %s\n", pWin2k3
->dwCustomSDBMap
, wine_dbgstr_w(szLayer
));
651 //ok(!memcmp(&pWin2k3->Query, result, sizeof(SDBQUERYRESULT_2k3)), "Expected pWin2k3->Query to equal result\n");
652 //ok_wstr(pWin7->szLayer, szLayer);
654 case sizeof(ShimData_Win7
):
655 pWin7
= (ShimData_Win7
*)pData
;
656 ok_hex(pWin7
->dwMagic
, SHIMDATA_MAGIC
);
657 ok_int(pWin7
->dwSize
, dwSize
);
658 ok(!memcmp(&pWin7
->Query
, result
, sizeof(*result
)), "Expected pWin7->Query to equal result\n");
659 ok_wstr(pWin7
->szLayer
, szLayer
);
661 case sizeof(ShimData_Win10_v1
):
662 pWin10
= (ShimData_Win10_v1
*)pData
;
663 ok_hex(pWin10
->dwMagic
, SHIMDATA_MAGIC
);
664 ok_int(pWin10
->dwSize
, dwSize
);
665 ok(!memcmp(&pWin10
->Query
, result
, sizeof(*result
)), "Expected pWin10->Query to equal result\n");
666 ok_wstr(pWin10
->szLayerEnv
, szLayer
);
667 ok_wstr(pWin10
->szLayer
, L
"");
669 case sizeof(ShimData_Win10_v2
):
670 pWin10_v2
= (ShimData_Win10_v2
*)pData
;
671 ok_hex(pWin10_v2
->dwMagic
, SHIMDATA_MAGIC
);
672 ok_int(pWin10_v2
->dwSize
, dwSize
);
673 ok(!memcmp(&pWin10_v2
->Query
, result
, sizeof(*result
)), "Expected pWin10->Query to equal result\n");
674 ok_wstr(pWin10_v2
->szLayerEnv
, szLayer
);
675 ok_wstr(pWin10_v2
->szLayer
, L
"");
678 skip("Unknown size %d\n", dwSize
);
682 ret
= pSdbUnpackAppCompatData(g_LayerDB
, NULL
, pData
, &result2
);
683 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
684 /* TODO: For some reason 2k3 does not seem to output the database GUIDs,
685 investigate when we have support for multible db's! */
686 if (dwSize
== sizeof(ShimData_Win2k3
))
688 SDBQUERYRESULT_2k3
* input
= (SDBQUERYRESULT_2k3
*)result
;
689 SDBQUERYRESULT_2k3
* output
= (SDBQUERYRESULT_2k3
*)&result2
;
690 const GUID rgGuidDB0
= {0x11111111, 0x1111, 0x1111, {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}};
692 // Check expected data.
693 ok(input
->dwLayerCount
== 1,
694 "Expected input->dwLayerCount to be 1, was %u for %s\n",
695 input
->dwLayerCount
, wine_dbgstr_w(szLayer
));
696 ok(input
->dwCustomSDBMap
== 1,
697 "Expected input->dwCustomSDBMap to be 1, was %u for %s\n",
698 input
->dwCustomSDBMap
, wine_dbgstr_w(szLayer
));
699 ok(IsEqualGUID(&input
->rgGuidDB
[0], &rgGuidDB0
),
700 "Expected input->rgGuidDB[0] to be %s, was %s for %s\n",
701 wine_dbgstr_guid(&rgGuidDB0
), wine_dbgstr_guid(&input
->rgGuidDB
[0]), wine_dbgstr_w(szLayer
));
703 // Check missing data.
704 ok(output
->dwLayerCount
== 0,
705 "Expected output->dwLayerCount to be 0, was %u for %s\n",
706 output
->dwLayerCount
, wine_dbgstr_w(szLayer
));
707 ok(output
->dwCustomSDBMap
== 0,
708 "Expected output->dwCustomSDBMap to be 0, was %u for %s\n",
709 output
->dwCustomSDBMap
, wine_dbgstr_w(szLayer
));
710 ok(IsEqualGUID(&output
->rgGuidDB
[0], &empty_result
.rgGuidDB
[0]),
711 "Expected output->rgGuidDB[0] to be empty, was %s for %s\n",
712 wine_dbgstr_guid(&output
->rgGuidDB
[0]), wine_dbgstr_w(szLayer
));
714 // Fake it for now, so the memcmp works.
715 output
->dwLayerCount
= input
->dwLayerCount
;
716 output
->dwCustomSDBMap
= input
->dwCustomSDBMap
;
717 output
->rgGuidDB
[0] = input
->rgGuidDB
[0];
719 ok(!memcmp(&result2
, result
, sizeof(*result
)), "Expected result2 to equal result for %s\n", wine_dbgstr_w(szLayer
));
721 RtlFreeHeap(GetProcessHeap(), 0, pData
);
726 #define expect_layeronly (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_layeronly_imp
729 static void Test_GetMatchingExe(void)
732 SDBQUERYRESULT_VISTA result
= { { 0 } };
733 WCHAR self
[MAX_PATH
];
734 DWORD flags
= (g_WinVersion
< WINVER_VISTA
) ? 0 : ((g_WinVersion
< WINVER_WIN10
) ? 1 : 0x21);
736 GetModuleFileNameW(NULL
, self
, MAX_PATH
);
737 SetEnvironmentVariableA("__COMPAT_LAYER", NULL
);
739 /* szPath cannot be NULL! */
740 ret
= pSdbGetMatchingExe(NULL
, L
"", NULL
, NULL
, 0, &result
);
741 ok(ret
== FALSE
, "Expected ret to be FALSE\n");
742 ok(!memcmp(&result
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
744 result
= empty_result
;
746 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
747 ok(ret
== FALSE
, "Expected ret to be FALSE\n");
748 ok(!memcmp(&result
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
750 result
= empty_result
;
751 SetEnvironmentVariableA("__COMPAT_LAYER", "Some_invalid_layer_name");
753 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
754 ok(ret
== FALSE
, "Expected ret to be FALSE\n");
755 if (g_WinVersion
< WINVER_WIN10
)
756 ok(!memcmp(&result
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
758 ok(!memcmp(&result
, &almost_empty
, sizeof(almost_empty
)), "Expected result to be almost empty\n");
760 result
= empty_result
;
761 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
763 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
764 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
765 expect_layeronly(&result
, "256Color", flags
);
767 Test_Shimdata(&result
, L
"256Color");
769 result
= empty_result
;
770 SetEnvironmentVariableA("__COMPAT_LAYER", "640X480");
772 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
773 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
774 expect_layeronly(&result
, "640X480", flags
);
776 Test_Shimdata(&result
, L
"640X480");
778 /* HIGHDPIAWARE does not exist in 2k3 */
779 if (g_WinVersion
> WINVER_2003
)
781 result
= empty_result
;
782 SetEnvironmentVariableA("__COMPAT_LAYER", "HIGHDPIAWARE");
784 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
785 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
786 expect_layeronly(&result
, "HIGHDPIAWARE", flags
);
788 Test_Shimdata(&result
, L
"HIGHDPIAWARE");
790 result
= empty_result
;
791 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color HIGHDPIAWARE 640X480");
793 ret
= pSdbGetMatchingExe(NULL
, self
, NULL
, NULL
, 0, &result
);
794 ok(ret
== TRUE
, "Expected ret to be TRUE\n");
795 expect_layeronly(&result
, "256Color HIGHDPIAWARE 640X480", flags
);
797 Test_Shimdata(&result
, L
"256Color HIGHDPIAWARE 640X480");
802 HANDLE
xOpenFile(WCHAR
* ApplicationName
)
804 UNICODE_STRING FileName
;
805 OBJECT_ATTRIBUTES ObjectAttributes
;
806 IO_STATUS_BLOCK IoStatusBlock
;
810 if (!RtlDosPathNameToNtPathName_U(ApplicationName
, &FileName
, NULL
, NULL
))
812 skip("Unable to translate %s to Nt path\n", wine_dbgstr_w(ApplicationName
));
817 InitializeObjectAttributes(&ObjectAttributes
, &FileName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
818 Status
= NtOpenFile(&FileHandle
,
820 FILE_READ_ATTRIBUTES
|
825 FILE_SHARE_READ
| FILE_SHARE_DELETE
,
826 FILE_SYNCHRONOUS_IO_NONALERT
|
827 FILE_NON_DIRECTORY_FILE
);
829 RtlFreeUnicodeString(&FileName
);
831 if (!NT_SUCCESS(Status
))
838 #define RESET_CHECKRUNAPP_VARS()\
840 if (AppCompatData && AppCompatData != &Query) { RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData); } \
841 ExeType = IMAGE_FILE_MACHINE_I386; \
842 SxsDataSize = FusionFlags = Reason = 0; \
844 memset(&Query, 0, sizeof(Query)); \
845 AppCompatData = &Query; \
846 AppCompatDataSize = 123456; \
849 #define CHECK_BASICS()\
852 ok(AppCompatData != NULL && AppCompatData != &Query, "Expected the pointer to be valid\n"); \
853 ok_hex(AppCompatDataSize, sizeof(SDBQUERYRESULT_VISTA)); \
854 ok(SxsData == NULL, "Expected the pointer to be NULL\n"); \
855 ok_hex(SxsDataSize, 0); \
856 ok_hex(FusionFlags, 0); \
859 /* W10 does not seem to use the flags at all, so with this macro we can still test it below 10. */
860 #define CHECKREASON(value, w10dum) (g_ModuleVersion < WINVER_WIN10 ? value : w10dum)
863 static BOOL
call_ApphelpCheckRunApp(HANDLE FileHandle
, PWCHAR ApplicationName
, PVOID Environment
, USHORT ExeType
,
864 PULONG Reason
, PVOID
* SdbQueryAppCompatData
, PULONG SdbQueryAppCompatDataSize
,
865 PVOID
* SxsData
, PULONG SxsDataSize
, PULONG FusionFlags
)
867 ULONG64 SomeFlag1
= 0;
870 if (pApphelpCheckRunAppEx_w7
)
872 return pApphelpCheckRunAppEx_w7(FileHandle
, NULL
, NULL
, ApplicationName
, Environment
, ExeType
, Reason
,
873 SdbQueryAppCompatData
, SdbQueryAppCompatDataSize
, SxsData
, SxsDataSize
,
874 FusionFlags
, &SomeFlag1
, &SomeFlag2
);
877 if (pApphelpCheckRunAppEx_w10
)
879 return pApphelpCheckRunAppEx_w10(FileHandle
, NULL
, NULL
, ApplicationName
, Environment
, NULL
, ExeType
, Reason
,
880 SdbQueryAppCompatData
, SdbQueryAppCompatDataSize
, SxsData
, SxsDataSize
,
881 FusionFlags
, &SomeFlag1
, &SomeFlag2
);
891 static void Test_ApphelpCheckRunApp(WCHAR szApphelp
[256])
894 HANDLE FileHandle
= NULL
;
895 WCHAR ApplicationName
[MAX_PATH
], EmptyName
[1] = { 0 };
896 DWORD expect_flags
= (g_WinVersion
< WINVER_WIN10
) ? 1 : 0x21;
899 PVOID AppCompatData
= NULL
, SxsData
, DuplicatedEnv
, Environment
;
900 ULONG AppCompatDataSize
, SxsDataSize
, FusionFlags
;
902 SDBQUERYRESULT_VISTA Query
;
904 /* this are the only interesting bits (with the exception of '1', which is there to invoke the 'default' case) */
905 const int kTestBits
= 0x70503;
907 if (!pApphelpCheckRunAppEx_w7
&& !pApphelpCheckRunAppEx_w10
)
909 skip("No usable ApphelpCheckRunAppEx\n");
913 GetModuleFileNameW(NULL
, ApplicationName
, MAX_PATH
);
915 FileHandle
= xOpenFile(ApplicationName
);
916 SetEnvironmentVariableA("__COMPAT_LAYER", NULL
);
917 if (!CreateEnvironmentBlock(&DuplicatedEnv
, NULL
, TRUE
))
918 DuplicatedEnv
= NULL
;
919 ok(DuplicatedEnv
!= NULL
, "Invalid env (%u)\n", GetLastError());
921 /* First with the environment without __COMPAT_LAYER */
922 RESET_CHECKRUNAPP_VARS();
924 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, DuplicatedEnv
, ExeType
, &Reason
,
925 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
928 ok_hex(Reason
, CHECKREASON(0x30000, 0));
929 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
931 /* We need this to be set for tests later on. */
932 SetEnvironmentVariableA("__COMPAT_LAYER", "256Color");
934 if (g_ModuleVersion
< WINVER_WIN10
)
936 /* Showing that when an environment is passed in, that is used instead of the current.
937 In Win10 this behavior is no longer observed */
939 RESET_CHECKRUNAPP_VARS();
941 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, DuplicatedEnv
, ExeType
, &Reason
,
942 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
945 ok_hex(Reason
, CHECKREASON(0x30000, 0));
946 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
949 for (n
= 0; n
< 32; ++n
)
951 ULONG ExpectedReason
;
952 if (!(kTestBits
& (1<<n
)))
954 RESET_CHECKRUNAPP_VARS();
955 ExpectedReason
= Reason
= (1 << n
);
956 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, DuplicatedEnv
, ExeType
, &Reason
,
957 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
960 if (ExpectedReason
== 2)
962 else if (ExpectedReason
== 0x100)
963 ExpectedReason
= 0x30000;
965 ExpectedReason
|= 0x30000;
966 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
967 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
970 if (g_ModuleVersion
< WINVER_WIN10
)
972 /* Now, using a NULL env, showing that the current environment is used.
973 W10 does no longer do this, so we skip this test here. */
976 RESET_CHECKRUNAPP_VARS();
978 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
979 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
982 ok_hex(Reason
, CHECKREASON(0x50000, 0));
983 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
984 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
986 for (n
= 0; n
< 32; ++n
)
988 ULONG ExpectedReason
;
989 RESET_CHECKRUNAPP_VARS();
990 if (!(kTestBits
& (1<<n
)))
992 ExpectedReason
= Reason
= (1 << n
);
993 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
994 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
997 if (ExpectedReason
== 2)
999 else if (ExpectedReason
== 0x100)
1000 ExpectedReason
= 0x50000;
1001 else if (ExpectedReason
== 0x400)
1002 ExpectedReason
= 0x30400;
1004 ExpectedReason
|= 0x50000;
1005 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1006 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1008 if (ExpectedReason
!= 0x30400)
1009 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1011 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1016 /* Passing in an environment with __COMPAT_LAYER set */
1017 Environment
= GetEnvironmentStringsW();
1019 RESET_CHECKRUNAPP_VARS();
1021 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1022 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1025 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1026 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1027 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1029 for (n
= 0; n
< 32; ++n
)
1031 ULONG ExpectedReason
;
1032 if (!(kTestBits
& (1<<n
)))
1034 RESET_CHECKRUNAPP_VARS();
1035 ExpectedReason
= Reason
= (1 << n
);
1036 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1037 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1040 if (ExpectedReason
== 2)
1042 else if (ExpectedReason
== 0x100)
1043 ExpectedReason
= 0x50000;
1044 else if (ExpectedReason
== 0x400)
1045 ExpectedReason
= 0x30400;
1047 ExpectedReason
|= 0x50000;
1048 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1049 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1051 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1052 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1054 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1058 /* NULL file handle still works */
1059 RESET_CHECKRUNAPP_VARS();
1061 ret
= call_ApphelpCheckRunApp(NULL
, ApplicationName
, Environment
, ExeType
, &Reason
,
1062 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1065 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1066 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1067 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1069 for (n
= 0; n
< 32; ++n
)
1071 ULONG ExpectedReason
;
1072 RESET_CHECKRUNAPP_VARS();
1073 if (!(kTestBits
& (1<<n
)))
1075 ExpectedReason
= Reason
= (1 << n
);
1076 ret
= call_ApphelpCheckRunApp(NULL
, ApplicationName
, Environment
, ExeType
, &Reason
,
1077 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1080 if (ExpectedReason
== 2)
1082 else if (ExpectedReason
== 0x100)
1083 ExpectedReason
= 0x50000;
1084 else if (ExpectedReason
== 0x400)
1085 ExpectedReason
= 0x30400;
1087 ExpectedReason
|= 0x50000;
1088 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1089 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1091 /* W10 does not use the flags anymore? */
1092 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1093 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1095 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1100 /* INVALID_HANDLE_VALUE file handle results in failure (according to flags!), but still results in AppCompatData */
1101 RESET_CHECKRUNAPP_VARS();
1103 ret
= call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE
, ApplicationName
, Environment
, ExeType
, &Reason
,
1104 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1108 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1109 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1111 for (n
= 0; n
< 32; ++n
)
1113 ULONG ExpectedReason
;
1114 if (!(kTestBits
& (1<<n
)))
1116 RESET_CHECKRUNAPP_VARS();
1117 ExpectedReason
= Reason
= (1 << n
);
1118 ret
= call_ApphelpCheckRunApp(INVALID_HANDLE_VALUE
, NULL
, Environment
, ExeType
, &Reason
,
1119 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1122 if (ExpectedReason
== 0x100)
1124 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1125 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1127 if (ExpectedReason
!= 0x400 && g_ModuleVersion
< WINVER_WIN7
)
1128 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1130 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1134 /* NULL filename crashes, showing this in the log before going down:
1135 [Err ][SdbpGetLongFileName ] Failed to get NT path name for ""
1136 [Err ][SdbpCreateSearchDBContext] Unable to parse executable path for "".
1137 [Err ][SdbGetMatchingExe ] Failed to create search DB context.
1139 RESET_CHECKRUNAPP_VARS();
1141 ret
= call_ApphelpCheckRunApp(FileHandle
, EmptyName
, Environment
, ExeType
, &Reason
,
1142 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1145 ok_hex(Reason
, CHECKREASON(0x30000, 0));
1146 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1147 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1149 /* 0 ExeType = don't care? */
1150 RESET_CHECKRUNAPP_VARS();
1153 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1154 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1157 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1158 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1159 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1161 for (n
= 0; n
< 32; ++n
)
1163 ULONG ExpectedReason
;
1164 if (!(kTestBits
& (1<<n
)))
1166 RESET_CHECKRUNAPP_VARS();
1168 ExpectedReason
= Reason
= (1 << n
);
1169 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1170 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1173 if (ExpectedReason
== 2)
1175 else if (ExpectedReason
== 0x100)
1176 ExpectedReason
= 0x50000;
1177 else if (ExpectedReason
== 0x400)
1178 ExpectedReason
= 0x30400;
1180 ExpectedReason
|= 0x50000;
1181 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1182 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1184 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1185 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1187 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1192 RESET_CHECKRUNAPP_VARS();
1193 ExeType
= IMAGE_FILE_MACHINE_POWERPCFP
;
1195 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1196 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1199 ok_hex(Reason
, CHECKREASON(0x50000, 0));
1200 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1201 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1203 for (n
= 0; n
< 32; ++n
)
1205 ULONG ExpectedReason
;
1206 if (!(kTestBits
& (1<<n
)))
1208 RESET_CHECKRUNAPP_VARS();
1209 ExeType
= IMAGE_FILE_MACHINE_POWERPCFP
;
1210 ExpectedReason
= Reason
= (1 << n
);
1211 ret
= call_ApphelpCheckRunApp(FileHandle
, ApplicationName
, Environment
, ExeType
, &Reason
,
1212 &AppCompatData
, &AppCompatDataSize
, &SxsData
, &SxsDataSize
, &FusionFlags
);
1215 if (ExpectedReason
== 2)
1217 else if (ExpectedReason
== 0x100)
1218 ExpectedReason
= 0x50000;
1219 else if (ExpectedReason
== 0x400)
1220 ExpectedReason
= 0x30400;
1222 ExpectedReason
|= 0x50000;
1223 ok_hex(Reason
, CHECKREASON(ExpectedReason
, (1 << n
)));
1224 if (AppCompatData
&& AppCompatDataSize
== sizeof(SDBQUERYRESULT_VISTA
))
1226 if (ExpectedReason
!= 0x30400 || g_ModuleVersion
>= WINVER_WIN10
)
1227 expect_layeronly(AppCompatData
, "256Color", expect_flags
);
1229 ok(!memcmp(AppCompatData
, &empty_result
, sizeof(empty_result
)), "Expected result to be empty\n");
1234 if (AppCompatData
&& AppCompatData
!= &Query
)
1235 RtlFreeHeap(RtlGetProcessHeap(), 0, AppCompatData
);
1237 FreeEnvironmentStringsW(Environment
);
1238 DestroyEnvironmentBlock(DuplicatedEnv
);
1239 NtClose(FileHandle
);
1245 WCHAR szApphelp
[MAX_PATH
];
1246 ShimData_QueryOffset QueryOffset
;
1248 NTSTATUS ExceptionStatus
= STATUS_SUCCESS
;
1250 //SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "127");
1251 //SetEnvironmentVariable("SHIMENG_DEBUG_LEVEL", "127");
1253 silence_debug_output();
1255 hdll
= LoadLibraryA("apphelp.dll");
1259 g_WinVersion
= get_host_winver();
1260 g_ModuleVersion
= get_module_version(hdll
);
1261 trace("Detected host: 0x%x, module: 0x%x\n", g_WinVersion
, g_ModuleVersion
);
1263 GetModuleFileNameW(hdll
, szApphelp
, _countof(szApphelp
));
1266 pSdbGetMatchingExe
= (void*)GetProcAddress(hdll
, "SdbGetMatchingExe");
1267 pSdbInitDatabase
= (void*)GetProcAddress(hdll
, "SdbInitDatabase");
1268 pSdbReleaseDatabase
= (void*)GetProcAddress(hdll
, "SdbReleaseDatabase");
1269 pSdbTagRefToTagID
= (void*)GetProcAddress(hdll
, "SdbTagRefToTagID");
1270 pSdbGetTagFromTagID
= (void*)GetProcAddress(hdll
, "SdbGetTagFromTagID");
1271 pSdbGetLayerTagRef
= (void*)GetProcAddress(hdll
, "SdbGetLayerTagRef");
1273 switch (g_ModuleVersion
)
1276 pApphelpCheckRunAppEx_w7
= (void*)GetProcAddress(hdll
, "ApphelpCheckRunAppEx");
1279 pApphelpCheckRunAppEx_w10
= (void*)GetProcAddress(hdll
, "ApphelpCheckRunAppEx");
1282 skip("Unknown apphelp.dll version %x, cannot determine which ApphelpCheckRunApp(Ex) function to use\n", g_ModuleVersion
);
1286 pSdbPackAppCompatData
= (void*)GetProcAddress(hdll
, "SdbPackAppCompatData");
1287 pSdbUnpackAppCompatData
= (void*)GetProcAddress(hdll
, "SdbUnpackAppCompatData");
1288 pSdbGetAppCompatDataSize
= (void*)GetProcAddress(hdll
, "SdbGetAppCompatDataSize");
1291 memset(&QueryOffset
, 0, sizeof(QueryOffset
));
1292 QueryOffset
.dwMagic_2k3
= QueryOffset
.dwMagic_7_10
= QueryOffset
.dwMagic_10_v2
= SHIMDATA_MAGIC
;
1293 QueryOffset
.dwSize_2k3
= 1;
1294 QueryOffset
.dwSize_7_10
= 2;
1295 QueryOffset
.dwSize_10_v2
= 3;
1297 g_ShimDataSize
= g_WinVersion
< WINVER_WIN10
? 4096 : 8192;
1300 ShimDataType
= pSdbGetAppCompatDataSize(&QueryOffset
);
1302 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1304 ExceptionStatus
= _SEH2_GetExceptionCode();
1308 ok(ExceptionStatus
== STATUS_SUCCESS
, "Exception 0x%08x, expected 0x%08x\n", ExceptionStatus
, STATUS_SUCCESS
);
1309 if (ExceptionStatus
!= STATUS_SUCCESS
)
1311 skip("SdbGetAppCompatDataSize not functional\n");
1315 /* New version of Win10.. */
1316 if (g_WinVersion
== WINVER_WIN10
&& ShimDataType
== 3)
1317 g_ShimDataSize
= 4096;
1319 if (g_WinVersion
== g_ModuleVersion
)
1321 Test_layers(szApphelp
);
1322 Test_repeatlayer(szApphelp
);
1326 skip("Tests requiring process launch, reported OS version (0x%x) does not match apphelp version (0x%x)\n", g_WinVersion
, g_ModuleVersion
);
1330 Test_GetMatchingExe();
1333 Test_ApphelpCheckRunApp(szApphelp
);
1335 pSdbReleaseDatabase(g_LayerDB
);