// 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); }