簡體   English   中英

UWP C# pipe 客戶端連接Win32失敗 C++ pipe 服務器

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

我正在嘗試在客戶端 UWP C# 應用程序和服務器 Win32 C++ 應用程序之間進行通信,這兩個應用程序都在同一個 package 中,我正在使用 Win32 應用程序作為桌面擴展來為 UWP 應用程序提供附加功能。

文檔中可以清楚地看到,在同一個 package 中的 UWP 應用程序之間名為 pipe 的通信,但不清楚在同一個 package 中的 UWP 和 Win32 應用程序。

UWP進程創建的pipe名稱為\\\\.\\pipe\\Local\\PipeName轉換為\\\\.\\pipe\\Sessions\\<SessionId>\\AppContainerNamedObjects\\<AppContainerSid>\\PipeName 我可以使用它在作為服務器的 UWP 和作為客戶端的 Win32 之間進行通信。 但是即使我像在官方 RPC 示例中那樣設置了 ACL 之后,我也無法執行相反的操作。 我沒有使用自定義功能,而是使用DeriveAppContainerSidFromAppContainerName從 package 系列名稱派生 SID。

我的 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);

我的 UWP C# 客戶端代碼如下所示:

using (var client = new NamedPipeClientStream(".", "Local\\PipeName", PipeDirection.InOut, PipeOptions.Asynchronous))
        {
            await client.ConnectAsync();
            // Do something
        }

當我嘗試從客戶端連接時, "Access to the path is denied." 錯誤。

我能夠獲得此工作的一個版本 - C# UWP 應用程序 pipe 客戶端成功連接到非 UWP C++ pipe 服務器。 我的設置與您的非常相似,但有一些差異。

  1. 使用與客戶端連接的 C# 版本時,我一點運氣都沒有。 我成功使用了CreateFileW 您可以使用 DllImport 在 C# 內部調用此 function。
  2. 我的 pipe 名字略有不同。 我的非 UWP 程序正在構建我的 pipe 服務器,因此我認為我不需要使用“本地”子路徑。 我的服務器 pipe 路徑是: \\\\.\\pipe\\Pipe 我的客戶端 pipe 路徑是: \\.\pipe\\Pipe 我能夠與這些名字建立聯系。
  3. 根據我自己使用DeriveAppContainerSidFromAppContainerName的經驗,我似乎無法從中獲得正確的 SID。 我會找回一個,但是當我將它與 Powershell 中“CheckNetIsolation.exe LoopbackExempt -s”的 SID 進行比較時,它是不同的。 不知道為什么會這樣,但我硬編碼了正確的 SID 並且成功了。 擁有不正確的 SID 確實會導致訪問被拒絕錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM