Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ if(WIN32)
rcfile.h
registry.cpp
registry.h
Usp10Loader.cpp
Usp10Loader.h
verchk.cpp
verchk.h
WWCOMUtil.cpp
Expand Down
111 changes: 111 additions & 0 deletions Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2026 TheSuperHackers
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "Usp10Loader.h"
#include "mutex.h"


static CriticalSectionClass Usp10LoaderCriticalSection;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be part of the class?


HMODULE Usp10Loader::Module = HMODULE(nullptr);
bool Usp10Loader::LoadAttempted = false;
Usp10Loader::ScriptIsComplex_t Usp10Loader::ScriptIsComplexPtr = nullptr;
Usp10Loader::ScriptStringAnalyse_t Usp10Loader::ScriptStringAnalysePtr = nullptr;
Usp10Loader::ScriptStringFree_t Usp10Loader::ScriptStringFreePtr = nullptr;
Usp10Loader::ScriptStringSize_t Usp10Loader::ScriptStringSizePtr = nullptr;
Usp10Loader::ScriptStringOut_t Usp10Loader::ScriptStringOutPtr = nullptr;


bool Usp10Loader::load()
{
CriticalSectionClass::LockClass lock(Usp10LoaderCriticalSection);

if (LoadAttempted) {
return Module != HMODULE(nullptr);
}
LoadAttempted = true;

char dll_path[MAX_PATH];
const char dll_name[] = "\\usp10.dll";
const UINT path_length = ::GetSystemDirectoryA(dll_path, ARRAY_SIZE(dll_path));
if (path_length == 0 || path_length + ARRAY_SIZE(dll_name) > ARRAY_SIZE(dll_path)) {
return false;
}
strcpy(dll_path + path_length, dll_name);

Module = ::LoadLibraryA(dll_path);
if (Module == HMODULE(nullptr)) {
return false;
}

ScriptIsComplexPtr = reinterpret_cast<ScriptIsComplex_t>(::GetProcAddress(Module, "ScriptIsComplex"));
ScriptStringAnalysePtr = reinterpret_cast<ScriptStringAnalyse_t>(::GetProcAddress(Module, "ScriptStringAnalyse"));
ScriptStringFreePtr = reinterpret_cast<ScriptStringFree_t>(::GetProcAddress(Module, "ScriptStringFree"));
ScriptStringSizePtr = reinterpret_cast<ScriptStringSize_t>(::GetProcAddress(Module, "ScriptString_pSize"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe keep the "_pSize" naming consistent across all variables?

ScriptStringOutPtr = reinterpret_cast<ScriptStringOut_t>(::GetProcAddress(Module, "ScriptStringOut"));

if (ScriptIsComplexPtr == nullptr || ScriptStringAnalysePtr == nullptr || ScriptStringFreePtr == nullptr ||
ScriptStringSizePtr == nullptr || ScriptStringOutPtr == nullptr)
{
::FreeLibrary(Module);
Module = HMODULE(nullptr);
return false;
}

return true;
}


bool Usp10Loader::isLoaded()
{
return load();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This calling load looks strange.

Maybe return return Module != HMODULE(nullptr); ?

}


HRESULT WINAPI Usp10Loader::ScriptIsComplex(const WCHAR *text, int text_length, DWORD flags)
{
return load() ? ScriptIsComplexPtr(text, text_length, flags) : E_FAIL;
}


HRESULT WINAPI Usp10Loader::ScriptStringAnalyse(HDC dc, const void *text, int text_length, int glyph_count,
int charset, DWORD flags, int required_width, ScriptControl *control, ScriptState *state,
const int *spacing, ScriptTabDefinition *tabs, const BYTE *character_classes, ScriptStringAnalysis *analysis)
{
return load() ? ScriptStringAnalysePtr(dc, text, text_length, glyph_count, charset, flags, required_width,
control, state, spacing, tabs, character_classes, analysis) : E_FAIL;
}


HRESULT WINAPI Usp10Loader::ScriptStringFree(ScriptStringAnalysis *analysis)
{
return load() ? ScriptStringFreePtr(analysis) : E_FAIL;
}


const SIZE *WINAPI Usp10Loader::ScriptString_pSize(ScriptStringAnalysis analysis)
Comment thread
xezon marked this conversation as resolved.
{
return load() ? ScriptStringSizePtr(analysis) : nullptr;
}


HRESULT WINAPI Usp10Loader::ScriptStringOut(ScriptStringAnalysis analysis, int x, int y, UINT options,
const RECT *rect, int minimum_selection, int maximum_selection, BOOL disabled)
{
return load() ? ScriptStringOutPtr(analysis, x, y, options, rect, minimum_selection, maximum_selection, disabled) : E_FAIL;
}
71 changes: 71 additions & 0 deletions Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2026 TheSuperHackers
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "win.h"


class Usp10Loader
{
public:

typedef void *ScriptStringAnalysis;
struct ScriptControl;
struct ScriptState;
struct ScriptTabDefinition;

enum
{
SIC_COMPLEX = 0x00000001,
SSA_FALLBACK = 0x00000020,
SSA_GLYPHS = 0x00000080,
SSA_RTL = 0x00000100,
};

static bool isLoaded();

static HRESULT WINAPI ScriptIsComplex(const WCHAR *text, int text_length, DWORD flags);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these made WINAPI?

I see DbgHelpLoader does the same but it probably should not have.

static HRESULT WINAPI ScriptStringAnalyse(HDC dc, const void *text, int text_length, int glyph_count,
int charset, DWORD flags, int required_width, ScriptControl *control, ScriptState *state,
const int *spacing, ScriptTabDefinition *tabs, const BYTE *character_classes,
ScriptStringAnalysis *analysis);
static HRESULT WINAPI ScriptStringFree(ScriptStringAnalysis *analysis);
static const SIZE *WINAPI ScriptString_pSize(ScriptStringAnalysis analysis);
static HRESULT WINAPI ScriptStringOut(ScriptStringAnalysis analysis, int x, int y, UINT options,
const RECT *rect, int minimum_selection, int maximum_selection, BOOL disabled);

private:

static bool load();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current model does not allow to unload it. Is this acceptable?


typedef HRESULT (WINAPI *ScriptIsComplex_t)(const WCHAR *, int, DWORD);
typedef HRESULT (WINAPI *ScriptStringAnalyse_t)(HDC, const void *, int, int, int, DWORD, int,
ScriptControl *, ScriptState *, const int *, ScriptTabDefinition *, const BYTE *, ScriptStringAnalysis *);
typedef HRESULT (WINAPI *ScriptStringFree_t)(ScriptStringAnalysis *);
typedef const SIZE *(WINAPI *ScriptStringSize_t)(ScriptStringAnalysis);
typedef HRESULT (WINAPI *ScriptStringOut_t)(ScriptStringAnalysis, int, int, UINT, const RECT *, int, int, BOOL);

static HMODULE Module;
static bool LoadAttempted;
static ScriptIsComplex_t ScriptIsComplexPtr;
static ScriptStringAnalyse_t ScriptStringAnalysePtr;
static ScriptStringFree_t ScriptStringFreePtr;
static ScriptStringSize_t ScriptStringSizePtr;
static ScriptStringOut_t ScriptStringOutPtr;
};