private static SafeMemoryMappedFileHandle CreateCore(
            SafeFileHandle fileHandle, String mapName, HandleInheritability inheritability,
            MemoryMappedFileAccess access, MemoryMappedFileOptions options, Int64 capacity)
        {
            Interop.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability);

            // split the long into two ints
            int capacityLow  = unchecked ((int)(capacity & 0x00000000FFFFFFFFL));
            int capacityHigh = unchecked ((int)(capacity >> 32));

            SafeMemoryMappedFileHandle handle = fileHandle != null?
                                                Interop.mincore.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName) :
                                                    Interop.mincore.CreateFileMapping(Interop.INVALID_HANDLE_VALUE, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName);

            Int32 errorCode = Marshal.GetLastWin32Error();

            if (!handle.IsInvalid)
            {
                if (errorCode == Interop.ERROR_ALREADY_EXISTS)
                {
                    handle.Dispose();
                    throw Win32Marshal.GetExceptionForWin32Error(errorCode);
                }
            }
            else if (handle.IsInvalid)
            {
                throw Win32Marshal.GetExceptionForWin32Error(errorCode);
            }

            return(handle);
        }
Beispiel #2
0
        public override void CopyFile(string sourceFullPath, string destFullPath, bool overwrite)
        {
            Interop.SECURITY_ATTRIBUTES secAttrs = default(Interop.SECURITY_ATTRIBUTES);
            int errorCode = Interop.mincore.CopyFile(sourceFullPath, destFullPath, !overwrite);

            if (errorCode != Interop.ERROR_SUCCESS)
            {
                String fileName = destFullPath;

                if (errorCode != Interop.ERROR_FILE_EXISTS)
                {
                    // For a number of error codes (sharing violation, path
                    // not found, etc) we don't know if the problem was with
                    // the source or dest file.  Try reading the source file.
                    using (SafeFileHandle handle = Interop.mincore.UnsafeCreateFile(sourceFullPath, Win32FileStream.GENERIC_READ, FileShare.Read, ref secAttrs, FileMode.Open, 0, IntPtr.Zero))
                    {
                        if (handle.IsInvalid)
                        {
                            fileName = sourceFullPath;
                        }
                    }

                    if (errorCode == Interop.ERROR_ACCESS_DENIED)
                    {
                        if (DirectoryExists(destFullPath))
                        {
                            throw new IOException(SR.Format(SR.Arg_FileIsDirectory_Name, destFullPath), Interop.ERROR_ACCESS_DENIED);
                        }
                    }
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fileName);
            }
        }
Beispiel #3
0
 internal static Interop.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
 {
     Interop.SECURITY_ATTRIBUTES secAttrs = default(Interop.SECURITY_ATTRIBUTES);
     if ((inheritability & HandleInheritability.Inheritable) != 0)
     {
         secAttrs                = new Interop.SECURITY_ATTRIBUTES();
         secAttrs.nLength        = (uint)Marshal.SizeOf(secAttrs);
         secAttrs.bInheritHandle = true;
     }
     return(secAttrs);
 }
