microsoft / XboxGameBarSamples

Sample code for Xbox Game Bar Widgets
https://developer.microsoft.com/games/products/game-bar/
MIT License
145 stars 27 forks source link

NamedPipeClientStream.Connect throws IOException "This functionality is not supported in the context of an app container" #44

Open tarkim opened 4 years ago

tarkim commented 4 years ago

We'd like to communicate with our desktop app via named pipes. SDK docs mention named pipes in "Inter-process communication options" section along with RPC, so I expected this to work.

I don't have the actual Game Bar widget in the project yet, so far I only wanted to check whether pipes would work: basically this is blank UWP project with custom capability declared and SCCD added to it. I have followed Custom Capability sample (https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/CustomCapability), but instead of RPC server I create named pipe in desktop app: CreateNamedPipe + ConnectNamedPipe.

Whenever I call NamedPipeClientStream.Connect from UWP, it throws IOException with message "This functionality is not supported in the context of an app container", but on server side (desktop app) ConnectNamedPipe succeeds - it returns TRUE in synchronous mode.

The custom capability part seems to work fine, because if I remove custom capability declaration from appxmanifest, NamedPipeClientStream.Connect throws UnauthorizedAccessException instead.

I've tried 'byte' and 'message' pipe types on server side, result is always the same.

Are named pipes supported? If not, please update SDK docs to reflect this.

Windows 10, Version 1909 (18363.693).

vidager commented 4 years ago

Hi tarkim,

Yes, named pipes are supported. On 1903/09 using CreateFileFromApp to connect from a UWP app to a named pipe server will result in the error you're seeing. It is blocked from an API perspective not ACL security level. This API "block" has been lifted in OS 2004. However, you can still easily get this to work on 1903/09+ by just calling CreateFileW directly rather than CreateFileFromApp. To do this, add the following to the top of your pch.h file, replacing your existing include of windows.h (if you had one).

#undef WINAPI_FAMILY
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
#define NOMINMAX
#include <windows.h>

If you get compilation errors with some legacy desktop #defines, you can undef them as they're likely unused. Like this (right after the #include :

#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
#ifdef GetObject
#undef GetObject
#endif
#ifdef SendMessage
#undef SendMessage
#endif
#ifdef GetUserName
#undef GetUserName
#endif

We will update the documentation for named pipes to clarify this detail.

Also, yes the RPC sample we link leverages Custom Capabilities, but unless you really need them, we would recommend using the package SID method described in our documentation. It's much simpler. You can reuse all the code in the custom capability sample from the point where you'd acquire the SID of the custom cap. Instead of the custom cap SID, you'll be using your package SID. Everything else is the same.

vidager commented 4 years ago

For .NET code, we aren't sure of a solution yet. We can investigate.

tarkim commented 4 years ago

Hi Ben,

Indeed, CreateFileW and ReadFile/WriteFile work without any issues even on 1909.

Would be nice to have native .NET support, but this is more than enough to proceed with implementation.

Thank you so much.

vidager commented 4 years ago

Hi tarkim,

Glad the workaround is working for you. I reached out to some folks in Windows and the responses I've gotten so far seem to indicate no easy workaround for .NET. I believe the .NET named pipe class should work on Windows 2004, but that's not helpful when shipping a Game Bar widget on 1903+. It seems that Pinvoke is your best option here. I'm sorry we don't have a better solution for .NET named pipes ATM.

visionarylab commented 4 years ago

@vidager Can we have example if any .NET desktop app and Game Bar widget communication example, via RPC / DOM

All the above issues are simplified if you package your desktop app and include your Game Bar widget in the same package.

Actually i am kinda confusing of above. it is mean i just need to deploy via the same organization's package name? Any getting started example, we could working on. Even we cant deploy the Game Bar widget now, it could useful to let us testing this fantastic convenient feature on our own dev pc.

andrewpros commented 4 years ago

