Msgs.pas 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. unit Msgs;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2007 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Message file handling functions
  8. $jrsoftware: issrc/Projects/Msgs.pas,v 1.20 2009/03/23 13:31:17 mlaan Exp $
  9. }
  10. interface
  11. uses
  12. MsgIDs, Struct;
  13. const
  14. SNewLine = #13#10; { line break }
  15. SNewLine2 = #13#10#13#10; { double line break }
  16. var
  17. SetupMessages: array[TSetupMessageID] of String;
  18. MessagesLangOptions: TMessagesLangOptions;
  19. function FmtMessage(S: PChar; const Args: array of String): String;
  20. function FmtSetupMessage(const ID: TSetupMessageID; const Args: array of String): String;
  21. function FmtSetupMessage1(const ID: TSetupMessageID; const Arg1: String): String;
  22. procedure AssignSetupMessages(const P; const Size: Cardinal);
  23. procedure LoadSetupMessages(const Filename: String; const Offset: Cardinal;
  24. const LoadMessagesLangOptions: Boolean);
  25. function IntToHexStr8(I: Integer): String;
  26. const
  27. { You don't have to translate these. The only time they are used is when an
  28. error occurs before or while the messages file is loaded. Otherwise, it
  29. uses the corresponding messages in the messages file. }
  30. SSetupFileMissing = 'The file %1 is missing from the installation directory. ' +
  31. 'Please correct the problem or obtain a new copy of the program.';
  32. SSetupFileCorrupt = 'The setup files are corrupted. Please obtain a new ' +
  33. 'copy of the program.';
  34. SSetupFileCorruptOrWrongVer = 'The setup files are corrupted, or are ' +
  35. 'incompatible with this version of Setup. Please correct the problem or ' +
  36. 'obtain a new copy of the program.';
  37. SMsgsFileMissing = 'Messages file "%s" is missing. Please correct ' +
  38. 'the problem or obtain a new copy of the program.';
  39. implementation
  40. uses
  41. Windows, SysUtils, Compress, CmnFunc2, FileClass;
  42. const
  43. SMsgsFileTooLarge = 'Internal error: Messages file is too large';
  44. function FmtMessage(S: PChar; const Args: array of String): String;
  45. var
  46. P: PChar;
  47. Z: String;
  48. begin
  49. Result := '';
  50. if S = nil then Exit;
  51. while True do begin
  52. P := StrScan(S, '%');
  53. if P = nil then begin
  54. Result := Result + S;
  55. Break;
  56. end;
  57. if P <> S then begin
  58. SetString(Z, S, P - S);
  59. Result := Result + Z;
  60. S := P;
  61. end;
  62. Inc(P);
  63. if CharInSet(P^, ['1'..'9']) and (Ord(P^) - Ord('1') <= High(Args)) then begin
  64. Result := Result + Args[Ord(P^) - Ord('1')];
  65. Inc(S, 2);
  66. end
  67. else begin
  68. Result := Result + '%';
  69. Inc(S);
  70. if P^ = '%' then
  71. Inc(S);
  72. end;
  73. end;
  74. end;
  75. function FmtSetupMessage(const ID: TSetupMessageID; const Args: array of String): String;
  76. begin
  77. Result := FmtMessage(PChar(SetupMessages[ID]), Args);
  78. end;
  79. function FmtSetupMessage1(const ID: TSetupMessageID; const Arg1: String): String;
  80. begin
  81. Result := FmtSetupMessage(ID, [Arg1]);
  82. end;
  83. procedure FreeSetupMessages;
  84. var
  85. I: TSetupMessageID;
  86. begin
  87. for I := Low(SetupMessages) to High(SetupMessages) do
  88. SetupMessages[I] := '';
  89. end;
  90. procedure Corrupted;
  91. begin
  92. raise Exception.Create(SSetupFileCorrupt);
  93. end;
  94. procedure AssignSetupMessages(const P; const Size: Cardinal);
  95. { Takes message data, and assigns the individual messages to SetupMessages. }
  96. var
  97. Header: ^TMessagesHeader;
  98. M, EndP: PChar;
  99. I: TSetupMessageID;
  100. L: Integer;
  101. begin
  102. if (Size <= SizeOf(TMessagesHdrID) + SizeOf(TMessagesHeader)) or
  103. (TMessagesHdrID(P) <> MessagesHdrID) then
  104. Corrupted;
  105. Cardinal(Header) := Cardinal(@P) + SizeOf(TMessagesHdrID);
  106. if (Header.TotalSize <> not Header.NotTotalSize) or
  107. (Cardinal(Header.TotalSize) <> Size) or
  108. (Header.NumMessages <> (Ord(High(SetupMessages)) - Ord(Low(SetupMessages)) + 1)) then
  109. Corrupted;
  110. Cardinal(M) := Cardinal(Header) + SizeOf(TMessagesHeader);
  111. Cardinal(EndP) := Cardinal(@P) + Cardinal(Header.TotalSize);
  112. if (GetCRC32(M^, (EndP - M) * SizeOf(Char)) <> Header.CRCMessages) or
  113. (EndP[-1] <> #0) then
  114. Corrupted;
  115. for I := Low(SetupMessages) to High(SetupMessages) do begin
  116. if M >= EndP then
  117. Corrupted;
  118. L := StrLen(M);
  119. SetString(SetupMessages[I], M, L);
  120. Inc(M, L + 1);
  121. end;
  122. end;
  123. procedure LoadSetupMessages(const Filename: String; const Offset: Cardinal;
  124. const LoadMessagesLangOptions: Boolean);
  125. { Loads Setup messages from an uncompressed file }
  126. var
  127. F: TFile;
  128. TestID: TMessagesHdrID;
  129. Header: TMessagesHeader;
  130. P: Pointer;
  131. begin
  132. FreeSetupMessages;
  133. if not NewFileExists(Filename) then
  134. raise Exception.CreateFmt(SMsgsFileMissing, [Filename]);
  135. F := TFile.Create(Filename, fdOpenExisting, faRead, fsRead);
  136. try
  137. F.Seek(Offset);
  138. if F.Read(TestID, SizeOf(TestID)) <> SizeOf(TestID) then
  139. Corrupted;
  140. if TestID <> MessagesHdrID then
  141. Corrupted;
  142. if F.Read(Header, SizeOf(Header)) <> SizeOf(Header) then
  143. Corrupted;
  144. if (Header.TotalSize <> not Header.NotTotalSize) or
  145. (Header.TotalSize <= SizeOf(TestID) + SizeOf(Header)) or
  146. (Header.NumMessages <> (Ord(High(SetupMessages)) - Ord(Low(SetupMessages)) + 1)) then
  147. Corrupted;
  148. F.Seek(Offset);
  149. GetMem(P, Header.TotalSize);
  150. try
  151. if F.Read(P^, Header.TotalSize) <> Header.TotalSize then
  152. Corrupted;
  153. AssignSetupMessages(P^, Header.TotalSize);
  154. finally
  155. FreeMem(P);
  156. end;
  157. if LoadMessagesLangOptions then begin
  158. if F.Read(MessagesLangOptions, SizeOf(MessagesLangOptions)) <> SizeOf(MessagesLangOptions) then
  159. Corrupted;
  160. if MessagesLangOptions.ID <> MessagesLangOptionsID then
  161. Corrupted;
  162. end;
  163. finally
  164. F.Free;
  165. end;
  166. end;
  167. function IntToHexStr8(I: Integer): String;
  168. begin
  169. FmtStr(Result, '0x%.8x', [I]);
  170. end;
  171. initialization
  172. finalization
  173. FreeSetupMessages;
  174. end.