UnsafeNativeMethods.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Data / System / Data / SQLTypes / UnsafeNativeMethods.cs / 1305376 / UnsafeNativeMethods.cs

                            //------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

using System; 
using System.Diagnostics;
using System.Text;
using System.Runtime.InteropServices;
using System.Security; 
using Microsoft.Win32.SafeHandles;
using System.Data.Common; 
using System.Runtime.Versioning; 

namespace System.Data.SqlTypes 
{
    [SuppressUnmanagedCodeSecurity]
    internal static class UnsafeNativeMethods
    { 
        #region PInvoke methods
 
        [DllImport("NtDll.dll", CharSet = CharSet.Unicode)] 
        [ResourceExposure(ResourceScope.Machine)]
        internal static extern UInt32 NtCreateFile 
            (
                out Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle,
                Int32 desiredAccess,
                ref OBJECT_ATTRIBUTES objectAttributes, 
                out IO_STATUS_BLOCK ioStatusBlock,
                ref Int64 allocationSize, 
                UInt32 fileAttributes, 
                System.IO.FileShare shareAccess,
                UInt32 createDisposition, 
                UInt32 createOptions,
                SafeHandle eaBuffer,
                UInt32 eaLength
            ); 

        [DllImport("Kernel32.dll", SetLastError = true)] 
        [ResourceExposure(ResourceScope.None)] 
        internal static extern FileType GetFileType
            ( 
                Microsoft.Win32.SafeHandles.SafeFileHandle hFile
            );

        // do not use this PInvoke directly, use SafeGetFullPathName instead 
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        [ResourceExposure(ResourceScope.Machine)] 
        private static extern int GetFullPathName 
            (
                string path, 
                int numBufferChars,
                StringBuilder buffer,
                IntPtr lpFilePartOrNull
            ); 

        ///  
        /// safe wrapper for GetFullPathName 
        /// check that the path length is less than Int16.MaxValue before calling this API!
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        internal static string SafeGetFullPathName(string path)
        { 
            Debug.Assert(path != null, "path is null?");
            // make sure to test for Int16.MaxValue limit before calling this method 
            // see the below comment re GetLastWin32Error for the reason 
            Debug.Assert(path.Length < Int16.MaxValue);
 
            // since we expect network paths, the 'full path' is expected to be the same size
            // as the provided one. we still need to allocate +1 for null termination
            StringBuilder buffer = new StringBuilder(path.Length + 1);
 
            int cchRequiredSize = GetFullPathName(path, buffer.Capacity, buffer, IntPtr.Zero);
 
            // if our buffer was smaller than required, GetFullPathName will succeed and return us the required buffer size with null 
            if (cchRequiredSize > buffer.Capacity)
            { 
                // we have to reallocate and retry
                buffer.Capacity = cchRequiredSize;
                cchRequiredSize = GetFullPathName(path, buffer.Capacity, buffer, IntPtr.Zero);
            } 

            if (cchRequiredSize == 0) 
            { 
                // GetFullPathName call failed
                int lastError = Marshal.GetLastWin32Error(); 
                if (lastError == 0)
                {
                    // we found that in some cases GetFullPathName fail but does not set the last error value
                    // for example, it happens when the path provided to it is longer than 32K: return value is 0 (failure) 
                    // but GetLastError was zero too so we raised Win32Exception saying "The operation completed successfully".
                    // To raise proper "path too long" failure, check the length before calling this API. 
                    // For other (yet unknown cases), we will throw InvalidPath message since we do not know what exactly happened 
                    throw ADP.Argument(Res.GetString(Res.SqlFileStream_InvalidPath), "path");
                } 
                else
                {
                    System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(lastError);
                    ADP.TraceExceptionAsReturnValue(e); 
                    throw e;
                } 
            } 

            // this should not happen since we already reallocate 
            Debug.Assert(cchRequiredSize <= buffer.Capacity, string.Format(
                System.Globalization.CultureInfo.InvariantCulture,
                "second call to GetFullPathName returned greater size: {0} > {1}",
                cchRequiredSize, 
                buffer.Capacity));
 
            return buffer.ToString(); 
        }
 
