コード例 #1
0
        private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle?result)
        {
#if TARGET_WINDOWS
            ArgumentException.ThrowIfNullOrEmpty(name);

            result = null;
            SafeWaitHandle myHandle = Interop.Kernel32.OpenEvent(AccessRights, false, name);

            if (myHandle.IsInvalid)
            {
                int errorCode = Marshal.GetLastPInvokeError();

                myHandle.Dispose();

                if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_INVALID_NAME)
                {
                    return(OpenExistingResult.NameNotFound);
                }
                if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND)
                {
                    return(OpenExistingResult.PathNotFound);
                }
                if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
                {
                    return(OpenExistingResult.NameInvalid);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
            }
            result = new EventWaitHandle(myHandle);
            return(OpenExistingResult.Success);
#else
            throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
#endif
        }
コード例 #2
0
        internal static void CompleteInitialization(SafeCloseSocketAndEvent socketAndEventHandle)
        {
            SafeWaitHandle handle = socketAndEventHandle._waitHandle.GetSafeWaitHandle();
            bool           b      = false;

            try
            {
                handle.DangerousAddRef(ref b);
            }
            catch
            {
                if (b)
                {
                    handle.DangerousRelease();
                    socketAndEventHandle._waitHandle = null;
                    b = false;
                }
            }
            finally
            {
                if (b)
                {
                    handle.Dispose();
                }
            }
        }
コード例 #3
0
        private void CreateSemaphoreCore(int initialCount, int maximumCount, string?name, out bool createdNew)
        {
            Debug.Assert(initialCount >= 0);
            Debug.Assert(maximumCount >= 1);
            Debug.Assert(initialCount <= maximumCount);

#if TARGET_UNIX || TARGET_BROWSER
            if (name != null)
            {
                throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
            }
#endif
            SafeWaitHandle myHandle = Interop.Kernel32.CreateSemaphoreEx(IntPtr.Zero, initialCount, maximumCount, name, 0, AccessRights);

            int errorCode = Marshal.GetLastPInvokeError();
            if (myHandle.IsInvalid)
            {
                myHandle.Dispose();

                if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
                {
                    throw new WaitHandleCannotBeOpenedException(
                              SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
                }

                throw Win32Marshal.GetExceptionForLastWin32Error();
            }
            createdNew          = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
            this.SafeWaitHandle = myHandle;
        }
コード例 #4
0
        internal static void CompleteInitialization(SafeCloseSocketAndEvent socketAndEventHandle)
        {
            SafeWaitHandle safeWaitHandle = socketAndEventHandle.waitHandle.SafeWaitHandle;
            bool           success        = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                safeWaitHandle.DangerousAddRef(ref success);
            }
            catch
            {
                if (success)
                {
                    safeWaitHandle.DangerousRelease();
                    socketAndEventHandle.waitHandle = null;
                    success = false;
                }
            }
            finally
            {
                if (success)
                {
                    safeWaitHandle.Dispose();
                }
            }
        }
コード例 #5
0
        /// <summary>Gets or creates <see cref="Mutex" /> instance, allowing a <see cref="MutexSecurity" /> to be optionally specified to set it during the mutex creation.</summary>
        /// <param name="initiallyOwned"><see langword="true" /> to give the calling thread initial ownership of the named system mutex if the named system mutex is created as a result of this call; otherwise, <see langword="false" />.</param>
        /// <param name="name">The optional name of the system mutex. If this argument is set to <see langword="null" /> or <see cref="string.Empty" />, a local mutex is created.</param>
        /// <param name="createdNew">When this method returns, this argument is always set to <see langword="true" /> if a local mutex is created; that is, when <paramref name="name" /> is <see langword="null" /> or <see cref="string.Empty" />. If <paramref name="name" /> has a valid non-empty value, this argument is set to <see langword="true" /> when the system mutex is created, or it is set to <see langword="false" /> if an existing system mutex is found with that name. This parameter is passed uninitialized.</param>
        /// <param name="mutexSecurity">The optional mutex access control security to apply.</param>
        /// <returns>An object that represents a system mutex, if named, or a local mutex, if nameless.</returns>
        /// <exception cref="ArgumentException">.NET Framework only: The length of the name exceeds the maximum limit.</exception>
        /// <exception cref="WaitHandleCannotBeOpenedException">A mutex handle with system-wide <paramref name="name" /> cannot be created. A mutex handle of a different type might have the same name.</exception>
        public static unsafe Mutex Create(bool initiallyOwned, string name, out bool createdNew, MutexSecurity mutexSecurity)
        {
            if (mutexSecurity == null)
            {
                return(new Mutex(initiallyOwned, name, out createdNew));
            }

            uint mutexFlags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0;

            fixed(byte *pSecurityDescriptor = mutexSecurity.GetSecurityDescriptorBinaryForm())
            {
                var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
                {
                    nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
                    lpSecurityDescriptor = (IntPtr)pSecurityDescriptor
                };

                SafeWaitHandle handle = Interop.Kernel32.CreateMutexEx(
                    (IntPtr)(&secAttrs),
                    name,
                    mutexFlags,
                    (uint)MutexRights.FullControl // Equivalent to MUTEX_ALL_ACCESS
                    );

                ValidateMutexHandle(handle, name, out createdNew);

                Mutex          mutex = new Mutex(initiallyOwned);
                SafeWaitHandle old   = mutex.SafeWaitHandle;

                mutex.SafeWaitHandle = handle;
                old.Dispose();

                return(mutex);
            }
        }
コード例 #6
0
ファイル: MemoryMap.cs プロジェクト: zodiacon/ManagedWindows
 public void Dispose()
 {
     if (_owner)
     {
         _hProcess.Dispose();
     }
 }
コード例 #7
0
        protected virtual void Dispose(bool explicitDisposing)
        {
            if (!disposed)
            {
                //
                // This is only the case if the handle was never properly initialized
                // most likely a bug in the derived class
                //
                if (safe_wait_handle == null)
                {
                    return;
                }

                lock (this){
                    if (disposed)
                    {
                        return;
                    }

                    disposed = true;
                    if (safe_wait_handle != null)
                    {
                        safe_wait_handle.Dispose();
                    }
                }
            }
        }
コード例 #8
0
        /// <summary>Gets or creates an <see cref="Semaphore" /> instance, allowing a <see cref="SemaphoreSecurity " /> instance to be optionally specified to set it during the event creation.</summary>
        /// <param name="initialCount">The initial number of requests for the semaphore that can be satisfied concurrently.</param>
        /// <param name="maximumCount">The maximum number of requests for the semaphore that can be satisfied concurrently.</param>
        /// <param name="name">Optional argument to create a system semaphore. Set to <see langword="null" /> or <see cref="string.Empty" /> to create a local semaphore.</param>
        /// <param name="createdNew">When this method returns, this argument is always set to <see langword="true" /> if a local semaphore is created; that is, when <paramref name="name" /> is <see langword="null" /> or <see cref="string.Empty" />. If <paramref name="name" /> has a valid, non-empty value, this argument is set to <see langword="true" /> when the system semaphore is created, or it is set to <see langword="false" /> if an existing system semaphore is found with that name. This parameter is passed uninitialized.</param>
        /// <param name="semaphoreSecurity">The optional semaphore access control security to apply.</param>
        /// <returns>An object that represents a system semaphore, if named, or a local semaphore, if nameless.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="initialCount" /> is a negative number.
        /// -or-
        /// <paramref name="maximumCount" /> is not a positive number.</exception>
        /// <exception cref="ArgumentException"><paramref name="initialCount" /> is greater than <paramref name="maximumCount" />.</exception>
        /// <exception cref="WaitHandleCannotBeOpenedException">A semaphore handle with the system-wide name '<paramref name="name" />' cannot be created. A semaphore handle of a different type might have the same name.</exception>
        public static unsafe Semaphore Create(int initialCount, int maximumCount, string?name, out bool createdNew, SemaphoreSecurity?semaphoreSecurity)
        {
            if (semaphoreSecurity == null)
            {
                return(new Semaphore(initialCount, maximumCount, name, out createdNew));
            }

            if (initialCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum);
            }

            if (maximumCount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedPosNum);
            }

            if (initialCount > maximumCount)
            {
                throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum);
            }

            fixed(byte *pSecurityDescriptor = semaphoreSecurity.GetSecurityDescriptorBinaryForm())
            {
                var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
                {
                    nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
                    lpSecurityDescriptor = (IntPtr)pSecurityDescriptor
                };

                SafeWaitHandle handle = Interop.Kernel32.CreateSemaphoreEx(
                    (IntPtr)(&secAttrs),
                    initialCount,
                    maximumCount,
                    name,
                    0,                                // This parameter is reserved and must be 0.
                    (uint)SemaphoreRights.FullControl // Equivalent to SEMAPHORE_ALL_ACCESS
                    );

                int errorCode = Marshal.GetLastPInvokeError();

                if (handle.IsInvalid)
                {
                    handle.Dispose();

                    if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
                    {
                        throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
                    }

                    throw Win32Marshal.GetExceptionForLastWin32Error();
                }

                createdNew = (errorCode != Interop.Errors.ERROR_ALREADY_EXISTS);

                return(CreateAndReplaceHandle(handle));
            }
        }
コード例 #9
0
        internal static void CompleteInitialization(SafeCloseSocketAndEvent socketAndEventHandle)
        {
            SafeWaitHandle handle = socketAndEventHandle._waitHandle.GetSafeWaitHandle();

            bool ignore = false;

            handle.DangerousAddRef(ref ignore);

            // TODO #3562: Investigate if this pattern is still correct.
            // Note that the handle still has a reference from the above DangerousAddRef.
            handle.Dispose();
        }
コード例 #10
0
ファイル: SemaphoreAcl.cs プロジェクト: pgovind/runtime
        /// <summary>Gets or creates an <see cref="Semaphore" /> instance, allowing a <see cref="SemaphoreSecurity " /> instance to be optionally specified to set it during the event creation.</summary>
        /// <param name="initialCount">The initial number of requests for the semaphore that can be satisfied concurrently.</param>
        /// <param name="maximumCount">The maximum number of requests for the semaphore that can be satisfied concurrently.</param>
        /// <param name="name">Optional argument to create a system semaphore. Set to <see langword="null" /> or <see cref="string.Empty" /> to create a local semaphore.</param>
        /// <param name="createdNew">When this method returns, this argument is always set to <see langword="true" /> if a local semaphore is created; that is, when <paramref name="name" /> is <see langword="null" /> or <see cref="string.Empty" />. If <paramref name="name" /> has a valid, non-empty value, this argument is set to <see langword="true" /> when the system semaphore is created, or it is set to <see langword="false" /> if an existing system semaphore is found with that name. This parameter is passed uninitialized.</param>
        /// <param name="semaphoreSecurity">The optional semaphore access control security to apply.</param>
        /// <returns>An object that represents a system semaphore, if named, or a local semaphore, if nameless.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="initialCount" /> is a negative number.
        /// -or-
        /// <paramref name="maximumCount" /> is not a positive number.</exception>
        /// <exception cref="ArgumentException"><paramref name="initialCount" /> is greater than <paramref name="maximumCount" />.</exception>
        /// <exception cref="WaitHandleCannotBeOpenedException">A semaphore handle with the system-wide name '<paramref name="name" />' cannot be created. A semaphore handle of a different type might have the same name.</exception>
        public static unsafe Semaphore Create(int initialCount, int maximumCount, string name, out bool createdNew, SemaphoreSecurity semaphoreSecurity)
        {
            if (semaphoreSecurity == null)
            {
                return(new Semaphore(initialCount, maximumCount, name, out createdNew));
            }

            if (initialCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum);
            }

            if (maximumCount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedPosNum);
            }

            if (initialCount > maximumCount)
            {
                throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum);
            }

            fixed(byte *pSecurityDescriptor = semaphoreSecurity.GetSecurityDescriptorBinaryForm())
            {
                var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
                {
                    nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
                    lpSecurityDescriptor = (IntPtr)pSecurityDescriptor
                };

                SafeWaitHandle handle = Interop.Kernel32.CreateSemaphoreEx(
                    (IntPtr)(&secAttrs),
                    initialCount,
                    maximumCount,
                    name,
                    0,                                // This parameter is reserved and must be 0.
                    (uint)SemaphoreRights.FullControl // Equivalent to SEMAPHORE_ALL_ACCESS
                    );

                ValidateHandle(handle, name, out createdNew);

                Semaphore      semaphore = new Semaphore(initialCount, maximumCount);
                SafeWaitHandle old       = semaphore.SafeWaitHandle;

                semaphore.SafeWaitHandle = handle;
                old.Dispose();

                return(semaphore);
            }
        }
