Compartilhando objetos nomeados

Este tópico explica como partilhar objetos nomeados entre aplicações de ambiente de trabalho empacotadas (incluindo aplicações do SDK de Aplicações Windows empacotadas com MSIX) e aplicações Win32 não empacotadas.

Objetos nomeados em aplicações em pacote

Os objetos nomeados fornecem uma forma fácil para os processos partilharem handles de objetos. Depois de um processo ter criado um objeto nomeado, outros processos podem usar o nome para chamar a função apropriada para abrir um identificador para o objeto. Os objetos nomeados são comumente usados para sincronização de threads e comunicação entre processos.

As aplicações que correm num AppContainer (como aplicações UWP) têm por defeito um espaço de nomes isolado com objetos nomeados — só podem aceder a objetos nomeados que criaram. As aplicações de ambiente de trabalho empacotadas com total confiança (incluindo aplicações do SDK de Aplicações Windows) não têm este isolamento e criam objetos nomeados no namespace global. Consulte as considerações do SDK de Aplicações Windows para mais detalhes.

Para partilhar objetos nomeados com aplicações 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 deste artigo também são úteis quando pretende restringir o acesso entre quaisquer processos, independentemente da embalagem.

Criação de objetos nomeados

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

Todas estas APIs partilham um LPSECURITY_ATTRIBUTES parâmetro que permite ao chamador especificar listas de controlo de acesso (ACLs) para controlar que processos podem aceder ao objeto. Para partilhar objetos nomeados com aplicações empacotadas, deve ser concedida permissão dentro das ACLs quando os objetos nomeados são criados.

Os identificadores de segurança (SIDs) representam identidades dentro das ACLs. Cada aplicação empacotada tem o seu próprio SID baseado no nome da sua família de pacotes. Pode gerar o SID para uma aplicação empacotada ao passar o nome da família do pacote para DeriveAppContainerSidFromAppContainerName.

Note

O nome da família do pacote pode ser encontrado através do editor de manifestos do pacote no Visual Studio durante o período de desenvolvimento, através do Partner Center para aplicações publicadas na Microsoft Store, ou através do comando PowerShell Get-AppxPackage para aplicações já instaladas.

Este exemplo demonstra o padrão básico necessário para ACL um objeto nomeado. Para partilhar objetos nomeados com aplicações empacotadas, construa uma estrutura EXPLICIT_ACCESS para cada aplicação:

Ao preencher o parâmetro LPSECURITY_ATTRIBUTES nas chamadas a Create com regras EXPLICIT_ACCESS para aplicações empacotadas, pode conceder a essas aplicações acesso para abrirem o objeto nomeado.

Note

As aplicações Win32 podem aceder a objetos nomeados criados pelas aplicações AppContainer qualificando os nomes dos objetos ao abri-los, desde que o DACL do objeto permita o acesso. O DACL padrão para a maioria dos objetos nomeados concede acesso ao criador e aos administradores. Se definiu um DACL restritivo, os chamadores Win32 também precisam de uma entrada de acesso explícita.

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

O exemplo seguinte mostra como criar um evento nomeado e conceder acesso a uma aplicação empacotada:

#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;
}

Abrir objetos nomeados

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

Os objetos nomeados criados por uma aplicação empacotada são criados dentro do namespace da aplicação, também conhecido como caminho do objeto nomeado. Ao abrir objetos nomeados criados por uma aplicação empacotada, os nomes dos objetos devem ser prefixados com o caminho nomeado do objeto da aplicação criadora.

GetAppContainerNamedObjectPath devolve o caminho do objeto nomeado para uma aplicação empacotada com base no seu SID. Pode gerar o SID para uma aplicação incluída num pacote ao passar o nome da família do pacote para DeriveAppContainerSidFromAppContainerName.

Note

O nome da família do pacote pode ser encontrado através do editor de manifestos do pacote no Visual Studio durante o período de desenvolvimento, através do Partner Center para aplicações publicadas na Microsoft Store, ou através do comando PowerShell Get-AppxPackage para aplicações já instaladas.

Ao abrir objetos nomeados criados por uma aplicação empacotada, use o formato <PATH>\<NAME>:

  • Substitua <PATH> pelo caminho do objeto com nome da aplicação de criação.
  • Substitui <NAME> pelo nome do objeto.

Note

Prefixar os nomes dos objetos com <PATH> só é necessário se uma aplicação empacotada criou o objeto. Os objetos nomeados criados por aplicações Win32 não precisam de ser qualificados, embora o acesso tenha de ser concedido quando os objetos são criados.

Considerações sobre o SDK de aplicações Windows

As aplicações de ambiente de trabalho do SDK de Aplicações Windows embaladas com MSIX funcionam como processos de confiança total com identidade de pacote — não correm num AppContainer. Isto significa que os seus objetos nomeados são criados no espaço de nomes global por defeito, tal como as aplicações Win32 tradicionais.

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

  • Comunicação com uma aplicação UWP — As aplicações UWP correm num AppContainer e possuem espaços de nomes isolados com objetos nomeados. Use GetAppContainerNamedObjectPath e conceda acesso através de ACLs para aceder aos objetos nomeados de uma aplicação UWP.
  • Restrição de acesso — Mesmo entre aplicações de confiança total, pode querer usar ACLs explícitas para limitar que processos podem abrir os seus objetos nomeados.
  • Aplicações SDK de Aplicações Windows não empacotadas — Os objetos nomeados estão no espaço global sem necessidade de tratamento especial, idênticos às aplicações Win32 tradicionais.

Remarks

Os objetos nomeados em aplicações empacotadas são isolados por predefinição para preservar a segurança e garantir o suporte para eventos do ciclo de vida da aplicação, como a suspensão e a terminação. Partilhar objetos nomeados entre aplicações introduz restrições apertadas de binding e versionamento e exige que cada aplicação seja resiliente ao ciclo de vida das outras. Por estas razões, recomenda-se partilhar apenas objetos nomeados entre aplicações do mesmo editor.