|
@@ -0,0 +1,89 @@
|
|
|
+unit Msi;
|
|
|
+
|
|
|
+{
|
|
|
+ Inno Setup
|
|
|
+ Copyright (C) 1997-2020 Jordan Russell
|
|
|
+ Portions by Martijn Laan
|
|
|
+ For conditions of distribution and use, see LICENSE.TXT.
|
|
|
+
|
|
|
+ MSI functions
|
|
|
+}
|
|
|
+
|
|
|
+interface
|
|
|
+
|
|
|
+function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64; var ErrorCode: Cardinal): Boolean;
|
|
|
+
|
|
|
+implementation
|
|
|
+
|
|
|
+uses
|
|
|
+ Windows, SysUtils, CmnFunc2, PathFunc, VerInfo;
|
|
|
+
|
|
|
+var
|
|
|
+ MsiLoaded: Boolean;
|
|
|
+ MsiLibrary: HMODULE;
|
|
|
+ MsiEnumRelatedProductsFunc: function(lpUpgradeCode: PChar; dwReserved, iProductIndex: DWORD; lpProductBuf: PChar): UINT; stdcall;
|
|
|
+ MsiGetProductInfoFunc: function(szProduct, szAttribute, lpValueBuf: PChar; var pcchValueBuf: DWORD): UINT; stdcall;
|
|
|
+ MsiLibraryLastError, MsiEnumRelatedProductsFuncLastError, MsiGetProductInfoFuncLastError: Cardinal;
|
|
|
+
|
|
|
+function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64; var ErrorCode: Cardinal): Boolean;
|
|
|
+var
|
|
|
+ ProductCode: array[0..38] of Char;
|
|
|
+ VersionStringSize: DWORD;
|
|
|
+ VersionString: String;
|
|
|
+ VersionNumbers: TFileVersionNumbers;
|
|
|
+ PackedVersion: Int64;
|
|
|
+begin
|
|
|
+ Result := False;
|
|
|
+
|
|
|
+ if not MsiLoaded then begin
|
|
|
+ MsiLibrary := SafeLoadLibrary(AddBackslash(GetSystemDir) + 'msi.dll', SEM_NOOPENFILEERRORBOX);
|
|
|
+ if MsiLibrary <> 0 then begin
|
|
|
+ MsiEnumRelatedProductsFunc := GetProcAddress(MsiLibrary, 'MsiEnumRelatedProductsW');
|
|
|
+ MsiEnumRelatedProductsFuncLastError := GetLastError;
|
|
|
+ MsiGetProductInfoFunc := GetProcAddress(MsiLibrary, 'MsiGetProductInfoW');
|
|
|
+ MsiGetProductInfoFuncLastError := GetLastError;
|
|
|
+ end else
|
|
|
+ MsiLibraryLastError := GetLastError;
|
|
|
+ MsiLoaded := True;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if MsiLibrary = 0 then
|
|
|
+ ErrorCode := MsiLibraryLastError
|
|
|
+ else if not Assigned(MsiEnumRelatedProductsFunc) then
|
|
|
+ ErrorCode := MsiEnumRelatedProductsFuncLastError
|
|
|
+ else if not Assigned(MsiGetProductInfoFunc) then
|
|
|
+ ErrorCode := MsiGetProductInfoFuncLastError
|
|
|
+ else
|
|
|
+ ErrorCode := ERROR_SUCCESS;
|
|
|
+ if ErrorCode <> ERROR_SUCCESS then
|
|
|
+ Exit;
|
|
|
+
|
|
|
+ ErrorCode := MsiEnumRelatedProductsFunc(PChar(UpgradeCode), 0, 0, ProductCode);
|
|
|
+ if ErrorCode <> ERROR_SUCCESS then begin
|
|
|
+ if ErrorCode = ERROR_NO_MORE_ITEMS then
|
|
|
+ ErrorCode := ERROR_SUCCESS; { Not installed so should just return False without an error }
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+
|
|
|
+ VersionStringSize := 16;
|
|
|
+ SetLength(VersionString, VersionStringSize);
|
|
|
+ ErrorCode := MsiGetProductInfoFunc(ProductCode, 'VersionString', PChar(VersionString), VersionStringSize);
|
|
|
+ if ErrorCode = ERROR_MORE_DATA then begin
|
|
|
+ SetLength(VersionString, VersionStringSize+1);
|
|
|
+ ErrorCode := MsiGetProductInfoFunc(ProductCode, 'VersionString', PChar(VersionString), VersionStringSize);
|
|
|
+ end;
|
|
|
+ if ErrorCode <> ERROR_SUCCESS then
|
|
|
+ Exit;
|
|
|
+ SetLength(VersionString, VersionStringSize);
|
|
|
+
|
|
|
+ if not StrToVersionNumbers(VersionString, VersionNumbers) then begin
|
|
|
+ ErrorCode := ERROR_BAD_FORMAT;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+
|
|
|
+ PackedVersion := (Int64(VersionNumbers.MS) shl 32) or VersionNumbers.LS;
|
|
|
+ Result := PackedVersion >= PackedMinVersion;
|
|
|
+ ErrorCode := ERROR_SUCCESS;
|
|
|
+end;
|
|
|
+
|
|
|
+end.
|