Setup.MsiFunc.pas 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. unit Setup.MsiFunc;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2020 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. MSI functions
  8. }
  9. interface
  10. function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64; var ErrorCode: Cardinal): Boolean;
  11. implementation
  12. uses
  13. Windows, SysUtils, Shared.CommonFunc, PathFunc, Shared.VerInfoFunc;
  14. var
  15. MsiLoaded: Boolean;
  16. MsiLibrary: HMODULE;
  17. MsiEnumRelatedProductsFunc: function(lpUpgradeCode: PChar; dwReserved, iProductIndex: DWORD; lpProductBuf: PChar): UINT; stdcall;
  18. MsiGetProductInfoFunc: function(szProduct, szAttribute, lpValueBuf: PChar; var pcchValueBuf: DWORD): UINT; stdcall;
  19. MsiLibraryLastError, MsiEnumRelatedProductsFuncLastError, MsiGetProductInfoFuncLastError: Cardinal;
  20. function IsMsiProductInstalled(const UpgradeCode: String; const PackedMinVersion: Int64; var ErrorCode: Cardinal): Boolean;
  21. var
  22. ProductCode: array[0..38] of Char;
  23. VersionStringSize: DWORD;
  24. VersionString: String;
  25. VersionNumbers: TFileVersionNumbers;
  26. PackedVersion: Int64;
  27. begin
  28. Result := False;
  29. if not MsiLoaded then begin
  30. MsiLibrary := SafeLoadLibrary(AddBackslash(GetSystemDir) + 'msi.dll', SEM_NOOPENFILEERRORBOX);
  31. if MsiLibrary <> 0 then begin
  32. MsiEnumRelatedProductsFunc := GetProcAddress(MsiLibrary, 'MsiEnumRelatedProductsW');
  33. MsiEnumRelatedProductsFuncLastError := GetLastError;
  34. MsiGetProductInfoFunc := GetProcAddress(MsiLibrary, 'MsiGetProductInfoW');
  35. MsiGetProductInfoFuncLastError := GetLastError;
  36. end else
  37. MsiLibraryLastError := GetLastError;
  38. MsiLoaded := True;
  39. end;
  40. if MsiLibrary = 0 then
  41. ErrorCode := MsiLibraryLastError
  42. else if not Assigned(MsiEnumRelatedProductsFunc) then
  43. ErrorCode := MsiEnumRelatedProductsFuncLastError
  44. else if not Assigned(MsiGetProductInfoFunc) then
  45. ErrorCode := MsiGetProductInfoFuncLastError
  46. else
  47. ErrorCode := ERROR_SUCCESS;
  48. if ErrorCode <> ERROR_SUCCESS then
  49. Exit;
  50. ErrorCode := MsiEnumRelatedProductsFunc(PChar(UpgradeCode), 0, 0, ProductCode);
  51. if ErrorCode <> ERROR_SUCCESS then begin
  52. if ErrorCode = ERROR_NO_MORE_ITEMS then
  53. ErrorCode := ERROR_SUCCESS; { Not installed so should just return False without an error }
  54. Exit;
  55. end;
  56. VersionStringSize := 16;
  57. SetLength(VersionString, VersionStringSize);
  58. ErrorCode := MsiGetProductInfoFunc(ProductCode, 'VersionString', PChar(VersionString), VersionStringSize);
  59. if ErrorCode = ERROR_MORE_DATA then begin
  60. Inc(VersionStringSize);
  61. SetLength(VersionString, VersionStringSize);
  62. ErrorCode := MsiGetProductInfoFunc(ProductCode, 'VersionString', PChar(VersionString), VersionStringSize);
  63. end;
  64. if ErrorCode <> ERROR_SUCCESS then
  65. Exit;
  66. SetLength(VersionString, VersionStringSize);
  67. if not StrToVersionNumbers(VersionString, VersionNumbers) then begin
  68. ErrorCode := ERROR_BAD_FORMAT;
  69. Exit;
  70. end;
  71. PackedVersion := (Int64(VersionNumbers.MS) shl 32) or VersionNumbers.LS;
  72. Result := PackedVersion >= PackedMinVersion;
  73. ErrorCode := ERROR_SUCCESS;
  74. end;
  75. end.