1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
/*
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later OR CPOL-1.02
*
* Parts of this file are based on:
* https://www.codeproject.com/articles/570751/devmsi-an-example-cplusplus-msi-wix-deferred-custo
*
* Licensed under the The Code Project Open License (CPOL):
* https://www.codeproject.com/info/cpol10.aspx
*/
#include "NCMsiHelper.h"
/**
* Sets up logging for MSIs and then calls the appropriate custom action with argc/argv parameters.
*
* MSI deferred custom action dlls have to handle parameters (properties) a little differently,
* since the deferred action may not have an active session when it begins. Since the easiest
* way to pass parameter(s) is to put them all into a CustomActionData property and then retrieve it,
* the easiest thing to do on this ( C/C++ ) end is to pull the parameter and then split it into
* a list of parameter(s) that we need.
*
* For this implementation, it made sense to treat the single string provided in CustomActionData
* as if it were a command line, and then parse it out just as if it were a command line. Obviously,
* the "program name" isn't going to be the first argument unless the MSI writer is pedantic, but
* otherwise it seems to be a good way to do it.
*
* Since all entry points need to do this same work, it was easiest to have a single function that
* would do the setup, pull the CustomActionData parameter, split it into an argc/argv style of
* argument list, and then pass that argument list into a function that actually does something
* interesting.
*
* @param hInstall The hInstall parameter provided by MSI/WiX.
* @param func The function to be called with argc/argv parameters.
* @param actionName The text description of the function. It will be put in the log.
* @return Returns ERROR_SUCCESS or ERROR_INSTALL_FAILURE.
*/
UINT CustomActionArgcArgv(MSIHANDLE hInstall, CUSTOM_ACTION_ARGC_ARGV func, LPCSTR actionName)
{
LPWSTR pszCustomActionData = nullptr, *argv = nullptr;
HRESULT hr = WcaInitialize(hInstall, actionName);
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
// Retrieve our custom action property. This is one of
// only three properties we can request on a Deferred
// Custom Action. So, we assume the caller puts all
// parameters in this one property.
hr = WcaGetProperty(L"CustomActionData", &pszCustomActionData);
ExitOnFailure(hr, "Failed to get Custom Action Data.");
WcaLog(LOGMSG_STANDARD, "Custom Action Data = '%ls'.", pszCustomActionData);
// Convert the string retrieved into a standard argc/arg layout
// (ignoring the fact that the first parameter is whatever was
// passed, not necessarily the application name/path).
int argc = 0;
argv = CommandLineToArgvW(pszCustomActionData, &argc);
if (argv) {
hr = HRESULT_FROM_WIN32(GetLastError());
ExitOnFailure(hr, "Failed to convert Custom Action Data to argc/argv.");
}
hr = (func)(argc, argv);
ExitOnFailure(hr, "Custom action failed");
LExit:
// Resource freeing here!
ReleaseStr(pszCustomActionData);
if (argv)
LocalFree(argv);
return WcaFinalize(SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE);
}
UINT __stdcall ExecNsisUninstaller(MSIHANDLE hInstall)
{
return CustomActionArgcArgv(hInstall, DoExecNsisUninstaller, "ExecNsisUninstaller");
}
UINT __stdcall RemoveNavigationPaneEntries(MSIHANDLE hInstall)
{
return CustomActionArgcArgv(hInstall, DoRemoveNavigationPaneEntries, "RemoveNavigationPaneEntries");
}
/**
* DllMain - Initialize and cleanup WiX custom action utils.
*/
extern "C" BOOL WINAPI DllMain(
__in HINSTANCE hInst,
__in ULONG ulReason,
__in LPVOID
)
{
switch(ulReason)
{
case DLL_PROCESS_ATTACH:
WcaGlobalInitialize(hInst);
break;
case DLL_PROCESS_DETACH:
WcaGlobalFinalize();
break;
}
return TRUE;
}
|