internal ManagedPropSpec(PROPSPEC propSpec)
        {
            SecurityHelper.DemandUnmanagedCode();
            PropSpecType propType = (PropSpecType)propSpec.propType;

            if (propType == PropSpecType.Name)
            {
                this.PropName = Marshal.PtrToStringUni(propSpec.union.name);
                return;
            }
            if (propType == PropSpecType.Id)
            {
                this.PropId = propSpec.union.propId;
                return;
            }
            throw new ArgumentException(SR.Get("FilterPropSpecUnknownUnionSelector"), "propSpec");
        }
        internal static void MarshalPropSpec(ManagedPropSpec propSpec, ref PROPSPEC native)
        {
            native.propType = (uint)propSpec.PropType;
            PropSpecType propType = propSpec.PropType;

            if (propType == PropSpecType.Name)
            {
                native.union.name = Marshal.StringToCoTaskMemUni(propSpec.PropName);
                return;
            }
            if (propType == PropSpecType.Id)
            {
                native.union.propId = propSpec.PropId;
                return;
            }
            Invariant.Assert(false);
        }
        /// <summary>
        /// Marshal Managed to Native PROPSPEC
        /// </summary>
        /// <param name="propSpec"></param>
        /// <param name="native"></param>
        internal static void MarshalPropSpec(ManagedPropSpec propSpec, ref PROPSPEC native)
        {
            native.propType = (uint)propSpec.PropType;
            switch (propSpec.PropType)
            {
            case PropSpecType.Id:
                native.union.propId = (uint)propSpec.PropId;
                break;

            case PropSpecType.Name:
                native.union.name = Marshal.StringToCoTaskMemUni(propSpec.PropName);
                break;

            default:
                Invariant.Assert(false);     // propSpec.PropType is set by internal code in the filter logic.
                break;
            }
        }
Пример #4
0
        /// <summary>
        /// Create a ManagedPropSpec from an unmanaged one
        /// </summary>
        internal ManagedPropSpec(PROPSPEC propSpec)
        {
            // Assign to properties rather than fields to ensure consistency through side-effects.
            switch ((PropSpecType)propSpec.propType)
            {
            case PropSpecType.Id:
            {
                PropId = propSpec.union.propId;
                break;
            }

            case PropSpecType.Name:
            {
                PropName = Marshal.PtrToStringUni(propSpec.union.name);
                break;
            }

            default:
                throw new ArgumentException(SR.Get(SRID.FilterPropSpecUnknownUnionSelector), "propSpec");
            }
        }
Пример #5
0
        SetOleProperty(
            Guid fmtid,
            uint propId,
            object propVal
            )
        {
            CheckDisposed();

            IPropertyStorage ps =
                fmtid == FormatId.SummaryInformation ? _psSummInfo : _psDocSummInfo;

            if (ps == null)
            {
                //
                // The property set does not exist, so create it.
                //
                if (propVal != null)
                {
                    _pss.Create(
                        ref fmtid,
                        ref fmtid,
                        SafeNativeCompoundFileConstants.PROPSETFLAG_ANSI,
                        (uint)_grfMode,
                        out ps
                        );
                    if (fmtid == FormatId.SummaryInformation)
                    {
                        _psSummInfo = ps;
                    }
                    else
                    {
                        _psDocSummInfo = ps;
                    }
                }
                else
                {
                    //
                    // But if we were going to delete the property anyway, there's
                    // nothing to do.
                    //
                    return;
                }
            }

            PROPSPEC[]    propSpecs = new PROPSPEC[1];
            PROPVARIANT[] vals      = new PROPVARIANT[1];

            propSpecs[0].propType     = (uint)PropSpecType.Id;
            propSpecs[0].union.propId = propId;

            if (propVal == null)
            {
                //
                // New value is null => remove the property. Unlike in the case of ReadMultiple,
                // we can just let this one throw an exception on failure. There are no non-zero
                // success codes to worry about.
                //
                ps.DeleteMultiple(1, propSpecs);
                return;
            }

            //
            // New value is non-null => set a new value for the property.
            //
            IntPtr pszVal = IntPtr.Zero;

            try
            {
                if (propVal is string)
                {
                    //
                    // 1) We store string properties internally as UTF-16.
                    //    During save, convert the string (UTF-16) to CP_ACP and back
                    // 2) If property value changed during that process, store it in CF OLE Storage as UTF-8
                    // 3) Otherwise store it as CP_ACP
                    //
                    string inputString = propVal as string;

                    pszVal = Marshal.StringToCoTaskMemAnsi(inputString);
                    string convertedString = Marshal.PtrToStringAnsi(pszVal);

                    if (String.CompareOrdinal(inputString, convertedString) != 0)
                    {
                        // The string is not an ASCII string. Use UTF-8 to encode it!
                        byte[] byteArray = UTF8Encoding.UTF8.GetBytes(inputString);
                        int    nLen      = byteArray.Length;

                        //
                        // Before memory allocation for holding UTF-8 codes, we need to first free the memory
                        // allocated by Marshal.StringToCoTaskMemAnsi().
                        // Note that if there is any exception in this try scope, the memory will still be released
                        // by the finally of this try scope.
                        //
                        if (pszVal != IntPtr.Zero)
                        {
                            Marshal.FreeCoTaskMem(pszVal);
                            pszVal = IntPtr.Zero;
                        }

                        pszVal = Marshal.AllocCoTaskMem(checked (nLen + 1));  //The extra one byte is for the string terminator null.

                        Marshal.Copy(byteArray, 0, pszVal, nLen);
                        Marshal.WriteByte(pszVal, nLen, 0);     //Put the string terminator null at the end of the array.
                    }

                    vals[0].vt           = VARTYPE.VT_LPSTR;
                    vals[0].union.pszVal = pszVal;
                }
                else if (propVal is DateTime)
                {
                    // set FileTime as an Int64 to avoid pointer operations
                    vals[0].vt         = VARTYPE.VT_FILETIME;
                    vals[0].union.hVal = ((DateTime)propVal).ToFileTime();
                }
                else
                {
                    throw new ArgumentException(
                              SR.Get(SRID.InvalidDocumentPropertyType, propVal.GetType().ToString()),
                              "propVal");
                }

                //
                // Again, we can just let it throw on failure; no non-zero success codes. It won't throw
                // if the property doesn't exist.
                //
                ps.WriteMultiple(1, propSpecs, vals, 0);
            }
            finally
            {
                if (pszVal != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(pszVal);
                }
            }
        }
