Create a Package Support Framework fixup
If there is no runtime fix for your issue, you can create a new runtime fix by writing replacement functions and including any configuration data that makes sense. Let's look at each part.
Replacement functions
First, identify which function calls fail when your application runs in an MSIX container. Then, you can create replacement functions that you'd like the runtime manager to call instead. This gives you an opportunity to replace the implementation of a function with behavior that conforms to the rules of the modern runtime environment.
Declare the FIXUP_DEFINE_EXPORTS
macro and then add a include statement for the fixup_framework.h
at the top of each .CPP file where you intend to add the functions of your runtime fix.
#define FIXUP_DEFINE_EXPORTS
#include <fixup_framework.h>
Important
Make sure that the FIXUP_DEFINE_EXPORTS
macro appears before the include statement.
Create a function that has the same signature of the function who's behavior you want to modify. Here's an example function that replaces the MessageBoxW
function.
auto MessageBoxWImpl = &::MessageBoxW;
int WINAPI MessageBoxWFixup(
_In_opt_ HWND hwnd,
_In_opt_ LPCWSTR,
_In_opt_ LPCWSTR caption,
_In_ UINT type)
{
return MessageBoxWImpl(hwnd, L"SUCCESS: This worked", caption, type);
}
DECLARE_FIXUP(MessageBoxWImpl, MessageBoxWFixup);
The call to DECLARE_FIXUP
maps the MessageBoxW
function to your new replacement function. When your application attempts to call the MessageBoxW
function, it will call the replacement function instead.
Protect against recursive calls to functions in runtime fixes
The reentrancy_guard
type can be added to your functions to protect them against recursive function calls.
For example, you might produce a replacement function for the CreateFile
function. Your implementation might call the CopyFile
function, but the implementation of the CopyFile
function might call the CreateFile
function. This may lead to an infinite recursive cycle of calls to the CreateFile
function.
For more information on reentrancy_guard
see authoring.md
Configuration data
If you want to add configuration data to your runtime fix, consider adding it to the config.json
. That way, you can use the FixupQueryCurrentDllConfig
to easily parse that data. This example parses a boolean and string value from that configuration file.
if (auto configRoot = ::FixupQueryCurrentDllConfig())
{
auto& config = configRoot->as_object();
if (auto enabledValue = config.try_get("enabled"))
{
g_enabled = enabledValue->as_boolean().get();
}
if (auto logPathValue = config.try_get("logPath"))
{
g_logPath = logPathValue->as_string().wstring();
}
}
Fixup metadata
Each fixup and the PSF Launcher application has an XML metadata file that contains the following information:
- Version: The version of the PSF is in MAJOR.MINOR.PATCH format according to Sem Version 2.
- Minimum Windows Platform: The minimum windows version required for the fixup or PSF Launcher.
- Description: A short description of the fixup.
- WhenToUse: Heuristics on when you should apply the fixup.
For an example, see the FileRedirectionFixupMetadata.xml metadata file for the redirection fixup. The metadata schema is available here.