diff --git a/src/platform/windows.cc b/src/platform/windows.cc index 49be68c44..d83a1b0c4 100644 --- a/src/platform/windows.cc +++ b/src/platform/windows.cc @@ -872,7 +872,44 @@ extern "C" // Remote printing extern "C" { -#pragma comment(lib, "XpsPrint.lib") +// Dynamic loading of XPS Print functions +typedef HRESULT(WINAPI *StartXpsPrintJobFunc)( + LPCWSTR printerName, + LPCWSTR jobName, + LPCWSTR outputFileName, + HANDLE progressEvent, + HANDLE completionEvent, + UINT8* printablePagesOn, + UINT32 printablePagesOnCount, + IXpsPrintJob** xpsPrintJob, + IXpsPrintJobStream** documentStream, + IXpsPrintJobStream** printTicketStream); + +static HMODULE xpsPrintModule = nullptr; +static StartXpsPrintJobFunc StartXpsPrintJobPtr = nullptr; + +static bool InitXpsPrint() +{ + if (xpsPrintModule == nullptr) + { + xpsPrintModule = LoadLibraryA("XpsPrint.dll"); + if (xpsPrintModule == nullptr) + { + flog("Failed to load XpsPrint.dll. Error: %d\n", GetLastError()); + return false; + } + + StartXpsPrintJobPtr = (StartXpsPrintJobFunc)GetProcAddress(xpsPrintModule, "StartXpsPrintJob"); + if (StartXpsPrintJobPtr == nullptr) + { + flog("Failed to get StartXpsPrintJob function. Error: %d\n", GetLastError()); + FreeLibrary(xpsPrintModule); + xpsPrintModule = nullptr; + return false; + } + } + return true; +} #pragma warning(push) #pragma warning(disable : 4995) @@ -886,6 +923,13 @@ extern "C" int PrintXPSRawData(LPWSTR printerName, BYTE *rawData, ULONG dataSize) { + // Check if XPS Print DLL is available + if (!InitXpsPrint()) + { + flog("XPS Print functionality not available on this system\n"); + return -1; + } + BOOL isCoInitializeOk = FALSE; HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); if (hr == RPC_E_CHANGED_MODE) @@ -931,7 +975,7 @@ extern "C" // `StartXpsPrintJob()` is deprecated, but we still use it for compatibility. // We may change to use the `Print Document Package API` in the future. // https://learn.microsoft.com/en-us/windows/win32/printdocs/xpsprint-functions - hr = StartXpsPrintJob( + hr = StartXpsPrintJobPtr( printerName, L"Print Job 1", nullptr, @@ -976,5 +1020,15 @@ extern "C" return 0; } + void CleanupXpsPrint() + { + if (xpsPrintModule != nullptr) + { + FreeLibrary(xpsPrintModule); + xpsPrintModule = nullptr; + StartXpsPrintJobPtr = nullptr; + } + } + #pragma warning(pop) }