Ejemplo n.º 1
0
        /// <summary>
        /// Writes the property To an output stream.
        /// </summary>
        /// <param name="out1">The output stream To Write To.</param>
        /// <param name="codepage">The codepage To use for writing non-wide strings</param>
        /// <returns>the number of bytes written To the stream</returns>
        public int Write(Stream out1, int codepage)
        {
            int  length      = 0;
            long variantType = this.Type;

            /* Ensure that wide strings are written if the codepage is Unicode. */
            if (codepage == (int)Constants.CP_UNICODE && variantType == Variant.VT_LPSTR)
            {
                variantType = Variant.VT_LPWSTR;
            }

            length += TypeWriter.WriteUIntToStream(out1, (uint)variantType);
            length += VariantSupport.Write(out1, variantType, this.Value, codepage);
            return(length);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Writes the property Set To an output stream.
        /// </summary>
        /// <param name="out1">the output stream To Write the section To</param>
        public virtual void Write(Stream out1)
        {
            /* Write the number of sections in this property Set stream. */
            int nrSections = sections.Count;
            int length     = 0;

            /* Write the property Set's header. */
            length += TypeWriter.WriteToStream(out1, (short)ByteOrder);
            length += TypeWriter.WriteToStream(out1, (short)Format);
            length += TypeWriter.WriteToStream(out1, OSVersion);
            length += TypeWriter.WriteToStream(out1, ClassID);
            length += TypeWriter.WriteToStream(out1, nrSections);
            int offset = OFFSet_HEADER;

            /* Write the section list, i.e. the references To the sections. Each
             * entry in the section list consist of the section's class ID and the
             * section's offset relative To the beginning of the stream. */
            offset += nrSections * (ClassID.Length + LittleEndianConsts.INT_SIZE);
            int sectionsBegin = offset;

            for (IEnumerator i = sections.GetEnumerator(); i.MoveNext();)
            {
                MutableSection s        = (MutableSection)i.Current;
                ClassID        formatID = s.FormatID;
                if (formatID == null)
                {
                    throw new NoFormatIDException();
                }
                length += TypeWriter.WriteToStream(out1, s.FormatID);
                length += TypeWriter.WriteUIntToStream(out1, (uint)offset);

                offset += s.Size;
            }

            /* Write the sections themselves. */
            offset = sectionsBegin;
            for (IEnumerator i = sections.GetEnumerator(); i.MoveNext();)
            {
                MutableSection s = (MutableSection)i.Current;
                offset += s.Write(out1);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Writes a variant value To an output stream. This method ensures that
        /// always a multiple of 4 bytes is written.
        /// If the codepage is UTF-16, which is encouraged, strings
        /// <strong>must</strong> always be written as {@link Variant#VT_LPWSTR}
        /// strings, not as {@link Variant#VT_LPSTR} strings. This method ensure this
        /// by Converting strings appropriately, if needed.
        /// </summary>
        /// <param name="out1">The stream To Write the value To.</param>
        /// <param name="type">The variant's type.</param>
        /// <param name="value">The variant's value.</param>
        /// <param name="codepage">The codepage To use To Write non-wide strings</param>
        /// <returns>The number of entities that have been written. In many cases an
        /// "entity" is a byte but this is not always the case.</returns>
        public static int Write(Stream out1, long type,
                                Object value, int codepage)
        {
            int length = 0;

            switch ((int)type)
            {
            case Variant.VT_BOOL:
            {
                int trueOrFalse;
                if ((bool)value)
                {
                    trueOrFalse = 1;
                }
                else
                {
                    trueOrFalse = 0;
                }
                length = TypeWriter.WriteUIntToStream(out1, (uint)trueOrFalse);
                break;
            }

            case Variant.VT_LPSTR:
            {
                if (codepage == 0)
                {
                    throw new ArgumentOutOfRangeException("codepage");
                }
                byte[] bytes =
                    (codepage == -1 ?
                     Encoding.UTF8.GetBytes((string)value) :
                     Encoding.GetEncoding(codepage).GetBytes((string)value));

                length = TypeWriter.WriteUIntToStream(out1, (uint)bytes.Length + 1);
                byte[] b = new byte[bytes.Length + 1];
                Array.Copy(bytes, 0, b, 0, bytes.Length);
                b[b.Length - 1] = 0x00;
                out1.Write(b, 0, b.Length);
                length += b.Length;
                break;
            }

            case Variant.VT_LPWSTR:
            {
                int nrOfChars = ((String)value).Length + 1;
                length += TypeWriter.WriteUIntToStream(out1, (uint)nrOfChars);
                char[] s = Util.Pad4((String)value);
                for (int i = 0; i < s.Length; i++)
                {
                    int  high  = ((s[i] & 0x0000ff00) >> 8);
                    int  low   = (s[i] & 0x000000ff);
                    byte highb = (byte)high;
                    byte lowb  = (byte)low;
                    out1.WriteByte(lowb);
                    out1.WriteByte(highb);
                    length += 2;
                }
                out1.WriteByte(0x00);
                out1.WriteByte(0x00);
                length += 2;
                break;
            }

            case Variant.VT_CF:
            {
                byte[] b = (byte[])value;
                out1.Write(b, 0, b.Length);
                length = b.Length;
                break;
            }

            case Variant.VT_EMPTY:
            {
                TypeWriter.WriteUIntToStream(out1, Variant.VT_EMPTY);
                length = LittleEndianConsts.INT_SIZE;
                break;
            }

            case Variant.VT_I2:
            {
                short x;
                try
                {
                    x = Convert.ToInt16(value, CultureInfo.InvariantCulture);
                }catch (OverflowException)
                {
                    x = (short)((int)value);
                }
                TypeWriter.WriteToStream(out1, x);
                length = LittleEndianConsts.SHORT_SIZE;
                break;
            }

            case Variant.VT_I4:
            {
                if (!(value is int))
                {
                    throw new Exception("Could not cast an object To "
                                        + "int" + ": "
                                        + value.GetType().Name + ", "
                                        + value.ToString());
                }
                length += TypeWriter.WriteToStream(out1, (int)value);
                break;
            }

            case Variant.VT_I8:
            {
                TypeWriter.WriteToStream(out1, Convert.ToInt64(value, CultureInfo.CurrentCulture));
                length = LittleEndianConsts.LONG_SIZE;
                break;
            }

            case Variant.VT_R8:
            {
                length += TypeWriter.WriteToStream(out1,
                                                   (Double)value);
                break;
            }

            case Variant.VT_FILETIME:
            {
                long filetime;
                if (value != null)
                {
                    filetime = Util.DateToFileTime((DateTime)value);
                }
                else
                {
                    filetime = 0;
                }
                int high = (int)((filetime >> 32) & 0x00000000FFFFFFFFL);
                int low  = (int)(filetime & 0x00000000FFFFFFFFL);
                length += TypeWriter.WriteUIntToStream
                              (out1, (uint)(0x0000000FFFFFFFFL & low));
                length += TypeWriter.WriteUIntToStream
                              (out1, (uint)(0x0000000FFFFFFFFL & high));

                break;
            }

            default:
            {
                /* The variant type is not supported yet. However, if the value
                 * is a byte array we can Write it nevertheless. */
                if (value is byte[])
                {
                    byte[] b = (byte[])value;
                    out1.Write(b, 0, b.Length);
                    length = b.Length;
                    WriteUnsupportedTypeMessage
                        (new WritingNotSupportedException(type, value));
                }
                else
                {
                    throw new WritingNotSupportedException(type, value);
                }
                break;
            }
            }

            return(length);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Writes the section's dictionary
        /// </summary>
        /// <param name="out1">The output stream To Write To.</param>
        /// <param name="dictionary">The dictionary.</param>
        /// <param name="codepage">The codepage to be used to Write the dictionary items.</param>
        /// <returns>The number of bytes written</returns>
        /// <remarks>
        /// see MSDN KB: http://msdn.microsoft.com/en-us/library/aa380065(VS.85).aspx
        /// </remarks>
        private static int WriteDictionary(Stream out1,
                                           IDictionary dictionary, int codepage)
        {
            int length = TypeWriter.WriteUIntToStream(out1, (uint)dictionary.Count);

            for (IEnumerator i = dictionary.Keys.GetEnumerator(); i.MoveNext();)
            {
                long   key   = Convert.ToInt64(i.Current, CultureInfo.InvariantCulture);
                String value = (String)dictionary[key];
                //tony qu added: some key is int32 instead of int64
                if (value == null)
                {
                    value = (String)dictionary[(int)key];
                }

                if (codepage == (int)Constants.CP_UNICODE)
                {
                    /* Write the dictionary item in Unicode. */
                    int sLength = value.Length + 1;
                    if (sLength % 2 == 1)
                    {
                        sLength++;
                    }
                    length += TypeWriter.WriteUIntToStream(out1, (uint)key);
                    length += TypeWriter.WriteUIntToStream(out1, (uint)sLength);
                    byte[] ca =
                        Encoding.GetEncoding(codepage).GetBytes(value);
                    for (int j = 0; j < ca.Length; j += 2)   //Tony qu fixed the bug
                    {
                        out1.WriteByte(ca[j + 1]);
                        out1.WriteByte(ca[j]);
                        length += 2;
                    }
                    sLength -= value.Length;
                    while (sLength > 0)
                    {
                        out1.WriteByte(0x00);
                        out1.WriteByte(0x00);
                        length += 2;
                        sLength--;
                    }
                }
                else
                {
                    /* Write the dictionary item in another codepage than
                     * Unicode. */
                    length += TypeWriter.WriteUIntToStream(out1, (uint)key);
                    length += TypeWriter.WriteUIntToStream(out1, (uint)value.Length + 1);

                    try
                    {
                        byte[] ba =
                            Encoding.GetEncoding(codepage).GetBytes(value);
                        for (int j = 0; j < ba.Length; j++)
                        {
                            out1.WriteByte(ba[j]);
                            length++;
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new IllegalPropertySetDataException(ex);
                    }

                    out1.WriteByte(0x00);
                    length++;
                }
            }
            return(length);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Writes this section into an output stream.
        /// Internally this is done by writing into three byte array output
        /// streams: one for the properties, one for the property list and one for
        /// the section as such. The two former are Appended To the latter when they
        /// have received all their data.
        /// </summary>
        /// <param name="out1">The stream To Write into.</param>
        /// <returns>The number of bytes written, i.e. the section's size.</returns>
        public int Write(Stream out1)
        {
            /* Check whether we have alReady generated the bytes making out the
             * section. */
            if (!dirty && sectionBytes != null)
            {
                out1.Write(sectionBytes, 0, sectionBytes.Length);
                return(sectionBytes.Length);
            }

            /* The properties are written To this stream. */
            using (MemoryStream propertyStream =
                       new MemoryStream())
            {
                /* The property list is established here. After each property that has
                 * been written To "propertyStream", a property list entry is written To
                 * "propertyListStream". */
                using (MemoryStream propertyListStream =
                           new MemoryStream())
                {
                    /* Maintain the current position in the list. */
                    int position = 0;

                    /* Increase the position variable by the size of the property list so
                     * that it points behind the property list and To the beginning of the
                     * properties themselves. */
                    position += 2 * LittleEndianConsts.INT_SIZE +
                                PropertyCount * 2 * LittleEndianConsts.INT_SIZE;

                    /* Writing the section's dictionary it tricky. If there is a dictionary
                     * (property 0) the codepage property (property 1) must be Set, Too. */
                    int codepage = -1;
                    if (GetProperty(PropertyIDMap.PID_DICTIONARY) != null)
                    {
                        Object p1 = GetProperty(PropertyIDMap.PID_CODEPAGE);
                        if (p1 != null)
                        {
                            if (!(p1 is int))
                            {
                                throw new IllegalPropertySetDataException
                                          ("The codepage property (ID = 1) must be an " +
                                          "Integer object.");
                            }
                        }
                        else
                        {
                            /* Warning: The codepage property is not Set although a
                             * dictionary is present. In order To cope with this problem we
                             * Add the codepage property and Set it To Unicode. */
                            SetProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
                                        (int)Constants.CP_UNICODE);
                        }
                        codepage = Codepage;
                    }



                    /* Sort the property list by their property IDs: */
                    preprops.Sort(new PropertyComparer());

                    /* Write the properties and the property list into their respective
                     * streams: */
                    for (int i = 0; i < preprops.Count; i++)
                    {
                        MutableProperty p  = (MutableProperty)preprops[i];
                        long            id = p.ID;

                        /* Write the property list entry. */
                        TypeWriter.WriteUIntToStream(propertyListStream, (uint)p.ID);
                        TypeWriter.WriteUIntToStream(propertyListStream, (uint)position);

                        /* If the property ID is not equal 0 we Write the property and all
                         * is fine. However, if it Equals 0 we have To Write the section's
                         * dictionary which has an implicit type only and an explicit
                         * value. */
                        if (id != 0)
                        {
                            /* Write the property and update the position To the next
                             * property. */
                            position += p.Write(propertyStream, Codepage);
                        }
                        else
                        {
                            if (codepage == -1)
                            {
                                throw new IllegalPropertySetDataException
                                          ("Codepage (property 1) is undefined.");
                            }
                            position += WriteDictionary(propertyStream, dictionary,
                                                        codepage);
                        }
                    }
                    propertyStream.Flush();
                    propertyListStream.Flush();

                    /* Write the section: */
                    byte[] pb1 = propertyListStream.ToArray();
                    byte[] pb2 = propertyStream.ToArray();

                    /* Write the section's Length: */
                    TypeWriter.WriteToStream(out1, LittleEndianConsts.INT_SIZE * 2 +
                                             pb1.Length + pb2.Length);

                    /* Write the section's number of properties: */
                    TypeWriter.WriteToStream(out1, PropertyCount);

                    /* Write the property list: */
                    out1.Write(pb1, 0, pb1.Length);

                    /* Write the properties: */
                    out1.Write(pb2, 0, pb2.Length);

                    int streamLength = LittleEndianConsts.INT_SIZE * 2 + pb1.Length + pb2.Length;
                    return(streamLength);
                }
            }
        }