2017-06-10 20:31:58 +00:00
/*
* Copyright 2016 , 2017 Mark Jansen
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
*/
# include <ntstatus.h>
# define WIN32_NO_STATUS
# include <windows.h>
# include <shlwapi.h>
# include <winnt.h>
# include <userenv.h>
# ifdef __REACTOS__
# include <ntndk.h>
# else
# include <winternl.h>
# endif
# include <winerror.h>
# include <stdio.h>
# include "wine/test.h"
# include "apphelp_apitest.h"
typedef void * HSDB ;
typedef void * PDB ;
typedef DWORD TAGREF ;
typedef WORD TAG ;
static HMODULE hdll ;
BOOL ( WINAPI * pSdbGetMatchingExe ) ( HSDB hsdb , LPCWSTR szPath , LPCWSTR szModuleName , LPCWSTR pszEnvironment , DWORD dwFlags , PSDBQUERYRESULT_VISTA pQueryResult ) ;
HSDB ( WINAPI * pSdbInitDatabase ) ( DWORD dwFlags , LPCWSTR pszDatabasePath ) ;
void ( WINAPI * pSdbReleaseDatabase ) ( HSDB hsdb ) ;
BOOL ( WINAPI * pSdbTagRefToTagID ) ( HSDB hsdb , TAGREF trWhich , PDB * ppdb , TAGID * ptiWhich ) ;
TAG ( WINAPI * pSdbGetTagFromTagID ) ( PDB pdb , TAGID tiWhich ) ;
TAGREF ( WINAPI * pSdbGetLayerTagRef ) ( HSDB hsdb , LPCWSTR layerName ) ;
/* TODO: Investigate ApphelpCheckRunApp, for some reason there is not AppCompatData generated... */
BOOL ( WINAPI * pApphelpCheckRunAppEx_w7 ) ( HANDLE FileHandle , PVOID Unk1 , PVOID Unk2 , PWCHAR ApplicationName , PVOID Environment , USHORT ExeType , PULONG Reason ,
PVOID * SdbQueryAppCompatData , PULONG SdbQueryAppCompatDataSize , PVOID * SxsData , PULONG SxsDataSize ,
PULONG FusionFlags , PULONG64 SomeFlag1 , PULONG SomeFlag2 ) ;
BOOL ( WINAPI * pApphelpCheckRunAppEx_w10 ) ( HANDLE FileHandle , PVOID Unk1 , PVOID Unk2 , PWCHAR ApplicationName , PVOID Environment , PVOID Unk3 , USHORT ExeType , PULONG Reason ,
PVOID * SdbQueryAppCompatData , PULONG SdbQueryAppCompatDataSize , PVOID * SxsData , PULONG SxsDataSize ,
PULONG FusionFlags , PULONG64 SomeFlag1 , PULONG SomeFlag2 ) ;
BOOL ( WINAPI * pSdbPackAppCompatData ) ( HSDB hsdb , PSDBQUERYRESULT_VISTA pQueryResult , PVOID * ppData , DWORD * dwSize ) ;
BOOL ( WINAPI * pSdbUnpackAppCompatData ) ( HSDB hsdb , LPCWSTR pszImageName , PVOID pData , PSDBQUERYRESULT_VISTA pQueryResult ) ;
DWORD ( WINAPI * pSdbGetAppCompatDataSize ) ( PVOID pData ) ;
static HSDB g_LayerDB ;
static DWORD g_ShimDataSize ;
static DWORD g_ModuleVersion ;
static const SDBQUERYRESULT_VISTA empty_result = { { 0 } } ;
static const SDBQUERYRESULT_VISTA almost_empty = { { 0 } , { 0 } , { 0 } , 0 , 0 , 0 , 0 , { 0 } , SHIMREG_DISABLE_LAYER , 0 } ;
# define SHIMDATA_MAGIC 0xAC0DEDAB
# define MAX_LAYER_LENGTH 256
typedef struct ShimData_Win2k3
{
WCHAR szModule [ 34 ] ;
DWORD dwSize ;
DWORD dwMagic ;
TAGREF atrExes [ SDB_MAX_EXES_2k3 ] ;
TAGREF atrLayers [ SDB_MAX_LAYERS ] ;
DWORD dwUnk0 ;
DWORD dwUnk1 ;
DWORD dwCustomSDBMap ;
GUID rgGuidDB [ SDB_MAX_SDBS ] ;
} ShimData_Win2k3 ;
typedef struct ShimData_Win7
{
WCHAR szModule [ 260 ] ;
DWORD dwSize ;
DWORD dwMagic ;
SDBQUERYRESULT_VISTA Query ;
WCHAR szLayer [ MAX_LAYER_LENGTH ] ;
DWORD unknown ; // 0x14c
} ShimData_Win7 ;
typedef struct ShimData_Win10_v1
{
WCHAR szModule [ 260 ] ;
DWORD dwSize ;
DWORD dwMagic ;
DWORD unk1 ;
SDBQUERYRESULT_VISTA Query ;
WCHAR szLayer [ MAX_LAYER_LENGTH ] ;
char padding1 [ 0x200 ] ;
char padding2 [ 0x404 ] ; // Contains some data at the start
DWORD unk2 ;
DWORD unk3 ;
WCHAR processname [ MAX_PATH ] ;
WCHAR szLayerEnv [ MAX_LAYER_LENGTH ] ;
WCHAR unk4 [ MAX_LAYER_LENGTH ] ;
char padding4 [ 120 ] ;
} ShimData_Win10_v1 ;
typedef struct ShimData_Win10_v2
{
DWORD dwSize ;
DWORD dwMagic ;
DWORD unk1 ;
DWORD unk2 ;
SDBQUERYRESULT_VISTA Query ;
WCHAR szLayer [ MAX_LAYER_LENGTH ] ;
char padding1 [ 0x200 ] ;
char padding2 [ 0x2ae + 0x54 + 0x2a + 0x16 + 0x16 ] ;
DWORD unk3 ;
DWORD unk4 ;
WCHAR processname [ MAX_PATH - 2 ] ;
WCHAR szLayerEnv [ MAX_LAYER_LENGTH ] ;
WCHAR unk5 [ MAX_LAYER_LENGTH ] ;
char padding4 [ 76 ] ;
} ShimData_Win10_v2 ;
typedef struct ShimData_QueryOffset
{
DWORD dwSize_10_v2 ;
DWORD dwMagic_10_v2 ;
char spacing1 [ 60 ] ;
DWORD dwSize_2k3 ;
DWORD dwMagic_2k3 ;
char spacing2 [ 444 ] ;
DWORD dwSize_7_10 ;
DWORD dwMagic_7_10 ;
} ShimData_QueryOffset ;
C_ASSERT ( sizeof ( ShimData_Win2k3 ) = = 392 ) ;
C_ASSERT ( sizeof ( ShimData_Win7 ) = = 1500 ) ;
C_ASSERT ( sizeof ( ShimData_Win10_v1 ) = = 4712 ) ;
C_ASSERT ( sizeof ( ShimData_Win10_v2 ) = = 3976 ) ;
C_ASSERT ( offsetof ( ShimData_Win10_v2 , dwSize ) = = 0 ) ;
C_ASSERT ( offsetof ( ShimData_Win2k3 , dwSize ) = = 68 ) ;
C_ASSERT ( offsetof ( ShimData_Win7 , dwSize ) = = 520 ) ;
C_ASSERT ( offsetof ( ShimData_Win10_v1 , dwSize ) = = 520 ) ;
C_ASSERT ( offsetof ( ShimData_Win10_v2 , dwMagic ) = = 4 ) ;
C_ASSERT ( offsetof ( ShimData_Win2k3 , dwMagic ) = = 72 ) ;
C_ASSERT ( offsetof ( ShimData_Win7 , dwMagic ) = = 524 ) ;
C_ASSERT ( offsetof ( ShimData_Win10_v1 , dwMagic ) = = 524 ) ;
C_ASSERT ( offsetof ( ShimData_QueryOffset , dwSize_10_v2 ) = = 0 ) ;
C_ASSERT ( offsetof ( ShimData_QueryOffset , dwSize_2k3 ) = = 68 ) ;
C_ASSERT ( offsetof ( ShimData_QueryOffset , dwSize_7_10 ) = = 520 ) ;
C_ASSERT ( offsetof ( ShimData_QueryOffset , dwMagic_10_v2 ) = = 4 ) ;
C_ASSERT ( offsetof ( ShimData_QueryOffset , dwMagic_2k3 ) = = 72 ) ;
C_ASSERT ( offsetof ( ShimData_QueryOffset , dwMagic_7_10 ) = = 524 ) ;
# define SDB_DATABASE_MAIN_SHIM 0x80030000
# define SDBGMEF_IGNORE_ENVIRONMENT 0x1
typedef struct test_RemoteShimInfo
{
ULARGE_INTEGER AppCompatFlags ;
ULARGE_INTEGER AppCompatFlagsUser ;
PVOID pShimData ;
DWORD ShimDataSize ;
PVOID AppCompatInfo ;
} test_RemoteShimInfo ;
static BOOL readproc ( HANDLE proc , LPVOID address , PVOID target , DWORD size )
{
SIZE_T dwRead ;
if ( ReadProcessMemory ( proc , address , target , size , & dwRead ) )
{
ok ( dwRead = = size , " Expected to read %u bytes, got %lu \n " , size , dwRead ) ;
return dwRead = = size ;
}
ok ( 0 , " RPM failed with %u \n " , GetLastError ( ) ) ;
return FALSE ;
}
static BOOL get_shiminfo ( HANDLE proc , test_RemoteShimInfo * info )
{
PROCESS_BASIC_INFORMATION pbi = { 0 } ;
ULONG sizeOut = 0 ;
NTSTATUS status = NtQueryInformationProcess ( proc , ProcessBasicInformation , & pbi , sizeof ( pbi ) , & sizeOut ) ;
ok ( NT_SUCCESS ( status ) , " Expected NtQI to succeed, but failed with: %x \n " , status ) ;
memset ( info , 0 , sizeof ( * info ) ) ;
if ( NT_SUCCESS ( status ) )
{
PEB peb = { 0 } ;
if ( readproc ( proc , pbi . PebBaseAddress , & peb , sizeof ( peb ) ) )
{
MEMORY_BASIC_INFORMATION mbi = { 0 } ;
SIZE_T dwRead ;
info - > AppCompatFlags = peb . AppCompatFlags ;
info - > AppCompatFlagsUser = peb . AppCompatFlagsUser ;
info - > AppCompatInfo = peb . AppCompatInfo ;
if ( peb . pShimData = = NULL )
return TRUE ;
dwRead = VirtualQueryEx ( proc , ( LPCVOID ) peb . pShimData , & mbi , sizeof ( mbi ) ) ;
ok ( dwRead = = sizeof ( mbi ) , " Expected VQE to return %u, got %lu \n " , sizeof ( mbi ) , dwRead ) ;
if ( dwRead = = sizeof ( mbi ) | | peb . pShimData = = NULL )
{
info - > ShimDataSize = mbi . RegionSize ;
info - > pShimData = malloc ( mbi . RegionSize ) ;
if ( readproc ( proc , peb . pShimData , info - > pShimData , mbi . RegionSize ) )
return TRUE ;
free ( info - > pShimData ) ;
info - > pShimData = NULL ;
}
}
}
return FALSE ;
}
static HANDLE create_proc ( BOOL suspended )
{
static char proc_name [ MAX_PATH ] = { 0 } ;
STARTUPINFOA si = { sizeof ( si ) } ;
PROCESS_INFORMATION pi ;
BOOL res ;
if ( ! proc_name [ 0 ] )
{
GetModuleFileNameA ( NULL , proc_name , MAX_PATH ) ;
}
res = CreateProcessA ( NULL , proc_name , NULL , NULL , TRUE , suspended ? CREATE_SUSPENDED : 0 , NULL , NULL , & si , & pi ) ;
if ( ! res )
return NULL ;
CloseHandle ( pi . hThread ) ;
return pi . hProcess ;
}
static void create_environ ( const char * layers [ ] , size_t num )
{
char buf [ 256 ] = { 0 } ;
size_t n ;
for ( n = 0 ; n < num ; + + n )
{
if ( n )
strcat ( buf , " " ) ;
strcat ( buf , layers [ n ] ) ;
}
SetEnvironmentVariableA ( " __COMPAT_LAYER " , buf ) ;
}
static void ValidateShim ( TAGREF trLayer , const char * name )
{
HSDB hsdb = pSdbInitDatabase ( SDB_DATABASE_MAIN_SHIM , NULL ) ;
ok ( hsdb ! = NULL , " Expected a valid handle \n " ) ;
if ( hsdb )
{
PDB pdb = NULL ;
TAGID tagid = 0xdeadbeef ;
WCHAR nameW [ 256 ] = { 0 } ;
BOOL ret ;
mbstowcs ( nameW , name , strlen ( name ) ) ;
ret = pSdbTagRefToTagID ( hsdb , trLayer , & pdb , & tagid ) ;
ok ( ret = = TRUE , " Expected pSdbTagRefToTagID to succeed \n " ) ;
if ( ret )
{
TAG tag ;
ok ( pdb ! = NULL , " Expected pdb to be a valid pointer \n " ) ;
ok ( tagid ! = 0 & & tagid ! = 0xdeadbeef , " Expected tagid to be a valid tag id, was: 0x%x \n " , tagid ) ;
tag = pSdbGetTagFromTagID ( pdb , tagid ) ;
ok ( tag = = 0x700b , " Expected tag to be 0x700b, was 0x%x \n " , ( DWORD ) tag ) ;
}
pSdbReleaseDatabase ( hsdb ) ;
}
}
static void Validate_ShimData_Win2k3 ( PVOID data , size_t count , const char * layers [ ] )
{
//size_t n;
ShimData_Win2k3 * pShimData = ( ShimData_Win2k3 * ) data ;
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 ) ) ;
ok ( pShimData - > dwMagic = = SHIMDATA_MAGIC , " Expected pShimData->dwMagic to be 0x%x, was 0x%x \n " , SHIMDATA_MAGIC , pShimData - > dwMagic ) ;
ok ( pShimData - > dwSize = = sizeof ( ShimData_Win2k3 ) , " Expected pShimData->dwSize to be %u, was %u \n " , sizeof ( ShimData_Win2k3 ) , pShimData - > dwSize ) ;
ok ( pShimData - > dwCustomSDBMap = = 1 , " Expected pShimData->dwCustomSDBMap to be 1, was %u \n " , pShimData - > dwCustomSDBMap ) ;
}
static void Validate_ShimData_Win7 ( PVOID data , WCHAR szApphelp [ 256 ] , size_t count , const char * layers [ ] )
{
size_t n ;
ShimData_Win7 * pShimData = ( ShimData_Win7 * ) data ;
ok ( ! lstrcmpW ( pShimData - > szModule , szApphelp ) , " Expected pShimData->Module to be %s, was %s \n " ,
wine_dbgstr_w ( szApphelp ) , wine_dbgstr_w ( pShimData - > szModule ) ) ;
ok ( pShimData - > dwMagic = = SHIMDATA_MAGIC , " Expected pShimData->dwMagic to be 0x%x, was 0x%x \n " ,
SHIMDATA_MAGIC , pShimData - > dwMagic ) ;
ok ( pShimData - > dwSize = = sizeof ( ShimData_Win7 ) , " Expected pShimData->dwSize to be %u, was %u \n " ,
sizeof ( ShimData_Win7 ) , pShimData - > dwSize ) ;
if ( pShimData - > Query . dwLayerCount ! = min ( count , SDB_MAX_LAYERS ) )
{
char buf [ 250 ] = { 0 } ;
GetEnvironmentVariableA ( " __COMPAT_LAYER " , buf , _countof ( buf ) ) ;
trace ( " At test: %s \n " , buf ) ;
}
ok ( pShimData - > Query . dwLayerCount = = min ( count , SDB_MAX_LAYERS ) ,
" Expected LayerCount to be %u, was %u \n " , min ( count , SDB_MAX_LAYERS ) , pShimData - > Query . dwLayerCount ) ;
for ( n = 0 ; n < SDB_MAX_LAYERS ; + + n )
{
if ( n < count )
{
ok ( pShimData - > Query . atrLayers [ n ] ! = 0 , " Expected to find a valid layer in index %u / %u \n " , n , count ) ;
ValidateShim ( pShimData - > Query . atrLayers [ n ] , layers [ n ] ) ;
}
else
ok ( pShimData - > Query . atrLayers [ n ] = = 0 , " Expected to find an empty layer in index %u / %u \n " , n , count ) ;
}
ok ( pShimData - > unknown = = 0x14c , " Expected pShimData->unknown to be 0x14c, was 0x%x \n " , pShimData - > unknown ) ;
}
static void Validate_ShimData_Win10_v2 ( PVOID data , WCHAR szApphelp [ 256 ] , size_t count , const char * layers [ ] )
{
size_t n ;
ShimData_Win10_v2 * pShimData = ( ShimData_Win10_v2 * ) data ;
if ( pShimData - > dwMagic ! = SHIMDATA_MAGIC )
{
skip ( " Yet another unknown shimdata variant... \n " ) ;
return ;
}
ok ( pShimData - > dwSize = = sizeof ( ShimData_Win10_v2 ) , " Expected pShimData->dwSize to be %u, was %u \n " ,
sizeof ( ShimData_Win10_v2 ) , pShimData - > dwSize ) ;
if ( pShimData - > Query . dwLayerCount ! = min ( count , SDB_MAX_LAYERS ) )
{
char buf [ 250 ] = { 0 } ;
GetEnvironmentVariableA ( " __COMPAT_LAYER " , buf , _countof ( buf ) ) ;
trace ( " At test: %s \n " , buf ) ;
}
ok ( pShimData - > Query . dwLayerCount = = min ( count , SDB_MAX_LAYERS ) ,
" Expected LayerCount to be %u, was %u \n " , min ( count , SDB_MAX_LAYERS ) , pShimData - > Query . dwLayerCount ) ;
for ( n = 0 ; n < SDB_MAX_LAYERS ; + + n )
{
if ( n < count )
{
ok ( pShimData - > Query . atrLayers [ n ] ! = 0 , " Expected to find a valid layer in index %u / %u \n " , n , count ) ;
ValidateShim ( pShimData - > Query . atrLayers [ n ] , layers [ n ] ) ;
}
else
ok ( pShimData - > Query . atrLayers [ n ] = = 0 , " Expected to find an empty layer in index %u / %u \n " , n , count ) ;
}
}
static void Validate_ShimData_Win10 ( PVOID data , WCHAR szApphelp [ 256 ] , size_t count , const char * layers [ ] )
{
size_t n ;
ShimData_Win10_v1 * pShimData = ( ShimData_Win10_v1 * ) data ;
if ( pShimData - > dwMagic ! = SHIMDATA_MAGIC )
{
Validate_ShimData_Win10_v2 ( data , szApphelp , count , layers ) ;
return ;
}
ok ( ! lstrcmpiW ( pShimData - > szModule , szApphelp ) , " Expected pShimData->Module to be %s, was %s \n " ,
wine_dbgstr_w ( szApphelp ) , wine_dbgstr_w ( pShimData - > szModule ) ) ;
ok ( pShimData - > dwSize = = sizeof ( ShimData_Win10_v1 ) , " Expected pShimData->dwSize to be %u, was %u \n " ,
sizeof ( ShimData_Win10_v1 ) , pShimData - > dwSize ) ;
if ( pShimData - > Query . dwLayerCount ! = min ( count , SDB_MAX_LAYERS ) )
{
char buf [ 250 ] = { 0 } ;
GetEnvironmentVariableA ( " __COMPAT_LAYER " , buf , _countof ( buf ) ) ;
trace ( " At test: %s \n " , buf ) ;
}
ok ( pShimData - > Query . dwLayerCount = = min ( count , SDB_MAX_LAYERS ) ,
" Expected LayerCount to be %u, was %u \n " , min ( count , SDB_MAX_LAYERS ) , pShimData - > Query . dwLayerCount ) ;
for ( n = 0 ; n < SDB_MAX_LAYERS ; + + n )
{
if ( n < count )
{
ok ( pShimData - > Query . atrLayers [ n ] ! = 0 , " Expected to find a valid layer in index %u / %u \n " , n , count ) ;
ValidateShim ( pShimData - > Query . atrLayers [ n ] , layers [ n ] ) ;
}
else
ok ( pShimData - > Query . atrLayers [ n ] = = 0 , " Expected to find an empty layer in index %u / %u \n " , n , count ) ;
}
}
static void Validate_EmptyShimData_Win10 ( PVOID data )
{
ShimData_Win10_v1 * pShimData = ( ShimData_Win10_v1 * ) data ;
ok ( pShimData ! = NULL , " Expected pShimData \n " ) ;
if ( ! pShimData )
return ;
if ( pShimData - > dwMagic ! = SHIMDATA_MAGIC )
{
ShimData_Win10_v2 * pShimData2 = ( ShimData_Win10_v2 * ) data ;
if ( pShimData2 - > dwMagic ! = SHIMDATA_MAGIC )
{
skip ( " Unknown shimdata (win10) \n " ) ;
return ;
}
ok ( ! lstrcmpiW ( pShimData2 - > szLayer , L " " ) , " Expected pShimData->szLayer to be '', was %s \n " , wine_dbgstr_w ( pShimData2 - > szLayer ) ) ;
ok ( pShimData2 - > dwSize = = sizeof ( ShimData_Win10_v2 ) , " Expected pShimData->dwSize to be %u, was %u \n " , sizeof ( ShimData_Win10_v2 ) , pShimData2 - > dwSize ) ;
ok ( ! memcmp ( & pShimData2 - > Query , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
else
{
ok ( ! lstrcmpiW ( pShimData - > szModule , L " " ) , " Expected pShimData->Module to be '', was %s \n " , wine_dbgstr_w ( pShimData - > szModule ) ) ;
ok ( ! lstrcmpiW ( pShimData - > szLayer , L " " ) , " Expected pShimData->szLayer to be '', was %s \n " , wine_dbgstr_w ( pShimData - > szLayer ) ) ;
ok ( pShimData - > dwSize = = sizeof ( ShimData_Win10_v1 ) , " Expected pShimData->dwSize to be %u, was %u \n " , sizeof ( ShimData_Win10_v1 ) , pShimData - > dwSize ) ;
ok ( ! memcmp ( & pShimData - > Query , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
}
static void Test_layers ( WCHAR szApphelp [ 256 ] )
{
static const char * layers [ ] = {
" 256Color " , " NT4SP5 " , " DisableNXHideUI " , " DisableNXShowUI " ,
" WIN2000SP3 " , " 640X480 " , /*"DISABLEDWM",*/ " HIGHDPIAWARE " ,
/*"RUNASADMIN",*/ " DISABLETHEMES " /*, "Layer_Win95VersionLie"*/ } ;
size_t n ;
HANDLE proc ;
test_RemoteShimInfo info ;
BOOL res ;
for ( n = 0 ; n < = ( sizeof ( layers ) / sizeof ( layers [ 0 ] ) ) ; + + n )
{
create_environ ( layers , n ) ;
proc = create_proc ( TRUE ) ;
res = get_shiminfo ( proc , & info ) ;
TerminateProcess ( proc , 0 ) ;
CloseHandle ( proc ) ;
if ( ! res )
{
ok ( 0 , " Unable to get process info (%u)! \n " , n ) ;
continue ;
}
if ( n = = 0 )
{
ok ( info . AppCompatFlags . QuadPart = = 0 , " Expected AppCompatFlags to be 0, was: %s \n " , wine_dbgstr_longlong ( info . AppCompatFlags . QuadPart ) ) ;
ok ( info . AppCompatFlagsUser . QuadPart = = 0 , " Expected AppCompatFlagsUser to be 0, was: %s \n " , wine_dbgstr_longlong ( info . AppCompatFlagsUser . QuadPart ) ) ;
ok ( info . AppCompatInfo = = NULL , " Expected AppCompatInfo to be NULL, was: %p \n " , info . AppCompatInfo ) ;
if ( g_WinVersion < WINVER_WIN10 )
{
ok ( info . pShimData = = NULL , " Expected pShimData to be NULL, was: %p \n " , info . pShimData ) ;
}
else
{
Validate_EmptyShimData_Win10 ( info . pShimData ) ;
}
}
else
{
ok ( info . AppCompatFlags . QuadPart = = 0 , " Expected AppCompatFlags to be 0, was: %s \n " , wine_dbgstr_longlong ( info . AppCompatFlags . QuadPart ) ) ;
ok ( info . AppCompatFlagsUser . QuadPart = = 0 , " Expected AppCompatFlagsUser to be 0, was: %s \n " , wine_dbgstr_longlong ( info . AppCompatFlagsUser . QuadPart ) ) ;
ok ( info . AppCompatInfo = = NULL , " Expected AppCompatInfo to be NULL, was: %p \n " , info . AppCompatInfo ) ;
ok ( info . pShimData ! = NULL , " Expected pShimData to be valid, was NULL \n " ) ;
ok ( info . ShimDataSize = = g_ShimDataSize , " Expected ShimDataSize to be %u, was: %u \n " , g_ShimDataSize , info . ShimDataSize ) ;
if ( info . pShimData )
{
if ( g_WinVersion < WINVER_VISTA )
Validate_ShimData_Win2k3 ( info . pShimData , n , layers ) ;
else if ( g_WinVersion < WINVER_WIN10 )
Validate_ShimData_Win7 ( info . pShimData , szApphelp , n , layers ) ;
else
Validate_ShimData_Win10 ( info . pShimData , szApphelp , n , layers ) ;
}
}
free ( info . pShimData ) ;
}
}
/*
[ Warn ] [ SdbGetMatchingExe ] __COMPAT_LAYER name cannot exceed 256 characters .
[ Info ] [ SdbpGetPermLayersInternal ] Failed to read value info from Key " \ Registry \ Machine \ Software \ Microsoft \ Windows NT \ CurrentVersion \ AppCompatFlags \ Layers " Status 0xc0000034
[ 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
[ Warn ] [ SdbpEnumUserSdb ] Failed to open key " \ Registry \ Machine \ Software \ Microsoft \ Windows NT \ CurrentVersion \ AppCompatFlags \ Custom \ NotepadReplacer.exe " Status 0xc0000034
*/
static void Test_repeatlayer ( WCHAR szApphelp [ 256 ] )
{
static const char * layers [ ] = {
" 256Color " , " 256Color " , " 256Color " , " 256Color " ,
" 256Color " , " 256Color " , " 256Color " , " 256Color " } ;
HANDLE proc ;
test_RemoteShimInfo info ;
BOOL res ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , " 256Color 256Color 256Color 256Color 256Color 256Color 256Color 256Color " ) ;
proc = create_proc ( TRUE ) ;
res = get_shiminfo ( proc , & info ) ;
TerminateProcess ( proc , 0 ) ;
CloseHandle ( proc ) ;
if ( res )
{
ok ( info . AppCompatFlags . QuadPart = = 0 , " Expected AppCompatFlags to be 0, was: %s \n " , wine_dbgstr_longlong ( info . AppCompatFlags . QuadPart ) ) ;
ok ( info . AppCompatFlagsUser . QuadPart = = 0 , " Expected AppCompatFlagsUser to be 0, was: %s \n " , wine_dbgstr_longlong ( info . AppCompatFlagsUser . QuadPart ) ) ;
ok ( info . AppCompatInfo = = 0 , " Expected AppCompatInfo to be 0, was: %p \n " , info . AppCompatInfo ) ;
ok ( info . pShimData ! = NULL , " Expected pShimData to be valid, was NULL \n " ) ;
ok ( info . ShimDataSize = = g_ShimDataSize , " Expected ShimDataSize to be %u, was: %u \n " , g_ShimDataSize , info . ShimDataSize ) ;
if ( info . pShimData )
{
/* Win10 only 'loads' one layer */
if ( g_WinVersion < WINVER_VISTA )
Validate_ShimData_Win2k3 ( info . pShimData , SDB_MAX_LAYERS , layers ) ;
else if ( g_WinVersion < WINVER_WIN10 )
Validate_ShimData_Win7 ( info . pShimData , szApphelp , SDB_MAX_LAYERS , layers ) ;
else
Validate_ShimData_Win10 ( info . pShimData , szApphelp , 1 , layers ) ;
}
}
else
{
ok ( 0 , " Unable to get process info! \n " ) ;
}
}
TAGREF find_layer ( const char * szLayerStart , const char * szLayerEnd )
{
char layer [ 100 ] = { 0 } ;
WCHAR layerW [ 100 ] = { 0 } ;
strncpy ( layer , szLayerStart , szLayerEnd - szLayerStart ) ;
if ( ! g_LayerDB )
{
g_LayerDB = pSdbInitDatabase ( SDB_DATABASE_MAIN_SHIM , 0 ) ;
}
mbstowcs ( layerW , layer , strlen ( layer ) ) ;
return pSdbGetLayerTagRef ( g_LayerDB , layerW ) ;
}
static void expect_layeronly_imp ( SDBQUERYRESULT_VISTA * result , const char * layers , DWORD flags )
{
DWORD dwLayerCount = 0 , n ;
TAGREF atrLayers [ SDB_MAX_LAYERS ] = { 0 } ;
const char * layer = layers , * nextlayer ;
while ( layer & & * layer )
{
nextlayer = strchr ( layer , ' ' ) ;
atrLayers [ dwLayerCount + + ] = find_layer ( layer , nextlayer ? nextlayer : ( layer + strlen ( layer ) ) ) ;
layer = nextlayer ? ( nextlayer + 1 ) : NULL ;
}
if ( g_ModuleVersion < WINVER_VISTA )
{
SDBQUERYRESULT_2k3 * result2 = ( SDBQUERYRESULT_2k3 * ) result ;
result = NULL ;
winetest_ok ( ! memcmp ( & result2 - > atrExes , & empty_result . atrExes , sizeof ( result2 - > atrExes ) ) , " Expected atrExes to be empty \n " ) ;
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 " ) ;
for ( n = 0 ; n < dwLayerCount ; + + n )
{
winetest_ok ( result2 - > atrLayers [ n ] = = atrLayers [ n ] , " Expected atrLayers[%u] to be %x, was %x \n " ,
n , atrLayers [ n ] , result2 - > atrLayers [ n ] ) ;
}
winetest_ok ( result2 - > dwLayerFlags = = 0 , " Expected dwLayerFlags to be 0, was %u \n " , result2 - > dwLayerFlags ) ;
winetest_ok ( result2 - > trApphelp = = 0 , " Expected trApphelp to be 0, was %u \n " , result2 - > trApphelp ) ;
winetest_ok ( result2 - > dwExeCount = = 0 , " Expected dwExeCount to be 0, was %u \n " , result2 - > dwExeCount ) ;
winetest_ok ( result2 - > dwLayerCount = = dwLayerCount , " Expected dwLayerCount to be %u, was %u \n " , dwLayerCount , result2 - > dwLayerCount ) ;
winetest_ok ( ! memcmp ( & result2 - > guidID , & empty_result . guidID , sizeof ( result2 - > guidID ) ) , " Expected guidID to be empty \n " ) ;
winetest_ok ( result2 - > dwFlags = = flags , " Expected dwFlags to be 0x%x, was 0x%x \n " , flags , result2 - > dwFlags ) ;
winetest_ok ( result2 - > dwCustomSDBMap = = 1 , " Expected dwCustomSDBMap to be 1, was %u \n " , result2 - > dwCustomSDBMap ) ;
winetest_ok ( ! memcmp ( & result2 - > rgGuidDB [ 1 ] , & empty_result . rgGuidDB [ 1 ] , sizeof ( result2 - > rgGuidDB ) - sizeof ( result2 - > rgGuidDB [ 0 ] ) ) , " Expected rgGuidDB[+1] to be empty \n " ) ;
}
else
{
winetest_ok ( ! memcmp ( & result - > atrExes , & empty_result . atrExes , sizeof ( empty_result . atrExes ) ) , " Expected atrExes to be empty \n " ) ;
winetest_ok ( ! memcmp ( & result - > adwExeFlags , & empty_result . adwExeFlags , sizeof ( empty_result . adwExeFlags ) ) , " Expected adwExeFlags to be empty \n " ) ;
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 " ) ;
for ( n = 0 ; n < dwLayerCount ; + + n )
{
winetest_ok ( result - > atrLayers [ n ] = = atrLayers [ n ] , " Expected atrLayers[%u] to be %x, was %x \n " ,
n , atrLayers [ n ] , result - > atrLayers [ n ] ) ;
}
winetest_ok ( result - > dwLayerFlags = = 0 , " Expected dwLayerFlags to be 0, was %u \n " , result - > dwLayerFlags ) ;
winetest_ok ( result - > trApphelp = = 0 , " Expected trApphelp to be 0, was %u \n " , result - > trApphelp ) ;
winetest_ok ( result - > dwExeCount = = 0 , " Expected dwExeCount to be 0, was %u \n " , result - > dwExeCount ) ;
winetest_ok ( result - > dwLayerCount = = dwLayerCount , " Expected dwLayerCount to be %u, was %u \n " , dwLayerCount , result - > dwLayerCount ) ;
winetest_ok ( ! memcmp ( & result - > guidID , & empty_result . guidID , sizeof ( empty_result . guidID ) ) , " Expected guidID to be empty \n " ) ;
winetest_ok ( result - > dwFlags = = flags , " Expected dwFlags to be 0x%x, was 0x%x \n " , flags , result - > dwFlags ) ;
winetest_ok ( result - > dwCustomSDBMap = = 1 , " Expected dwCustomSDBMap to be 1, was %u \n " , result - > dwCustomSDBMap ) ;
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 " ) ;
}
}
static void Test_Shimdata ( SDBQUERYRESULT_VISTA * result , const WCHAR * szLayer )
{
BOOL ret ;
PVOID pData ;
DWORD dwSize ;
pData = NULL ;
dwSize = 0 ;
ret = pSdbPackAppCompatData ( g_LayerDB , result , & pData , & dwSize ) ;
ok ( ret = = TRUE , " Expected ret to be TRUE \n " ) ;
if ( pData )
{
ShimData_Win2k3 * pWin2k3 ;
ShimData_Win7 * pWin7 ;
ShimData_Win10_v1 * pWin10 ;
ShimData_Win10_v2 * pWin10_v2 ;
SDBQUERYRESULT_VISTA result2 = { { 0 } } ;
DWORD res = pSdbGetAppCompatDataSize ( pData ) ;
ok_int ( dwSize , res ) ;
switch ( dwSize )
{
case sizeof ( ShimData_Win2k3 ) :
pWin2k3 = ( ShimData_Win2k3 * ) pData ;
ok_hex ( pWin2k3 - > dwMagic , SHIMDATA_MAGIC ) ;
ok_int ( pWin2k3 - > dwSize , dwSize ) ;
ok ( pWin2k3 - > dwCustomSDBMap = = 1 , " Expected pWin2k3->dwCustomSDBMap to equal 1, was %u for %s \n " , pWin2k3 - > dwCustomSDBMap , wine_dbgstr_w ( szLayer ) ) ;
//ok(!memcmp(&pWin2k3->Query, result, sizeof(SDBQUERYRESULT_2k3)), "Expected pWin2k3->Query to equal result\n");
//ok_wstr(pWin7->szLayer, szLayer);
break ;
case sizeof ( ShimData_Win7 ) :
pWin7 = ( ShimData_Win7 * ) pData ;
ok_hex ( pWin7 - > dwMagic , SHIMDATA_MAGIC ) ;
ok_int ( pWin7 - > dwSize , dwSize ) ;
ok ( ! memcmp ( & pWin7 - > Query , result , sizeof ( * result ) ) , " Expected pWin7->Query to equal result \n " ) ;
ok_wstr ( pWin7 - > szLayer , szLayer ) ;
break ;
case sizeof ( ShimData_Win10_v1 ) :
pWin10 = ( ShimData_Win10_v1 * ) pData ;
ok_hex ( pWin10 - > dwMagic , SHIMDATA_MAGIC ) ;
ok_int ( pWin10 - > dwSize , dwSize ) ;
ok ( ! memcmp ( & pWin10 - > Query , result , sizeof ( * result ) ) , " Expected pWin10->Query to equal result \n " ) ;
ok_wstr ( pWin10 - > szLayerEnv , szLayer ) ;
ok_wstr ( pWin10 - > szLayer , L " " ) ;
break ;
case sizeof ( ShimData_Win10_v2 ) :
pWin10_v2 = ( ShimData_Win10_v2 * ) pData ;
ok_hex ( pWin10_v2 - > dwMagic , SHIMDATA_MAGIC ) ;
ok_int ( pWin10_v2 - > dwSize , dwSize ) ;
ok ( ! memcmp ( & pWin10_v2 - > Query , result , sizeof ( * result ) ) , " Expected pWin10->Query to equal result \n " ) ;
ok_wstr ( pWin10_v2 - > szLayerEnv , szLayer ) ;
ok_wstr ( pWin10_v2 - > szLayer , L " " ) ;
break ;
default :
skip ( " Unknown size %d \n " , dwSize ) ;
break ;
}
ret = pSdbUnpackAppCompatData ( g_LayerDB , NULL , pData , & result2 ) ;
ok ( ret = = TRUE , " Expected ret to be TRUE \n " ) ;
/* TODO: For some reason 2k3 does not seem to output the database GUIDs,
investigate when we have support for multible db ' s ! */
if ( dwSize = = sizeof ( ShimData_Win2k3 ) )
{
/* Fake it for now, so the memcmp works. */
SDBQUERYRESULT_2k3 * input = ( SDBQUERYRESULT_2k3 * ) result ;
SDBQUERYRESULT_2k3 * output = ( SDBQUERYRESULT_2k3 * ) & result2 ;
ok ( output - > dwCustomSDBMap = = 0 , " Expected output->dwCustomSDBMap to be 0, was %u for %s \n " , output - > dwCustomSDBMap , wine_dbgstr_w ( szLayer ) ) ;
output - > dwCustomSDBMap = input - > dwCustomSDBMap ;
output - > rgGuidDB [ 0 ] = input - > rgGuidDB [ 0 ] ;
}
ok ( ! memcmp ( & result2 , result , sizeof ( result ) ) , " Expected result2 to equal result for %s \n " , wine_dbgstr_w ( szLayer ) ) ;
RtlFreeHeap ( GetProcessHeap ( ) , 0 , pData ) ;
}
}
# define expect_layeronly (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_layeronly_imp
static void Test_GetMatchingExe ( void )
{
BOOL ret ;
SDBQUERYRESULT_VISTA result = { { 0 } } ;
WCHAR self [ MAX_PATH ] ;
DWORD flags = ( g_WinVersion < WINVER_VISTA ) ? 0 : ( ( g_WinVersion < WINVER_WIN10 ) ? 1 : 0x21 ) ;
GetModuleFileNameW ( NULL , self , MAX_PATH ) ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , NULL ) ;
/* szPath cannot be NULL! */
ret = pSdbGetMatchingExe ( NULL , L " " , NULL , NULL , 0 , & result ) ;
ok ( ret = = FALSE , " Expected ret to be FALSE \n " ) ;
ok ( ! memcmp ( & result , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
result = empty_result ;
ret = pSdbGetMatchingExe ( NULL , self , NULL , NULL , 0 , & result ) ;
ok ( ret = = FALSE , " Expected ret to be FALSE \n " ) ;
ok ( ! memcmp ( & result , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
result = empty_result ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , " Some_invalid_layer_name " ) ;
ret = pSdbGetMatchingExe ( NULL , self , NULL , NULL , 0 , & result ) ;
ok ( ret = = FALSE , " Expected ret to be FALSE \n " ) ;
if ( g_WinVersion < WINVER_WIN10 )
ok ( ! memcmp ( & result , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
else
ok ( ! memcmp ( & result , & almost_empty , sizeof ( almost_empty ) ) , " Expected result to be almost empty \n " ) ;
result = empty_result ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , " 256Color " ) ;
ret = pSdbGetMatchingExe ( NULL , self , NULL , NULL , 0 , & result ) ;
ok ( ret = = TRUE , " Expected ret to be TRUE \n " ) ;
expect_layeronly ( & result , " 256Color " , flags ) ;
Test_Shimdata ( & result , L " 256Color " ) ;
result = empty_result ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , " 640X480 " ) ;
ret = pSdbGetMatchingExe ( NULL , self , NULL , NULL , 0 , & result ) ;
ok ( ret = = TRUE , " Expected ret to be TRUE \n " ) ;
expect_layeronly ( & result , " 640X480 " , flags ) ;
Test_Shimdata ( & result , L " 640X480 " ) ;
/* HIGHDPIAWARE does not exist in 2k3 */
if ( g_WinVersion > WINVER_2003 )
{
result = empty_result ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , " HIGHDPIAWARE " ) ;
ret = pSdbGetMatchingExe ( NULL , self , NULL , NULL , 0 , & result ) ;
ok ( ret = = TRUE , " Expected ret to be TRUE \n " ) ;
expect_layeronly ( & result , " HIGHDPIAWARE " , flags ) ;
Test_Shimdata ( & result , L " HIGHDPIAWARE " ) ;
result = empty_result ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , " 256Color HIGHDPIAWARE 640X480 " ) ;
ret = pSdbGetMatchingExe ( NULL , self , NULL , NULL , 0 , & result ) ;
ok ( ret = = TRUE , " Expected ret to be TRUE \n " ) ;
expect_layeronly ( & result , " 256Color HIGHDPIAWARE 640X480 " , flags ) ;
Test_Shimdata ( & result , L " 256Color HIGHDPIAWARE 640X480 " ) ;
}
}
HANDLE xOpenFile ( WCHAR * ApplicationName )
{
UNICODE_STRING FileName ;
OBJECT_ATTRIBUTES ObjectAttributes ;
IO_STATUS_BLOCK IoStatusBlock ;
NTSTATUS Status ;
HANDLE FileHandle ;
if ( ! RtlDosPathNameToNtPathName_U ( ApplicationName , & FileName , NULL , NULL ) )
{
skip ( " Unable to translate %s to Nt path \n " , wine_dbgstr_w ( ApplicationName ) ) ;
return NULL ;
}
InitializeObjectAttributes ( & ObjectAttributes , & FileName , OBJ_CASE_INSENSITIVE , NULL , NULL ) ;
Status = NtOpenFile ( & FileHandle ,
SYNCHRONIZE |
FILE_READ_ATTRIBUTES |
FILE_READ_DATA |
FILE_EXECUTE ,
& ObjectAttributes ,
& IoStatusBlock ,
FILE_SHARE_READ | FILE_SHARE_DELETE ,
FILE_SYNCHRONOUS_IO_NONALERT |
FILE_NON_DIRECTORY_FILE ) ;
RtlFreeUnicodeString ( & FileName ) ;
if ( ! NT_SUCCESS ( Status ) )
return NULL ;
return FileHandle ;
}
# define RESET_CHECKRUNAPP_VARS()\
do { \
if ( AppCompatData & & AppCompatData ! = & Query ) { RtlFreeHeap ( RtlGetProcessHeap ( ) , 0 , AppCompatData ) ; } \
ExeType = IMAGE_FILE_MACHINE_I386 ; \
SxsDataSize = FusionFlags = Reason = 0 ; \
SxsData = NULL ; \
memset ( & Query , 0 , sizeof ( Query ) ) ; \
AppCompatData = & Query ; \
AppCompatDataSize = 123456 ; \
} while ( 0 )
# define CHECK_BASICS()\
do { \
ok_hex ( ret , TRUE ) ; \
ok ( AppCompatData ! = NULL & & AppCompatData ! = & Query , " Expected the pointer to be valid \n " ) ; \
ok_hex ( AppCompatDataSize , sizeof ( SDBQUERYRESULT_VISTA ) ) ; \
ok ( SxsData = = NULL , " Expected the pointer to be NULL \n " ) ; \
ok_hex ( SxsDataSize , 0 ) ; \
ok_hex ( FusionFlags , 0 ) ; \
} while ( 0 )
/* W10 does not seem to use the flags at all, so with this macro we can still test it below 10. */
# define CHECKREASON(value, w10dum) (g_ModuleVersion < WINVER_WIN10 ? value : w10dum)
static BOOL call_ApphelpCheckRunApp ( HANDLE FileHandle , PWCHAR ApplicationName , PVOID Environment , USHORT ExeType ,
PULONG Reason , PVOID * SdbQueryAppCompatData , PULONG SdbQueryAppCompatDataSize ,
PVOID * SxsData , PULONG SxsDataSize , PULONG FusionFlags )
{
ULONG64 SomeFlag1 = 0 ;
ULONG SomeFlag2 = 0 ;
if ( pApphelpCheckRunAppEx_w7 )
{
return pApphelpCheckRunAppEx_w7 ( FileHandle , NULL , NULL , ApplicationName , Environment , ExeType , Reason ,
SdbQueryAppCompatData , SdbQueryAppCompatDataSize , SxsData , SxsDataSize ,
FusionFlags , & SomeFlag1 , & SomeFlag2 ) ;
}
if ( pApphelpCheckRunAppEx_w10 )
{
return pApphelpCheckRunAppEx_w10 ( FileHandle , NULL , NULL , ApplicationName , Environment , NULL , ExeType , Reason ,
SdbQueryAppCompatData , SdbQueryAppCompatDataSize , SxsData , SxsDataSize ,
FusionFlags , & SomeFlag1 , & SomeFlag2 ) ;
}
return FALSE ;
}
static void Test_ApphelpCheckRunApp ( WCHAR szApphelp [ 256 ] )
{
BOOL ret ;
HANDLE FileHandle = NULL ;
WCHAR ApplicationName [ MAX_PATH ] , EmptyName [ 1 ] = { 0 } ;
DWORD expect_flags = ( g_WinVersion < WINVER_WIN10 ) ? 1 : 0x21 ;
USHORT ExeType ;
PVOID AppCompatData = NULL , SxsData , DuplicatedEnv , Environment ;
ULONG AppCompatDataSize , SxsDataSize , FusionFlags ;
ULONG Reason ;
SDBQUERYRESULT_VISTA Query ;
int n ;
/* this are the only interesting bits (with the exception of '1', which is there to invoke the 'default' case) */
const int kTestBits = 0x70503 ;
if ( ! pApphelpCheckRunAppEx_w7 & & ! pApphelpCheckRunAppEx_w10 )
{
skip ( " No usable ApphelpCheckRunAppEx \n " ) ;
return ;
}
GetModuleFileNameW ( NULL , ApplicationName , MAX_PATH ) ;
FileHandle = xOpenFile ( ApplicationName ) ;
SetEnvironmentVariableA ( " __COMPAT_LAYER " , NULL ) ;
if ( ! CreateEnvironmentBlock ( & DuplicatedEnv , NULL , TRUE ) )
DuplicatedEnv = NULL ;
ok ( DuplicatedEnv ! = NULL , " Invalid env (%u) \n " , GetLastError ( ) ) ;
/* First with the environment without __COMPAT_LAYER */
RESET_CHECKRUNAPP_VARS ( ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , DuplicatedEnv , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x30000 , 0 ) ) ;
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
/* We need this to be set for tests later on. */
SetEnvironmentVariableA ( " __COMPAT_LAYER " , " 256Color " ) ;
if ( g_ModuleVersion < WINVER_WIN10 )
{
/* Showing that when an environment is passed in, that is used instead of the current.
In Win10 this behavior is no longer observed */
RESET_CHECKRUNAPP_VARS ( ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , DuplicatedEnv , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x30000 , 0 ) ) ;
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
for ( n = 0 ; n < 32 ; + + n )
{
ULONG ExpectedReason ;
if ( ! ( kTestBits & ( 1 < < n ) ) )
continue ;
RESET_CHECKRUNAPP_VARS ( ) ;
ExpectedReason = Reason = ( 1 < < n ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , DuplicatedEnv , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
if ( ExpectedReason = = 2 )
ExpectedReason = 2 ;
else if ( ExpectedReason = = 0x100 )
ExpectedReason = 0x30000 ;
else
ExpectedReason | = 0x30000 ;
ok_hex ( Reason , CHECKREASON ( ExpectedReason , ( 1 < < n ) ) ) ;
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
if ( g_ModuleVersion < WINVER_WIN10 )
{
/* Now, using a NULL env, showing that the current environment is used.
W10 does no longer do this , so we skip this test here . */
Environment = NULL ;
RESET_CHECKRUNAPP_VARS ( ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x50000 , 0 ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
for ( n = 0 ; n < 32 ; + + n )
{
ULONG ExpectedReason ;
RESET_CHECKRUNAPP_VARS ( ) ;
if ( ! ( kTestBits & ( 1 < < n ) ) )
continue ;
ExpectedReason = Reason = ( 1 < < n ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
if ( ExpectedReason = = 2 )
ExpectedReason = 2 ;
else if ( ExpectedReason = = 0x100 )
ExpectedReason = 0x50000 ;
else if ( ExpectedReason = = 0x400 )
ExpectedReason = 0x30400 ;
else
ExpectedReason | = 0x50000 ;
ok_hex ( Reason , CHECKREASON ( ExpectedReason , ( 1 < < n ) ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
{
if ( ExpectedReason ! = 0x30400 )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
else
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
}
}
/* Passing in an environment with __COMPAT_LAYER set */
Environment = GetEnvironmentStringsW ( ) ;
RESET_CHECKRUNAPP_VARS ( ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x50000 , 0 ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
for ( n = 0 ; n < 32 ; + + n )
{
ULONG ExpectedReason ;
if ( ! ( kTestBits & ( 1 < < n ) ) )
continue ;
RESET_CHECKRUNAPP_VARS ( ) ;
ExpectedReason = Reason = ( 1 < < n ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
if ( ExpectedReason = = 2 )
ExpectedReason = 2 ;
else if ( ExpectedReason = = 0x100 )
ExpectedReason = 0x50000 ;
else if ( ExpectedReason = = 0x400 )
ExpectedReason = 0x30400 ;
else
ExpectedReason | = 0x50000 ;
ok_hex ( Reason , CHECKREASON ( ExpectedReason , ( 1 < < n ) ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
{
if ( ExpectedReason ! = 0x30400 | | g_ModuleVersion > = WINVER_WIN10 )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
else
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
}
/* NULL file handle still works */
RESET_CHECKRUNAPP_VARS ( ) ;
ret = call_ApphelpCheckRunApp ( NULL , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x50000 , 0 ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
for ( n = 0 ; n < 32 ; + + n )
{
ULONG ExpectedReason ;
RESET_CHECKRUNAPP_VARS ( ) ;
if ( ! ( kTestBits & ( 1 < < n ) ) )
continue ;
ExpectedReason = Reason = ( 1 < < n ) ;
ret = call_ApphelpCheckRunApp ( NULL , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
if ( ExpectedReason = = 2 )
ExpectedReason = 2 ;
else if ( ExpectedReason = = 0x100 )
ExpectedReason = 0x50000 ;
else if ( ExpectedReason = = 0x400 )
ExpectedReason = 0x30400 ;
else
ExpectedReason | = 0x50000 ;
ok_hex ( Reason , CHECKREASON ( ExpectedReason , ( 1 < < n ) ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
{
/* W10 does not use the flags anymore? */
if ( ExpectedReason ! = 0x30400 | | g_ModuleVersion > = WINVER_WIN10 )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
else
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
}
/* INVALID_HANDLE_VALUE file handle results in failure (according to flags!), but still results in AppCompatData */
RESET_CHECKRUNAPP_VARS ( ) ;
ret = call_ApphelpCheckRunApp ( INVALID_HANDLE_VALUE , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , 0 ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
for ( n = 0 ; n < 32 ; + + n )
{
ULONG ExpectedReason ;
if ( ! ( kTestBits & ( 1 < < n ) ) )
continue ;
RESET_CHECKRUNAPP_VARS ( ) ;
ExpectedReason = Reason = ( 1 < < n ) ;
ret = call_ApphelpCheckRunApp ( INVALID_HANDLE_VALUE , NULL , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
if ( ExpectedReason = = 0x100 )
ExpectedReason = 0 ;
ok_hex ( Reason , CHECKREASON ( ExpectedReason , ( 1 < < n ) ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
{
2017-06-11 13:09:43 +00:00
if ( ExpectedReason ! = 0x400 & & g_ModuleVersion < WINVER_WIN7 )
2017-06-10 20:31:58 +00:00
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
else
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
}
/* NULL filename crashes, showing this in the log before going down:
[ Err ] [ SdbpGetLongFileName ] Failed to get NT path name for " "
[ Err ] [ SdbpCreateSearchDBContext ] Unable to parse executable path for " " .
[ Err ] [ SdbGetMatchingExe ] Failed to create search DB context .
*/
RESET_CHECKRUNAPP_VARS ( ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , EmptyName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x30000 , 0 ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
/* 0 ExeType = don't care? */
RESET_CHECKRUNAPP_VARS ( ) ;
ExeType = 0 ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x50000 , 0 ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
for ( n = 0 ; n < 32 ; + + n )
{
ULONG ExpectedReason ;
if ( ! ( kTestBits & ( 1 < < n ) ) )
continue ;
RESET_CHECKRUNAPP_VARS ( ) ;
ExeType = 0 ;
ExpectedReason = Reason = ( 1 < < n ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
if ( ExpectedReason = = 2 )
ExpectedReason = 2 ;
else if ( ExpectedReason = = 0x100 )
ExpectedReason = 0x50000 ;
else if ( ExpectedReason = = 0x400 )
ExpectedReason = 0x30400 ;
else
ExpectedReason | = 0x50000 ;
ok_hex ( Reason , CHECKREASON ( ExpectedReason , ( 1 < < n ) ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
{
if ( ExpectedReason ! = 0x30400 | | g_ModuleVersion > = WINVER_WIN10 )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
else
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
}
RESET_CHECKRUNAPP_VARS ( ) ;
ExeType = IMAGE_FILE_MACHINE_POWERPCFP ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
ok_hex ( Reason , CHECKREASON ( 0x50000 , 0 ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
for ( n = 0 ; n < 32 ; + + n )
{
ULONG ExpectedReason ;
if ( ! ( kTestBits & ( 1 < < n ) ) )
continue ;
RESET_CHECKRUNAPP_VARS ( ) ;
ExeType = IMAGE_FILE_MACHINE_POWERPCFP ;
ExpectedReason = Reason = ( 1 < < n ) ;
ret = call_ApphelpCheckRunApp ( FileHandle , ApplicationName , Environment , ExeType , & Reason ,
& AppCompatData , & AppCompatDataSize , & SxsData , & SxsDataSize , & FusionFlags ) ;
CHECK_BASICS ( ) ;
if ( ExpectedReason = = 2 )
ExpectedReason = 2 ;
else if ( ExpectedReason = = 0x100 )
ExpectedReason = 0x50000 ;
else if ( ExpectedReason = = 0x400 )
ExpectedReason = 0x30400 ;
else
ExpectedReason | = 0x50000 ;
ok_hex ( Reason , CHECKREASON ( ExpectedReason , ( 1 < < n ) ) ) ;
if ( AppCompatData & & AppCompatDataSize = = sizeof ( SDBQUERYRESULT_VISTA ) )
{
if ( ExpectedReason ! = 0x30400 | | g_ModuleVersion > = WINVER_WIN10 )
expect_layeronly ( AppCompatData , " 256Color " , expect_flags ) ;
else
ok ( ! memcmp ( AppCompatData , & empty_result , sizeof ( empty_result ) ) , " Expected result to be empty \n " ) ;
}
}
if ( AppCompatData & & AppCompatData ! = & Query )
RtlFreeHeap ( RtlGetProcessHeap ( ) , 0 , AppCompatData ) ;
FreeEnvironmentStringsW ( Environment ) ;
DestroyEnvironmentBlock ( DuplicatedEnv ) ;
NtClose ( FileHandle ) ;
}
START_TEST ( env )
{
WCHAR szApphelp [ MAX_PATH ] ;
ShimData_QueryOffset QueryOffset ;
DWORD ShimDataType ;
NTSTATUS ExceptionStatus = STATUS_SUCCESS ;
2017-06-11 13:09:43 +00:00
//SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "127");
//SetEnvironmentVariable("SHIMENG_DEBUG_LEVEL", "127");
2017-06-10 20:31:58 +00:00
2017-06-11 13:09:43 +00:00
silence_debug_output ( ) ;
2017-06-10 20:31:58 +00:00
hdll = LoadLibraryA ( " apphelp.dll " ) ;
g_WinVersion = get_host_winver ( ) ;
g_ModuleVersion = get_module_version ( hdll ) ;
trace ( " Detected host: 0x%x, module: 0x%x \n " , g_WinVersion , g_ModuleVersion ) ;
GetModuleFileNameW ( hdll , szApphelp , _countof ( szApphelp ) ) ;
pSdbGetMatchingExe = ( void * ) GetProcAddress ( hdll , " SdbGetMatchingExe " ) ;
pSdbInitDatabase = ( void * ) GetProcAddress ( hdll , " SdbInitDatabase " ) ;
pSdbReleaseDatabase = ( void * ) GetProcAddress ( hdll , " SdbReleaseDatabase " ) ;
pSdbTagRefToTagID = ( void * ) GetProcAddress ( hdll , " SdbTagRefToTagID " ) ;
pSdbGetTagFromTagID = ( void * ) GetProcAddress ( hdll , " SdbGetTagFromTagID " ) ;
pSdbGetLayerTagRef = ( void * ) GetProcAddress ( hdll , " SdbGetLayerTagRef " ) ;
switch ( g_ModuleVersion )
{
case WINVER_WIN7 :
pApphelpCheckRunAppEx_w7 = ( void * ) GetProcAddress ( hdll , " ApphelpCheckRunAppEx " ) ;
break ;
case WINVER_WIN10 :
pApphelpCheckRunAppEx_w10 = ( void * ) GetProcAddress ( hdll , " ApphelpCheckRunAppEx " ) ;
break ;
default :
skip ( " Unknown apphelp.dll version %x, cannot determine which ApphelpCheckRunApp(Ex) function to use \n " , g_ModuleVersion ) ;
break ;
}
pSdbPackAppCompatData = ( void * ) GetProcAddress ( hdll , " SdbPackAppCompatData " ) ;
pSdbUnpackAppCompatData = ( void * ) GetProcAddress ( hdll , " SdbUnpackAppCompatData " ) ;
pSdbGetAppCompatDataSize = ( void * ) GetProcAddress ( hdll , " SdbGetAppCompatDataSize " ) ;
memset ( & QueryOffset , 0 , sizeof ( QueryOffset ) ) ;
QueryOffset . dwMagic_2k3 = QueryOffset . dwMagic_7_10 = QueryOffset . dwMagic_10_v2 = SHIMDATA_MAGIC ;
QueryOffset . dwSize_2k3 = 1 ;
QueryOffset . dwSize_7_10 = 2 ;
QueryOffset . dwSize_10_v2 = 3 ;
g_ShimDataSize = g_WinVersion < WINVER_WIN10 ? 4096 : 8192 ;
_SEH2_TRY
{
ShimDataType = pSdbGetAppCompatDataSize ( & QueryOffset ) ;
}
_SEH2_EXCEPT ( EXCEPTION_EXECUTE_HANDLER )
{
ExceptionStatus = _SEH2_GetExceptionCode ( ) ;
}
_SEH2_END ;
ok ( ExceptionStatus = = STATUS_SUCCESS , " Exception 0x%08x, expected 0x%08x \n " , ExceptionStatus , STATUS_SUCCESS ) ;
if ( ExceptionStatus ! = STATUS_SUCCESS )
{
skip ( " SdbGetAppCompatDataSize not functional \n " ) ;
return ;
}
2017-06-11 13:09:43 +00:00
/* New version of Win10.. */
2017-06-10 20:31:58 +00:00
if ( g_WinVersion = = WINVER_WIN10 & & ShimDataType = = 3 )
g_ShimDataSize = 4096 ;
if ( g_WinVersion = = g_ModuleVersion )
{
Test_layers ( szApphelp ) ;
Test_repeatlayer ( szApphelp ) ;
}
else
{
skip ( " Tests requiring process launch, reported OS version (0x%x) does not match apphelp version (0x%x) \n " , g_WinVersion , g_ModuleVersion ) ;
}
{
Test_GetMatchingExe ( ) ;
}
Test_ApphelpCheckRunApp ( szApphelp ) ;
if ( g_LayerDB )
pSdbReleaseDatabase ( g_LayerDB ) ;
}