From 3dc95ced87d38c347a9fc3a222eb4c52eaad4615 Mon Sep 17 00:00:00 2001 From: Ilya Date: Wed, 30 Nov 2022 23:00:12 +0500 Subject: [PATCH] Replace `DllImport` with `LibraryImport` - 1 (#18603) --- .../CoreCLR/CorePsPlatform.cs | 24 +-- .../System.Management.Automation.csproj | 8 +- .../CommandCompletion/CompletionCompleters.cs | 39 ++--- .../engine/Interop/Windows/AllocConsole.cs | 16 ++ .../engine/Interop/Windows/CoInitializeEx.cs | 18 ++ .../engine/Interop/Windows/CoUninitialize.cs | 15 ++ .../engine/Interop/Windows/CreateHardLink.cs | 16 ++ .../Interop/Windows/CreateSymbolicLink.cs | 25 +++ .../engine/Interop/Windows/FindClose.cs | 16 ++ .../engine/Interop/Windows/FindFirstFile.cs | 55 ++++++ .../Interop/Windows/GetConsoleWindow.cs | 15 ++ .../Interop/Windows/GetCurrentThreadId.cs | 2 - .../Interop/Windows/GetForegroundWindow.cs | 15 ++ .../engine/Interop/Windows/GetOEMCP.cs | 15 ++ .../engine/Interop/Windows/NetShareEnum.cs | 28 ++++ .../Windows/NtQueryInformationProcess.cs | 31 ++++ .../engine/Interop/Windows/QueryDosDevice.cs | 2 - ...ueryProcessPlaceholderCompatibilityMode.cs | 25 +++ .../engine/Interop/Windows/SHGetFileInfo.cs | 2 - .../Interop/Windows/SetForegroundWindow.cs | 16 ++ .../engine/Interop/Windows/ShowWindow.cs | 32 ++++ .../engine/Interop/Windows/VariantClear.cs | 2 - .../Interop/Windows/WNetCancelConnection2.cs | 15 ++ .../engine/NativeCommandProcessor.cs | 114 ++----------- .../engine/ProcessCodeMethods.cs | 26 +-- .../namespaces/FileSystemProvider.cs | 157 ++---------------- .../utils/ClrFacade.cs | 17 +- 27 files changed, 413 insertions(+), 333 deletions(-) create mode 100644 src/System.Management.Automation/engine/Interop/Windows/AllocConsole.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/CoInitializeEx.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/CoUninitialize.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/CreateHardLink.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/CreateSymbolicLink.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/FindClose.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/FindFirstFile.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/GetConsoleWindow.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/GetForegroundWindow.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/GetOEMCP.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/NetShareEnum.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/NtQueryInformationProcess.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/RtlQueryProcessPlaceholderCompatibilityMode.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/SetForegroundWindow.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/ShowWindow.cs create mode 100644 src/System.Management.Automation/engine/Interop/Windows/WNetCancelConnection2.cs diff --git a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs index 8f379acc71..39ba394842 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs @@ -163,19 +163,16 @@ namespace System.Management.Automation private static readonly Lazy _isStaSupported = new Lazy(() => { - // See objbase.h - const int COINIT_APARTMENTTHREADED = 0x2; - const int E_NOTIMPL = unchecked((int)0X80004001); - int result = Windows.NativeMethods.CoInitializeEx(IntPtr.Zero, COINIT_APARTMENTTHREADED); + int result = Interop.Windows.CoInitializeEx(IntPtr.Zero, Interop.Windows.COINIT_APARTMENTTHREADED); // If 0 is returned the thread has been initialized for the first time // as an STA and thus supported and needs to be uninitialized. if (result > 0) { - Windows.NativeMethods.CoUninitialize(); + Interop.Windows.CoUninitialize(); } - return result != E_NOTIMPL; + return result != Interop.Windows.E_NOTIMPL; }); private static bool? _isNanoServer = null; @@ -453,21 +450,6 @@ namespace System.Management.Automation return Unix.NativeMethods.WaitPid(pid, nohang); } - internal static partial class Windows - { - /// The native methods class. - internal static partial class NativeMethods - { - private const string ole32Lib = "api-ms-win-core-com-l1-1-0.dll"; - - [LibraryImport(ole32Lib)] - internal static partial int CoInitializeEx(IntPtr reserve, int coinit); - - [LibraryImport(ole32Lib)] - internal static partial void CoUninitialize(); - } - } - // Please note that `Win32Exception(Marshal.GetLastWin32Error())` // works *correctly* on Linux in that it creates an exception with // the string perror would give you for the last set value of errno. diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 115e6ab354..97d6416128 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -86,10 +86,11 @@ - - + + + @@ -97,4 +98,7 @@ + + + diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index 60a2c31124..467526a015 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -30,7 +30,7 @@ namespace System.Management.Automation { /// /// - public static partial class CompletionCompleters + public static class CompletionCompleters { static CompletionCompleters() { @@ -4739,47 +4739,48 @@ namespace System.Management.Automation public string remark; } - private const int MAX_PREFERRED_LENGTH = -1; - private const int NERR_Success = 0; - private const int ERROR_MORE_DATA = 234; - private const int STYPE_DISKTREE = 0; - private const int STYPE_MASK = 0x000000FF; - private static readonly System.IO.EnumerationOptions _enumerationOptions = new System.IO.EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, AttributesToSkip = 0 // Default is to skip Hidden and System files, so we clear this to retain existing behavior }; - [LibraryImport("Netapi32.dll", StringMarshalling = StringMarshalling.Utf16)] - private static partial int NetShareEnum(string serverName, int level, out IntPtr bufptr, int prefMaxLen, - out uint entriesRead, out uint totalEntries, ref uint resumeHandle); - internal static List GetFileShares(string machine, bool ignoreHidden) { #if UNIX return new List(); #else - IntPtr shBuf; - uint numEntries; + nint shBuf = nint.Zero; + uint numEntries = 0; uint totalEntries; uint resumeHandle = 0; - int result = NetShareEnum(machine, 1, out shBuf, - MAX_PREFERRED_LENGTH, out numEntries, out totalEntries, - ref resumeHandle); + int result = Interop.Windows.NetShareEnum( + machine, + level: 1, + out shBuf, + Interop.Windows.MAX_PREFERRED_LENGTH, + out numEntries, + out totalEntries, + ref resumeHandle); var shares = new List(); - if (result == NERR_Success || result == ERROR_MORE_DATA) + if (result == Interop.Windows.NERR_Success || result == Interop.Windows.ERROR_MORE_DATA) { for (int i = 0; i < numEntries; ++i) { - IntPtr curInfoPtr = (IntPtr)((long)shBuf + (Marshal.SizeOf() * i)); + nint curInfoPtr = shBuf + (Marshal.SizeOf() * i); SHARE_INFO_1 shareInfo = Marshal.PtrToStructure(curInfoPtr); - if ((shareInfo.type & STYPE_MASK) != STYPE_DISKTREE) + if ((shareInfo.type & Interop.Windows.STYPE_MASK) != Interop.Windows.STYPE_DISKTREE) + { continue; + } + if (ignoreHidden && shareInfo.netname.EndsWith('$')) + { continue; + } + shares.Add(shareInfo.netname); } } diff --git a/src/System.Management.Automation/engine/Interop/Windows/AllocConsole.cs b/src/System.Management.Automation/engine/Interop/Windows/AllocConsole.cs new file mode 100644 index 0000000000..072e5d1b18 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/AllocConsole.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool AllocConsole(); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/CoInitializeEx.cs b/src/System.Management.Automation/engine/Interop/Windows/CoInitializeEx.cs new file mode 100644 index 0000000000..a3eae4fd59 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/CoInitializeEx.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Windows + { + internal const int COINIT_APARTMENTTHREADED = 0x2; + internal const int E_NOTIMPL = unchecked((int)0X80004001); + + [LibraryImport("api-ms-win-core-com-l1-1-0.dll")] + internal static partial int CoInitializeEx(nint reserve, int coinit); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/CoUninitialize.cs b/src/System.Management.Automation/engine/Interop/Windows/CoUninitialize.cs new file mode 100644 index 0000000000..d872cf17f3 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/CoUninitialize.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Windows + { + [LibraryImport("api-ms-win-core-com-l1-1-0.dll")] + internal static partial void CoUninitialize(); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/CreateHardLink.cs b/src/System.Management.Automation/engine/Interop/Windows/CreateHardLink.cs new file mode 100644 index 0000000000..a6cbc61619 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/CreateHardLink.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("api-ms-win-core-file-l2-1-0.dll", EntryPoint = "CreateHardLinkW", StringMarshalling = StringMarshalling.Utf16)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool CreateHardLink(string name, string existingFileName, nint securityAttributes); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/CreateSymbolicLink.cs b/src/System.Management.Automation/engine/Interop/Windows/CreateSymbolicLink.cs new file mode 100644 index 0000000000..2c4995d878 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/CreateSymbolicLink.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [Flags] + internal enum SymbolicLinkFlags + { + File = 0, + Directory = 1, + AllowUnprivilegedCreate = 2, + } + + [LibraryImport("api-ms-win-core-file-l2-1-0.dll", EntryPoint = "CreateSymbolicLinkW", StringMarshalling = StringMarshalling.Utf16)] + [return: MarshalAs(UnmanagedType.I1)] + internal static partial bool CreateSymbolicLink(string name, string destination, SymbolicLinkFlags symbolicLinkFlags); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/FindClose.cs b/src/System.Management.Automation/engine/Interop/Windows/FindClose.cs new file mode 100644 index 0000000000..a5903c72c7 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/FindClose.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("api-ms-win-core-file-l1-1-0.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool FindClose(nint handle); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/FindFirstFile.cs b/src/System.Management.Automation/engine/Interop/Windows/FindFirstFile.cs new file mode 100644 index 0000000000..b3cd84b028 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/FindFirstFile.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Keep native struct names.")] + [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "Keep native struct names.")] + internal static unsafe partial class Windows + { + internal const int MAX_PATH = 260; + + internal struct FILE_TIME + { + public uint dwLowDateTime; + public uint dwHighDateTime; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal unsafe struct WIN32_FIND_DATA + { + internal uint dwFileAttributes; + internal FILE_TIME ftCreationTime; + internal FILE_TIME ftLastAccessTime; + internal FILE_TIME ftLastWriteTime; + internal uint nFileSizeHigh; + internal uint nFileSizeLow; + internal uint dwReserved0; + internal uint dwReserved1; + internal fixed char cFileName[MAX_PATH]; + internal fixed char cAlternateFileName[14]; + } + + internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private SafeFindHandle() : base(true) { } + + protected override bool ReleaseHandle() + { + return Interop.Windows.FindClose(this.handle); + } + } + + // We use 'FindFirstFileW' instead of 'FindFirstFileExW' because the latter doesn't work correctly with Unicode file names on FAT32. + // See https://github.com/PowerShell/PowerShell/issues/16804 + [LibraryImport("api-ms-win-core-file-l1-1-0.dll", EntryPoint = "FindFirstFileW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] + internal static partial SafeFindHandle FindFirstFile(string lpFileName, ref WIN32_FIND_DATA lpFindFileData); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/GetConsoleWindow.cs b/src/System.Management.Automation/engine/Interop/Windows/GetConsoleWindow.cs new file mode 100644 index 0000000000..60d9229ea6 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/GetConsoleWindow.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("Kernel32.dll")] + internal static partial nint GetConsoleWindow(); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/GetCurrentThreadId.cs b/src/System.Management.Automation/engine/Interop/Windows/GetCurrentThreadId.cs index 84da911898..80a0c7a4c4 100644 --- a/src/System.Management.Automation/engine/Interop/Windows/GetCurrentThreadId.cs +++ b/src/System.Management.Automation/engine/Interop/Windows/GetCurrentThreadId.cs @@ -3,7 +3,6 @@ #nullable enable -#if !UNIX using System.Runtime.InteropServices; internal static partial class Interop @@ -14,4 +13,3 @@ internal static partial class Interop internal static partial uint GetCurrentThreadId(); } } -#endif diff --git a/src/System.Management.Automation/engine/Interop/Windows/GetForegroundWindow.cs b/src/System.Management.Automation/engine/Interop/Windows/GetForegroundWindow.cs new file mode 100644 index 0000000000..2ba5753516 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/GetForegroundWindow.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("user32.dll")] + internal static partial nint GetForegroundWindow(); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/GetOEMCP.cs b/src/System.Management.Automation/engine/Interop/Windows/GetOEMCP.cs new file mode 100644 index 0000000000..4267deb116 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/GetOEMCP.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("api-ms-win-core-localization-l1-2-0.dll")] + internal static partial uint GetOEMCP(); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/NetShareEnum.cs b/src/System.Management.Automation/engine/Interop/Windows/NetShareEnum.cs new file mode 100644 index 0000000000..c3b430dec1 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/NetShareEnum.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + internal const int MAX_PREFERRED_LENGTH = -1; + internal const int NERR_Success = 0; + internal const int ERROR_MORE_DATA = 234; + internal const int STYPE_DISKTREE = 0; + internal const int STYPE_MASK = 0x000000FF; + + [LibraryImport("Netapi32.dll", StringMarshalling = StringMarshalling.Utf16)] + internal static partial int NetShareEnum( + string serverName, + int level, + out nint bufptr, + int prefMaxLen, + out uint entriesRead, + out uint totalEntries, + ref uint resumeHandle); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/NtQueryInformationProcess.cs b/src/System.Management.Automation/engine/Interop/Windows/NtQueryInformationProcess.cs new file mode 100644 index 0000000000..1a83952973 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/NtQueryInformationProcess.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [StructLayout(LayoutKind.Sequential)] + internal struct PROCESS_BASIC_INFORMATION + { + public nint ExitStatus; + public nint PebBaseAddress; + public nint AffinityMask; + public nint BasePriority; + public nint UniqueProcessId; + public nint InheritedFromUniqueProcessId; + } + + [LibraryImport("ntdll.dll")] + internal static partial int NtQueryInformationProcess( + nint processHandle, + int processInformationClass, + out PROCESS_BASIC_INFORMATION processInformation, + int processInformationLength, + out int returnLength); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/QueryDosDevice.cs b/src/System.Management.Automation/engine/Interop/Windows/QueryDosDevice.cs index 670c6254cf..419a4ef127 100644 --- a/src/System.Management.Automation/engine/Interop/Windows/QueryDosDevice.cs +++ b/src/System.Management.Automation/engine/Interop/Windows/QueryDosDevice.cs @@ -3,7 +3,6 @@ #nullable enable -#if !UNIX using System; using System.Buffers; using System.ComponentModel; @@ -123,4 +122,3 @@ internal static partial class Interop } } } -#endif diff --git a/src/System.Management.Automation/engine/Interop/Windows/RtlQueryProcessPlaceholderCompatibilityMode.cs b/src/System.Management.Automation/engine/Interop/Windows/RtlQueryProcessPlaceholderCompatibilityMode.cs new file mode 100644 index 0000000000..9e82f2c66c --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/RtlQueryProcessPlaceholderCompatibilityMode.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + internal const sbyte PHCM_APPLICATION_DEFAULT = 0; + internal const sbyte PHCM_DISGUISE_PLACEHOLDER = 1; + internal const sbyte PHCM_EXPOSE_PLACEHOLDERS = 2; + internal const sbyte PHCM_MAX = 2; + internal const sbyte PHCM_ERROR_INVALID_PARAMETER = -1; + internal const sbyte PHCM_ERROR_NO_TEB = -2; + + [LibraryImport("ntdll.dll")] + internal static partial sbyte RtlQueryProcessPlaceholderCompatibilityMode(); + + [LibraryImport("ntdll.dll")] + internal static partial sbyte RtlSetProcessPlaceholderCompatibilityMode(sbyte pcm); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/SHGetFileInfo.cs b/src/System.Management.Automation/engine/Interop/Windows/SHGetFileInfo.cs index 5843a1c639..a6deaa39c4 100644 --- a/src/System.Management.Automation/engine/Interop/Windows/SHGetFileInfo.cs +++ b/src/System.Management.Automation/engine/Interop/Windows/SHGetFileInfo.cs @@ -3,7 +3,6 @@ #nullable enable -#if !UNIX using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; @@ -37,4 +36,3 @@ internal static partial class Interop } } } -#endif diff --git a/src/System.Management.Automation/engine/Interop/Windows/SetForegroundWindow.cs b/src/System.Management.Automation/engine/Interop/Windows/SetForegroundWindow.cs new file mode 100644 index 0000000000..5945fac960 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/SetForegroundWindow.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetForegroundWindow(nint hWnd); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/ShowWindow.cs b/src/System.Management.Automation/engine/Interop/Windows/ShowWindow.cs new file mode 100644 index 0000000000..d33b0a0e24 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/ShowWindow.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + internal const int SW_HIDE = 0; + internal const int SW_SHOWNORMAL = 1; + internal const int SW_NORMAL = 1; + internal const int SW_SHOWMINIMIZED = 2; + internal const int SW_SHOWMAXIMIZED = 3; + internal const int SW_MAXIMIZE = 3; + internal const int SW_SHOWNOACTIVATE = 4; + internal const int SW_SHOW = 5; + internal const int SW_MINIMIZE = 6; + internal const int SW_SHOWMINNOACTIVE = 7; + internal const int SW_SHOWNA = 8; + internal const int SW_RESTORE = 9; + internal const int SW_SHOWDEFAULT = 10; + internal const int SW_FORCEMINIMIZE = 11; + internal const int SW_MAX = 11; + + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool ShowWindow(nint hWnd, int nCmdShow); + } +} diff --git a/src/System.Management.Automation/engine/Interop/Windows/VariantClear.cs b/src/System.Management.Automation/engine/Interop/Windows/VariantClear.cs index a3c0ce70d8..414a0912c8 100644 --- a/src/System.Management.Automation/engine/Interop/Windows/VariantClear.cs +++ b/src/System.Management.Automation/engine/Interop/Windows/VariantClear.cs @@ -3,7 +3,6 @@ #nullable enable -#if !UNIX using System.Runtime.InteropServices; internal static partial class Interop @@ -14,4 +13,3 @@ internal static partial class Interop internal static partial void VariantClear(nint pVariant); } } -#endif diff --git a/src/System.Management.Automation/engine/Interop/Windows/WNetCancelConnection2.cs b/src/System.Management.Automation/engine/Interop/Windows/WNetCancelConnection2.cs new file mode 100644 index 0000000000..841fdc7f12 --- /dev/null +++ b/src/System.Management.Automation/engine/Interop/Windows/WNetCancelConnection2.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static unsafe partial class Windows + { + [LibraryImport("mpr.dll", EntryPoint = "WNetCancelConnection2W", StringMarshalling = StringMarshalling.Utf16)] + internal static partial int WNetCancelConnection2(string driveName, int flags, [MarshalAs(UnmanagedType.Bool)] bool force); + } +} diff --git a/src/System.Management.Automation/engine/NativeCommandProcessor.cs b/src/System.Management.Automation/engine/NativeCommandProcessor.cs index 1c43f421a9..ecf5e79de1 100644 --- a/src/System.Management.Automation/engine/NativeCommandProcessor.cs +++ b/src/System.Management.Automation/engine/NativeCommandProcessor.cs @@ -2078,66 +2078,13 @@ namespace System.Management.Automation /// Static class that allows you to show and hide the console window /// associated with this process. /// - internal static partial class ConsoleVisibility + internal static class ConsoleVisibility { /// /// If set to true, then native commands will always be run redirected... /// public static bool AlwaysCaptureApplicationIO { get; set; } - [LibraryImport("Kernel32.dll")] - internal static partial IntPtr GetConsoleWindow(); - - internal const int SW_HIDE = 0; - internal const int SW_SHOWNORMAL = 1; - internal const int SW_NORMAL = 1; - internal const int SW_SHOWMINIMIZED = 2; - internal const int SW_SHOWMAXIMIZED = 3; - internal const int SW_MAXIMIZE = 3; - internal const int SW_SHOWNOACTIVATE = 4; - internal const int SW_SHOW = 5; - internal const int SW_MINIMIZE = 6; - internal const int SW_SHOWMINNOACTIVE = 7; - internal const int SW_SHOWNA = 8; - internal const int SW_RESTORE = 9; - internal const int SW_SHOWDEFAULT = 10; - internal const int SW_FORCEMINIMIZE = 11; - internal const int SW_MAX = 11; - - /// - /// Code to control the display properties of the a window... - /// - /// The window to show... - /// The command to do. - /// True if it was successful. - [LibraryImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool ShowWindow(IntPtr hWnd, int nCmdShow); - - /// - /// Code to allocate a console... - /// - /// True if a console was created... - [LibraryImport("kernel32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool AllocConsole(); - - /// - /// Called to save the foreground window before allocating a hidden console window. - /// - /// A handle to the foreground window. - [LibraryImport("user32.dll")] - private static partial IntPtr GetForegroundWindow(); - - /// - /// Called to restore the foreground window after allocating a hidden console window. - /// - /// A handle to the window that should be activated and brought to the foreground. - /// True if the window was brought to the foreground. - [LibraryImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool SetForegroundWindow(IntPtr hWnd); - /// /// If no console window is attached to this process, then allocate one, /// hide it and return true. If there's already a console window attached, then @@ -2146,77 +2093,44 @@ namespace System.Management.Automation /// internal static bool AllocateHiddenConsole() { +#if UNIX + return false; +#else // See if there is already a console attached. - IntPtr hwnd = ConsoleVisibility.GetConsoleWindow(); - if (hwnd != IntPtr.Zero) + IntPtr hwnd = Interop.Windows.GetConsoleWindow(); + if (hwnd != nint.Zero) { return false; } // save the foreground window since allocating a console window might remove focus from it - IntPtr savedForeground = ConsoleVisibility.GetForegroundWindow(); + IntPtr savedForeground = Interop.Windows.GetForegroundWindow(); // Since there is no console window, allocate and then hide it... // Suppress the PreFAST warning about not using Marshal.GetLastWin32Error() to // get the error code. -#pragma warning disable 56523 - ConsoleVisibility.AllocConsole(); - hwnd = ConsoleVisibility.GetConsoleWindow(); + Interop.Windows.AllocConsole(); + hwnd = Interop.Windows.GetConsoleWindow(); bool returnValue; - if (hwnd == IntPtr.Zero) + if (hwnd == nint.Zero) { returnValue = false; } else { returnValue = true; - ConsoleVisibility.ShowWindow(hwnd, ConsoleVisibility.SW_HIDE); + Interop.Windows.ShowWindow(hwnd, Interop.Windows.SW_HIDE); AlwaysCaptureApplicationIO = true; } - if (savedForeground != IntPtr.Zero && ConsoleVisibility.GetForegroundWindow() != savedForeground) + if (savedForeground != nint.Zero && Interop.Windows.GetForegroundWindow() != savedForeground) { - ConsoleVisibility.SetForegroundWindow(savedForeground); + Interop.Windows.SetForegroundWindow(savedForeground); } return returnValue; - } - - /// - /// If there is a console attached, then make it visible - /// and allow interactive console applications to be run. - /// - public static void Show() - { - IntPtr hwnd = GetConsoleWindow(); - if (hwnd != IntPtr.Zero) - { - ShowWindow(hwnd, SW_SHOW); - AlwaysCaptureApplicationIO = false; - } - else - { - throw PSTraceSource.NewInvalidOperationException(); - } - } - - /// - /// If there is a console attached, then hide it and always capture - /// output from the child process. - /// - public static void Hide() - { - IntPtr hwnd = GetConsoleWindow(); - if (hwnd != IntPtr.Zero) - { - ShowWindow(hwnd, SW_HIDE); - AlwaysCaptureApplicationIO = true; - } - else - { - throw PSTraceSource.NewInvalidOperationException(); - } +#endif } } diff --git a/src/System.Management.Automation/engine/ProcessCodeMethods.cs b/src/System.Management.Automation/engine/ProcessCodeMethods.cs index c54d992989..68d47fbec7 100644 --- a/src/System.Management.Automation/engine/ProcessCodeMethods.cs +++ b/src/System.Management.Automation/engine/ProcessCodeMethods.cs @@ -11,7 +11,7 @@ namespace Microsoft.PowerShell /// /// Helper functions for process info. /// - public static partial class ProcessCodeMethods + public static class ProcessCodeMethods { private const int InvalidProcessId = -1; @@ -61,32 +61,12 @@ namespace Microsoft.PowerShell internal static int GetParentPid(Process process) { Diagnostics.Assert(process != null, "Ensure process is not null before calling"); - PROCESS_BASIC_INFORMATION pbi; + Interop.Windows.PROCESS_BASIC_INFORMATION pbi; int size; - var res = NtQueryInformationProcess(process.Handle, 0, out pbi, Marshal.SizeOf(), out size); + var res = Interop.Windows.NtQueryInformationProcess(process.Handle, 0, out pbi, Marshal.SizeOf(), out size); return res != 0 ? InvalidProcessId : pbi.InheritedFromUniqueProcessId.ToInt32(); } - - [StructLayout(LayoutKind.Sequential)] - private struct PROCESS_BASIC_INFORMATION - { - public IntPtr ExitStatus; - public IntPtr PebBaseAddress; - public IntPtr AffinityMask; - public IntPtr BasePriority; - public IntPtr UniqueProcessId; - public IntPtr InheritedFromUniqueProcessId; - } - - [LibraryImport("ntdll.dll")] - private static partial int NtQueryInformationProcess( - IntPtr processHandle, - int processInformationClass, - out PROCESS_BASIC_INFORMATION processInformation, - int processInformationLength, - out int returnLength); #endif - } } diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index e13ac80fa1..6b18e44b88 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -474,9 +474,9 @@ namespace Microsoft.PowerShell.Commands if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134, 0)) { // let's be safe, don't change the PlaceHolderCompatibilityMode if the current one is not what we expect - if (NativeMethods.RtlQueryProcessPlaceholderCompatibilityMode() == NativeMethods.PHCM_DISGUISE_PLACEHOLDER) + if (Interop.Windows.RtlQueryProcessPlaceholderCompatibilityMode() == Interop.Windows.PHCM_DISGUISE_PLACEHOLDER) { - NativeMethods.RtlSetProcessPlaceholderCompatibilityMode(NativeMethods.PHCM_EXPOSE_PLACEHOLDERS); + Interop.Windows.RtlSetProcessPlaceholderCompatibilityMode(Interop.Windows.PHCM_EXPOSE_PLACEHOLDERS); } } #endif @@ -725,12 +725,6 @@ namespace Microsoft.PowerShell.Commands #if UNIX return drive; #else - return WinRemoveDrive(drive); -#endif - } - - private PSDriveInfo WinRemoveDrive(PSDriveInfo drive) - { if (IsNetworkMappedDrive(drive)) { const int CONNECT_UPDATE_PROFILE = 0x00000001; @@ -758,7 +752,7 @@ namespace Microsoft.PowerShell.Commands { try { - code = NativeMethods.WNetCancelConnection2(driveName, flags, true); + code = Interop.Windows.WNetCancelConnection2(driveName, flags, true); } catch (System.DllNotFoundException) { @@ -774,6 +768,7 @@ namespace Microsoft.PowerShell.Commands } return drive; +#endif } /// @@ -2446,7 +2441,7 @@ namespace Microsoft.PowerShell.Commands #if UNIX success = Platform.NonWindowsCreateHardLink(path, strTargetPath); #else - success = WinCreateHardLink(path, strTargetPath); + success = Interop.Windows.CreateHardLink(path, strTargetPath, IntPtr.Zero); #endif } @@ -2649,25 +2644,21 @@ namespace Microsoft.PowerShell.Commands } } +#if !UNIX private static bool WinCreateSymbolicLink(string path, string strTargetPath, bool isDirectory) { // The new AllowUnprivilegedCreate is only available on Win10 build 14972 or newer - var flags = isDirectory ? NativeMethods.SymbolicLinkFlags.Directory : NativeMethods.SymbolicLinkFlags.File; + var flags = isDirectory ? Interop.Windows.SymbolicLinkFlags.Directory : Interop.Windows.SymbolicLinkFlags.File; if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 14972, 0)) { - flags |= NativeMethods.SymbolicLinkFlags.AllowUnprivilegedCreate; + flags |= Interop.Windows.SymbolicLinkFlags.AllowUnprivilegedCreate; } - var created = NativeMethods.CreateSymbolicLink(path, strTargetPath, flags); + var created = Interop.Windows.CreateSymbolicLink(path, strTargetPath, flags); return created; } - - private static bool WinCreateHardLink(string path, string strTargetPath) - { - bool success = NativeMethods.CreateHardLink(path, strTargetPath, IntPtr.Zero); - return success; - } +#endif private static bool WinCreateJunction(string path, string strTargetPath) { @@ -7114,27 +7105,6 @@ namespace Microsoft.PowerShell.Commands [DllImport("mpr.dll", CharSet = CharSet.Unicode)] internal static extern int WNetAddConnection2(ref NetResource netResource, byte[] password, string username, int flags); - /// - /// WNetCancelConnection2 function cancels an existing network connection. - /// - /// - /// PSDrive Name. - /// - /// - /// Connection Type. - /// - /// - /// Specifies whether the disconnection should occur if there are open files or jobs - /// on the connection. If this parameter is FALSE, the function fails - /// if there are open files or jobs. - /// - /// If connection is removed then success is returned or - /// else the error code describing the type of failure that occurred while - /// trying to remove the connection is returned. - /// - [LibraryImport("mpr.dll", EntryPoint ="WNetCancelConnection2W", StringMarshalling = StringMarshalling.Utf16)] - internal static partial int WNetCancelConnection2(string driveName, int flags, [MarshalAs(UnmanagedType.Bool)] bool force); - /// /// WNetGetConnection function retrieves the name of the network resource associated with a local device. /// @@ -7228,75 +7198,6 @@ namespace Microsoft.PowerShell.Commands [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool PathIsNetworkPath(string path); #endif - - /// - /// Creates a symbolic link using the native API. - /// - /// Path of the symbolic link. - /// Path of the target of the symbolic link. - /// Flag values from SymbolicLinkFlags enum. - /// 1 on successful creation. - [LibraryImport(PinvokeDllNames.CreateSymbolicLinkDllName, EntryPoint = "CreateSymbolicLinkW", StringMarshalling = StringMarshalling.Utf16)] - [return: MarshalAs(UnmanagedType.I1)] - internal static partial bool CreateSymbolicLink(string name, string destination, SymbolicLinkFlags symbolicLinkFlags); - - /// - /// Flags used when creating a symbolic link. - /// - [Flags] - internal enum SymbolicLinkFlags - { - /// - /// Symbolic link is a file. - /// - File = 0, - - /// - /// Symbolic link is a directory. - /// - Directory = 1, - - /// - /// Allow creation of symbolic link without elevation. Requires Developer mode. - /// - AllowUnprivilegedCreate = 2, - } - - /// - /// Creates a hard link using the native API. - /// - /// Name of the hard link. - /// Path to the target of the hard link. - /// - /// - [LibraryImport(PinvokeDllNames.CreateHardLinkDllName, EntryPoint = "CreateHardLinkW", StringMarshalling = StringMarshalling.Utf16)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool CreateHardLink(string name, string existingFileName, IntPtr SecurityAttributes); - - // OneDrive placeholder support -#if !UNIX - /// - /// Returns the placeholder compatibility mode for the current process. - /// - /// The process's placeholder compatibily mode (PHCM_xxx), or a negative value on error (PCHM_ERROR_xxx). - [LibraryImport("ntdll.dll")] - internal static partial sbyte RtlQueryProcessPlaceholderCompatibilityMode(); - - /// - /// Sets the placeholder compatibility mode for the current process. - /// - /// The placeholder compatibility mode to set. - /// The process's previous placeholder compatibily mode (PHCM_xxx), or a negative value on error (PCHM_ERROR_xxx). - [LibraryImport("ntdll.dll")] - internal static partial sbyte RtlSetProcessPlaceholderCompatibilityMode(sbyte pcm); - - internal const sbyte PHCM_APPLICATION_DEFAULT = 0; - internal const sbyte PHCM_DISGUISE_PLACEHOLDER = 1; - internal const sbyte PHCM_EXPOSE_PLACEHOLDERS = 2; - internal const sbyte PHCM_MAX = 2; - internal const sbyte PHCM_ERROR_INVALID_PARAMETER = -1; - internal const sbyte PHCM_ERROR_NO_TEB = -2; -#endif } /// @@ -7963,40 +7864,6 @@ namespace Microsoft.PowerShell.Commands FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile); - internal sealed partial class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid - { - private SafeFindHandle() : base(true) { } - - protected override bool ReleaseHandle() - { - return FindClose(this.handle); - } - - [LibraryImport(PinvokeDllNames.FindCloseDllName)] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool FindClose(IntPtr handle); - } - - // We use 'FindFirstFileW' instead of 'FindFirstFileExW' because the latter doesn't work correctly with Unicode file names on FAT32. - // See https://github.com/PowerShell/PowerShell/issues/16804 - [LibraryImport(PinvokeDllNames.FindFirstFileDllName, EntryPoint = "FindFirstFileW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] - private static partial SafeFindHandle FindFirstFile(string lpFileName, ref WIN32_FIND_DATA lpFindFileData); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal unsafe struct WIN32_FIND_DATA - { - internal uint dwFileAttributes; - internal FILE_TIME ftCreationTime; - internal FILE_TIME ftLastAccessTime; - internal FILE_TIME ftLastWriteTime; - internal uint nFileSizeHigh; - internal uint nFileSizeLow; - internal uint dwReserved0; - internal uint dwReserved1; - internal fixed char cFileName[MAX_PATH]; - internal fixed char cAlternateFileName[14]; - } - /// /// Gets the target of the specified reparse point. /// @@ -8162,14 +8029,14 @@ namespace Microsoft.PowerShell.Commands return !InternalTestHooks.OneDriveTestRecurseOn; } - WIN32_FIND_DATA data = default; + Interop.Windows.WIN32_FIND_DATA data = default; string fullPath = Path.TrimEndingDirectorySeparator(fileInfo.FullName); if (fullPath.Length >= MAX_PATH) { fullPath = PathUtils.EnsureExtendedPrefix(fullPath); } - using (SafeFindHandle handle = FindFirstFile(fullPath, ref data)) + using (Interop.Windows.SafeFindHandle handle = Interop.Windows.FindFirstFile(fullPath, ref data)) { if (handle.IsInvalid) { diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs index 0bccb456e6..cbd10e6c83 100644 --- a/src/System.Management.Automation/utils/ClrFacade.cs +++ b/src/System.Management.Automation/utils/ClrFacade.cs @@ -7,7 +7,6 @@ using System.IO; using System.Management.Automation.Internal; using System.Management.Automation.Language; using System.Reflection; -using System.Runtime.InteropServices; using System.Runtime.Loader; using System.Security; using System.Text; @@ -19,7 +18,7 @@ namespace System.Management.Automation /// ClrFacade contains all diverging code (different implementation for FullCLR and CoreCLR using if/def). /// It exposes common APIs that can be used by the rest of the code base. /// - internal static partial class ClrFacade + internal static class ClrFacade { /// /// Initialize powershell AssemblyLoadContext and register the 'Resolving' event, if it's not done already. @@ -113,7 +112,7 @@ namespace System.Management.Automation #if UNIX s_oemEncoding = new UTF8Encoding(false); #else - uint oemCp = NativeMethods.GetOEMCP(); + uint oemCp = Interop.Windows.GetOEMCP(); s_oemEncoding = Encoding.GetEncoding((int)oemCp); #endif } @@ -362,17 +361,5 @@ namespace System.Management.Automation } #endregion Misc - - /// - /// Native methods that are used by facade methods. - /// - private static partial class NativeMethods - { - /// - /// Pinvoke for GetOEMCP to get the OEM code page. - /// - [LibraryImport(PinvokeDllNames.GetOEMCPDllName)] - internal static partial uint GetOEMCP(); - } } }