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