[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
Mon Aug 8 15:55:36 CEST 2016


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

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 |   66 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 14 deletions(-)

diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp
index ae2b9f6..1be0350 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,63 @@ int Utility::MksTemp(char *tmpl)
 
 String Utility::GetIcingaInstallPath(void)
 {
-	char szProduct[39];
+	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. */
+	HINSTANCE hInst = LoadLibrary("msi.dll");
+	if (hInst){
+		pMsiGetProductInfo MsiGetProductInfo = (pMsiGetProductInfo)GetProcAddress(hInst, "MsiGetProductInfoA");
+		pMsiEnumProducts MsiEnumProducts = (pMsiEnumProducts)GetProcAddress(hInst, "MsiEnumProductsA");
+
+		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;
 
-	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;
 
-		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");
+		FreeLibrary(hInst);
+	}
+
+	/* It seems we either lack Msi.dll or Icinga 2 was not found installed as an MSI */
+	Log(LogDebug, "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);
+
+	/* If the executable is in the root of the volume then return immediately with an empty string */
+	if ( sizeof(path) < 4)
+		return "";
 
-	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