コード例 #11
0
ファイル: AutoResetEventTest.cs プロジェクト: xxponline/mono
        [Test]         // bug #81529
        public void Handle_Invalid()
        {
            AutoResetEvent are1 = new AutoResetEvent(false);
            SafeWaitHandle swh1 = are1.SafeWaitHandle;

            are1.Handle = (IntPtr)(-1);
            Assert.IsTrue(swh1 != are1.SafeWaitHandle, "#1");
            Assert.IsFalse(swh1.IsClosed, "#2");
            Assert.IsFalse(swh1.IsInvalid, "#3");
            Assert.IsFalse(are1.SafeWaitHandle.IsClosed, "#4");
            Assert.IsTrue(are1.SafeWaitHandle.IsInvalid, "#5");
            are1.Close();
            swh1.Dispose();
        }
コード例 #12
0
ファイル: AutoResetEventTest.cs プロジェクト: xxponline/mono
        [Test]         // bug #81529
        public void SafeWaitHandle()
        {
            AutoResetEvent are1 = new AutoResetEvent(false);
            AutoResetEvent are2 = new AutoResetEvent(false);
            SafeWaitHandle swh1 = are1.SafeWaitHandle;
            SafeWaitHandle swh2 = are2.SafeWaitHandle;

            are1.SafeWaitHandle = are2.SafeWaitHandle;
            Assert.AreSame(are1.SafeWaitHandle, are2.SafeWaitHandle, "#1");
            Assert.AreEqual(are1.Handle, are2.Handle, "#2");
            Assert.IsFalse(are1.SafeWaitHandle.IsInvalid, "#3");
            Assert.IsFalse(are1.SafeWaitHandle.IsClosed, "#4");
            Assert.IsFalse(swh1.IsClosed, "#5");
            Assert.IsFalse(swh1.IsInvalid, "#6");
            swh1.Dispose();
            are1.Close();
        }
コード例 #13
0
        public static bool TryOpenExisting(string name, MutexRights rights, out Mutex result)
        {
            SafeWaitHandle myHandle = OpenMutex((uint)rights, false, name);

            result = null;
            if (myHandle.IsInvalid)
            {
                return(false);
            }
            result = new Mutex(initiallyOwned: false);
            SafeWaitHandle old = result.SafeWaitHandle;

            result.SafeWaitHandle = myHandle;
            old.Dispose();

            return(true);
        }
コード例 #14
0
ファイル: SoundCaptureBase.cs プロジェクト: t3dders/gitpad
        private void Dispose(bool disposing)
        {
            if (disposed)
            {
                return;
            }

            disposed = true;
            GC.SuppressFinalize(this);
            if (IsCapturing)
            {
                Stop();
            }
            positionEventHandle.Dispose();
            positionEvent.Close();
            terminated.Close();
        }
コード例 #15
0
        /// <summary>Gets or creates an <see cref="EventWaitHandle" /> instance, allowing a <see cref="EventWaitHandleSecurity " /> instance to be optionally specified to set it during the event creation.</summary>
        /// <param name="initialState"><see langword="true" /> to set the initial state to signaled if the named event is created as a result of this call; <see langword="false" /> to set it to non-signaled.</param>
        /// <param name="mode">One of the enum values that determines whether the event resets automatically or manually.</param>
        /// <param name="name">The name, if the event is a system-wide synchronization event; otherwise, <see langword="null" /> or an empty string.</param>
        /// <param name="createdNew">When this method returns, this argument is always set to <see langword="true" /> if a local event is created; that is, when <paramref name="name" /> is <see langword="null" /> or <see cref="string.Empty" />. If <paramref name="name" /> has a valid, non-empty value, this argument is set to <see langword="true" /> when the system event is created, or it is set to <see langword="false" /> if an existing system event is found with that name. This parameter is passed uninitialized.</param>
        /// <param name="eventSecurity">The optional Windows access control security to apply.</param>
        /// <returns>An object that represents a system event wait handle, if named, or a local event wait handle, if nameless.</returns>
        /// <exception cref="ArgumentNullException">.NET Framework only: The <paramref name="name" /> length is beyond MAX_PATH (260 characters).</exception>
        /// <exception cref="ArgumentOutOfRangeException">The <paramref name="mode" /> enum value was out of legal range.</exception>
        /// <exception cref="DirectoryNotFoundException">Could not find a part of the path specified in <paramref name="name" />.</exception>
        /// <exception cref="WaitHandleCannotBeOpenedException">A system-wide synchronization event with the provided <paramref name="name" /> was not found.
        /// -or-
        /// An <see cref="EventWaitHandle" /> with system-wide name <paramref name="name" /> cannot be created. An <see cref="EventWaitHandle" /> of a different type might have the same name.</exception>
        /// <remarks>If a `name` is passed and the system event already exists, the existing event is returned. If `name` is `null` or <see cref="string.Empty" />, a new local event is always created.</remarks>
        public static unsafe EventWaitHandle Create(bool initialState, EventResetMode mode, string?name, out bool createdNew, EventWaitHandleSecurity?eventSecurity)
        {
            if (eventSecurity == null)
            {
                return(new EventWaitHandle(initialState, mode, name, out createdNew));
            }

            if (mode != EventResetMode.AutoReset && mode != EventResetMode.ManualReset)
            {
                throw new ArgumentOutOfRangeException(nameof(mode));
            }

            uint eventFlags = initialState ? Interop.Kernel32.CREATE_EVENT_INITIAL_SET : 0;

            if (mode == EventResetMode.ManualReset)
            {
                eventFlags |= Interop.Kernel32.CREATE_EVENT_MANUAL_RESET;
            }

            fixed(byte *pSecurityDescriptor = eventSecurity.GetSecurityDescriptorBinaryForm())
            {
                var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
                {
                    nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
                    lpSecurityDescriptor = (IntPtr)pSecurityDescriptor
                };

                SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(
                    (IntPtr)(&secAttrs),
                    name,
                    eventFlags,
                    (uint)EventWaitHandleRights.FullControl);

                ValidateHandle(handle, name, out createdNew);

                EventWaitHandle ewh = new EventWaitHandle(initialState, mode);
                SafeWaitHandle  old = ewh.SafeWaitHandle;

                ewh.SafeWaitHandle = handle;
                old.Dispose();

                return(ewh);
            }
        }
コード例 #16
0
ファイル: AutoResetEventTest.cs プロジェクト: xxponline/mono
        public void Handle_Valid()
        {
            AutoResetEvent are1 = new AutoResetEvent(false);
            SafeWaitHandle swh1 = are1.SafeWaitHandle;

            Assert.IsFalse(swh1.IsClosed, "#1");
            Assert.IsFalse(swh1.IsInvalid, "#2");
            IntPtr dummyHandle = (IntPtr)2;

            are1.Handle = dummyHandle;
            Assert.AreEqual(are1.Handle, dummyHandle, "#3");
            Assert.IsFalse(swh1.IsClosed, "#4");
            Assert.IsFalse(swh1.IsClosed, "#5");
            Assert.IsFalse(swh1.IsInvalid, "#6");
            Assert.IsFalse(are1.SafeWaitHandle.IsClosed, "#7");
            Assert.IsFalse(are1.SafeWaitHandle.IsInvalid, "#8");
            are1.Close();
            swh1.Dispose();
        }
コード例 #17
0
        private static OpenExistingResult OpenExistingWorker(string name, out Mutex?result)
        {
            ArgumentException.ThrowIfNullOrEmpty(name);

            result = null;
            // To allow users to view & edit the ACL's, call OpenMutex
            // with parameters to allow us to view & edit the ACL.  This will
            // fail if we don't have permission to view or edit the ACL's.
            // If that happens, ask for less permissions.
            SafeWaitHandle myHandle = Interop.Kernel32.OpenMutex(AccessRights, false, name);

            if (myHandle.IsInvalid)
            {
                int errorCode = Marshal.GetLastPInvokeError();

                myHandle.Dispose();

#if TARGET_UNIX || TARGET_BROWSER
                if (errorCode == Interop.Errors.ERROR_FILENAME_EXCED_RANGE)
                {
                    // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8
                    throw new ArgumentException(SR.Argument_WaitHandleNameTooLong, nameof(name));
                }
#endif
                if (Interop.Errors.ERROR_FILE_NOT_FOUND == errorCode || Interop.Errors.ERROR_INVALID_NAME == errorCode)
                {
                    return(OpenExistingResult.NameNotFound);
                }
                if (Interop.Errors.ERROR_PATH_NOT_FOUND == errorCode)
                {
                    return(OpenExistingResult.PathNotFound);
                }
                if (Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
                {
                    return(OpenExistingResult.NameInvalid);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
            }

            result = new Mutex(myHandle);
            return(OpenExistingResult.Success);
        }
コード例 #18
0
        private IntPtr ExecuteFuntion(string module, string function, byte[] arguments, bool canWait = true)
        {
            SafeWaitHandle remoteThread = null;

            var argumentsAllocation =
                _memoryManager.Allocate(
                    arguments.Length,
                    MemoryProtectionType.ReadWrite, !canWait);

            if (argumentsAllocation.Address == IntPtr.Zero)
            {
                throw new Win32Exception("Failed to allocate memory in remote process.");
            }

            try
            {
                var processHandle = _process.SafeHandle;
                // Write the arguments buffer to our allocated address
                _memoryManager.WriteMemory(argumentsAllocation.Address.ToInt64(), arguments);

                // Execute the function call in a new thread
                remoteThread = ThreadHelper.CreateRemoteThread(processHandle,
                                                               ThreadHelper.GetProcAddress(processHandle, module, function),
                                                               argumentsAllocation.Address);

                if (canWait)
                {
                    Interop.Kernel32.WaitForSingleObject(
                        remoteThread,
                        System.Threading.Timeout.Infinite);
                }

                return(argumentsAllocation.Address);
            }
            finally
            {
                remoteThread?.Dispose();
                if (canWait)
                {
                    _memoryManager.Deallocate(argumentsAllocation);
                }
            }
        }
コード例 #19
0
        private static OpenExistingResult OpenExistingWorker(string name, SemaphoreRights rights, out Semaphore?result)
        {
            ArgumentNullException.ThrowIfNull(name);

            if (name.Length == 0)
            {
                throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
            }

            result = null;
            SafeWaitHandle handle = Interop.Kernel32.OpenSemaphore((uint)rights, false, name);

            int errorCode = Marshal.GetLastPInvokeError();

            if (handle.IsInvalid)
            {
                handle.Dispose();
                return(errorCode switch
                {
                    Interop.Errors.ERROR_FILE_NOT_FOUND or Interop.Errors.ERROR_INVALID_NAME => OpenExistingResult.NameNotFound,
                    Interop.Errors.ERROR_PATH_NOT_FOUND => OpenExistingResult.PathNotFound,
                    Interop.Errors.ERROR_INVALID_HANDLE => OpenExistingResult.NameInvalid,
                    _ => throw Win32Marshal.GetExceptionForLastWin32Error()
                });
コード例 #20
0
        public ChildProcess(string FileName, string CommandLine, string Input)
        {
            JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
            if (JobHandle == null)
            {
                throw new Win32Exception();
            }

            JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

            LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            int    Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);

            Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

            if (SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
            {
                throw new Win32Exception();
            }

            SafeFileHandle StdInRead   = null;
            SafeFileHandle StdOutWrite = null;
            SafeWaitHandle StdErrWrite = null;

            try
            {
                SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
                SecurityAttributes.bInheritHandle = 1;

                if (CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, DUPLICATE_SAME_ACCESS, true, 0) == 0)
                {
                    throw new Win32Exception();
                }

                STARTUPINFO StartupInfo = new STARTUPINFO();
                StartupInfo.cb         = Marshal.SizeOf(StartupInfo);
                StartupInfo.hStdInput  = StdInRead;
                StartupInfo.hStdOutput = StdOutWrite;
                StartupInfo.hStdError  = StdErrWrite;
                StartupInfo.dwFlags    = STARTF_USESTDHANDLES;

                PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();
                try
                {
                    if (CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, CREATE_NO_WINDOW | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, new IntPtr(0), null, StartupInfo, ProcessInfo) == 0)
                    {
                        throw new Win32Exception();
                    }
                    if (AssignProcessToJobObject(JobHandle, ProcessInfo.hProcess) == 0)
                    {
                        throw new Win32Exception();
                    }
                    if (ResumeThread(ProcessInfo.hThread) == -1)
                    {
                        throw new Win32Exception();
                    }

                    using (StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
                    {
                        if (!String.IsNullOrEmpty(Input))
                        {
                            StdInWriter.WriteLine(Input);
                            StdInWriter.Flush();
                        }
                    }

                    InnerStream   = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
                    ReadStream    = new StreamReader(InnerStream, Console.OutputEncoding);
                    ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
                }
                finally
                {
                    if (ProcessInfo.hProcess != null && ProcessHandle == null)
                    {
                        CloseHandle(ProcessInfo.hProcess);
                    }
                    if (ProcessInfo.hThread != null)
                    {
                        CloseHandle(ProcessInfo.hThread);
                    }
                }
            }
            finally
            {
                if (StdInRead != null)
                {
                    StdInRead.Dispose();
                    StdInRead = null;
                }
                if (StdOutWrite != null)
                {
                    StdOutWrite.Dispose();
                    StdOutWrite = null;
                }
                if (StdErrWrite != null)
                {
                    StdErrWrite.Dispose();
                    StdErrWrite = null;
                }
            }
        }
コード例 #21
0
 public void Dispose()
 {
     InterruptWait();
     _handle.Dispose();
 }
コード例 #22
0
        public ChildProcess(string FileName, string WorkingDir, string CommandLine, string Input)
        {
            JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
            if (JobHandle == null)
            {
                throw new Win32Exception();
            }

            JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

            LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            int    Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);

            Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

            if (SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
            {
                throw new Win32Exception();
            }

            PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();

            try
            {
                lock (CreateProcessLock)
                {
                    SafeFileHandle StdInRead   = null;
                    SafeFileHandle StdOutWrite = null;
                    SafeWaitHandle StdErrWrite = null;
                    try
                    {
                        SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
                        SecurityAttributes.nLength        = Marshal.SizeOf(SecurityAttributes);
                        SecurityAttributes.bInheritHandle = 1;

                        if (CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
                        {
                            throw new Win32Exception();
                        }
                        if (CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
                        {
                            throw new Win32Exception();
                        }
                        if (DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, 0, true, DUPLICATE_SAME_ACCESS) == 0)
                        {
                            throw new Win32Exception();
                        }

                        STARTUPINFO StartupInfo = new STARTUPINFO();
                        StartupInfo.cb         = Marshal.SizeOf(StartupInfo);
                        StartupInfo.hStdInput  = StdInRead;
                        StartupInfo.hStdOutput = StdOutWrite;
                        StartupInfo.hStdError  = StdErrWrite;
                        StartupInfo.dwFlags    = STARTF_USESTDHANDLES;

                        if (CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, CREATE_NO_WINDOW | CREATE_SUSPENDED, new IntPtr(0), WorkingDir, StartupInfo, ProcessInfo) == 0)
                        {
                            throw new Win32Exception();
                        }
                    }
                    finally
                    {
                        if (StdInRead != null)
                        {
                            StdInRead.Dispose();
                            StdInRead = null;
                        }
                        if (StdOutWrite != null)
                        {
                            StdOutWrite.Dispose();
                            StdOutWrite = null;
                        }
                        if (StdErrWrite != null)
                        {
                            StdErrWrite.Dispose();
                            StdErrWrite = null;
                        }
                    }
                }

                if (AssignProcessToJobObject(JobHandle, ProcessInfo.hProcess) == 0)
                {
                    // Support for nested job objects was only addeed in Windows 8; prior to that, assigning processes to job objects would fail. Figure out if we're already in a job, and ignore the error if we are.
                    int OriginalError = Marshal.GetLastWin32Error();

                    bool bProcessInJob;
                    IsProcessInJob(GetCurrentProcess(), IntPtr.Zero, out bProcessInJob);

                    if (!bProcessInJob)
                    {
                        throw new Win32Exception(OriginalError);
                    }
                }

                if (ResumeThread(ProcessInfo.hThread) == -1)
                {
                    throw new Win32Exception();
                }

                using (StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
                {
                    if (!String.IsNullOrEmpty(Input))
                    {
                        StdInWriter.WriteLine(Input);
                        StdInWriter.Flush();
                    }
                }

                InnerStream   = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
                ReadStream    = new StreamReader(InnerStream, Console.OutputEncoding);
                ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
            }
            finally
            {
                if (ProcessInfo.hProcess != null && ProcessHandle == null)
                {
                    CloseHandle(ProcessInfo.hProcess);
                }
                if (ProcessInfo.hThread != null)
                {
                    CloseHandle(ProcessInfo.hThread);
                }
            }
        }
コード例 #23
0
        private IntPtr ExecuteFuntion(string module, string function, byte[] arguments, bool canWait = true)
        {
            SafeWaitHandle hThread = null;

            using (var hProcess = GetProcessHandle(_processHandle.Id,
                                                   Interop.Advapi32.ProcessOptions.PROCESS_CREATE_THREAD |
                                                   Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION |
                                                   Interop.Advapi32.ProcessOptions.PROCESS_VM_OPERATION |
                                                   Interop.Advapi32.ProcessOptions.PROCESS_VM_READ |
                                                   Interop.Advapi32.ProcessOptions.PROCESS_VM_WRITE))
            {
                // Allocate space in the remote process for the DLL path.
                IntPtr remoteAllocAddr = Interop.Kernel32.VirtualAllocEx(
                    hProcess,
                    IntPtr.Zero,
                    new UIntPtr((uint)arguments.Length),
                    Interop.Kernel32.AllocationType.Commit | Interop.Kernel32.AllocationType.Reserve,
                    Interop.Kernel32.MemoryProtection.ReadWrite);

                if (remoteAllocAddr == IntPtr.Zero)
                {
                    throw new Win32Exception("Failed to allocate memory in remote process.");
                }

                try
                {
                    // Write the DLL path to the allocated memory.
                    bool result = Interop.Kernel32.WriteProcessMemory(
                        hProcess,
                        remoteAllocAddr,
                        arguments,
                        arguments.Length,
                        out IntPtr bytesWritten);

                    if (!result || bytesWritten.ToInt32() != arguments.Length)
                    {
                        throw new Win32Exception("Failed to allocate memory in remote process.");
                    }

                    // Create a thread in the process at LoadLibraryW and pass it the DLL path.
                    hThread = Interop.Kernel32.CreateRemoteThread(
                        hProcess,
                        IntPtr.Zero,
                        UIntPtr.Zero,
                        GetWin32ProcAddress(module, function),
                        remoteAllocAddr,
                        0,
                        IntPtr.Zero);

                    if (hThread.IsInvalid)
                    {
                        throw new Win32Exception("Failed to create thread in remote process.");
                    }

                    if (canWait)
                    {
                        const int infiniteWait = -1;
                        Interop.Kernel32.WaitForSingleObject(
                            hThread,
                            infiniteWait);
                    }

                    return(remoteAllocAddr);
                }
                finally
                {
                    hThread?.Dispose();
                    if (canWait)
                    {
                        Interop.Kernel32.VirtualFreeEx(
                            hProcess,
                            remoteAllocAddr,
                            new UIntPtr(0),
                            Interop.Kernel32.FreeType.Release);
                    }
                }
            }
        }
コード例 #24
0
 public void Dispose()
 {
     _handle.Dispose();
 }
コード例 #25
0
        /// <summary>
        /// Spawns a new managed process.
        /// </summary>
        /// <param name="FileName">Path to the executable to be run</param>
        /// <param name="CommandLine">Command line arguments for the process</param>
        /// <param name="WorkingDirectory">Working directory for the new process. May be null to use the current working directory.</param>
        /// <param name="Environment">Environment variables for the new process. May be null, in which case the current process' environment is inherited</param>
        /// <param name="Input">Text to be passed via stdin to the new process. May be null.</param>
        public ManagedProcess(string FileName, string CommandLine, string WorkingDirectory, IReadOnlyDictionary <string, string> Environment, string Input, ManagedProcessPriority Priority, ulong MemoryLimit)
        {
            // Create the job object that the child process will be added to
            JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
            if (JobHandle == null)
            {
                throw new Win32Exception();
            }

            // Configure the job object to terminate the processes added to it when the handle is closed
            JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

            LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_PROCESS_MEMORY;
            LimitInformation.ProcessMemoryLimit = new UIntPtr(MemoryLimit);

            int    Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);

            Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

            if (SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
            {
                throw new Win32Exception();
            }

            // Create the child process
            IntPtr         EnvironmentBlock = IntPtr.Zero;
            SafeFileHandle StdInRead        = null;
            SafeFileHandle StdOutWrite      = null;
            SafeWaitHandle StdErrWrite      = null;

            try
            {
                // Create stdin and stdout pipes for the child process. We'll close the handles for the child process' ends after it's been created.
                SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
                SecurityAttributes.bInheritHandle = 1;

                if (CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, DUPLICATE_SAME_ACCESS, true, 0) == 0)
                {
                    throw new Win32Exception();
                }

                // Create the environment block for the child process, if necessary.
                if (Environment != null)
                {
                    // The native format for the environment block is a sequence of null terminated strings with a final null terminator.
                    List <byte> EnvironmentBytes = new List <byte>();
                    foreach (KeyValuePair <string, string> Pair in Environment)
                    {
                        EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Key));
                        EnvironmentBytes.Add((byte)'=');
                        EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Value));
                        EnvironmentBytes.Add((byte)0);
                    }
                    EnvironmentBytes.Add((byte)0);

                    // Allocate an unmanaged block of memory to store it.
                    EnvironmentBlock = Marshal.AllocHGlobal(EnvironmentBytes.Count);
                    Marshal.Copy(EnvironmentBytes.ToArray(), 0, EnvironmentBlock, EnvironmentBytes.Count);
                }

                // Set the startup parameters for the new process
                STARTUPINFO StartupInfo = new STARTUPINFO();
                StartupInfo.cb         = Marshal.SizeOf(StartupInfo);
                StartupInfo.hStdInput  = StdInRead;
                StartupInfo.hStdOutput = StdOutWrite;
                StartupInfo.hStdError  = StdErrWrite;
                StartupInfo.dwFlags    = STARTF_USESTDHANDLES;

                PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();
                try
                {
                    // Get the flags to create the new process
                    ProcessCreationFlags Flags = ProcessCreationFlags.CREATE_NO_WINDOW | ProcessCreationFlags.CREATE_SUSPENDED | ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB;
                    switch (Priority)
                    {
                    case ManagedProcessPriority.BelowNormal:
                        Flags |= ProcessCreationFlags.BELOW_NORMAL_PRIORITY_CLASS;
                        break;

                    case ManagedProcessPriority.Normal:
                        Flags |= ProcessCreationFlags.NORMAL_PRIORITY_CLASS;
                        break;

                    case ManagedProcessPriority.AboveNormal:
                        Flags |= ProcessCreationFlags.ABOVE_NORMAL_PRIORITY_CLASS;
                        break;
                    }

                    // Create the new process as suspended, so we can modify it before it starts executing (and potentially preempting us)
                    if (CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, Flags, EnvironmentBlock, WorkingDirectory, StartupInfo, ProcessInfo) == 0)
                    {
                        throw new Win32Exception();
                    }

                    // Add it to our job object
                    if (AssignProcessToJobObject(JobHandle, ProcessInfo.hProcess) == 0)
                    {
                        throw new Win32Exception();
                    }

                    // Allow the thread to start running
                    if (ResumeThread(ProcessInfo.hThread) == -1)
                    {
                        throw new Win32Exception();
                    }

                    // If we have any input text, write it to stdin now
                    using (StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
                    {
                        if (!String.IsNullOrEmpty(Input))
                        {
                            StdInWriter.WriteLine(Input);
                            StdInWriter.Flush();
                        }
                    }

                    // Create the stream objects for reading the process output
                    InnerStream = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
                    ReadStream  = new StreamReader(InnerStream, Console.OutputEncoding);

                    // Wrap the process handle in a SafeFileHandle
                    ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
                }
                finally
                {
                    if (ProcessInfo.hProcess != IntPtr.Zero && ProcessHandle == null)
                    {
                        CloseHandle(ProcessInfo.hProcess);
                    }
                    if (ProcessInfo.hThread != IntPtr.Zero)
                    {
                        CloseHandle(ProcessInfo.hThread);
                    }
                }
            }
            finally
            {
                if (EnvironmentBlock != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(EnvironmentBlock);
                    EnvironmentBlock = IntPtr.Zero;
                }
                if (StdInRead != null)
                {
                    StdInRead.Dispose();
                    StdInRead = null;
                }
                if (StdOutWrite != null)
                {
                    StdOutWrite.Dispose();
                    StdOutWrite = null;
                }
                if (StdErrWrite != null)
                {
                    StdErrWrite.Dispose();
                    StdErrWrite = null;
                }
            }
        }
