Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

op2ext for Outpost 2 v1.4.x #303

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
71 changes: 44 additions & 27 deletions srcDLL/DllMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "OP2Memory.h"
#include "FileSystemHelper.h"
#include "FsInclude.h"
#include "ConsoleArgumentParser.h"
#include "Log.h"
#include "Log/LoggerFile.h"
#include "Log/LoggerMessageBox.h"
Expand Down Expand Up @@ -40,34 +41,39 @@ AppEvents appEvents;
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*reserved*/)
{
// This will be called once the program is unpacked and running
if (dwReason == DLL_PROCESS_ATTACH) {
// Setup logging
SetLoggerError(&loggerDistributor);
SetLoggerMessage(&loggerFile);
SetLoggerDebug(&loggerDebug);

// Construct global objects
vols = std::make_unique<std::vector<std::string>>();
moduleLoader = std::make_unique<ModuleLoader>();

// Set load offset for Outpost2.exe module, used during memory patching
// If this fails, it's because Outpost2.exe is not loaded
// Failure means op2ext.dll was loaded by something else, such as a unit test
// For unit tests, just stay in memory, it's not an error if this fails
if (EnableOp2MemoryPatching()) {
// These hooks are needed to further bootstrap the rest of module loading
if (!InstallTAppEventHooks()) {
LogError("Failed to install initial TApp event hooks. Module loading and patching disabled.");
return FALSE;
if ((dwReason == DLL_PROCESS_ATTACH) && CommandOptionExists("OPU")) {
wchar_t filename[MAX_PATH] = L"";
GetModuleFileNameW(NULL, &filename[0], MAX_PATH);

if (fs::path(filename).filename() == "Outpost2.exe") {
Copy link
Member

Choose a reason for hiding this comment

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

Could you explain the extra checks added here? I think I understand why the CommandOptionExists("OPU") check was added, based on what I've been told of the new architecture for 1.4.0. I'm less certain why the module filename check was added.

Copy link
Member Author

Choose a reason for hiding this comment

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

The winmm.dll shim (that loads op2ext.dll as an import) could potentially be loaded into any process, since it is a system DLL. This is just out of an abundance of caution.

// Setup logging
SetLoggerError(&loggerDistributor);
SetLoggerMessage(&loggerFile);
SetLoggerDebug(&loggerDebug);

// Construct global objects
vols = std::make_unique<std::vector<std::string>>();
moduleLoader = std::make_unique<ModuleLoader>();

// Set load offset for Outpost2.exe module, used during memory patching
// If this fails, it's because Outpost2.exe is not loaded
// Failure means op2ext.dll was loaded by something else, such as a unit test
// For unit tests, just stay in memory, it's not an error if this fails
if (EnableOp2MemoryPatching()) {
// These hooks are needed to further bootstrap the rest of module loading
if (!InstallTAppEventHooks()) {
LogError("Failed to install initial TApp event hooks. Module loading and patching disabled.");
return FALSE;
}

// Setup event handlers
appEvents.onInit.Add(&OnInit);
appEvents.onLoadShell.Add(&OnLoadShell);
appEvents.onShutDown.Add(&OnShutdown);

// Set active events
appEvents.Activate();
}

// Setup event handlers
appEvents.onInit.Add(&OnInit);
appEvents.onLoadShell.Add(&OnLoadShell);
appEvents.onShutDown.Add(&OnShutdown);

// Set active events
appEvents.Activate();
}

// Disable any more thread attach calls
Expand Down Expand Up @@ -104,11 +110,22 @@ bool InstallDepPatch()
}


// Redirects Outpost2.ini to be accessed from the OPU directory.
void RedirectIniFile()
{
const auto iniPath = GetOutpost2IniPath();
Op2MemCopy(0x00547090, iniPath.length() + 1, iniPath.data()); // Overwrite gConfigFile.iniPath
}
Copy link
Member

Choose a reason for hiding this comment

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

Should this copy be bounds checked? I assume the destination buffer is statically sized. If it's guaranteed to fit, we should probably add a note as to why.

Copy link
Member Author

Choose a reason for hiding this comment

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

The destination buffer is MAX_PATH-sized. While it could be bounds-checked, if we're trying a path longer than MAX_PATH, we're already going to explode due to OS limits. (Win10 did add large path support, but apps need to opt-in to it via the manifest and be coded to use them, and there's no real chance of doing that for OP2.)



void OnInit()
{
// Install DEP patch so newer versions of Windows don't terminate the game
InstallDepPatch();

// Set the game to look for Outpost2.ini under the OPU directory
RedirectIniFile();

// Order of precedence for loading vol files is:
// ART_PATH (from console module), Console Module, Ini Modules, Addon directory, Game directory

Expand Down
Loading