Fallout 4 Script Extender (F4SE)

repository·master·Indexed 40 days ago

https://github.com/ianpatt/f4se

A C++ project for the Fallout 4 Script Extender. Includes documentation on building from source using CMake and Visual Studio, the f4se_loader execution flow for DLL injection, and the f4se_steam_loader's IAT hooking mechanism for initializing the F4SE runtime.

Tokens
1.6K
Snippets
4
Records
8
Agent score
100%

What's inside F4SE

  1. Build f4se from source

    master

    To build f4se, you must first clone and build the common dependency. The build process uses CMake to configure the projects and generate a Visual Studio solution.

    1. Clone both the common and f4se repositories.
    2. Build and install common into an extern directory.
    3. Configure and build f4se using the extern directory for dependencies.

    The resulting Visual Studio solution will be located at f4se/build/umbrella.sln.

    git clone https://github.com/ianpatt/common
    git clone https://github.com/ianpatt/f4se
    cmake -B common/build -S common -DCMAKE_INSTALL_PREFIX=extern common
    cmake --build common/build --config Release --target install
    cmake -B f4se/build -S f4se -DCMAKE_INSTALL_PREFIX=extern f4se
    cmake --build f4se/build --config Release
  2. How the f4se_steam_loader initializes

    master

    The f4se_steam_loader is a DLL designed to be injected into the Fallout 4 process (specifically the Steam version) to facilitate the loading of F4SE.

    It follows this lifecycle:

    1. DLL Attachment: Upon DLL_PROCESS_ATTACH, it initializes a debug log in %USERPROFILE%\Documents\My Games\Fallout4\F4SE\f4se_steam_loader.log.
    2. IAT Hooking: It performs an Import Address Table (IAT) hook on __crtGetShowWindowMode from MSVCR110.dll. This is used as a trigger to execute code early in the process lifecycle.
    3. Code Injection: When the hooked function is called, HookMain is triggered. This function identifies the correct F4SE DLL (either f4se_*.dll or f4se_editor_*.dll) based on whether the running executable is the game or the Creation Kit editor, and then calls LoadLibrary to load the actual F4SE runtime.
  3. How the EarlyTerminationHandler manages plugin lifecycle

    master

    The EarlyTerminationHandler class is used to manage the lifecycle of the target process and ensure that if the loader receives a termination signal (like a console control event), the target process is also terminated.

    It works by registering a HandlerWrapper with SetConsoleCtrlHandler. When a termination signal is received, the Handler method is called, which executes TerminateProcess on the managed process handle.

    To use it, you call .start(HANDLE proc) to begin monitoring a process and .stop() to unregister the handler and stop monitoring.

    EarlyTerminationHandler handler;
    handle = OpenProcess(...);
    handler.start(handle);
    // ... later ...
    handler.stop();
  4. F4SE Loader execution flow

    master

    The f4se_loader follows this high-level execution pattern:

    1. Initialization: Opens a debug log in the user's Documents folder and parses command line arguments.
    2. Path Resolution: Determines the target process path (e.g., Fallout4.exe or CreationKit.exe) and the F4SE DLL path (e.g., f4se_xxx.dll).
    3. Validation:
      • Checks if the executable exists.
      • Verifies the DLL version against the executable's version using IdentifyEXE.
      • Validates the DLL signature via CheckDLLSignature.
    4. Environment Setup: Sets environment variables (F4SE_DLL, F4SE_RUNTIME, etc.) and Steam-related variables if necessary.
    5. Process Creation: Launches the target process in a CREATE_SUSPENDED state.
    6. Injection: Injects the F4SE DLL into the suspended process using InjectDLLThread.
    7. Resumption: Resumes the target process thread to begin execution with the injected DLL.
  5. AugmentEnvironment sets F4SE environment variables

    master

    The AugmentEnvironment function prepares the environment for the target process by setting specific environment variables that the F4SE DLL will require. It takes the full path to the process (procPath) and the full path to the DLL (dllPath).

    It sets the following environment variables:

    • F4SE_DLL: The filename of the F4SE DLL.
    • F4SE_RUNTIME: The filename of the target process executable.
    • F4SE_WAITFORDEBUGGER: Set to "1" if g_options.m_waitForDebugger is true, otherwise "0".
    void AugmentEnvironment(const std::string& procPath, const std::string& dllPath)
  6. Identify F4SE component version via resource metadata

    master

    The F4SE binary includes versioning information embedded in its resource file. When inspecting the compiled DLL or component, the following metadata fields are used to identify the specific version and purpose:

    • FileDescription: A component of the Fallout 4 Script Extender
    • InternalName: F4SE
    • ProductName: F4SE
    • FileVersion: Derived from F4SE_VERSION_VERSTRING
    • ProductVersion: Derived from F4SE_VERSION_VERSTRING

    If you are troubleshooting version mismatches, ensure the FileVersion reported by the OS or file properties matches the expected version of your F4SE installation.

  7. F4SE Loader command line arguments and options

    master

    The f4se_loader uses a global g_options object (of type Options) to parse command line arguments. The main function calls g_options.Read(argc, argv) to populate these settings.

    Key options used by the loader include:

    • m_launchCS: If true, attempts to launch CreationKit.exe instead of Fallout4.exe.
    • m_altEXE: Allows specifying an alternate path to the executable.
    • m_altDLL: Allows specifying an alternate path to the F4SE DLL.
    • m_launchSteam: If true, attempts to launch Steam if it is not running.
    • m_skipLauncher: If true, sets the SteamAppID environment variable to bypass the Steam launcher.
    • m_setPriority: Sets the process priority for the created process.
    • m_affinity: Sets the CPU affinity mask for the process.
    • m_noTimeout: Used during DLL injection to disable timeouts.
    • m_waitForClose: If true, the loader waits for the target process to exit before finishing.
  8. F4SE Steam Loader entry point (DllMain)

    master

    The entry point for the f4se_steam_loader DLL. It handles the DLL_PROCESS_ATTACH event to trigger the OnAttach sequence, which sets up logging and begins the IAT hooking process.

    BOOL WINAPI DllMain(HANDLE procHandle, DWORD reason, LPVOID reserved)
    {
    	if(reason == DLL_PROCESS_ATTACH)
    	{
    		g_dllHandle = procHandle;
    		OnAttach();
    	}
    
    	return TRUE;
    }