예제 #1
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));
            }
        }
예제 #2
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));
            }
        }