コード例 #26
0
        private static int CreateMutexHandle(bool initiallyOwned, string name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle)
        {
            bool flag  = false;
            bool flag2 = false;
            bool flag3 = false;

Label_0006:
            flag2       = false;
            flag3       = false;
            mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name);
            int num = Marshal.GetLastWin32Error();

            if (!mutexHandle.IsInvalid || (num != 5))
            {
                return(num);
            }
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                }
                finally
                {
                    Thread.BeginThreadAffinity();
                    flag = true;
                }
                mutexHandle = Win32Native.OpenMutex(0x100001, false, name);
                if (!mutexHandle.IsInvalid)
                {
                    num = 0xb7;
                    if (Environment.IsW2k3)
                    {
                        SafeWaitHandle handle = Win32Native.OpenMutex(0x100001, false, name);
                        if (!handle.IsInvalid)
                        {
                            RuntimeHelpers.PrepareConstrainedRegions();
                            try
                            {
                                uint     num2    = 0;
                                IntPtr   ptr     = mutexHandle.DangerousGetHandle();
                                IntPtr   ptr2    = handle.DangerousGetHandle();
                                IntPtr[] handles = new IntPtr[] { ptr, ptr2 };
                                num2 = Win32Native.WaitForMultipleObjects(2, handles, true, 0);
                                GC.KeepAlive(handles);
                                if (num2 == uint.MaxValue)
                                {
                                    if (Marshal.GetLastWin32Error() != 0x57)
                                    {
                                        mutexHandle.Dispose();
                                        flag3 = true;
                                    }
                                }
                                else
                                {
                                    flag2 = true;
                                    if ((num2 >= 0) && (num2 < 2))
                                    {
                                        Win32Native.ReleaseMutex(mutexHandle);
                                        Win32Native.ReleaseMutex(handle);
                                    }
                                    else if ((num2 >= 0x80) && (num2 < 130))
                                    {
                                        Win32Native.ReleaseMutex(mutexHandle);
                                        Win32Native.ReleaseMutex(handle);
                                    }
                                    mutexHandle.Dispose();
                                }
                                goto Label_0166;
                            }
                            finally
                            {
                                handle.Dispose();
                            }
                        }
                        mutexHandle.Dispose();
                        flag3 = true;
                    }
                }
                else
                {
                    num = Marshal.GetLastWin32Error();
                }
            }
            finally
            {
                if (flag)
                {
                    Thread.EndThreadAffinity();
                }
            }
