Vanara/PInvoke/User32/WinUser.Desktop.cs

1185 lines
59 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class User32
{
/// <summary>
/// <para>An application-defined callback function used with the <c>EnumDesktops</c> function. It receives a desktop name.</para>
/// <para>
/// The DESKTOPENUMPROC type defines a pointer to this callback function. <c>EnumDesktopProc</c> is a placeholder for the
/// application-defined function name.
/// </para>
/// </summary>
/// <param name="lpszDesktop">The name of the desktop.</param>
/// <param name="lParam">An application-defined value specified in the <c>EnumDesktops</c> function.</param>
/// <returns>To continue enumeration, the callback function must return TRUE. To stop enumeration, it must return FALSE.</returns>
// BOOL CALLBACK EnumDesktopProc( _In_ LPTSTR lpszDesktop, _In_ LPARAM lParam); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682612(v=vs.85).aspx
[UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Auto)]
[PInvokeData("Winbase.h", MSDNShortId = "ms682612")]
[return: MarshalAs(UnmanagedType.Bool)]
public delegate bool EnumDesktopProc(string lpszDesktop, [In] IntPtr lParam);
/// <summary>
/// <para>
/// An application-defined callback function used with the <c>EnumWindowStations</c> function. It receives a window station name.
/// </para>
/// <para>
/// The <c>WINSTAENUMPROC</c> type defines a pointer to this callback function. <c>EnumWindowStationProc</c> is a placeholder for the
/// application-defined function name.
/// </para>
/// </summary>
/// <param name="lpszWindowStation">The name of the window station.</param>
/// <param name="lParam">An application-defined value specified in the <c>EnumWindowStations</c> function.</param>
/// <returns>To continue enumeration, the callback function must return TRUE. To stop enumeration, it must return FALSE.</returns>
// BOOL CALLBACK EnumWindowStationProc( _In_ LPTSTR lpszWindowStation, _In_ LPARAM lParam); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682643(v=vs.85).aspx
[UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Auto)]
[PInvokeData("Winuser.h", MSDNShortId = "ms682643")]
[return: MarshalAs(UnmanagedType.Bool)]
public delegate bool EnumWindowStationProc(string lpszWindowStation, [In] IntPtr lParam);
/// <summary>Flags used by CreateDesktop.</summary>
[Flags]
public enum CreateDesktopFlags
{
/// <summary>Enables processes running in other accounts on the desktop to set hooks in this process.</summary>
DF_ALLOWOTHERACCOUNTHOOK = 0x0001
}
/// <summary>Flags used by CreateWindowStation.</summary>
[Flags]
public enum CreateWindowStationFlags
{
/// <summary>
/// If used and the window station already exists, the call fails. If this flag is not specified and the window station already
/// exists, the function succeeds and returns a new handle to the existing window station.
/// </summary>
CWF_CREATE_ONLY = 0x00000001,
}
/// <summary>The information to be retrieved by GetUserObjectInformation or set by SetUserObjectInformation.</summary>
[PInvokeData("winuser.h", MSDNShortId = "64f7361d-1a94-4d5b-86f1-a2a21737668a")]
public enum UserObjectInformationType
{
/// <summary>The handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.</summary>
[CorrespondingType(typeof(USEROBJECTFLAGS))]
UOI_FLAGS = 1,
/// <summary>
/// The size of the desktop heap, in KB, as a ULONG value. The hObj parameter must be a handle to a desktop object, otherwise,
/// the function fails.
/// <para>Windows Server 2003 and Windows XP/2000: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(uint))]
UOI_HEAPSIZE = 5,
/// <summary>
/// TRUE if the hObj parameter is a handle to the desktop object that is receiving input from the user. FALSE otherwise.
/// <para>Windows Server 2003 and Windows XP/2000: This value is not supported.</para>
/// </summary>
[CorrespondingType(typeof(uint))]
UOI_IO = 6,
/// <summary>The name of the object, as a string.</summary>
[CorrespondingType(typeof(string))]
UOI_NAME = 2,
/// <summary>The type name of the object, as a string.</summary>
[CorrespondingType(typeof(string))]
UOI_TYPE = 3,
/// <summary>
/// The SID structure that identifies the user that is currently associated with the specified object. If no user is associated
/// with the object, the value returned in the buffer pointed to by lpnLengthNeeded is zero. Note that SID is a variable length
/// structure. You will usually make a call to GetUserObjectInformation to determine the length of the SID before retrieving its value.
/// </summary>
[CorrespondingType(typeof(IntPtr))]
UOI_USER_SID = 4,
}
/// <summary>
/// <para>Closes an open handle to a desktop object.</para>
/// </summary>
/// <param name="hDesktop">
/// <para>
/// A handle to the desktop to be closed. This can be a handle returned by the CreateDesktop, OpenDesktop, or OpenInputDesktop
/// functions. Do not specify the handle returned by the GetThreadDesktop function.
/// </para>
/// </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 GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>CloseDesktop</c> function will fail if any thread in the calling process is using the specified desktop handle or if the
/// handle refers to the initial desktop of the calling process.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-closedesktop BOOL CloseDesktop( HDESK hDesktop );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "861e57b2-061c-4598-ad38-6aef7b79ca54")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseDesktop(HDESK hDesktop);
/// <summary>
/// <para>Closes an open window station handle.</para>
/// </summary>
/// <param name="hWinSta">
/// <para>
/// A handle to the window station to be closed. This handle is returned by the CreateWindowStation or OpenWindowStation function. Do
/// not specify the handle returned by the GetProcessWindowStation function.
/// </para>
/// </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 GetLastError.</para>
/// <para><c>Windows Server 2003 and Windows XP/2000:</c> This function does not set the last error code on failure.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>CloseWindowStation</c> function will fail if the handle being closed is for the window station assigned to the calling process.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-closewindowstation BOOL CloseWindowStation( HWINSTA
// hWinSta );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "417cb01b-c206-4b5b-9516-94e5d90717f4")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseWindowStation(HWINSTA hWinSta);
/// <summary>
/// <para>
/// Creates a new desktop, associates it with the current window station of the calling process, and assigns it to the calling
/// thread. The calling process must have an associated window station, either assigned by the system at process creation time or set
/// by the SetProcessWindowStation function.
/// </para>
/// <para>To specify the size of the heap for the desktop, use the CreateDesktopEx function.</para>
/// </summary>
/// <param name="lpszDesktop">
/// <para>The name of the desktop to be created. Desktop names are case-insensitive and may not contain backslash characters ().</para>
/// </param>
/// <param name="lpszDevice">
/// <para>Reserved; must be <c>NULL</c>.</para>
/// </param>
/// <param name="pDevmode">
/// <para>Reserved; must be <c>NULL</c>.</para>
/// </param>
/// <param name="dwFlags">
/// <para>This parameter can be zero or the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>DF_ALLOWOTHERACCOUNTHOOK 0x0001</term>
/// <term>Enables processes running in other accounts on the desktop to set hooks in this process.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwDesiredAccess">
/// <para>The access to the desktop. For a list of values, see Desktop Security and Access Rights.</para>
/// <para>
/// This parameter must include the <c>DESKTOP_CREATEWINDOW</c> access right, because internally <c>CreateDesktop</c> uses the handle
/// to create a window.
/// </para>
/// </param>
/// <param name="lpsa">
/// <para>
/// A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If
/// lpsa is NULL, the handle cannot be inherited.
/// </para>
/// <para>
/// The <c>lpSecurityDescriptor</c> member of the structure specifies a security descriptor for the new desktop. If this parameter is
/// NULL, the desktop inherits its security descriptor from the parent window station.
/// </para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is a handle to the newly created desktop. If the specified desktop already exists, the
/// function succeeds and returns a handle to the existing desktop. When you are finished using the handle, call the CloseDesktop
/// function to close it.
/// </para>
/// <para>If the function fails, the return value is <c>NULL</c>. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// If the dwDesiredAccess parameter specifies the <c>READ_CONTROL</c>, <c>WRITE_DAC</c>, or <c>WRITE_OWNER</c> standard access
/// rights, you must also request the <c>DESKTOP_READOBJECTS</c> and <c>DESKTOP_WRITEOBJECTS</c> access rights.
/// </para>
/// <para>
/// The number of desktops that can be created is limited by the size of the system desktop heap, which is 48 MB. Desktop objects use
/// the heap to store resources. You can increase the number of desktops that can be created by reducing the default heap reserved
/// for each desktop in the interactive window station. This value is specified in the "SharedSection" substring of the following
/// registry value: <c>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\Windows</c>. The default data
/// for this registry value is as follows:
/// </para>
/// <para>
/// "%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows
/// ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2
/// ProfileControl=Off MaxRequestThreads=16"
/// </para>
/// <para>The values for the "SharedSection" substring are described as follows:</para>
/// <list type="bullet">
/// <item>
/// <term>The first "SharedSection" value is the size of the shared heap common to all desktops, in kilobytes.</term>
/// </item>
/// <item>
/// <term>
/// The second "SharedSection" value is the size of the desktop heap needed for each desktop that is created in the interactive
/// window station, WinSta0, in kilobytes.
/// </term>
/// </item>
/// <item>
/// <term>
/// The third "SharedSection" value is the size of the desktop heap needed for each desktop that is created in a noninteractive
/// window station, in kilobytes.
/// </term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createdesktopa HDESK CreateDesktopA( LPCSTR lpszDesktop,
// LPCSTR lpszDevice, DEVMODEA *pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "c6ed40c5-13a9-4697-a727-730adc6a912d")]
public static extern SafeHDESK CreateDesktop(string lpszDesktop, [Optional] string lpszDevice, [Optional] IntPtr pDevmode, CreateDesktopFlags dwFlags, ACCESS_MASK dwDesiredAccess, SECURITY_ATTRIBUTES lpsa);
/// <summary>
/// <para>
/// Creates a new desktop with the specified heap, associates it with the current window station of the calling process, and assigns
/// it to the calling thread. The calling process must have an associated window station, either assigned by the system at process
/// creation time or set by the SetProcessWindowStation function.
/// </para>
/// </summary>
/// <param name="lpszDesktop">
/// <para>The name of the desktop to be created. Desktop names are case-insensitive and may not contain backslash characters ().</para>
/// </param>
/// <param name="lpszDevice">
/// <para>This parameter is reserved and must be NULL.</para>
/// </param>
/// <param name="pDevmode">
/// <para>This parameter is reserved and must be NULL.</para>
/// </param>
/// <param name="dwFlags">
/// <para>This parameter can be zero or the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>DF_ALLOWOTHERACCOUNTHOOK 0x0001</term>
/// <term>Enables processes running in other accounts on the desktop to set hooks in this process.</term>
/// </item>
/// </list>
/// </param>
/// <param name="dwDesiredAccess">
/// <para>The requested access to the desktop. For a list of values, see Desktop Security and Access Rights.</para>
/// <para>
/// This parameter must include the DESKTOP_CREATEWINDOW access right, because internally CreateDesktop uses the handle to create a window.
/// </para>
/// </param>
/// <param name="lpsa">
/// <para>
/// A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If
/// lpsa is NULL, the handle cannot be inherited.
/// </para>
/// <para>
/// The <c>lpSecurityDescriptor</c> member of the structure specifies a security descriptor for the new desktop. If this parameter is
/// NULL, the desktop inherits its security descriptor from the parent window station.
/// </para>
/// </param>
/// <param name="ulHeapSize">
/// <para>The size of the desktop heap, in kilobytes.</para>
/// </param>
/// <param name="pvoid">
/// <para>This parameter is reserved and must be NULL.</para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is a handle to the newly created desktop. If the specified desktop already exists, the
/// function succeeds and returns a handle to the existing desktop. When you are finished using the handle, call the CloseDesktop
/// function to close it.
/// </para>
/// <para>If the function fails, the return value is NULL. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// If the dwDesiredAccess parameter specifies the READ_CONTROL, WRITE_DAC, or WRITE_OWNER standard access rights, you must also
/// request the DESKTOP_READOBJECTS and DESKTOP_WRITEOBJECTS access rights.
/// </para>
/// <para>
/// The number of desktops that can be created is limited by the size of the system desktop heap. Desktop objects use the heap to
/// store resources. You can increase the number of desktops that can be created by increasing the size of the desktop heap or by
/// reducing the default heap reserved for each desktop in the interactive window station. This value is specified in the
/// SharedSection substring of the following registry value: <c>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
/// Manager\SubSystems\Windows</c>. The default data for this registry value is as follows:
/// </para>
/// <para>
/// %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows
/// ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2
/// ProfileControl=Off MaxRequestThreads=16
/// </para>
/// <para>The values for the SharedSection substring are described as follows:</para>
/// <list type="bullet">
/// <item>
/// <term>The first SharedSection value is the size of the shared heap common to all desktops, in kilobytes.</term>
/// </item>
/// <item>
/// <term>
/// The second SharedSection value is the size of the desktop heap needed for each desktop that is created in the interactive window
/// station, WinSta0, in kilobytes.
/// </term>
/// </item>
/// <item>
/// <term>
/// The third SharedSection value is the size of the desktop heap needed for each desktop that is created in a noninteractive window
/// station, in kilobytes.
/// </term>
/// </item>
/// </list>
/// <para>
/// The default size of the desktop heap depends on factors such as hardware architecture. To retrieve the size of the desktop heap,
/// call the GetUserObjectInformation function with UOI_HEAPSIZE.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createdesktopexa HDESK CreateDesktopExA( LPCSTR
// lpszDesktop, LPCSTR lpszDevice, DEVMODEA *pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa, ULONG
// ulHeapSize, PVOID pvoid );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "2fe8859d-1fe3-4f44-aa97-58e61779c4cc")]
public static extern SafeHDESK CreateDesktopEx(string lpszDesktop, [Optional] string lpszDevice, [Optional] IntPtr pDevmode, CreateDesktopFlags dwFlags, ACCESS_MASK dwDesiredAccess, SECURITY_ATTRIBUTES lpsa, uint ulHeapSize, [Optional] IntPtr pvoid);
/// <summary>
/// <para>Creates a window station object, associates it with the calling process, and assigns it to the current session.</para>
/// </summary>
/// <param name="lpwinsta">
/// <para>
/// The name of the window station to be created. Window station names are case-insensitive and cannot contain backslash characters
/// (). Only members of the Administrators group are allowed to specify a name. If lpwinsta is <c>NULL</c> or an empty string, the
/// system forms a window station name using the logon session identifier for the calling process. To get this name, call the
/// GetUserObjectInformation function.
/// </para>
/// </param>
/// <param name="dwFlags">
/// <para>
/// If this parameter is <c>CWF_CREATE_ONLY</c> and the window station already exists, the call fails. If this flag is not specified
/// and the window station already exists, the function succeeds and returns a new handle to the existing window station.
/// </para>
/// <para><c>Windows XP/2000:</c> This parameter is reserved and must be zero.</para>
/// </param>
/// <param name="dwDesiredAccess">
/// <para>
/// The type of access the returned handle has to the window station. In addition, you can specify any of the standard access rights,
/// such as <c>READ_CONTROL</c> or <c>WRITE_DAC</c>, and a combination of the window station-specific access rights. For more
/// information, see Window Station Security and Access Rights.
/// </para>
/// </param>
/// <param name="lpsa">
/// <para>
/// A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If
/// lpsa is <c>NULL</c>, the handle cannot be inherited.
/// </para>
/// <para>
/// The <c>lpSecurityDescriptor</c> member of the structure specifies a security descriptor for the new window station. If lpsa is
/// <c>NULL</c>, the window station (and any desktops created within the window) gets a security descriptor that grants
/// <c>GENERIC_ALL</c> access to all users.
/// </para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is a handle to the newly created window station. If the specified window station
/// already exists, the function succeeds and returns a handle to the existing window station.
/// </para>
/// <para>If the function fails, the return value is <c>NULL</c>. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>After you are done with the handle, you must call CloseWindowStation to free the handle.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createwindowstationa HWINSTA CreateWindowStationA( LPCSTR
// lpwinsta, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "c1aee546-decd-46c9-8d02-d6792f5a6a0d")]
public static extern SafeHWINSTA CreateWindowStation(string lpwinsta, CreateWindowStationFlags dwFlags, ACCESS_MASK dwDesiredAccess, SECURITY_ATTRIBUTES lpsa);
/// <summary>
/// <para>
/// Enumerates all desktops associated with the specified window station of the calling process. The function passes the name of each
/// desktop, in turn, to an application-defined callback function.
/// </para>
/// </summary>
/// <param name="hwinsta">
/// <para>
/// A handle to the window station whose desktops are to be enumerated. This handle is returned by the CreateWindowStation,
/// GetProcessWindowStation, or OpenWindowStation function, and must have the WINSTA_ENUMDESKTOPS access right. For more information,
/// see Window Station Security and Access Rights.
/// </para>
/// <para>If this parameter is NULL, the current window station is used.</para>
/// </param>
/// <param name="lpEnumFunc">
/// <para>A pointer to an application-defined EnumDesktopProc callback function.</para>
/// </param>
/// <param name="lParam">
/// <para>An application-defined value to be passed to the callback function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns the nonzero value returned by the callback function that was pointed to by lpEnumFunc.</para>
/// <para>
/// If the function is unable to perform the enumeration, the return value is zero. Call GetLastError to get extended error information.
/// </para>
/// <para>
/// If the callback function fails, the return value is zero. The callback function can call SetLastError to set an error code for
/// the caller to retrieve by calling GetLastError.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>EnumDesktops</c> function enumerates only those desktops for which the calling process has the DESKTOP_ENUMERATE access
/// right. For more information, see Desktop Security and Access Rights.
/// </para>
/// <para>
/// The <c>EnumDesktops</c> function repeatedly invokes the lpEnumFunc callback function until the last desktop is enumerated or the
/// callback function returns FALSE.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumdesktopsa BOOL EnumDesktopsA( HWINSTA hwinsta,
// DESKTOPENUMPROCA lpEnumFunc, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "3e900b34-2c60-4281-881f-13a746674aec")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumDesktops(HWINSTA hwinsta, EnumDesktopProc lpEnumFunc, IntPtr lParam);
/// <summary>Enumerates all desktops associated with the specified window station of the calling process.</summary>
/// <param name="hwinsta">
/// <para>
/// A handle to the window station whose desktops are to be enumerated. This handle is returned by the CreateWindowStation,
/// GetProcessWindowStation, or OpenWindowStation function, and must have the WINSTA_ENUMDESKTOPS access right. For more information,
/// see Window Station Security and Access Rights.
/// </para>
/// <para>If this parameter is NULL, the current window station is used.</para>
/// </param>
/// <returns>The list of desktop names in the specified window station of the calling process.</returns>
/// <remarks>
/// <para>
/// The <c>EnumDesktops</c> function enumerates only those desktops for which the calling process has the DESKTOP_ENUMERATE access
/// right. For more information, see Desktop Security and Access Rights.
/// </para>
/// </remarks>
public static IEnumerable<string> EnumDesktops(HWINSTA hwinsta)
{
var ret = new List<string>();
if (!EnumDesktops(hwinsta, EnumProc, IntPtr.Zero))
Win32Error.ThrowLastError();
return ret;
bool EnumProc(string desktopName, IntPtr lParam)
{
ret.Add(desktopName);
return true;
}
}
/// <summary>
/// <para>
/// Enumerates all top-level windows associated with the specified desktop. It passes the handle to each window, in turn, to an
/// application-defined callback function.
/// </para>
/// </summary>
/// <param name="hDesktop">
/// <para>
/// A handle to the desktop whose top-level windows are to be enumerated. This handle is returned by the CreateDesktop,
/// GetThreadDesktop, OpenDesktop, or OpenInputDesktop function, and must have the <c>DESKTOP_READOBJECTS</c> access right. For more
/// information, see Desktop Security and Access Rights.
/// </para>
/// <para>If this parameter is NULL, the current desktop is used.</para>
/// </param>
/// <param name="lpfn">
/// <para>A pointer to an application-defined EnumWindowsProc callback function.</para>
/// </param>
/// <param name="lParam">
/// <para>An application-defined value to be passed to the callback function.</para>
/// </param>
/// <returns>
/// <para>If the function fails or is unable to perform the enumeration, the return value is zero.</para>
/// <para>To get extended error information, call GetLastError.</para>
/// <para>You must ensure that the callback function sets SetLastError if it fails.</para>
/// <para><c>Windows Server 2003 and Windows XP/2000:</c> If there are no windows on the desktop, GetLastError returns <c>ERROR_INVALID_HANDLE</c>.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>EnumDesktopWindows</c> function repeatedly invokes the lpfn callback function until the last top-level window is
/// enumerated or the callback function returns <c>FALSE</c>.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumdesktopwindows BOOL EnumDesktopWindows( HDESK
// hDesktop, WNDENUMPROC lpfn, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "b399ff19-e2e5-4509-8bb5-9647734881b3")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumDesktopWindows(HDESK hDesktop, EnumWindowsProc lpfn, IntPtr lParam);
/// <summary>
/// <para>
/// Enumerates all window stations in the current session. The function passes the name of each window station, in turn, to an
/// application-defined callback function.
/// </para>
/// </summary>
/// <param name="lpEnumFunc">
/// <para>A pointer to an application-defined EnumWindowStationProc callback function.</para>
/// </param>
/// <param name="lParam">
/// <para>An application-defined value to be passed to the callback function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns the nonzero value returned by the callback function that was pointed to by lpEnumFunc.</para>
/// <para>
/// If the function is unable to perform the enumeration, the return value is zero. Call GetLastError to get extended error information.
/// </para>
/// <para>
/// If the callback function fails, the return value is zero. The callback function can call SetLastError to set an error code for
/// the caller to retrieve by calling GetLastError.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>EnumWindowStations</c> function enumerates only those window stations for which the calling process has the
/// WINSTA_ENUMERATE access right. For more information, see Window Station Security and Access Rights.
/// </para>
/// <para>
/// <c>EnumWindowStations</c> repeatedly invokes the lpEnumFunc callback function until the last window station is enumerated or the
/// callback function returns FALSE.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumwindowstationsa BOOL EnumWindowStationsA(
// WINSTAENUMPROCA lpEnumFunc, LPARAM lParam );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "418d4d6a-9e4d-4fe3-8e1b-398c732c6e23")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindowStations(EnumWindowStationProc lpEnumFunc, IntPtr lParam);
/// <summary>
/// <para>Retrieves a handle to the current window station for the calling process.</para>
/// </summary>
/// <returns>
/// <para>If the function succeeds, the return value is a handle to the window station.</para>
/// <para>If the function fails, the return value is NULL. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The system associates a window station with a process when the process is created. A process can use the SetProcessWindowStation
/// function to change its window station.
/// </para>
/// <para>
/// The calling process can use the returned handle in calls to the GetUserObjectInformation, GetUserObjectSecurity,
/// SetUserObjectInformation, and SetUserObjectSecurity functions.
/// </para>
/// <para>Do not close the handle returned by this function.</para>
/// <para>
/// A service application is created with an associated window station and desktop, so there is no need to call a USER or GDI
/// function to connect the service to a window station and desktop.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getprocesswindowstation HWINSTA GetProcessWindowStation( );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "f8929122-d277-4260-b2a7-5e76eb3ca876")]
// SafeHWINSTA not used as this handle should not be closed.
public static extern HWINSTA GetProcessWindowStation();
/// <summary>
/// <para>Retrieves a handle to the desktop assigned to the specified thread.</para>
/// </summary>
/// <param name="dwThreadId">
/// <para>The thread identifier. The GetCurrentThreadId and CreateProcess functions return thread identifiers.</para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is a handle to the desktop associated with the specified thread. You do not need to
/// call the CloseDesktop function to close the returned handle.
/// </para>
/// <para>If the function fails, the return value is NULL. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The system associates a desktop with a thread when that thread is created. A thread can use the SetThreadDesktop function to
/// change its desktop. The desktop associated with a thread must be on the window station associated with the thread's process.
/// </para>
/// <para>
/// The calling process can use the returned handle in calls to the GetUserObjectInformation, GetUserObjectSecurity,
/// SetUserObjectInformation, and SetUserObjectSecurity functions.
/// </para>
/// <para>
/// A service application is created with an associated window station and desktop, so there is no need to call a USER or GDI
/// function to connect the service to a window station and desktop.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getthreaddesktop HDESK GetThreadDesktop( DWORD dwThreadId );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "51eec935-43c7-495b-b1fc-2bd5ba1e0090")]
// SafeHDESK not used as this handle should not be closed.
public static extern HDESK GetThreadDesktop(uint dwThreadId);
/// <summary>
/// <para>Retrieves information about the specified window station or desktop object.</para>
/// </summary>
/// <param name="hObj">
/// <para>
/// A handle to the window station or desktop object. This handle is returned by the CreateWindowStation, OpenWindowStation,
/// CreateDesktop, or OpenDesktop function.
/// </para>
/// </param>
/// <param name="nIndex">
/// <para>The information to be retrieved. The parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>UOI_FLAGS 1</term>
/// <term>The handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.</term>
/// </item>
/// <item>
/// <term>UOI_HEAPSIZE 5</term>
/// <term>
/// The size of the desktop heap, in KB, as a ULONG value. The hObj parameter must be a handle to a desktop object, otherwise, the
/// function fails. Windows Server 2003 and Windows XP/2000: This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>UOI_IO 6</term>
/// <term>
/// TRUE if the hObj parameter is a handle to the desktop object that is receiving input from the user. FALSE otherwise. Windows
/// Server 2003 and Windows XP/2000: This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>UOI_NAME 2</term>
/// <term>The name of the object, as a string.</term>
/// </item>
/// <item>
/// <term>UOI_TYPE 3</term>
/// <term>The type name of the object, as a string.</term>
/// </item>
/// <item>
/// <term>UOI_USER_SID 4</term>
/// <term>
/// The SID structure that identifies the user that is currently associated with the specified object. If no user is associated with
/// the object, the value returned in the buffer pointed to by lpnLengthNeeded is zero. Note that SID is a variable length structure.
/// You will usually make a call to GetUserObjectInformation to determine the length of the SID before retrieving its value.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pvInfo">
/// <para>A pointer to a buffer to receive the object information.</para>
/// </param>
/// <param name="nLength">
/// <para>The size of the buffer pointed to by the pvInfo parameter, in bytes.</para>
/// </param>
/// <param name="lpnLengthNeeded">
/// <para>
/// A pointer to a variable receiving the number of bytes required to store the requested information. If this variable's value is
/// greater than the value of the nLength parameter when the function returns, the function returns FALSE, and none of the
/// information is copied to the pvInfo buffer. If the value of the variable pointed to by lpnLengthNeeded is less than or equal to
/// the value of nLength, the entire information block is copied.
/// </para>
/// </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 GetLastError.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getuserobjectinformationa BOOL GetUserObjectInformationA(
// HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "64f7361d-1a94-4d5b-86f1-a2a21737668a")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetUserObjectInformation(IntPtr hObj, UserObjectInformationType nIndex, IntPtr pvInfo, uint nLength, out uint lpnLengthNeeded);
/// <summary>
/// <para>Retrieves information about the specified window station or desktop object.</para>
/// </summary>
/// <param name="hObj">
/// <para>
/// A handle to the window station or desktop object. This handle is returned by the CreateWindowStation, OpenWindowStation,
/// CreateDesktop, or OpenDesktop function.
/// </para>
/// </param>
/// <param name="nIndex">
/// <para>The information to be retrieved. The parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>UOI_FLAGS 1</term>
/// <term>The handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.</term>
/// </item>
/// <item>
/// <term>UOI_HEAPSIZE 5</term>
/// <term>
/// The size of the desktop heap, in KB, as a ULONG value. The hObj parameter must be a handle to a desktop object, otherwise, the
/// function fails. Windows Server 2003 and Windows XP/2000: This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>UOI_IO 6</term>
/// <term>
/// TRUE if the hObj parameter is a handle to the desktop object that is receiving input from the user. FALSE otherwise. Windows
/// Server 2003 and Windows XP/2000: This value is not supported.
/// </term>
/// </item>
/// <item>
/// <term>UOI_NAME 2</term>
/// <term>The name of the object, as a string.</term>
/// </item>
/// <item>
/// <term>UOI_TYPE 3</term>
/// <term>The type name of the object, as a string.</term>
/// </item>
/// <item>
/// <term>UOI_USER_SID 4</term>
/// <term>
/// The SID structure that identifies the user that is currently associated with the specified object. If no user is associated with
/// the object, the value returned in the buffer pointed to by lpnLengthNeeded is zero. Note that SID is a variable length structure.
/// You will usually make a call to GetUserObjectInformation to determine the length of the SID before retrieving its value.
/// </term>
/// </item>
/// </list>
/// </param>
/// <returns>The value specified by <typeparamref name="T"/> and <paramref name="nIndex"/>.</returns>
[PInvokeData("winuser.h", MSDNShortId = "64f7361d-1a94-4d5b-86f1-a2a21737668a")]
public static T GetUserObjectInformation<T>(IntPtr hObj, UserObjectInformationType nIndex)
{
if (!CorrespondingTypeAttribute.CanGet(nIndex, typeof(T))) throw new ArgumentException("Type mismatch");
GetUserObjectInformation(hObj, nIndex, IntPtr.Zero, 0, out var sz);
var mem = new SafeHGlobalHandle((int)sz);
if (!GetUserObjectInformation(hObj, nIndex, (IntPtr)mem, sz, out var _))
Win32Error.ThrowLastError();
if (typeof(T) == typeof(string))
return (T)(object)mem.ToString(-1);
return mem.ToStructure<T>();
}
/// <summary>
/// <para>Opens the specified desktop object.</para>
/// </summary>
/// <param name="lpszDesktop">
/// <para>The name of the desktop to be opened. Desktop names are case-insensitive.</para>
/// <para>This desktop must belong to the current window station.</para>
/// </param>
/// <param name="dwFlags">
/// <para>This parameter can be zero or the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>DF_ALLOWOTHERACCOUNTHOOK 0x0001</term>
/// <term>Allows processes running in other accounts on the desktop to set hooks in this process.</term>
/// </item>
/// </list>
/// </param>
/// <param name="fInherit">
/// <para>
/// If this value is <c>TRUE</c>, processes created by this process will inherit the handle. Otherwise, the processes do not inherit
/// this handle.
/// </para>
/// </param>
/// <param name="dwDesiredAccess">
/// <para>The access to the desktop. For a list of access rights, see Desktop Security and Access Rights.</para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is a handle to the opened desktop. When you are finished using the handle, call the
/// CloseDesktop function to close it.
/// </para>
/// <para>If the function fails, the return value is <c>NULL</c>. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The calling process must have an associated window station, either assigned by the system at process creation time or set by the
/// SetProcessWindowStation function.
/// </para>
/// <para>
/// If the dwDesiredAccess parameter specifies the <c>READ_CONTROL</c>, <c>WRITE_DAC</c>, or <c>WRITE_OWNER</c> standard access
/// rights, you must also request the <c>DESKTOP_READOBJECTS</c> and <c>DESKTOP_WRITEOBJECTS</c> access rights.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-opendesktopa HDESK OpenDesktopA( LPCSTR lpszDesktop, DWORD
// dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "7f805f47-1737-4f4b-a74a-9c1423b65f2c")]
public static extern SafeHDESK OpenDesktop(string lpszDesktop, CreateDesktopFlags dwFlags, [MarshalAs(UnmanagedType.Bool)] bool fInherit, ACCESS_MASK dwDesiredAccess);
/// <summary>
/// <para>Opens the desktop that receives user input.</para>
/// </summary>
/// <param name="dwFlags">
/// <para>This parameter can be zero or the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>DF_ALLOWOTHERACCOUNTHOOK 0x0001</term>
/// <term>Allows processes running in other accounts on the desktop to set hooks in this process.</term>
/// </item>
/// </list>
/// </param>
/// <param name="fInherit">
/// <para>
/// If this value is <c>TRUE</c>, processes created by this process will inherit the handle. Otherwise, the processes do not inherit
/// this handle.
/// </para>
/// </param>
/// <param name="dwDesiredAccess">
/// <para>The access to the desktop. For a list of access rights, see Desktop Security and Access Rights.</para>
/// </param>
/// <returns>
/// <para>
/// If the function succeeds, the return value is a handle to the desktop that receives user input. When you are finished using the
/// handle, call the CloseDesktop function to close it.
/// </para>
/// <para>If the function fails, the return value is <c>NULL</c>. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The calling process must have an associated window station, either assigned by the system when the process is created, or set by
/// the SetProcessWindowStation function. The window station associated with the calling process must be capable of receiving input.
/// </para>
/// <para>
/// If the calling process is running in a disconnected session, the function returns a handle to the desktop that becomes active
/// when the user restores the connection.
/// </para>
/// <para>An application can use the SwitchDesktop function to change the input desktop.</para>
/// <para>
/// If the dwDesiredAccess parameter specifies the <c>READ_CONTROL</c>, <c>WRITE_DAC</c>, or <c>WRITE_OWNER</c> standard access
/// rights, you must also request the <c>DESKTOP_READOBJECTS</c> and <c>DESKTOP_WRITEOBJECTS</c> access rights.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-openinputdesktop HDESK OpenInputDesktop( DWORD dwFlags,
// BOOL fInherit, ACCESS_MASK dwDesiredAccess );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "023d421e-bf32-4e08-b5b3-b7b2ca6c4e00")]
public static extern SafeHDESK OpenInputDesktop(CreateDesktopFlags dwFlags, [MarshalAs(UnmanagedType.Bool)] bool fInherit, ACCESS_MASK dwDesiredAccess);
/// <summary>
/// <para>Opens the specified window station.</para>
/// </summary>
/// <param name="lpszWinSta">
/// <para>The name of the window station to be opened. Window station names are case-insensitive.</para>
/// <para>This window station must belong to the current session.</para>
/// </param>
/// <param name="fInherit">
/// <para>
/// If this value is <c>TRUE</c>, processes created by this process will inherit the handle. Otherwise, the processes do not inherit
/// this handle.
/// </para>
/// </param>
/// <param name="dwDesiredAccess">
/// <para>The access to the window station. For a list of access rights, see Window Station Security and Access Rights.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is the handle to the specified window station.</para>
/// <para>If the function fails, the return value is <c>NULL</c>. To get extended error information, call GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>After you are done with the handle, you must call CloseWindowStation to free the handle.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-openwindowstationa HWINSTA OpenWindowStationA( LPCSTR
// lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "78ee7100-1bad-4c2d-b923-c5e67191bd41")]
public static extern SafeHWINSTA OpenWindowStation(string lpszWinSta, [MarshalAs(UnmanagedType.Bool)] bool fInherit, ACCESS_MASK dwDesiredAccess);
/// <summary>
/// <para>
/// Assigns the specified window station to the calling process. This enables the process to access objects in the window station
/// such as desktops, the clipboard, and global atoms. All subsequent operations on the window station use the access rights granted
/// to hWinSta.
/// </para>
/// </summary>
/// <param name="hWinSta">
/// <para>
/// A handle to the window station. This can be a handle returned by the CreateWindowStation, OpenWindowStation, or
/// GetProcessWindowStation function.
/// </para>
/// <para>This window station must be associated with the current session.</para>
/// </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 GetLastError.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setprocesswindowstation BOOL SetProcessWindowStation(
// HWINSTA hWinSta );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "d64814a7-945c-4e73-a977-5f696d60610e")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetProcessWindowStation(HWINSTA hWinSta);
/// <summary>
/// <para>
/// Assigns the specified desktop to the calling thread. All subsequent operations on the desktop use the access rights granted to
/// the desktop.
/// </para>
/// </summary>
/// <param name="hDesktop">
/// <para>
/// A handle to the desktop to be assigned to the calling thread. This handle is returned by the CreateDesktop, GetThreadDesktop,
/// OpenDesktop, or OpenInputDesktop function.
/// </para>
/// <para>This desktop must be associated with the current window station for the process.</para>
/// </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 GetLastError.</para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>SetThreadDesktop</c> function will fail if the calling thread has any windows or hooks on its current desktop (unless the
/// hDesktop parameter is a handle to the current desktop).
/// </para>
/// <para>
/// <c>Warning</c> There is a significant security risk for any service that opens a window on the interactive desktop. By opening a
/// desktop window, a service makes itself vulnerable to attack from the logged-on user, whose application could send malicious
/// messages to the service's desktop window and affect its ability to function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setthreaddesktop BOOL SetThreadDesktop( HDESK hDesktop );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "619c591f-54b7-4b61-aa07-fc57e05ee37a")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetThreadDesktop(HDESK hDesktop);
/// <summary>
/// <para>Sets information about the specified window station or desktop object.</para>
/// </summary>
/// <param name="hObj">
/// <para>
/// A handle to the window station, desktop object or a current process pseudo handle. This handle can be returned by the
/// CreateWindowStation, OpenWindowStation, CreateDesktop, OpenDesktop or GetCurrentProcess function.
/// </para>
/// </param>
/// <param name="nIndex">
/// <para>The object information to be set. This parameter can be the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>UOI_FLAGS 1</term>
/// <term>Sets the object's handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.</term>
/// </item>
/// <item>
/// <term>UOI_TIMERPROC_EXCEPTION_SUPPRESSION 7</term>
/// <term>
/// Sets the exception handling behavior when calling TimerProc. hObj must be the process handle returned by the GetCurrentProcess
/// function. The pvInfo parameter must point to a BOOL. If TRUE, Windows will enclose its calls to TimerProc with an exception
/// handler that consumes and discards all exceptions. This has been the default behavior since Windows 2000, although that may
/// change in future versions of Windows. If pvInfo points to FALSE, Windows will not enclose its calls to TimerProc with an
/// exception handler. A setting of FALSE is recommended. Otherwise, the application could behave unpredictably, and could be more
/// vulnerable to security exploits.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="pvInfo">
/// <para>A pointer to a buffer containing the object information, or a BOOL.</para>
/// </param>
/// <param name="nLength">
/// <para>The size of the information contained in the buffer pointed to by pvInfo, in bytes.</para>
/// </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 GetLastError.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setuserobjectinformationa BOOL SetUserObjectInformationA(
// HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength );
[DllImport(Lib.User32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("winuser.h", MSDNShortId = "42ce6946-1659-41a3-8ba7-21588583b4bd")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetUserObjectInformation(IntPtr hObj, UserObjectInformationType nIndex, IntPtr pvInfo, uint nLength);
/// <summary>Sets information about the specified window station or desktop object.</summary>
/// <typeparam name="T">The type being set.</typeparam>
/// <param name="hObj">
/// A handle to the window station, desktop object or a current process pseudo handle. This handle can be returned by the
/// CreateWindowStation, OpenWindowStation, CreateDesktop, OpenDesktop or GetCurrentProcess function.
/// </param>
/// <param name="nIndex">
/// <para>The object information to be set. This parameter can be the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>UOI_FLAGS 1</term>
/// <term>Sets the object's handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.</term>
/// </item>
/// <item>
/// <term>UOI_TIMERPROC_EXCEPTION_SUPPRESSION 7</term>
/// <term>
/// Sets the exception handling behavior when calling TimerProc. hObj must be the process handle returned by the GetCurrentProcess
/// function. The pvInfo parameter must point to a BOOL. If TRUE, Windows will enclose its calls to TimerProc with an exception
/// handler that consumes and discards all exceptions. This has been the default behavior since Windows 2000, although that may
/// change in future versions of Windows. If pvInfo points to FALSE, Windows will not enclose its calls to TimerProc with an
/// exception handler. A setting of FALSE is recommended. Otherwise, the application could behave unpredictably, and could be more
/// vulnerable to security exploits.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="info">A buffer containing the object information, or a BOOL.</param>
/// <exception cref="System.ArgumentException">Type mismatch</exception>
public static void SetUserObjectInformation<T>(IntPtr hObj, UserObjectInformationType nIndex, T info)
{
if (!CorrespondingTypeAttribute.CanSet(nIndex, typeof(T))) throw new ArgumentException("Type mismatch");
var mem = typeof(T) == typeof(string) ? new SafeHGlobalHandle(info.ToString()) : SafeHGlobalHandle.CreateFromStructure(info);
if (!SetUserObjectInformation(hObj, nIndex, (IntPtr)mem, (uint)mem.Size))
Win32Error.ThrowLastError();
}
/// <summary>
/// <para>
/// Makes the specified desktop visible and activates it. This enables the desktop to receive input from the user. The calling
/// process must have DESKTOP_SWITCHDESKTOP access to the desktop for the <c>SwitchDesktop</c> function to succeed.
/// </para>
/// </summary>
/// <param name="hDesktop">
/// <para>A handle to the desktop. This handle is returned by the CreateDesktop and OpenDesktop functions.</para>
/// <para>This desktop must be associated with the current window station for the process.</para>
/// </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 GetLastError. However,
/// <c>SwitchDesktop</c> only sets the last error for the following cases:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>When the desktop belongs to an invisible window station</term>
/// </item>
/// <item>
/// <term>
/// When hDesktop is an invalid handle, refers to a destroyed desktop, or belongs to a different session than that of the calling process
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>SwitchDesktop</c> function fails if the desktop belongs to an invisible window station. <c>SwitchDesktop</c> also fails
/// when called from a process that is associated with a secured desktop such as the WinLogon and ScreenSaver desktops. Processes
/// that are associated with a secured desktop include custom UserInit processes. Such calls typically fail with an "access denied" error.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-switchdesktop BOOL SwitchDesktop( HDESK hDesktop );
[DllImport(Lib.User32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "401be515-ada9-42be-b8e8-4e86f513bb8d")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SwitchDesktop(HDESK hDesktop);
/// <summary>
/// <para>Contains information about a window station or desktop handle.</para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taguserobjectflags typedef struct tagUSEROBJECTFLAGS {
// BOOL fInherit; BOOL fReserved; DWORD dwFlags; } USEROBJECTFLAGS, *PUSEROBJECTFLAGS;
[PInvokeData("winuser.h", MSDNShortId = "5a973d45-5ff4-47e7-a927-72d3fdd61dc9")]
[StructLayout(LayoutKind.Sequential)]
public struct USEROBJECTFLAGS
{
/// <summary>
/// <para>If this member is TRUE, new processes inherit the handle. Otherwise, the handle is not inherited.</para>
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool fInherit;
/// <summary>
/// <para>Reserved for future use. This member must be FALSE.</para>
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool fReserved;
/// <summary>
/// <para>For window stations, this member can contain the following window station attribute.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>WSF_VISIBLE 0x0001L</term>
/// <term>Window station has visible display surfaces.</term>
/// </item>
/// </list>
/// <para>For desktops, the <c>dwFlags</c> member can contain the following value.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>DF_ALLOWOTHERACCOUNTHOOK 0x0001L</term>
/// <term>Allows processes running in other accounts on the desktop to set hooks in this process.</term>
/// </item>
/// </list>
/// </summary>
public uint dwFlags;
}
/// <summary>Provides a <see cref="SafeHandle"/> to a that releases a created HDESK instance at disposal using CloseDesktop.</summary>
public class SafeHDESK : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="HDESK"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeHDESK(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
private SafeHDESK() : base()
{
}
/// <summary>Performs an implicit conversion from <see cref="SafeHDESK"/> to <see cref="HDESK"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HDESK(SafeHDESK h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => CloseDesktop(this);
}
/// <summary>Provides a <see cref="SafeHandle"/> to a that releases a created HWINSTA instance at disposal using CloseWindowStation.</summary>
public class SafeHWINSTA : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="HWINSTA"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeHWINSTA(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
private SafeHWINSTA() : base()
{
}
/// <summary>Performs an implicit conversion from <see cref="SafeHWINSTA"/> to <see cref="HWINSTA"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator HWINSTA(SafeHWINSTA h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => CloseWindowStation(this);
}
}
}