SetupTypes.pas 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. unit SetupTypes;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2018 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Types and functions used by both ISCmplr-only and Setup-only units
  8. }
  9. interface
  10. uses
  11. SysUtils, Classes, Struct;
  12. type
  13. TSetupStep = (ssPreInstall, ssInstall, ssPostInstall, ssDone);
  14. TUninstallStep = (usAppMutexCheck, usUninstall, usPostUninstall, usDone);
  15. const
  16. { Predefined page identifiers }
  17. wpWelcome = 1;
  18. wpLicense = 2;
  19. wpPassword = 3;
  20. wpInfoBefore = 4;
  21. wpUserInfo = 5;
  22. wpSelectDir = 6;
  23. wpSelectComponents = 7;
  24. wpSelectProgramGroup = 8;
  25. wpSelectTasks = 9;
  26. wpReady = 10;
  27. wpPreparing = 11;
  28. wpInstalling = 12;
  29. wpInfoAfter = 13;
  30. wpFinished = 14;
  31. type
  32. TInstallOnThisVersionResult = (irInstall, irNotOnThisPlatform,
  33. irVersionTooLow, irServicePackTooLow, irVerTooHigh);
  34. TRenamedConstantCallBack = procedure(const Cnst, CnstRenamed: String) of object;
  35. const
  36. crHand = 1;
  37. CodeRootKeyFlagMask = $7F000000;
  38. CodeRootKeyFlag32Bit = $01000000;
  39. CodeRootKeyFlag64Bit = $02000000;
  40. CodeRootKeyValidFlags = CodeRootKeyFlag32Bit or CodeRootKeyFlag64Bit;
  41. HKEY_AUTO = 1; { Any value will work as long as it isn't 0 and doesn't match a predefined key handle (8xxxxxxx) nor includes any of the CodeRootKeyValidFlags flags. }
  42. function StringsToCommaString(const Strings: TStrings): String;
  43. procedure SetStringsFromCommaString(const Strings: TStrings; const Value: String);
  44. function StrToSetupVersionData(const S: String; var VerData: TSetupVersionData): Boolean;
  45. procedure HandleRenamedConstants(var Cnst: String; const RenamedConstantCallback: TRenamedConstantCallback);
  46. implementation
  47. uses
  48. CmnFunc2;
  49. function QuoteStringIfNeeded(const S: String): String;
  50. { Used internally by StringsToCommaString. Adds quotes around the string if
  51. needed, and doubles any embedded quote characters.
  52. Note: No lead byte checking is done since spaces/commas/quotes aren't used
  53. as trail bytes in any of the Far East code pages (CJK). }
  54. var
  55. Len, QuoteCount, I: Integer;
  56. HasSpecialChars: Boolean;
  57. P: PChar;
  58. begin
  59. Len := Length(S);
  60. HasSpecialChars := False;
  61. QuoteCount := 0;
  62. for I := 1 to Len do begin
  63. case S[I] of
  64. #0..' ', ',': HasSpecialChars := True;
  65. '"': Inc(QuoteCount);
  66. end;
  67. end;
  68. if not HasSpecialChars and (QuoteCount = 0) then begin
  69. Result := S;
  70. Exit;
  71. end;
  72. SetString(Result, nil, Len + QuoteCount + 2);
  73. P := Pointer(Result);
  74. P^ := '"';
  75. Inc(P);
  76. for I := 1 to Len do begin
  77. if S[I] = '"' then begin
  78. P^ := '"';
  79. Inc(P);
  80. end;
  81. P^ := S[I];
  82. Inc(P);
  83. end;
  84. P^ := '"';
  85. end;
  86. function StringsToCommaString(const Strings: TStrings): String;
  87. { Creates a comma-delimited string from Strings.
  88. Note: Unlike Delphi 2's TStringList.CommaText property, this function can
  89. handle an unlimited number of characters. }
  90. var
  91. I: Integer;
  92. S: String;
  93. begin
  94. if (Strings.Count = 1) and (Strings[0] = '') then
  95. Result := '""'
  96. else begin
  97. Result := '';
  98. for I := 0 to Strings.Count-1 do begin
  99. S := QuoteStringIfNeeded(Strings[I]);
  100. if I = 0 then
  101. Result := S
  102. else
  103. Result := Result + ',' + S;
  104. end;
  105. end;
  106. end;
  107. procedure SetStringsFromCommaString(const Strings: TStrings; const Value: String);
  108. { Replaces Strings with strings from the comma- or space-delimited Value.
  109. Note: No lead byte checking is done since spaces/commas/quotes aren't used
  110. as trail bytes in any of the Far East code pages (CJK).
  111. Also, this isn't bugged like Delphi 3+'s TStringList.CommaText property --
  112. SetStringsFromCommaString(..., 'a,') will add two items, not one. }
  113. var
  114. P, PStart, PDest: PChar;
  115. CharCount: Integer;
  116. S: String;
  117. begin
  118. Strings.BeginUpdate;
  119. try
  120. Strings.Clear;
  121. P := PChar(Value);
  122. while CharInSet(P^, [#1..' ']) do
  123. Inc(P);
  124. if P^ <> #0 then begin
  125. while True do begin
  126. if P^ = '"' then begin
  127. Inc(P);
  128. PStart := P;
  129. CharCount := 0;
  130. while P^ <> #0 do begin
  131. if P^ = '"' then begin
  132. Inc(P);
  133. if P^ <> '"' then Break;
  134. end;
  135. Inc(CharCount);
  136. Inc(P);
  137. end;
  138. P := PStart;
  139. SetString(S, nil, CharCount);
  140. PDest := Pointer(S);
  141. while P^ <> #0 do begin
  142. if P^ = '"' then begin
  143. Inc(P);
  144. if P^ <> '"' then Break;
  145. end;
  146. PDest^ := P^;
  147. Inc(P);
  148. Inc(PDest);
  149. end;
  150. end
  151. else begin
  152. PStart := P;
  153. while (P^ > ' ') and (P^ <> ',') do
  154. Inc(P);
  155. SetString(S, PStart, P - PStart);
  156. end;
  157. Strings.Add(S);
  158. while CharInSet(P^, [#1..' ']) do
  159. Inc(P);
  160. if P^ = #0 then
  161. Break;
  162. if P^ = ',' then begin
  163. repeat
  164. Inc(P);
  165. until not CharInSet(P^, [#1..' ']);
  166. end;
  167. end;
  168. end;
  169. finally
  170. Strings.EndUpdate;
  171. end;
  172. end;
  173. function StrToSetupVersionData(const S: String; var VerData: TSetupVersionData): Boolean;
  174. procedure Split(const Str: String; var Ver: TSetupVersionDataVersion;
  175. var ServicePack: Word);
  176. var
  177. I, J: Integer;
  178. Z, B: String;
  179. HasBuild: Boolean;
  180. begin
  181. Cardinal(Ver) := 0;
  182. ServicePack := 0;
  183. Z := Lowercase(Str);
  184. I := Pos('sp', Z);
  185. if I <> 0 then begin
  186. J := StrToInt(Copy(Z, I+2, Maxint));
  187. if (J < Low(Byte)) or (J > High(Byte)) then
  188. Abort;
  189. ServicePack := J shl 8;
  190. { ^ Shift left 8 bits because we're setting the "major" service pack
  191. version number. This parser doesn't currently accept "minor" service
  192. pack version numbers. }
  193. SetLength(Z, I-1);
  194. end;
  195. I := Pos('.', Z);
  196. if I = Length(Z) then Abort;
  197. if I <> 0 then begin
  198. J := StrToInt(Copy(Z, 1, I-1));
  199. if (J < 0) or (J > 127) then
  200. Abort;
  201. Ver.Major := J;
  202. Z := Copy(Z, I+1, Maxint);
  203. I := Pos('.', Z);
  204. HasBuild := I <> 0;
  205. if not HasBuild then
  206. I := Length(Z)+1;
  207. B := Copy(Z, I+1, Maxint);
  208. Z := Copy(Z, 1, I-1);
  209. J := StrToInt(Z);
  210. if (J < 0) or (J > 99) then Abort;
  211. Ver.Minor := J;
  212. if HasBuild then begin
  213. J := StrToInt(B);
  214. if (J < Low(Ver.Build)) or (J > High(Ver.Build)) then
  215. Abort;
  216. Ver.Build := J;
  217. end;
  218. end
  219. else begin { no minor version specified }
  220. J := StrToInt(Z);
  221. if (J < 0) or (J > 127) then
  222. Abort;
  223. Ver.Major := J;
  224. end;
  225. end;
  226. var
  227. I: Integer;
  228. SP: Word;
  229. begin
  230. try
  231. VerData.WinVersion := 0;
  232. I := Pos(',', S);
  233. if I <> 0 then begin
  234. Split(Trim(Copy(S, 1, I-1)),
  235. TSetupVersionDataVersion(VerData.WinVersion), SP);
  236. if SP <> 0 then Abort; { only NT has service packs }
  237. end;
  238. Split(Trim(Copy(S, I+1, Maxint)),
  239. TSetupVersionDataVersion(VerData.NTVersion), VerData.NTServicePack);
  240. Result := True;
  241. except
  242. if (ExceptObject is EAbort) or (ExceptObject is EConvertError) then
  243. Result := False
  244. else
  245. raise;
  246. end;
  247. end;
  248. procedure HandleRenamedConstants(var Cnst: String; const RenamedConstantCallback: TRenamedConstantCallback);
  249. var
  250. CnstRenamed: String;
  251. begin
  252. if Cnst = 'fonts' then
  253. CnstRenamed := 'commonfonts'
  254. else if Cnst = 'sendto' then
  255. CnstRenamed := 'usersendto'
  256. else if Cnst = 'pf' then
  257. CnstRenamed := 'commonpf'
  258. else if Cnst = 'pf32' then
  259. CnstRenamed := 'commonpf32'
  260. else if Cnst = 'pf64' then
  261. CnstRenamed := 'commonpf64'
  262. else if Cnst = 'cf' then
  263. CnstRenamed := 'commoncf'
  264. else if Cnst = 'cf32' then
  265. CnstRenamed := 'commoncf32'
  266. else if Cnst = 'cf64' then
  267. CnstRenamed := 'commoncf64'
  268. else
  269. CnstRenamed := '';
  270. if CnstRenamed <> '' then begin
  271. if Assigned(RenamedConstantCallback) then
  272. RenamedConstantCallback(Cnst, CnstRenamed);
  273. Cnst := CnstRenamed;
  274. end;
  275. end;
  276. end.