Label_0166:
            if ((flag2 || flag3) || (num == 2))
            {
                goto Label_0006;
            }
            if (num == 0)
            {
                num = 0xb7;
            }
            return(num);
        }
コード例 #27
0
        /// <summary>
        /// Spawns a new managed process.
        /// </summary>
        /// <param name="Group">The managed process group to add to</param>
        /// <param name="FileName">Path to the executable to be run</param>
        /// <param name="CommandLine">Command line arguments for the process</param>
        /// <param name="WorkingDirectory">Working directory for the new process. May be null to use the current working directory.</param>
        /// <param name="Environment">Environment variables for the new process. May be null, in which case the current process' environment is inherited</param>
        /// <param name="Input">Text to be passed via stdin to the new process. May be null.</param>
        public ManagedProcess(ManagedProcessGroup Group, string FileName, string CommandLine, string WorkingDirectory, IReadOnlyDictionary <string, string> Environment, string Input, ManagedProcessPriority Priority)
        {
            // Create the child process
            IntPtr EnvironmentBlock = IntPtr.Zero;

            try
            {
                // Create the environment block for the child process, if necessary.
                if (Environment != null)
                {
                    // The native format for the environment block is a sequence of null terminated strings with a final null terminator.
                    List <byte> EnvironmentBytes = new List <byte>();
                    foreach (KeyValuePair <string, string> Pair in Environment)
                    {
                        EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Key));
                        EnvironmentBytes.Add((byte)'=');
                        EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Value));
                        EnvironmentBytes.Add((byte)0);
                    }
                    EnvironmentBytes.Add((byte)0);

                    // Allocate an unmanaged block of memory to store it.
                    EnvironmentBlock = Marshal.AllocHGlobal(EnvironmentBytes.Count);
                    Marshal.Copy(EnvironmentBytes.ToArray(), 0, EnvironmentBlock, EnvironmentBytes.Count);
                }

                PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();
                try
                {
                    // Get the flags to create the new process
                    ProcessCreationFlags Flags = ProcessCreationFlags.CREATE_NO_WINDOW | ProcessCreationFlags.CREATE_SUSPENDED;
                    switch (Priority)
                    {
                    case ManagedProcessPriority.BelowNormal:
                        Flags |= ProcessCreationFlags.BELOW_NORMAL_PRIORITY_CLASS;
                        break;

                    case ManagedProcessPriority.Normal:
                        Flags |= ProcessCreationFlags.NORMAL_PRIORITY_CLASS;
                        break;

                    case ManagedProcessPriority.AboveNormal:
                        Flags |= ProcessCreationFlags.ABOVE_NORMAL_PRIORITY_CLASS;
                        break;
                    }

                    // Acquire a global lock before creating inheritable handles. If multiple threads create inheritable handles at the same time, and child processes will inherit them all.
                    // Since we need to wait for output pipes to be closed (in order to consume all output), this can result in output reads not returning until all processes with the same
                    // inherited handles are closed.
                    lock (LockObject)
                    {
                        SafeFileHandle StdInRead   = null;
                        SafeFileHandle StdOutWrite = null;
                        SafeWaitHandle StdErrWrite = null;
                        try
                        {
                            // Create stdin and stdout pipes for the child process. We'll close the handles for the child process' ends after it's been created.
                            SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
                            SecurityAttributes.nLength        = Marshal.SizeOf(SecurityAttributes);
                            SecurityAttributes.bInheritHandle = 1;

                            if (CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
                            {
                                throw new Win32Exception();
                            }
                            if (CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
                            {
                                throw new Win32Exception();
                            }
                            if (DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, 0, true, DUPLICATE_SAME_ACCESS) == 0)
                            {
                                throw new Win32Exception();
                            }

                            // Create the new process as suspended, so we can modify it before it starts executing (and potentially preempting us)
                            STARTUPINFO StartupInfo = new STARTUPINFO();
                            StartupInfo.cb         = Marshal.SizeOf(StartupInfo);
                            StartupInfo.hStdInput  = StdInRead;
                            StartupInfo.hStdOutput = StdOutWrite;
                            StartupInfo.hStdError  = StdErrWrite;
                            StartupInfo.dwFlags    = STARTF_USESTDHANDLES;

                            if (CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, Flags, EnvironmentBlock, WorkingDirectory, StartupInfo, ProcessInfo) == 0)
                            {
                                throw new Win32Exception();
                            }
                        }
                        finally
                        {
                            // Close the write ends of the handle. We don't want any other process to be able to inherit these.
                            if (StdInRead != null)
                            {
                                StdInRead.Dispose();
                                StdInRead = null;
                            }
                            if (StdOutWrite != null)
                            {
                                StdOutWrite.Dispose();
                                StdOutWrite = null;
                            }
                            if (StdErrWrite != null)
                            {
                                StdErrWrite.Dispose();
                                StdErrWrite = null;
                            }
                        }
                    }

                    // Add it to our job object
                    if (AssignProcessToJobObject(Group.JobHandle, ProcessInfo.hProcess) == 0)
                    {
                        // Support for nested job objects was only addeed in Windows 8; prior to that, assigning processes to job objects would fail. Figure out if we're already in a job, and ignore the error if we are.
                        int OriginalError = Marshal.GetLastWin32Error();

                        bool bProcessInJob;
                        IsProcessInJob(GetCurrentProcess(), IntPtr.Zero, out bProcessInJob);

                        if (!bProcessInJob)
                        {
                            throw new Win32Exception(OriginalError);
                        }
                    }

                    // Allow the thread to start running
                    if (ResumeThread(ProcessInfo.hThread) == -1)
                    {
                        throw new Win32Exception();
                    }

                    // If we have any input text, write it to stdin now
                    using (StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
                    {
                        if (!String.IsNullOrEmpty(Input))
                        {
                            StdInWriter.WriteLine(Input);
                            StdInWriter.Flush();
                        }
                    }

                    // Create the stream objects for reading the process output
                    InnerStream = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
                    ReadStream  = new StreamReader(InnerStream, Console.OutputEncoding);

                    // Wrap the process handle in a SafeFileHandle
                    ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
                }
                finally
                {
                    if (ProcessInfo.hProcess != IntPtr.Zero && ProcessHandle == null)
                    {
                        CloseHandle(ProcessInfo.hProcess);
                    }
                    if (ProcessInfo.hThread != IntPtr.Zero)
                    {
                        CloseHandle(ProcessInfo.hThread);
                    }
                }
            }
            finally
            {
                if (EnvironmentBlock != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(EnvironmentBlock);
                    EnvironmentBlock = IntPtr.Zero;
                }
            }
        }
