mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-15 00:41:01 +03:00
fix(msi): pass the printer name in a format the custom action can read
[~] is MSI's escape for a NUL character, not the delimiter WcaReadStringFromCaData splits on -- that is a literal wide char 128, which a Formatted property value cannot carry -- and WcaGetProperty returns a null-terminated string anyway. So the second field was unreachable: InstallPrinter always fell back to the stock name and installed a printer and port called "RustDesk Printer" inside a customer's branded package, while UninstallPrinter, whose data is a single field and parsed fine, went looking for "Acme Printer" and left the real one behind for good. Both actions now read CustomActionData directly and split on a character that cannot occur in a Windows path or in a validated app name. A package built before this carries no separator and keeps the stock name, as it did. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7fBdTwziR5BHTkSz7Tzcm
This commit is contained in:
@@ -1021,10 +1021,9 @@ UINT __stdcall InstallPrinter(
|
|||||||
DWORD er = ERROR_SUCCESS;
|
DWORD er = ERROR_SUCCESS;
|
||||||
|
|
||||||
int nResult = 0;
|
int nResult = 0;
|
||||||
LPWSTR installFolder = NULL;
|
|
||||||
LPWSTR appName = NULL;
|
|
||||||
LPWSTR pwz = NULL;
|
|
||||||
LPWSTR pwzData = NULL;
|
LPWSTR pwzData = NULL;
|
||||||
|
std::wstring appNameValue;
|
||||||
|
std::wstring installFolderValue;
|
||||||
|
|
||||||
hr = WcaInitialize(hInstall, "InstallPrinter");
|
hr = WcaInitialize(hInstall, "InstallPrinter");
|
||||||
ExitOnFailure(hr, "Failed to initialize");
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
@@ -1032,25 +1031,30 @@ UINT __stdcall InstallPrinter(
|
|||||||
hr = WcaGetProperty(L"CustomActionData", &pwzData);
|
hr = WcaGetProperty(L"CustomActionData", &pwzData);
|
||||||
ExitOnFailure(hr, "failed to get CustomActionData");
|
ExitOnFailure(hr, "failed to get CustomActionData");
|
||||||
|
|
||||||
pwz = pwzData;
|
// "<app name>|<install folder>". Split here rather than through
|
||||||
hr = WcaReadStringFromCaData(&pwz, &installFolder);
|
// WcaReadStringFromCaData, whose delimiter is a literal wide char 128 that a
|
||||||
ExitOnFailure(hr, "failed to read database key from custom action data: %ls", pwz);
|
// Formatted property value cannot carry.
|
||||||
|
|
||||||
// Names the printer. Optional, so that a package built before this was passed in
|
|
||||||
// still installs, keeping the stock printer name.
|
|
||||||
if (FAILED(WcaReadStringFromCaData(&pwz, &appName)))
|
|
||||||
{
|
{
|
||||||
ReleaseNullStr(appName);
|
std::wstring data(pwzData);
|
||||||
|
size_t separator = data.find(L'|');
|
||||||
|
if (separator == std::wstring::npos)
|
||||||
|
{
|
||||||
|
// A package built before the name was passed in; keep the stock name.
|
||||||
|
appNameValue.clear();
|
||||||
|
installFolderValue = data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appNameValue = data.substr(0, separator);
|
||||||
|
installFolderValue = data.substr(separator + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WcaLog(LOGMSG_STANDARD, "Try to install RD printer in : %ls", installFolder);
|
WcaLog(LOGMSG_STANDARD, "Try to install RD printer in : %ls", installFolderValue.c_str());
|
||||||
RemotePrinter::installUpdatePrinter(installFolder, appName ? appName : L"");
|
RemotePrinter::installUpdatePrinter(installFolderValue, appNameValue);
|
||||||
WcaLog(LOGMSG_STANDARD, "Install RD printer done");
|
WcaLog(LOGMSG_STANDARD, "Install RD printer done");
|
||||||
|
|
||||||
LExit:
|
LExit:
|
||||||
if (appName) {
|
|
||||||
ReleaseStr(appName);
|
|
||||||
}
|
|
||||||
if (pwzData) {
|
if (pwzData) {
|
||||||
ReleaseStr(pwzData);
|
ReleaseStr(pwzData);
|
||||||
}
|
}
|
||||||
@@ -1065,32 +1069,24 @@ UINT __stdcall UninstallPrinter(
|
|||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
DWORD er = ERROR_SUCCESS;
|
DWORD er = ERROR_SUCCESS;
|
||||||
|
|
||||||
LPWSTR appName = NULL;
|
|
||||||
LPWSTR pwz = NULL;
|
|
||||||
LPWSTR pwzData = NULL;
|
LPWSTR pwzData = NULL;
|
||||||
|
std::wstring appNameValue;
|
||||||
|
|
||||||
hr = WcaInitialize(hInstall, "UninstallPrinter");
|
hr = WcaInitialize(hInstall, "UninstallPrinter");
|
||||||
ExitOnFailure(hr, "Failed to initialize");
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
// Must match the name install used, otherwise the printer is left behind. Absent
|
// Must match the name install used, otherwise the printer is left behind. Absent
|
||||||
// on packages built before this was passed in, where it was the stock name.
|
// on packages built before this was passed in, where it was the stock name.
|
||||||
if (SUCCEEDED(WcaGetProperty(L"CustomActionData", &pwzData)))
|
if (SUCCEEDED(WcaGetProperty(L"CustomActionData", &pwzData)) && pwzData)
|
||||||
{
|
{
|
||||||
pwz = pwzData;
|
appNameValue = pwzData;
|
||||||
if (FAILED(WcaReadStringFromCaData(&pwz, &appName)))
|
|
||||||
{
|
|
||||||
ReleaseNullStr(appName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WcaLog(LOGMSG_STANDARD, "Try to uninstall RD printer");
|
WcaLog(LOGMSG_STANDARD, "Try to uninstall RD printer");
|
||||||
RemotePrinter::uninstallPrinter(appName ? appName : L"");
|
RemotePrinter::uninstallPrinter(appNameValue);
|
||||||
WcaLog(LOGMSG_STANDARD, "Uninstall RD printer done");
|
WcaLog(LOGMSG_STANDARD, "Uninstall RD printer done");
|
||||||
|
|
||||||
LExit:
|
LExit:
|
||||||
if (appName) {
|
|
||||||
ReleaseStr(appName);
|
|
||||||
}
|
|
||||||
if (pwzData) {
|
if (pwzData) {
|
||||||
ReleaseStr(pwzData);
|
ReleaseStr(pwzData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,13 @@
|
|||||||
<CustomAction Id="SetPropertyServiceStop.SetParam.PropertyName" Return="check" Property="PropertyName" Value="STOP_SERVICE" />
|
<CustomAction Id="SetPropertyServiceStop.SetParam.PropertyName" Return="check" Property="PropertyName" Value="STOP_SERVICE" />
|
||||||
<CustomAction Id="TryDeleteStartupShortcut.SetParam" Return="check" Property="ShortcutName" Value="$(var.Product) Tray" />
|
<CustomAction Id="TryDeleteStartupShortcut.SetParam" Return="check" Property="ShortcutName" Value="$(var.Product) Tray" />
|
||||||
<CustomAction Id="RemoveAmyuniIdd.SetParam" Return="check" Property="RemoveAmyuniIdd" Value="[INSTALLFOLDER_INNER]" />
|
<CustomAction Id="RemoveAmyuniIdd.SetParam" Return="check" Property="RemoveAmyuniIdd" Value="[INSTALLFOLDER_INNER]" />
|
||||||
<!-- [~] separates the fields the custom action reads back. ProductName names the
|
<!-- The app name comes first and is separated by '|', which cannot occur in a
|
||||||
printer, so the dll carries no app name and one build serves every custom client. -->
|
Windows path nor in a validated app name. wcautil's own delimiter is a
|
||||||
<CustomAction Id="InstallPrinter.SetParam" Return="check" Property="InstallPrinter" Value="[INSTALLFOLDER_INNER][~][ProductName]" />
|
literal wide char 128 that a Formatted value cannot carry, and [~] is
|
||||||
|
MSI's NUL escape rather than that delimiter, so the action parses this
|
||||||
|
itself. Passing the name keeps the dll free of it, so one build serves
|
||||||
|
every custom client. -->
|
||||||
|
<CustomAction Id="InstallPrinter.SetParam" Return="check" Property="InstallPrinter" Value="[ProductName]|[INSTALLFOLDER_INNER]" />
|
||||||
<CustomAction Id="UninstallPrinter.SetParam" Return="check" Property="UninstallPrinter" Value="[ProductName]" />
|
<CustomAction Id="UninstallPrinter.SetParam" Return="check" Property="UninstallPrinter" Value="[ProductName]" />
|
||||||
<InstallExecuteSequence>
|
<InstallExecuteSequence>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user