Beispiel #4
0
        // Using synchronous Anonymous pipes for process input/output redirection means we would end up
        // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since
        // it will take advantage of the NT IO completion port infrastructure. But we can't really use
        // Overlapped I/O for process input/output as it would break Console apps (managed Console class
        // methods such as WriteLine as well as native CRT functions like printf) which are making an
        // assumption that the console standard handles (obtained via GetStdHandle()) are opened
        // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
        private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs)
        {
            Interop.SECURITY_ATTRIBUTES securityAttributesParent = new Interop.SECURITY_ATTRIBUTES();
            securityAttributesParent.bInheritHandle = true;

            SafeFileHandle hTmp = null;

            try
            {
                if (parentInputs)
                {
                    CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
                }
                else
                {
                    CreatePipeWithSecurityAttributes(out hTmp,
                                                     out childHandle,
                                                     securityAttributesParent,
                                                     0);
                }
                // Duplicate the parent handle to be non-inheritable so that the child process
                // doesn't have access. This is done for correctness sake, exact reason is unclear.
                // One potential theory is that child process can do something brain dead like
                // closing the parent end of the pipe and there by getting into a blocking situation
                // as parent will not be draining the pipe at the other end anymore.
                SafeProcessHandle currentProcHandle = Interop.mincore.GetCurrentProcess();
                if (!Interop.mincore.DuplicateHandle(currentProcHandle,
                                                     hTmp,
                                                     currentProcHandle,
                                                     out parentHandle,
                                                     0,
                                                     false,
                                                     Interop.DUPLICATE_SAME_ACCESS))
                {
                    throw new Win32Exception();
                }
            }
            finally
            {
                if (hTmp != null && !hTmp.IsInvalid)
                {
                    hTmp.Dispose();
                }
            }
        }
        private void Create(string pipeName, PipeDirection direction, int maxNumberOfServerInstances,
                            PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
                            HandleInheritability inheritability)
        {
            Debug.Assert(pipeName != null && pipeName.Length != 0, "fullPipeName is null or empty");
            Debug.Assert(direction >= PipeDirection.In && direction <= PipeDirection.InOut, "invalid pipe direction");
            Debug.Assert(inBufferSize >= 0, "inBufferSize is negative");
            Debug.Assert(outBufferSize >= 0, "outBufferSize is negative");
            Debug.Assert((maxNumberOfServerInstances >= 1 && maxNumberOfServerInstances <= 254) || (maxNumberOfServerInstances == MaxAllowedServerInstances), "maxNumberOfServerInstances is invalid");
            Debug.Assert(transmissionMode >= PipeTransmissionMode.Byte && transmissionMode <= PipeTransmissionMode.Message, "transmissionMode is out of range");

            string fullPipeName = Path.GetFullPath(@"\\.\pipe\" + pipeName);

            // Make sure the pipe name isn't one of our reserved names for anonymous pipes.
            if (String.Equals(fullPipeName, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentOutOfRangeException("pipeName", SR.ArgumentOutOfRange_AnonymousReserved);
            }


            int openMode = ((int)direction) |
                           (maxNumberOfServerInstances == 1 ? Interop.FILE_FLAG_FIRST_PIPE_INSTANCE : 0) |
                           (int)options;

            // We automatically set the ReadMode to match the TransmissionMode.
            int pipeModes = (int)transmissionMode << 2 | (int)transmissionMode << 1;

            // Convert -1 to 255 to match win32 (we asserted that it is between -1 and 254).
            if (maxNumberOfServerInstances == MaxAllowedServerInstances)
            {
                maxNumberOfServerInstances = 255;
            }

            Interop.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability);
            SafePipeHandle handle = Interop.mincore.CreateNamedPipe(fullPipeName, openMode, pipeModes,
                                                                    maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref secAttrs);

            if (handle.IsInvalid)
            {
                throw Win32Marshal.GetExceptionForLastWin32Error();
            }

            InitializeHandle(handle, false, (options & PipeOptions.Asynchronous) != 0);
        }
Beispiel #6
0
        private void Create(PipeDirection direction, HandleInheritability inheritability, int bufferSize)
        {
            Debug.Assert(direction != PipeDirection.InOut, "Anonymous pipe direction shouldn't be InOut");
            Debug.Assert(bufferSize >= 0, "bufferSize is negative");

            bool           bSuccess;
            SafePipeHandle serverHandle;
            SafePipeHandle newServerHandle;

            // Create the two pipe handles that make up the anonymous pipe.
            Interop.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability);
            if (direction == PipeDirection.In)
            {
                bSuccess = Interop.mincore.CreatePipe(out serverHandle, out _clientHandle, ref secAttrs, bufferSize);
            }
            else
            {
                bSuccess = Interop.mincore.CreatePipe(out _clientHandle, out serverHandle, ref secAttrs, bufferSize);
            }

            if (!bSuccess)
            {
                throw Win32Marshal.GetExceptionForLastWin32Error();
            }

            // Duplicate the server handle to make it not inheritable.  Note: We need to do this so that the child
            // process doesn't end up getting another copy of the server handle.  If it were to get a copy, the
            // OS wouldn't be able to inform the child that the server has closed its handle because it will see
            // that there is still one server handle that is open.
            bSuccess = Interop.mincore.DuplicateHandle(Interop.mincore.GetCurrentProcess(), serverHandle, Interop.mincore.GetCurrentProcess(),
                                                       out newServerHandle, 0, false, Interop.DUPLICATE_SAME_ACCESS);

            if (!bSuccess)
            {
                throw Win32Marshal.GetExceptionForLastWin32Error();
            }

            // Close the inheritable server handle.
            serverHandle.Dispose();

            InitializeHandle(newServerHandle, false, false);

            State = PipeState.Connected;
        }
