diff --git a/PInvoke/WslApi/Vanara.PInvoke.WslApi.csproj b/PInvoke/WslApi/Vanara.PInvoke.WslApi.csproj new file mode 100644 index 00000000..f001b970 --- /dev/null +++ b/PInvoke/WslApi/Vanara.PInvoke.WslApi.csproj @@ -0,0 +1,18 @@ + + + + wslapi.dll + + + PInvoke API (methods, structures and constants) imported from Windows Subsystem for Linux. + Vanara.PInvoke.WslApi + $(AssemblyName) + $(AssemblyName) + pinvoke;vanara;net-extensions;interop;WslApi;wsl;windows subsystem for linux + + + + + + + \ No newline at end of file diff --git a/PInvoke/WslApi/WslApi.cs b/PInvoke/WslApi/WslApi.cs new file mode 100644 index 00000000..adff175e --- /dev/null +++ b/PInvoke/WslApi/WslApi.cs @@ -0,0 +1,175 @@ +namespace Vanara.PInvoke +{ + /// Items from the WslApi.dll. + public static partial class WslApi + { + private const string Lib_WslApi = "wslapi.dll"; + + /// + /// The WSL_DISTRIBUTION_FLAGS enumeration specifies the behavior of a distribution in the Windows Subsystem for Linux (WSL). + /// + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/ne-wslapi-wsl_distribution_flags typedef enum { + // WSL_DISTRIBUTION_FLAGS_NONE = 0x0, WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP = 0x1, WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH = 0x2, + // WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING = 0x4 } WSL_DISTRIBUTION_FLAGS; + [PInvokeData("wslapi.h", MSDNShortId = "NE:wslapi.WSL_DISTRIBUTION_FLAGS")] + [Flags] + public enum WSL_DISTRIBUTION_FLAGS + { + /// + /// Value: 0x0 + /// No flags are being supplied. + /// + WSL_DISTRIBUTION_FLAGS_NONE = 0x0, + + /// + /// Value: 0x1 + /// + /// Allow the distribution to interoperate with Windows processes (for example, the user can invoke "cmd.exe" or "notepad.exe" + /// from within a WSL session). + /// + /// + WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP = 0x1, + + /// + /// Value: 0x2 + /// Add the Windows %PATH% environment variable values to WSL sessions. + /// + WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH = 0x2, + + /// + /// Value: 0x4 + /// Automatically mount Windows drives inside of WSL sessions (for example, "C:" will be available under "/mnt/c"). + /// + WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING = 0x4, + + /// + WSL_DISTRIBUTION_FLAGS_VALID = WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP | WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH | WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING, + + /// + WSL_DISTRIBUTION_FLAGS_DEFAULT = WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP | WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH | WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING, + } + + /// Modifies the behavior of a distribution registered with the Windows Subsystem for Linux (WSL). + /// Unique name representing a distribution (for example, "Fabrikam.Distro.10.01"). + /// The Linux user ID to use when launching new WSL sessions for this distribution. + /// Flags specifying what behavior to use for this distribution. + /// Returns S_OK on success, or a failing HRESULT otherwise. + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wslconfiguredistribution HRESULT WslConfigureDistribution( + // PCWSTR distributionName, ULONG defaultUID, WSL_DISTRIBUTION_FLAGS wslDistributionFlags ); + [PInvokeData("wslapi.h", MSDNShortId = "NF:wslapi.WslConfigureDistribution")] + [DllImport(Lib_WslApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern HRESULT WslConfigureDistribution(string distributionName, uint defaultUID, WSL_DISTRIBUTION_FLAGS wslDistributionFlags); + + /// Retrieves the current configuration of a distribution registered with the Windows Subsystem for Linux (WSL). + /// Unique name representing a distribution (for example, "Fabrikam.Distro.10.01"). + /// The version of WSL for which this distribution is configured. + /// The default user ID used when launching new WSL sessions for this distribution. + /// The flags governing the behavior of this distribution. + /// + /// The address of a pointer to an array of default environment variable strings used when launching new WSL sessions for this distribution. + /// + /// The number of elements in pDefaultEnvironmentVariablesArray. + /// Returns S_OK on success, or a failing HRESULT otherwise. + /// + /// The caller is responsible for freeing each string in pDefaultEnvironmentVariablesArray (and the array itself) via CoTaskMemFree. + /// + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wslgetdistributionconfiguration HRESULT + // WslGetDistributionConfiguration( [in] PCWSTR distributionName, [out] ULONG *distributionVersion, [out] ULONG *defaultUID, [out] + // WSL_DISTRIBUTION_FLAGS *wslDistributionFlags, [out] PSTR **defaultEnvironmentVariables, [out] ULONG + // *defaultEnvironmentVariableCount ); + [PInvokeData("wslapi.h", MSDNShortId = "NF:wslapi.WslGetDistributionConfiguration")] + [DllImport(Lib_WslApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern HRESULT WslGetDistributionConfiguration(string distributionName, out uint distributionVersion, out uint defaultUID, + out WSL_DISTRIBUTION_FLAGS wslDistributionFlags, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 5)] out string[] defaultEnvironmentVariables, + out uint defaultEnvironmentVariableCount); + + /// Determines if a distribution is registered with the Windows Subsystem for Linux (WSL). + /// Unique name representing a distribution (for example, "Fabrikam.Distro.10.01"). + /// Returns TRUE if the supplied distribution is currently registered, or FALSE otherwise. + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wslisdistributionregistered BOOL WslIsDistributionRegistered( + // PCWSTR distributionName ); + [PInvokeData("wslapi.h", MSDNShortId = "NF:wslapi.WslIsDistributionRegistered")] + [DllImport(Lib_WslApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool WslIsDistributionRegistered(string distributionName); + + /// Launches a Windows Subsystem for Linux (WSL) process in the context of a particular distribution. + /// Unique name representing a distribution (for example, "Fabrikam.Distro.10.01"). + /// Command to execute. If no command is supplied, launches the default shell. + /// + /// Governs whether or not the launched process should inherit the calling process's working directory. If FALSE, the process is + /// started in the WSL default user's home directory ("~"). + /// + /// Handle to use for STDIN. + /// Handle to use for STDOUT. + /// Handle to use for STDERR. + /// Pointer to address to receive the process HANDLE associated with the newly-launched WSL process. + /// Returns S_OK on success, or a failing HRESULT otherwise. + /// Caller is responsible for calling CloseHandle on the value returned in phProcess on success. + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wsllaunch HRESULT WslLaunch( [in] PCWSTR distributionName, + // [in, optional] PCWSTR command, [in] BOOL useCurrentWorkingDirectory, [in] HANDLE stdIn, [in] HANDLE stdOut, [in] HANDLE stdErr, + // [out] HANDLE *process ); + [PInvokeData("wslapi.h", MSDNShortId = "NF:wslapi.WslLaunch")] + [DllImport(Lib_WslApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern HRESULT WslLaunch(string distributionName, [In, Optional] string? command, + [MarshalAs(UnmanagedType.Bool)] bool useCurrentWorkingDirectory, [In] HFILE stdIn, [In] HFILE stdOut, + [In] HFILE stdErr, out HPROCESS process); + + /// + /// Launches an interactive Windows Subsystem for Linux (WSL) process in the context of a particular distribution.This differs from + /// WslLaunch in that the end user will be able to interact with the newly-created process. + /// + /// Unique name representing a distribution (for example, "Fabrikam.Distro.10.01"). + /// Command to execute. If no command is supplied, launches the default shell. + /// + /// Governs whether or not the launched process should inherit the calling process's working directory. If FALSE, the process is + /// started in the WSL default user's home directory ("~"). + /// + /// Receives the exit code of the process after it exits. + /// Returns S_OK on success, or a failing HRESULT otherwise. + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wsllaunchinteractive HRESULT WslLaunchInteractive( [in] + // PCWSTR distributionName, [in, optional] PCWSTR command, [in] BOOL useCurrentWorkingDirectory, [out] DWORD *exitCode ); + [PInvokeData("wslapi.h", MSDNShortId = "NF:wslapi.WslLaunchInteractive")] + [DllImport(Lib_WslApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern HRESULT WslLaunchInteractive(string distributionName, [In, Optional] string? command, + [MarshalAs(UnmanagedType.Bool)] bool useCurrentWorkingDirectory, out uint exitCode); + + /// Registers a new distribution with the Windows Subsystem for Linux (WSL). + /// Unique name representing a distribution (for example, "Fabrikam.Distro.10.01"). + /// Full path to a .tar.gz file containing the file system of the distribution to register. + /// + /// + /// This function can return one of the following values. Use the SUCCEEDED and FAILED macros to test the return value of this function. + /// + /// + /// + /// Return Code + /// Description + /// + /// + /// S_OK + /// Distribution successfully registered with the Windows Subsystem for Linux. + /// + /// + /// HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) + /// Failed because a distribution with this name has already been registered. + /// + /// + /// + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wslregisterdistribution HRESULT WslRegisterDistribution( [in] + // PCWSTR distributionName, [in] PCWSTR tarGzFilename ); + [PInvokeData("wslapi.h", MSDNShortId = "NF:wslapi.WslRegisterDistribution")] + [DllImport(Lib_WslApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern HRESULT WslRegisterDistribution(string distributionName, string tarGzFilename); + + /// Unregisters a distribution from the Windows Subsystem for Linux (WSL). + /// Unique name representing a distribution (for example, "Fabrikam.Distro.10.01"). + /// Returns S_OK on success, or a failing HRESULT otherwise. + // https://learn.microsoft.com/en-us/windows/win32/api/wslapi/nf-wslapi-wslunregisterdistribution HRESULT WslUnregisterDistribution( + // [in] PCWSTR distributionName ); + [PInvokeData("wslapi.h", MSDNShortId = "NF:wslapi.WslUnregisterDistribution")] + [DllImport(Lib_WslApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern HRESULT WslUnregisterDistribution(string distributionName); + } +} \ No newline at end of file diff --git a/Vanara.sln b/Vanara.sln index 44671903..786b7868 100644 --- a/Vanara.sln +++ b/Vanara.sln @@ -439,6 +439,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Odbc32", "UnitTests\PInvoke EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.OleDb", "PInvoke\OleDb\Vanara.PInvoke.OleDb.csproj", "{2DCB4898-C95C-4529-9655-E087171B44DC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.WslApi", "PInvoke\WslApi\Vanara.PInvoke.WslApi.csproj", "{9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -3849,6 +3851,24 @@ Global {2DCB4898-C95C-4529-9655-E087171B44DC}.Release|x64.Build.0 = Release|x64 {2DCB4898-C95C-4529-9655-E087171B44DC}.Release|x86.ActiveCfg = Release|x86 {2DCB4898-C95C-4529-9655-E087171B44DC}.Release|x86.Build.0 = Release|x86 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Debug|x64.ActiveCfg = Debug|x64 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Debug|x64.Build.0 = Debug|x64 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Debug|x86.ActiveCfg = Debug|x86 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Debug|x86.Build.0 = Debug|x86 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.DebugNoTests|Any CPU.ActiveCfg = Debug|Any CPU + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.DebugNoTests|Any CPU.Build.0 = Debug|Any CPU + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.DebugNoTests|x64.ActiveCfg = Debug|x64 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.DebugNoTests|x64.Build.0 = Debug|x64 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.DebugNoTests|x86.ActiveCfg = Debug|x86 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.DebugNoTests|x86.Build.0 = Debug|x86 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Release|Any CPU.Build.0 = Release|Any CPU + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Release|x64.ActiveCfg = Release|x64 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Release|x64.Build.0 = Release|x64 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Release|x86.ActiveCfg = Release|x86 + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4046,6 +4066,7 @@ Global {ED1BF632-4ACD-4B6B-9F27-C6DE86E00D37} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} {94724746-9D66-45E5-8EF1-419E29C6DF12} = {385CAD2D-0A5E-4F80-927B-D5499D126B90} {2DCB4898-C95C-4529-9655-E087171B44DC} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} + {9E2D6D4B-69D0-46A0-A18A-186E3FA269BD} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {543FAC75-2AF1-4EF1-9609-B242B63FEED4}