Предоставление общего доступа к именованным объектам

В этом разделе объясняется, как совместно использовать именованные объекты между упакованными классическими приложениями (включая Windows App SDK приложения, упакованные с помощью MSIX) и распакованными приложениями Win32.

Именованные объекты в упакованных приложениях

Именованные объекты предоставляют простой способ совместного использования дескрипторов объектов. После того как процесс создал именованный объект, другие процессы могут использовать это имя для вызова соответствующей функции, чтобы открыть дескриптор объекта. Именованные объекты обычно используются для синхронизации потоков и взаимодействия между процессами.

Приложения, которые выполняются в AppContainer (например, приложения UWP), имеют изолированное пространство имен именованных объектов по умолчанию— они могут получить доступ только к созданным именованным объектам. Упакованные классические настольные приложения с полным уровнем доверия (включая приложения Windows App SDK) не имеют этой изоляции и создают именованные объекты в глобальном пространстве имён. См. вопросы, связанные с Windows App SDK, для получения дополнительных сведений.

Для совместного использования именованных объектов с приложениями AppContainer необходимо задать разрешения при создании объектов, а имена должны быть квалифицированы при открытии объектов. Методы, описанные в этой статье, также полезны, если требуется ограничить доступ между любыми процессами, независимо от упаковки.

Создание именованных объектов

Именованные объекты создаются с помощью соответствующего Create API:

Все эти API предоставляют общий LPSECURITY_ATTRIBUTES доступ к параметру, который позволяет вызывающей программе указывать списки управления доступом (ACL) для управления доступом к объекту. Чтобы предоставить общий доступ к именованным объектам с упакованными приложениями, необходимо предоставить разрешение в списках управления доступом при создании именованных объектов.

Идентификаторы безопасности (SID) обозначают субъекты безопасности в списках управления доступом (ACL). У каждого упаковаемого приложения есть собственный идентификатор безопасности на основе имени семейства пакетов. SID для упакованного приложения можно сгенерировать, передав его имя семейства пакетов в DeriveAppContainerSidFromAppContainerName.

Note

Имя семейства пакетов можно найти с помощью редактора манифеста пакета в Visual Studio во время разработки, через Центр партнеров для приложений, опубликованных через Microsoft Store, или с помощью команды Get-AppxPackage PowerShell для уже установленных приложений.

В этом примере показан базовый шаблон, необходимый для ACL именованного объекта. Чтобы предоставить общий доступ к именованным объектам с упакованными приложениями, создайте структуру EXPLICIT_ACCESS для каждого приложения:

Заполняя LPSECURITY_ATTRIBUTES параметр в вызовах Create правилами упакованных EXPLICIT_ACCESS приложений, вы можете предоставить доступ к этим приложениям для открытия именованного объекта.

Note

Приложения Win32 могут получить доступ к именованным объектам, созданным приложениями AppContainer, задав имена объектов при открытии, если DACL объекта разрешает доступ. DaCL по умолчанию для большинства именованных объектов предоставляет доступ к создателю и администраторам. Если вы установили ограничение DACL, вызывающие Win32 также нуждаются в явной записи доступа.

Пример. Создание именованного события с помощью ACL (C++)

В следующем примере показано, как создать именованное событие и предоставить доступ к упаковаированному приложению:

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

Открытие именованных объектов

Именованные объекты открываются путем передачи имени соответствующему Open API:

Именованные объекты, созданные упакованным приложением, создаются в пространстве имен приложения, также известном как путь именованного объекта. При открытии именованных объектов, созданных упакованным приложением, к именам объектов необходимо добавлять в качестве префикса путь именованных объектов создающего приложения.

GetAppContainerNamedObjectPath возвращает путь к именованному объекту для упакованного приложения по его SID. SID для упакованного приложения можно сгенерировать, передав имя его семейства пакетов в DeriveAppContainerSidFromAppContainerName.

Note

Имя семейства пакетов можно найти с помощью редактора манифеста пакета в Visual Studio во время разработки, через Центр партнеров для приложений, опубликованных через Microsoft Store, или с помощью команды Get-AppxPackage PowerShell для уже установленных приложений.

При открытии именованных объектов, созданных упакованным приложением, используйте формат <PATH>\<NAME>:

  • Замените <PATH> на именованный путь к объекту для создания приложения.
  • Замените <NAME> именем объекта.

Note

Добавление префикса <PATH> к именам объектов требуется только в том случае, если этот объект был создан упакованным приложением. Именованные объекты, созданные приложениями Win32, не должны быть квалифицированы, хотя доступ по-прежнему должен предоставляться при создании объектов.

Рекомендации по пакету SDK для приложений Для Windows

Классические приложения Windows App SDK для настольных компьютеров, упакованные в MSIX, выполняются как процессы полного доверия с удостоверяющими данными пакета — они не работают в AppContainer. Это означает, что именованные объекты создаются в глобальном пространстве имен по умолчанию, как и традиционные приложения Win32.

Тем не менее, в следующих сценариях вам по-прежнему необходимо использовать описанные выше процедуры ACL и проверки пути:

  • Взаимодействие с приложением UWP — приложения UWP выполняются в AppContainer и имеют изолированные пространства имен для именованных объектов. Используйте GetAppContainerNamedObjectPath и предоставьте доступ через ACL для доступа к именованным объектам UWP-приложения.
  • Ограничение доступа — даже между приложениями с полным доверием может потребоваться использовать явные списки управления доступом, чтобы ограничить, какие процессы могут открывать именованные объекты.
  • Неупакованные приложения Windows App SDK — именованные объекты находятся в глобальном пространстве имён и не требуют специальной обработки, как и в традиционных приложениях Win32.

Remarks

Именованные объекты в упакованных приложениях по умолчанию изолированы для сохранения безопасности и обеспечения поддержки событий жизненного цикла приложения, таких как приостановка и завершение. Совместное использование именованных объектов в приложениях вводит жесткие ограничения привязки и управления версиями и требует, чтобы каждое приложение было устойчивым к жизненному циклу других пользователей. По этим причинам рекомендуется предоставлять общий доступ к именованным объектам только между приложениями одного и того же издателя.