Branch data Line data Source code
1 : : #ifndef LINUXMOCK_H
2 : : #define LINUXMOCK_H
3 : :
4 : : #ifndef _WIN32
5 : : #include <chrono>
6 : : #include <optional>
7 : : #include <cstdint>
8 : : #include <cstring>
9 : : #include <algorithm>
10 : : #include <map>
11 : : #include <vector>
12 : : #include <string>
13 : : #include <cstdarg>
14 : : #include "../../utils/StringUtils.h"
15 : :
16 : : // Dummy typedefs for Linux compatibility
17 : : using DWORD = uint32_t;
18 : : using HANDLE = void*;
19 : : using HWND = void*;
20 : : using BOOL = int;
21 : : using UINT = unsigned int;
22 : : using LONG = long;
23 : : using SHORT = short;
24 : : using VOID = void;
25 : : using PVOID = void*;
26 : : using UINT_PTR = unsigned long;
27 : : using LPARAM = long;
28 : : using WPARAM = unsigned long;
29 : : using LRESULT = long;
30 : : using HRESULT = long;
31 : : using WORD = uint16_t;
32 : : using BYTE = uint8_t;
33 : : using LONG_PTR = intptr_t;
34 : : using ULONG_PTR = uintptr_t;
35 : : using LPDWORD = uint32_t*;
36 : : using HMODULE = void*;
37 : : using HICON = void*;
38 : : using HRSRC = void*;
39 : : using LPVOID = void*;
40 : : using LPCSTR = const char*;
41 : :
42 : : typedef struct _GUID {
43 : : uint32_t Data1;
44 : : uint16_t Data2;
45 : : uint16_t Data3;
46 : : uint8_t Data4[8];
47 : : } GUID;
48 : :
49 : : #ifndef __cdecl
50 : : #define __cdecl
51 : : #endif
52 : :
53 : : #ifndef TRUE
54 : : #define TRUE 1
55 : : #endif
56 : :
57 : : #ifndef FALSE
58 : : #define FALSE 0
59 : : #endif
60 : :
61 : : #ifndef NULL
62 : : #define NULL nullptr
63 : : #endif
64 : :
65 : : #ifndef MAX_PATH
66 : : #define MAX_PATH 260
67 : : #endif
68 : :
69 : : #ifndef _TRUNCATE
70 : : #define _TRUNCATE ((size_t)-1)
71 : : #endif
72 : :
73 : : // Windows Constants for Mocking
74 : : #define INVALID_HANDLE_VALUE (reinterpret_cast<HANDLE>(static_cast<intptr_t>(-1))) // NOLINT(performance-no-int-to-ptr)
75 : : #define PAGE_READWRITE 0x04
76 : : #define FILE_MAP_ALL_ACCESS 0xF001F
77 : : #define FILE_MAP_READ 0x04
78 : : #define ERROR_ALREADY_EXISTS 183
79 : : #define WAIT_OBJECT_0 0
80 : : #define WAIT_FAILED 0xFFFFFFFF
81 : : #define INFINITE 0xFFFFFFFF
82 : : #define SYNCHRONIZE 0x00100000L
83 : : #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
84 : :
85 : : // Window Styles & Constants
86 : : #define WS_OVERLAPPEDWINDOW 0
87 : : #define WS_VISIBLE 0
88 : : #define GWL_EXSTYLE -20
89 : : #define WS_EX_TOPMOST 0x00000008L
90 : : #define HWND_TOPMOST (reinterpret_cast<HWND>(static_cast<intptr_t>(-1))) // NOLINT(performance-no-int-to-ptr)
91 : : #define HWND_NOTOPMOST (reinterpret_cast<HWND>(static_cast<intptr_t>(-2))) // NOLINT(performance-no-int-to-ptr)
92 : : #define SWP_NOMOVE 0x0002
93 : : #define SWP_NOSIZE 0x0001
94 : : #define SWP_FRAMECHANGED 0x0020
95 : :
96 : : // Resources
97 : : #define RT_GROUP_ICON (reinterpret_cast<LPCSTR>(static_cast<intptr_t>(14))) // NOLINT(performance-no-int-to-ptr)
98 : : #define LOAD_LIBRARY_AS_DATAFILE 0x00000002
99 : : #define MAKEINTRESOURCE(i) (reinterpret_cast<char*>(static_cast<intptr_t>(static_cast<WORD>(i)))) // NOLINT(performance-no-int-to-ptr)
100 : : #define MAKEINTRESOURCEA(i) (reinterpret_cast<char*>(static_cast<intptr_t>(static_cast<WORD>(i)))) // NOLINT(performance-no-int-to-ptr)
101 : :
102 : : // Memory Mapping Mock (Global Storage)
103 : : namespace MockSM {
104 : 27364 : inline std::map<std::string, std::vector<uint8_t>>& GetMaps() {
105 [ + + + - ]: 27364 : static std::map<std::string, std::vector<uint8_t>> maps;
106 : 27364 : return maps;
107 : : }
108 : 13358 : inline DWORD& LastError() {
109 : : static DWORD err = 0;
110 : 13358 : return err;
111 : : }
112 : 6692 : inline bool& FailNext() {
113 : : static bool fail = false;
114 : 6692 : return fail;
115 : : }
116 : 10 : inline DWORD& WaitResult() {
117 : : static DWORD res = 0; // WAIT_OBJECT_0
118 : 10 : return res;
119 : : }
120 : : }
121 : :
122 : : // Interlocked functions for Linux mocking
123 : 20379 : inline long InterlockedCompareExchange(long volatile* Destination, long Exchange, long Comparand) {
124 : 20379 : long old = *Destination;
125 [ + + ]: 20379 : if (old == Comparand) *Destination = Exchange;
126 : 20379 : return old;
127 : : }
128 : 4 : inline long InterlockedIncrement(long volatile* Addend) { return ++(*Addend); }
129 : 1 : inline long InterlockedDecrement(long volatile* Addend) { return --(*Addend); }
130 : 4374 : inline long InterlockedExchange(long volatile* Target, long Value) {
131 : 4374 : long old = *Target;
132 : 4374 : *Target = Value;
133 : 4374 : return old;
134 : : }
135 : :
136 : : // Memory and Event mocks
137 : 16000 : inline void YieldProcessor() {}
138 : 4 : inline DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) {
139 [ + + ]: 4 : if (MockSM::WaitResult() != 0) {
140 : 2 : DWORD res = MockSM::WaitResult();
141 : 2 : MockSM::WaitResult() = 0;
142 : 2 : return res;
143 : : }
144 : 2 : return WAIT_OBJECT_0;
145 : : }
146 : 3170 : inline BOOL SetEvent(HANDLE hEvent) { return TRUE; }
147 : 20027 : inline BOOL CloseHandle(HANDLE hObject) {
148 [ + + + + ]: 20027 : if (hObject != reinterpret_cast<HANDLE>(static_cast<intptr_t>(0)) &&
149 [ + - ]: 13349 : hObject != reinterpret_cast<HANDLE>(static_cast<intptr_t>(1)) &&
150 [ + + ]: 13349 : hObject != reinterpret_cast<HANDLE>(static_cast<intptr_t>(2)) &&
151 : : hObject != INVALID_HANDLE_VALUE) {
152 [ + - ]: 13348 : delete static_cast<std::string*>(hObject);
153 : : }
154 : 20027 : return TRUE;
155 : : }
156 : 6677 : inline DWORD GetLastError() { return MockSM::LastError(); }
157 : :
158 : : // Shared Memory Mocks
159 : 6686 : inline HANDLE CreateFileMappingA(HANDLE hFile, void* lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, const char* lpName) {
160 [ + + ]: 6686 : if (MockSM::FailNext()) {
161 : 3 : MockSM::FailNext() = false;
162 : 3 : return nullptr;
163 : : }
164 [ + + ]: 6683 : if (lpName == nullptr) return reinterpret_cast<HANDLE>(static_cast<intptr_t>(1));
165 [ + - ]: 6681 : std::string name(lpName);
166 : 6681 : auto& maps = MockSM::GetMaps();
167 [ + - + + ]: 6681 : if (maps.find(name) == maps.end()) {
168 [ + - + - ]: 4 : maps[name].resize(dwMaximumSizeLow);
169 : 4 : MockSM::LastError() = 0;
170 : : } else {
171 : 6677 : MockSM::LastError() = ERROR_ALREADY_EXISTS;
172 : : }
173 [ + - + - : 6681 : return reinterpret_cast<HANDLE>(new std::string(name));
- - ]
174 : 6681 : }
175 : :
176 : 6677 : inline HANDLE OpenFileMappingA(DWORD dwDesiredAccess, BOOL bInheritHandle, const char* lpName) {
177 [ + + ]: 6677 : if (lpName == nullptr) return nullptr;
178 [ + - ]: 6674 : std::string name(lpName);
179 : 6674 : auto& maps = MockSM::GetMaps();
180 [ + - + + ]: 6674 : if (maps.find(name) != maps.end()) {
181 [ + - + - : 6667 : return reinterpret_cast<HANDLE>(new std::string(name));
- - ]
182 : : }
183 : 7 : return nullptr;
184 : 6674 : }
185 : :
186 : 13345 : inline void* MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, size_t dwNumberOfBytesToMap) {
187 [ + + + + : 13345 : if (hFileMappingObject == reinterpret_cast<HANDLE>(static_cast<intptr_t>(1)) || hFileMappingObject == nullptr || hFileMappingObject == INVALID_HANDLE_VALUE) return nullptr;
+ + ]
188 : 13342 : std::string* name = static_cast<std::string*>(hFileMappingObject);
189 : 13342 : return MockSM::GetMaps()[*name].data();
190 : : }
191 : :
192 : 13351 : inline BOOL UnmapViewOfFile(const void* lpBaseAddress) { return TRUE; }
193 : 6676 : inline HANDLE CreateEventA(void* lpEventAttributes, BOOL bManualReset, BOOL bInitialState, const char* lpName) { return reinterpret_cast<HANDLE>(static_cast<intptr_t>(1)); }
194 : :
195 : : // Window mocks
196 : : namespace MockGUI {
197 : 11 : inline LONG_PTR& ExStyle() { static LONG_PTR style = 0; return style; }
198 : : }
199 : :
200 : 1 : inline HWND GetConsoleWindow() { return reinterpret_cast<HWND>(static_cast<intptr_t>(1)); }
201 : 6336 : inline BOOL IsWindow(HWND hWnd) {
202 [ + + + + ]: 6336 : return (hWnd == reinterpret_cast<HWND>(static_cast<intptr_t>(1)) || hWnd == reinterpret_cast<HWND>(static_cast<intptr_t>(2))); // Accept our mock handles
203 : : }
204 : 1 : inline HWND CreateWindowA(const char* lpClassName, const char* lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, void* hMenu, HMODULE hInstance, void* lpParam) {
205 : 1 : return reinterpret_cast<HWND>(static_cast<intptr_t>(2));
206 : : }
207 : 7 : inline LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) {
208 [ + + ]: 7 : if (nIndex == GWL_EXSTYLE) return MockGUI::ExStyle();
209 : 1 : return 0;
210 : : }
211 : 4 : inline BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags) {
212 [ + + ]: 4 : if (hWndInsertAfter == HWND_TOPMOST) MockGUI::ExStyle() |= WS_EX_TOPMOST;
213 [ + + ]: 4 : if (hWndInsertAfter == HWND_NOTOPMOST) MockGUI::ExStyle() &= ~WS_EX_TOPMOST;
214 : 4 : return TRUE;
215 : : }
216 : 1 : inline BOOL DestroyWindow(HWND hWnd) { return TRUE; }
217 : :
218 : : // Resource Mocks
219 : 2 : inline HMODULE GetModuleHandle(const char* lpModuleName) { return reinterpret_cast<HMODULE>(static_cast<intptr_t>(1)); }
220 : 1 : inline HICON LoadIcon(HMODULE hInstance, const char* lpIconName) { return reinterpret_cast<HICON>(static_cast<intptr_t>(1)); }
221 : 1 : inline DWORD GetModuleFileNameA(HMODULE hModule, char* lpFilename, DWORD nSize) {
222 : 1 : StringUtils::SafeCopy(lpFilename, nSize, "LMUFFB.exe");
223 : 1 : return (DWORD)strlen(lpFilename);
224 : : }
225 : 1 : inline HMODULE LoadLibraryExA(const char* lpLibFileName, HANDLE hFile, DWORD dwFlags) { return reinterpret_cast<HMODULE>(static_cast<intptr_t>(1)); }
226 : 1 : inline HRSRC FindResourceA(HMODULE hModule, const char* lpName, const char* lpType) { return reinterpret_cast<HRSRC>(static_cast<intptr_t>(1)); }
227 : 1 : inline BOOL FreeLibrary(HMODULE hLibModule) { return TRUE; }
228 : :
229 : : // Version Info Mocks
230 : 1 : inline DWORD GetFileVersionInfoSizeA(const char* lptstrFilename, LPDWORD lpdwHandle) {
231 [ + - ]: 1 : if (lpdwHandle) *lpdwHandle = 0;
232 : 1 : return 1024;
233 : : }
234 : 1 : inline BOOL GetFileVersionInfoA(const char* lptstrFilename, DWORD dwHandle, DWORD dwLen, void* lpData) {
235 : 1 : memset(lpData, 0, dwLen);
236 : 1 : return TRUE;
237 : : }
238 : 8 : inline BOOL VerQueryValueA(const void* pBlock, const char* lpSubBlock, void** lplpBuffer, UINT* puLen) {
239 : : static uint16_t translation[2] = { 0x0409, 0x04B0 }; // English (US), Unicode
240 [ + + ]: 8 : if (strstr(lpSubBlock, "Translation")) {
241 : 2 : *lplpBuffer = &translation;
242 [ + - ]: 2 : if (puLen) *puLen = sizeof(translation);
243 : 2 : return TRUE;
244 : : }
245 [ + + ]: 6 : if (strstr(lpSubBlock, "CompanyName")) {
246 : 2 : *lplpBuffer = (void*)"lmuFFB";
247 [ + - ]: 2 : if (puLen) *puLen = 7;
248 : 2 : return TRUE;
249 : : }
250 [ + + ]: 4 : if (strstr(lpSubBlock, "ProductVersion")) {
251 : 2 : *lplpBuffer = (void*)LMUFFB_VERSION;
252 [ + - ]: 2 : if (puLen) *puLen = (UINT)strlen(LMUFFB_VERSION) + 1;
253 : 2 : return TRUE;
254 : : }
255 : 2 : return FALSE;
256 : : }
257 : :
258 : : // D3D11 & DXGI Mocks for Issue #189
259 : : typedef enum D3D_DRIVER_TYPE { D3D_DRIVER_TYPE_HARDWARE = 0 } D3D_DRIVER_TYPE;
260 : : typedef enum D3D_FEATURE_LEVEL { D3D_FEATURE_LEVEL_10_0 = 0x1000, D3D_FEATURE_LEVEL_11_0 = 0xb000 } D3D_FEATURE_LEVEL;
261 : : #define D3D11_SDK_VERSION (7)
262 : :
263 : : typedef struct DXGI_SAMPLE_DESC { UINT Count; UINT Quality; } DXGI_SAMPLE_DESC;
264 : : typedef enum DXGI_FORMAT { DXGI_FORMAT_R8G8B8A8_UNORM = 28, DXGI_FORMAT_UNKNOWN = 0 } DXGI_FORMAT;
265 : : typedef enum DXGI_USAGE { DXGI_USAGE_RENDER_TARGET_OUTPUT = 1 << 4 } DXGI_USAGE;
266 : : typedef enum DXGI_SWAP_EFFECT { DXGI_SWAP_EFFECT_DISCARD = 0, DXGI_SWAP_EFFECT_FLIP_DISCARD = 4 } DXGI_SWAP_EFFECT;
267 : : typedef enum DXGI_SWAP_CHAIN_FLAG { DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH = 2 } DXGI_SWAP_CHAIN_FLAG;
268 : : typedef enum DXGI_SCALING { DXGI_SCALING_STRETCH = 0 } DXGI_SCALING;
269 : : typedef enum DXGI_ALPHA_MODE { DXGI_ALPHA_MODE_UNSPECIFIED = 0 } DXGI_ALPHA_MODE;
270 : :
271 : : typedef struct DXGI_SWAP_CHAIN_DESC1 {
272 : : UINT Width; UINT Height; DXGI_FORMAT Format; BOOL Stereo; DXGI_SAMPLE_DESC SampleDesc;
273 : : DXGI_USAGE BufferUsage; UINT BufferCount; DXGI_SCALING Scaling; DXGI_SWAP_EFFECT SwapEffect;
274 : : DXGI_ALPHA_MODE AlphaMode; UINT Flags;
275 : : } DXGI_SWAP_CHAIN_DESC1;
276 : :
277 : : typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC {
278 : : struct { UINT Numerator; UINT Denominator; } RefreshRate;
279 : : int ScanlineOrdering; int Scaling; BOOL Windowed;
280 : : } DXGI_SWAP_CHAIN_FULLSCREEN_DESC;
281 : :
282 : : // Mock interfaces
283 : : struct IUnknown {
284 : : virtual HRESULT QueryInterface(const GUID& riid, void** ppvObject) = 0;
285 : : virtual ULONG_PTR Release() = 0;
286 : : };
287 : :
288 : : struct IDXGIObject : public IUnknown {};
289 : : struct IDXGIDevice : public IDXGIObject {
290 : : virtual HRESULT GetAdapter(struct IDXGIAdapter** ppAdapter) = 0;
291 : : };
292 : : struct IDXGIAdapter : public IDXGIObject {
293 : : virtual HRESULT GetParent(const GUID& riid, void** ppParent) = 0;
294 : : };
295 : : struct IDXGIFactory2 : public IDXGIObject {
296 : : virtual HRESULT CreateSwapChainForHwnd(IUnknown* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, struct IDXGIOutput* pRestrictToOutput, struct IDXGISwapChain1** ppSwapChain) = 0;
297 : : };
298 : :
299 : : // Concrete mock for testing
300 : : struct MockDXGIFactory2 : public IDXGIFactory2 {
301 : 1 : HRESULT QueryInterface(const GUID& riid, void** ppvObject) override { return -1; }
302 : 1 : ULONG_PTR Release() override { return 0; }
303 : 3 : HRESULT CreateSwapChainForHwnd(IUnknown* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, struct IDXGIOutput* pRestrictToOutput, struct IDXGISwapChain1** ppSwapChain) override {
304 [ + + ]: 3 : if (pDesc) {
305 : : extern DXGI_SWAP_CHAIN_DESC1 g_captured_swap_chain_desc;
306 : 2 : g_captured_swap_chain_desc = *pDesc;
307 : : }
308 : 3 : return 0; // S_OK
309 : : }
310 : : };
311 : : struct IDXGISwapChain : public IDXGIObject {
312 : : virtual HRESULT GetBuffer(UINT Buffer, const GUID& riid, void** ppSurface) = 0;
313 : : virtual HRESULT Present(UINT SyncInterval, UINT Flags) = 0;
314 : : virtual HRESULT ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) = 0;
315 : : };
316 : : struct IDXGISwapChain1 : public IDXGISwapChain {};
317 : :
318 : : struct ID3D11DeviceChild : public IUnknown {};
319 : : struct ID3D11DeviceContext : public ID3D11DeviceChild {
320 : : virtual void OMSetRenderTargets(UINT NumViews, struct ID3D11RenderTargetView* const* ppRenderTargetViews, struct ID3D11DepthStencilView* pDepthStencilView) = 0;
321 : : virtual void ClearRenderTargetView(struct ID3D11RenderTargetView* pRenderTargetView, const float ColorRGBA[4]) = 0;
322 : : };
323 : : struct ID3D11Device : public IUnknown {
324 : : virtual HRESULT CreateRenderTargetView(struct ID3D11Resource* pResource, const struct D3D11_RENDER_TARGET_VIEW_DESC* pDesc, struct ID3D11RenderTargetView** ppRTView) = 0;
325 : : };
326 : :
327 : : #define IID_PPV_ARGS(ppType) GUID(), (void**)(ppType)
328 : :
329 : : #endif // _WIN32
330 : :
331 : : #endif // LINUXMOCK_H
|