Reactos
1/*
2 * PROJECT: ReactOS Cicero
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Cicero base
5 * COPYRIGHT: Copyright 2023-2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include "precomp.h"
9#include "cicbase.h"
10#include <shlwapi.h>
11#include <stdlib.h>
12#include <string.h>
13#include <tchar.h>
14#include <strsafe.h>
15
16void* operator new(size_t size, const CicNoThrow&) noexcept
17{
18 return cicMemAllocClear(size);
19}
20void* operator new[](size_t size, const CicNoThrow&) noexcept
21{
22 return cicMemAllocClear(size);
23}
24void operator delete(void* ptr) noexcept
25{
26 cicMemFree(ptr);
27}
28void operator delete[](void* ptr) noexcept
29{
30 cicMemFree(ptr);
31}
32void operator delete(void* ptr, size_t size) noexcept
33{
34 cicMemFree(ptr);
35}
36void operator delete[](void* ptr, size_t size) noexcept
37{
38 cicMemFree(ptr);
39}
40
41LPVOID cicMemReCalloc(LPVOID mem, SIZE_T num, SIZE_T size) noexcept
42{
43 SIZE_T old_size, new_size = num * size;
44 LPVOID ret;
45
46 if (!mem)
47 return cicMemAllocClear(new_size);
48
49 old_size = LocalSize(mem);
50 ret = cicMemReAlloc(mem, new_size);
51 if (!ret)
52 return NULL;
53
54 if (new_size > old_size)
55 ZeroMemory((PBYTE)ret + old_size, new_size - old_size);
56
57 return ret;
58}
59
60// FIXME
61typedef enum _PROCESSINFOCLASS
62{
63 ProcessBasicInformation = 0,
64 ProcessDebugPort = 7,
65 ProcessWow64Information = 26,
66 ProcessImageFileName = 27,
67 ProcessBreakOnTermination = 29
68} PROCESSINFOCLASS;
69
70// FIXME
71typedef LONG NTSTATUS;
72
73/* ntdll!NtQueryInformationProcess */
74typedef NTSTATUS (WINAPI *FN_NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
75
76EXTERN_C
77BOOL cicIsWow64(VOID)
78{
79 static FN_NtQueryInformationProcess s_fnNtQueryInformationProcess = NULL;
80 ULONG_PTR Value;
81
82 if (!s_fnNtQueryInformationProcess)
83 {
84 HMODULE hNTDLL = cicGetSystemModuleHandle(TEXT("ntdll.dll"), FALSE);
85 if (!hNTDLL)
86 return FALSE;
87
88 s_fnNtQueryInformationProcess =
89 (FN_NtQueryInformationProcess)GetProcAddress(hNTDLL, "NtQueryInformationProcess");
90 if (!s_fnNtQueryInformationProcess)
91 return FALSE;
92 }
93
94 Value = 0;
95 s_fnNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information,
96 &Value, sizeof(Value), NULL);
97 return !!Value;
98}
99
100EXTERN_C
101void cicGetOSInfo(LPUINT puACP, LPDWORD pdwOSInfo)
102{
103 *pdwOSInfo = 0;
104
105 /* Check OS version info */
106 OSVERSIONINFO VerInfo;
107 VerInfo.dwOSVersionInfoSize = sizeof(VerInfo);
108 GetVersionEx(&VerInfo);
109 if (VerInfo.dwPlatformId == DLLVER_PLATFORM_NT)
110 {
111 *pdwOSInfo |= CIC_OSINFO_NT;
112 if (VerInfo.dwMajorVersion >= 5)
113 {
114 *pdwOSInfo |= CIC_OSINFO_2KPLUS;
115 if (VerInfo.dwMinorVersion > 0)
116 *pdwOSInfo |= CIC_OSINFO_XPPLUS;
117 }
118 }
119 else
120 {
121 if (VerInfo.dwMinorVersion >= 10)
122 *pdwOSInfo |= CIC_OSINFO_98PLUS;
123 else
124 *pdwOSInfo |= CIC_OSINFO_95;
125 }
126
127 /* Check codepage */
128 *puACP = GetACP();
129 switch (*puACP)
130 {
131 case 932: /* Japanese (Japan) */
132 case 936: /* Chinese (PRC, Singapore) */
133 case 949: /* Korean (Korea) */
134 case 950: /* Chinese (Taiwan, Hong Kong) */
135 *pdwOSInfo |= CIC_OSINFO_CJK;
136 break;
137 }
138
139 if (GetSystemMetrics(SM_IMMENABLED))
140 *pdwOSInfo |= CIC_OSINFO_IMM;
141
142 if (GetSystemMetrics(SM_DBCSENABLED))
143 *pdwOSInfo |= CIC_OSINFO_DBCS;
144}
145
146// Get an instance handle that is already loaded
147EXTERN_C
148HINSTANCE
149cicGetSystemModuleHandle(
150 _In_ LPCTSTR pszFileName,
151 _In_ BOOL bSysWinDir)
152{
153 CicSystemModulePath ModPath;
154 if (!ModPath.Init(pszFileName, bSysWinDir))
155 return NULL;
156 return GetModuleHandle(ModPath.m_szPath);
157}
158
159// Load a system library
160EXTERN_C
161HINSTANCE
162cicLoadSystemLibrary(
163 _In_ LPCTSTR pszFileName,
164 _In_ BOOL bSysWinDir)
165{
166 CicSystemModulePath ModPath;
167 if (!ModPath.Init(pszFileName, bSysWinDir))
168 return NULL;
169 return ::LoadLibrary(ModPath.m_szPath);
170}
171
172BOOL
173CicSystemModulePath::Init(
174 _In_ LPCTSTR pszFileName,
175 _In_ BOOL bSysWinDir)
176{
177 SIZE_T cchPath;
178 if (bSysWinDir)
179 {
180 // Usually C:\Windows or C:\ReactOS
181 cchPath = ::GetSystemWindowsDirectory(m_szPath, _countof(m_szPath));
182 }
183 else
184 {
185 // Usually C:\Windows\system32 or C:\ReactOS\system32
186 cchPath = ::GetSystemDirectory(m_szPath, _countof(m_szPath));
187 }
188
189 m_szPath[_countof(m_szPath) - 1] = TEXT('\0'); // Avoid buffer overrun
190
191 if ((cchPath == 0) || (cchPath > _countof(m_szPath) - 2))
192 goto Failure;
193
194 // Add backslash if necessary
195 if ((cchPath > 0) && (m_szPath[cchPath - 1] != TEXT('\\')))
196 {
197 m_szPath[cchPath + 0] = TEXT('\\');
198 m_szPath[cchPath + 1] = TEXT('\0');
199 }
200
201 // Append pszFileName
202 if (FAILED(StringCchCat(m_szPath, _countof(m_szPath), pszFileName)))
203 goto Failure;
204
205 m_cchPath = _tcslen(m_szPath);
206 return TRUE;
207
208Failure:
209 m_szPath[0] = UNICODE_NULL;
210 m_cchPath = 0;
211 return FALSE;
212}
213
214static FN_CoCreateInstance
215_cicGetSetUserCoCreateInstance(FN_CoCreateInstance fnUserCoCreateInstance)
216{
217 static FN_CoCreateInstance s_fn = NULL;
218 if (fnUserCoCreateInstance)
219 s_fn = fnUserCoCreateInstance;
220 return s_fn;
221}
222
223EXTERN_C
224HRESULT
225cicRealCoCreateInstance(
226 _In_ REFCLSID rclsid,
227 _In_ LPUNKNOWN pUnkOuter,
228 _In_ DWORD dwClsContext,
229 _In_ REFIID iid,
230 _Out_ LPVOID *ppv)
231{
232 static HINSTANCE s_hOle32 = NULL;
233 static FN_CoCreateInstance s_fnCoCreateInstance = NULL;
234 if (!s_fnCoCreateInstance)
235 {
236 if (!s_hOle32)
237 s_hOle32 = cicLoadSystemLibrary(TEXT("ole32.dll"), FALSE);
238 s_fnCoCreateInstance = (FN_CoCreateInstance)GetProcAddress(s_hOle32, "CoCreateInstance");
239 if (!s_fnCoCreateInstance)
240 return E_NOTIMPL;
241 }
242
243 return s_fnCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
244}
245
246/**
247 * @implemented
248 */
249HRESULT
250cicCoCreateInstance(
251 _In_ REFCLSID rclsid,
252 _In_ LPUNKNOWN pUnkOuter,
253 _In_ DWORD dwClsContext,
254 _In_ REFIID iid,
255 _Out_ LPVOID *ppv)
256{
257 // NOTE: It looks like Cicero wants to hook CoCreateInstance
258 FN_CoCreateInstance fnUserCoCreateInstance = _cicGetSetUserCoCreateInstance(NULL);
259 if (fnUserCoCreateInstance)
260 return fnUserCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
261
262 return cicRealCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
263}
264
265/**
266 * @implemented
267 */
268EXTERN_C
269BOOL
270TFInitLib(FN_CoCreateInstance fnCoCreateInstance)
271{
272 if (fnCoCreateInstance)
273 _cicGetSetUserCoCreateInstance(fnCoCreateInstance);
274 return TRUE;
275}