Loading Extensions

Overview

UAW Extensions are dynamic libraries (DLL files on Windows). Extensions are enumerated from the Windows Registry.

RationaleUse of the Registry allows administrators to install extensions for all users on a machine, while allowing individual users to override the administrator’s presets. And there are more advantages of the Registry over e.g. configuration files.

To make an extension available under Options > Extensions, create a sub-key under HKEY_CURRENT_USER\Software\TFXplorer\Extensions with the following format:

Name Type Meaning
Path REG_SZ Path to the dynamic-link library (DLL) of the extension. This path is either absolute or relative to the UAW installation.
RationaleExtensions may be placed anywhere on the system, not just in a sub-directory of the UAW installation. This allows users to install extensions individually – even without having administrator rights on the system.
Active REG_DWORD Non-zero if the user allowed the extension to load on startup.
RationaleOn machines with multiple Windows users, users may choose their extensions individually. However, the Path value must be present even if a user deactivated an extension, so that they can later re-activate it if they want.
DataPath REG_SZ Optional. Path to the extension’s data. This path is either absolute or relative to the UAW installation. Allows to load the same extension more than once with different data.
RationaleMakes modding possible. Allows developer features like side-by-side testing, debug vs. release versions, etc.

Creating a Dynamic Library

If you are using Visual Studio, start your extension by creating a new DLL project. For other toolsets, refer to their documentation.

Then, add the compiled DLL to the Registry according to the previous chapter.

When UAW loads an extension, it loads the DLL given under Path and searches it for a function named uaw_extension_main_????, where the last four characters correspond to the unique identifier of the UAW API version. This UID changes randomly with every update to the API.

RationaleExtensions cannot guess future version IDs, so they cannot wrongfully declare themselves upwards-compatible with API versions that have not even been released. UAW, on the other hand, can determine the API versions supported by a specific plugin upfront, thus providing compatibility.

This is, however, not your business. When you define the entry point like below, use the UAW_EXTENSION_CREATE macro from UAW API.h, which automatically resolves to the entry point name associated with the API version of your UAW headers.

int UAW_CALL UAW_EXTENSION_CREATE(
	struct UAW_API_Extension *       uaw,
	struct UAW_Extension_Callbacks * result,
	void *                           legacyPleaseIgnore
) {
	// If you work object-oriented, create an instance and store its address here.
	// It will be passed back to you with every callback.
	result->implementation = …;

	// If you need a chance to clean up before UAW quits, place your callback here.
	result->unload = …;

	// For display in the Extensions menu (from the strings sample):
	result->string      = &stringFromStringID;
	result->name        = extensionName;
	result->author      = extensionAuthor;
	result->url         = extensionUrl;
	result->description = extensionDescription;

	return 1; // success (zero for failure)
}

If you write your extension in C++ instead of C, make sure that the function is declared extern "C"!

With Visual Studio, you can use __declspec(dllexport) to make the function visible to UAW.