From ff659159e041bf6c083e6b7fcb9b726065a9dd73 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Mon, 3 May 2021 09:55:22 -0700 Subject: Move Util.wixext into ext --- src/ext/Util/ca/scamanifest.cpp | 377 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 src/ext/Util/ca/scamanifest.cpp (limited to 'src/ext/Util/ca/scamanifest.cpp') diff --git a/src/ext/Util/ca/scamanifest.cpp b/src/ext/Util/ca/scamanifest.cpp new file mode 100644 index 00000000..adb8d3d3 --- /dev/null +++ b/src/ext/Util/ca/scamanifest.cpp @@ -0,0 +1,377 @@ +// 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" + +LPCWSTR vcsPerfmonManifestQuery = L"SELECT `Component_`, `File`, `ResourceFileDirectory` FROM `Wix4PerfmonManifest`"; +LPCWSTR vcsEventManifestQuery = L"SELECT `Component_`, `File` FROM `Wix4EventManifest`"; +enum ePerfMonManifestQuery { pfmComponent = 1, pfmFile, pfmResourceFileDir }; +enum eEventManifestQuery { emComponent = 1, emFile}; + +BOOL IsVistaOrAbove() +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + #pragma warning(suppress: 4996) //TODO: use non-deprecated function to check OS version + if (!::GetVersionEx(&osvi)) + { + return false; + } + return osvi.dwMajorVersion >= 6; +} + + +/******************************************************************** + ConfigurePerfmonManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling + Perfmon counter manifest registering + +********************************************************************/ +extern "C" UINT __stdcall ConfigurePerfmonManifestRegister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzResourceFilePath = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigurePerfmonManifestReg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestRegister() because the target system does not support perfmon manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4PerfmonManifest")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestRegister() because Wix4PerfmonManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsPerfmonManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on PerfMonManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, pfmComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for PerfMonManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for PerfMonManifest"); + if (!WcaIsInstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, pfmFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for PerfMonManifest"); + + hr = WcaGetRecordFormattedString(hRec, pfmResourceFileDir, &pwzResourceFilePath); + ExitOnFailure(hr, "failed to get ApplicationIdentity for PerfMonManifest"); + size_t iResourcePath = lstrlenW(pwzResourceFilePath); + if ( iResourcePath > 0 && *(pwzResourceFilePath + iResourcePath -1) == L'\\') + *(pwzResourceFilePath + iResourcePath -1) = 0; //remove the trailing '\' + + hr = StrAllocFormatted(&pwzCommand, L"\"unlodctr.exe\" /m:\"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule RollbackRegisterPerfmonManifest action"); + + if ( *pwzResourceFilePath ) + { + hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\" \"%s\"", pwzFile, pwzResourceFilePath); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + } + else + { + hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + } + + WcaLog(LOGMSG_VERBOSE, "RegisterPerfmonManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RegisterPerfmonManifest action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing PerfMonManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzResourceFilePath); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + +/******************************************************************** + ConfigurePerfmonUninstall - CUSTOM ACTION ENTRY POINT for uninstalling + Perfmon counters + +********************************************************************/ +extern "C" UINT __stdcall ConfigurePerfmonManifestUnregister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzResourceFilePath = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigurePerfmonManifestUnreg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestUnregister() because the target system does not support perfmon manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (WcaTableExists(L"Wix4PerfmonManifest") != S_OK) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigurePerfmonManifestUnregister() because Wix4PerfmonManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsPerfmonManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4PerfmonManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, pfmComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for Wix4PerfmonManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for Wix4PerfmonManifest"); + if (!WcaIsUninstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, pfmFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for Wix4PerfmonManifest"); + + hr = WcaGetRecordFormattedString(hRec, pfmResourceFileDir, &pwzResourceFilePath); + ExitOnFailure(hr, "failed to get ApplicationIdentity for Wix4PerfmonManifest"); + size_t iResourcePath = lstrlenW(pwzResourceFilePath); + if ( iResourcePath > 0 && *(pwzResourceFilePath + iResourcePath -1) == L'\\') + *(pwzResourceFilePath + iResourcePath -1) = 0; //remove the trailing '\' + + hr = StrAllocFormatted(&pwzCommand, L"\"lodctr.exe\" /m:\"%s\" \"%s\"", pwzFile, pwzResourceFilePath); + ExitOnFailure(hr, "failed to copy string in Wix4PerfmonManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RollbackUnregisterPerfmonManifest action"); + + hr = StrAllocFormatted(&pwzCommand, L"\"unlodctr.exe\" /m:\"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in PerfMonManifest"); + + WcaLog(LOGMSG_VERBOSE, "UnRegisterPerfmonManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterPerfmonManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule UnregisterPerfmonManifest action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing PerfMonManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzResourceFilePath); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +/******************************************************************** + ConfigureEventManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling + Event manifest registering + +********************************************************************/ +extern "C" UINT __stdcall ConfigureEventManifestRegister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigureEventManifestReg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestRegister() because the target system does not support event manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4EventManifest")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestRegister() because Wix4EventManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsEventManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4EventManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, emComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for Wix4EventManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for Wix4EventManifest"); + if (!WcaIsInstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, emFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for Wix4EventManifest"); + + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" um \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackRegisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule RollbackRegisterEventManifest action"); + + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" im \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + WcaLog(LOGMSG_VERBOSE, "RegisterEventManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RegisterEventManifest"), pwzCommand, COST_EVENTMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RegisterEventManifest action"); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing Wix4EventManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + + + +/******************************************************************** + ConfigureEventManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling + Event manifest registering + +********************************************************************/ +extern "C" UINT __stdcall ConfigureEventManifestUnregister( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hView, hRec; + LPWSTR pwzData = NULL, pwzFile = NULL, pwzCommand = NULL; + INSTALLSTATE isInstalled, isAction; + + hr = WcaInitialize(hInstall, "ConfigureEventManifestUnreg"); + ExitOnFailure(hr, "Failed to initialize"); + + if (!IsVistaOrAbove()) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because the target system does not support event manifest"); + ExitFunction1(hr = S_FALSE); + } + // check to see if necessary tables are specified + if (S_OK != WcaTableExists(L"Wix4EventManifest")) + { + WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because Wix4EventManifest table not present"); + ExitFunction1(hr = S_FALSE); + } + + hr = WcaOpenExecuteView(vcsEventManifestQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4EventManifest table"); + while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) + { + // get component install state + hr = WcaGetRecordString(hRec, emComponent, &pwzData); + ExitOnFailure(hr, "failed to get Component for Wix4EventManifest"); + er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); + hr = HRESULT_FROM_WIN32(er); + ExitOnFailure(hr, "failed to get Component state for Wix4EventManifest"); + + // nothing to do on an install + // schedule the rollback action when reinstalling to re-register pre-patch manifest + if (!WcaIsUninstalling(isInstalled, isAction) && !WcaIsReInstalling(isInstalled, isAction)) + { + continue; + } + + hr = WcaGetRecordFormattedString(hRec, emFile, &pwzFile); + ExitOnFailure(hr, "failed to get File for Wix4EventManifest"); + + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" im \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackUnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); + ExitOnFailure(hr, "failed to schedule RollbackUnregisterEventManifest action"); + + // no need to uninstall on a repair/patch. Register action will re-register and update the manifest. + if (!WcaIsReInstalling(isInstalled, isAction)) + { + hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" um \"%s\"", pwzFile); + ExitOnFailure(hr, "failed to copy string in Wix4EventManifest"); + WcaLog(LOGMSG_VERBOSE, "UnregisterEventManifest's CustomActionData: '%ls'", pwzCommand); + + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"UnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); + ExitOnFailure(hr, "failed to schedule UnregisterEventManifest action"); + } + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + ExitOnFailure(hr, "Failure while processing Wix4EventManifest"); + + hr = S_OK; + +LExit: + ReleaseStr(pwzData); + ReleaseStr(pwzFile); + ReleaseStr(pwzCommand); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + -- cgit v1.2.3-55-g6feb