chmspecialfiles.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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: TStream): 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. {$IFDEF ENDIAN_BIG}
  35. I: Integer;
  36. {$ENDIF}
  37. Size: Word = 2;
  38. NEntries: Word = 0;
  39. begin
  40. // ::DataSpace/NameList
  41. {$IFDEF ENDIAN_BIG}
  42. for I := 1 to 13 do begin
  43. PWord(@MSCompressedName[I])^ := NToLE(PWord(@MSCompressedName[I])^);
  44. PWord(@UnCompressedName[I])^ := NToLE(PWord(@UnCompressedName[I])^);
  45. end;
  46. {$ENDIF}
  47. if snUnCompressed in SectionNames then begin
  48. Inc(Size, 14);
  49. Inc(NEntries);
  50. end;
  51. if snMSCompressed in SectionNames then begin
  52. Inc(Size, 14);
  53. Inc(NEntries);
  54. end;
  55. AStream.WriteWord(NToLE(Size));
  56. AStream.WriteWord(NToLE(NEntries));
  57. if snUnCompressed in SectionNames then begin
  58. AStream.WriteWord(NToLE(Word(12)));
  59. AStream.Write(UnCompressedName[1], 13*2);
  60. end;
  61. if snMSCompressed in SectionNames then begin
  62. AStream.WriteWord(NToLE(Word(12)));
  63. AStream.Write(MSCompressedName[1], 13*2);
  64. end;
  65. Result := Size * SizeOf(Word);
  66. end;
  67. function WriteControlDataToStream(const AStream: TStream; const LZXResetInterval,
  68. WindowSize, CacheSize: DWord): Integer;
  69. var
  70. LZXC: array [0..3] of char = 'LZXC';
  71. begin
  72. // ::DataSpace/Storage/MSCompressed/ControlData
  73. Result := AStream.Position;
  74. AStream.WriteDWord(NToLE(DWord(6))); // number of dwords following this one
  75. AStream.Write(LZXC, 4);
  76. AStream.WriteDWord(NToLE(DWord(2))); // Version
  77. AStream.WriteDWord(NToLE(LZXResetInterval));
  78. AStream.WriteDWord(NToLE(WindowSize));
  79. AStream.WriteDWord(NToLE(CacheSize)); // what is this??
  80. AStream.WriteDWord(0);
  81. Result := AStream.Position - Result;
  82. end;
  83. function WriteSpanInfoToStream(const AStream: TStream; UncompressedSize: QWord): Integer;
  84. begin
  85. // ::DataSpace/Storage/MSCompressed/SpanInfo
  86. Result := AStream.Write(NToLE(UncompressedSize), SizeOf(QWord));
  87. end;
  88. function WriteTransformListToStream(const AStream: TStream): Integer;
  89. const
  90. //AGuid = '{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}';
  91. // use the broken guid
  92. 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}';
  93. begin
  94. // ::DataSpace/Storage/MSCompressed/Transform/List
  95. Result := AStream.Write(AGuid, SizeOf(AGuid));
  96. end;
  97. function WriteResetTableToStream(const AStream: TStream;
  98. ResetTableStream: TMemoryStream): Integer;
  99. begin
  100. // ::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/
  101. // ::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable
  102. ResetTableStream.Position := 0;
  103. Result := AStream.CopyFrom(ResetTableStream, ResetTableStream.Size-SizeOf(QWord));
  104. end;
  105. function WriteContentToStream(const AStream: TStream; ContentStream: TStream): Integer;
  106. begin
  107. // ::DataSpace/Storage/MSCompressed/Content
  108. ContentStream.Position := 0;
  109. //WriteLn('Compressed Data start''s at: ', AStream.Position,' Size is: ', ContentStream.Size);
  110. Result := AStream.CopyFrom(ContentStream, ContentStream.Size);
  111. end;
  112. end.