Beispiel #7
0
        private static SafeFileHandle OpenHandle(string fullPath, bool asDirectory)
        {
            String root = fullPath.Substring(0, PathHelpers.GetRootLength(fullPath));

            if (root == fullPath && root[1] == Path.VolumeSeparatorChar)
            {
                throw new ArgumentException(SR.Arg_PathIsVolume);
            }

            Interop.SECURITY_ATTRIBUTES secAttrs = default(Interop.SECURITY_ATTRIBUTES);
            SafeFileHandle handle = Interop.mincore.SafeCreateFile(
                fullPath,
                (int)Interop.GENERIC_WRITE,
                FileShare.ReadWrite | FileShare.Delete,
                ref secAttrs,
                FileMode.Open,
                asDirectory ? (int)Interop.FILE_FLAG_BACKUP_SEMANTICS : (int)FileOptions.None,
                IntPtr.Zero
                );

            if (handle.IsInvalid)
            {
                int errorCode = Marshal.GetLastWin32Error();

                // NT5 oddity - when trying to open "C:\" as a File,
                // we usually get ERROR_PATH_NOT_FOUND from the OS.  We should
                // probably be consistent w/ every other directory.
                if (!asDirectory && errorCode == Interop.ERROR_PATH_NOT_FOUND && fullPath.Equals(Directory.GetDirectoryRoot(fullPath)))
                {
                    errorCode = Interop.ERROR_ACCESS_DENIED;
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }
            return(handle);
        }
Beispiel #8
0
        private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, Interop.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize)
        {
            bool ret = Interop.mincore.CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize);

            if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid)
            {
                throw new Win32Exception();
            }
        }
 private unsafe static Interop.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability)
 {
     Interop.SECURITY_ATTRIBUTES secAttrs = default(Interop.SECURITY_ATTRIBUTES);
     if ((inheritability & HandleInheritability.Inheritable) != 0)
     {
         secAttrs = new Interop.SECURITY_ATTRIBUTES();
         secAttrs.nLength = (uint)Marshal.SizeOf(secAttrs);
         secAttrs.bInheritHandle = true;
     }
     return secAttrs;
 }
Beispiel #10
0
 internal static extern SafePipeHandle CreateNamedPipe(string pipeName,
                                                       int openMode, int pipeMode, int maxInstances,
                                                       int outBufferSize, int inBufferSize, int defaultTimeout,
                                                       ref Interop.SECURITY_ATTRIBUTES securityAttributes);
Beispiel #11
0
 internal static extern SafePipeHandle CreateNamedPipeClient(String lpFileName,
                                                             int dwDesiredAccess, System.IO.FileShare dwShareMode,
                                                             ref Interop.SECURITY_ATTRIBUTES secAttrs, System.IO.FileMode dwCreationDisposition,
                                                             int dwFlagsAndAttributes, IntPtr hTemplateFile);
Beispiel #12
0
 internal static extern bool CreatePipe(out SafePipeHandle hReadPipe,
                                        out SafePipeHandle hWritePipe, ref Interop.SECURITY_ATTRIBUTES pipeSecAttrs, int nSize);
Beispiel #13
0
        private void ConnectInternal(int timeout, CancellationToken cancellationToken, int startTime)
        {
            Interop.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability);

            int _pipeFlags = (int)_pipeOptions;

            if (_impersonationLevel != TokenImpersonationLevel.None)
            {
                _pipeFlags |= Interop.SECURITY_SQOS_PRESENT;
                _pipeFlags |= (((int)_impersonationLevel - 1) << 16);
            }

            // This is the main connection loop. It will loop until the timeout expires.  Most of the
            // time, we will be waiting in the WaitNamedPipe win32 blocking function; however, there are
            // cases when we will need to loop: 1) The server is not created (WaitNamedPipe returns
            // straight away in such cases), and 2) when another client connects to our server in between
            // our WaitNamedPipe and CreateFile calls.
            int elapsed = 0;

            do
            {
                // We want any other exception and and success to have priority over cancellation.
                cancellationToken.ThrowIfCancellationRequested();

                // Wait for pipe to become free (this will block unless the pipe does not exist).
                int timeLeft = timeout - elapsed;
                int waitTime;
                if (cancellationToken.CanBeCanceled)
                {
                    waitTime = Math.Min(CancellationCheckInterval, timeLeft);
                }
                else
                {
                    waitTime = timeLeft;
                }

                if (!Interop.mincore.WaitNamedPipe(_normalizedPipePath, waitTime))
                {
                    int errorCode = Marshal.GetLastWin32Error();

                    // Server is not yet created so let's keep looping.
                    if (errorCode == Interop.ERROR_FILE_NOT_FOUND)
                    {
                        continue;
                    }

                    // The timeout has expired.
                    if (errorCode == Interop.ERROR_SUCCESS)
                    {
                        if (cancellationToken.CanBeCanceled)
                        {
                            // It may not be real timeout and only checking for cancellation
                            // let the while condition check it and decide
                            continue;
                        }
                        else
                        {
                            break;
                        }
                    }

                    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.GENERIC_READ;
                }
                if ((PipeDirection.Out & _direction) != 0)
                {
                    access |= Interop.GENERIC_WRITE;
                }
                SafePipeHandle handle = Interop.mincore.CreateNamedPipeClient(_normalizedPipePath,
                                                                              access,        // read and write access
                                                                              0,             // sharing: none
                                                                              ref secAttrs,  // security attributes
                                                                              FileMode.Open, // open existing
                                                                              _pipeFlags,    // impersonation flags
                                                                              Interop.NULL); // 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.ERROR_PIPE_BUSY)
                    {
                        continue;
                    }

                    throw Win32Marshal.GetExceptionForWin32Error(errorCode);
                }

                // Success!
                InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0);
                State = PipeState.Connected;

                return;
            }while (timeout == Timeout.Infinite || (elapsed = unchecked (Environment.TickCount - startTime)) < timeout);
            // BUGBUG: SerialPort does not use unchecked arithmetic when calculating elapsed times.  This is needed
            //         because Environment.TickCount can overflow (though only every 49.7 days).

            throw new TimeoutException();
        }
