private unsafe AsyncSerialStream_AsyncResult BeginWriteCore(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int timeout)
        {
            // Create and store async stream class library specific data in the
            // async result
            AsyncSerialStream_AsyncResult asyncResult = new AsyncSerialStream_AsyncResult();
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject;
            asyncResult._isWrite = true;

            asyncResult._oldTimeout = WriteTimeout;        // set "old" timeout
            WriteTimeout = timeout;

            // For Synchronous IO, I could go with either a callback and using
            // the managed Monitor class, or I could create a handle and wait on it.
            ManualResetEvent waitHandle = new ManualResetEvent(false);
            asyncResult._waitHandle = waitHandle;

            // Create a managed overlapped class
            // We will set the file offsets later
            Overlapped overlapped = new Overlapped(0, 0, 0, asyncResult);

            // Pack the Overlapped class, and store it in the async result
            NativeOverlapped* intOverlapped = overlapped.Pack(IOCallback);
            asyncResult._overlapped = intOverlapped;

            // Keep the array in one location in memory until the OS reads the
            // relevant data from the array.  Free GCHandle later.
            asyncResult.PinBuffer(array);

            int hr = 0;
            // queue an async WriteFile operation and pass in a packed overlapped
            int r = WriteFileNative(_handleProtector, array, offset, numBytes, intOverlapped, out hr);

            // WriteFile, the OS version, will return 0 on failure.  But
            // my WriteFileNative wrapper returns -1.  My wrapper will return
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // On async requests that completed sequentially, r==0
            // Note that you will NEVER RELIABLY be able to get the number of bytes
            // written back from this call when using overlapped IO!  You must
            // not pass in a non-null lpNumBytesWritten to WriteFile when using
            // overlapped structures!
            if (r == -1)
            {
                if (hr != NativeMethods.ERROR_IO_PENDING)
                {

                    if (hr == NativeMethods.ERROR_HANDLE_EOF)
                        InternalResources.EndOfFile();
                    else
                        InternalResources.WinIOError(hr, String.Empty);
                }
            }
            return asyncResult;
        }
        // ----SUBSECTION: internal methods supporting public read/write methods-------*
        private unsafe AsyncSerialStream_AsyncResult BeginReadCore(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int numBufferedBytesRead, int timeout)
        {
            // Create and store async stream class library specific data in the
            // async result
            AsyncSerialStream_AsyncResult asyncResult = new AsyncSerialStream_AsyncResult();
            asyncResult._userCallback = userCallback;
            asyncResult._userStateObject = stateObject;
            asyncResult._isWrite = false;

            asyncResult._oldTimeout = ReadTimeout; // store "old" timeout
            ReadTimeout = timeout;    // enforce timeouts in COMMTIMEOUTS structure

            // Must set this here to ensure all the state on the IAsyncResult
            // object is set before we call ReadFile, which gives the OS an
            // opportunity to run our callback (including the user callback &
            // the call to EndRead) before ReadFile has returned.
            asyncResult._numBufferedBytes = numBufferedBytesRead;

            // For Synchronous IO, I could go with either a callback and using
            // the managed Monitor class, or I could create a handle and wait on it.
            ManualResetEvent waitHandle = new ManualResetEvent(false);
            asyncResult._waitHandle = waitHandle;

            // Create a managed overlapped class
            // We will set the file offsets later
            Overlapped overlapped = new Overlapped(0, 0, 0, asyncResult);

            // Pack the Overlapped class, and store it in the async result
            NativeOverlapped* intOverlapped = overlapped.Pack(IOCallback);
            asyncResult._overlapped = intOverlapped;

            // Keep the array in one location in memory until the OS writes the
            // relevant data into the array.  Free GCHandle later.
            asyncResult.PinBuffer(array);

            // queue an async ReadFile operation and pass in a packed overlapped
            //int r = ReadFile(_handle, array, numBytes, null, intOverlapped);
            int hr = 0;
            int r = ReadFileNative(_handleProtector, array, offset, numBytes,
             intOverlapped, out hr);

            // ReadFile, the OS version, will return 0 on failure.  But
            // my ReadFileNative wrapper returns -1.  My wrapper will return
            // the following:
            // On error, r==-1.
            // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
            // on async requests that completed sequentially, r==0
            // Note that you will NEVER RELIABLY be able to get the number of bytes
            // read back from this call when using overlapped structures!  You must
            // not pass in a non-null lpNumBytesRead to ReadFile when using
            // overlapped structures!
            if (r == -1)
            {
                if (hr != NativeMethods.ERROR_IO_PENDING)
                {
                    if (hr == NativeMethods.ERROR_HANDLE_EOF)
                        InternalResources.EndOfFile();
                    else
                        InternalResources.WinIOError(hr, String.Empty);
                }
            }

            return asyncResult;
        }