Ejemplo n.º 1
0
        StorageBasedPackageProperties(
            StorageRoot root
            )
        {
            _pss = (IPropertySetStorage)root.GetRootIStorage();

            //
            // Open the property sets with the same access with which the file itself
            // was opened.
            //
            _grfMode = SafeNativeCompoundFileConstants.STGM_DIRECT
                       | SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess(root.OpenAccess, ref _grfMode);

            OpenPropertyStorage(ref FormatId.SummaryInformation, out _psSummInfo);
            OpenPropertyStorage(ref FormatId.DocumentSummaryInformation, out _psDocSummInfo);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates a stream with the given parameters
        /// </summary>
        /// <param name="mode">Creation mode</param>
        /// <param name="access">Access mode</param>
        /// <param name="dataSpace">Data space encoding</param>
        /// <returns>Stream object to manipulate data</returns>
        internal Stream Create(FileMode mode, FileAccess access, string dataSpace)
        {
            CheckDisposedStatus();

            int              grfMode            = 0;
            IStream          createdSafeIStream = null;
            DataSpaceManager dataSpaceManager   = null;

            // Check to make sure root container is not read-only, and that
            //  we're not pointlessly trying to create a read-only stream.
            CreateTimeReadOnlyCheck(access);

            // Check to see if the data space label is valid
            if (null != dataSpace)
            {
                if (0 == dataSpace.Length)
                {
                    throw new ArgumentException(
                              SR.Get(SRID.DataSpaceLabelInvalidEmpty));
                }

                dataSpaceManager = parentStorage.Root.GetDataSpaceManager();
                if (!dataSpaceManager.DataSpaceIsDefined(dataSpace))
                {
                    throw new ArgumentException(
                              SR.Get(SRID.DataSpaceLabelUndefined));
                }
            }

            openFileAccess = access;
            // becasue of the stream caching mechanism we must adjust FileAccess parameter.
            // We want to open stream with the widest access posible, in case Package was open in ReadWrite
            // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly.
            // There is a possibility of a next request coming in as as ReadWrite request, and we would like to
            // take advanatage of the cached stream by wrapping with appropriate access limitations.
            if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite)
            {
                access = FileAccess.ReadWrite;
            }

            // Generate the access flags from the access parameter
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess(access, ref grfMode);

            // Only SHARE_EXCLUSIVE for now, FileShare issue TBD
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;

            CheckAccessMode(grfMode);

            // Act based on FileMode
            switch (mode)
            {
            case FileMode.Create:
                // Close down any existing streams floating out there
                if (null != core.exposedStream)
                {
                    ((Stream)(core.exposedStream)).Close();
                }
                core.exposedStream = null;

                if (null != core.safeIStream)
                {
                    // Release reference
                    ((IDisposable)core.safeIStream).Dispose();
                    core.safeIStream = null;
                }

                // Cleanup done, create new stream in its place.
                grfMode           |= SafeNativeCompoundFileConstants.STGM_CREATE;
                createdSafeIStream = CreateStreamOnParentIStorage(
                    core.streamName,
                    grfMode);
                break;

            case FileMode.CreateNew:
                // If we've created a CFStream, this fails because stream is already there.
                if (null != core.safeIStream)
                {
                    throw new IOException(
                              SR.Get(SRID.StreamAlreadyExist));
                }

                // Need to call Create API with NULL create flags
                createdSafeIStream = CreateStreamOnParentIStorage(
                    core.streamName,
                    grfMode);
                break;

            case FileMode.Append:       // None of these are valid in a Create
            case FileMode.Open:
            case FileMode.OpenOrCreate:
            case FileMode.Truncate:
            default:
                throw new ArgumentException(
                          SR.Get(SRID.FileModeInvalid));
            }

            core.safeIStream = createdSafeIStream;
            // At this point we passed all previous checks and got the underlying IStream.
            //  Set our data space label to the given label, and the stream to the retrieved stream.
            core.dataSpaceLabel = dataSpace;
            if (null != dataSpace)
            {
                dataSpaceManager.CreateDataSpaceMapping(
                    new CompoundFileStreamReference(parentStorage.FullNameInternal, core.streamName),
                    core.dataSpaceLabel);
            }

            Stream returnStream =
                BuildStreamOnUnderlyingIStream(core.safeIStream, openFileAccess, this);

            _needToGetTransformInfo = false;    // We created stream with the given dataspace setting
                                                //  so, there is no need to get the dataspace setting
            core.exposedStream = returnStream;

            return(returnStream);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Opens a stream with the given open mode flags and access flags
        /// </summary>
        /// <param name="mode">Open mode flags</param>
        /// <param name="access">File access flags</param>
        /// <returns>Stream object to manipulate data</returns>
        public Stream GetStream(FileMode mode, FileAccess access)
        {
            CheckDisposedStatus();

            int     grfMode       = 0;
            IStream openedIStream = null;

            openFileAccess = access;
            // becasue of the stream caching mechanism we must adjust FileAccess parameter.
            // We want to open stream with the widest access posible, in case Package was open in ReadWrite
            // we need to open stream in ReadWrite even if user explicitly asked us to do ReadOnly/WriteOnly.
            // There is a possibility of a next request coming in as as ReadWrite request, and we would like to
            // take advanatage of the cached stream by wrapping with appropriate access limitations.
            if (parentStorage.Root.OpenAccess == FileAccess.ReadWrite)
            {
                // Generate the access flags from the access parameter
                access = FileAccess.ReadWrite;
            }

            // Generate the access flags from the access parameter
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess(access, ref grfMode);

            // Only SHARE_EXCLUSIVE for now, FileShare issue TBD
            grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;

            CheckAccessMode(grfMode);

            // Act based on FileMode
            switch (mode)
            {
            case FileMode.Append:
                throw new ArgumentException(
                          SR.Get(SRID.FileModeUnsupported));

            case FileMode.Create:
                // Check to make sure root container is not read-only, and that
                //  we're not pointlessly trying to create a read-only stream.
                CreateTimeReadOnlyCheck(openFileAccess);

                // Close down any existing streams floating out there
                if (null != core.exposedStream)
                {
                    ((Stream)(core.exposedStream)).Close();
                }
                core.exposedStream = null;

                if (null != core.safeIStream)
                {
                    // Close out existing stream
                    ((IDisposable)core.safeIStream).Dispose();
                    core.safeIStream = null;
                }

                // Cleanup done, create new stream in its place
                grfMode      |= SafeNativeCompoundFileConstants.STGM_CREATE;
                openedIStream = CreateStreamOnParentIStorage(
                    core.streamName,
                    grfMode);
                break;

            case FileMode.CreateNew:
                throw new ArgumentException(
                          SR.Get(SRID.FileModeUnsupported));

            case FileMode.Open:
                // If we've got a stream, return a CFStream built from its clone
                if (null != core.safeIStream)
                {
                    return(CFStreamOfClone(openFileAccess));
                }

                // Need to call Open API with NULL open flags
                openedIStream = OpenStreamOnParentIStorage(
                    core.streamName,
                    grfMode);
                break;

            case FileMode.OpenOrCreate:
                // If we've got a stream, return a CFStream built from its clone
                if (null != core.safeIStream)
                {
                    return(CFStreamOfClone(openFileAccess));
                }

                // Skip creation attempt for read-only container or specifying
                //  read-only stream
                if (FileAccess.Read != parentStorage.Root.OpenAccess &&
                    FileAccess.Read != openFileAccess)
                {
                    // Try creating first.  If it already exists then do an open.  This
                    //  seems ugly but this method involves the fewest number of
                    //  managed/unmanaged transitions.

                    if (!parentStorage.Exists)
                    {
                        parentStorage.Create();
                    }
                    int nativeCallErrorCode =
                        parentStorage.SafeIStorage.CreateStream(
                            core.streamName,
                            grfMode,
                            0,
                            0,
                            out openedIStream);

                    if (SafeNativeCompoundFileConstants.S_OK != nativeCallErrorCode &&
                        SafeNativeCompoundFileConstants.STG_E_FILEALREADYEXISTS != nativeCallErrorCode)
                    {
                        throw new IOException(
                                  SR.Get(SRID.UnableToCreateStream),
                                  new COMException(
                                      SR.Get(SRID.NamedAPIFailure, "IStorage.CreateStream"),
                                      nativeCallErrorCode));
                    }

                    // Parent storage has changed - invalidate all standing enuemrators
                    parentStorage.InvalidateEnumerators();

                    // else - proceed with open
                }

                if (null == openedIStream)
                {
                    // If we make it here, it means the create stream call failed
                    //  because of a STG_E_FILEALREADYEXISTS
                    //  or container is read-only
                    openedIStream = OpenStreamOnParentIStorage(
                        core.streamName,
                        grfMode);
                }
                break;

            case FileMode.Truncate:
                throw new ArgumentException(
                          SR.Get(SRID.FileModeUnsupported));

            default:
                throw new ArgumentException(
                          SR.Get(SRID.FileModeInvalid));
            }

            core.safeIStream = openedIStream;

            Stream returnStream =
                BuildStreamOnUnderlyingIStream(core.safeIStream, openFileAccess, this);

            core.exposedStream = returnStream;

            return(returnStream);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        /// <summary>Open a container given all the settings</summary>
        /// <param name="path">Path to container on local file system</param>
        /// <param name="mode">See System.IO.FileMode in .NET SDK</param>
        /// <param name="access">See System.IO.FileAccess in .NET SDK</param>
        /// <param name="share">See System.IO.FileShare in .NET SDK</param>
        /// <param name="sectorSize">Compound File sector size, must be 512 or 4096</param>
        /// <returns>StorageRoot instance representing the file</returns>
        internal static StorageRoot Open(
            string path,
            FileMode mode,
            FileAccess access,
            FileShare share,
            int sectorSize)
        {
            int grfMode     = 0;
            int returnValue = 0;

            // Simple path validation
            ContainerUtilities.CheckStringAgainstNullAndEmpty(path, "Path");

            Guid IID_IStorage = new Guid(0x0000000B, 0x0000, 0x0000, 0xC0, 0x00,
                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

            IStorage newRootStorage;

            ////////////////////////////////////////////////////////////////////
            // Generate STGM from FileMode
            switch (mode)
            {
            case FileMode.Append:
                throw new ArgumentException(
                          SR.FileModeUnsupported);

            case FileMode.Create:
                grfMode |= SafeNativeCompoundFileConstants.STGM_CREATE;
                break;

            case FileMode.CreateNew:
            {
                FileInfo existTest = new FileInfo(path);
                if (existTest.Exists)
                {
                    throw new IOException(
                              SR.FileAlreadyExists);
                }
            }
                goto case FileMode.Create;

            case FileMode.Open:
                break;

            case FileMode.OpenOrCreate:
            {
                FileInfo existTest = new FileInfo(path);
                if (existTest.Exists)
                {
                    // File exists, use open code path
                    goto case FileMode.Open;
                }
                else
                {
                    // File does not exist, use create code path
                    goto case FileMode.Create;
                }
            }

            case FileMode.Truncate:
                throw new ArgumentException(
                          SR.FileModeUnsupported);

            default:
                throw new ArgumentException(
                          SR.FileModeInvalid);
            }

            // Generate the access flags from the access parameter
            SafeNativeCompoundFileMethods.UpdateModeFlagFromFileAccess(access, ref grfMode);

            // Generate STGM from FileShare

            // Note: the .NET SDK does not specify the proper behavior in reaction to
            //  incompatible flags being sent in together.  Should ArgumentException be
            //  thrown?  Or do some values "trump" others?
            if (0 != (share & FileShare.Inheritable))
            {
                throw new ArgumentException(
                          SR.FileShareUnsupported);
            }
            else if (share == FileShare.None) // FileShare.None is zero, using "&" to check causes unreachable code error
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;
            }
            else if (share == FileShare.Read)
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_WRITE;
            }
            else if (share == FileShare.Write)
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_READ; // Note that this makes little sense when we don't support combination of flags
            }
            else if (share == FileShare.ReadWrite)
            {
                grfMode |= SafeNativeCompoundFileConstants.STGM_SHARE_DENY_NONE;
            }
            else
            {
                throw new ArgumentException(
                          SR.FileShareInvalid);
            }

            if (0 != (grfMode & SafeNativeCompoundFileConstants.STGM_CREATE))
            {
                // STGM_CREATE set, call StgCreateStorageEx.
                returnValue = SafeNativeCompoundFileMethods.SafeStgCreateStorageEx(
                    path,
                    grfMode,
                    stgFormatDocFile,
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref IID_IStorage,
                    out newRootStorage);
            }
            else
            {
                // STGM_CREATE not set, call StgOpenStorageEx.
                returnValue = SafeNativeCompoundFileMethods.SafeStgOpenStorageEx(
                    path,
                    grfMode,
                    stgFormatDocFile,
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref IID_IStorage,
                    out newRootStorage);
            }

            switch (returnValue)
            {
            case SafeNativeCompoundFileConstants.S_OK:
                return(StorageRoot.CreateOnIStorage(
                           newRootStorage));

            case SafeNativeCompoundFileConstants.STG_E_FILENOTFOUND:
                throw new FileNotFoundException(
                          SR.ContainerNotFound);

            case SafeNativeCompoundFileConstants.STG_E_INVALIDFLAG:
                throw new ArgumentException(
                          SR.StorageFlagsUnsupported,
                          new COMException(
                              SR.CFAPIFailure,
                              returnValue));

            default:
                throw new IOException(
                          SR.ContainerCanNotOpen,
                          new COMException(
                              SR.CFAPIFailure,
                              returnValue));
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Create a container StorageRoot based on the given System.IO.Stream object
        /// </summary>
        /// <param name="baseStream">The new Stream upon which to build the new StorageRoot</param>
        /// <param name="mode">The mode (Open or Create) to use on the lock bytes</param>
        /// <returns>New StorageRoot object built on the given Stream</returns>
        internal static StorageRoot CreateOnStream(Stream baseStream, FileMode mode)
        {
            if (null == baseStream)
            {
                throw new ArgumentNullException("baseStream");
            }

            IStorage storageOnStream;
            int      returnValue;
            int      openFlags = SafeNativeCompoundFileConstants.STGM_SHARE_EXCLUSIVE;

            if (baseStream.CanRead)
            {
                if (baseStream.CanWrite)
                {
                    openFlags |= SafeNativeCompoundFileConstants.STGM_READWRITE;
                }
                else
                {
                    openFlags |= SafeNativeCompoundFileConstants.STGM_READ;

                    if (FileMode.Create == mode)
                    {
                        throw new ArgumentException(
                                  SR.CanNotCreateContainerOnReadOnlyStream);
                    }
                }
            }
            else
            {
                throw new ArgumentException(
                          SR.CanNotCreateStorageRootOnNonReadableStream);
            }

            if (FileMode.Create == mode)
            {
                returnValue = SafeNativeCompoundFileMethods.SafeStgCreateDocfileOnStream(
                    baseStream,
                    openFlags | SafeNativeCompoundFileConstants.STGM_CREATE,
                    out storageOnStream);
            }
            else if (FileMode.Open == mode)
            {
                returnValue = SafeNativeCompoundFileMethods.SafeStgOpenStorageOnStream(
                    baseStream,
                    openFlags,
                    out storageOnStream);
            }
            else
            {
                throw new ArgumentException(
                          SR.CreateModeMustBeCreateOrOpen);
            }

            switch ((uint)returnValue)
            {
            case SafeNativeCompoundFileConstants.S_OK:
                return(StorageRoot.CreateOnIStorage(
                           storageOnStream));

            default:
                throw new IOException(
                          SR.UnableToCreateOnStream,
                          new COMException(
                              SR.CFAPIFailure,
                              returnValue));
            }
        }