Fix/preserve deleted printer (#16500)

* fix(windows): preserve manually deleted printers

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(windows): distinguish printer detection failures

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(windows): skip printer detection when disabled

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(flutter): load printer status asynchronously

Signed-off-by: fufesou <linlong1266@gmail.com>

* refactor(flutter): remove printer status mounted checks

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(msi): preserve deleted printers in direct upgrades

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(windows): preserve deleted printers in silent EXE installs

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(windows): skip printer installation when detection fails

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(installer): default printer off when detection fails

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(printer): limit checked enumeration to presence queries

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(installer): allow cancellation during printer detection

Inline MSI update command construction without changing its arguments.

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix(flutter): time out installer printer detection

Signed-off-by: fufesou <linlong1266@gmail.com>

* chore

Signed-off-by: fufesou <linlong1266@gmail.com>

* test(windows): cover multilingual install app names

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou authored and GitHub committed 2026-10-10 00:21:17 +08:00
1 parent 0bc2473ffe
commit 001b0e9617
6 files changed
+186 -22

No files matched your search

+66
View File
@@ -3,6 +3,7 @@
#include <Windows.h>
#include <winspool.h>
#include <setupapi.h>
#include <strutil.h>
#include <memory>
#include <string>
#include <functional>
@@ -356,6 +357,42 @@ namespace RemotePrinter
return EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, level, pPrinterInfo, cbBuf, pcbNeeded, pcReturned);
}
static HRESULT queryPrinterPresence(LPCWSTR name)
{
constexpr DWORD printerInfoLevel = 1;
DWORD needed = 0;
DWORD returned = 0;
if (!enumLocalPrinter(printerInfoLevel, NULL, 0, &needed, &returned))
{
const DWORD error = GetLastError();
if (error != ERROR_INSUFFICIENT_BUFFER || needed == 0)
{
return error == ERROR_SUCCESS ? E_FAIL : HRESULT_FROM_WIN32(error);
}
}
if (needed == 0)
{
return S_FALSE;
}
std::vector<BYTE> buffer(needed);
if (!enumLocalPrinter(printerInfoLevel, buffer.data(), needed, &needed, &returned))
{
const DWORD error = GetLastError();
return error == ERROR_SUCCESS ? E_FAIL : HRESULT_FROM_WIN32(error);
}
const auto printers = reinterpret_cast<const PRINTER_INFO_1W *>(buffer.data());
for (DWORD i = 0; i < returned; i++)
{
if (isNameEqual(name, printers[i].pName))
{
return S_OK;
}
}
return S_FALSE;
}
BOOL isPrinterAdded(LPCWSTR name)
{
auto onData = [name](const PRINTER_INFO_1W &info)
@@ -528,3 +565,32 @@ namespace RemotePrinter
WcaLog(LOGMSG_STANDARD, "Deleted the local port\n");
}
}
extern "C" UINT __stdcall SetPrinterInstallDefault(__in MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
LPWSTR appName = NULL;
hr = WcaInitialize(hInstall, "SetPrinterInstallDefault");
ExitOnFailure(hr, "Failed to initialize printer detection");
hr = WcaGetProperty(L"ProductName", &appName);
ExitOnFailure(hr, "Failed to get the printer's application name");
hr = RemotePrinter::queryPrinterPresence(RemotePrinter::printerNameOf(appName).c_str());
if (FAILED(hr))
{
WcaLog(LOGMSG_STANDARD, "Failed to detect the existing printer (0x%08X); skipping printer installation.", static_cast<UINT>(hr));
}
if (hr != S_OK)
{
hr = WcaSetProperty(L"INSTALLPRINTER", L"0");
ExitOnFailure(hr, "Failed to disable printer installation");
WcaLog(LOGMSG_STANDARD, "The application's printer was not confirmed present; leaving printer installation disabled by default.");
}
LExit:
ReleaseStr(appName);
return WcaFinalize(SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE);
}