private void InitFromHandle(SafeFileHandle handle)
{
int handleType = Interop.Kernel32.GetFileType(_fileHandle);
Debug.Assert(handleType == Interop.Kernel32.FileTypes.FILE_TYPE_DISK || handleType == Interop.Kernel32.FileTypes.FILE_TYPE_PIPE || handleType == Interop.Kernel32.FileTypes.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!");
_canSeek = handleType == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;
_isPipe = handleType == Interop.Kernel32.FileTypes.FILE_TYPE_PIPE;
// This is necessary for async IO using IO Completion ports via our
// managed Threadpool API's. This calls the OS's
// BindIoCompletionCallback method, and passes in a stub for the
// LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped
// struct for this request and gets a delegate to a managed callback
// from there, which it then calls on a threadpool thread. (We allocate
// our native OVERLAPPED structs 2 pointers too large and store EE
// state & a handle to a delegate there.)
//
// If, however, we've already bound this file handle to our completion port,
// don't try to bind it again because it will fail. A handle can only be
// bound to a single completion port at a time.
if (_useAsyncIO && !GetSuppressBindHandle(handle))
{
try
{
_fileHandle.ThreadPoolBinding = ThreadPoolBoundHandle.BindHandle(_fileHandle);
}
catch (Exception ex)
{
// If you passed in a synchronous handle and told us to use
// it asynchronously, throw here.
throw new ArgumentException(SR.Arg_HandleNotAsync, nameof(handle), ex);
}
}
else if (!_useAsyncIO)
{
if (handleType != Interop.Kernel32.FileTypes.FILE_TYPE_PIPE)
VerifyHandleIsSync();
}
if (_canSeek)
SeekCore(0, SeekOrigin.Current);
else
_filePosition = 0;
}