[icinga-checkins] icinga.org: icinga2/feature/wsa-12128: Add a fallback incase Msi.dll is not available

git at icinga.org git at icinga.org
Sat Aug 6 11:30:24 CEST 2016


Module: icinga2
Branch: feature/wsa-12128
Commit: 662a1340560e203a804e66f93cf155a918dd14f0
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=662a1340560e203a804e66f93cf155a918dd14f0

Author: Rune Darrud <theflyingcorpse at gmail.com>
Date:   Sat Aug  6 01:20:36 2016 +0200

Add a fallback incase Msi.dll is not available

refs #12128

---

 lib/base/utility.cpp |   74 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 58 insertions(+), 16 deletions(-)

diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp
index ae2b9f6..af0ab7d 100644
--- a/lib/base/utility.cpp
+++ b/lib/base/utility.cpp
@@ -55,7 +55,6 @@
 #	include <VersionHelpers.h>
 #	include <windows.h>
 #	include <io.h>
-#	include <msi.h>
 #	include <shlobj.h>
 #endif /*_WIN32*/
 
@@ -1900,24 +1899,67 @@ int Utility::MksTemp(char *tmpl)
 
 String Utility::GetIcingaInstallPath(void)
 {
-	char szProduct[39];
-
-	for (int i = 0; MsiEnumProducts(i, szProduct) == ERROR_SUCCESS; i++) {
-		char szName[128];
-		DWORD cbName = sizeof(szName);
-		if (MsiGetProductInfo(szProduct, INSTALLPROPERTY_INSTALLEDPRODUCTNAME, szName, &cbName) != ERROR_SUCCESS)
-			continue;
-
-		if (strcmp(szName, "Icinga 2") != 0)
-			continue;
+	typedef long(__stdcall *pMsiGetProductInfo)(
+		char szProduct[39], 
+		char szProperty[65535], 
+		char lpValueBuf[65535], 
+		DWORD *pcchValueBuf);
+	typedef long(__stdcall *pMsiEnumProducts)(
+		DWORD iProductIndex,
+		char lpProductBuf[65535]);
+	
+	/* First lets see if Icinga2 is installed using the Msi
+	   If debugging Icinga2 using Visual Studio, this must be done to get the registry setup. */
+	if (HINSTANCE hInst = LoadLibrary("msi.dll")){
+		pMsiGetProductInfo MsiGetProductInfo = (pMsiGetProductInfo)GetProcAddress(hInst, "MsiGetProductInfoA");
+		pMsiEnumProducts MsiEnumProducts = (pMsiEnumProducts)GetProcAddress(hInst, "MsiEnumProductsA");
+
+		if (MsiGetProductInfo && MsiEnumProducts) {
+			char szProduct[39];
+
+			for (int i = 0; MsiEnumProducts(i, szProduct) == ERROR_SUCCESS; i++) {
+
+				char szName[128];
+				DWORD cbName = sizeof(szName);
+				// INSTALLPROPERTY_INSTALLEDPRODUCTNAME from msi.h is hardcoded here as InstalledProductName
+				if (MsiGetProductInfo(szProduct, "InstalledProductName", szName, &cbName) != ERROR_SUCCESS)
+					continue;
+
+				if (strcmp(szName, "Icinga 2") != 0)
+					continue;
+
+				char szLocation[1024];
+				DWORD cbLocation = sizeof(szLocation);
+				// INSTALLPROPERTY_INSTALLLOCATION from msi.h is hardcoded here as InstallLocation
+				if (MsiGetProductInfo(szProduct, "InstallLocation", szLocation, &cbLocation) == ERROR_SUCCESS)
+					FreeLibrary(hInst);
+					return szLocation;
+			}
+			Log(LogWarning, "utility", "Unable to find 'Icinga 2' installed as an MSI");
+		}
+		else {
+			Log(LogInformation, "utility", "Unable to load Msi.dll functions to find 'Icinga 2' install path");
+		}
+		FreeLibrary(hInst);
+	}
+	
+	/* It seems we either lack Msi.dll or Icinga 2 was not found installed as an MSI */
+	Log(LogInformation, "utility", "Using fallback to find the Icinga2 install path");
 
-		char szLocation[1024];
-		DWORD cbLocation = sizeof(szLocation);
-		if (MsiGetProductInfo(szProduct, INSTALLPROPERTY_INSTALLLOCATION, szLocation, &cbLocation) == ERROR_SUCCESS)
-			return szLocation;
+	char result[MAX_PATH + 1];
+	if (GetModuleFileName(NULL, result, MAX_PATH)== 0) {
+		return "";
 	}
+	std::string strExe = result;
+	/* Get the directory of the executable */
+	std::string path = Utility::DirName(strExe);
 
-	return "";
+	/* If the executable is in the root of the volume then return immediately with an empty string */
+	if ( sizeof(path) < 4)
+		return "";
+		
+	/* Return the parent directory of the current directory */
+	return Utility::DirName(path);
 }
 
 String Utility::GetIcingaDataPath(void)



More information about the icinga-checkins mailing list