using System; using System.Collections.Generic; using System.Text; namespace HH.WMS.Utils.ExcelLibrary.CompoundDocumentFormat { /// /// Directory Entry Structure /// The size of each directory entry is exactly 128 bytes. /// public class DirectoryEntry : IComparable { /// /// Character array of the name of the entry, always 16-bit Unicode characters, /// with trailing zero character (results in a maximum name length of 31 characters) /// public char[] NameBuffer; /// /// Size of the used area of the character buffer of the name /// (not character count), including the trailing zero character /// public UInt16 NameDataSize; /// /// Type of the entry: /// 00H = Empty 03H = LockBytes (unknown) /// 01H = User storage 04H = Property (unknown) /// 02H = User stream 05H = Root storage /// public byte EntryType; /// /// Node colour of the entry: 00H = Red 01H = Black /// public byte NodeColor; /// /// DID of the left child node inside the red-black tree of all direct members of the parent storage /// (if this entry is a user storage or stream), ¨C1 if there is no left child /// public int LeftChildDID; /// /// DID of the right child node inside the red-black tree of all direct members of the parent storage /// (if this entry is a user storage or stream), ¨C1 if there is no right child /// public int RightChildDID; /// /// The directory organises direct members (storages and streams) of each storage in a separate red-black tree. /// DID of the root node entry of the red-black tree of all storage members /// (if this entry is a storage), ¨C1 otherwise /// public int MembersTreeNodeDID; /// /// Unique identifier, if this is a storage (not of interest in the following, may be all 0) /// public Guid UniqueIdentifier; /// /// User flags (not of interest in the following, may be all 0) /// public int UserFlags; /// /// Time stamp of creation of this entry. /// Most implementations do not write a valid time stamp, but fill up this space with zero bytes. /// public DateTime CreationTime; /// /// Time stamp of last modification of this entry. /// Most implementations do not write a valid time stamp, but fill up this space with zero bytes. /// public DateTime LastModificationTime; /// /// SID of first sector or short-sector, if this entry refers to a stream, /// SID of first sector of the short-stream container stream, if this is the root storage entry, /// 0 otherwise /// public int FirstSectorID; /// /// Total stream size in bytes, if this entry refers to a stream, /// total size of the shortstream container stream, if this is the root storage entry, /// 0 otherwise /// public int StreamLength; /// /// Not used /// public int UnUsed; public int ID = -1; public CompoundDocument Document; public DirectoryEntry Parent; public Dictionary Members = new Dictionary(); internal DirectoryEntry() { } public DirectoryEntry(string name) { this.NameBuffer = new char[32]; this.Name = name; this.CreationTime = DateTime.Now; this.LastModificationTime = this.CreationTime; this.LeftChildDID = -1; this.RightChildDID = -1; this.MembersTreeNodeDID = -1; this.FirstSectorID = SID.EOC; } public DirectoryEntry(CompoundDocument document, string name) : this(name) { Document = document; } public void AddChild(DirectoryEntry entry) { if (entry.Parent != null) { throw new ArgumentException("DirectoryEntry already has a parent."); } entry.Parent = this; this.Members.Add(entry.Name, entry); } byte[] data; public byte[] Data { get { if (data == null) { data = Document.GetStreamData(this); } return data; } set { data = value; } } public override string ToString() { return Name; } string name; public string Name { get { if (name == null) { int NameLength = NameDataSize / 2 - 1; if (NameLength == 1) { name = String.Empty; } else { name = new string(NameBuffer, 0, NameLength); } } return name; } set { if (value.Length > 31) { throw new Exception("Directory Entry Name exceeds 31 chars."); } value.ToCharArray().CopyTo(NameBuffer, 0); NameBuffer[value.Length] = '\0'; NameDataSize = (UInt16)((value.Length + 1) * 2); name = value; } } #region IComparable ³ÉÔ± public int CompareTo(DirectoryEntry other) { return CompareString(this.Name, other.Name); } static int CompareString(string strA, string strB) { if (strA != null && strB != null) { if (strA.Length < strB.Length) { return -1; } else if (strA.Length > strB.Length) { return 1; } } return String.Compare(strA, strB, StringComparison.OrdinalIgnoreCase); } #endregion } }