Compartilhamento de objetos nomeados

Este tópico explica como compartilhar objetos nomeados entre aplicativos de área de trabalho empacotados (incluindo SDK do Aplicativo Windows aplicativos empacotados com MSIX) e aplicativos Win32 não empacotados.

Objetos nomeados em aplicativos empacotados

Os objetos nomeados fornecem uma maneira fácil para os processos compartilharem identificadores de objeto. Depois que um processo tiver criado um objeto nomeado, outros processos poderão usar o nome para chamar a função apropriada para abrir um identificador para o objeto. Objetos nomeados geralmente são usados para sincronização de threads e comunicação entre processos.

Os aplicativos executados em um AppContainer (como aplicativos UWP) têm um namespace de objeto nomeado isolado por padrão: eles só podem acessar objetos nomeados que criaram. Aplicativos de área de trabalho empacotados com confiança total (incluindo aplicativos do SDK do Aplicativo Windows) não têm esse isolamento e criam objetos nomeados no espaço de nomes global. Consulte SDK do Aplicativo Windows considerações para obter detalhes.

Para compartilhar objetos nomeados com aplicativos AppContainer, as permissões devem ser definidas quando os objetos são criados e os nomes devem ser qualificados quando os objetos são abertos. As técnicas neste artigo também são úteis quando você deseja restringir o acesso entre todos os processos, independentemente do empacotamento.

Criando objetos nomeados

Os objetos nomeados são criados com uma API correspondente Create :

Todas essas APIs compartilham um LPSECURITY_ATTRIBUTES parâmetro que permite ao chamador especificar ACLs (listas de controle de acesso) para controlar quais processos podem acessar o objeto. Para compartilhar objetos nomeados com aplicativos empacotados, a permissão deve ser concedida nas ACLs quando os objetos nomeados são criados.

SIDs (identificadores de segurança) representam identidades nas ACLs. Cada aplicativo empacotado tem seu próprio SID com base no nome da família de pacotes. Você pode gerar o SID para um aplicativo empacotado passando o nome da família de pacotes para DeriveAppContainerSidFromAppContainerName.

Note

O nome da família de pacotes pode ser encontrado por meio do editor de manifesto do pacote em Visual Studio durante o tempo de desenvolvimento, por meio do Partner Center para aplicativos publicados por meio do Microsoft Store ou por meio do comando Get-AppxPackage PowerShell para aplicativos que já estão instalados.

Este exemplo demonstra o padrão básico necessário para ACL de um objeto nomeado. Para compartilhar objetos nomeados com aplicativos empacotados, crie uma estrutura EXPLICIT_ACCESS para cada aplicativo:

Ao preencher o parâmetro LPSECURITY_ATTRIBUTES nas chamadas Create com regras EXPLICIT_ACCESS para aplicativos empacotados, você pode conceder a esses aplicativos acesso para abrir o objeto nomeado.

Note

Aplicativos Win32 podem acessar objetos nomeados criados por aplicativos AppContainer qualificando os nomes de objeto ao abri-los, desde que a DACL do objeto permita o acesso. A DACL padrão para a maioria dos objetos nomeados concede acesso ao criador e aos administradores. Se você definiu uma DACL restritiva, os chamadores do Win32 também precisarão de uma entrada de acesso explícita.

Exemplo: criando um evento nomeado com ACL (C++)

O exemplo a seguir mostra como criar um evento nomeado e conceder acesso a um aplicativo empacotado:

#include <windows.h>
#include <sddl.h>
#include <aclapi.h>
#include <userenv.h>

