Vanara/PInvoke/Kernel32/WinBase.Lib.cs

305 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class Kernel32
{
/// <summary>Retrieves the application-specific portion of the search path used to locate DLLs for the application.</summary>
/// <param name="nBufferLength">The size of the output buffer, in characters.</param>
/// <param name="lpBuffer">A pointer to a buffer that receives the application-specific portion of the search path.</param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is the length of the string copied to lpBuffer, in characters, not including the
/// terminating null character. If the return value is greater than nBufferLength, it specifies the size of the buffer required for
/// the path.
/// </para>
/// <para>If the function fails, the return value is zero. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
// DWORD WINAPI GetDllDirectory( _In_ DWORD nBufferLength, _Out_ LPTSTR lpBuffer); https://msdn.microsoft.com/en-us/library/windows/desktop/ms683186(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("WinBase.h", MSDNShortId = "ms683186")]
public static extern uint GetDllDirectory(uint nBufferLength, StringBuilder lpBuffer);
/// <summary>Retrieves the application-specific portion of the search path used to locate DLLs for the application.</summary>
/// <returns>The application-specific portion of the search path.</returns>
public static string GetDllDirectory() => FunctionHelper.CallMethodWithStrBuf((StringBuilder sb, ref uint sz) => GetDllDirectory(sz, sb), out var str, (sz, r) => r <= sz) > 0 ? str : throw Win32Error.GetLastError().GetException();
/// <summary>
/// <para>Loads and executes an application or creates a new instance of an existing application.</para>
/// <para>
/// <c>Note</c> This function is provided only for compatibility with 16-bit versions of Windows. Applications should use the
/// CreateProcess function.
/// </para>
/// </summary>
/// <param name="lpModuleName"><para>
/// The file name of the application to be run. When specifying a path, be sure to use backslashes (), not forward slashes (/). If
/// the lpModuleName parameter does not contain a directory path, the system searches for the executable file in this order:
/// </para>
/// <list type="number">
/// <item>
/// <term>The directory from which the application loaded.</term>
/// </item>
/// <item>
/// <term>The current directory.</term>
/// </item>
/// <item>
/// <term>The system directory. Use the GetSystemDirectory function to get the path of this directory.</term>
/// </item>
/// <item>
/// <term>
/// The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. The name of this
/// directory is System.
/// </term>
/// </item>
/// <item>
/// <term>The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.</term>
/// </item>
/// <item>
/// <term>The directories that are listed in the PATH environment variable.</term>
/// </item>
/// </list></param>
/// <param name="lpParameterBlock"><para>A pointer to an application-defined <c>LOADPARMS32</c> structure that defines the new application's parameter block.</para>
/// <para>
/// Set all unused members to NULL, except for <c>lpCmdLine</c>, which must point to a null-terminated string if it is not used. For
/// more information, see Remarks.
/// </para></param>
/// <returns>
/// <para>If the function succeeds, the return value is greater than 31.</para>
/// <para>If the function fails, the return value is an error value, which may be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>0</term>
/// <term>The system is out of memory or resources.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_FORMAT 11L</term>
/// <term>The .exe file is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_FILE_NOT_FOUND 2L</term>
/// <term>The specified file was not found.</term>
/// </item>
/// <item>
/// <term>ERROR_PATH_NOT_FOUND 3L</term>
/// <term>The specified path was not found.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>The <c>LOADPARMS32</c> structure has the following form:</para>
/// <list type="table">
/// <listheader>
/// <term>Member</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>lpEnvAddress</term>
/// <term>
/// Pointer to an array of null-terminated strings that supply the environment strings for the new process. The array has a value of
/// NULL as its last entry. A value of NULL for this parameter causes the new process to start with the same environment as the
/// calling process.
/// </term>
/// </item>
/// <item>
/// <term>lpCmdLine</term>
/// <term>
/// Pointer to a Pascal-style string that contains a correctly formed command line. The first byte of the string contains the number
/// of bytes in the string. The remainder of the string contains the command line arguments, excluding the name of the child process.
/// If there are no command line arguments, this parameter must point to a zero length string; it cannot be NULL.
/// </term>
/// </item>
/// <item>
/// <term>lpCmdShow</term>
/// <term>
/// Pointer to a structure containing two WORD values. The first value must always be set to two. The second value specifies how the
/// application window is to be shown and is used to supply the wShowWindow member of the STARTUPINFO structure to the CreateProcess
/// function. See the description of the nCmdShow parameter of the ShowWindow function for a list of acceptable values.
/// </term>
/// </item>
/// <item>
/// <term>dwReserved</term>
/// <term>This parameter is reserved; it must be zero.</term>
/// </item>
/// </list>
/// <para>
/// Applications should use the CreateProcess function instead of <c>LoadModule</c>. The <c>LoadModule</c> function calls
/// CreateProcess by forming the parameters as follows.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>CreateProcess parameter</term>
/// <term>Argument used</term>
/// </listheader>
/// <item>
/// <term>lpszApplicationName</term>
/// <term>lpModuleName</term>
/// </item>
/// <item>
/// <term>lpszCommandLine</term>
/// <term>lpParameterBlock.lpCmdLine</term>
/// </item>
/// <item>
/// <term>lpProcessAttributes</term>
/// <term>NULL</term>
/// </item>
/// <item>
/// <term>lpThreadAttributes</term>
/// <term>NULL</term>
/// </item>
/// <item>
/// <term>bInheritHandles</term>
/// <term>FALSE</term>
/// </item>
/// <item>
/// <term>dwCreationFlags</term>
/// <term>0</term>
/// </item>
/// <item>
/// <term>lpEnvironment</term>
/// <term>lpParameterBlock.lpEnvAddress</term>
/// </item>
/// <item>
/// <term>lpCurrentDirectory</term>
/// <term>NULL</term>
/// </item>
/// <item>
/// <term>lpStartupInfo</term>
/// <term>
/// The structure is initialized to zero. The cb member is set to the size of the structure. The wShowWindow member is set to the
/// value of the second word of lpParameterBlock.lpCmdShow.
/// </term>
/// </item>
/// <item>
/// <term>lpProcessInformation.hProcess</term>
/// <term>The handle is immediately closed.</term>
/// </item>
/// <item>
/// <term>lpProcessInformation.hThread</term>
/// <term>The handle is immediately closed.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-loadmodule DWORD LoadModule( LPCSTR lpModuleName, LPVOID
// lpParameterBlock );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winbase.h", MSDNShortId = "80571b80-851a-4272-bfa6-d26e217e714a")]
public static extern uint LoadModule([MarshalAs(UnmanagedType.LPStr)] string lpModuleName, [In] LOADPARMS32 lpParameterBlock);
/// <summary>Adds a directory to the search path used to locate DLLs for the application.</summary>
/// <param name="lpPathName">
/// The directory to be added to the search path. If this parameter is an empty string (""), the call removes the current directory
/// from the default DLL search order. If this parameter is NULL, the function restores the default search order.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
// BOOL WINAPI SetDllDirectory( _In_opt_ LPCTSTR lpPathName); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686203(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("Winbase.h", MSDNShortId = "ms686203")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetDllDirectory(string lpPathName);
/// <summary>Defines the new application's parameter block.</summary>
[PInvokeData("winbase.h", MSDNShortId = "80571b80-851a-4272-bfa6-d26e217e714a")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class LOADPARMS32 : IDisposable
{
/// <summary>
/// Pointer to an array of null-terminated strings that supply the environment strings for the new process. The array has a value
/// of NULL as its last entry. A value of NULL for this parameter causes the new process to start with the same environment as
/// the calling process.
/// </summary>
private IntPtr lpEnvAddress;
/// <summary>
/// Pointer to a Pascal-style string that contains a correctly formed command line. The first byte of the string contains the
/// number of bytes in the string. The remainder of the string contains the command line arguments, excluding the name of the
/// child process. If there are no command line arguments, this parameter must point to a zero length string; it cannot be NULL.
/// </summary>
private IntPtr lpCmdLine;
/// <summary>
/// Pointer to a structure containing two WORD values. The first value must always be set to two. The second value specifies how
/// the application window is to be shown and is used to supply the wShowWindow member of the STARTUPINFO structure to the
/// CreateProcess function. See the description of the nCmdShow parameter of the ShowWindow function for a list of acceptable values.
/// </summary>
private IntPtr lpCmdShow;
/// <summary>This parameter is reserved; it must be zero.</summary>
private readonly uint dwReserved;
/// <summary>Initializes a new instance of the <see cref="LOADPARMS32"/> class.</summary>
public LOADPARMS32()
{
lpCmdShow = Marshal.AllocHGlobal(4);
Marshal.WriteInt16(lpCmdShow, 2);
lpCmdLine = StringHelper.AllocChars(1, Marshal.AllocHGlobal, CharSet.Ansi);
}
/// <summary>A string that contains a correctly formed command line, excluding the name of the child process.</summary>
public string CmdLine
{
get
{
var l = Marshal.ReadByte(lpCmdLine);
return l == 0 ? string.Empty : StringHelper.GetString(lpCmdLine.Offset(1), CharSet.Ansi, l);
}
set
{
Marshal.FreeHGlobal(lpCmdLine);
if (string.IsNullOrEmpty(value))
lpCmdLine = StringHelper.AllocChars(1, Marshal.AllocHGlobal, CharSet.Ansi);
else
{
lpCmdLine = Marshal.AllocHGlobal(value.Length + 1);
Marshal.WriteByte(lpCmdLine, (byte)value.Length);
StringHelper.Write(value, lpCmdLine.Offset(1), out _, false, CharSet.Ansi);
}
}
}
/// <summary>
/// Specifies how application window is to be shown and is used to supply the wShowWindow member of the STARTUPINFO structure to
/// the CreateProcess function.
/// </summary>
public ShowWindowCommand CmdShow
{
get => (ShowWindowCommand)Marshal.ReadInt16(lpCmdShow, 2);
set => Marshal.WriteInt16(lpCmdShow, 2, (short)value);
}
/// <summary>
/// A list of strings that supply the environment strings for the new process. A value of <see langword="null"/> for this
/// parameter causes the new process to start with the same environment as the calling process.
/// </summary>
public IEnumerable<string> EnvAddress
{
get => lpEnvAddress == IntPtr.Zero ? null : lpEnvAddress.ToStringEnum(CharSet.Ansi);
set
{
if (lpEnvAddress != IntPtr.Zero)
Marshal.FreeHGlobal(lpEnvAddress);
lpEnvAddress = value is null ? IntPtr.Zero : value.MarshalToPtr(StringListPackMethod.Concatenated, Marshal.AllocHGlobal, out _, CharSet.Ansi);
}
}
void IDisposable.Dispose()
{
Marshal.FreeHGlobal(lpEnvAddress);
Marshal.FreeHGlobal(lpCmdLine);
Marshal.FreeHGlobal(lpCmdShow);
lpEnvAddress = lpCmdLine = lpCmdShow = IntPtr.Zero;
}
}
}
}