SetupTypes.pas 8.2 KB

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