Пример #6
0
        GetOleProperty(
            Guid fmtid,
            uint propId
            )
        {
            CheckDisposed();

            // fmtid is always either DocSum or Sum.
            IPropertyStorage ps =
                fmtid == FormatId.SummaryInformation ? _psSummInfo : _psDocSummInfo;

            if (ps == null)
            {
                // This file doesn't even contain the property storage that this
                // property belongs to, so it certainly doesn't contain the property.
                return(null);
            }

            object obj = null;

            PROPSPEC[]    propSpecs = new PROPSPEC[1];
            PROPVARIANT[] vals      = new PROPVARIANT[1];

            propSpecs[0].propType     = (uint)PropSpecType.Id;
            propSpecs[0].union.propId = propId;

            VARTYPE vtExpected = GetVtFromPropId(fmtid, propId);

            int hresult = ps.ReadMultiple(1, propSpecs, vals);

            if (hresult == SafeNativeCompoundFileConstants.S_OK)
            {
                try
                {
                    if (vals[0].vt != vtExpected)
                    {
                        throw new FileFormatException(
                                  SR.Get(
                                      SRID.WrongDocumentPropertyVariantType,
                                      propId,
                                      fmtid.ToString(),
                                      vals[0].vt,
                                      vtExpected
                                      )
                                  );
                    }

                    switch (vals[0].vt)
                    {
                    case VARTYPE.VT_LPSTR:
                        //
                        // We store string properties as CP_ACP or UTF-8.
                        // But no matter which format the string was encoded, we always use the UTF-8
                        // encoder/decoder to decode the byte array, because the UTF-8 code of an ASCII
                        // string is the same as the ASCII string.
                        //
                        IntPtr pszVal = vals[0].union.pszVal;
                        //
                        // Because both the ASCII string and UTF-8 encoded string (byte array) are
                        // stored in a memory block (pszVal) terminated by null, we can use
                        // Marshal.PtrToStringAnsi(pszVal) to convert the memory block pointed by
                        // pszVal to a string. Then from the string.Length, we can get the number of
                        // bytes in the memory block. Otherwise, we cannot easily tell how many bytes
                        // are stored in pszVal without an extra parameter.
                        //
                        string ansiString = Marshal.PtrToStringAnsi(pszVal);
                        int    nLen       = ansiString.Length;

                        byte[] byteArray = new byte[nLen];
                        Marshal.Copy(pszVal, byteArray, 0, nLen);

                        obj = UTF8Encoding.UTF8.GetString(byteArray);
                        break;

                    case VARTYPE.VT_FILETIME:
                        //
                        // DateTime doesn't have a conversion from FILETIME. It has a
                        // misleadingly named "FromFileTime" method that actually wants
                        // a long. So...
                        //
                        obj = new Nullable <DateTime>(DateTime.FromFileTime(vals[0].union.hVal));
                        break;

                    default:
                        throw new FileFormatException(
                                  SR.Get(SRID.InvalidDocumentPropertyVariantType, vals[0].vt));
                    }
                }
                finally
                {
#pragma warning suppress 6031 // suppressing a "by design" ignored return value
                    SafeNativeCompoundFileMethods.SafePropVariantClear(ref vals[0]);
                }
            }
            else if (hresult == SafeNativeCompoundFileConstants.S_FALSE)
            {
                // Do nothing -- return the null object reference.
            }
            else
            {
                SecurityHelper.ThrowExceptionForHR(hresult);
            }

            return(obj);
        }