HANDLE CreateSharedEvent(PCWSTR eventName, PCWSTR packageFamilyName)
{
    // Derive the SID for the target packaged application
    PSID appContainerSid = nullptr;
    HRESULT hr = DeriveAppContainerSidFromAppContainerName(
        packageFamilyName, &appContainerSid);
    if (FAILED(hr)) return nullptr;

    // Build an EXPLICIT_ACCESS entry granting synchronization and signal rights
    EXPLICIT_ACCESS_W explicitAccess = {};
    explicitAccess.grfAccessPermissions = SYNCHRONIZE | EVENT_MODIFY_STATE;
    explicitAccess.grfAccessMode = GRANT_ACCESS;
    explicitAccess.grfInheritance = NO_INHERITANCE;
    explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_USER;
    explicitAccess.Trustee.ptstrName = reinterpret_cast<LPWSTR>(appContainerSid);

    // Create the ACL
    PACL acl = nullptr;
    DWORD result = SetEntriesInAclW(1, &explicitAccess, nullptr, &acl);
    if (result != ERROR_SUCCESS)
    {
        FreeSid(appContainerSid);
        return nullptr;
    }

    // Create the security descriptor
    SECURITY_DESCRIPTOR sd = {};
    if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ||
        !SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE))
    {
        LocalFree(acl);
        FreeSid(appContainerSid);
        return nullptr;
    }

    SECURITY_ATTRIBUTES sa = {};
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = &sd;
    sa.bInheritHandle = FALSE;

    // Create the named event with only the rights the creator needs
    HANDLE hEvent = CreateEventExW(&sa, eventName, 0,
        SYNCHRONIZE | EVENT_MODIFY_STATE);

    // Cleanup
    LocalFree(acl);
    FreeSid(appContainerSid);

    return hEvent;
}

Abrindo objetos nomeados

Os objetos nomeados são abertos passando um nome para uma API correspondente Open :

Objetos nomeados criados por um aplicativo empacotado são criados dentro do namespace do aplicativo, também conhecido como o caminho do objeto nomeado. Ao abrir objetos nomeados criados por um aplicativo empacotado, os nomes dos objetos devem ser prefixados com o caminho de objeto nomeado do aplicativo de criação.

GetAppContainerNamedObjectPath retorna o caminho do objeto nomeado para um aplicativo empacotado com base em seu SID. Você pode gerar o SID para um aplicativo empacotado passando o nome da família de pacotes para DeriveAppContainerSidFromAppContainerName.

Note

O nome da família de pacotes pode ser encontrado por meio do editor de manifesto do pacote em Visual Studio durante o tempo de desenvolvimento, por meio do Partner Center para aplicativos publicados por meio do Microsoft Store ou por meio do comando Get-AppxPackage PowerShell para aplicativos que já estão instalados.

Ao abrir objetos nomeados criados por um aplicativo empacotado, use o formato <PATH>\<NAME>:

  • Substitua <PATH> pelo caminho de objeto nomeado do aplicativo de criação.
  • Substitua <NAME> pelo nome do objeto.

Note

A prefixação de nomes de objeto com <PATH> só será necessária se um aplicativo empacotado tiver criado o objeto. Objetos nomeados criados por aplicativos Win32 não precisam ser qualificados, embora o acesso ainda precise ser concedido quando os objetos forem criados.

Considerações sobre o SDK do Aplicativo do Windows

Os aplicativos da área de trabalho do SDK do Aplicativo Windows empacotados com MSIX são executados como processos de confiança total com identidade de pacote — eles não são executados em um AppContainer. Isso significa que seus objetos nomeados são criados no namespace global por padrão, assim como os aplicativos Win32 tradicionais.

No entanto, você ainda precisa dos procedimentos de ACL e de qualificação de caminho descritos acima nestes cenários:

  • Comunicação com um aplicativo UWP – aplicativos UWP são executados em um AppContainer e têm namespaces de objeto nomeado isolados. Use GetAppContainerNamedObjectPath e conceda acesso por meio de ACLs para acessar os objetos nomeados de um aplicativo UWP.
  • Restringir o acesso — mesmo entre aplicativos de confiança total, talvez você queira usar ACLs explícitas para limitar quais processos podem abrir seus objetos nomeados.
  • Aplicativos de SDK do Aplicativo Windows não empacotados — os objetos nomeados estão no namespace global sem necessidade de tratamento especial, idêntico aos aplicativos Win32 tradicionais.

Remarks

Objetos nomeados em aplicativos empacotados são isolados por padrão para preservar a segurança e garantir o suporte para eventos de ciclo de vida do aplicativo, como suspensão e encerramento. O compartilhamento de objetos nomeados entre aplicativos introduz restrições rígidas de acoplamento e de versionamento e exige que cada aplicativo seja capaz de lidar com o ciclo de vida dos demais. Por esses motivos, é recomendável compartilhar apenas objetos nomeados entre aplicativos do mesmo editor.