internal static void WriteToSync <T>(this Stream stream, Stream toStream, long?copyLength, long?maxLength, bool calculateMd5, bool syncRead, ExecutionState <T> executionState, StreamDescriptor streamCopyState)
        {
            if (copyLength.HasValue && maxLength.HasValue)
            {
                throw new ArgumentException(SR.StreamLengthMismatch);
            }

            if (stream.CanSeek && maxLength.HasValue && stream.Length - stream.Position > maxLength)
            {
                throw new InvalidOperationException(SR.StreamLengthError);
            }

            if (stream.CanSeek && copyLength.HasValue && stream.Length - stream.Position < copyLength)
            {
                throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
            }

            byte[] buffer = new byte[GetBufferSize(stream)];

            if (streamCopyState != null && calculateMd5 && streamCopyState.Md5HashRef == null)
            {
                streamCopyState.Md5HashRef = new MD5Wrapper();
            }

            RegisteredWaitHandle waitHandle     = null;
            ManualResetEvent     completedEvent = null;

            if (!syncRead && executionState.OperationExpiryTime.HasValue)
            {
                completedEvent = new ManualResetEvent(false);
                waitHandle     = ThreadPool.RegisterWaitForSingleObject(
                    completedEvent,
                    StreamExtensions.MaximumCopyTimeCallback <T>,
                    executionState,
                    executionState.RemainingTimeout,
                    true);
            }

            try
            {
                long?bytesRemaining = copyLength;
                int  readCount;
                do
                {
                    if (executionState.OperationExpiryTime.HasValue && DateTime.Now.CompareTo(executionState.OperationExpiryTime.Value) > 0)
                    {
                        throw Exceptions.GenerateTimeoutException(executionState.Cmd != null ? executionState.Cmd.CurrentResult : null, null);
                    }

                    // Determine how many bytes to read this time so that no more than copyLength bytes are read
                    int bytesToRead = MinBytesToRead(bytesRemaining, buffer.Length);

                    if (bytesToRead == 0)
                    {
                        break;
                    }

                    // Read synchronously or asynchronously
                    readCount = syncRead
                                    ? stream.Read(buffer, 0, bytesToRead)
                                    : stream.EndRead(stream.BeginRead(buffer, 0, bytesToRead, null /* Callback */, null /* State */));

                    // Decrement bytes to write from bytes read
                    if (bytesRemaining.HasValue)
                    {
                        bytesRemaining -= readCount;
                    }

                    // Write
                    if (readCount > 0)
                    {
                        toStream.Write(buffer, 0, readCount);

                        // Update the StreamDescriptor after the bytes are successfully committed to the output stream
                        if (streamCopyState != null)
                        {
                            streamCopyState.Length += readCount;

                            if (maxLength.HasValue && streamCopyState.Length > maxLength.Value)
                            {
                                throw new InvalidOperationException(SR.StreamLengthError);
                            }

                            if (streamCopyState.Md5HashRef != null)
                            {
                                streamCopyState.Md5HashRef.UpdateHash(buffer, 0, readCount);
                            }
                        }
                    }
                }while (readCount != 0);

                if (bytesRemaining.HasValue && bytesRemaining != 0)
                {
                    throw new ArgumentOutOfRangeException("copyLength", SR.StreamLengthShortError);
                }
            }
            catch (Exception)
            {
                if (executionState.OperationExpiryTime.HasValue && DateTime.Now.CompareTo(executionState.OperationExpiryTime.Value) > 0)
                {
                    throw Exceptions.GenerateTimeoutException(executionState.Cmd != null ? executionState.Cmd.CurrentResult : null, null);
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (waitHandle != null)
                {
                    waitHandle.Unregister(null);
                }

                if (completedEvent != null)
                {
                    completedEvent.Close();
                }
            }

            if (streamCopyState != null && streamCopyState.Md5HashRef != null)
            {
                streamCopyState.Md5        = streamCopyState.Md5HashRef.ComputeHash();
                streamCopyState.Md5HashRef = null;
            }
        }