Example #1
0
        /// <summary>
        /// Opens a new scope
        /// </summary>
        public static IDisposable Create()
        {
            var protector = new HandleProtector(Current);
            Current = protector;

            return protector;
        }
Example #2
0
        internal unsafe int WriteFileNative(HandleProtector hp, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr)
        {
            // Don't corrupt memory when multiple threads are erroneously writing
            // to this stream simultaneously.  (Note that the OS is reading from
            // the array we pass to WriteFile, but if we read beyond the end and
            // that memory isn't allocated, we could get an AV.)
            if (bytes.Length - offset < count)
                throw new IndexOutOfRangeException(InternalResources.GetResourceString("IndexOutOfRange_IORaceCondition"));

            // You can't use the fixed statement on an array of length 0.
            if (bytes.Length == 0)
            {
                hr = 0;
                return 0;
            }

            int numBytesWritten = 0;
            int r = 0;

            bool incremented = false;
            try
            {
                if (hp.TryAddRef(ref incremented))
                {
                    fixed (byte* p = bytes)
                    {
                        r = UnsafeNativeMethods.WriteFile(hp.Handle, p + offset, count, NativeMethods.NULL, overlapped);
                    }
                }
                else
                    hr = NativeMethods.ERROR_INVALID_HANDLE;  // Handle was closed.
            }
            finally
            {
                if (incremented) hp.Release();
            }

            if (r == 0)
            {
                hr = Marshal.GetLastWin32Error();
                // Note: we should never silently swallow an error here without some
                // extra work.  We must make sure that BeginWriteCore won't return an
                // IAsyncResult that will cause EndWrite to block, since the OS won't
                // call AsyncFSCallback for us.

                // For invalid handles, detect the error and mark our handle
                // as closed to give slightly better error messages.  Also
                // help ensure we avoid handle recycling bugs.
                if (hr == NativeMethods.ERROR_INVALID_HANDLE)
                    _handleProtector.ForciblyMarkAsClosed();

                return -1;
            }
            else
                hr = 0;
            return numBytesWritten;
        }
Example #3
0
        private HandleProtector _handleProtector; // See the HandleProtector class.

        #endregion Fields

        #region Constructors

        // -----------SECTION: constructor --------------------------*
        // this method is used by SerialPort upon SerialStream's creation
        internal SerialStream(string resource, int baudRate, Parity parity, int dataBits, StopBits stopBits, int readTimeout, int writeTimeout, Handshake handshake,
            bool dtrEnable, bool rtsEnable, bool discardNull, byte parityReplace)
        {
            //Error checking done in SerialPort.

            IntPtr tempHandle = UnsafeNativeMethods.CreateFile("\\\\.\\" + resource,
                NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE,
                0,    // comm devices must be opened w/exclusive-access
                NativeMethods.NULL, // no security attributes
                UnsafeNativeMethods.OPEN_EXISTING, // comm devices must use OPEN_EXISTING
                UnsafeNativeMethods.FILE_FLAG_OVERLAPPED |
                UnsafeNativeMethods.FILE_ATTRIBUTE_NORMAL,    // async I/O
                NativeMethods.NULL  // hTemplate must be NULL for comm devices
                );

            if (tempHandle == NativeMethods.INVALID_HANDLE_VALUE)
            {
                int errorCode = Marshal.GetLastWin32Error();
                switch (errorCode)
                {
                    case NativeMethods.ERROR_FILE_NOT_FOUND:
                        throw new FileNotFoundException("ERROR_FILE_NOT_FOUND", InternalResources.GetResourceString("IO.FileNotFound_FileName", resource));

                    case NativeMethods.ERROR_ACCESS_DENIED:
                        throw new UnauthorizedAccessException(InternalResources.GetResourceString("UnauthorizedAccess_IODenied_Path", resource));
                    default:
                        InternalResources.WinIOError();
                        break;
                }
            }

            if (UnsafeNativeMethods.GetFileType(tempHandle) != UnsafeNativeMethods.FILE_TYPE_CHAR)
                throw new ArgumentException("INVALID_RESOURCE_FILE", InternalResources.GetResourceString("Arg_InvalidResourceFile"));

            _handleProtector = new __HandleProtector(tempHandle, true);

            // set properties of the stream that exist as members in SerialStream
            this.portName = resource;
            this.handshake = handshake;
            this.dtrEnable = dtrEnable;
            this.rtsEnable = rtsEnable;
            this.parityReplace = parityReplace;

            tempBuf = new byte[1];            // used in ReadByte()

            // fill COMMPROPERTIES struct, which has our maximum allowed baud rate
            commProp = new UnsafeNativeMethods.COMMPROP();
            if (UnsafeNativeMethods.GetCommProperties(_handleProtector.Handle, ref commProp) == false)
            {
                UnsafeNativeMethods.CloseHandle(_handleProtector.Handle);
                InternalResources.WinIOError();
            }
            if (baudRate > commProp.dwMaxBaud)
                throw new ArgumentOutOfRangeException("baudRate", "Requested baud greater than maximum for this device driver = " + commProp.dwMaxBaud);

            comStat = new UnsafeNativeMethods.COMSTAT();
            // create internal DCB structure, initialize according to Platform SDK
            // standard: ms-help://MS.MSNDNQTR.2002APR.1003/hardware/commun_965u.htm
            dcb = new UnsafeNativeMethods.DCB();

            // set constant properties of the DCB
            InitializeDCB(baudRate, parity, dataBits, stopBits, discardNull);

            // set timeout defaults
            commTimeouts.ReadIntervalTimeout = (readTimeout == SerialPort.InfiniteTimeout) ? 0 : NativeMethods.MAXDWORD;
            commTimeouts.ReadTotalTimeoutMultiplier = (readTimeout > 0 && readTimeout != SerialPort.InfiniteTimeout)
                                                            ? NativeMethods.MAXDWORD : 0;
            commTimeouts.ReadTotalTimeoutConstant = (readTimeout > 0 && readTimeout != SerialPort.InfiniteTimeout) ?
                                                            readTimeout : 0;
            commTimeouts.WriteTotalTimeoutMultiplier = 0;
            commTimeouts.WriteTotalTimeoutConstant = ((writeTimeout == SerialPort.InfiniteTimeout) ?
                                                            0 : writeTimeout);
            // note - we cannot have a meaningful conception of a 0 write timeout, since every write takes at
            // least 0 mills.

            // set unmanaged timeout structure
            if (UnsafeNativeMethods.SetCommTimeouts(_handleProtector.Handle, ref commTimeouts) == false)
            {
                UnsafeNativeMethods.CloseHandle(_handleProtector.Handle);
                InternalResources.WinIOError();
            }

            if (!ThreadPool.BindHandle(_handleProtector.Handle))
            {
                throw new IOException(InternalResources.GetResourceString("IO.IO_BindHandleFailed"));
            }

            // prep. for starting event cycle.
            myWaitCommCallback = new WaitEventCallback(WaitForCommEvent);
            myAsyncCallback = new AsyncCallback(EndWaitForCommEvent);
            state = null;    // no need for new object, since we never use it.

            IAsyncResult ar = myWaitCommCallback.BeginInvoke(myAsyncCallback, state);
        }