chmspecialfiles.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. { Copyright (C) <2005> <Andrew Haines> chmspecialfiles.pas
  2. This library is free software; you can redistribute it and/or modify it
  3. under the terms of the GNU Library General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or (at your
  5. option) any later version.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  8. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  9. for more details.
  10. You should have received a copy of the GNU Library General Public License
  11. along with this library; if not, write to the Free Software Foundation,
  12. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  13. }
  14. {
  15. See the file COPYING.FPC, included in this distribution,
  16. for details about the copyright.
  17. }
  18. unit chmspecialfiles;
  19. {$mode objfpc}{$H+}
  20. interface
  21. uses
  22. Classes, SysUtils, chmtypes;
  23. function WriteNameListToStream(const AStream: TStream; SectionNames: TSectionNames): Integer;
  24. function WriteControlDataToStream(const AStream: TStream; const LZXResetInterval, WindowSize, CacheSize: DWord): Integer;
  25. function WriteSpanInfoToStream(const AStream: TStream; UncompressedSize: QWord): Integer;
  26. function WriteTransformListToStream(const AStream: TStream): Integer;
  27. function WriteResetTableToStream(const AStream: TStream; ResetTableStream: TMemoryStream): Integer;
  28. function WriteContentToStream(const AStream: TStream; ContentStream: TMemoryStream): Integer;
  29. implementation
  30. function WriteNameListToStream(const AStream: TStream; SectionNames: TSectionNames): Integer;
  31. var
  32. MSCompressedName: WideString = 'MSCompressed'#0; // Length 13
  33. UnCompressedName: WideString = 'Uncompressed'#0;
  34. I: Integer;
  35. Size: Word = 2;
  36. NEntries: Word = 0;
  37. begin
  38. // ::DataSpace/NameList
  39. {$IFDEF ENDIAN_BIG}
  40. for I := 1 to 13 do begin
  41. PWord(@MSCompressedName[I])^ := NToLE(PWord(@MSCompressedName[I])^);
  42. PWord(@UnCompressedName[I])^ := NToLE(PWord(@UnCompressedName[I])^);
  43. end;
  44. {$ENDIF}
  45. if snUnCompressed in SectionNames then begin
  46. Inc(Size, 14);
  47. Inc(NEntries);
  48. end;
  49. if snMSCompressed in SectionNames then begin
  50. Inc(Size, 14);
  51. Inc(NEntries);
  52. end;
  53. AStream.WriteWord(NToLE(Size));
  54. AStream.WriteWord(NToLE(NEntries));
  55. if snUnCompressed in SectionNames then begin
  56. AStream.WriteWord(NToLE(Word(12)));
  57. AStream.Write(UnCompressedName[1], 13*2);
  58. end;
  59. if snMSCompressed in SectionNames then begin
  60. AStream.WriteWord(NToLE(Word(12)));
  61. AStream.Write(MSCompressedName[1], 13*2);
  62. end;
  63. Result := Size * SizeOf(Word);
  64. end;
  65. function WriteControlDataToStream(const AStream: TStream; const LZXResetInterval,
  66. WindowSize, CacheSize: DWord): Integer;
  67. var
  68. LZXC: array [0..3] of char = 'LZXC';
  69. begin
  70. // ::DataSpace/Storage/MSCompressed/ControlData
  71. Result := AStream.Position;
  72. AStream.WriteDWord(NToLE(DWord(6))); // number of dwords following this one
  73. AStream.Write(LZXC, 4);
  74. AStream.WriteDWord(NToLE(DWord(2))); // Version
  75. AStream.WriteDWord(NToLE(LZXResetInterval));
  76. AStream.WriteDWord(NToLE(WindowSize));
  77. AStream.WriteDWord(NToLE(CacheSize)); // what is this??
  78. AStream.WriteDWord(0);
  79. Result := AStream.Position - Result;
  80. end;
  81. function WriteSpanInfoToStream(const AStream: TStream; UncompressedSize: QWord): Integer;
  82. begin
  83. // ::DataSpace/Storage/MSCompressed/SpanInfo
  84. Result := AStream.Write(NToLE(UncompressedSize), SizeOf(QWord));
  85. end;
  86. function WriteTransformListToStream(const AStream: TStream): Integer;
  87. const
  88. //AGuid = '{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}';
  89. // use the broken guid
  90. AGuid = '{'#0'7'#0'F'#0'C'#0'2'#0'8'#0'9'#0'4'#0'0'#0'-'#0'9'#0'D'#0'3'#0'1'#0'-'#0'1'#0'1'#0'D'#0'0'#0; //-9B27-00A0C91E9C7C}';
  91. begin
  92. // ::DataSpace/Storage/MSCompressed/Transform/List
  93. Result := AStream.Write(AGuid, SizeOf(AGuid));
  94. end;
  95. function WriteResetTableToStream(const AStream: TStream;
  96. ResetTableStream: TMemoryStream): Integer;
  97. begin
  98. // ::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/
  99. // ::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable
  100. ResetTableStream.Position := 0;
  101. Result := AStream.CopyFrom(ResetTableStream, ResetTableStream.Size-SizeOf(QWord));
  102. end;
  103. function WriteContentToStream(const AStream: TStream; ContentStream: TMemoryStream): Integer;
  104. begin
  105. // ::DataSpace/Storage/MSCompressed/Content
  106. ContentStream.Position := 0;
  107. //WriteLn('Compressed Data start''s at: ', AStream.Position,' Size is: ', ContentStream.Size);
  108. Result := AStream.CopyFrom(ContentStream, ContentStream.Size);
  109. end;
  110. end.