コード例 #28
0
        private void Dispose(bool disposing)
        {
            lock (_disposeLock)
            {
                if (!_isDisposed)
                {
                    if (disposing)
                    {
                        // Dispose managed resources.

                        // Dispose wait handles.
                        if (_procSafeWaitHandle != null)
                        {
                            _procSafeWaitHandle.Dispose();
                        }

                        // Abort monitor thread.
                        if (_monitorThread != null)
                        {
                            _monitorThread.Abort();
                        }

                        if (_consoleParams.IsAvailable)
                        {
                            // Close console window.
                            unsafe
                            {
                                ConsoleParams *consoleParams = (ConsoleParams *)_consoleParams.Get();

                                if (consoleParams->ConsoleWindowHandle != IntPtr.Zero)
                                {
                                    WinApi.SendMessage(consoleParams->ConsoleWindowHandle, WinApi.WM_CLOSE,
                                                       IntPtr.Zero, IntPtr.Zero);
                                }
                            }
                        }

                        // Dispose shared memory objects.
                        if (_consoleParams != null)
                        {
                            _consoleParams.Dispose();
                        }
                        if (_consoleScreenInfo != null)
                        {
                            _consoleScreenInfo.Dispose();
                        }
                        if (_consoleCursorInfo != null)
                        {
                            _consoleCursorInfo.Dispose();
                        }
                        if (_consoleBufferInfo != null)
                        {
                            _consoleBufferInfo.Dispose();
                        }
                        if (_consoleBuffer != null)
                        {
                            _consoleBuffer.Dispose();
                        }
                        if (_consoleCopyInfo != null)
                        {
                            _consoleCopyInfo.Dispose();
                        }
                        if (_consolePasteInfo != null)
                        {
                            _consolePasteInfo.Dispose();
                        }
                        if (_consoleMouseEvent != null)
                        {
                            _consoleMouseEvent.Dispose();
                        }
                        if (_consoleNewSizeInfo != null)
                        {
                            _consoleNewSizeInfo.Dispose();
                        }
                        if (_consoleNewScrollPos != null)
                        {
                            _consoleNewScrollPos.Dispose();
                        }

                        //// Kill console process.
                        //if (_process != null)
                        //{
                        //    _process.Kill();
                        //    _process.Dispose();
                        //}
                    }

                    // Dispose unmanaged resources.
                }

                _isDisposed = true;
            }
        }