Closed totaam closed 4 years ago
Blocked by #1528.
With the cx_freeze 5 workarounds added in #1528#comment:2 and the service stub added in r15933 + r15934 (based on cx_Freeze samples: service), a "Xpra-Service.exe" is created - it just doesn't do anything when you run it... The documentation is non-existent, and the executable doesn't give you any help at all. But I eventually found that we're supposed to install it by running:
Xpra-Service.exe --install NAME [configfile]
Problem is that this fails with:
Service not installed. See log file for details.
What log file you ask? Well "./.log" obviously, NOT. This file contains:
[04380] 2017/05/23 22:46:14.473 starting logging at level ERROR
[04380] 2017/05/23 22:46:14.520 Win32 error 0x5 encountered.
[04380] 2017/05/23 22:46:14.520 Context: cannot open service manager
[04380] 2017/05/23 22:46:14.520 Message: Access is denied.
[04380] 2017/05/23 22:46:14.520 ending logging
Fine, let's run it as administrator:
[02964] 2017/05/23 22:49:55.695 starting logging at level ERROR
[02964] 2017/05/23 22:49:55.757 Win32 error 0x57 encountered.
[02964] 2017/05/23 22:49:55.757 Context: cannot start service
[02964] 2017/05/23 22:49:55.757 Message: The parameter is incorrect.
[02964] 2017/05/23 22:49:55.773 ending logging
At least the service is registered and visible in the "Services" control tool, and the same error message is available in the "eventvwr". We'll need to get rid of "cx_Logging", it's unmaintained since 2014, undocumented (which filename is used from the service?) and generally not helpful.
OK, the reason why this fails with the cryptic error 0x57 is because the path to the service binary is empty (for whatever reason). Assuming that the service has been installed using:
Xpra-Service.exe --install XPRA-TEST
The path can then be changed using regedit, or using Sc config. First query the service:
sc qc XpraXPRA-TEST
Change the path:
sc config XpraXPRA-TEST binPath= "C:\Program Files\Xpra\Xpra-Service.exe"
We can now also set it to auto-start:
sc config XpraXPRA-TEST start= auto
With these changes, starting the service takes longer to fail.. but fail it does with: Error 1053: The service did not respond to the start or control request in a timely fashion We can find the service PID with:
sc queryex XpraXPRA-TEST
Then kill it with:
taskkill /f /pid $PID
We could workaround the broken path installation by running the "sc config" commands after the service registration, still as part of the EXE / MSI installation process.
But the fact that the process does not respond is more problematic... Ideas:
Difficulties in building the Complete Service Example with mingw:
StringCchPrintf
with snprintf
, or better: add #undef __CRT__NO_INLINE
before #include <strsafe.h>
(maybe we should link against some lib instead?)g++ -o Svc.exe Svc.cpp -Wno-write-strings
__try
and __except
: msdn: try-except Statement, workaround is to not handle this at all...
#define __try
#define __finally
libgcc_s_dw2-1.dll
and libwinpthread-1.dll
service-mingw.patch
(2.7 KiB)patch for building the service example with mingw
Stub cx_freeze5 service removed in r15960 (#1528 re-scheduled), replaced in r15962 by a shim implemented in C.
Still TODO:
commonappdata
to locate the cert - or just generated the path in the config fileNotes:
C:\Windows\System32\config\systemprofile\AppData\Roaming\Xpra
start-shadow-from-proxy.patch
(8.1 KiB)ugly work in progress patch to use on top of r15971
logon.patch
(22.6 KiB)work in progress logon patch
The ugly and incomplete patch above does:
- GetCurrentProcess
- OpenProcessToken
- [GetTokenInformation](https:#### 2017-05-26 12:34:49: antoine commented
The ugly and incomplete patch above does:
And adds a small Login-Test.exe
utility. Problem is that this works when running from the service context, but not when running directly from the utility - even when running from an administrator shell. This is going to make development and testing tedious.
Some useful links:
And adds a small
Login-Test.exe
utility. Problem is that this works when running from the service context, but not when running directly from the utility - even when running from an administrator shell. This is going to make development and testing tedious.Some useful links:
logon-v2.patch
(50.2 KiB)logon succeeds but launching the new process does not..
With the patch above, I could logon but when trying to start the server, or even a test application like whoami.exe
with all of its dlls installed, the event log would show:
Application popup: Xpra_cmd.exe - Application Error : \
The application was unable to start correctly (0xc0000142). Click OK to close the application.
The environment looked suspicious, but since we use the LOGON_WITH_PROFILE
flag, it should be OK. (will need to re-check that)
See What is up with "The application failed to initialize properly (0xc0000142)" error?, which has lots of relevant information. (and some dead links too.. sigh)
Also some pointers here: The Perils and Pitfalls of Launching a Process Under New Credentials.
It was just missing the desktop name in the STARTUPINFO
.... (not obvious)
Now maybe we also need permission to access that desktop? As per CreateProcessAsUser() windowstations and desktops, because the resulting screen is empty.
r15980 adds all the hooks for starting the shadow process from the service. Still TODO:
C:\Windows\system32>netsh advfirewall firewall add rule name="Open Port 14500" d
ir=in action=allow protocol=TCP localport=14500
logon.py
(17.8 KiB)this implementation does not work - but has some useful functions
See #389 comment 23 for LogonUser
links.
See Another Windows 10 SKU is on its way, this time for remote desktops: With the new SKU, the multi-session capability is now a part of desktop Windows
See also: python-win32: runas analog: Starting a subprocess in Windows is somewhat of a black art, I fear.
Fixes and updates:
The service somehow fails to find the glib typelib. Debugging this is tedious, will add yet another shim to make it easier to debug.
The gi bindings error is an unrelated packaging blocker bug: #2393.
aUpdates:
CKCON_X11_DISPLAY
Some related pointers:
aUpdates:
Xpra\
prefix, assume named-pipe protocol on win32The shadow we start creates a named-pipe, but the proxy server running as "system" cannot connect to it. Some pointers:
Updates:
XPRA_NAMED_PIPE_UNRESTRICTED=1
With these changes, the proxy manages to start a shadow subprocess, but it doesn't seem to reach a usable state. Redirecting its output to a log file shows that it goes through server initialization, it stops after loading a few icons.
service-test.patch
(3.8 KiB)tweaks to make it easier to test and debug the service
logon.c
(18.9 KiB)logon.c example from "Starting an Interactive Client Process in C++"
We need to either shadow the console (so remote users can login from the login screen) or find a way to create a session programmatically.
More pointers:
Progress made using the openssh server (#2711): we can shadow the Winlogon secure desktop
using https://docs.microsoft.com/en-us/sysinternals/downloads/psexec
More pointers:
r25977 starts the shadow server on the Winlogon secure desktop
, it's more useful than the proxy it replaces since we can actually see the desktop.
To make more progress, it would be useful to:
Winlogon secure desktop
from real sessionsAs for the change of desktop, that's going to be harder. GTK probably can't be taught to re-initialize against the new display, so we would need to spawn a new process and either give it the existing socket connection, or proxy it.
r25980: we can now easily start new commands when connected to a shadow server
Maybe the blank display problems (comment:17 IIRC), can be fixed by using a SYSTEM
privilege, just like -s
with psexec, see #2711#comment:1.
Also: CreateProcessAsUser creates blank/black window: The call to LogonUser generates a new session (and associated logon SID) rather than reusing the existing one, so your process does not have access to the desktop, and only has minimal access to the window station
r26188 uses paexec (as per #2711) to start the shadow server.
Tested by reverting r25977 and then connecting to the proxy server using:
xpra shadow "ssl://user:password@server:14500/" --ssl-server-verify=none
Progress! This now allows the shadow server to access the GUI session, even though it is started from a SYSTEM account. But only if the user is already logged in.
If the user is not already logged in, the shadow command will just fail:
New ssl connection received
from 'CLIENTIP:44224'
on '0.0.0.0:14500'
Authentication required by win32 authenticator module 1
sending challenge for username 'windows 10 test' using xor digest
proxy_auth win32.get_sessions()=(0, 0, [], {}, {})
proxy_auth(Protocol(..), {..}, None) found sessions: (0, 0, [], {}, {})
proxy_session: displays=[], start_sessions=True, start-new-session={b'mode': b'shadow', b'display': b''}
start_new_session('windows 10 test', 0, 0, {b'mode': b'shadow', b'display': b''}, [])
start_win32_shadow('windows 10 test', {b'mode': b'shadow', b'display': b''})
exec_command('windows 10 test', ['paexec.exe', '-i', '1', '-s', 'C:\\Program Files\\Xpra\\Xpra-Shadow.exe', '--bind=windows_10_test', '-d', 'proxy,win32'], {..})
lsa_logon_user(..)
logon_msv1_s4u(windows 10 test)=..
creation_info=<xpra.platform.win32.create_process_lib.CREATIONINFO object at 0x0000000000c9ca40>
Popen(['paexec.exe', '-i', '1', '-s', 'C:\\Program Files\\Xpra\\Xpra-Shadow.exe', '--bind=windows_10_test', '-d', 'proxy,win32'])=<xpra.platform.win32.create_process_lib.Popen object at 0x0000000000ceb070>
poll()=4294967287
stdout=b''
stderr=b''
start_server_subprocess failed
Traceback (most recent call last):
File "E:\Xpra\trunk\src/xpra/server/proxy/proxy_server.py", line 349, in proxy_session
proc, socket_path, display = self.start_new_session(username, uid, gid, sns, displays)
File "C:\Program Files\Xpra\lib\xpra\platform\win32\proxy_server.py", line 49, in start_new_session
return self.start_win32_shadow(username, new_session_dict)
File "C:\Program Files\Xpra\lib\xpra\platform\win32\proxy_server.py", line 94, in start_win32_shadow
raise Exception("shadow subprocess failed with exit code %s" % r)
Exception: shadow subprocess failed with exit code 4294967287
Error: failed to start server subprocess:
shadow subprocess failed with exit code 4294967287
disconnect(server error, ('failed to start a new session',))
So we need some other call to create the GUI session. No idea which one.
Pointers:
creating window station and windows desktop using c#
Programmatically create and launch and RDP session (without gui)
All of those solutions use windows forms (GUI based), Creating a Remote Desktop Client Application without using Windows Forms (C#), How to use ActiveX component in ClassLibrary without Winforms.
To compile any of those C# based solutions, we need the AxMSTSCLib.dll
.
Where is the AxMSTSCLib library located? The answer (not found in that link) is actually here: SharpRDP: If you do not want to use the provided DLLs you will need to .NET SDK to create the AxMSTSCLib.dll DLL. To create it you'll need to run aximp from the SDK on mstscax.dll. %
To logoff once we're done: WTSLogoffSession function
Eventually, I would like to compile this DLL from the command line (Command-line build with csc.exe), as part of the build process.
Next difficulty: calling this dotnet code from the python server without using pythonnet since that's not supported under mingw.
Options:
Updates in r26196 + r26197 including the VS project to create the DesktopLogon.dll
.
Reverting r25977 should work, but paexec is now failing (was working fine before..)
The server log files can be located using xpra info | grep log-file
.
On my win10 test system, they end up in: C:\Windows\System32\config\systemprofile\AppData\Local\Xpra
.
(both the Xpra-Proxy.log
and Xpra-Shadow.log
)
win32-system-proxy.patch
(3.8 KiB)switch back to launching the proxy
With the patch above, the proxy tries to run:
paexec.exe -i 1 -s "C:\Program Files\Xpra\Xpra-Shadow.exe" --bind=Windows_10_Test -d win32,proxy
When trying this command from an ssh session, paexec now fails (used to work?!):
Remote app failed to start. Returned error:
Failed to start "C:\Program Files\Xpra\Xpra-Shadow.exe" --bind=Windows_10_Test -d win32,proxy. Access is denied. [Err=0x5, 5]
PAExec returning exit code -9
Then I also got File not found
- that one was completely misleading, nothing to do with the path, just the -i
argument needed a different session id!
sessions.py
(7.5 KiB)various ill-fated attempts to get the list of sessions
Sort of working after:
TODO:
Error: write connection \\.\pipe\Xpra\test reset
bytes or integer address expected instead of memoryview instance: 0
Logon
doesn't work? (doesn't run on the correct desktop?)xpra stop
to prevent zombies? (needs peercred, or a private socket)win32_proxy_service.py
to change settings (ie: debug), and rename to just "xpra service" since we can then configure "shadow" or "proxy" on demandOther APIs and projects which may still be useful:
Updates:
memoryview
xpra stop
commandNew weird bug: the service responds on boot (if auto-start is on), responds if started using the service manager when logged in, but it seems to die when a user logs out? (only if it had started a shadow server? even if that process is now gone.. maybe a SIGPIPE
?)
So the DesktopSession.dll
hack still doesn't work, but using rdesktop -i $USER -p $PASSWORD $IP
does what we need ... Just need to emulate it? Without actually showing anything via RDP, and without terminating the session... because disconnecting RDP stops our server receiving anything - the station / desktop are suspended? (logging in resumes the session!)
New links:
This will have to do for this release, follow up in #2756.
The proxy server does work and can start a shadow server for any user, but it is unable to create the station / desktop if one does not exist already..
Split from #389, similar to #1105 for Linux, we want to have a system wide service running even before the user logs in. Users can then trigger a login.
Some links already added in #389 comment 23.