private void OpenSqlFileStream ( string path, byte[] transactionContext, System.IO.FileAccess access, System.IO.FileOptions options, Int64 allocationSize ) { //----------------------------------------------------------------- // precondition validation // these should be checked by any caller of this method // ensure we have validated and normalized the path before Debug.Assert ( path != null ); Debug.Assert (transactionContext != null); if (access != FileAccess.Read && access != FileAccess.Write && access != FileAccess.ReadWrite) throw ADP.ArgumentOutOfRange ("access"); // FileOptions is a set of flags, so AND the given value against the set of values we do not support if ( ( options & ~( FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.SequentialScan ) ) != 0 ) throw ADP.ArgumentOutOfRange ( "options" ); //----------------------------------------------------------------- // normalize the provided path // * compress path to remove any occurences of '.' or '..' // * trim whitespace from the beginning and end of the path // * ensure that the path starts with '\\' // * ensure that the path does not start with '\\.\' // * ensure that the path is not longer than Int16.MaxValue path = GetFullPathInternal ( path ); // ensure the running code has permission to read/write the file DemandAccessPermission(path, access); FileFullEaInformation eaBuffer = null; SecurityQualityOfService qos = null; UnicodeString objectName = null; Microsoft.Win32.SafeHandles.SafeFileHandle hFile = null; int nDesiredAccess = UnsafeNativeMethods.FILE_READ_ATTRIBUTES | UnsafeNativeMethods.SYNCHRONIZE; UInt32 dwCreateOptions = 0; UInt32 dwCreateDisposition = 0; System.IO.FileShare shareAccess = System.IO.FileShare.None; switch (access) { case System.IO.FileAccess.Read: nDesiredAccess |= UnsafeNativeMethods.FILE_READ_DATA; shareAccess = System.IO.FileShare.Delete | System.IO.FileShare.ReadWrite; dwCreateDisposition = (uint) UnsafeNativeMethods.CreationDisposition.FILE_OPEN; break; case System.IO.FileAccess.Write: nDesiredAccess |= UnsafeNativeMethods.FILE_WRITE_DATA; shareAccess = System.IO.FileShare.Delete | System.IO.FileShare.Read; dwCreateDisposition = (uint) UnsafeNativeMethods.CreationDisposition.FILE_OVERWRITE; break; case System.IO.FileAccess.ReadWrite: default: // we validate the value of 'access' parameter in the beginning of this method Debug.Assert(access == System.IO.FileAccess.ReadWrite); nDesiredAccess |= UnsafeNativeMethods.FILE_READ_DATA | UnsafeNativeMethods.FILE_WRITE_DATA; shareAccess = System.IO.FileShare.Delete | System.IO.FileShare.Read; dwCreateDisposition = (uint) UnsafeNativeMethods.CreationDisposition.FILE_OVERWRITE; break; } if ((options & System.IO.FileOptions.WriteThrough) != 0) { dwCreateOptions |= (uint) UnsafeNativeMethods.CreateOption.FILE_WRITE_THROUGH; } if ((options & System.IO.FileOptions.Asynchronous) == 0) { dwCreateOptions |= (uint) UnsafeNativeMethods.CreateOption.FILE_SYNCHRONOUS_IO_NONALERT; } if ((options & System.IO.FileOptions.SequentialScan) != 0) { dwCreateOptions |= (uint) UnsafeNativeMethods.CreateOption.FILE_SEQUENTIAL_ONLY; } if ( (options & System.IO.FileOptions.RandomAccess) != 0) { dwCreateOptions |= (uint) UnsafeNativeMethods.CreateOption.FILE_RANDOM_ACCESS; } try { eaBuffer = new FileFullEaInformation(transactionContext); qos = new SecurityQualityOfService(UnsafeNativeMethods.SecurityImpersonationLevel.SecurityAnonymous, false, false); // NOTE: the Name property is intended to reveal the publicly available moniker for the // FILESTREAM attributed column data. We will not surface the internal processing that // takes place to create the mappedPath. string mappedPath = InitializeNtPath(path); objectName = new UnicodeString(mappedPath); UnsafeNativeMethods.OBJECT_ATTRIBUTES oa; oa.length = Marshal.SizeOf(typeof(UnsafeNativeMethods.OBJECT_ATTRIBUTES)); oa.rootDirectory = IntPtr.Zero; oa.attributes = (int)UnsafeNativeMethods.Attributes.CaseInsensitive; oa.securityDescriptor = IntPtr.Zero; oa.securityQualityOfService = qos; oa.objectName = objectName; UnsafeNativeMethods.IO_STATUS_BLOCK ioStatusBlock; uint oldMode; uint retval = 0; UnsafeNativeMethods.SetErrorModeWrapper ( UnsafeNativeMethods.SEM_FAILCRITICALERRORS, out oldMode ); try { Bid.Trace("<sc.SqlFileStream.OpenSqlFileStream|ADV> %d#, desiredAccess=0x%08x, allocationSize=%I64d, fileAttributes=0x%08x, shareAccess=0x%08x, dwCreateDisposition=0x%08x, createOptions=0x%08x\n", ObjectID, (int) nDesiredAccess, allocationSize, 0, (int) shareAccess, dwCreateDisposition, dwCreateOptions ); retval = UnsafeNativeMethods.NtCreateFile(out hFile, nDesiredAccess, ref oa, out ioStatusBlock, ref allocationSize, 0, shareAccess, dwCreateDisposition, dwCreateOptions, eaBuffer, (uint) eaBuffer.Length); } finally { UnsafeNativeMethods.SetErrorModeWrapper( oldMode, out oldMode ); } switch ( retval ) { case 0: break; case UnsafeNativeMethods.STATUS_SHARING_VIOLATION: throw ADP.InvalidOperation ( Res.GetString ( Res.SqlFileStream_FileAlreadyInTransaction ) ); case UnsafeNativeMethods.STATUS_INVALID_PARAMETER: throw ADP.Argument ( Res.GetString ( Res.SqlFileStream_InvalidParameter ) ); case UnsafeNativeMethods.STATUS_OBJECT_NAME_NOT_FOUND: { System.IO.DirectoryNotFoundException e = new System.IO.DirectoryNotFoundException(); ADP.TraceExceptionAsReturnValue ( e ); throw e; } default: { uint error = UnsafeNativeMethods.RtlNtStatusToDosError ( retval ); if ( error == UnsafeNativeMethods.ERROR_MR_MID_NOT_FOUND ) { // status code could not be mapped to a Win32 error code error = retval; } System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception ( unchecked ( (int) error ) ); ADP.TraceExceptionAsReturnValue ( e ); throw e; } } if ( hFile.IsInvalid ) { System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception ( UnsafeNativeMethods.ERROR_INVALID_HANDLE ); ADP.TraceExceptionAsReturnValue ( e ); throw e; } UnsafeNativeMethods.FileType fileType = UnsafeNativeMethods.GetFileType(hFile); if (fileType != UnsafeNativeMethods.FileType.Disk) { hFile.Dispose(); throw ADP.Argument ( Res.GetString ( Res.SqlFileStream_PathNotValidDiskResource ) ); } // if the user is opening the SQL FileStream in read/write mode, we assume that they want to scan // through current data and then append new data to the end, so we need to tell SQL Server to preserve // the existing file contents. if ( access == System.IO.FileAccess.ReadWrite ) { uint ioControlCode = UnsafeNativeMethods.CTL_CODE ( UnsafeNativeMethods.FILE_DEVICE_FILE_SYSTEM, IoControlCodeFunctionCode, (byte) UnsafeNativeMethods.Method.METHOD_BUFFERED, (byte) UnsafeNativeMethods.Access.FILE_ANY_ACCESS); uint cbBytesReturned = 0; if ( !UnsafeNativeMethods.DeviceIoControl ( hFile, ioControlCode, IntPtr.Zero, 0, IntPtr.Zero, 0, out cbBytesReturned, IntPtr.Zero ) ) { System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception ( Marshal.GetLastWin32Error() ); ADP.TraceExceptionAsReturnValue ( e ); throw e; } } // now that we've successfully opened a handle on the path and verified that it is a file, // use the SafeFileHandle to initialize our internal System.IO.FileStream instance // NOTE: need to assert UnmanagedCode permissions for this constructor. This is relatively benign // in that we've done much the same validation as in the FileStream(string path, ...) ctor case // most notably, validating that the handle type corresponds to an on-disk file. bool bRevertAssert = false; try { SecurityPermission sp = new SecurityPermission ( SecurityPermissionFlag.UnmanagedCode ); sp.Assert(); bRevertAssert = true; System.Diagnostics.Debug.Assert ( m_fs == null ); #if MOBILE m_fs = new System.IO.FileStream ( hFile.DangerousGetHandle (), access, ( ( options & System.IO.FileOptions.Asynchronous ) != 0 ), DefaultBufferSize ); #else m_fs = new System.IO.FileStream ( hFile, access, DefaultBufferSize, ( ( options & System.IO.FileOptions.Asynchronous ) != 0 ) ); #endif } finally { if ( bRevertAssert ) SecurityPermission.RevertAssert(); } } catch { if ( hFile != null && !hFile.IsInvalid ) hFile.Dispose(); throw; } finally { if (eaBuffer != null) { eaBuffer.Dispose(); eaBuffer = null; } if (qos != null) { qos.Dispose(); qos = null; } if (objectName != null) { objectName.Dispose(); objectName = null; } } }
private void OpenSqlFileStream(string path, byte[] transactionContext, FileAccess access, FileOptions options, long allocationSize) { if (((access != FileAccess.Read) && (access != FileAccess.Write)) && (access != FileAccess.ReadWrite)) { throw ADP.ArgumentOutOfRange("access"); } if ((options & ~(FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)) != FileOptions.None) { throw ADP.ArgumentOutOfRange("options"); } path = GetFullPathInternal(path); DemandAccessPermission(path, access); FileFullEaInformation eaBuffer = null; SecurityQualityOfService service = null; UnicodeString str = null; SafeFileHandle fileHandle = null; int num2 = 0x100080; uint num = 0; uint num4 = 0; FileShare none = FileShare.None; switch (access) { case FileAccess.Read: num2 |= 1; none = FileShare.Delete | FileShare.ReadWrite; num4 = 1; break; case FileAccess.Write: num2 |= 2; none = FileShare.Delete | FileShare.Read; num4 = 4; break; default: num2 |= 3; none = FileShare.Delete | FileShare.Read; num4 = 4; break; } if ((options & (FileOptions.None | FileOptions.WriteThrough)) != FileOptions.None) { num |= 2; } if ((options & FileOptions.Asynchronous) == FileOptions.None) { num |= 0x20; } if ((options & FileOptions.SequentialScan) != FileOptions.None) { num |= 4; } if ((options & FileOptions.RandomAccess) != FileOptions.None) { num |= 0x800; } try { System.Data.SqlTypes.UnsafeNativeMethods.OBJECT_ATTRIBUTES object_attributes; eaBuffer = new FileFullEaInformation(transactionContext); service = new SecurityQualityOfService(System.Data.SqlTypes.UnsafeNativeMethods.SecurityImpersonationLevel.SecurityAnonymous, false, false); str = new UnicodeString(InitializeNtPath(path)); object_attributes.length = Marshal.SizeOf(typeof(System.Data.SqlTypes.UnsafeNativeMethods.OBJECT_ATTRIBUTES)); object_attributes.rootDirectory = IntPtr.Zero; object_attributes.attributes = 0x40; object_attributes.securityDescriptor = IntPtr.Zero; object_attributes.securityQualityOfService = service; object_attributes.objectName = str; uint mode = System.Data.SqlTypes.UnsafeNativeMethods.SetErrorMode(1); uint status = 0; try { System.Data.SqlTypes.UnsafeNativeMethods.IO_STATUS_BLOCK io_status_block; Bid.Trace("<sc.SqlFileStream.OpenSqlFileStream|ADV> %d#, desiredAccess=0x%08x, allocationSize=%I64d, fileAttributes=0x%08x, shareAccess=0x%08x, dwCreateDisposition=0x%08x, createOptions=0x%08x\n", this.ObjectID, num2, allocationSize, 0, (int) none, num4, num); status = System.Data.SqlTypes.UnsafeNativeMethods.NtCreateFile(out fileHandle, num2, ref object_attributes, out io_status_block, ref allocationSize, 0, none, num4, num, eaBuffer, (uint) eaBuffer.Length); } finally { System.Data.SqlTypes.UnsafeNativeMethods.SetErrorMode(mode); } switch (status) { case 0: break; case 0xc000000d: throw ADP.Argument(Res.GetString("SqlFileStream_InvalidParameter")); case 0xc0000034: { DirectoryNotFoundException e = new DirectoryNotFoundException(); ADP.TraceExceptionAsReturnValue(e); throw e; } case 0xc0000043: throw ADP.InvalidOperation(Res.GetString("SqlFileStream_FileAlreadyInTransaction")); default: { uint num6 = System.Data.SqlTypes.UnsafeNativeMethods.RtlNtStatusToDosError(status); if (num6 == 0x13d) { num6 = status; } Win32Exception exception3 = new Win32Exception((int) num6); ADP.TraceExceptionAsReturnValue(exception3); throw exception3; } } if (fileHandle.IsInvalid) { Win32Exception exception2 = new Win32Exception(6); ADP.TraceExceptionAsReturnValue(exception2); throw exception2; } if (System.Data.SqlTypes.UnsafeNativeMethods.GetFileType(fileHandle) != System.Data.SqlTypes.UnsafeNativeMethods.FileType.Disk) { fileHandle.Dispose(); throw ADP.Argument(Res.GetString("SqlFileStream_PathNotValidDiskResource")); } if (access == FileAccess.ReadWrite) { uint ioControlCode = System.Data.SqlTypes.UnsafeNativeMethods.CTL_CODE(9, 0x958, 0, 0); uint cbBytesReturned = 0; if (!System.Data.SqlTypes.UnsafeNativeMethods.DeviceIoControl(fileHandle, ioControlCode, IntPtr.Zero, 0, IntPtr.Zero, 0, out cbBytesReturned, IntPtr.Zero)) { Win32Exception exception = new Win32Exception(Marshal.GetLastWin32Error()); ADP.TraceExceptionAsReturnValue(exception); throw exception; } } bool flag = false; try { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); flag = true; this.m_fs = new FileStream(fileHandle, access, 1, (options & FileOptions.Asynchronous) != FileOptions.None); } finally { if (flag) { CodeAccessPermission.RevertAssert(); } } } catch { if ((fileHandle != null) && !fileHandle.IsInvalid) { fileHandle.Dispose(); } throw; } finally { if (eaBuffer != null) { eaBuffer.Dispose(); eaBuffer = null; } if (service != null) { service.Dispose(); service = null; } if (str != null) { str.Dispose(); str = null; } } }
private void OpenSqlFileStream(string path, byte[] transactionContext, FileAccess access, FileOptions options, long allocationSize) { if (((access != FileAccess.Read) && (access != FileAccess.Write)) && (access != FileAccess.ReadWrite)) { throw ADP.ArgumentOutOfRange("access"); } if ((options & ~(FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.SequentialScan | FileOptions.WriteThrough)) != FileOptions.None) { throw ADP.ArgumentOutOfRange("options"); } path = GetFullPathInternal(path); DemandAccessPermission(path, access); FileFullEaInformation eaBuffer = null; SecurityQualityOfService service = null; UnicodeString str = null; SafeFileHandle fileHandle = null; int num2 = 0x100080; uint num = 0; uint num4 = 0; FileShare none = FileShare.None; switch (access) { case FileAccess.Read: num2 |= 1; none = FileShare.Delete | FileShare.ReadWrite; num4 = 1; break; case FileAccess.Write: num2 |= 2; none = FileShare.Delete | FileShare.Read; num4 = 4; break; default: num2 |= 3; none = FileShare.Delete | FileShare.Read; num4 = 4; break; } if ((options & (FileOptions.None | FileOptions.WriteThrough)) != FileOptions.None) { num |= 2; } if ((options & FileOptions.Asynchronous) == FileOptions.None) { num |= 0x20; } if ((options & FileOptions.SequentialScan) != FileOptions.None) { num |= 4; } if ((options & FileOptions.RandomAccess) != FileOptions.None) { num |= 0x800; } try { System.Data.SqlTypes.UnsafeNativeMethods.OBJECT_ATTRIBUTES object_attributes; eaBuffer = new FileFullEaInformation(transactionContext); service = new SecurityQualityOfService(System.Data.SqlTypes.UnsafeNativeMethods.SecurityImpersonationLevel.SecurityAnonymous, false, false); str = new UnicodeString(InitializeNtPath(path)); object_attributes.length = Marshal.SizeOf(typeof(System.Data.SqlTypes.UnsafeNativeMethods.OBJECT_ATTRIBUTES)); object_attributes.rootDirectory = IntPtr.Zero; object_attributes.attributes = 0x40; object_attributes.securityDescriptor = IntPtr.Zero; object_attributes.securityQualityOfService = service; object_attributes.objectName = str; uint mode = System.Data.SqlTypes.UnsafeNativeMethods.SetErrorMode(1); uint status = 0; try { System.Data.SqlTypes.UnsafeNativeMethods.IO_STATUS_BLOCK io_status_block; Bid.Trace("<sc.SqlFileStream.OpenSqlFileStream|ADV> %d#, desiredAccess=0x%08x, allocationSize=%I64d, fileAttributes=0x%08x, shareAccess=0x%08x, dwCreateDisposition=0x%08x, createOptions=0x%08x\n", this.ObjectID, num2, allocationSize, 0, (int)none, num4, num); status = System.Data.SqlTypes.UnsafeNativeMethods.NtCreateFile(out fileHandle, num2, ref object_attributes, out io_status_block, ref allocationSize, 0, none, num4, num, eaBuffer, (uint)eaBuffer.Length); } finally { System.Data.SqlTypes.UnsafeNativeMethods.SetErrorMode(mode); } switch (status) { case 0: break; case 0xc000000d: throw ADP.Argument(Res.GetString("SqlFileStream_InvalidParameter")); case 0xc0000034: { DirectoryNotFoundException e = new DirectoryNotFoundException(); ADP.TraceExceptionAsReturnValue(e); throw e; } case 0xc0000043: throw ADP.InvalidOperation(Res.GetString("SqlFileStream_FileAlreadyInTransaction")); default: { uint num6 = System.Data.SqlTypes.UnsafeNativeMethods.RtlNtStatusToDosError(status); if (num6 == 0x13d) { num6 = status; } Win32Exception exception3 = new Win32Exception((int)num6); ADP.TraceExceptionAsReturnValue(exception3); throw exception3; } } if (fileHandle.IsInvalid) { Win32Exception exception2 = new Win32Exception(6); ADP.TraceExceptionAsReturnValue(exception2); throw exception2; } if (System.Data.SqlTypes.UnsafeNativeMethods.GetFileType(fileHandle) != System.Data.SqlTypes.UnsafeNativeMethods.FileType.Disk) { fileHandle.Dispose(); throw ADP.Argument(Res.GetString("SqlFileStream_PathNotValidDiskResource")); } if (access == FileAccess.ReadWrite) { uint ioControlCode = System.Data.SqlTypes.UnsafeNativeMethods.CTL_CODE(9, 0x958, 0, 0); uint cbBytesReturned = 0; if (!System.Data.SqlTypes.UnsafeNativeMethods.DeviceIoControl(fileHandle, ioControlCode, IntPtr.Zero, 0, IntPtr.Zero, 0, out cbBytesReturned, IntPtr.Zero)) { Win32Exception exception = new Win32Exception(Marshal.GetLastWin32Error()); ADP.TraceExceptionAsReturnValue(exception); throw exception; } } bool flag = false; try { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); flag = true; this.m_fs = new FileStream(fileHandle, access, 1, (options & FileOptions.Asynchronous) != FileOptions.None); } finally { if (flag) { CodeAccessPermission.RevertAssert(); } } } catch { if ((fileHandle != null) && !fileHandle.IsInvalid) { fileHandle.Dispose(); } throw; } finally { if (eaBuffer != null) { eaBuffer.Dispose(); eaBuffer = null; } if (service != null) { service.Dispose(); service = null; } if (str != null) { str.Dispose(); str = null; } } }