public override void CopyFile(string sourceFullPath, string destFullPath, bool overwrite) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); int errorCode = Interop.Kernel32.CopyFile(sourceFullPath, destFullPath, !overwrite); if (errorCode != Interop.Errors.ERROR_SUCCESS) { string fileName = destFullPath; if (errorCode != Interop.Errors.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.Kernel32.UnsafeCreateFile(sourceFullPath, GENERIC_READ, FileShare.Read, ref secAttrs, FileMode.Open, 0, IntPtr.Zero)) { if (handle.IsInvalid) { fileName = sourceFullPath; } } if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED) { if (DirectoryExists(destFullPath)) { throw new IOException(SR.Format(SR.Arg_FileIsDirectory_Name, destFullPath), Interop.Errors.ERROR_ACCESS_DENIED); } } } throw Win32Marshal.GetExceptionForWin32Error(errorCode, fileName); } }
private unsafe SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); int access = ((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | ((_access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0); // Our Inheritable bit was stolen from Windows, but should be set in // the security attributes class. Don't leave this bit set. share &= ~FileShare.Inheritable; // Must use a valid Win32 constant here... if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS parameters = new Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS(); parameters.dwSize = (uint)sizeof(Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS); parameters.dwFileFlags = (uint)options; parameters.lpSecurityAttributes = &secAttrs; using (DisableMediaInsertionPrompt.Create()) { return(ValidateFileHandle(Interop.Kernel32.CreateFile2( lpFileName: _path, dwDesiredAccess: access, dwShareMode: share, dwCreationDisposition: mode, pCreateExParams: ref parameters))); } }
/// <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); } }
private static unsafe SafeFileHandle CreateFileHandle(string fullPath, FileMode mode, FileSystemRights rights, FileShare share, FileOptions options, FileSecurity security) { Debug.Assert(fullPath != null); // Must use a valid Win32 constant if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } // For mitigating local elevation of privilege attack through named pipes make sure we always call CreateFile with SECURITY_ANONYMOUS so that the // named pipe server can't impersonate a high privileged client security context (note that this is the effective default on CreateFile2) // SECURITY_SQOS_PRESENT flags that a SECURITY_ flag is present. int flagsAndAttributes = (int)options | Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS; SafeFileHandle handle; fixed(byte *pSecurityDescriptor = security.GetSecurityDescriptorBinaryForm()) { var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES { nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES), bInheritHandle = ((share & FileShare.Inheritable) != 0) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE, lpSecurityDescriptor = (IntPtr)pSecurityDescriptor }; using (DisableMediaInsertionPrompt.Create()) { handle = Interop.Kernel32.CreateFile(fullPath, (int)rights, share, &secAttrs, mode, flagsAndAttributes, IntPtr.Zero); ValidateFileHandle(handle, fullPath); } } return(handle); }
private static unsafe SafeFileHandle CreateFileOpenHandle(string path, FileMode mode, FileAccess access, FileShare share, FileOptions options) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); int fAccess = ((access & FileAccess.Read) == FileAccess.Read ? Interop.Kernel32.GenericOperations.GENERIC_READ : 0) | ((access & FileAccess.Write) == FileAccess.Write ? Interop.Kernel32.GenericOperations.GENERIC_WRITE : 0); // Our Inheritable bit was stolen from Windows, but should be set in // the security attributes class. Don't leave this bit set. share &= ~FileShare.Inheritable; // Must use a valid Win32 constant here... if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } int flagsAndAttributes = (int)options; // For mitigating local elevation of privilege attack through named pipes // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the // named pipe server can't impersonate a high privileged client security context // (note that this is the effective default on CreateFile2) flagsAndAttributes |= (Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS); using (DisableMediaInsertionPrompt.Create()) { Debug.Assert(path != null); return(ValidateFileHandle( Interop.Kernel32.CreateFile(path, fAccess, share, &secAttrs, mode, flagsAndAttributes, IntPtr.Zero), path, (options & FileOptions.Asynchronous) != 0)); } }
/// <summary> /// Used by the 2 Create factory method groups. A null fileHandle specifies that the /// memory mapped file should not be associated with an existing file on disk (i.e. start /// out empty). /// </summary> private static SafeMemoryMappedFileHandle CreateCore( FileStream?fileStream, string?mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { SafeFileHandle?fileHandle = fileStream != null ? fileStream.SafeFileHandle : null; Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability); SafeMemoryMappedFileHandle handle = fileHandle != null? Interop.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options, capacity, mapName) : Interop.CreateFileMapping(new IntPtr(-1), ref secAttrs, GetPageAccess(access) | (int)options, capacity, mapName); int errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { if (errorCode == Interop.Errors.ERROR_ALREADY_EXISTS) { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } else // handle.IsInvalid { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } return(handle); }
private static unsafe SafeFileHandle CreateFile(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default; if ((share & FileShare.Inheritable) != 0) { secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES { nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES), bInheritHandle = Interop.BOOL.TRUE }; } int fAccess = ((access & FileAccess.Read) == FileAccess.Read ? Interop.Kernel32.GenericOperations.GENERIC_READ : 0) | ((access & FileAccess.Write) == FileAccess.Write ? Interop.Kernel32.GenericOperations.GENERIC_WRITE : 0); // Our Inheritable bit was stolen from Windows, but should be set in // the security attributes class. Don't leave this bit set. share &= ~FileShare.Inheritable; // Must use a valid Win32 constant here... if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } int flagsAndAttributes = (int)options; // For mitigating local elevation of privilege attack through named pipes // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the // named pipe server can't impersonate a high privileged client security context // (note that this is the effective default on CreateFile2) flagsAndAttributes |= (Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS); SafeFileHandle fileHandle = Interop.Kernel32.CreateFile(fullPath, fAccess, share, &secAttrs, mode, flagsAndAttributes, IntPtr.Zero); if (fileHandle.IsInvalid) { // Return a meaningful exception with the full path. // NT5 oddity - when trying to open "C:\" as a Win32FileStream, // we usually get ERROR_PATH_NOT_FOUND from the OS. We should // probably be consistent w/ every other directory. int errorCode = Marshal.GetLastPInvokeError(); if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && fullPath !.Length == PathInternal.GetRootLength(fullPath)) { errorCode = Interop.Errors.ERROR_ACCESS_DENIED; } fileHandle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } fileHandle._path = fullPath; fileHandle._fileOptions = options; fileHandle._lengthCanBeCached = (share & FileShare.Write) == 0 && (access & FileAccess.Write) == 0; return(fileHandle); }
/// <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)); } }
// Creates the anonymous pipe. This overload is used in Mono to implement public constructors. private void Create(PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity) { 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. GCHandle pinningHandle = default; try { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, ref pinningHandle); if (direction == PipeDirection.In) { bSuccess = Interop.Kernel32.CreatePipe(out serverHandle, out _clientHandle, ref secAttrs, bufferSize); } else { bSuccess = Interop.Kernel32.CreatePipe(out _clientHandle, out serverHandle, ref secAttrs, bufferSize); } } finally { if (pinningHandle.IsAllocated) { pinningHandle.Free(); } } 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.Kernel32.DuplicateHandle(Interop.Kernel32.GetCurrentProcess(), serverHandle, Interop.Kernel32.GetCurrentProcess(), out newServerHandle, 0, false, Interop.Kernel32.HandleOptions.DUPLICATE_SAME_ACCESS); if (!bSuccess) { throw Win32Marshal.GetExceptionForLastWin32Error(); } // Close the inheritable server handle. serverHandle.Dispose(); InitializeHandle(newServerHandle, false, false); State = PipeState.Connected; }
internal static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecurityAttributes( GCHandle securityDescriptorHandle, Interop.BOOL inheritHandle = Interop.BOOL.FALSE) { Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributes = new Interop.Kernel32.SECURITY_ATTRIBUTES(); securityAttributes.bInheritHandle = inheritHandle; securityAttributes.nLength = (uint)Marshal.SizeOf(securityAttributes); securityAttributes.lpSecurityDescriptor = securityDescriptorHandle.AddrOfPinnedObject(); return(securityAttributes); }
internal static extern int RegCreateKeyEx( SafeRegistryHandle hKey, string lpSubKey, int Reserved, string lpClass, int dwOptions, int samDesired, ref Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs, out SafeRegistryHandle hkResult, out int lpdwDisposition);
internal static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES { nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES), bInheritHandle = ((inheritability & HandleInheritability.Inheritable) != 0) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE }; return(secAttrs); }
internal static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); secAttrs.bInheritHandle = Interop.BOOL.TRUE; } return(secAttrs); }
internal static SafeFileHandle UnsafeCreateFile( string lpFileName, int dwDesiredAccess, FileShare dwShareMode, ref Interop.Kernel32.SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile) { return(CreateFile(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)); }
/// <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); int errorCode = Marshal.GetLastPInvokeError(); if (handle.IsInvalid) { handle.SetHandleAsInvalid(); if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { throw new WaitHandleCannotBeOpenedException(SR.Format(SR.WaitHandleCannotBeOpenedException_InvalidHandle, name)); } throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } createdNew = (errorCode != Interop.Errors.ERROR_ALREADY_EXISTS); return(CreateAndReplaceHandle(handle)); } }
private static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default; if ((share & FileShare.Inheritable) != 0) { secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES { nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES), bInheritHandle = Interop.BOOL.TRUE }; } return(secAttrs); }
private unsafe SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); int fAccess = ((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | ((_access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0); // Our Inheritable bit was stolen from Windows, but should be set in // the security attributes class. Don't leave this bit set. share &= ~FileShare.Inheritable; // Must use a valid Win32 constant here... if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS parameters = new Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS(); parameters.dwSize = (uint)sizeof(Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS); parameters.dwFileFlags = (uint)options; parameters.lpSecurityAttributes = &secAttrs; SafeFileHandle fileHandle = Interop.Kernel32.CreateFile2( lpFileName: _path, dwDesiredAccess: fAccess, dwShareMode: share, dwCreationDisposition: mode, pCreateExParams: ¶meters); fileHandle.IsAsync = _useAsyncIO; if (fileHandle.IsInvalid) { // Return a meaningful exception with the full path. // NT5 oddity - when trying to open "C:\" as a Win32FileStream, // we usually get ERROR_PATH_NOT_FOUND from the OS. We should // probably be consistent w/ every other directory. int errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && _path.Length == PathInternal.GetRootLength(_path)) { errorCode = Interop.Errors.ERROR_ACCESS_DENIED; } throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path); } return(fileHandle); }
/// <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); } }
/// <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 ); int errorCode = Marshal.GetLastWin32Error(); if (handle.IsInvalid) { handle.SetHandleAsInvalid(); if (errorCode == Interop.Errors.ERROR_FILENAME_EXCED_RANGE) { throw new ArgumentException(SR.Argument_WaitHandleNameTooLong, nameof(name)); } if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); } throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } createdNew = (errorCode != Interop.Errors.ERROR_ALREADY_EXISTS); return(CreateAndReplaceHandle(handle)); } }
internal static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability, PipeSecurity pipeSecurity, ref GCHandle pinningHandle) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability); if (pipeSecurity != null) { byte[] securityDescriptor = pipeSecurity.GetSecurityDescriptorBinaryForm(); pinningHandle = GCHandle.Alloc(securityDescriptor, GCHandleType.Pinned); fixed(byte *pSecurityDescriptor = securityDescriptor) { secAttrs.lpSecurityDescriptor = (IntPtr)pSecurityDescriptor; } } return(secAttrs); }
// 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 synchronously! private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs) { Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributesParent = new Interop.Kernel32.SECURITY_ATTRIBUTES(); securityAttributesParent.bInheritHandle = Interop.BOOL.TRUE; SafeFileHandle hTmp = null; try { if (parentInputs) { CreatePipeWithSecurityAttributes(out childHandle, out hTmp, ref securityAttributesParent, 0); } else { CreatePipeWithSecurityAttributes(out hTmp, out childHandle, ref 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.Kernel32.GetCurrentProcess(); if (!Interop.Kernel32.DuplicateHandle(currentProcHandle, hTmp, currentProcHandle, out parentHandle, 0, false, Interop.Kernel32.HandleOptions.DUPLICATE_SAME_ACCESS)) { throw new Win32Exception(); } } finally { if (hTmp != null && !hTmp.IsInvalid) { hTmp.Dispose(); } } }
/// <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); } }
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(nameof(pipeName), SR.ArgumentOutOfRange_AnonymousReserved); } int openMode = ((int)direction) | (maxNumberOfServerInstances == 1 ? Interop.Kernel32.FileOperations.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.Kernel32.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability); SafePipeHandle handle = Interop.Kernel32.CreateNamedPipe(fullPipeName, openMode, pipeModes, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref secAttrs); if (handle.IsInvalid) { throw Win32Marshal.GetExceptionForLastWin32Error(); } InitializeHandle(handle, false, (options & PipeOptions.Asynchronous) != 0); }
private unsafe RegistryKey CreateSubKeyInternalCore(string subkey, RegistryKeyPermissionCheck permissionCheck, object registrySecurityObj, RegistryOptions registryOptions) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); int disposition = 0; // By default, the new key will be writable. SafeRegistryHandle result = null; int ret = Interop.Advapi32.RegCreateKeyEx(_hkey, subkey, 0, null, (int)registryOptions /* specifies if the key is volatile */, GetRegistryKeyAccess(permissionCheck != RegistryKeyPermissionCheck.ReadSubTree) | (int)_regView, ref secAttrs, out result, out disposition); if (ret == 0 && !result.IsInvalid) { RegistryKey key = new RegistryKey(result, (permissionCheck != RegistryKeyPermissionCheck.ReadSubTree), false, _remoteKey, false, _regView); CheckPermission(RegistryInternalCheck.CheckSubTreePermission, subkey, false, permissionCheck); key._checkMode = permissionCheck; if (subkey.Length == 0) { key._keyName = _keyName; } else { key._keyName = _keyName + "\\" + subkey; } return(key); } else if (ret != 0) // syscall failed, ret is an error code. { Win32Error(ret, _keyName + "\\" + subkey); // Access denied? } Debug.Fail("Unexpected code path in RegistryKey::CreateSubKey"); return(null); }
public void SafeMemoryMappedViewHandle_CanUseInPInvoke_Windows() { const int BUF_SIZE = 256; Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default; using SafeMemoryMappedFileHandle fileHandle = Interop.Kernel32.CreateFileMapping( new IntPtr(-1), ref secAttrs, Interop.Kernel32.PageOptions.PAGE_EXECUTE_READWRITE, 0, BUF_SIZE, CreateUniqueMapName()); using SafeMemoryMappedViewHandle handle = Interop.Kernel32.MapViewOfFile( fileHandle, Interop.Kernel32.FileMapOptions.FILE_MAP_READ, 0, 0, (UIntPtr)BUF_SIZE); Assert.NotNull(handle); }
internal static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability, PipeSecurity pipeSecurity, ref GCHandle pinningHandle) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs.bInheritHandle = Interop.BOOL.TRUE; } if (pipeSecurity != null) { byte[] securityDescriptor = pipeSecurity.GetSecurityDescriptorBinaryForm(); pinningHandle = GCHandle.Alloc(securityDescriptor, GCHandleType.Pinned); fixed(byte *pSecurityDescriptor = securityDescriptor) { secAttrs.lpSecurityDescriptor = (IntPtr)pSecurityDescriptor; } } return(secAttrs); }
private unsafe RegistryKey CreateSubKeyInternalCore(string subkey, bool writable, RegistryOptions registryOptions) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); int disposition = 0; // By default, the new key will be writable. SafeRegistryHandle result = null; int ret = Interop.mincore.RegCreateKeyEx(_hkey, subkey, 0, null, (int)registryOptions /* specifies if the key is volatile */, (int)GetRegistryKeyRights(writable) | (int)_regView, ref secAttrs, out result, out disposition); if (ret == 0 && !result.IsInvalid) { RegistryKey key = new RegistryKey(result, writable, false, _remoteKey, false, _regView); if (subkey.Length == 0) { key._keyName = _keyName; } else { key._keyName = _keyName + "\\" + subkey; } return(key); } else if (ret != 0) // syscall failed, ret is an error code. { Win32Error(ret, _keyName + "\\" + subkey); // Access denied? } Debug.Fail("Unexpected code path in RegistryKey::CreateSubKey"); return(null); }
internal static unsafe SafeFileHandle UnsafeCreateFile( string lpFileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, ref Interop.Kernel32.SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile) { Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS parameters; parameters.dwSize = (uint)Marshal.SizeOf <Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS>(); parameters.dwFileAttributes = (uint)dwFlagsAndAttributes & 0x0000FFFF; parameters.dwSecurityQosFlags = (uint)dwFlagsAndAttributes & 0x000F0000; parameters.dwFileFlags = (uint)dwFlagsAndAttributes & 0xFFF00000; parameters.hTemplateFile = hTemplateFile; fixed(Interop.Kernel32.SECURITY_ATTRIBUTES *lpSecurityAttributes = &securityAttrs) { parameters.lpSecurityAttributes = (IntPtr)lpSecurityAttributes; return(Interop.Kernel32.CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, ref parameters)); } }
[System.Security.SecurityCritical] // auto-generated internal static SafeFileHandle SafeCreateFile( String lpFileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, ref Interop.Kernel32.SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile) { SafeFileHandle handle = UnsafeCreateFile(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); if (!handle.IsInvalid) { int fileType = Interop.Kernel32.GetFileType(handle); if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK) { handle.Dispose(); throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); } } return(handle); }
private static SafeFileHandle OpenHandle(string fullPath, bool asDirectory) { string root = fullPath.Substring(0, PathInternal.GetRootLength(fullPath)); if (root == fullPath && root[1] == Path.VolumeSeparatorChar) { // intentionally not fullpath, most upstack public APIs expose this as path. throw new ArgumentException(SR.Arg_PathIsVolume, "path"); } Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); SafeFileHandle handle = Interop.Kernel32.SafeCreateFile( fullPath, Interop.Kernel32.GenericOperations.GENERIC_WRITE, FileShare.ReadWrite | FileShare.Delete, ref secAttrs, FileMode.Open, asDirectory ? Interop.Kernel32.FileOperations.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.Errors.ERROR_PATH_NOT_FOUND && fullPath.Equals(Directory.GetDirectoryRoot(fullPath))) { errorCode = Interop.Errors.ERROR_ACCESS_DENIED; } throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } return(handle); }
private static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); secAttrs.bInheritHandle = Interop.BOOL.TRUE; } return secAttrs; }
private unsafe static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); if ((share & FileShare.Inheritable) != 0) { secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); secAttrs.bInheritHandle = Interop.BOOL.TRUE; } return secAttrs; }
/// <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.Kernel32.STARTUPINFO startupInfo = new Interop.Kernel32.STARTUPINFO(); Interop.Kernel32.PROCESS_INFORMATION processInfo = new Interop.Kernel32.PROCESS_INFORMATION(); Interop.Kernel32.SECURITY_ATTRIBUTES unused_SecAttrs = new Interop.Kernel32.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.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_INPUT_HANDLE), false); } if (startInfo.RedirectStandardOutput) { CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false); } else { startupInfo.hStdOutput = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_OUTPUT_HANDLE), false); } if (startInfo.RedirectStandardError) { CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false); } else { startupInfo.hStdError = new SafeFileHandle(Interop.Kernel32.GetStdHandle(Interop.Kernel32.HandleTypes.STD_ERROR_HANDLE), false); } startupInfo.dwFlags = Interop.Advapi32.StartupInfoOptions.STARTF_USESTDHANDLES; } // set up the creation flags parameter int creationFlags = 0; if (startInfo.CreateNoWindow) creationFlags |= Interop.Advapi32.StartupInfoOptions.CREATE_NO_WINDOW; // set up the environment block parameter IntPtr environmentPtr = (IntPtr)0; if (startInfo._environmentVariables != null) { creationFlags |= Interop.Advapi32.StartupInfoOptions.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(); if (startInfo.UserName.Length != 0) { if (startInfo.Password != null && startInfo.PasswordInClearText != null) { throw new ArgumentException(SR.CantSetDuplicatePassword); } Interop.Advapi32.LogonFlags logonFlags = (Interop.Advapi32.LogonFlags)0; if (startInfo.LoadUserProfile) { logonFlags = Interop.Advapi32.LogonFlags.LOGON_WITH_PROFILE; } if (startInfo.Password != null) { IntPtr passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(startInfo.Password); try { retVal = Interop.Advapi32.CreateProcessWithLogonW( startInfo.UserName, startInfo.Domain, passwordPtr, logonFlags, null, // we don't need this since all the info is in commandLine commandLine, creationFlags, environmentPtr, workingDirectory, startupInfo, // pointer to STARTUPINFO processInfo // pointer to PROCESS_INFORMATION ); if (!retVal) errorCode = Marshal.GetLastWin32Error(); } finally { Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr); } } else { unsafe { fixed (char* passwordPtr = startInfo.PasswordInClearText ?? string.Empty) { retVal = Interop.Advapi32.CreateProcessWithLogonW( startInfo.UserName, startInfo.Domain, (IntPtr)passwordPtr, logonFlags, null, // we don't need this since all the info is in commandLine commandLine, creationFlags, environmentPtr, workingDirectory, startupInfo, // pointer to STARTUPINFO processInfo // pointer to PROCESS_INFORMATION ); } } if (!retVal) errorCode = Marshal.GetLastWin32Error(); } if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != (IntPtr)INVALID_HANDLE_VALUE) procSH.InitialSetHandle(processInfo.hProcess); if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != (IntPtr)INVALID_HANDLE_VALUE) threadSH.InitialSetHandle(processInfo.hThread); if (!retVal) { if (errorCode == Interop.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH) { throw new Win32Exception(errorCode, SR.InvalidApplication); } throw new Win32Exception(errorCode); } } else { retVal = Interop.Kernel32.CreateProcess( null, // we don't need this since all the info is in commandLine commandLine, // pointer to the command line string ref unused_SecAttrs, // address to process security attributes, we don't need to inherit the handle ref 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)INVALID_HANDLE_VALUE) procSH.InitialSetHandle(processInfo.hProcess); if (processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)INVALID_HANDLE_VALUE) threadSH.InitialSetHandle(processInfo.hThread); if (!retVal) { if (errorCode == Interop.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.Errors.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.Kernel32.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.Kernel32.GetConsoleOutputCP()); _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096); } if (startInfo.RedirectStandardError) { Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.Kernel32.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; }