Beispiel #14
0
        // Using synchronous Anonymous pipes for process input/output redirection means we would end up 
        // wasting a worker threadpool thread per pipe instance. Overlapped pipe IO is desirable, since 
        // it will take advantage of the NT IO completion port infrastructure. But we can't really use 
        // Overlapped I/O for process input/output as it would break Console apps (managed Console class 
        // methods such as WriteLine as well as native CRT functions like printf) which are making an
        // assumption that the console standard handles (obtained via GetStdHandle()) are opened
        // for synchronous I/O and hence they can work fine with ReadFile/WriteFile synchrnously!
        private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs)
        {
            Interop.SECURITY_ATTRIBUTES securityAttributesParent = new Interop.SECURITY_ATTRIBUTES();
            securityAttributesParent.bInheritHandle = true;

            SafeFileHandle hTmp = null;
            try
            {
                if (parentInputs)
                {
                    CreatePipeWithSecurityAttributes(out childHandle, out hTmp, securityAttributesParent, 0);
                }
                else
                {
                    CreatePipeWithSecurityAttributes(out hTmp,
                                                          out childHandle,
                                                          securityAttributesParent,
                                                          0);
                }
                // Duplicate the parent handle to be non-inheritable so that the child process 
                // doesn't have access. This is done for correctness sake, exact reason is unclear.
                // One potential theory is that child process can do something brain dead like 
                // closing the parent end of the pipe and there by getting into a blocking situation
                // as parent will not be draining the pipe at the other end anymore. 
                SafeProcessHandle currentProcHandle = Interop.mincore.GetCurrentProcess();
                if (!Interop.mincore.DuplicateHandle(currentProcHandle,
                                                     hTmp,
                                                     currentProcHandle,
                                                     out parentHandle,
                                                     0,
                                                     false,
                                                     Interop.DUPLICATE_SAME_ACCESS))
                {
                    throw new Win32Exception();
                }
            }
            finally
            {
                if (hTmp != null && !hTmp.IsInvalid)
                {
                    hTmp.Dispose();
                }
            }
        }
Beispiel #15
0
        /// <summary>Starts the process using the supplied start info.</summary>
        /// <param name="startInfo">The start info with which to start the process.</param>
        private bool StartCore(ProcessStartInfo startInfo)
        {
            if (startInfo.StandardOutputEncoding != null && !startInfo.RedirectStandardOutput)
            {
                throw new InvalidOperationException(SR.StandardOutputEncodingNotAllowed);
            }

            if (startInfo.StandardErrorEncoding != null && !startInfo.RedirectStandardError)
            {
                throw new InvalidOperationException(SR.StandardErrorEncodingNotAllowed);
            }

            // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
            //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
            //      that the child process can not close them
            //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
            //      GetStdHandle for the handles that are not being redirected

            //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed.
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);

            Interop.STARTUPINFO         startupInfo     = new Interop.STARTUPINFO();
            Interop.PROCESS_INFORMATION processInfo     = new Interop.PROCESS_INFORMATION();
            Interop.SECURITY_ATTRIBUTES unused_SecAttrs = new Interop.SECURITY_ATTRIBUTES();
            SafeProcessHandle           procSH          = new SafeProcessHandle();
            SafeThreadHandle            threadSH        = new SafeThreadHandle();
            bool retVal;
            int  errorCode = 0;
            // handles used in parent process
            SafeFileHandle standardInputWritePipeHandle = null;
            SafeFileHandle standardOutputReadPipeHandle = null;
            SafeFileHandle standardErrorReadPipeHandle  = null;
            GCHandle       environmentHandle            = new GCHandle();

            lock (s_createProcessLock)
            {
                try
                {
                    // set up the streams
                    if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)
                    {
                        if (startInfo.RedirectStandardInput)
                        {
                            CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
                        }
                        else
                        {
                            startupInfo.hStdInput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.STD_INPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardOutput)
                        {
                            CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
                        }
                        else
                        {
                            startupInfo.hStdOutput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.STD_OUTPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardError)
                        {
                            CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
                        }
                        else
                        {
                            startupInfo.hStdError = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.STD_ERROR_HANDLE), false);
                        }

                        startupInfo.dwFlags = Interop.STARTF_USESTDHANDLES;
                    }

                    // set up the creation flags paramater
                    int creationFlags = 0;
                    if (startInfo.CreateNoWindow)
                    {
                        creationFlags |= Interop.CREATE_NO_WINDOW;
                    }

                    // set up the environment block parameter
                    IntPtr environmentPtr = (IntPtr)0;
                    if (startInfo._environmentVariables != null)
                    {
                        creationFlags |= Interop.CREATE_UNICODE_ENVIRONMENT;
                        byte[] environmentBytes = EnvironmentVariablesToByteArray(startInfo._environmentVariables);
                        environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
                        environmentPtr    = environmentHandle.AddrOfPinnedObject();
                    }
                    string workingDirectory = startInfo.WorkingDirectory;
                    if (workingDirectory == string.Empty)
                    {
                        workingDirectory = Directory.GetCurrentDirectory();
                    }

                    try { }
                    finally
                    {
                        retVal = Interop.mincore.CreateProcess(
                            null,                // we don't need this since all the info is in commandLine
                            commandLine,         // pointer to the command line string
                            unused_SecAttrs,     // address to process security attributes, we don't need to inheriat the handle
                            unused_SecAttrs,     // address to thread security attributes.
                            true,                // handle inheritance flag
                            creationFlags,       // creation flags
                            environmentPtr,      // pointer to new environment block
                            workingDirectory,    // pointer to current directory name
                            startupInfo,         // pointer to STARTUPINFO
                            processInfo          // pointer to PROCESS_INFORMATION
                            );
                        if (!retVal)
                        {
                            errorCode = Marshal.GetLastWin32Error();
                        }
                        if (processInfo.hProcess != (IntPtr)0 && processInfo.hProcess != (IntPtr)Interop.INVALID_HANDLE_VALUE)
                        {
                            procSH.InitialSetHandle(processInfo.hProcess);
                        }
                        if (processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)Interop.INVALID_HANDLE_VALUE)
                        {
                            threadSH.InitialSetHandle(processInfo.hThread);
                        }
                    }
                    if (!retVal)
                    {
                        if (errorCode == Interop.ERROR_BAD_EXE_FORMAT || errorCode == Interop.ERROR_EXE_MACHINE_TYPE_MISMATCH)
                        {
                            throw new Win32Exception(errorCode, SR.InvalidApplication);
                        }
                        throw new Win32Exception(errorCode);
                    }
                }
                finally
                {
                    // free environment block
                    if (environmentHandle.IsAllocated)
                    {
                        environmentHandle.Free();
                    }

                    startupInfo.Dispose();
                }
            }

            if (startInfo.RedirectStandardInput)
            {
                Encoding enc = GetEncoding((int)Interop.mincore.GetConsoleCP());
                _standardInput           = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), enc, 4096);
                _standardInput.AutoFlush = true;
            }
            if (startInfo.RedirectStandardOutput)
            {
                Encoding enc = (startInfo.StandardOutputEncoding != null) ? startInfo.StandardOutputEncoding : GetEncoding((int)Interop.mincore.GetConsoleOutputCP());
                _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError)
            {
                Encoding enc = (startInfo.StandardErrorEncoding != null) ? startInfo.StandardErrorEncoding : GetEncoding((int)Interop.mincore.GetConsoleOutputCP());
                _standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }

            bool ret = false;

            if (!procSH.IsInvalid)
            {
                SetProcessHandle(procSH);
                SetProcessId((int)processInfo.dwProcessId);
                threadSH.Dispose();
                ret = true;
            }

            return(ret);
        }
        private static SafeMemoryMappedFileHandle CreateOrOpenCore(
            String mapName, HandleInheritability inheritability, MemoryMappedFileAccess access,
            MemoryMappedFileOptions options, Int64 capacity)
        {
            /// Try to open the file if it exists -- this requires a bit more work. Loop until we can
            /// either create or open a memory mapped file up to a timeout. CreateFileMapping may fail
            /// if the file exists and we have non-null security attributes, in which case we need to
            /// use OpenFileMapping.  But, there exists a race condition because the memory mapped file
            /// may have closed inbetween the two calls -- hence the loop.
            ///
            /// The retry/timeout logic increases the wait time each pass through the loop and times
            /// out in approximately 1.4 minutes. If after retrying, a MMF handle still hasn't been opened,
            /// throw an InvalidOperationException.

            Debug.Assert(access != MemoryMappedFileAccess.Write, "Callers requesting write access shouldn't try to create a mmf");

            SafeMemoryMappedFileHandle handle = null;

            Interop.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability);

            // split the long into two ints
            Int32 capacityLow  = unchecked ((Int32)(capacity & 0x00000000FFFFFFFFL));
            Int32 capacityHigh = unchecked ((Int32)(capacity >> 32));

            int waitRetries = 14;   //((2^13)-1)*10ms == approximately 1.4mins
            int waitSleep   = 0;

            // keep looping until we've exhausted retries or break as soon we we get valid handle
            while (waitRetries > 0)
            {
                // try to create
                handle = Interop.mincore.CreateFileMapping(Interop.INVALID_HANDLE_VALUE, ref secAttrs,
                                                           GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName);

                if (!handle.IsInvalid)
                {
                    break;
                }
                else
                {
                    Int32 createErrorCode = Marshal.GetLastWin32Error();
                    if (createErrorCode != Interop.ERROR_ACCESS_DENIED)
                    {
                        throw Win32Marshal.GetExceptionForWin32Error(createErrorCode);
                    }
                }

                // try to open
                handle = Interop.mincore.OpenFileMapping(GetFileMapAccess(access), (inheritability &
                                                                                    HandleInheritability.Inheritable) != 0, mapName);

                // valid handle
                if (!handle.IsInvalid)
                {
                    break;
                }
                // didn't get valid handle; have to retry
                else
                {
                    Int32 openErrorCode = Marshal.GetLastWin32Error();
                    if (openErrorCode != Interop.ERROR_FILE_NOT_FOUND)
                    {
                        throw Win32Marshal.GetExceptionForWin32Error(openErrorCode);
                    }

                    // increase wait time
                    --waitRetries;
                    if (waitSleep == 0)
                    {
                        waitSleep = 10;
                    }
                    else
                    {
                        ThreadSleep(waitSleep);
                        waitSleep *= 2;
                    }
                }
            }

            // finished retrying but couldn't create or open
            if (handle == null || handle.IsInvalid)
            {
                throw new InvalidOperationException(SR.InvalidOperation_CantCreateFileMapping);
            }

            return(handle);
        }
        private bool TryConnect(int timeout, CancellationToken cancellationToken)
        {
            Interop.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability);

            int _pipeFlags = (int)_pipeOptions;

            if (_impersonationLevel != TokenImpersonationLevel.None)
            {
                _pipeFlags |= Interop.SECURITY_SQOS_PRESENT;
                _pipeFlags |= (((int)_impersonationLevel - 1) << 16);
            }

            if (!Interop.mincore.WaitNamedPipe(_normalizedPipePath, timeout))
            {
                int errorCode = Marshal.GetLastWin32Error();

                // Server is not yet created
                if (errorCode == Interop.ERROR_FILE_NOT_FOUND)
                {
                    return(false);
                }

                // The timeout has expired.
                if (errorCode == Interop.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.GENERIC_READ;
            }
            if ((PipeDirection.Out & _direction) != 0)
            {
                access |= Interop.GENERIC_WRITE;
            }
            SafePipeHandle handle = Interop.mincore.CreateNamedPipeClient(_normalizedPipePath,
                                                                          access,        // read and write access
                                                                          0,             // sharing: none
                                                                          ref secAttrs,  // security attributes
                                                                          FileMode.Open, // open existing
                                                                          _pipeFlags,    // impersonation flags
                                                                          Interop.NULL); // 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.ERROR_PIPE_BUSY)
                {
                    return(false);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode);
            }

            // Success!
            InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0);
            State = PipeState.Connected;

            return(true);
        }
