简体   繁体   English

UWP C# pipe 客户端连接Win32失败 C++ pipe 服务器

[英]UWP C# pipe client fails to connect to Win32 C++ pipe server

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.我正在尝试在客户端 UWP C# 应用程序和服务器 Win32 C++ 应用程序之间进行通信,这两个应用程序都在同一个 package 中,我正在使用 Win32 应用程序作为桌面扩展来为 UWP 应用程序提供附加功能。

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.文档中可以清楚地看到,在同一个 package 中的 UWP 应用程序之间名为 pipe 的通信,但不清楚在同一个 package 中的 UWP 和 Win32 应用程序。

The pipe created by UWP process with name \\\\.\\pipe\\Local\\PipeName is converted to \\\\.\\pipe\\Sessions\\<SessionId>\\AppContainerNamedObjects\\<AppContainerSid>\\PipeName . UWP进程创建的pipe名称为\\\\.\\pipe\\Local\\PipeName转换为\\\\.\\pipe\\Sessions\\<SessionId>\\AppContainerNamedObjects\\<AppContainerSid>\\PipeName I can use this to communicate between UWP as server and Win32 as client.我可以使用它在作为服务器的 UWP 和作为客户端的 Win32 之间进行通信。 But I can't do the reverse even after I set up the ACLs as done in the official RPC sample .但是即使我像在官方 RPC 示例中那样设置了 ACL 之后,我也无法执行相反的操作。 Instead of using custom capability I used DeriveAppContainerSidFromAppContainerName to to derive a SID from package family name.我没有使用自定义功能,而是使用DeriveAppContainerSidFromAppContainerName从 package 系列名称派生 SID。

My Win32 C++ server code looks like this:我的 Win32 C++ 服务器代码如下所示:

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:我的 UWP C# 客户端代码如下所示:

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."当我尝试从客户端连接时, "Access to the path is denied." error.错误。

I was able to get a version of this working-- a C# UWP app pipe client successfully connecting to a non-UWP C++ pipe server.我能够获得此工作的一个版本 - C# UWP 应用程序 pipe 客户端成功连接到非 UWP C++ pipe 服务器。 My setup is very similar to yours, but there are a few differences.我的设置与您的非常相似,但有一些差异。

  1. I did not have much luck at all using the C# version of connecting with the client.使用与客户端连接的 C# 版本时,我一点运气都没有。 I was successful with using CreateFileW .我成功使用了CreateFileW You can call this function inside of your C# by using an DllImport.您可以使用 DllImport 在 C# 内部调用此 function。
  2. My pipe names are slightly different.我的 pipe 名字略有不同。 My non-UWP program is what is making my pipe server, so I think I do not need to use the "Local" sub-path.我的非 UWP 程序正在构建我的 pipe 服务器,因此我认为我不需要使用“本地”子路径。 My server pipe path is: \\\\.\\pipe\\Pipe .我的服务器 pipe 路径是: \\\\.\\pipe\\Pipe My client pipe path is: \\.\pipe\\Pipe .我的客户端 pipe 路径是: \\.\pipe\\Pipe I was able to get a connection with these names.我能够与这些名字建立联系。
  3. In my own experience with using DeriveAppContainerSidFromAppContainerName , I could not seem to get the correct SID from it.根据我自己使用DeriveAppContainerSidFromAppContainerName的经验,我似乎无法从中获得正确的 SID。 I would get one back, but when I would compare it the SID from "CheckNetIsolation.exe LoopbackExempt -s" in Powershell, it was different.我会找回一个,但是当我将它与 Powershell 中“CheckNetIsolation.exe LoopbackExempt -s”的 SID 进行比较时,它是不同的。 Not sure why that is, but I hard-coded the correct SID and that worked.不知道为什么会这样,但我硬编码了正确的 SID 并且成功了。 Having the incorrect SID does result in an access denied error.拥有不正确的 SID 确实会导致访问被拒绝错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM