3

I enumerated the desktops on my system (I'm using SysInternals Desktops, so I knew I had extras) using:

EnumDesktops(Nothing, AddressOf EnumDesktopsProc, Nothing)

with these declarations:

Private Declare Auto Function EnumDesktops Lib "User32" (ByVal hWinSta As IntPtr, ByVal edp As EnumDesktopProc, ByVal lParam As IntPtr) As Boolean
Private Declare Auto Function OpenDesktop Lib "User32" (<MarshalAs(UnmanagedType.LPTStr)> ByVal DesktopName As String, ByVal dwFlags As Integer, <MarshalAs(UnmanagedType.Bool)>ByVal fInherit As Boolean, ByVal dwDesiredAccess As AccessMask) As DesktopHandle

Private desktopNames As New List(Of String)

Private Delegate Function EnumDesktopProc(<MarshalAs(UnmanagedType.LPTStr)>ByVal DesktopName As String, ByVal lParam As IntPtr) As Boolean

Private Function EnumDesktopsProc(
          ByVal DesktopName As String,
          ByVal lParam As IntPtr
        ) As Boolean

    desktopNames.Add(DesktopName)
    Return True
End Function

I retrieved:

"WinSta0"
"Service-0x0-3e7$"
"Service-0x0-3e4$"
"Service-0x0-3e5$"
"SAWinSta"
"__X78B95_89_IW"
"Service-0x0-119d1e$"
"Service-0x0-4e05f$"

And when I attempted to open them with:

OpenDesktop(DesktopName, 0, False, AccessMask.DESKTOP_ENUMERATE)

(where AccessMask is a big Enum duplicating the data here and here, and DesktopHandle is a SafeHandle)

they all return NULL (Nothing) and GetLastWin32Error returns 2 "The system cannot find the file specified.". Why?

I checked alternate declarations for OpenDesktop and different AccessMask values with no effect (except when the declaration was actually wrong). I note I could get a different error when adding a "path" to the DesktopName, specifically 161 "The specified path is invalid."

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101

1 Answers1

4

The documentation for EnumDesktops is at least misleading, if not wrong. Passing NULL (Nothing) as the first parameter is returning the desktops of the "Session 0" window station. You need to use the result from GetProcessWindowStation(). I.e. change the first line above to:

Private Declare Auto Function GetProcessWindowStation Lib "User32" () As IntPtr

EnumDesktops(GetProcessWindowStation(), AddressOf EnumDesktopsProc, Nothing)

(There is a user comment added to the EnumDesktops documentation but I missed it, so I thought others might too.)

Note the documentation for GetProcessWindowStation explicitly says it does not need closing, so it doesn't need wrapping in a SafeHandle.

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
  • With this EnumDesktops returns "s" and "D" for me. If I try to open them with OpenDesktop it returns a zero handle. Are those names valid desktop names or do I use OpenDesktop wrong? – Fox Jun 22 '20 at 09:20