This really needs some examples, i need to connect to external win32 desktop app (not mine) that uses named pipes as api for any software that wants to use it, but i dont see a possible way. It is not created with UWP in mind.

I'm on win 10 x64 2004 and NamedPipeClientStream doesn't work, it throws UnauthorizedAccessException.

Do i still need the Custom Capability or SCCD?

Wasn't able to understand how to do either of that, but it look like the desktop app needs to be prepared to allow UWP access and that would make it impossible?

My widget is UWP .Net and it will not be published into store, it will be a local deploy for me and friends for now.

Does anyone have any example how to make it work or workaround?

tarkim commented 4 years ago

Server part must set corresponding access rights on pipe or RPC endpoint to allow your UWP app to connect to it.

In your case it seems you need to ask this Win32 app author to explicitly allow connection from your UWP app by adding its app SID to pipe's security descriptor.

Pretty like in the sample (https://github.com/microsoft/Windows-universal-samples/blob/master/Samples/CustomCapability/Service/Server/RpcServer.cpp#L135), but instead of custom capability one should use app SID here.

andrewpros commented 4 years ago

Ok, so let me get this straight, this Win32 app api via named pipe is open for everyone, i dont think the author would add support for just one UWP app SID, i mean its non logical, if u have an open api you want it to work for any app, right?

So the question remains, is it possible in any way to do it so ANY UWP app can connect to it? As this is what the author would implement for an open api.

Does UWP supports this functionality at all or not, the documentation is not clear.

But if it doesn't then what's left? A workaround to make your own mediator like app that connects to another WPF app that can connect to the end api, in wpf it just works, just pushing the commands thru middleman, but if it is possible then why make it so hard in the first place with UWP, i dont get it.

Any advise is welcome.

vidager commented 4 years ago

Hi andrewpros,

Yes, a Security Descriptor can specify that it allows access to all application packages. It is this SID: S-1-15-2-1. AKA ALL_APPLICATION_PACKAGES. The shorthand for the Security Descriptor string would be "AC". For AC to work you also need WD (Everyone), but sounds like that's already there on the server. SDDL example:

 "O:PSG:BUD:(A;;0x1F;;;WD)(A;;0x1F;;;AC)S:(ML;;NX;;;LW)"

But...this is highly discouraged for production. Just like apps on your phone, UWP store apps are sandboxed. By default they cannot communicate with other processes without going through OS sanctioned channels. This ensures the OS can provide proper security and privacy enforcement around apps on behalf of the user. e.g. If the user said the app can't access the microphone, but some process is sitting on the box that allows all apps to access microphone (perhaps through named pipes), there's a hole in the security/privacy model for the user, and user trust is broken/privacy violated/security compromised, etc.

Obviously this is a difficult task on Windows Desktop as desktop users can simply install desktop apps with installers from anywhere.

So for you and you friends, go for it. Whoever owns the win32 desktop npipe endpoint should proceed with caution before pushing that out for general availability.

Let me know if you have other questions!

Thanks, Ben

andrewpros commented 3 years ago

Its been a while...

Well, i do understand the security concerns, but as long as UWP and win32 desktop will live together, so long this security "measure" will not work and it will only create issues for devs, forcing them to do more work, but after all, they can make it work and this "feature" is just not more secure than the current win32 state where for example named pipes connections are available without any such limits.

The only real secure fix from MS without waiting 20 years would be to block it for all apps, be it uwp or win32 and add a middleman, a permission page in the system settings where the user can explicitly allow (default blocked) app to access other app services, being educated at the same time on that page that this is a security concern and to be sure what u are doing.

This way it solves all off the issues, users have control over their security and multiple app services/access and devs can just create software that works without limitation, but is need by the user to agree to it, everyone is happy and more secure at the same time, the user decides.

That said, this topic provided every useful data to me and i was able to make it work in both instances.

but i hoped i can make it without the mediator, its better that way

Anyway, thanks for help.