/// <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)); } }
/// <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)); } }