private bool TryConnect(int timeout, CancellationToken cancellationToken)
{
Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability);
int _pipeFlags = (int)_pipeOptions;
if (_impersonationLevel != TokenImpersonationLevel.None)
{
_pipeFlags |= Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT;
_pipeFlags |= (((int)_impersonationLevel - 1) << 16);
}
if (!Interop.Kernel32.WaitNamedPipe(_normalizedPipePath, timeout))
{
int errorCode = Marshal.GetLastWin32Error();
// Server is not yet created
if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND)
{
return false;
}
// The timeout has expired.
if (errorCode == Interop.Errors.ERROR_SUCCESS)
{
if (cancellationToken.CanBeCanceled)
{
// It may not be real timeout.
return false;
}
throw new TimeoutException();
}
throw Win32Marshal.GetExceptionForWin32Error(errorCode);
}
// Pipe server should be free. Let's try to connect to it.
int access = 0;
if ((PipeDirection.In & _direction) != 0)
{
access |= Interop.Kernel32.GenericOperations.GENERIC_READ;
}
if ((PipeDirection.Out & _direction) != 0)
{
access |= Interop.Kernel32.GenericOperations.GENERIC_WRITE;
}
SafePipeHandle handle = Interop.Kernel32.CreateNamedPipeClient(_normalizedPipePath,
access, // read and write access
0, // sharing: none
ref secAttrs, // security attributes
FileMode.Open, // open existing
_pipeFlags, // impersonation flags
IntPtr.Zero); // template file: null
if (handle.IsInvalid)
{
int errorCode = Marshal.GetLastWin32Error();
// Handle the possible race condition of someone else connecting to the server
// between our calls to WaitNamedPipe & CreateFile.
if (errorCode == Interop.Errors.ERROR_PIPE_BUSY)
{
return false;
}
throw Win32Marshal.GetExceptionForWin32Error(errorCode);
}
// Success!
InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0);
State = PipeState.Connected;
return true;
}