1 /*
2  * PROJECT:     appshim_apitest
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Tests for ForceDxSetupSuccess shim
5  * COPYRIGHT:   Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include <ntstatus.h>
9 #define WIN32_NO_STATUS
10 #include <windows.h>
11 #include "wine/test.h"
12 
13 #include "appshim_apitest.h"
14 
15 static HMODULE g_hShimDll;
16 static HMODULE g_hSentinelModule = (HMODULE)&g_hShimDll;  /* Not a valid hmodule, so a nice sentinel */
17 static tGETHOOKAPIS pGetHookAPIs;
18 
19 static INT (WINAPI *DirectXSetupGetVersion)(DWORD *lpdwVersion, DWORD *lpdwMinorVersion);
20 
21 
22 typedef HMODULE(WINAPI* LOADLIBRARYAPROC)(PCSTR);
23 typedef HMODULE(WINAPI* LOADLIBRARYWPROC)(PCWSTR);
24 typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HMODULE, PCSTR);
25 typedef BOOL(WINAPI* FREELIBRARYPROC)(HMODULE);
26 
27 
my_LoadLibraryA(PCSTR Name)28 static HMODULE WINAPI my_LoadLibraryA(PCSTR Name)
29 {
30     return g_hSentinelModule;
31 }
32 
test_LoadLibraryA(PHOOKAPI hook)33 static void test_LoadLibraryA(PHOOKAPI hook)
34 {
35     LOADLIBRARYAPROC proc;
36 
37     ok_str(hook->LibraryName, "KERNEL32.DLL");
38     hook->OriginalFunction = my_LoadLibraryA;
39     proc = hook->ReplacementFunction;
40 
41     /* Original function is not called */
42     ok_ptr(proc("dsetup"), g_hShimDll);
43     ok_ptr(proc("dsetup.dll"), g_hShimDll);
44     ok_ptr(proc("DSETUP.DLL"), g_hShimDll);
45     ok_ptr(proc("DSeTuP.DlL"), g_hShimDll);
46 
47     ok_ptr(proc("dsetup32"), g_hShimDll);
48     ok_ptr(proc("dsetup32.dll"), g_hShimDll);
49     ok_ptr(proc("DSETUP32.DLL"), g_hShimDll);
50     ok_ptr(proc("DSeTuP32.DlL"), g_hShimDll);
51 
52     ok_ptr(proc("c:\\bogus/dsetup"), g_hShimDll);
53     ok_ptr(proc("c:\\bogus\\dsetup.dll"), g_hShimDll);
54     ok_ptr(proc("c:/bogus/DSETUP.DLL"), g_hShimDll);
55     ok_ptr(proc("c:\\bogus\\DSeTuP.DlL"), g_hShimDll);
56 
57     ok_ptr(proc("////////////////////dsetup32"), g_hShimDll);
58     ok_ptr(proc("\\\\\\\\\\\\\\dsetup32.dll"), g_hShimDll);
59     ok_ptr(proc("xxxxxxxxxxx\\DSETUP32.DLL"), g_hShimDll);
60     ok_ptr(proc("xxxxxxxxxxx//DSeTuP32.DlL"), g_hShimDll);
61 
62     /* Original function is called */
63     ok_ptr(proc(NULL), g_hSentinelModule);
64     ok_ptr(proc("dsetup\\something"), g_hSentinelModule);
65     ok_ptr(proc("dsetup.dl"), g_hSentinelModule);
66     ok_ptr(proc("c:\\DSETUP.DLL."), g_hSentinelModule);
67     ok_ptr(proc("DSeTuP.D"), g_hSentinelModule);
68 }
69 
my_LoadLibraryW(PCWSTR Name)70 static HMODULE WINAPI my_LoadLibraryW(PCWSTR Name)
71 {
72     return g_hSentinelModule;
73 }
74 
test_LoadLibraryW(PHOOKAPI hook)75 static void test_LoadLibraryW(PHOOKAPI hook)
76 {
77     LOADLIBRARYWPROC proc;
78 
79     ok_str(hook->LibraryName, "KERNEL32.DLL");
80 
81     hook->OriginalFunction = my_LoadLibraryW;
82     proc = hook->ReplacementFunction;
83 
84     /* Original function is not called */
85     ok_ptr(proc(L"dsetup"), g_hShimDll);
86     ok_ptr(proc(L"dsetup.dll"), g_hShimDll);
87     ok_ptr(proc(L"DSETUP.DLL"), g_hShimDll);
88     ok_ptr(proc(L"DSeTuP.DlL"), g_hShimDll);
89 
90     ok_ptr(proc(L"dsetup32"), g_hShimDll);
91     ok_ptr(proc(L"dsetup32.dll"), g_hShimDll);
92     ok_ptr(proc(L"DSETUP32.DLL"), g_hShimDll);
93     ok_ptr(proc(L"DSeTuP32.DlL"), g_hShimDll);
94 
95     ok_ptr(proc(L"c:\\bogus/dsetup"), g_hShimDll);
96     ok_ptr(proc(L"c:\\bogus\\dsetup.dll"), g_hShimDll);
97     ok_ptr(proc(L"c:/bogus/DSETUP.DLL"), g_hShimDll);
98     ok_ptr(proc(L"c:\\bogus\\DSeTuP.DlL"), g_hShimDll);
99 
100     ok_ptr(proc(L"////////////////////dsetup32"), g_hShimDll);
101     ok_ptr(proc(L"\\\\\\\\\\\\\\dsetup32.dll"), g_hShimDll);
102     ok_ptr(proc(L"xxxxxxxxxxx\\DSETUP32.DLL"), g_hShimDll);
103     ok_ptr(proc(L"xxxxxxxxxxx//DSeTuP32.DlL"), g_hShimDll);
104 
105     /* Original function is called */
106     ok_ptr(proc(NULL), g_hSentinelModule);
107     ok_ptr(proc(L"dsetup\\something"), g_hSentinelModule);
108     ok_ptr(proc(L"dsetup.dl"), g_hSentinelModule);
109     ok_ptr(proc(L"c:\\DSETUP.DLL."), g_hSentinelModule);
110     ok_ptr(proc(L"DSeTuP.D"), g_hSentinelModule);
111 }
112 
test_GetProcAddress(PHOOKAPI hook)113 static void test_GetProcAddress(PHOOKAPI hook)
114 {
115     GETPROCADDRESSPROC proc;
116     DWORD n;
117     PCSTR Functions[] = {
118         "DirectXSetup",
119         "DirectXSetupA",
120         "DirectXSetupW",
121         "DirectXSetupGetVersion",
122         /* And not case sensitive? */
123         "directxsetup",
124         "DIRECTXSETUPA",
125         "DiReCtXsEtUpW",
126         NULL
127     };
128     HMODULE mod = GetModuleHandleA("kernel32.dll");
129 
130     ok_str(hook->LibraryName, "KERNEL32.DLL");
131     hook->OriginalFunction = GetProcAddress;    /* Some versions seem to call GetProcAddress regardless of what is put here.. */
132     proc = hook->ReplacementFunction;
133 
134     ok_ptr(proc(mod, "CreateFileA"), GetProcAddress(mod, "CreateFileA"));
135     ok_ptr(proc(g_hShimDll, "CreateFileA"), NULL);
136 
137     for (n = 0; Functions[n]; ++n)
138     {
139         FARPROC fn = proc(g_hShimDll, Functions[n]);
140         ok(fn != NULL, "Got NULL for %s\n", Functions[n]);
141         /* And yet, no export! */
142         ok_ptr(GetProcAddress(g_hShimDll, Functions[n]), NULL);
143     }
144 
145     /* Not every function is shimmed */
146     ok_ptr(proc(g_hShimDll, "DirectXSetupShowEULA"), NULL);
147     /* Retrieve a pointer for our next test */
148     DirectXSetupGetVersion = (PVOID)proc(g_hShimDll, "DirectXSetupGetVersion");
149 }
150 
151 static int g_NumShim = 0;
152 static int g_NumSentinel = 0;
153 static int g_NumCalls = 0;
my_FreeLibrary(HMODULE module)154 BOOL WINAPI my_FreeLibrary(HMODULE module)
155 {
156     if (module == g_hSentinelModule)
157         ++g_NumSentinel;
158     else if (module == g_hShimDll)
159         ++g_NumShim;
160     ++g_NumCalls;
161     return 33;
162 }
163 
test_FreeLibrary(PHOOKAPI hook)164 static void test_FreeLibrary(PHOOKAPI hook)
165 {
166     FREELIBRARYPROC proc;
167 
168     ok_str(hook->LibraryName, "KERNEL32.DLL");
169     hook->OriginalFunction = my_FreeLibrary;
170     proc = hook->ReplacementFunction;
171 
172     ok_int(proc(NULL), 33);
173     ok_int(proc(NULL), 33);
174     ok_int(proc(g_hSentinelModule), 33);
175     ok_int(proc(g_hSentinelModule), 33);
176     ok_int(proc(g_hShimDll), TRUE);
177     ok_int(proc(g_hShimDll), TRUE);
178 
179     ok_int(g_NumShim, 0);
180     ok_int(g_NumSentinel, 2);
181     ok_int(g_NumCalls, 4);
182 }
183 
184 
START_TEST(forcedxsetup)185 START_TEST(forcedxsetup)
186 {
187     DWORD num_shims = 0, n;
188     PHOOKAPI hook;
189 
190     if (!LoadShimDLL(L"aclayers.dll", &g_hShimDll, &pGetHookAPIs))
191         return;
192 
193     hook = pGetHookAPIs("", L"ForceDxSetupSuccess", &num_shims);
194 
195     ok(hook != NULL, "Expected hook to be a valid pointer\n");
196     ok(num_shims == 6, "Expected num_shims to be 6, was: %u\n", num_shims);
197 
198     if (!hook || !num_shims)
199         return;
200 
201     for (n = 0; n < num_shims; ++n)
202     {
203         if (!_stricmp(hook[n].FunctionName, "LoadLibraryA"))
204             test_LoadLibraryA(hook + n);
205         else if (!_stricmp(hook[n].FunctionName, "LoadLibraryW"))
206             test_LoadLibraryW(hook + n);
207         else if (!_stricmp(hook[n].FunctionName, "GetProcAddress"))
208             test_GetProcAddress(hook + n);
209         else if (!_stricmp(hook[n].FunctionName, "FreeLibrary"))
210             test_FreeLibrary(hook + n);
211     }
212 
213     ok(DirectXSetupGetVersion != NULL, "No DirectXSetupGetVersion\n");
214     if (DirectXSetupGetVersion)
215     {
216         DWORD dwVersion = 0xdeadbeef;
217         DWORD dwMinorVersion = 0xbeefdead;
218         INT Res = DirectXSetupGetVersion(&dwVersion, &dwMinorVersion);
219         ok_int(Res, 1);
220         ok_hex(dwVersion, MAKELONG(7, 4));     // DirectX 7.0
221         ok_hex(dwMinorVersion, MAKELONG(1792, 0));
222 
223         Res = DirectXSetupGetVersion(NULL, NULL);
224         ok_int(Res, 1);
225     }
226 }
227