MicrosoftCompoundDocument.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. using System;
  2. using System.Collections;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5. namespace FastReport.Export.BIFF8
  6. {
  7. /// <summary>
  8. /// Provides API to binary stream
  9. /// </summary>
  10. public /*abstract*/ class StreamHelper : MemoryStream
  11. {
  12. internal void SkipBytes(int count)
  13. {
  14. base.Position = base.Position + count;
  15. }
  16. internal ushort ReadUshort()
  17. {
  18. byte hi, low;
  19. low = (byte)ReadByte();
  20. hi = (byte)ReadByte();
  21. return (ushort)((int)low + (int)(hi << 8));
  22. }
  23. internal uint ReadUint()
  24. {
  25. uint b0 = (uint)ReadByte();
  26. uint b1 = (uint)ReadByte();
  27. uint b2 = (uint)ReadByte();
  28. uint b3 = (uint)ReadByte();
  29. uint result = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  30. return result;
  31. }
  32. internal int ReadInt()
  33. {
  34. int b0 = ReadByte();
  35. int b1 = ReadByte();
  36. int b2 = ReadByte();
  37. int b3 = ReadByte();
  38. int result = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  39. return result;
  40. }
  41. internal double ReadDouble()
  42. {
  43. double[] result = new double[1];
  44. byte[] bytes = new byte[8];
  45. for (int i = 0; i < 8; i++) bytes[i] = (byte)ReadByte();
  46. IntPtr ptr = Marshal.AllocHGlobal(8);
  47. Marshal.Copy(bytes, 0, ptr, 8);
  48. Marshal.Copy(ptr, result, 0, 1);
  49. Marshal.FreeHGlobal(ptr);
  50. return result[0];
  51. }
  52. internal string ReadUnicodeString(bool short_len)
  53. {
  54. string str = "";
  55. int num_rich_runs = 0;
  56. UInt16 Char_Count = short_len ? (UInt16)ReadByte() : ReadUshort();
  57. byte options = (byte)ReadByte();
  58. if ((options & 0x8) != 0)
  59. num_rich_runs = ReadUshort();
  60. if ((options & 0x1) != 0)
  61. {
  62. for (int i = 0; i < Char_Count; i++)
  63. {
  64. char ch = (char)ReadUshort();
  65. str += ch;
  66. }
  67. }
  68. else
  69. {
  70. for (int i = 0; i < Char_Count; i++)
  71. {
  72. char ch = (char)ReadByte();
  73. str += ch;
  74. }
  75. }
  76. return str;
  77. }
  78. internal bool CanCompressString(string s)
  79. {
  80. int str_len = s.Length;
  81. for (int i = 0; i < str_len; i++)
  82. if (s[i] > 255) return false;
  83. return true;
  84. }
  85. internal void WriteUnicodeString(string FontName, bool short_len)
  86. {
  87. WriteUnicodeString(FontName, short_len, false);
  88. }
  89. internal void WriteUnicodeString(string FontName, bool short_len, bool compress)
  90. {
  91. int str_len = FontName.Length;
  92. if (short_len)
  93. {
  94. WriteByte((byte)str_len);
  95. }
  96. else
  97. {
  98. WriteUshort((ushort)str_len);
  99. }
  100. WriteByte(compress ? (byte)0 : (byte)0x001); // Uncompressed
  101. if (compress)
  102. {
  103. for (int i = 0; i < str_len; i++)
  104. {
  105. char ch = FontName[i];
  106. if (ch == 0xd)
  107. WriteByte((byte)0xa);
  108. else
  109. WriteByte((byte)ch);
  110. }
  111. }
  112. else
  113. {
  114. for (int i = 0; i < str_len; i++)
  115. {
  116. char ch = FontName[i];
  117. if (ch == 0xd)
  118. WriteUshort((ushort)0xa);
  119. else
  120. WriteUshort((ushort)ch);
  121. }
  122. }
  123. }
  124. internal int SizeUnicodeString(string FontName, bool short_len)
  125. {
  126. return SizeUnicodeString(FontName, short_len, false);
  127. }
  128. internal int SizeUnicodeString(string FontName, bool short_len, bool compress)
  129. {
  130. int str_len = FontName.Length;
  131. if (!compress)
  132. str_len *= 2;
  133. return str_len + (short_len ? 2 : 3);
  134. }
  135. internal byte[] ReadBytes(int count)
  136. {
  137. byte[] result = new byte[count];
  138. for (int i = 0; i < count; i++)
  139. result[i] = unchecked((byte)ReadByte());
  140. return result;
  141. }
  142. internal ushort[] ReadUshorts(int count)
  143. {
  144. ushort[] result = new ushort[count];
  145. for (int i = 0; i < count; i++) result[i] = ReadUshort();
  146. return result;
  147. }
  148. internal int[] ReadInts(int count)
  149. {
  150. int[] result = new int[count];
  151. for (int i = 0; i < count; i++) result[i] = ReadInt();
  152. return result;
  153. }
  154. internal void WriteUshort(ushort value)
  155. {
  156. unchecked
  157. {
  158. byte lo = (byte)(value);
  159. WriteByte(lo);
  160. byte hi = (byte)(value >> 8);
  161. WriteByte(hi);
  162. }
  163. }
  164. internal void WriteUint(uint value)
  165. {
  166. unchecked
  167. {
  168. byte b0 = (byte)value;
  169. byte b1 = (byte)(value >> 8);
  170. byte b2 = (byte)(value >> 16);
  171. byte b3 = (byte)(value >> 24);
  172. WriteByte(b0);
  173. WriteByte(b1);
  174. WriteByte(b2);
  175. WriteByte(b3);
  176. }
  177. }
  178. internal void WriteInt(int value)
  179. {
  180. unchecked
  181. {
  182. byte b0 = (byte)value;
  183. byte b1 = (byte)(value >> 8);
  184. byte b2 = (byte)(value >> 16);
  185. byte b3 = (byte)(value >> 24);
  186. WriteByte(b0);
  187. WriteByte(b1);
  188. WriteByte(b2);
  189. WriteByte(b3);
  190. }
  191. }
  192. internal void WriteDouble(double value)
  193. {
  194. double[] source = new double[1];
  195. source[0] = value;
  196. byte[] bytes = new byte[8];
  197. IntPtr ptr = Marshal.AllocHGlobal(8);
  198. Marshal.Copy(source, 0, ptr, 1);
  199. Marshal.Copy(ptr, bytes, 0, bytes.Length);
  200. Marshal.FreeHGlobal(ptr);
  201. for (int i = 0; i < 8; i++) WriteByte(bytes[i]);
  202. }
  203. internal void WriteBytes(byte[] values)
  204. {
  205. for (int i = 0; i < values.Length; i++) WriteByte(values[i]);
  206. }
  207. internal void WriteBytes(byte[] values, int start_index, int count)
  208. {
  209. for (int i = 0; i < count; i++) WriteByte(values[start_index + i]);
  210. }
  211. internal void WriteInts(int[] values)
  212. {
  213. WriteInts(values, 0);
  214. }
  215. internal void WriteInts(int[] values, int start_index)
  216. {
  217. for (int i = start_index; i < values.Length; i++) WriteInt(values[i]);
  218. }
  219. internal void WriteUints(uint[] values)
  220. {
  221. WriteUints(values, 0);
  222. }
  223. internal void WriteUints(uint[] values, int start_index)
  224. {
  225. for (int i = start_index; i < values.Length; i++) WriteUint(values[i]);
  226. }
  227. }
  228. internal class DirectoryEntry
  229. {
  230. internal enum DirEntryType
  231. {
  232. // Type of the entry:
  233. Empty = 0x00, // 00H = Empty
  234. UserStorage = 0x01, // 01H = User storage
  235. UseStream = 0x02, // 02H = User stream
  236. LockBytes = 0x03, // 03H = LockBytes (unknown)
  237. Property = 0x04, // 04H = Property (unknown)
  238. RootStorage = 0x05 // 05H = Root storage
  239. }
  240. #if false
  241. // 0 64
  242. // Character array of the name of the entry, always 16-bit Unicode characters, with trailing
  243. //zero character (results in a maximum name length of 31 characters)
  244. byte[] name = new byte[64];
  245. //64 2
  246. //Size of the used area of the character buffer of the name (not character count), including
  247. //the trailing zero character (e.g. 12 for a name with 5 characters: (5+1)∙2 = 12)
  248. ushort name_size;
  249. #else
  250. public string entry_name;
  251. #endif
  252. // 66 1
  253. // Type of the entry: 00H = Empty 03H = LockBytes (unknown)
  254. // 01H = User storage 04H = Property (unknown)
  255. // 02H = User stream 05H = Root storage
  256. internal DirEntryType type;
  257. // 67 1 Node colour of the entry: 00H = Red 01H = Black
  258. internal byte colour;
  259. // 68 4 DirID of the left child node inside the red-black tree of all direct members of the parent
  260. // storage (if this entry is a user storage or stream), –1 if there is no left child
  261. internal int leftChildDirID;
  262. //72 4 DirID of the right child node inside the red-black tree of all direct members of the parent
  263. //storage (if this entry is a user storage or stream), –1 if there is no right child
  264. internal int rightChildDirID;
  265. // 76 4 DirID of the root node entry of the red-black tree of all storage members (if this entry is a
  266. //storage,), –1 otherwise
  267. internal int rootDirID;
  268. // 80 16 Unique identifier, if this is a storage (not of interest in the following, may be all 0)
  269. private byte[] uid = new byte[16];
  270. // 96 4 User flags (not of interest in the following, may be all 0)
  271. private uint userFlags;
  272. // 100 8 Time stamp of creation of this entry.
  273. private byte[] creationTime = new byte[8];
  274. // 108 8 Time stamp of last modification of this entry
  275. private byte[] modificationTime = new byte[8];
  276. // 116 4 SecID of first sector or short-sector, if this entry refers to a stream
  277. public UInt32 bOF;
  278. //120 4 Total stream size in bytes, if this entry refers to a stream
  279. public UInt32 size;
  280. // 124 4 Not used
  281. public void Read(StreamHelper File)
  282. {
  283. entry_name = "";
  284. ushort name_size;
  285. for (int i = 0; i < 32; i++)
  286. {
  287. char ch = (char)File.ReadUshort();
  288. if (ch != '\0') entry_name += ch;
  289. }
  290. name_size = File.ReadUshort();
  291. type = (DirEntryType)File.ReadByte();
  292. colour = (byte)File.ReadByte();
  293. leftChildDirID = File.ReadInt();
  294. rightChildDirID = File.ReadInt();
  295. rootDirID = File.ReadInt();
  296. uid = File.ReadBytes(uid.Length);
  297. userFlags = File.ReadUint();
  298. creationTime = File.ReadBytes(creationTime.Length);
  299. modificationTime = File.ReadBytes(modificationTime.Length);
  300. bOF = File.ReadUint();
  301. size = File.ReadUint();
  302. File.SkipBytes(sizeof(UInt32));
  303. }
  304. public DirectoryEntry()
  305. {
  306. colour = 0x00; // Black
  307. leftChildDirID = -1;
  308. rightChildDirID = -1;
  309. rootDirID = -1;
  310. uid = new byte[16];
  311. // 96 4 User flags (not of interest in the following, may be all 0)
  312. userFlags = 0;
  313. // 100 8 Time stamp of creation of this entry. Most implementations do not write a valid
  314. // time stamp, but fill up this space with zero bytes.
  315. creationTime = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 };
  316. // 108 8 Time stamp of last modification of this entry. Most implementations do not write
  317. // a valid time stamp, but fill up this space with zero bytes.
  318. modificationTime = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 };
  319. // Fixed empry values
  320. this.bOF = 0;
  321. this.size = 0;
  322. this.type = DirEntryType.Empty;
  323. this.entry_name = "";
  324. }
  325. public DirectoryEntry(string name, DirEntryType type) : this()
  326. {
  327. this.type = type;
  328. this.entry_name = name;
  329. }
  330. internal void Write(StreamHelper File)
  331. {
  332. int name_len = entry_name.Length;
  333. if (name_len > 32) name_len = 32;
  334. for (int i = 0; i < name_len; i++)
  335. {
  336. char ch = entry_name[i];
  337. File.WriteUshort(ch);
  338. }
  339. for (int i = name_len; i < 32; i++)
  340. {
  341. File.WriteUshort(0);
  342. }
  343. File.WriteUshort((ushort)(2 + name_len * 2));
  344. File.WriteByte((byte)type);
  345. File.WriteByte(colour);
  346. File.WriteInt(leftChildDirID);
  347. File.WriteInt(rightChildDirID);
  348. File.WriteInt(rootDirID);
  349. File.WriteBytes(uid);
  350. File.WriteUint(userFlags);
  351. File.WriteBytes(creationTime);
  352. File.WriteBytes(modificationTime);
  353. File.WriteUint(bOF);
  354. File.WriteUint(size);
  355. File.SkipBytes(sizeof(UInt32));
  356. }
  357. }
  358. internal class CompoundDocumentHeader : StreamHelper
  359. {
  360. private byte[] id0 = new byte[8]; // Must be: D0 CF 11 E0 A1 B1 1A E1
  361. private byte[] uid = new byte[16];
  362. private ushort revision; // Might be: 3E
  363. private ushort version; // Might be: 03
  364. private ushort byteOrder; // Little-Endian: FE FF; Big-Endian: FF FE
  365. private ushort secSize; // Sector size is 2**SecSize bytes
  366. private ushort shortSecSize; // Short sector size is 2**ShortSecSize bytes
  367. // fixed byte NotUsed1[10];
  368. private uint satCount; // Count of sectors used for the SAT
  369. public int dir; // First sector of the directory stream
  370. // fixed byte NotUsed2[4];
  371. public UInt32 minStreamSize; // Streams that have sizes less than this value are stored in the short stream
  372. private int sSAT; // First sector of the SSAT
  373. private uint sSATCount; // Count of sectors used for the SSAT
  374. private int mSAT; // First sector of the MSAT
  375. private uint mSATCount; // Count of sectors used for the MSAT
  376. private int[] mSATSectors = new int[109]; // First 109 SecID values in the MSAT
  377. private ArrayList sat = new ArrayList();
  378. private ArrayList shortSAT = new ArrayList();
  379. private ArrayList additional_mSAT = new ArrayList();
  380. private uint totalAllocatedSectors;
  381. private uint totalAllocatedShortSectors;
  382. internal BIFF8_Container shortStreamContainer;
  383. public int SectorSize { get { return 1 << secSize; } }
  384. public int ShortSectorSize { get { return 1 << shortSecSize; } }
  385. internal int SectorOffset(int index)
  386. {
  387. int a = 512 + index * SectorSize;
  388. return a;
  389. }
  390. internal int ShortSectorOffset(int index)
  391. {
  392. int a = index * ShortSectorSize;
  393. return a;
  394. }
  395. internal int NextSector(int index)
  396. {
  397. return (int)sat[index];
  398. }
  399. internal int NextShortSector(int index)
  400. {
  401. return (int)shortSAT[index];
  402. }
  403. internal void Read()
  404. {
  405. id0 = ReadBytes(id0.Length);
  406. uid = ReadBytes(uid.Length);
  407. revision = ReadUshort();
  408. version = ReadUshort();
  409. byteOrder = ReadUshort();
  410. secSize = ReadUshort();
  411. shortSecSize = ReadUshort();
  412. SkipBytes(10);
  413. satCount = ReadUint();
  414. dir = ReadInt();
  415. SkipBytes(4);
  416. minStreamSize = ReadUint();
  417. sSAT = ReadInt();
  418. sSATCount = ReadUint();
  419. mSAT = ReadInt();
  420. mSATCount = ReadUint();
  421. mSATSectors = ReadInts(mSATSectors.Length);
  422. // Read SAT into memory
  423. for (int i = 0; i < satCount; i++)
  424. {
  425. if (i >= 109) throw new Exception("Huge SAT not implemented");
  426. int SAT_Sector = mSATSectors[i];
  427. int Position = SectorOffset(SAT_Sector);
  428. this.Position = Position;
  429. sat.AddRange(new ArrayList(ReadInts(this.SectorSize / sizeof(UInt32))));
  430. }
  431. // Read SSAT into memory
  432. int SSAT_Sector = sSAT;
  433. for (int i = 0; i < sSATCount; i++)
  434. {
  435. int Position = SectorOffset(SSAT_Sector);
  436. this.Position = Position;
  437. shortSAT.AddRange(new ArrayList(ReadInts(this.SectorSize / sizeof(UInt32))));
  438. SSAT_Sector = NextSector(SSAT_Sector);
  439. }
  440. }
  441. internal void Write()
  442. {
  443. this.Position = 0;
  444. WriteBytes(id0);
  445. WriteBytes(uid);
  446. WriteUshort(revision);
  447. WriteUshort(version);
  448. WriteUshort(byteOrder);
  449. WriteUshort(secSize);
  450. WriteUshort(shortSecSize);
  451. SkipBytes(10);
  452. WriteUint(satCount);
  453. WriteInt(dir);
  454. SkipBytes(4);
  455. WriteUint(minStreamSize);
  456. WriteInt(sSAT);
  457. WriteUint(sSATCount);
  458. WriteInt(mSAT);
  459. WriteUint(mSATCount);
  460. WriteInts(mSATSectors);
  461. // Write SSAT to memory
  462. int SSATEntriesPerSector = this.SectorSize / sizeof(UInt32);
  463. int SSAT_Sector = sSAT;
  464. for (int i = 0; i < sSATCount;)
  465. {
  466. this.Position = SectorOffset(SSAT_Sector);
  467. for (int j = 0; j < SSATEntriesPerSector; j++)
  468. {
  469. int value = (int)shortSAT[i * SSATEntriesPerSector + j];
  470. this.WriteInt(value);
  471. }
  472. i++;
  473. if (i == sSATCount) continue;
  474. SSAT_Sector = this.AllocateSector(SSAT_Sector);
  475. }
  476. // Write SAT to memory
  477. for (int i = 0; i < satCount; i++)
  478. {
  479. int SAT_Sector = 0;
  480. if (i >= 109) SAT_Sector = (int)this.additional_mSAT[i - 109];//throw new Exception("Huge SAT not implemented");
  481. else SAT_Sector = this.mSATSectors[i];
  482. this.Position = SectorOffset(SAT_Sector);
  483. for (int j = 0; j < this.SectorSize / sizeof(UInt32); j++)
  484. {
  485. int value = -1;
  486. int idx = i * this.SectorSize / sizeof(UInt32) + j;
  487. if (idx < sat.Count)
  488. value = (int)sat[idx];
  489. this.WriteInt(value);
  490. }
  491. }
  492. // Write MSAT to memory
  493. int MSATEntriesPerSector = this.SectorSize / sizeof(Int32);
  494. int MSAT_Sector = mSAT;
  495. for (int i = 0; i < mSATCount;)
  496. {
  497. this.Position = SectorOffset(MSAT_Sector);
  498. for (int j = 0; j < MSATEntriesPerSector; j++)
  499. {
  500. int n = i * SSATEntriesPerSector + j;
  501. int value = -1;
  502. if (n < satCount)
  503. value = n >= 109 ? (int)additional_mSAT[n - 109] : mSATSectors[n];
  504. this.WriteInt(value);
  505. }
  506. i++;
  507. if (i == mSATCount) continue;
  508. MSAT_Sector = this.AllocateSector(MSAT_Sector);
  509. }
  510. }
  511. internal void Reset()
  512. {
  513. id0 = new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
  514. revision = 0x003e;
  515. version = 0x0003;
  516. byteOrder = 0xfffe;
  517. secSize = 0x0009;
  518. shortSecSize = 0x0006;
  519. satCount = 0;
  520. minStreamSize = 0x00001000;
  521. mSAT = -2;
  522. mSATCount = 0;
  523. // Reset SAT table
  524. this.sat.Clear();
  525. // Reset SSAT table
  526. sSATCount = 0;
  527. this.shortSAT.Clear();
  528. // Reset MSAT table
  529. for (int i = 0; i < mSATSectors.Length; i++)
  530. {
  531. mSATSectors[i] = -1;
  532. }
  533. this.additional_mSAT.Clear();
  534. this.totalAllocatedSectors = 0;
  535. this.totalAllocatedShortSectors = 0;
  536. this.shortStreamContainer.SetLength(0);
  537. dir = AllocateSector();
  538. sSAT = AllocateSector();
  539. mSAT = AllocateSector();
  540. mSATCount = 1;
  541. }
  542. internal CompoundDocumentHeader(FileStream f)
  543. : base()
  544. {
  545. f.CopyTo(this, (int)f.Length);
  546. this.Position = 0;
  547. }
  548. internal CompoundDocumentHeader()
  549. : base()
  550. {
  551. shortStreamContainer = new BIFF8_Container();
  552. Reset();
  553. this.Position = 0;
  554. }
  555. internal void FinalWriteToStream(Stream f)
  556. {
  557. this.Position = 0;
  558. this.CopyTo(f, (int)this.Length);
  559. }
  560. internal void SetCurentSector(int Dir)
  561. {
  562. base.Position = SectorOffset(Dir);
  563. }
  564. internal void ReadShortStreamContainer(DirectoryEntry entry)
  565. {
  566. int StorePosition = (int)this.Position;
  567. int SectorOfContainer;
  568. shortStreamContainer = new BIFF8_Container();
  569. int idx = 0;
  570. for (
  571. SectorOfContainer = (int)entry.bOF;
  572. SectorOfContainer >= 0;
  573. SectorOfContainer = this.NextSector(SectorOfContainer)
  574. )
  575. {
  576. this.SetCurentSector(SectorOfContainer);
  577. for (int i = 0; i < this.SectorSize && idx < entry.size; i++)
  578. {
  579. shortStreamContainer.WriteByte((byte)ReadByte());
  580. }
  581. }
  582. this.Position = StorePosition;
  583. }
  584. internal int WriteShortStreamContainer()
  585. {
  586. int StorePosition = (int)this.Position;
  587. int FirstSectorOfContainer = this.AllocateSector();
  588. int ContainerSize = (int)shortStreamContainer.Length;
  589. shortStreamContainer.Position = 0;
  590. for (
  591. int SectorOfContainer = (int)FirstSectorOfContainer;
  592. ContainerSize > 0;
  593. SectorOfContainer = this.AllocateSector(SectorOfContainer)
  594. )
  595. {
  596. this.SetCurentSector(SectorOfContainer);
  597. for (int i = 0; i < this.SectorSize; i++)
  598. {
  599. byte value = 0xff;
  600. if (shortStreamContainer.Position < shortStreamContainer.Length)
  601. {
  602. value = (byte)shortStreamContainer.ReadByte();
  603. }
  604. this.WriteByte(value);
  605. }
  606. ContainerSize -= this.SectorSize;
  607. if (ContainerSize <= 0) break;
  608. }
  609. this.Position = StorePosition;
  610. return FirstSectorOfContainer;
  611. }
  612. internal int AllocateSector()
  613. {
  614. int new_sector;
  615. new_sector = sat.IndexOf(-1);
  616. if (new_sector == -1)
  617. {
  618. AllocateSATSector();
  619. new_sector = sat.IndexOf(-1);
  620. if (new_sector == -1)
  621. {
  622. throw new Exception("Unable allocate SAT sector");
  623. }
  624. sat[new_sector] = -2;
  625. int self = sat.IndexOf(-1);
  626. sat[self] = -3;
  627. if (satCount >= 109)
  628. {
  629. //throw new Exception("Huge SAT not implemented");
  630. this.additional_mSAT.Add(self);
  631. }
  632. else mSATSectors[satCount] = self;
  633. satCount++;
  634. }
  635. totalAllocatedSectors++;
  636. sat[new_sector] = -2;
  637. return new_sector;
  638. }
  639. internal int AllocateSector(int PrevSector)
  640. {
  641. int Sector = AllocateSector();
  642. sat[PrevSector] = Sector;
  643. return Sector;
  644. }
  645. internal int AllocateShortSector()
  646. {
  647. int new_sector;
  648. new_sector = shortSAT.IndexOf(-1);
  649. if (new_sector == -1)
  650. {
  651. AllocateSSATSector();
  652. new_sector = shortSAT.IndexOf(-1);
  653. if (new_sector == -1)
  654. {
  655. throw new Exception("Unable allocate SSAT sector");
  656. }
  657. }
  658. totalAllocatedShortSectors++;
  659. shortSAT[new_sector] = -2;
  660. return new_sector;
  661. }
  662. internal int AllocateShortSector(int PrevSector)
  663. {
  664. int Sector = AllocateShortSector();
  665. shortSAT[PrevSector] = Sector;
  666. return Sector;
  667. }
  668. private void AllocateSATSector()
  669. {
  670. if (satCount > 109)
  671. {
  672. //throw new Exception("Large MSAT does not implemented yet");
  673. }
  674. int SATEntriesPerSector = this.ShortSectorSize / sizeof(UInt32);
  675. ArrayList sat_new_sectors = new ArrayList();
  676. #if false // BIG DEAL
  677. sat_new_sectors.Add(-3); // Sector is used by SAT itself
  678. for (int i = 1; i < SATEntriesPerSector; i++)
  679. #else
  680. for (int i = 0; i < SATEntriesPerSector; i++)
  681. #endif
  682. {
  683. sat_new_sectors.Add(-1);
  684. }
  685. sat.AddRange(sat_new_sectors);
  686. int local = sat.Count / SATEntriesPerSector;
  687. // MSATSectors[SATCount] = (int)
  688. totalAllocatedSectors++;
  689. }
  690. private void AllocateSSATSector()
  691. {
  692. int SSATEntriesPerSector = this.SectorSize / sizeof(UInt32);
  693. ArrayList ssat_new_sectors = new ArrayList();
  694. // ssat_new_sectors.Add(-3); // Sector is used by SAT itself
  695. for (int i = 0; i < SSATEntriesPerSector; i++)
  696. {
  697. ssat_new_sectors.Add(-1);
  698. }
  699. this.shortSAT.AddRange(ssat_new_sectors);
  700. int local = shortSAT.Count / SSATEntriesPerSector;
  701. sSATCount++;
  702. }
  703. #if false
  704. internal int AllocateStream(int WriteQueueLength, bool non_packing_stream)
  705. {
  706. int BOF;
  707. int Sector;
  708. // int WriteQueueLength = Container.Length;
  709. if (WriteQueueLength == 0) return -1;
  710. if (WriteQueueLength >= this.MinStreamSize || non_packing_stream)
  711. {
  712. BOF = Sector = this.AllocateSector();
  713. // int SourceCopyIndex = 0;
  714. do
  715. {
  716. int CopyCount = (WriteQueueLength < this.SectorSize) ? WriteQueueLength : this.SectorSize;
  717. // this.SetCurentSector(Sector);
  718. // this.WriteBytes(Container, SourceCopyIndex, CopyCount);
  719. WriteQueueLength -= CopyCount;
  720. if (WriteQueueLength == 0) break;
  721. Sector = this.AllocateSector(Sector);
  722. } while (true);
  723. }
  724. else
  725. {
  726. BOF = Sector = AllocateShortSector();
  727. // int SourceCopyIndex = 0;
  728. do
  729. {
  730. int CopyCount = (WriteQueueLength < this.ShortSectorSize) ? WriteQueueLength : this.ShortSectorSize;
  731. // this.SetCurentSector(Sector);
  732. // this.WriteBytes(Container, SourceCopyIndex, CopyCount);
  733. WriteQueueLength -= CopyCount;
  734. if (WriteQueueLength == 0) break;
  735. Sector = this.AllocateShortSector(Sector);
  736. } while (true);
  737. }
  738. return BOF;
  739. }
  740. #endif
  741. }
  742. internal class DirectoryStream : ArrayList
  743. {
  744. private CompoundDocumentHeader documentHeader;
  745. internal new DirectoryEntry this[int index]
  746. {
  747. get
  748. {
  749. return base[index] as DirectoryEntry;
  750. }
  751. }
  752. internal void Reset()
  753. {
  754. for (int i = 0; i < this.Count; i++)
  755. {
  756. base[i] = 0;
  757. }
  758. base.Clear();
  759. }
  760. internal void Read(int Dir, StreamHelper file)
  761. {
  762. do
  763. {
  764. documentHeader.SetCurentSector(Dir);
  765. for (int i = 0; i < documentHeader.SectorSize / 128; i++)
  766. {
  767. DirectoryEntry entry = new DirectoryEntry();
  768. entry.Read(file);
  769. Add(entry);
  770. }
  771. Dir = documentHeader.NextSector(Dir);
  772. } while (Dir != -2);
  773. }
  774. internal void Write(int Dir, StreamHelper file)
  775. {
  776. int local_directory_index = 0;
  777. DirectoryEntry entry;
  778. documentHeader.SetCurentSector(Dir);
  779. for (int i = 0; i < documentHeader.SectorSize / 128; i++)
  780. {
  781. if (local_directory_index < this.Count)
  782. {
  783. entry = this[local_directory_index] as DirectoryEntry;
  784. }
  785. else
  786. {
  787. entry = new DirectoryEntry();
  788. }
  789. entry.Write(file);
  790. local_directory_index++;
  791. }
  792. }
  793. public DirectoryStream(CompoundDocumentHeader header)
  794. {
  795. documentHeader = header;
  796. }
  797. internal DirectoryEntry Add(
  798. string FileName,
  799. BIFF8_Stream stream,
  800. int left, int right)
  801. {
  802. DirectoryEntry entry = stream.streamDirEntry;
  803. entry.entry_name = FileName;
  804. entry.type = DirectoryEntry.DirEntryType.UseStream;
  805. entry.size = (uint)stream.Length;
  806. entry.leftChildDirID = left;
  807. entry.rightChildDirID = right;
  808. entry.colour = 0x01;
  809. stream.Position = 0;
  810. // byte[] payload = stream.ReadBytes((int) entry.Size);
  811. // entry.BOF = (uint)DocumentHeader.AllocateStream( payload.Length, false );
  812. stream.streamDirEntry = entry;
  813. this.Add(entry);
  814. return entry;
  815. }
  816. internal DirectoryEntry Add(string FileName)
  817. {
  818. BIFF8_Container Container = documentHeader.shortStreamContainer;
  819. DirectoryEntry entry = new DirectoryEntry();
  820. entry.entry_name = FileName;
  821. entry.type = DirectoryEntry.DirEntryType.RootStorage;
  822. entry.size = (uint)Container.Length;
  823. entry.bOF = (uint)documentHeader.WriteShortStreamContainer();
  824. entry.rootDirID = 3;
  825. entry.colour = 0x01;
  826. this.Add(entry);
  827. return entry;
  828. }
  829. }
  830. /// <summary>
  831. ///
  832. /// </summary>
  833. internal class BIFF8_Container : StreamHelper
  834. {
  835. }
  836. internal class BIFF8_Stream : StreamHelper
  837. {
  838. internal DirectoryEntry streamDirEntry;
  839. internal CompoundDocumentHeader documentHeader;
  840. private int ShortSectorSize { get { return documentHeader.ShortSectorSize; } }
  841. internal void Write()
  842. {
  843. this.Position = 0;
  844. int BytesCount = (int)this.Length;
  845. if (BytesCount < documentHeader.minStreamSize)
  846. {
  847. this.streamDirEntry.bOF = (uint)this.documentHeader.AllocateShortSector();
  848. int Sector = (int)this.streamDirEntry.bOF;
  849. while (BytesCount > 0)
  850. {
  851. int chunk_size = (BytesCount >= ShortSectorSize) ? ShortSectorSize : BytesCount;
  852. byte[] sector = this.ReadBytes(documentHeader.ShortSectorSize);
  853. documentHeader.shortStreamContainer.Position = documentHeader.ShortSectorOffset(Sector);
  854. documentHeader.shortStreamContainer.Write(sector, 0, chunk_size);
  855. BytesCount -= chunk_size;
  856. if (BytesCount <= 0) break;
  857. Sector = documentHeader.AllocateShortSector(Sector);
  858. }
  859. }
  860. else
  861. {
  862. this.streamDirEntry.bOF = (uint)this.documentHeader.AllocateSector();
  863. int Sector = (int)this.streamDirEntry.bOF;
  864. while (BytesCount > 0)
  865. {
  866. documentHeader.SetCurentSector(Sector);
  867. byte[] sector = this.ReadBytes(documentHeader.SectorSize);
  868. documentHeader.Write(sector, 0, documentHeader.SectorSize);
  869. BytesCount -= documentHeader.SectorSize;
  870. if (BytesCount <= 0) break;
  871. Sector = documentHeader.AllocateSector(Sector);
  872. }
  873. }
  874. }
  875. public BIFF8_Stream(CompoundDocumentHeader document_header, DirectoryEntry entry)
  876. {
  877. this.streamDirEntry = entry;
  878. this.documentHeader = document_header;
  879. int Sector = (int)entry.bOF;
  880. int BytesCount = (int)entry.size;
  881. if (BytesCount < documentHeader.minStreamSize)
  882. {
  883. while (BytesCount > 0)
  884. {
  885. int chunk_size = (BytesCount >= ShortSectorSize) ? ShortSectorSize : BytesCount;
  886. documentHeader.shortStreamContainer.Position = documentHeader.ShortSectorOffset(Sector);
  887. byte[] sector_data = documentHeader.shortStreamContainer.ReadBytes(chunk_size);
  888. this.Write(sector_data, 0, chunk_size);
  889. Sector = documentHeader.NextShortSector(Sector);
  890. BytesCount -= chunk_size;
  891. }
  892. }
  893. else
  894. {
  895. while (BytesCount > 0)
  896. {
  897. documentHeader.SetCurentSector(Sector);
  898. if (BytesCount >= documentHeader.SectorSize)
  899. {
  900. byte[] sector = documentHeader.ReadBytes(documentHeader.SectorSize);
  901. base.Write(sector, 0, documentHeader.SectorSize);
  902. BytesCount -= documentHeader.SectorSize;
  903. }
  904. else
  905. {
  906. byte[] sector = documentHeader.ReadBytes(BytesCount);
  907. base.Write(sector, 0, BytesCount);
  908. BytesCount -= documentHeader.SectorSize;
  909. }
  910. Sector = documentHeader.NextSector(Sector);
  911. }
  912. }
  913. base.Position = 0;
  914. }
  915. }
  916. }