I am trying to communicate between client UWP C# app and server Win32 C++ app, both apps are in same package and I am using the Win32 app as desktop extension to provide additional functionality to UWP app.
From the docs it is clear that named pipe communication between UWP apps in same package but it isn't clear about UWP and Win32 app in same package.
The pipe created by UWP process with name \\.\pipe\Local\PipeName
is converted to \\.\pipe\Sessions\<SessionId>\AppContainerNamedObjects\<AppContainerSid>\PipeName
. I can use this to communicate between UWP as server and Win32 as client. But I can't do the reverse even after I set up the ACLs as done in the official RPC sample. Instead of using custom capability I used DeriveAppContainerSidFromAppContainerName
to to derive a SID from package family name.
My Win32 C++ server code looks like this:
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
PSID everyoneSid = NULL;
PSID packageSid = NULL;
EXPLICIT_ACCESS ea[2] = {};
PACL acl = NULL;
SECURITY_DESCRIPTOR pipeSecurityDescriptor = {};
if (DeriveAppContainerSidFromAppContainerName(Package::Current().Id().FamilyName().c_str(), &packageSid) == S_OK &&
// Get the SID that represents 'everyone' (this doesn't include AppContainers)
AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid))
{
// Now create the Access Control List (ACL) for the Security descriptor
// Everyone GENERIC_ALL access
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfAccessPermissions = GENERIC_ALL;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = static_cast<LPWSTR>(everyoneSid);
// Package Family GENERIC_ALL access
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfAccessPermissions = GENERIC_ALL;
ea[1].grfInheritance = NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
ea[1].Trustee.ptstrName = static_cast<LPWSTR>(packageSid);
if (SetEntriesInAcl(ARRAYSIZE(ea), ea, NULL, &acl) != ERROR_SUCCESS &&
// Initialize an empty security descriptor
InitializeSecurityDescriptor(&pipeSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION) &&
// Assign the ACL to the security descriptor
SetSecurityDescriptorDacl(&pipeSecurityDescriptor, TRUE, acl, FALSE))
{
SECURITY_ATTRIBUTES pipeSecurityAttributes{ .nLength = sizeof(SECURITY_ATTRIBUTES), .lpSecurityDescriptor = &pipeSecurityDescriptor, .bInheritHandle = FALSE };
HANDLE hPipe = CreateNamedPipe(L"\\.\pipe\Sessions\<SessionId>\AppContainerNamedObjects\<AppContainerSid>\PipeName}", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_WAIT_FOREVER, &pipeSecurityAttributes);
if (hPipe)
{
ConnectNamedPipe(hPipe, NULL);
// Do something
}
}
}
if (everyoneSid) FreeSid(everyoneSid);
if (packageSid) FreeSid(packageSid);
if (acl) LocalFree(acl);
My UWP C# client code looks like this:
using (var client = new NamedPipeClientStream(".", "Local\PipeName", PipeDirection.InOut, PipeOptions.Asynchronous))
{
await client.ConnectAsync();
// Do something
}
When I am trying to connect from client I am getting "Access to the path is denied."
error.