1 /*
2  * PROJECT:     ReactOS 'Layers' Shim library
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     ForceDxSetupSuccess shim
5  * COPYRIGHT:   Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #define WIN32_NO_STATUS
9 #include <windef.h>
10 #include <winbase.h>
11 #include <shimlib.h>
12 #include "ntndk.h"
13 
14 typedef HMODULE(WINAPI* LOADLIBRARYAPROC)(LPCSTR lpLibFileName);
15 typedef HMODULE(WINAPI* LOADLIBRARYWPROC)(LPCWSTR lpLibFileName);
16 typedef HMODULE(WINAPI* LOADLIBRARYEXAPROC)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
17 typedef HMODULE(WINAPI* LOADLIBRARYEXWPROC)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
18 typedef FARPROC(WINAPI* GETPROCADDRESSPROC)(HMODULE hModule, LPCSTR lpProcName);
19 typedef BOOL   (WINAPI* FREELIBRARYPROC)(HINSTANCE hLibModule);
20 
21 
22 #define SHIM_NS         ForceDXSetupSuccess
23 #include <setup_shim.inl>
24 
25 
26 #define DSETUPERR_SUCCESS 0
27 
28 INT_PTR WINAPI DirectXSetup(HWND hWnd, LPSTR lpszRootPath, DWORD dwFlags)
29 {
30     SHIM_MSG("Returning DSETUPERR_SUCCESS\n");
31     return DSETUPERR_SUCCESS;
32 }
33 
34 INT_PTR WINAPI DirectXSetupA(HWND hWnd, LPSTR lpszRootPath, DWORD dwFlags)
35 {
36     SHIM_MSG("Returning DSETUPERR_SUCCESS\n");
37     return DSETUPERR_SUCCESS;
38 }
39 
40 INT_PTR WINAPI DirectXSetupW(HWND hWnd, LPWSTR lpszRootPath, DWORD dwFlags)
41 {
42     SHIM_MSG("Returning DSETUPERR_SUCCESS\n");
43     return DSETUPERR_SUCCESS;
44 }
45 
46 INT_PTR WINAPI DirectXSetupGetVersion(DWORD *lpdwVersion, DWORD *lpdwMinorVersion)
47 {
48     if (lpdwVersion)
49         *lpdwVersion = MAKELONG(7, 4);     // DirectX 7.0
50     if (lpdwMinorVersion)
51         *lpdwMinorVersion = MAKELONG(1792, 0);
52 
53     return TRUE;
54 }
55 
56 static BOOL IsDxSetupW(PCUNICODE_STRING LibraryPath)
57 {
58     static const UNICODE_STRING DxSetupDlls[] = {
59         RTL_CONSTANT_STRING(L"dsetup.dll"),
60         RTL_CONSTANT_STRING(L"dsetup32.dll"),
61         RTL_CONSTANT_STRING(L"dsetup"),
62         RTL_CONSTANT_STRING(L"dsetup32"),
63     };
64     static const UNICODE_STRING PathDividerFind = RTL_CONSTANT_STRING(L"\\/");
65     UNICODE_STRING LibraryName;
66     USHORT PathDivider;
67     DWORD n;
68 
69     if (!NT_SUCCESS(RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, LibraryPath, &PathDividerFind, &PathDivider)))
70         PathDivider = 0;
71 
72     if (PathDivider)
73         PathDivider += sizeof(WCHAR);
74 
75     LibraryName.Buffer = LibraryPath->Buffer + PathDivider / sizeof(WCHAR);
76     LibraryName.Length = LibraryPath->Length - PathDivider;
77     LibraryName.MaximumLength = LibraryPath->MaximumLength - PathDivider;
78 
79     for (n = 0; n < ARRAYSIZE(DxSetupDlls); ++n)
80     {
81         if (RtlEqualUnicodeString(&LibraryName, DxSetupDlls + n, TRUE))
82         {
83             SHIM_MSG("Found %wZ\n", DxSetupDlls + n);
84             return TRUE;
85         }
86     }
87     return FALSE;
88 }
89 
90 static BOOL IsDxSetupA(PCANSI_STRING LibraryPath)
91 {
92     BOOL bIsDxSetup;
93     UNICODE_STRING LibraryPathW;
94 
95     if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&LibraryPathW, LibraryPath, TRUE)))
96     {
97         bIsDxSetup = IsDxSetupW(&LibraryPathW);
98         RtlFreeUnicodeString(&LibraryPathW);
99         return bIsDxSetup;
100     }
101     return FALSE;
102 }
103 
104 HMODULE WINAPI SHIM_OBJ_NAME(APIHook_LoadLibraryA)(LPCSTR lpLibFileName)
105 {
106     ANSI_STRING Library;
107 
108     RtlInitAnsiString(&Library, lpLibFileName);
109     if (IsDxSetupA(&Library))
110         return ShimLib_Instance();
111 
112     return CALL_SHIM(0, LOADLIBRARYAPROC)(lpLibFileName);
113 }
114 
115 HMODULE WINAPI SHIM_OBJ_NAME(APIHook_LoadLibraryW)(LPCWSTR lpLibFileName)
116 {
117     UNICODE_STRING Library;
118 
119     RtlInitUnicodeString(&Library, lpLibFileName);
120     if (IsDxSetupW(&Library))
121         return ShimLib_Instance();
122 
123     return CALL_SHIM(1, LOADLIBRARYWPROC)(lpLibFileName);
124 }
125 
126 HMODULE WINAPI SHIM_OBJ_NAME(APIHook_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
127 {
128     ANSI_STRING Library;
129 
130     RtlInitAnsiString(&Library, lpLibFileName);
131     if (IsDxSetupA(&Library))
132         return ShimLib_Instance();
133 
134     return CALL_SHIM(2, LOADLIBRARYEXAPROC)(lpLibFileName, hFile, dwFlags);
135 }
136 
137 HMODULE WINAPI SHIM_OBJ_NAME(APIHook_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
138 {
139     UNICODE_STRING Library;
140 
141     RtlInitUnicodeString(&Library, lpLibFileName);
142     if (IsDxSetupW(&Library))
143         return ShimLib_Instance();
144 
145     return CALL_SHIM(3, LOADLIBRARYEXWPROC)(lpLibFileName, hFile, dwFlags);
146 }
147 
148 FARPROC WINAPI SHIM_OBJ_NAME(APIHook_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName)
149 {
150     static const STRING DxSetupFunctions[] = {
151         RTL_CONSTANT_STRING("DirectXSetup"),
152         RTL_CONSTANT_STRING("DirectXSetupA"),
153         RTL_CONSTANT_STRING("DirectXSetupW"),
154         RTL_CONSTANT_STRING("DirectXSetupGetVersion"),
155     };
156     static const FARPROC DxSetupRedirections[] = {
157         DirectXSetup,
158         DirectXSetupA,
159         DirectXSetupW,
160         DirectXSetupGetVersion,
161     };
162     DWORD n;
163 
164     if (hModule == ShimLib_Instance() && ((ULONG_PTR)lpProcName > MAXUSHORT))
165     {
166         STRING ProcName;
167         RtlInitAnsiString(&ProcName, lpProcName);
168         for (n = 0; n < ARRAYSIZE(DxSetupFunctions); ++n)
169         {
170             if (RtlEqualString(&ProcName, DxSetupFunctions + n, TRUE))
171             {
172                 SHIM_MSG("Intercepted %Z\n", DxSetupFunctions + n);
173                 return DxSetupRedirections[n];
174             }
175         }
176     }
177     return CALL_SHIM(4, GETPROCADDRESSPROC)(hModule, lpProcName);
178 }
179 
180 BOOL WINAPI SHIM_OBJ_NAME(APIHook_FreeLibrary)(HINSTANCE hLibModule)
181 {
182     if (hLibModule == ShimLib_Instance())
183     {
184         SHIM_MSG("Intercepted\n");
185         return TRUE;
186     }
187 
188     return CALL_SHIM(5, FREELIBRARYPROC)(hLibModule);
189 }
190 
191 
192 #define SHIM_NUM_HOOKS  6
193 #define SHIM_SETUP_HOOKS \
194     SHIM_HOOK(0, "KERNEL32.DLL", "LoadLibraryA", SHIM_OBJ_NAME(APIHook_LoadLibraryA)) \
195     SHIM_HOOK(1, "KERNEL32.DLL", "LoadLibraryW", SHIM_OBJ_NAME(APIHook_LoadLibraryW)) \
196     SHIM_HOOK(2, "KERNEL32.DLL", "LoadLibraryExA", SHIM_OBJ_NAME(APIHook_LoadLibraryExA)) \
197     SHIM_HOOK(3, "KERNEL32.DLL", "LoadLibraryExW", SHIM_OBJ_NAME(APIHook_LoadLibraryExW)) \
198     SHIM_HOOK(4, "KERNEL32.DLL", "GetProcAddress", SHIM_OBJ_NAME(APIHook_GetProcAddress)) \
199     SHIM_HOOK(5, "KERNEL32.DLL", "FreeLibrary", SHIM_OBJ_NAME(APIHook_FreeLibrary))
200 
201 #include <implement_shim.inl>
202