| File: src\sdk\artifacts\.packages\microsoft.codeanalysis.buildclient\5.10.0-1.26371.101\contentFiles\cs\net11.0\NativeMethods.cs | Web Access |
| Project: src\sdk\src\Cli\dotnet\dotnet.csproj (dotnet) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable enable using System; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using Microsoft.Win32.SafeHandles; namespace Microsoft.CodeAnalysis.CommandLine { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct STARTUPINFO { internal Int32 cb; internal string? lpReserved; internal string? lpDesktop; internal string? lpTitle; internal Int32 dwX; internal Int32 dwY; internal Int32 dwXSize; internal Int32 dwYSize; internal Int32 dwXCountChars; internal Int32 dwYCountChars; internal Int32 dwFillAttribute; internal Int32 dwFlags; internal Int16 wShowWindow; internal Int16 cbReserved2; internal IntPtr lpReserved2; internal IntPtr hStdInput; internal IntPtr hStdOutput; internal IntPtr hStdError; } [StructLayout(LayoutKind.Sequential)] internal struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public int dwProcessId; public int dwThreadId; } /// <summary> /// Interop methods. /// </summary> #if NET [SupportedOSPlatform("windows")] #endif internal static class NativeMethods { #region Constants internal static readonly IntPtr NullPtr = IntPtr.Zero; internal static readonly IntPtr InvalidIntPtr = new IntPtr(-1); internal const uint NORMAL_PRIORITY_CLASS = 0x0020; internal const uint CREATE_NO_WINDOW = 0x08000000; internal const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400; internal const Int32 STARTF_USESTDHANDLES = 0x00000100; internal const int ERROR_SUCCESS = 0; #endregion //------------------------------------------------------------------------------ // CloseHandle //------------------------------------------------------------------------------ [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CloseHandle(IntPtr hObject); //------------------------------------------------------------------------------ // CreateProcess //------------------------------------------------------------------------------ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CreateProcess ( string? lpApplicationName, [In, Out] StringBuilder lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, [In, MarshalAs(UnmanagedType.Bool)] bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation ); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr GetCommandLine(); #if !NET //------------------------------------------------------------------------------ // ResolveLinkTarget //------------------------------------------------------------------------------ extension(File) { public static FileSystemInfo? ResolveLinkTarget(string path, bool returnFinalTarget) { return ResolveLinkTargetWin32(path, returnFinalTarget); } } #endif /// <remarks> /// Unlike .NET Core's implementation of <c>File.ResolveLinkTarget</c>, /// this resolves virtual disk mappings (created via <c>subst</c>). /// </remarks> public static FileSystemInfo? ResolveLinkTargetWin32(string path, bool returnFinalTarget) { if (!returnFinalTarget) throw new NotSupportedException(); using var handle = CreateFileW( lpFileName: path, dwDesiredAccess: FILE_READ_ATTRIBUTES, dwShareMode: FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, lpSecurityAttributes: IntPtr.Zero, dwCreationDisposition: OPEN_EXISTING, dwFlagsAndAttributes: FILE_FLAG_BACKUP_SEMANTICS, // needed for directories hTemplateFile: IntPtr.Zero); if (handle.IsInvalid) { return null; } uint flags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS; uint needed = GetFinalPathNameByHandleW(hFile: handle, lpszFilePath: null, cchFilePath: 0, dwFlags: flags); if (needed == 0) return null; var sb = new StringBuilder((int)needed + 1); uint len = GetFinalPathNameByHandleW(hFile: handle, lpszFilePath: sb, cchFilePath: (uint)sb.Capacity, dwFlags: flags); if (len == 0) return null; return new FileInfo(TrimWin32ExtendedPrefix(sb.ToString())); } private static string TrimWin32ExtendedPrefix(string s) { if (s.StartsWith(@"\\?\UNC\", StringComparison.Ordinal)) return @"\\" + s.Substring(8); if (s.StartsWith(@"\\?\", StringComparison.Ordinal)) return s.Substring(4); return s; } // https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants private const uint FILE_READ_ATTRIBUTES = 0x0080; // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew private const uint FILE_SHARE_READ = 0x00000001; private const uint FILE_SHARE_WRITE = 0x00000002; private const uint FILE_SHARE_DELETE = 0x00000004; private const uint OPEN_EXISTING = 3; private const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew private const uint VOLUME_NAME_DOS = 0x0; private const uint FILE_NAME_NORMALIZED = 0x0; // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern SafeFileHandle CreateFileW( string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern uint GetFinalPathNameByHandleW( SafeFileHandle hFile, StringBuilder? lpszFilePath, uint cchFilePath, uint dwFlags); } }