Пример #7
0
        internal static void MarshalPropSpec(ManagedPropSpec propSpec, ref PROPSPEC native)
        {
            native.propType = (uint)propSpec.PropType;
            switch (propSpec.PropType)
            {
                case PropSpecType.Id:
                    native.union.propId = (uint)propSpec.PropId;
                    break;

                case PropSpecType.Name:
                    native.union.name = Marshal.StringToCoTaskMemUni(propSpec.PropName);
                    break;

                default:
                    Invariant.Assert(false); // propSpec.PropType is set by internal code in the filter logic.
                    break;
            }
        }
        SetOleProperty(
            Guid fmtid,
            uint propId,
            object propVal
            )
        {
            CheckDisposed();

            IPropertyStorage ps =
                fmtid == FormatId.SummaryInformation ? _psSummInfo : _psDocSummInfo;

            if (ps == null)
            {
                //
                // The property set does not exist, so create it.
                //
                if (propVal != null)
                {
                    _pss.Create(
                            ref fmtid,
                            ref fmtid,
                            SafeNativeCompoundFileConstants.PROPSETFLAG_ANSI,
                            (uint)_grfMode,
                            out ps
                            );
                    if (fmtid == FormatId.SummaryInformation)
                    {
                        _psSummInfo = ps;
                    }
                    else
                    {
                        _psDocSummInfo = ps;
                    }
                }
                else
                {
                    //
                    // But if we were going to delete the property anyway, there's
                    // nothing to do.
                    //
                    return;
                }
            }

            PROPSPEC[] propSpecs = new PROPSPEC[1];
            PROPVARIANT[] vals = new PROPVARIANT[1];

            propSpecs[0].propType = (uint)PropSpecType.Id;
            propSpecs[0].union.propId = propId;

            if (propVal == null)
            {
                //
                // New value is null => remove the property. Unlike in the case of ReadMultiple,
                // we can just let this one throw an exception on failure. There are no non-zero
                // success codes to worry about.
                //
                ps.DeleteMultiple(1, propSpecs);
                return;
            }

            //
            // New value is non-null => set a new value for the property.
            //
            IntPtr pszVal = IntPtr.Zero;
            try
            {
                if (propVal is string)
                {
                    //
                    // 1) We store string properties internally as UTF-16. 
                    //    During save, convert the string (UTF-16) to CP_ACP and back
                    // 2) If property value changed during that process, store it in CF OLE Storage as UTF-8
                    // 3) Otherwise store it as CP_ACP
                    //
                    string inputString = propVal as string;

                    pszVal = Marshal.StringToCoTaskMemAnsi(inputString);
                    string convertedString = Marshal.PtrToStringAnsi(pszVal);

                    if (String.CompareOrdinal(inputString, convertedString) != 0)
                    {
                        // The string is not an ASCII string. Use UTF-8 to encode it!
                        byte[] byteArray = UTF8Encoding.UTF8.GetBytes(inputString);
                        int nLen = byteArray.Length;

                        //
                        // Before memory allocation for holding UTF-8 codes, we need to first free the memory
                        // allocated by Marshal.StringToCoTaskMemAnsi().
                        // Note that if there is any exception in this try scope, the memory will still be released
                        // by the finally of this try scope.
                        //
                        if (pszVal != IntPtr.Zero)
                        {
                            Marshal.FreeCoTaskMem(pszVal);
                            pszVal = IntPtr.Zero;
                        }

                        pszVal = Marshal.AllocCoTaskMem(checked(nLen + 1));  //The extra one byte is for the string terminator null.

                        Marshal.Copy(byteArray, 0, pszVal, nLen);
                        Marshal.WriteByte(pszVal, nLen, 0);     //Put the string terminator null at the end of the array.
                    }

                    vals[0].vt = VARTYPE.VT_LPSTR;
                    vals[0].union.pszVal = pszVal;
                }
                else if (propVal is DateTime)
                {
                    // set FileTime as an Int64 to avoid pointer operations
                    vals[0].vt = VARTYPE.VT_FILETIME;
                    vals[0].union.hVal = ((DateTime)propVal).ToFileTime();
                }
                else
                {
                    throw new ArgumentException(
                                SR.Get(SRID.InvalidDocumentPropertyType, propVal.GetType().ToString()),
                                "propVal");
                }

                //
                // Again, we can just let it throw on failure; no non-zero success codes. It won't throw
                // if the property doesn't exist.
                //
                ps.WriteMultiple(1, propSpecs, vals, 0);
            }
            finally
            {
                if (pszVal != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(pszVal);
                }
            }
        }
        GetOleProperty(
            Guid fmtid,
            uint propId
            )
        {
            CheckDisposed();

            // fmtid is always either DocSum or Sum.
            IPropertyStorage ps =
                fmtid == FormatId.SummaryInformation ? _psSummInfo : _psDocSummInfo;
            if (ps == null)
            {
                // This file doesn't even contain the property storage that this
                // property belongs to, so it certainly doesn't contain the property.
                return null;
            }

            object obj = null;

            PROPSPEC[] propSpecs = new PROPSPEC[1];
            PROPVARIANT[] vals = new PROPVARIANT[1];

            propSpecs[0].propType = (uint)PropSpecType.Id;
            propSpecs[0].union.propId = propId;

            VARTYPE vtExpected = GetVtFromPropId(fmtid, propId);

            int hresult = ps.ReadMultiple(1, propSpecs, vals);

            if (hresult == SafeNativeCompoundFileConstants.S_OK)
            {
                try
                {
                    if (vals[0].vt != vtExpected)
                    {
                        throw new FileFormatException(
                                        SR.Get(
                                            SRID.WrongDocumentPropertyVariantType,
                                            propId,
                                            fmtid.ToString(),
                                            vals[0].vt,
                                            vtExpected
                                            )
                                        );
                    }

                    switch (vals[0].vt)
                    {
                        case VARTYPE.VT_LPSTR:
                            //
                            // We store string properties as CP_ACP or UTF-8. 
                            // But no matter which format the string was encoded, we always use the UTF-8
                            // encoder/decoder to decode the byte array, because the UTF-8 code of an ASCII
                            // string is the same as the ASCII string.
                            //
                            IntPtr pszVal = vals[0].union.pszVal;
                            //
                            // Because both the ASCII string and UTF-8 encoded string (byte array) are
                            // stored in a memory block (pszVal) terminated by null, we can use 
                            // Marshal.PtrToStringAnsi(pszVal) to convert the memory block pointed by
                            // pszVal to a string. Then from the string.Length, we can get the number of
                            // bytes in the memory block. Otherwise, we cannot easily tell how many bytes
                            // are stored in pszVal without an extra parameter.
                            //
                            string ansiString = Marshal.PtrToStringAnsi(pszVal);
                            int nLen = ansiString.Length;

                            byte[] byteArray = new byte[nLen];
                            Marshal.Copy(pszVal, byteArray, 0, nLen);

                            obj = UTF8Encoding.UTF8.GetString(byteArray);
                            break;

                        case VARTYPE.VT_FILETIME:
                            //
                            // DateTime doesn't have a conversion from FILETIME. It has a
                            // misleadingly named "FromFileTime" method that actually wants
                            // a long. So...
                            //
                            obj = new Nullable<DateTime>(DateTime.FromFileTime(vals[0].union.hVal));
                            break;

                        default:
                            throw new FileFormatException(
                                        SR.Get(SRID.InvalidDocumentPropertyVariantType, vals[0].vt));
                    }
                }
                finally
                {
#pragma warning suppress 6031 // suppressing a "by design" ignored return value
                    SafeNativeCompoundFileMethods.SafePropVariantClear(ref vals[0]);
                }
            }
            else if (hresult == SafeNativeCompoundFileConstants.S_FALSE)
            {
                // Do nothing -- return the null object reference.
            }
            else
            {
                SecurityHelper.ThrowExceptionForHR(hresult);
            }

            return obj;
        }
Пример #10
0
        internal ManagedPropSpec(PROPSPEC propSpec) 
        {
            SecurityHelper.DemandUnmanagedCode(); 
 
            // Assign to properties rather than fields to ensure consistency through side-effects.
            switch ((PropSpecType)propSpec.propType) 
            {
                case PropSpecType.Id:
                    {
                        PropId = propSpec.union.propId; 
                        break;
                    } 
 
                case PropSpecType.Name:
                    { 
                        PropName = Marshal.PtrToStringUni(propSpec.union.name);
                        break;
                    }
                default: 
                    throw new ArgumentException(SR.Get(SRID.FilterPropSpecUnknownUnionSelector), "propSpec");
            } 
        }