Beispiel #18
0
        public override void CreateDirectory(string fullPath)
        {
            int length = fullPath.Length;

            // We need to trim the trailing slash or the code will try to create 2 directories of the same name.
            if (length >= 2 && PathHelpers.EndsInDirectorySeparator(fullPath))
            {
                length--;
            }

            int lengthRoot = PathHelpers.GetRootLength(fullPath);

            // For UNC paths that are only // or ///
            if (length == 2 && PathHelpers.IsDirectorySeparator(fullPath[1]))
            {
                throw new IOException(SR.Format(SR.IO_CannotCreateDirectory, fullPath));
            }

            // We can save a bunch of work if the directory we want to create already exists.  This also
            // saves us in the case where sub paths are inaccessible (due to ERROR_ACCESS_DENIED) but the
            // final path is accessable and the directory already exists.  For example, consider trying
            // to create c:\Foo\Bar\Baz, where everything already exists but ACLS prevent access to c:\Foo
            // and c:\Foo\Bar.  In that case, this code will think it needs to create c:\Foo, and c:\Foo\Bar
            // and fail to due so, causing an exception to be thrown.  This is not what we want.
            if (DirectoryExists(fullPath))
            {
                return;
            }

            List <string> stackDir = new List <string>();

            // Attempt to figure out which directories don't exist, and only
            // create the ones we need.  Note that InternalExists may fail due
            // to Win32 ACL's preventing us from seeing a directory, and this
            // isn't threadsafe.

            bool somepathexists = false;

            if (length > lengthRoot)
            {
                // Special case root (fullpath = X:\\)
                int i = length - 1;
                while (i >= lengthRoot && !somepathexists)
                {
                    String dir = fullPath.Substring(0, i + 1);

                    if (!DirectoryExists(dir)) // Create only the ones missing
                    {
                        stackDir.Add(dir);
                    }
                    else
                    {
                        somepathexists = true;
                    }

                    while (i > lengthRoot && !PathHelpers.IsDirectorySeparator(fullPath[i]))
                    {
                        i--;
                    }
                    i--;
                }
            }

            int count = stackDir.Count;

            // If we were passed a DirectorySecurity, convert it to a security
            // descriptor and set it in he call to CreateDirectory.
            Interop.SECURITY_ATTRIBUTES secAttrs = default(Interop.SECURITY_ATTRIBUTES);

            bool   r           = true;
            int    firstError  = 0;
            String errorString = fullPath;

            // If all the security checks succeeded create all the directories
            while (stackDir.Count > 0)
            {
                String name = stackDir[stackDir.Count - 1];
                stackDir.RemoveAt(stackDir.Count - 1);
                if (name.Length >= Interop.MAX_DIRECTORY_PATH)
                {
                    throw new PathTooLongException(SR.IO_PathTooLong);
                }
                r = Interop.mincore.CreateDirectory(name, ref secAttrs);
                if (!r && (firstError == 0))
                {
                    int currentError = Marshal.GetLastWin32Error();
                    // While we tried to avoid creating directories that don't
                    // exist above, there are at least two cases that will
                    // cause us to see ERROR_ALREADY_EXISTS here.  InternalExists
                    // can fail because we didn't have permission to the
                    // directory.  Secondly, another thread or process could
                    // create the directory between the time we check and the
                    // time we try using the directory.  Thirdly, it could
                    // fail because the target does exist, but is a file.
                    if (currentError != Interop.ERROR_ALREADY_EXISTS)
                    {
                        firstError = currentError;
                    }
                    else
                    {
                        // If there's a file in this directory's place, or if we have ERROR_ACCESS_DENIED when checking if the directory already exists throw.
                        if (File.InternalExists(name) || (!DirectoryExists(name, out currentError) && currentError == Interop.ERROR_ACCESS_DENIED))
                        {
                            firstError  = currentError;
                            errorString = name;
                        }
                    }
                }
            }

            // We need this check to mask OS differences
            // Handle CreateDirectory("X:\\") when X: doesn't exist. Similarly for n/w paths.
            if ((count == 0) && !somepathexists)
            {
                String root = Directory.InternalGetDirectoryRoot(fullPath);
                if (!DirectoryExists(root))
                {
                    throw Win32Marshal.GetExceptionForWin32Error(Interop.ERROR_PATH_NOT_FOUND, root);
                }
                return;
            }

            // Only throw an exception if creating the exact directory we
            // wanted failed to work correctly.
            if (!r && (firstError != 0))
            {
                throw Win32Marshal.GetExceptionForWin32Error(firstError, errorString);
            }
        }
