forked from jrsoftware/issrc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMsi.pas
90 lines (75 loc) · 3.09 KB
/
Msi.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
Inc(VersionStringSize);
SetLength(VersionString, VersionStringSize);
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.