public override void CopyFile(string sourceFullPath, string destFullPath, bool overwrite) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); int errorCode = Interop.mincore.CopyFile(sourceFullPath, destFullPath, !overwrite); if (errorCode != Interop.mincore.Errors.ERROR_SUCCESS) { String fileName = destFullPath; if (errorCode != Interop.mincore.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.mincore.UnsafeCreateFile(sourceFullPath, Win32FileStream.GENERIC_READ, FileShare.Read, ref secAttrs, FileMode.Open, 0, IntPtr.Zero)) { if (handle.IsInvalid) { fileName = sourceFullPath; } } if (errorCode == Interop.mincore.Errors.ERROR_ACCESS_DENIED) { if (DirectoryExists(destFullPath)) { throw new IOException(SR.Format(SR.Arg_FileIsDirectory_Name, destFullPath), Interop.mincore.Errors.ERROR_ACCESS_DENIED); } } } throw Win32Marshal.GetExceptionForWin32Error(errorCode, fileName); } }
private static SafeMemoryMappedFileHandle CreateCore( FileStream fileStream, string mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { SafeFileHandle fileHandle = fileStream != null ? fileStream.SafeFileHandle : null; Interop.mincore.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability); SafeMemoryMappedFileHandle handle = fileHandle != null? Interop.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options, capacity, mapName) : Interop.CreateFileMapping(INVALID_HANDLE_VALUE, ref secAttrs, GetPageAccess(access) | (int)options, capacity, mapName); int errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { if (errorCode == Interop.mincore.Errors.ERROR_ALREADY_EXISTS) { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } else // handle.IsInvalid { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } return(handle); }
private static SafeMemoryMappedFileHandle CreateCore( SafeFileHandle fileHandle, string mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability); // split the long into two ints int capacityLow = unchecked ((int)(capacity & 0x00000000FFFFFFFFL)); int capacityHigh = unchecked ((int)(capacity >> 32)); SafeMemoryMappedFileHandle handle = fileHandle != null? Interop.mincore.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName) : Interop.mincore.CreateFileMapping(INVALID_HANDLE_VALUE, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName); int errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { if (errorCode == Interop.mincore.Errors.ERROR_ALREADY_EXISTS) { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } else if (handle.IsInvalid) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } return(handle); }
internal static SafeFileHandle UnsafeCreateFile( string lpFileName, int dwDesiredAccess, FileShare dwShareMode, ref Interop.mincore.SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile) { return(CreateFile(lpFileName, dwDesiredAccess, dwShareMode, ref securityAttrs, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)); }
internal static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)Marshal.SizeOf(secAttrs); secAttrs.bInheritHandle = true; } return(secAttrs); }
private unsafe static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)sizeof(Interop.mincore.SECURITY_ATTRIBUTES); secAttrs.bInheritHandle = Interop.BOOL.TRUE; } 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.mincore.SECURITY_ATTRIBUTES securityAttributesParent = new Interop.mincore.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.mincore.GetCurrentProcess(); if (!Interop.mincore.DuplicateHandle(currentProcHandle, hTmp, currentProcHandle, out parentHandle, 0, false, Interop.mincore.HandleOptions.DUPLICATE_SAME_ACCESS)) { throw new Win32Exception(); } } finally { if (hTmp != null && !hTmp.IsInvalid) { hTmp.Dispose(); } } }
private void Create(PipeDirection direction, HandleInheritability inheritability, int bufferSize) { Debug.Assert(direction != PipeDirection.InOut, "Anonymous pipe direction shouldn't be InOut"); Debug.Assert(bufferSize >= 0, "bufferSize is negative"); bool bSuccess; SafePipeHandle serverHandle; SafePipeHandle newServerHandle; // Create the two pipe handles that make up the anonymous pipe. Interop.mincore.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability); if (direction == PipeDirection.In) { bSuccess = Interop.mincore.CreatePipe(out serverHandle, out _clientHandle, ref secAttrs, bufferSize); } else { bSuccess = Interop.mincore.CreatePipe(out _clientHandle, out serverHandle, ref secAttrs, bufferSize); } if (!bSuccess) { throw Win32Marshal.GetExceptionForLastWin32Error(); } // Duplicate the server handle to make it not inheritable. Note: We need to do this so that the child // process doesn't end up getting another copy of the server handle. If it were to get a copy, the // OS wouldn't be able to inform the child that the server has closed its handle because it will see // that there is still one server handle that is open. bSuccess = Interop.mincore.DuplicateHandle(Interop.mincore.GetCurrentProcess(), serverHandle, Interop.mincore.GetCurrentProcess(), out newServerHandle, 0, false, Interop.mincore.HandleOptions.DUPLICATE_SAME_ACCESS); if (!bSuccess) { throw Win32Marshal.GetExceptionForLastWin32Error(); } // Close the inheritable server handle. serverHandle.Dispose(); InitializeHandle(newServerHandle, false, false); State = PipeState.Connected; }
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.mincore.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.mincore.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability); SafePipeHandle handle = Interop.mincore.CreateNamedPipe(fullPipeName, openMode, pipeModes, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref secAttrs); if (handle.IsInvalid) { throw Win32Marshal.GetExceptionForLastWin32Error(); } InitializeHandle(handle, false, (options & PipeOptions.Asynchronous) != 0); }
private unsafe RegistryKey CreateSubKeyInternalCore(string subkey, bool writable, RegistryOptions registryOptions) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.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); }
[System.Security.SecurityCritical] // auto-generated internal static SafeFileHandle SafeCreateFile( String lpFileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, ref Interop.mincore.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.mincore.GetFileType(handle); if (fileType != Interop.mincore.FileTypes.FILE_TYPE_DISK) { handle.Dispose(); throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); } } return(handle); }
private static unsafe SafeFileHandle CreateFile( string lpFileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, ref Interop.mincore.SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile) { Interop.mincore.CREATEFILE2_EXTENDED_PARAMETERS parameters; parameters.dwSize = (uint)Marshal.SizeOf <Interop.mincore.CREATEFILE2_EXTENDED_PARAMETERS>(); parameters.dwFileAttributes = (uint)dwFlagsAndAttributes & 0x0000FFFF; parameters.dwSecurityQosFlags = (uint)dwFlagsAndAttributes & 0x000F0000; parameters.dwFileFlags = (uint)dwFlagsAndAttributes & 0xFFF00000; parameters.hTemplateFile = hTemplateFile; fixed(Interop.mincore.SECURITY_ATTRIBUTES *lpSecurityAttributes = &securityAttrs) { parameters.lpSecurityAttributes = (IntPtr)lpSecurityAttributes; return(Interop.mincore.CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, ref parameters)); } }
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.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); SafeFileHandle handle = Interop.mincore.SafeCreateFile( fullPath, (int)Interop.mincore.GenericOperations.GENERIC_WRITE, FileShare.ReadWrite | FileShare.Delete, ref secAttrs, FileMode.Open, asDirectory ? (int)Interop.mincore.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.mincore.Errors.ERROR_PATH_NOT_FOUND && fullPath.Equals(Directory.GetDirectoryRoot(fullPath))) { errorCode = Interop.mincore.Errors.ERROR_ACCESS_DENIED; } throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } return(handle); }
private static SafeMemoryMappedFileHandle CreateCore( FileStream fileStream, string mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { SafeFileHandle fileHandle = fileStream != null ? fileStream.SafeFileHandle : null; Interop.mincore.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability); // split the long into two ints int capacityLow = unchecked ((int)(capacity & 0x00000000FFFFFFFFL)); int capacityHigh = unchecked ((int)(capacity >> 32)); SafeMemoryMappedFileHandle handle = fileHandle != null? Interop.mincore.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName) : Interop.mincore.CreateFileMapping(INVALID_HANDLE_VALUE, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName); int errorCode = Marshal.GetLastWin32Error(); if (!handle.IsInvalid) { // If the object exists before the function call, the function // returns a handle to the existing object (with its current size, // not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS. if (errorCode == Interop.mincore.Errors.ERROR_ALREADY_EXISTS) { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } else // handle.IsInvalid { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } return(handle); }
internal static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)Marshal.SizeOf(secAttrs); secAttrs.bInheritHandle = true; } return secAttrs; }
private static SafeMemoryMappedFileHandle CreateOrOpenCore( string mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity) { /// Try to open the file if it exists -- this requires a bit more work. Loop until we can /// either create or open a memory mapped file up to a timeout. CreateFileMapping may fail /// if the file exists and we have non-null security attributes, in which case we need to /// use OpenFileMapping. But, there exists a race condition because the memory mapped file /// may have closed between the two calls -- hence the loop. /// /// The retry/timeout logic increases the wait time each pass through the loop and times /// out in approximately 1.4 minutes. If after retrying, a MMF handle still hasn't been opened, /// throw an InvalidOperationException. Debug.Assert(access != MemoryMappedFileAccess.Write, "Callers requesting write access shouldn't try to create a mmf"); SafeMemoryMappedFileHandle handle = null; Interop.mincore.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability); // split the long into two ints int capacityLow = unchecked ((int)(capacity & 0x00000000FFFFFFFFL)); int capacityHigh = unchecked ((int)(capacity >> 32)); int waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins int waitSleep = 0; // keep looping until we've exhausted retries or break as soon we get valid handle while (waitRetries > 0) { // try to create handle = Interop.mincore.CreateFileMapping(INVALID_HANDLE_VALUE, ref secAttrs, GetPageAccess(access) | (int)options, capacityHigh, capacityLow, mapName); if (!handle.IsInvalid) { break; } else { handle.Dispose(); int createErrorCode = Marshal.GetLastWin32Error(); if (createErrorCode != Interop.mincore.Errors.ERROR_ACCESS_DENIED) { throw Win32Marshal.GetExceptionForWin32Error(createErrorCode); } } // try to open handle = Interop.mincore.OpenFileMapping(GetFileMapAccess(access), (inheritability & HandleInheritability.Inheritable) != 0, mapName); // valid handle if (!handle.IsInvalid) { break; } // didn't get valid handle; have to retry else { handle.Dispose(); int openErrorCode = Marshal.GetLastWin32Error(); if (openErrorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) { throw Win32Marshal.GetExceptionForWin32Error(openErrorCode); } // increase wait time --waitRetries; if (waitSleep == 0) { waitSleep = 10; } else { ThreadSleep(waitSleep); waitSleep *= 2; } } } // finished retrying but couldn't create or open if (handle == null || handle.IsInvalid) { throw new InvalidOperationException(SR.InvalidOperation_CantCreateFileMapping); } return(handle); }
/// <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.mincore.STARTUPINFO startupInfo = new Interop.mincore.STARTUPINFO(); Interop.mincore.PROCESS_INFORMATION processInfo = new Interop.mincore.PROCESS_INFORMATION(); Interop.mincore.SECURITY_ATTRIBUTES unused_SecAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); SafeProcessHandle procSH = new SafeProcessHandle(); SafeThreadHandle threadSH = new SafeThreadHandle(); bool retVal; int errorCode = 0; // handles used in parent process SafeFileHandle standardInputWritePipeHandle = null; SafeFileHandle standardOutputReadPipeHandle = null; SafeFileHandle standardErrorReadPipeHandle = null; GCHandle environmentHandle = new GCHandle(); lock (s_createProcessLock) { try { // set up the streams if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) { if (startInfo.RedirectStandardInput) { CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true); } else { startupInfo.hStdInput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_INPUT_HANDLE), false); } if (startInfo.RedirectStandardOutput) { CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false); } else { startupInfo.hStdOutput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_OUTPUT_HANDLE), false); } if (startInfo.RedirectStandardError) { CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false); } else { startupInfo.hStdError = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_ERROR_HANDLE), false); } startupInfo.dwFlags = Interop.mincore.StartupInfoOptions.STARTF_USESTDHANDLES; } // set up the creation flags parameter int creationFlags = 0; if (startInfo.CreateNoWindow) { creationFlags |= Interop.mincore.StartupInfoOptions.CREATE_NO_WINDOW; } // set up the environment block parameter IntPtr environmentPtr = (IntPtr)0; if (startInfo._environmentVariables != null) { creationFlags |= Interop.mincore.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) { Interop.mincore.LogonFlags logonFlags = (Interop.mincore.LogonFlags) 0; if (startInfo.LoadUserProfile) { logonFlags = Interop.mincore.LogonFlags.LOGON_WITH_PROFILE; } try { } finally { retVal = Interop.mincore.CreateProcessWithLogonW( startInfo.UserName, startInfo.Domain, startInfo.PasswordInClearText, 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.mincore.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.mincore.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH) { throw new Win32Exception(errorCode, SR.InvalidApplication); } throw new Win32Exception(errorCode); } } else { try { } finally { retVal = Interop.mincore.CreateProcess( null, // we don't need this since all the info is in commandLine commandLine, // pointer to the command line string 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.mincore.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.mincore.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.mincore.GetConsoleCP()); _standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), enc, 4096); _standardInput.AutoFlush = true; } if (startInfo.RedirectStandardOutput) { Encoding enc = startInfo.StandardOutputEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP()); _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096); } if (startInfo.RedirectStandardError) { Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP()); _standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096); } bool ret = false; if (!procSH.IsInvalid) { SetProcessHandle(procSH); SetProcessId((int)processInfo.dwProcessId); threadSH.Dispose(); ret = true; } return(ret); }
private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, ref Interop.mincore.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize) { bool ret = Interop.mincore.CreatePipe(out hReadPipe, out hWritePipe, ref lpPipeAttributes, nSize); if (!ret || hReadPipe.IsInvalid || hWritePipe.IsInvalid) { throw new Win32Exception(); } }
private bool TryConnect(int timeout, CancellationToken cancellationToken) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability); int _pipeFlags = (int)_pipeOptions; if (_impersonationLevel != TokenImpersonationLevel.None) { _pipeFlags |= Interop.mincore.SecurityOptions.SECURITY_SQOS_PRESENT; _pipeFlags |= (((int)_impersonationLevel - 1) << 16); } if (!Interop.mincore.WaitNamedPipe(_normalizedPipePath, timeout)) { int errorCode = Marshal.GetLastWin32Error(); // Server is not yet created if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) { return(false); } // The timeout has expired. if (errorCode == Interop.mincore.Errors.ERROR_SUCCESS) { if (cancellationToken.CanBeCanceled) { // It may not be real timeout. return(false); } throw new TimeoutException(); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Pipe server should be free. Let's try to connect to it. int access = 0; if ((PipeDirection.In & _direction) != 0) { access |= Interop.mincore.GenericOperations.GENERIC_READ; } if ((PipeDirection.Out & _direction) != 0) { access |= Interop.mincore.GenericOperations.GENERIC_WRITE; } SafePipeHandle handle = Interop.mincore.CreateNamedPipeClient(_normalizedPipePath, access, // read and write access 0, // sharing: none ref secAttrs, // security attributes FileMode.Open, // open existing _pipeFlags, // impersonation flags IntPtr.Zero); // template file: null if (handle.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); // Handle the possible race condition of someone else connecting to the server // between our calls to WaitNamedPipe & CreateFile. if (errorCode == Interop.mincore.Errors.ERROR_PIPE_BUSY) { return(false); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Success! InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0); State = PipeState.Connected; return(true); }
[System.Security.SecuritySafeCritical] // auto-generated private unsafe static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); if ((share & FileShare.Inheritable) != 0) { secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)sizeof(Interop.mincore.SECURITY_ATTRIBUTES); secAttrs.bInheritHandle = Interop.BOOL.TRUE; } return secAttrs; }
[System.Security.SecuritySafeCritical] // auto-generated private static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); if ((share & FileShare.Inheritable) != 0) { secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)Marshal.SizeOf(secAttrs); secAttrs.bInheritHandle = 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.mincore.STARTUPINFO startupInfo = new Interop.mincore.STARTUPINFO(); Interop.mincore.PROCESS_INFORMATION processInfo = new Interop.mincore.PROCESS_INFORMATION(); Interop.mincore.SECURITY_ATTRIBUTES unused_SecAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); SafeProcessHandle procSH = new SafeProcessHandle(); SafeThreadHandle threadSH = new SafeThreadHandle(); bool retVal; int errorCode = 0; // handles used in parent process SafeFileHandle standardInputWritePipeHandle = null; SafeFileHandle standardOutputReadPipeHandle = null; SafeFileHandle standardErrorReadPipeHandle = null; GCHandle environmentHandle = new GCHandle(); lock (s_createProcessLock) { try { // set up the streams if (startInfo.RedirectStandardInput || startInfo.RedirectStandardOutput || startInfo.RedirectStandardError) { if (startInfo.RedirectStandardInput) { CreatePipe(out standardInputWritePipeHandle, out startupInfo.hStdInput, true); } else { startupInfo.hStdInput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_INPUT_HANDLE), false); } if (startInfo.RedirectStandardOutput) { CreatePipe(out standardOutputReadPipeHandle, out startupInfo.hStdOutput, false); } else { startupInfo.hStdOutput = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_OUTPUT_HANDLE), false); } if (startInfo.RedirectStandardError) { CreatePipe(out standardErrorReadPipeHandle, out startupInfo.hStdError, false); } else { startupInfo.hStdError = new SafeFileHandle(Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_ERROR_HANDLE), false); } startupInfo.dwFlags = Interop.mincore.StartupInfoOptions.STARTF_USESTDHANDLES; } // set up the creation flags paramater int creationFlags = 0; if (startInfo.CreateNoWindow) creationFlags |= Interop.mincore.StartupInfoOptions.CREATE_NO_WINDOW; // set up the environment block parameter IntPtr environmentPtr = (IntPtr)0; if (startInfo._environmentVariables != null) { creationFlags |= Interop.mincore.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) { Interop.mincore.LogonFlags logonFlags = (Interop.mincore.LogonFlags)0; if (startInfo.LoadUserProfile) { logonFlags = Interop.mincore.LogonFlags.LOGON_WITH_PROFILE; } try { } finally { retVal = Interop.mincore.CreateProcessWithLogonW( startInfo.UserName, startInfo.Domain, startInfo.PasswordInClearText, 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.mincore.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.mincore.Errors.ERROR_EXE_MACHINE_TYPE_MISMATCH) throw new Win32Exception(errorCode, SR.InvalidApplication); throw new Win32Exception(errorCode); } } else { try { } finally { retVal = Interop.mincore.CreateProcess( null, // we don't need this since all the info is in commandLine commandLine, // pointer to the command line string ref unused_SecAttrs, // address to process security attributes, we don't need to inheriat 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.mincore.Errors.ERROR_BAD_EXE_FORMAT || errorCode == Interop.mincore.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.mincore.GetConsoleCP()); _standardInput = new StreamWriter(new FileStream(standardInputWritePipeHandle, FileAccess.Write, 4096, false), enc, 4096); _standardInput.AutoFlush = true; } if (startInfo.RedirectStandardOutput) { Encoding enc = startInfo.StandardOutputEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP()); _standardOutput = new StreamReader(new FileStream(standardOutputReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096); } if (startInfo.RedirectStandardError) { Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.mincore.GetConsoleOutputCP()); _standardError = new StreamReader(new FileStream(standardErrorReadPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096); } bool ret = false; if (!procSH.IsInvalid) { SetProcessHandle(procSH); SetProcessId((int)processInfo.dwProcessId); threadSH.Dispose(); ret = true; } return ret; }
// 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.mincore.SECURITY_ATTRIBUTES securityAttributesParent = new Interop.mincore.SECURITY_ATTRIBUTES(); securityAttributesParent.bInheritHandle = 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.mincore.GetCurrentProcess(); if (!Interop.mincore.DuplicateHandle(currentProcHandle, hTmp, currentProcHandle, out parentHandle, 0, false, Interop.mincore.HandleOptions.DUPLICATE_SAME_ACCESS)) { throw new Win32Exception(); } } finally { if (hTmp != null && !hTmp.IsInvalid) { hTmp.Dispose(); } } }
public override void CreateDirectory(string fullPath) { if (PathInternal.IsDirectoryTooLong(fullPath)) { throw new PathTooLongException(SR.IO_PathTooLong); } // We can save a bunch of work if the directory we want to create already exists. This also // saves us in the case where sub paths are inaccessible (due to ERROR_ACCESS_DENIED) but the // final path is accessable and the directory already exists. For example, consider trying // to create c:\Foo\Bar\Baz, where everything already exists but ACLS prevent access to c:\Foo // and c:\Foo\Bar. In that case, this code will think it needs to create c:\Foo, and c:\Foo\Bar // and fail to due so, causing an exception to be thrown. This is not what we want. if (DirectoryExists(fullPath)) { return; } List <string> stackDir = new List <string>(); // Attempt to figure out which directories don't exist, and only // create the ones we need. Note that InternalExists may fail due // to Win32 ACL's preventing us from seeing a directory, and this // isn't threadsafe. bool somepathexists = false; int length = fullPath.Length; // We need to trim the trailing slash or the code will try to create 2 directories of the same name. if (length >= 2 && PathHelpers.EndsInDirectorySeparator(fullPath)) { length--; } int lengthRoot = PathInternal.GetRootLength(fullPath); if (length > lengthRoot) { // Special case root (fullpath = X:\\) int i = length - 1; while (i >= lengthRoot && !somepathexists) { String dir = fullPath.Substring(0, i + 1); if (!DirectoryExists(dir)) // Create only the ones missing { stackDir.Add(dir); } else { somepathexists = true; } while (i > lengthRoot && !PathInternal.IsDirectorySeparator(fullPath[i])) { i--; } i--; } } int count = stackDir.Count; // If we were passed a DirectorySecurity, convert it to a security // descriptor and set it in he call to CreateDirectory. Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); bool r = true; int firstError = 0; String errorString = fullPath; // If all the security checks succeeded create all the directories while (stackDir.Count > 0) { String name = stackDir[stackDir.Count - 1]; stackDir.RemoveAt(stackDir.Count - 1); r = Interop.mincore.CreateDirectory(name, ref secAttrs); if (!r && (firstError == 0)) { int currentError = Marshal.GetLastWin32Error(); // While we tried to avoid creating directories that don't // exist above, there are at least two cases that will // cause us to see ERROR_ALREADY_EXISTS here. InternalExists // can fail because we didn't have permission to the // directory. Secondly, another thread or process could // create the directory between the time we check and the // time we try using the directory. Thirdly, it could // fail because the target does exist, but is a file. if (currentError != Interop.mincore.Errors.ERROR_ALREADY_EXISTS) { firstError = currentError; } else { // If there's a file in this directory's place, or if we have ERROR_ACCESS_DENIED when checking if the directory already exists throw. if (File.InternalExists(name) || (!DirectoryExists(name, out currentError) && currentError == Interop.mincore.Errors.ERROR_ACCESS_DENIED)) { firstError = currentError; errorString = name; } } } } // We need this check to mask OS differences // Handle CreateDirectory("X:\\") when X: doesn't exist. Similarly for n/w paths. if ((count == 0) && !somepathexists) { String root = Directory.InternalGetDirectoryRoot(fullPath); if (!DirectoryExists(root)) { throw Win32Marshal.GetExceptionForWin32Error(Interop.mincore.Errors.ERROR_PATH_NOT_FOUND, root); } return; } // Only throw an exception if creating the exact directory we // wanted failed to work correctly. if (!r && (firstError != 0)) { throw Win32Marshal.GetExceptionForWin32Error(firstError, errorString); } }
internal unsafe static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(HandleInheritability inheritability) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); if ((inheritability & HandleInheritability.Inheritable) != 0) { secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); secAttrs.nLength = (uint)sizeof(Interop.mincore.SECURITY_ATTRIBUTES); secAttrs.bInheritHandle = Interop.BOOL.TRUE; } return secAttrs; }