From f7020c0d16baf2b960e7123e233e20c519f6a340 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Sat, 15 Dec 2018 21:46:30 -0600 Subject: Import implementation of UtilCA from old repo's WixCA/scasched/scaexec. (#3) --- src/ca/qtexecca.cpp | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 src/ca/qtexecca.cpp (limited to 'src/ca/qtexecca.cpp') diff --git a/src/ca/qtexecca.cpp b/src/ca/qtexecca.cpp new file mode 100644 index 00000000..6acad0bb --- /dev/null +++ b/src/ca/qtexecca.cpp @@ -0,0 +1,312 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" + +#define OUTPUT_BUFFER 1024 + +// These old "CA" prefix names are deprecated, and intended to go away in wix 4.0, only staying now for compatibility reasons +const LPCWSTR CAQUIET_TIMEOUT_PROPERTY = L"QtExecCmdTimeout"; +const LPCWSTR CAQUIET_ARGUMENTS_PROPERTY = L"QtExecCmdLine"; +const LPCWSTR CAQUIET64_ARGUMENTS_PROPERTY = L"QtExec64CmdLine"; +// end deprecated section + +// WixCA name quiet commandline argument properties +const LPCWSTR WIX_QUIET_ARGUMENTS_PROPERTY = L"WixQuietExecCmdLine"; +const LPCWSTR WIX_QUIET64_ARGUMENTS_PROPERTY = L"WixQuietExec64CmdLine"; + +// WixCA quiet timeout properties +const LPCWSTR WIX_QUIET_TIMEOUT_PROPERTY = L"WixQuietExecCmdTimeout"; +const LPCWSTR WIX_QUIET64_TIMEOUT_PROPERTY = L"WixQuietExec64CmdTimeout"; + +// WixCA silent commandline argument properties +const LPCWSTR WIX_SILENT_ARGUMENTS_PROPERTY = L"WixSilentExecCmdLine"; +const LPCWSTR WIX_SILENT64_ARGUMENTS_PROPERTY = L"WixSilentExec64CmdLine"; + +// WixCA silent timeout properties +const LPCWSTR WIX_SILENT_TIMEOUT_PROPERTY = L"WixSilentExecCmdTimeout"; +const LPCWSTR WIX_SILENT64_TIMEOUT_PROPERTY = L"WixSilentExec64CmdTimeout"; + +HRESULT BuildCommandLine( + __in LPCWSTR wzProperty, + __out LPWSTR *ppwzCommand + ) +{ + Assert(ppwzCommand); + + HRESULT hr = S_OK; + BOOL fScheduled = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_SCHEDULED); + BOOL fRollback = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK); + BOOL fCommit = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_COMMIT); + + if (fScheduled || fRollback || fCommit) + { + if (WcaIsPropertySet("CustomActionData")) + { + hr = WcaGetProperty( L"CustomActionData", ppwzCommand); + ExitOnFailure(hr, "Failed to get CustomActionData"); + } + } + else if (WcaIsUnicodePropertySet(wzProperty)) + { + hr = WcaGetFormattedProperty(wzProperty, ppwzCommand); + ExitOnFailure(hr, "Failed to get %ls", wzProperty); + hr = WcaSetProperty(wzProperty, L""); // clear out the property now that we've read it + ExitOnFailure(hr, "Failed to set %ls", wzProperty); + } + + if (!*ppwzCommand) + { + ExitOnFailure(hr = E_INVALIDARG, "Failed to get command line data"); + } + + if (L'"' != **ppwzCommand) + { + WcaLog(LOGMSG_STANDARD, "Command string must begin with quoted application name."); + ExitOnFailure(hr = E_INVALIDARG, "invalid command line property value"); + } + +LExit: + return hr; +} + +#define ONEMINUTE 60000 + +DWORD GetTimeout(LPCWSTR wzPropertyName) +{ + DWORD dwTimeout = ONEMINUTE; + HRESULT hr = S_OK; + + LPWSTR pwzData = NULL; + + if (WcaIsUnicodePropertySet(wzPropertyName)) + { + hr = WcaGetProperty(wzPropertyName, &pwzData); + ExitOnFailure(hr, "Failed to get %ls", wzPropertyName); + + if ((dwTimeout = (DWORD)_wtoi(pwzData)) == 0) + { + dwTimeout = ONEMINUTE; + } + } + +LExit: + ReleaseStr(pwzData); + + return dwTimeout; + +} + +HRESULT ExecCommon( + __in LPCWSTR wzArgumentsProperty, + __in LPCWSTR wzTimeoutProperty, + __in BOOL fLogCommand, + __in BOOL fLogOutput + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzCommand = NULL; + DWORD dwTimeout = 0; + + hr = BuildCommandLine(wzArgumentsProperty, &pwzCommand); + ExitOnFailure(hr, "Failed to get Command Line"); + + dwTimeout = GetTimeout(wzTimeoutProperty); + + hr = QuietExec(pwzCommand, dwTimeout, fLogCommand, fLogOutput); + ExitOnFailure(hr, "QuietExec Failed"); + +LExit: + ReleaseStr(pwzCommand); + + return hr; +} + +HRESULT ExecCommon64( + __in LPCWSTR wzArgumentsProperty, + __in LPCWSTR wzTimeoutProperty, + __in BOOL fLogCommand, + __in BOOL fLogOutput + ) +{ + HRESULT hr = S_OK; + LPWSTR pwzCommand = NULL; + DWORD dwTimeout = 0; + BOOL fIsWow64Initialized = FALSE; + BOOL fRedirected = FALSE; + + hr = WcaInitializeWow64(); + if (S_FALSE == hr) + { + hr = TYPE_E_DLLFUNCTIONNOTFOUND; + } + ExitOnFailure(hr, "Failed to intialize WOW64."); + fIsWow64Initialized = TRUE; + + hr = WcaDisableWow64FSRedirection(); + ExitOnFailure(hr, "Failed to enable filesystem redirection."); + fRedirected = TRUE; + + hr = BuildCommandLine(wzArgumentsProperty, &pwzCommand); + ExitOnFailure(hr, "Failed to get Command Line"); + + dwTimeout = GetTimeout(wzTimeoutProperty); + + hr = QuietExec(pwzCommand, dwTimeout, fLogCommand, fLogOutput); + ExitOnFailure(hr, "QuietExec64 Failed"); + +LExit: + ReleaseStr(pwzCommand); + + if (fRedirected) + { + WcaRevertWow64FSRedirection(); + } + + if (fIsWow64Initialized) + { + WcaFinalizeWow64(); + } + + return hr; +} + +// These two custom actions are deprecated, and should go away in wix v4.0. WixQuietExec replaces this one, +// and is not intended to have any difference in behavior apart from CA name and property names. +extern "C" UINT __stdcall CAQuietExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "CAQuietExec"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon(CAQUIET_ARGUMENTS_PROPERTY, CAQUIET_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +// 2nd deprecated custom action name, superseded by WixQuietExec64 +extern "C" UINT __stdcall CAQuietExec64( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "CAQuietExec64"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon64(CAQUIET64_ARGUMENTS_PROPERTY, CAQUIET_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon64 method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixQuietExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixQuietExec"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon(WIX_QUIET_ARGUMENTS_PROPERTY, WIX_QUIET_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixQuietExec64( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixQuietExec64"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon64(WIX_QUIET64_ARGUMENTS_PROPERTY, WIX_QUIET64_TIMEOUT_PROPERTY, TRUE, TRUE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixSilentExec( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixSilentExec"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon(WIX_SILENT_ARGUMENTS_PROPERTY, WIX_SILENT_TIMEOUT_PROPERTY, FALSE, FALSE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} + +extern "C" UINT __stdcall WixSilentExec64( + __in MSIHANDLE hInstall + ) +{ + Assert(hInstall); + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "WixSilentExec64"); + ExitOnFailure(hr, "Failed to initialize"); + + hr = ExecCommon64(WIX_SILENT64_ARGUMENTS_PROPERTY, WIX_SILENT64_TIMEOUT_PROPERTY, FALSE, FALSE); + ExitOnFailure(hr, "Failed in ExecCommon method"); + +LExit: + if (FAILED(hr)) + { + er = ERROR_INSTALL_FAILURE; + } + + return WcaFinalize(er); +} -- cgit v1.2.3-55-g6feb