2023-12-13 12:37:15 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Cicero
|
|
|
|
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
|
|
|
* PURPOSE: Cicero base
|
|
|
|
* COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
|
|
|
*/
|
|
|
|
|
2023-12-20 13:01:39 +00:00
|
|
|
#pragma once
|
|
|
|
|
2023-12-21 10:05:33 +00:00
|
|
|
#ifndef __cplusplus
|
|
|
|
#error Cicero needs C++.
|
|
|
|
#endif
|
|
|
|
|
2023-12-20 13:01:39 +00:00
|
|
|
static inline LPVOID cicMemAlloc(SIZE_T size)
|
|
|
|
{
|
|
|
|
return LocalAlloc(0, size);
|
|
|
|
}
|
|
|
|
|
2023-12-13 12:37:15 +00:00
|
|
|
static inline LPVOID cicMemAllocClear(SIZE_T size)
|
|
|
|
{
|
|
|
|
return LocalAlloc(LMEM_ZEROINIT, size);
|
|
|
|
}
|
|
|
|
|
2023-12-20 13:01:39 +00:00
|
|
|
static inline LPVOID cicMemReAlloc(LPVOID ptr, SIZE_T newSize)
|
|
|
|
{
|
|
|
|
if (!ptr)
|
|
|
|
return LocalAlloc(LMEM_ZEROINIT, newSize);
|
|
|
|
return LocalReAlloc(ptr, newSize, LMEM_ZEROINIT);
|
|
|
|
}
|
|
|
|
|
2023-12-13 12:37:15 +00:00
|
|
|
static inline void cicMemFree(LPVOID ptr)
|
|
|
|
{
|
|
|
|
if (ptr)
|
|
|
|
LocalFree(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void* __cdecl operator new(size_t size) noexcept
|
|
|
|
{
|
|
|
|
return cicMemAllocClear(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void __cdecl operator delete(void* ptr) noexcept
|
|
|
|
{
|
|
|
|
cicMemFree(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void __cdecl operator delete(void* ptr, size_t size) noexcept
|
|
|
|
{
|
|
|
|
cicMemFree(ptr);
|
|
|
|
}
|
|
|
|
|
2023-12-23 00:34:41 +00:00
|
|
|
typedef struct CIC_LIBTHREAD
|
|
|
|
{
|
|
|
|
IUnknown *m_pUnknown1;
|
|
|
|
ITfDisplayAttributeMgr *m_pDisplayAttrMgr;
|
|
|
|
} CIC_LIBTHREAD, *PCIC_LIBTHREAD;
|
|
|
|
|
2023-12-21 10:05:33 +00:00
|
|
|
/* The flags of cicGetOSInfo() */
|
2023-12-22 02:52:06 +00:00
|
|
|
#define CIC_OSINFO_NT 0x01
|
|
|
|
#define CIC_OSINFO_2KPLUS 0x02
|
|
|
|
#define CIC_OSINFO_95 0x04
|
|
|
|
#define CIC_OSINFO_98PLUS 0x08
|
|
|
|
#define CIC_OSINFO_CJK 0x10
|
|
|
|
#define CIC_OSINFO_IMM 0x20
|
|
|
|
#define CIC_OSINFO_DBCS 0x40
|
|
|
|
#define CIC_OSINFO_XPPLUS 0x80
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
cicGetOSInfo(LPUINT puACP, LPDWORD pdwOSInfo)
|
2023-12-21 10:05:33 +00:00
|
|
|
{
|
2023-12-22 02:52:06 +00:00
|
|
|
*pdwOSInfo = 0;
|
2023-12-21 10:05:33 +00:00
|
|
|
|
|
|
|
/* Check OS version info */
|
2023-12-22 02:52:06 +00:00
|
|
|
OSVERSIONINFOW VerInfo;
|
|
|
|
VerInfo.dwOSVersionInfoSize = sizeof(VerInfo);
|
2023-12-21 10:05:33 +00:00
|
|
|
GetVersionExW(&VerInfo);
|
|
|
|
if (VerInfo.dwPlatformId == DLLVER_PLATFORM_NT)
|
2023-12-22 02:52:06 +00:00
|
|
|
{
|
|
|
|
*pdwOSInfo |= CIC_OSINFO_NT;
|
|
|
|
if (VerInfo.dwMajorVersion >= 5)
|
|
|
|
{
|
|
|
|
*pdwOSInfo |= CIC_OSINFO_2KPLUS;
|
|
|
|
if (VerInfo.dwMinorVersion > 0)
|
|
|
|
*pdwOSInfo |= CIC_OSINFO_XPPLUS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (VerInfo.dwMinorVersion >= 10)
|
|
|
|
*pdwOSInfo |= CIC_OSINFO_98PLUS;
|
|
|
|
else
|
|
|
|
*pdwOSInfo |= CIC_OSINFO_95;
|
|
|
|
}
|
2023-12-21 10:05:33 +00:00
|
|
|
|
|
|
|
/* Check codepage */
|
2023-12-22 02:52:06 +00:00
|
|
|
*puACP = GetACP();
|
|
|
|
switch (*puACP)
|
2023-12-21 10:05:33 +00:00
|
|
|
{
|
|
|
|
case 932: /* Japanese (Japan) */
|
|
|
|
case 936: /* Chinese (PRC, Singapore) */
|
|
|
|
case 949: /* Korean (Korea) */
|
|
|
|
case 950: /* Chinese (Taiwan, Hong Kong) */
|
2023-12-22 02:52:06 +00:00
|
|
|
*pdwOSInfo |= CIC_OSINFO_CJK;
|
2023-12-21 10:05:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetSystemMetrics(SM_IMMENABLED))
|
2023-12-22 02:52:06 +00:00
|
|
|
*pdwOSInfo |= CIC_OSINFO_IMM;
|
2023-12-21 10:05:33 +00:00
|
|
|
|
|
|
|
if (GetSystemMetrics(SM_DBCSENABLED))
|
2023-12-22 02:52:06 +00:00
|
|
|
*pdwOSInfo |= CIC_OSINFO_DBCS;
|
2023-12-21 10:05:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct CicSystemModulePath
|
|
|
|
{
|
2023-12-22 02:52:06 +00:00
|
|
|
WCHAR m_szPath[MAX_PATH + 2];
|
2023-12-21 10:05:33 +00:00
|
|
|
SIZE_T m_cchPath;
|
|
|
|
|
|
|
|
CicSystemModulePath()
|
|
|
|
{
|
|
|
|
m_szPath[0] = UNICODE_NULL;
|
|
|
|
m_cchPath = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL Init(_In_ LPCWSTR pszFileName, _In_ BOOL bSysWinDir);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Get an instance handle that is already loaded
|
|
|
|
static inline HINSTANCE
|
|
|
|
cicGetSystemModuleHandle(
|
|
|
|
_In_ LPCWSTR pszFileName,
|
|
|
|
_In_ BOOL bSysWinDir)
|
|
|
|
{
|
|
|
|
CicSystemModulePath ModPath;
|
|
|
|
if (!ModPath.Init(pszFileName, bSysWinDir))
|
|
|
|
return NULL;
|
|
|
|
return GetModuleHandleW(ModPath.m_szPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load a system library
|
|
|
|
static inline HINSTANCE
|
|
|
|
cicLoadSystemLibrary(
|
|
|
|
_In_ LPCWSTR pszFileName,
|
|
|
|
_In_ BOOL bSysWinDir)
|
|
|
|
{
|
|
|
|
CicSystemModulePath ModPath;
|
|
|
|
if (!ModPath.Init(pszFileName, bSysWinDir))
|
|
|
|
return NULL;
|
|
|
|
return ::LoadLibraryW(ModPath.m_szPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <ndk/pstypes.h> /* for PROCESSINFOCLASS */
|
|
|
|
|
|
|
|
/* ntdll!NtQueryInformationProcess */
|
|
|
|
typedef NTSTATUS (WINAPI *FN_NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
|
|
|
|
|
|
|
|
/* Is the current process on WoW64? */
|
|
|
|
static inline BOOL cicIsWow64(VOID)
|
|
|
|
{
|
|
|
|
static FN_NtQueryInformationProcess s_fnNtQueryInformationProcess = NULL;
|
|
|
|
ULONG_PTR Value;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
if (!s_fnNtQueryInformationProcess)
|
|
|
|
{
|
|
|
|
HMODULE hNTDLL = cicGetSystemModuleHandle(L"ntdll.dll", FALSE);
|
|
|
|
if (!hNTDLL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
s_fnNtQueryInformationProcess =
|
|
|
|
(FN_NtQueryInformationProcess)GetProcAddress(hNTDLL, "NtQueryInformationProcess");
|
|
|
|
if (!s_fnNtQueryInformationProcess)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value = 0;
|
|
|
|
Status = s_fnNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information,
|
|
|
|
&Value, sizeof(Value), NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return !!Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline BOOL
|
|
|
|
CicSystemModulePath::Init(
|
|
|
|
_In_ LPCWSTR pszFileName,
|
|
|
|
_In_ BOOL bSysWinDir)
|
|
|
|
{
|
|
|
|
SIZE_T cchPath;
|
|
|
|
if (bSysWinDir)
|
|
|
|
{
|
|
|
|
// Usually C:\Windows or C:\ReactOS
|
2023-12-26 01:31:53 +00:00
|
|
|
cchPath = ::GetSystemWindowsDirectoryW(m_szPath, _countof(m_szPath));
|
2023-12-21 10:05:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Usually C:\Windows\system32 or C:\ReactOS\system32
|
|
|
|
cchPath = ::GetSystemDirectoryW(m_szPath, _countof(m_szPath));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_szPath[_countof(m_szPath) - 1] = UNICODE_NULL; // Avoid buffer overrun
|
|
|
|
|
|
|
|
if ((cchPath == 0) || (cchPath > _countof(m_szPath) - 2))
|
|
|
|
goto Failure;
|
|
|
|
|
|
|
|
// Add backslash if necessary
|
|
|
|
if ((cchPath > 0) && (m_szPath[cchPath - 1] != L'\\'))
|
|
|
|
{
|
|
|
|
m_szPath[cchPath + 0] = L'\\';
|
|
|
|
m_szPath[cchPath + 1] = UNICODE_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append pszFileName
|
|
|
|
if (FAILED(StringCchCatW(m_szPath, _countof(m_szPath), pszFileName)))
|
|
|
|
goto Failure;
|
|
|
|
|
|
|
|
m_cchPath = wcslen(m_szPath);
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
Failure:
|
|
|
|
m_szPath[0] = UNICODE_NULL;
|
|
|
|
m_cchPath = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2023-12-23 00:34:41 +00:00
|
|
|
|
|
|
|
// ole32!CoCreateInstance
|
|
|
|
typedef HRESULT (WINAPI *FN_CoCreateInstance)(
|
|
|
|
REFCLSID rclsid,
|
|
|
|
LPUNKNOWN pUnkOuter,
|
|
|
|
DWORD dwClsContext,
|
|
|
|
REFIID iid,
|
|
|
|
LPVOID *ppv);
|
|
|
|
|
|
|
|
static inline FN_CoCreateInstance
|
|
|
|
_cicGetSetUserCoCreateInstance(FN_CoCreateInstance fnUserCoCreateInstance)
|
|
|
|
{
|
|
|
|
static FN_CoCreateInstance s_fn = NULL;
|
|
|
|
if (fnUserCoCreateInstance)
|
|
|
|
s_fn = fnUserCoCreateInstance;
|
|
|
|
return s_fn;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline HRESULT
|
2023-12-23 02:02:40 +00:00
|
|
|
cicRealCoCreateInstance(
|
2023-12-23 00:34:41 +00:00
|
|
|
REFCLSID rclsid,
|
|
|
|
LPUNKNOWN pUnkOuter,
|
|
|
|
DWORD dwClsContext,
|
|
|
|
REFIID iid,
|
|
|
|
LPVOID *ppv)
|
|
|
|
{
|
|
|
|
static HINSTANCE s_hOle32 = NULL;
|
|
|
|
static FN_CoCreateInstance s_fnCoCreateInstance = NULL;
|
|
|
|
if (!s_fnCoCreateInstance)
|
|
|
|
{
|
|
|
|
if (!s_hOle32)
|
|
|
|
s_hOle32 = cicLoadSystemLibrary(L"ole32.dll", FALSE);
|
|
|
|
s_fnCoCreateInstance = (FN_CoCreateInstance)GetProcAddress(s_hOle32, "CoCreateInstance");
|
|
|
|
if (!s_fnCoCreateInstance)
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return s_fnCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
|
|
|
|
}
|
|
|
|
|
2023-12-23 02:02:40 +00:00
|
|
|
/**
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
static inline HRESULT
|
|
|
|
cicCoCreateInstance(
|
|
|
|
REFCLSID rclsid,
|
|
|
|
LPUNKNOWN pUnkOuter,
|
|
|
|
DWORD dwClsContext,
|
|
|
|
REFIID iid,
|
|
|
|
LPVOID *ppv)
|
|
|
|
{
|
|
|
|
// NOTE: It looks like Cicero wants to hook CoCreateInstance
|
|
|
|
FN_CoCreateInstance fnUserCoCreateInstance = _cicGetSetUserCoCreateInstance(NULL);
|
|
|
|
if (fnUserCoCreateInstance)
|
|
|
|
return fnUserCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
|
|
|
|
|
|
|
|
return cicRealCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
|
|
|
|
}
|
|
|
|
|
2023-12-23 00:34:41 +00:00
|
|
|
/**
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
static inline BOOL
|
|
|
|
TFInitLib(FN_CoCreateInstance fnCoCreateInstance = NULL)
|
|
|
|
{
|
|
|
|
if (fnCoCreateInstance)
|
|
|
|
_cicGetSetUserCoCreateInstance(fnCoCreateInstance);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
static inline VOID
|
|
|
|
TFUninitLib(VOID)
|
|
|
|
{
|
|
|
|
//FIXME
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
static inline VOID
|
|
|
|
TFUninitLib_Thread(PCIC_LIBTHREAD pLibThread)
|
|
|
|
{
|
|
|
|
if (!pLibThread)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pLibThread->m_pUnknown1)
|
|
|
|
{
|
|
|
|
pLibThread->m_pUnknown1->Release();
|
|
|
|
pLibThread->m_pUnknown1 = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pLibThread->m_pDisplayAttrMgr)
|
|
|
|
{
|
|
|
|
pLibThread->m_pDisplayAttrMgr->Release();
|
|
|
|
pLibThread->m_pDisplayAttrMgr = NULL;
|
|
|
|
}
|
|
|
|
}
|