Beispiel #19
0
        /// <summary>Starts the process using the supplied start info.</summary>
        /// <param name="startInfo">The start info with which to start the process.</param>
        private bool StartCore(ProcessStartInfo startInfo)
        {
            // See knowledge base article Q190351 for an explanation of the following code.  Noteworthy tricky points:
            //    * The handles are duplicated as non-inheritable before they are passed to CreateProcess so
            //      that the child process can not close them
            //    * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
            //      GetStdHandle for the handles that are not being redirected

            StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments);

            Interop.STARTUPINFO startupInfo = new Interop.STARTUPINFO();
            Interop.PROCESS_INFORMATION processInfo = new Interop.PROCESS_INFORMATION();
            Interop.SECURITY_ATTRIBUTES unused_SecAttrs = new Interop.SECURITY_ATTRIBUTES();
            SafeProcessHandle procSH = new SafeProcessHandle();
            SafeThreadHandle threadSH = new SafeThreadHandle();
            bool retVal;
            int errorCode = 0;
            // handles used in parent process
            SafeFileHandle standardInputWritePipeHandle = null;
            SafeFileHandle standardOutputReadPipeHandle = null;
            SafeFileHandle standardErrorReadPipeHandle = null;
            GCHandle environmentHandle = new GCHandle();
            lock (s_createProcessLock)
            {
                try
                {
                    // set up the streams
                    if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError)
                    {
                        if (startInfo.RedirectStandardInput)
                        {
                            CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true);
                        }
                        else
                        {
                            startupInfo.hStdInput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.STD_INPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardOutput)
                        {
                            CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false);
                        }
                        else
                        {
                            startupInfo.hStdOutput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.STD_OUTPUT_HANDLE), false);
                        }

                        if (startInfo.RedirectStandardError)
                        {
                            CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false);
                        }
                        else
                        {
                            startupInfo.hStdError = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.STD_ERROR_HANDLE), false);
                        }

                        startupInfo.dwFlags = Interop.STARTF_USESTDHANDLES;
                    }

                    // set up the creation flags paramater
                    int creationFlags = 0;
                    if (startInfo.CreateNoWindow) creationFlags |= Interop.CREATE_NO_WINDOW;

                    // set up the environment block parameter
                    IntPtr environmentPtr = (IntPtr)0;
                    if (startInfo._environmentVariables != null)
                    {
                        creationFlags |= Interop.CREATE_UNICODE_ENVIRONMENT;
                        byte[] environmentBytes = EnvironmentVariablesToByteArray(startInfo._environmentVariables);
                        environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned);
                        environmentPtr = environmentHandle.AddrOfPinnedObject();
                    }
                    string workingDirectory = startInfo.WorkingDirectory;
                    if (workingDirectory == string.Empty)
                        workingDirectory = Directory.GetCurrentDirectory();

                    try { }
                    finally
                    {
                        retVal = Interop.mincore.CreateProcess(
                                null,                // we don't need this since all the info is in commandLine
                                commandLine,         // pointer to the command line string
                                unused_SecAttrs, // address to process security attributes, we don't need to inheriat the handle
                                unused_SecAttrs, // address to thread security attributes.
                                true,                // handle inheritance flag
                                creationFlags,       // creation flags
                                environmentPtr,      // pointer to new environment block
                                workingDirectory,    // pointer to current directory name
                                startupInfo,         // pointer to STARTUPINFO
                                processInfo      // pointer to PROCESS_INFORMATION
                            );
                        if (!retVal)
                            errorCode = Marshal.GetLastWin32Error();
                        if (processInfo.hProcess != (IntPtr)0 && processInfo.hProcess != (IntPtr)Interop.INVALID_HANDLE_VALUE)
                            procSH.InitialSetHandle(processInfo.hProcess);
                        if (processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)Interop.INVALID_HANDLE_VALUE)
                            threadSH.InitialSetHandle(processInfo.hThread);
                    }
                    if (!retVal)
                    {
                        if (errorCode == Interop.ERROR_BAD_EXE_FORMAT || errorCode == Interop.ERROR_EXE_MACHINE_TYPE_MISMATCH)
                        {
                            throw new Win32Exception(errorCode, SR.InvalidApplication);
                        }
                        throw new Win32Exception(errorCode);
                    }
                }
                finally
                {
                    // free environment block
                    if (environmentHandle.IsAllocated)
                    {
                        environmentHandle.Free();
                    }

                    startupInfo.Dispose();
                }
            }

            if (startInfo.RedirectStandardInput)
            {
                Encoding enc = GetEncoding((int)Interop.mincore.GetConsoleCP());
                _standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), enc, 4096);
                _standardInput.AutoFlush = true;
            }
            if (startInfo.RedirectStandardOutput)
            {
                Encoding enc = startInfo.StandardOutputEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP());
                _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }
            if (startInfo.RedirectStandardError)
            {
                Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP());
                _standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
            }

            bool ret = false;
            if (!procSH.IsInvalid)
            {
                SetProcessHandle(procSH);
                SetProcessId((int)processInfo.dwProcessId);
                threadSH.Dispose();
                ret = true;
            }

            return ret;
        }