        [DllImport("Kernel32.dll")]
        [ResourceExposure(ResourceScope.Process)]
        internal static extern uint SetErrorMode
            ( 
                uint mode
            ); 
 
        [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [ResourceExposure(ResourceScope.Machine)] 
        internal static extern bool DeviceIoControl
            (
                Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle,
                uint ioControlCode, 
                IntPtr inBuffer,
                uint cbInBuffer, 
                IntPtr outBuffer, 
                uint cbOutBuffer,
                out uint cbBytesReturned, 
                IntPtr overlapped
            );

        [DllImport("NtDll.dll")] 
        [ResourceExposure(ResourceScope.None)]
        internal static extern UInt32 RtlNtStatusToDosError 
            ( 
                UInt32 status
            ); 

        #region definitions from devioctl.h

        internal const ushort FILE_DEVICE_FILE_SYSTEM = 0x0009; 

        internal enum Method 
        { 
            METHOD_BUFFERED,
            METHOD_IN_DIRECT, 
            METHOD_OUT_DIRECT,
            METHOD_NEITHER
        };
 
        internal enum Access
        { 
            FILE_ANY_ACCESS, 
            FILE_READ_ACCESS,
            FILE_WRITE_ACCESS 
        }

        internal static uint CTL_CODE
            ( 
                ushort deviceType,
                ushort function, 
                byte method, 
                byte access
            ) 
        {
            if ( function > 4095 )
                throw ADP.ArgumentOutOfRange ( "function" );
 
            return (uint) ( ( deviceType << 16 ) | ( access << 14 ) | ( function << 2 ) | method );
        } 
 
        #endregion
 
        #endregion

        #region Error codes
 
        internal const int ERROR_INVALID_HANDLE             = 6;
        internal const int ERROR_MR_MID_NOT_FOUND           = 317; 
 
        internal const uint STATUS_INVALID_PARAMETER        = 0xc000000d;
        internal const uint STATUS_SHARING_VIOLATION        = 0xc0000043; 
        internal const uint STATUS_OBJECT_NAME_NOT_FOUND    = 0xc0000034;

        #endregion
 
        internal const uint SEM_FAILCRITICALERRORS = 0x0001;
 
        internal enum FileType : uint 
        {
            Unknown = 0x0000,   // FILE_TYPE_UNKNOWN 
            Disk    = 0x0001,   // FILE_TYPE_DISK
            Char    = 0x0002,   // FILE_TYPE_CHAR
            Pipe    = 0x0003,   // FILE_TYPE_PIPE
            Remote  = 0x8000    // FILE_TYPE_REMOTE 
        }
 
        #region definitions from wdm.h 

        [StructLayoutAttribute(LayoutKind.Sequential)] 
        internal struct OBJECT_ATTRIBUTES
        {
            internal int length;
            internal IntPtr rootDirectory; 
            internal SafeHandle objectName;
            internal int attributes; 
            internal IntPtr securityDescriptor; 
            internal SafeHandle securityQualityOfService;
        } 

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct UNICODE_STRING
        { 
            internal UInt16 length;
            internal UInt16 maximumLength; 
            internal string buffer; 
        }
 
        // VSTFDevDiv # 547461 [Backport SqlFileStream fix on Win7 to QFE branch]
        // Win7 enforces correct values for the _SECURITY_QUALITY_OF_SERVICE.qos member.
        // taken from _SECURITY_IMPERSONATION_LEVEL enum definition in winnt.h
        internal enum SecurityImpersonationLevel 
        {
            SecurityAnonymous, 
            SecurityIdentification, 
            SecurityImpersonation,
            SecurityDelegation 
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        internal struct SECURITY_QUALITY_OF_SERVICE 
        {
            internal UInt32 length; 
            [MarshalAs(UnmanagedType.I4)] 
            internal int impersonationLevel;
            internal byte contextDynamicTrackingMode; 
            internal byte effectiveOnly;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)] 
        internal struct IO_STATUS_BLOCK
        { 
            internal UInt32 status; 
            internal IntPtr information;
        } 

        [StructLayoutAttribute(LayoutKind.Sequential)]
        internal struct FILE_FULL_EA_INFORMATION
        { 
            internal UInt32 nextEntryOffset;
            internal Byte flags; 
            internal Byte EaNameLength; 
            internal UInt16 EaValueLength;
            internal Byte EaName; 
        }

        [Flags]
        internal enum CreateOption : uint 
        {
            FILE_WRITE_THROUGH = 0x00000002, 
            FILE_SEQUENTIAL_ONLY = 0x00000004, 
            FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008,
            FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020, 
            FILE_RANDOM_ACCESS = 0x00000800
        }

        internal enum CreationDisposition : uint 
        {
            FILE_SUPERSEDE = 0, 
            FILE_OPEN = 1, 
            FILE_CREATE = 2,
            FILE_OPEN_IF = 3, 
            FILE_OVERWRITE = 4,
            FILE_OVERWRITE_IF = 5
        }
 
        #endregion
 
        #region definitions from winnt.h 

        internal const int FILE_READ_DATA       = 0x0001; 
        internal const int FILE_WRITE_DATA      = 0x0002;
        internal const int FILE_READ_ATTRIBUTES = 0x0080;
        internal const int SYNCHRONIZE          = 0x00100000;
 
        #endregion
 
        #region definitions from ntdef.h 

        [Flags] 
        internal enum Attributes : uint
        {
            Inherit             = 0x00000002,
            Permanent           = 0x00000010, 
            Exclusive           = 0x00000020,
            CaseInsensitive     = 0x00000040, 
            OpenIf              = 0x00000080, 
            OpenLink            = 0x00000100,
            KernelHandle        = 0x00000200, 
            ForceAccessCheck    = 0x00000400,
            ValidAttributes     = 0x000007F2
        }
 
        #endregion
 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
// [....] 
//----------------------------------------------------------------------------- 

using System; 
using System.Diagnostics;
using System.Text;
using System.Runtime.InteropServices;
using System.Security; 
using Microsoft.Win32.SafeHandles;
using System.Data.Common; 
using System.Runtime.Versioning; 

namespace System.Data.SqlTypes 
{
    [SuppressUnmanagedCodeSecurity]
    internal static class UnsafeNativeMethods
    { 
        #region PInvoke methods
 
        [DllImport("NtDll.dll", CharSet = CharSet.Unicode)] 
        [ResourceExposure(ResourceScope.Machine)]
        internal static extern UInt32 NtCreateFile 
            (
                out Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle,
                Int32 desiredAccess,
                ref OBJECT_ATTRIBUTES objectAttributes, 
                out IO_STATUS_BLOCK ioStatusBlock,
                ref Int64 allocationSize, 
                UInt32 fileAttributes, 
                System.IO.FileShare shareAccess,
                UInt32 createDisposition, 
                UInt32 createOptions,
                SafeHandle eaBuffer,
                UInt32 eaLength
            ); 

        [DllImport("Kernel32.dll", SetLastError = true)] 
        [ResourceExposure(ResourceScope.None)] 
        internal static extern FileType GetFileType
            ( 
                Microsoft.Win32.SafeHandles.SafeFileHandle hFile
            );

        // do not use this PInvoke directly, use SafeGetFullPathName instead 
        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        [ResourceExposure(ResourceScope.Machine)] 
        private static extern int GetFullPathName 
            (
                string path, 
                int numBufferChars,
                StringBuilder buffer,
                IntPtr lpFilePartOrNull
            ); 

        ///  
        /// safe wrapper for GetFullPathName 
        /// check that the path length is less than Int16.MaxValue before calling this API!
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        internal static string SafeGetFullPathName(string path)
        { 
            Debug.Assert(path != null, "path is null?");
            // make sure to test for Int16.MaxValue limit before calling this method 
            // see the below comment re GetLastWin32Error for the reason 
            Debug.Assert(path.Length < Int16.MaxValue);
 
            // since we expect network paths, the 'full path' is expected to be the same size
            // as the provided one. we still need to allocate +1 for null termination
            StringBuilder buffer = new StringBuilder(path.Length + 1);
 
            int cchRequiredSize = GetFullPathName(path, buffer.Capacity, buffer, IntPtr.Zero);
 
            // if our buffer was smaller than required, GetFullPathName will succeed and return us the required buffer size with null 
            if (cchRequiredSize > buffer.Capacity)
            { 
                // we have to reallocate and retry
                buffer.Capacity = cchRequiredSize;
                cchRequiredSize = GetFullPathName(path, buffer.Capacity, buffer, IntPtr.Zero);
            } 

            if (cchRequiredSize == 0) 
            { 
                // GetFullPathName call failed
                int lastError = Marshal.GetLastWin32Error(); 
                if (lastError == 0)
                {
                    // we found that in some cases GetFullPathName fail but does not set the last error value
                    // for example, it happens when the path provided to it is longer than 32K: return value is 0 (failure) 
                    // but GetLastError was zero too so we raised Win32Exception saying "The operation completed successfully".
                    // To raise proper "path too long" failure, check the length before calling this API. 
                    // For other (yet unknown cases), we will throw InvalidPath message since we do not know what exactly happened 
                    throw ADP.Argument(Res.GetString(Res.SqlFileStream_InvalidPath), "path");
                } 
                else
                {
                    System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(lastError);
                    ADP.TraceExceptionAsReturnValue(e); 
                    throw e;
                } 
            } 

            // this should not happen since we already reallocate 
            Debug.Assert(cchRequiredSize <= buffer.Capacity, string.Format(
                System.Globalization.CultureInfo.InvariantCulture,
                "second call to GetFullPathName returned greater size: {0} > {1}",
                cchRequiredSize, 
                buffer.Capacity));
 
            return buffer.ToString(); 
        }
 
        [DllImport("Kernel32.dll")]
        [ResourceExposure(ResourceScope.Process)]
        internal static extern uint SetErrorMode
            ( 
                uint mode
            ); 
 
        [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        [ResourceExposure(ResourceScope.Machine)] 
        internal static extern bool DeviceIoControl
            (
                Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle,
                uint ioControlCode, 
                IntPtr inBuffer,
                uint cbInBuffer, 
                IntPtr outBuffer, 
                uint cbOutBuffer,
                out uint cbBytesReturned, 
                IntPtr overlapped
            );

        [DllImport("NtDll.dll")] 
        [ResourceExposure(ResourceScope.None)]
        internal static extern UInt32 RtlNtStatusToDosError 
            ( 
                UInt32 status
            ); 

        #region definitions from devioctl.h

        internal const ushort FILE_DEVICE_FILE_SYSTEM = 0x0009; 

        internal enum Method 
        { 
            METHOD_BUFFERED,
            METHOD_IN_DIRECT, 
            METHOD_OUT_DIRECT,
            METHOD_NEITHER
        };
 
        internal enum Access
        { 
            FILE_ANY_ACCESS, 
            FILE_READ_ACCESS,
            FILE_WRITE_ACCESS 
        }

        internal static uint CTL_CODE
            ( 
                ushort deviceType,
                ushort function, 
                byte method, 
                byte access
            ) 
        {
            if ( function > 4095 )
                throw ADP.ArgumentOutOfRange ( "function" );
 
            return (uint) ( ( deviceType << 16 ) | ( access << 14 ) | ( function << 2 ) | method );
        } 
 
        #endregion
 
        #endregion

        #region Error codes
 
        internal const int ERROR_INVALID_HANDLE             = 6;
        internal const int ERROR_MR_MID_NOT_FOUND           = 317; 
 
        internal const uint STATUS_INVALID_PARAMETER        = 0xc000000d;
        internal const uint STATUS_SHARING_VIOLATION        = 0xc0000043; 
        internal const uint STATUS_OBJECT_NAME_NOT_FOUND    = 0xc0000034;

        #endregion
 
        internal const uint SEM_FAILCRITICALERRORS = 0x0001;
 
        internal enum FileType : uint 
        {
            Unknown = 0x0000,   // FILE_TYPE_UNKNOWN 
            Disk    = 0x0001,   // FILE_TYPE_DISK
            Char    = 0x0002,   // FILE_TYPE_CHAR
            Pipe    = 0x0003,   // FILE_TYPE_PIPE
            Remote  = 0x8000    // FILE_TYPE_REMOTE 
        }
 
        #region definitions from wdm.h 

        [StructLayoutAttribute(LayoutKind.Sequential)] 
        internal struct OBJECT_ATTRIBUTES
        {
            internal int length;
            internal IntPtr rootDirectory; 
            internal SafeHandle objectName;
            internal int attributes; 
            internal IntPtr securityDescriptor; 
            internal SafeHandle securityQualityOfService;
        } 

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct UNICODE_STRING
        { 
            internal UInt16 length;
            internal UInt16 maximumLength; 
            internal string buffer; 
        }
 
        // VSTFDevDiv # 547461 [Backport SqlFileStream fix on Win7 to QFE branch]
        // Win7 enforces correct values for the _SECURITY_QUALITY_OF_SERVICE.qos member.
        // taken from _SECURITY_IMPERSONATION_LEVEL enum definition in winnt.h
        internal enum SecurityImpersonationLevel 
        {
            SecurityAnonymous, 
            SecurityIdentification, 
            SecurityImpersonation,
            SecurityDelegation 
        }

        [StructLayoutAttribute(LayoutKind.Sequential)]
        internal struct SECURITY_QUALITY_OF_SERVICE 
        {
            internal UInt32 length; 
            [MarshalAs(UnmanagedType.I4)] 
            internal int impersonationLevel;
            internal byte contextDynamicTrackingMode; 
            internal byte effectiveOnly;
        }

        [StructLayoutAttribute(LayoutKind.Sequential)] 
        internal struct IO_STATUS_BLOCK
        { 
            internal UInt32 status; 
            internal IntPtr information;
        } 

        [StructLayoutAttribute(LayoutKind.Sequential)]
        internal struct FILE_FULL_EA_INFORMATION
        { 
            internal UInt32 nextEntryOffset;
            internal Byte flags; 
            internal Byte EaNameLength; 
            internal UInt16 EaValueLength;
            internal Byte EaName; 
        }

        [Flags]
        internal enum CreateOption : uint 
        {
            FILE_WRITE_THROUGH = 0x00000002, 
            FILE_SEQUENTIAL_ONLY = 0x00000004, 
            FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008,
            FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020, 
            FILE_RANDOM_ACCESS = 0x00000800
        }

        internal enum CreationDisposition : uint 
        {
            FILE_SUPERSEDE = 0, 
            FILE_OPEN = 1, 
            FILE_CREATE = 2,
            FILE_OPEN_IF = 3, 
            FILE_OVERWRITE = 4,
            FILE_OVERWRITE_IF = 5
        }
 
        #endregion
 
        #region definitions from winnt.h 

        internal const int FILE_READ_DATA       = 0x0001; 
        internal const int FILE_WRITE_DATA      = 0x0002;
        internal const int FILE_READ_ATTRIBUTES = 0x0080;
        internal const int SYNCHRONIZE          = 0x00100000;
 
        #endregion
 
        #region definitions from ntdef.h 

        [Flags] 
        internal enum Attributes : uint
        {
            Inherit             = 0x00000002,
            Permanent           = 0x00000010, 
            Exclusive           = 0x00000020,
            CaseInsensitive     = 0x00000040, 
            OpenIf              = 0x00000080, 
            OpenLink            = 0x00000100,
            KernelHandle        = 0x00000200, 
            ForceAccessCheck    = 0x00000400,
            ValidAttributes     = 0x000007F2
        }
 
        #endregion
 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK