using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class User32
{
///
/// An application-defined callback function used with the EnumDesktops function. It receives a desktop name.
///
/// The DESKTOPENUMPROC type defines a pointer to this callback function. EnumDesktopProc is a placeholder for the
/// application-defined function name.
///
///
/// The name of the desktop.
/// An application-defined value specified in the EnumDesktops function.
/// To continue enumeration, the callback function must return TRUE. To stop enumeration, it must return FALSE.
// 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);
///
///
/// An application-defined callback function used with the EnumWindowStations function. It receives a window station name.
///
///
/// The WINSTAENUMPROC type defines a pointer to this callback function. EnumWindowStationProc is a placeholder for the
/// application-defined function name.
///
///
/// The name of the window station.
/// An application-defined value specified in the EnumWindowStations function.
/// To continue enumeration, the callback function must return TRUE. To stop enumeration, it must return FALSE.
// 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);
/// Flags used by CreateDesktop.
[Flags]
public enum CreateDesktopFlags
{
/// Enables processes running in other accounts on the desktop to set hooks in this process.
DF_ALLOWOTHERACCOUNTHOOK = 0x0001
}
/// Flags used by CreateWindowStation.
[Flags]
public enum CreateWindowStationFlags
{
///
/// 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.
///
CWF_CREATE_ONLY = 0x00000001,
}
/// The information to be retrieved by GetUserObjectInformation or set by SetUserObjectInformation.
[PInvokeData("winuser.h", MSDNShortId = "64f7361d-1a94-4d5b-86f1-a2a21737668a")]
public enum UserObjectInformationType
{
/// The handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.
[CorrespondingType(typeof(USEROBJECTFLAGS))]
UOI_FLAGS = 1,
///
/// 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.
///
[CorrespondingType(typeof(uint))]
UOI_HEAPSIZE = 5,
///
/// 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.
///
[CorrespondingType(typeof(uint))]
UOI_IO = 6,
/// The name of the object, as a string.
[CorrespondingType(typeof(string))]
UOI_NAME = 2,
/// The type name of the object, as a string.
[CorrespondingType(typeof(string))]
UOI_TYPE = 3,
///
/// 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.
///
[CorrespondingType(typeof(IntPtr))]
UOI_USER_SID = 4,
}
///
/// Closes an open handle to a desktop object.
///
///
///
/// 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.
///
///
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
///
/// The CloseDesktop 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.
///
///
// 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);
///
/// Closes an open window station handle.
///
///
///
/// 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.
///
///
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
/// Windows Server 2003 and Windows XP/2000: This function does not set the last error code on failure.
///
///
///
/// The CloseWindowStation function will fail if the handle being closed is for the window station assigned to the calling process.
///
///
// 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);
///
///
/// 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.
///
/// To specify the size of the heap for the desktop, use the CreateDesktopEx function.
///
///
/// The name of the desktop to be created. Desktop names are case-insensitive and may not contain backslash characters ().
///
///
/// Reserved; must be NULL.
///
///
/// Reserved; must be NULL.
///
///
/// This parameter can be zero or the following value.
///
///
/// Value
/// Meaning
///
/// -
/// DF_ALLOWOTHERACCOUNTHOOK 0x0001
/// Enables processes running in other accounts on the desktop to set hooks in this process.
///
///
///
///
/// The access to the desktop. For a list of values, see Desktop Security and Access Rights.
///
/// This parameter must include the DESKTOP_CREATEWINDOW access right, because internally CreateDesktop uses the handle
/// to create a window.
///
///
///
///
/// 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.
///
///
/// The lpSecurityDescriptor 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.
///
///
///
///
/// 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.
///
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
///
/// 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.
///
///
/// 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: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\Windows. The default data
/// for this registry value is as follows:
///
///
/// "%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"
///
/// The values for the "SharedSection" substring are described as follows:
///
/// -
/// The first "SharedSection" value is the size of the shared heap common to all desktops, in kilobytes.
///
/// -
///
/// 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.
///
///
/// -
///
/// 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.
///
///
///
///
// 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);
///
///
/// 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.
///
///
///
/// The name of the desktop to be created. Desktop names are case-insensitive and may not contain backslash characters ().
///
///
/// This parameter is reserved and must be NULL.
///
///
/// This parameter is reserved and must be NULL.
///
///
/// This parameter can be zero or the following value.
///
///
/// Value
/// Meaning
///
/// -
/// DF_ALLOWOTHERACCOUNTHOOK 0x0001
/// Enables processes running in other accounts on the desktop to set hooks in this process.
///
///
///
///
/// The requested access to the desktop. For a list of values, see Desktop Security and Access Rights.
///
/// This parameter must include the DESKTOP_CREATEWINDOW access right, because internally CreateDesktop uses the handle to create a window.
///
///
///
///
/// 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.
///
///
/// The lpSecurityDescriptor 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.
///
///
///
/// The size of the desktop heap, in kilobytes.
///
///
/// This parameter is reserved and must be NULL.
///
///
///
/// 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.
///
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
///
/// 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.
///
///
/// 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: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
/// Manager\SubSystems\Windows. The default data for this registry value is as follows:
///
///
/// %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
///
/// The values for the SharedSection substring are described as follows:
///
/// -
/// The first SharedSection value is the size of the shared heap common to all desktops, in kilobytes.
///
/// -
///
/// 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.
///
///
/// -
///
/// 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.
///
///
///
///
/// 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.
///
///
// 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);
///
/// Creates a window station object, associates it with the calling process, and assigns it to the current session.
///
///
///
/// 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 NULL 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.
///
///
///
///
/// If this parameter is CWF_CREATE_ONLY 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.
///
/// Windows XP/2000: This parameter is reserved and must be zero.
///
///
///
/// 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 READ_CONTROL or WRITE_DAC, and a combination of the window station-specific access rights. For more
/// information, see Window Station Security and Access Rights.
///
///
///
///
/// 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.
///
///
/// The lpSecurityDescriptor member of the structure specifies a security descriptor for the new window station. If lpsa is
/// NULL, the window station (and any desktops created within the window) gets a security descriptor that grants
/// GENERIC_ALL access to all users.
///
///
///
///
/// 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.
///
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
/// After you are done with the handle, you must call CloseWindowStation to free the handle.
///
// 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);
///
///
/// 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.
///
///
///
///
/// 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.
///
/// If this parameter is NULL, the current window station is used.
///
///
/// A pointer to an application-defined EnumDesktopProc callback function.
///
///
/// An application-defined value to be passed to the callback function.
///
///
/// If the function succeeds, it returns the nonzero value returned by the callback function that was pointed to by lpEnumFunc.
///
/// If the function is unable to perform the enumeration, the return value is zero. Call GetLastError to get extended error information.
///
///
/// 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.
///
///
///
///
/// The EnumDesktops 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.
///
///
/// The EnumDesktops function repeatedly invokes the lpEnumFunc callback function until the last desktop is enumerated or the
/// callback function returns FALSE.
///
///
// 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);
/// Enumerates all desktops associated with the specified window station of the calling process.
///
///
/// 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.
///
/// If this parameter is NULL, the current window station is used.
///
/// The list of desktop names in the specified window station of the calling process.
///
///
/// The EnumDesktops 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.
///
///
public static IEnumerable EnumDesktops(HWINSTA hwinsta)
{
var ret = new List();
if (!EnumDesktops(hwinsta, EnumProc, IntPtr.Zero))
Win32Error.ThrowLastError();
return ret;
bool EnumProc(string desktopName, IntPtr lParam)
{
ret.Add(desktopName);
return true;
}
}
///
///
/// 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.
///
///
///
///
/// 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 DESKTOP_READOBJECTS access right. For more
/// information, see Desktop Security and Access Rights.
///
/// If this parameter is NULL, the current desktop is used.
///
///
/// A pointer to an application-defined EnumWindowsProc callback function.
///
///
/// An application-defined value to be passed to the callback function.
///
///
/// If the function fails or is unable to perform the enumeration, the return value is zero.
/// To get extended error information, call GetLastError.
/// You must ensure that the callback function sets SetLastError if it fails.
/// Windows Server 2003 and Windows XP/2000: If there are no windows on the desktop, GetLastError returns ERROR_INVALID_HANDLE.
///
///
///
/// The EnumDesktopWindows function repeatedly invokes the lpfn callback function until the last top-level window is
/// enumerated or the callback function returns FALSE.
///
///
// 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);
///
///
/// 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.
///
///
///
/// A pointer to an application-defined EnumWindowStationProc callback function.
///
///
/// An application-defined value to be passed to the callback function.
///
///
/// If the function succeeds, it returns the nonzero value returned by the callback function that was pointed to by lpEnumFunc.
///
/// If the function is unable to perform the enumeration, the return value is zero. Call GetLastError to get extended error information.
///
///
/// 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.
///
///
///
///
/// The EnumWindowStations 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.
///
///
/// EnumWindowStations repeatedly invokes the lpEnumFunc callback function until the last window station is enumerated or the
/// callback function returns FALSE.
///
///
// 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);
///
/// Retrieves a handle to the current window station for the calling process.
///
///
/// If the function succeeds, the return value is a handle to the window station.
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
///
/// 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.
///
///
/// The calling process can use the returned handle in calls to the GetUserObjectInformation, GetUserObjectSecurity,
/// SetUserObjectInformation, and SetUserObjectSecurity functions.
///
/// Do not close the handle returned by this function.
///
/// 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.
///
///
// 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();
///
/// Retrieves a handle to the desktop assigned to the specified thread.
///
///
/// The thread identifier. The GetCurrentThreadId and CreateProcess functions return thread identifiers.
///
///
///
/// 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.
///
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
///
/// 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.
///
///
/// The calling process can use the returned handle in calls to the GetUserObjectInformation, GetUserObjectSecurity,
/// SetUserObjectInformation, and SetUserObjectSecurity functions.
///
///
/// 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.
///
///
// 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);
///
/// Retrieves information about the specified window station or desktop object.
///
///
///
/// A handle to the window station or desktop object. This handle is returned by the CreateWindowStation, OpenWindowStation,
/// CreateDesktop, or OpenDesktop function.
///
///
///
/// The information to be retrieved. The parameter can be one of the following values.
///
///
/// Value
/// Meaning
///
/// -
/// UOI_FLAGS 1
/// The handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.
///
/// -
/// UOI_HEAPSIZE 5
///
/// 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.
///
///
/// -
/// UOI_IO 6
///
/// 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.
///
///
/// -
/// UOI_NAME 2
/// The name of the object, as a string.
///
/// -
/// UOI_TYPE 3
/// The type name of the object, as a string.
///
/// -
/// UOI_USER_SID 4
///
/// 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.
///
///
///
///
///
/// A pointer to a buffer to receive the object information.
///
///
/// The size of the buffer pointed to by the pvInfo parameter, in bytes.
///
///
///
/// 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.
///
///
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
// 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);
///
/// Retrieves information about the specified window station or desktop object.
///
///
///
/// A handle to the window station or desktop object. This handle is returned by the CreateWindowStation, OpenWindowStation,
/// CreateDesktop, or OpenDesktop function.
///
///
///
/// The information to be retrieved. The parameter can be one of the following values.
///
///
/// Value
/// Meaning
///
/// -
/// UOI_FLAGS 1
/// The handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.
///
/// -
/// UOI_HEAPSIZE 5
///
/// 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.
///
///
/// -
/// UOI_IO 6
///
/// 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.
///
///
/// -
/// UOI_NAME 2
/// The name of the object, as a string.
///
/// -
/// UOI_TYPE 3
/// The type name of the object, as a string.
///
/// -
/// UOI_USER_SID 4
///
/// 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.
///
///
///
///
/// The value specified by and .
[PInvokeData("winuser.h", MSDNShortId = "64f7361d-1a94-4d5b-86f1-a2a21737668a")]
public static T GetUserObjectInformation(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();
}
///
/// Opens the specified desktop object.
///
///
/// The name of the desktop to be opened. Desktop names are case-insensitive.
/// This desktop must belong to the current window station.
///
///
/// This parameter can be zero or the following value.
///
///
/// Value
/// Meaning
///
/// -
/// DF_ALLOWOTHERACCOUNTHOOK 0x0001
/// Allows processes running in other accounts on the desktop to set hooks in this process.
///
///
///
///
///
/// If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit
/// this handle.
///
///
///
/// The access to the desktop. For a list of access rights, see Desktop Security and Access Rights.
///
///
///
/// 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.
///
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
///
/// The calling process must have an associated window station, either assigned by the system at process creation time or set by the
/// SetProcessWindowStation function.
///
///
/// 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.
///
///
// 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);
///
/// Opens the desktop that receives user input.
///
///
/// This parameter can be zero or the following value.
///
///
/// Value
/// Meaning
///
/// -
/// DF_ALLOWOTHERACCOUNTHOOK 0x0001
/// Allows processes running in other accounts on the desktop to set hooks in this process.
///
///
///
///
///
/// If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit
/// this handle.
///
///
///
/// The access to the desktop. For a list of access rights, see Desktop Security and Access Rights.
///
///
///
/// 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.
///
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
///
/// 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.
///
///
/// 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.
///
/// An application can use the SwitchDesktop function to change the input desktop.
///
/// 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.
///
///
// 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);
///
/// Opens the specified window station.
///
///
/// The name of the window station to be opened. Window station names are case-insensitive.
/// This window station must belong to the current session.
///
///
///
/// If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit
/// this handle.
///
///
///
/// The access to the window station. For a list of access rights, see Window Station Security and Access Rights.
///
///
/// If the function succeeds, the return value is the handle to the specified window station.
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
///
///
/// After you are done with the handle, you must call CloseWindowStation to free the handle.
///
// 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);
///
///
/// 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.
///
///
///
///
/// A handle to the window station. This can be a handle returned by the CreateWindowStation, OpenWindowStation, or
/// GetProcessWindowStation function.
///
/// This window station must be associated with the current session.
///
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
// 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);
///
///
/// Assigns the specified desktop to the calling thread. All subsequent operations on the desktop use the access rights granted to
/// the desktop.
///
///
///
///
/// A handle to the desktop to be assigned to the calling thread. This handle is returned by the CreateDesktop, GetThreadDesktop,
/// OpenDesktop, or OpenInputDesktop function.
///
/// This desktop must be associated with the current window station for the process.
///
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
///
///
///
/// The SetThreadDesktop 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).
///
///
/// Warning 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.
///
///
// 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);
///
/// Sets information about the specified window station or desktop object.
///
///
///
/// 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.
///
///
///
/// The object information to be set. This parameter can be the following value.
///
///
/// Value
/// Meaning
///
/// -
/// UOI_FLAGS 1
/// Sets the object's handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.
///
/// -
/// UOI_TIMERPROC_EXCEPTION_SUPPRESSION 7
///
/// 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.
///
///
///
///
///
/// A pointer to a buffer containing the object information, or a BOOL.
///
///
/// The size of the information contained in the buffer pointed to by pvInfo, in bytes.
///
///
/// If the function succeeds, the return value is nonzero.
/// If the function fails the return value is zero. To get extended error information, call GetLastError.
///
// 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);
/// Sets information about the specified window station or desktop object.
/// The type being set.
///
/// 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.
///
///
/// The object information to be set. This parameter can be the following value.
///
///
/// Value
/// Meaning
///
/// -
/// UOI_FLAGS 1
/// Sets the object's handle flags. The pvInfo parameter must point to a USEROBJECTFLAGS structure.
///
/// -
/// UOI_TIMERPROC_EXCEPTION_SUPPRESSION 7
///
/// 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.
///
///
///
///
/// A buffer containing the object information, or a BOOL.
/// Type mismatch
public static void SetUserObjectInformation(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();
}
///
///
/// 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 SwitchDesktop function to succeed.
///
///
///
/// A handle to the desktop. This handle is returned by the CreateDesktop and OpenDesktop functions.
/// This desktop must be associated with the current window station for the process.
///
///
/// If the function succeeds, the return value is nonzero.
///
/// If the function fails, the return value is zero. To get extended error information, call GetLastError. However,
/// SwitchDesktop only sets the last error for the following cases:
///
///
/// -
/// When the desktop belongs to an invisible window station
///
/// -
///
/// When hDesktop is an invalid handle, refers to a destroyed desktop, or belongs to a different session than that of the calling process
///
///
///
///
///
///
/// The SwitchDesktop function fails if the desktop belongs to an invisible window station. SwitchDesktop 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.
///
///
// 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);
///
/// Contains information about a window station or desktop handle.
///
// 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
{
///
/// If this member is TRUE, new processes inherit the handle. Otherwise, the handle is not inherited.
///
[MarshalAs(UnmanagedType.Bool)]
public bool fInherit;
///
/// Reserved for future use. This member must be FALSE.
///
[MarshalAs(UnmanagedType.Bool)]
public bool fReserved;
///
/// For window stations, this member can contain the following window station attribute.
///
///
/// Value
/// Meaning
///
/// -
/// WSF_VISIBLE 0x0001L
/// Window station has visible display surfaces.
///
///
/// For desktops, the dwFlags member can contain the following value.
///
///
/// Value
/// Meaning
///
/// -
/// DF_ALLOWOTHERACCOUNTHOOK 0x0001L
/// Allows processes running in other accounts on the desktop to set hooks in this process.
///
///
///
public uint dwFlags;
}
/// Provides a to a that releases a created HDESK instance at disposal using CloseDesktop.
public class SafeHDESK : SafeHANDLE
{
/// Initializes a new instance of the class and assigns an existing handle.
/// An object that represents the pre-existing handle to use.
///
/// to reliably release the handle during the finalization phase; otherwise, (not recommended).
///
public SafeHDESK(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
private SafeHDESK() : base()
{
}
/// Performs an implicit conversion from to .
/// The safe handle instance.
/// The result of the conversion.
public static implicit operator HDESK(SafeHDESK h) => h.handle;
///
protected override bool InternalReleaseHandle() => CloseDesktop(this);
}
/// Provides a to a that releases a created HWINSTA instance at disposal using CloseWindowStation.
public class SafeHWINSTA : SafeHANDLE
{
/// Initializes a new instance of the class and assigns an existing handle.
/// An object that represents the pre-existing handle to use.
///
/// to reliably release the handle during the finalization phase; otherwise, (not recommended).
///
public SafeHWINSTA(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
private SafeHWINSTA() : base()
{
}
/// Performs an implicit conversion from to .
/// The safe handle instance.
/// The result of the conversion.
public static implicit operator HWINSTA(SafeHWINSTA h) => h.handle;
///
protected override bool InternalReleaseHandle() => CloseWindowStation(this);
}
}
}