硬件支持应用 (HSA):驱动程序开发人员的步骤

硬件支持应用 (HSA) 是与特定驱动程序或 RPC(远程过程调用)终结点配对的设备特定应用。

若要将 Store 应用与驱动程序相关联,请首先保留一个名为自定义功能的特殊值。 然后,允许访问播发功能并向应用开发人员提供功能的应用。 本页面介绍这些驱动程序开发人员步骤。

应用开发人员步骤在硬件支持应用 (HSA):应用开发人员步骤中介绍。

HSA 是三项“DCH”设计原则之一。

保留自定义功能

首先,保留自定义功能:

  1. 给 Microsoft 硬件支持应用审核 (HSAReview@microsoft.com) 团队发送电子邮件,其中包含以下信息:

    • 联系信息

    • 公司名称

    • 功能的名称(必须唯一并引用所有者)

    • 功能需要访问哪些资源?

    • 任何安全或隐私问题

    • 将为合作伙伴处理哪些数据事件?

      • 事件是否包括个人标识符,例如精确的用户位置、密码、IP 地址、PUID、设备 ID、CID、用户名和联系人数据?

      • 数据事件是保留在用户设备上,还是发送给合作伙伴?

    • 功能提供哪些数据的访问权限?

    • 此功能的最终用户有何好处?

    • 包括 Microsoft Store 应用发布者 ID。 若要获取一个,请在 Microsoft Store 页面上创建一条主干应用条目。 有关保留应用 PFN 的详细信息,请参阅通过保留名称创建应用

  2. 如果请求获得批准,Microsoft 会通过电子邮件返回采用 CompanyName.capabilityName_PublisherID 的唯一自定义功能字符串名称。

现在,可以使用自定义功能允许访问 RPC 终结点或驱动程序。

允许使用自定义功能访问 UWP 应用的 RPC 终结点

若要允许访问具有自定义功能的 UWP 应用的 RPC 终结点,请执行以下步骤:

  1. 调用 DeriveCapabilitySidsFromName 将自定义功能名称转换为安全 ID (SID)。

  2. 将 SID 添加到允许访问的 ACE 以及 RPC 终结点安全描述符所需的任何其他 SID。

  3. 使用安全描述符中的信息创建 RPC 终结点。

可以在“自定义功能示例”中的“RPC 服务器代码”中看到上述实现。

允许使用自定义功能访问 UWP 应用的驱动程序

若要允许使用自定义功能访问 UWP 应用的驱动程序,请将数行添加到 INF 文件或驱动程序源。

在 INF 文件中,指定自定义功能,具体如下:

[WDMPNPB003_Device.NT.Interfaces]
AddInterface= {zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz},,AddInterfaceSection

[AddInterfaceSection]
AddProperty= AddInterfaceSection.AddProps

[AddInterfaceSection.AddProps]
; DEVPKEY_DeviceInterface_UnrestrictedAppCapabilities
{026e516e-b814-414b-83cd-856d6fef4822}, 8, 0x2012,, "CompanyName.myCustomCapabilityName_MyStorePubId"

或者,在驱动程序中执行以下操作:

WDF_DEVICE_INTERFACE_PROPERTY_DATA PropertyData = {};
WCHAR customCapabilities[] = L"CompanyName.myCustomCapabilityName_MyStorePubId\0";

WDF_DEVICE_INTERFACE_PROPERTY_DATA_INIT(
   &PropertyData,
   &m_VendorDefinedSubType,
   &DEVPKEY_DeviceInterface_UnrestrictedAppCapabilities);

Status = WdfDeviceAssignInterfaceProperty(
    m_FxDevice,
    &PropertyData,
    DEVPROP_TYPE_STRING_LIST,
    ARRAYSIZE(customCapabilities),
    reinterpret_cast<PVOID>(customCapabilities));

zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz 替换为要公开的接口的 GUID。 将 CompanyName 替换为公司名称,将 myCustomCapabilityName 替换为在公司内唯一的名称,将 MyStorePubId 替换为发布者商店 ID。

有关上面所示的驱动程序代码示例,请参阅适用于通用驱动程序的驱动程序包安装工具包

若要在内核模式下设置属性,请使用如下代码:

#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2)

//
// Adding Custom Capability:
//
// Adds a custom capability to device interface instance that allows a Windows
// Store device app to access this interface using Windows.Devices.Custom namespace.
// This capability can be defined either in INF or here as shown below. In order
// to define it from the INF, uncomment the section "OsrUsb Interface installation"
// from the INF and remove the block of code below.
//

static const wchar_t customCapabilities[] = L"microsoft.hsaTestCustomCapability_q536wpkpf5cy2\0";

status = g_pIoSetDeviceInterfacePropertyData(&symbolicLinkName,
                                              &DEVPKEY_DeviceInterface_UnrestrictedAppCapabilities,
                                              0,
                                              0,
                                              DEVPROP_TYPE_STRING_LIST,
                                              sizeof(customCapabilities),
                                              (PVOID)&customCapabilities);

if (!NT_SUCCESS(status)) {
    TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "IoSetDeviceInterfacePropertyData failed to set custom capability property  %!STATUS!\n", status);
    goto Error;
}

#endif

准备已签名自定义功能描述符 (SCCD) 文件

已签名自定义功能描述符 (SCCD) 文件是一个已签名的 XML 文件,用于授权使用一个或多个自定义功能。 通过提供此文件,驱动程序或 RPC 终结点的所有者可向应用开发人员授予自定义功能。

若要准备 SCCD 文件,请先更新自定义功能字符串。 使用以下示例作为起点:

<?xml version="1.0" encoding="utf-8"?>
<CustomCapabilityDescriptor xmlns="http://schemas.microsoft.com/appx/2016/sccd" xmlns:s="http://schemas.microsoft.com/appx/2016/sccd">
<CustomCapabilities>
    <CustomCapability Name="microsoft.hsaTestCustomCapability_q536wpkpf5cy2"></CustomCapability>
</CustomCapabilities>
<AuthorizedEntities>
    <AuthorizedEntity AppPackageFamilyName="MicrosoftHSATest.Microsoft.SDKSamples.Hsa.CPP_q536wpkpf5cy2" CertificateSignatureHash="ca9fc964db7e0c2938778f4559946833e7a8cfde0f3eaa07650766d4764e86c4"></AuthorizedEntity>
</AuthorizedEntities>
<Catalog>0000</Catalog>
</CustomCapabilityDescriptor>

接下来,自定义功能所有者从应用开发人员处获取包系列名称 (PFN) 和签名哈希,并在 SCCD 文件中更新这些字符串。

注意

不必直接使用证书对应用进行签名,但指定的证书必须是对应用进行签名的证书链的一部分。

完成 SCCD 后,功能所有者会通过电子邮件将其发送给 Microsoft 进行签名。 Microsoft 将已签名的 SCCD 返回给功能所有者。

然后,功能所有者将 SCCD 发送给应用开发人员。 应用开发人员将已签名的 SCCD 包含在应用清单中。 若要了解应用开发人员需要执行的操作,请参阅硬件支持应用 (HSA):应用开发人员步骤

限制 SCCD 的范围

出于测试目的,自定义功能所有者可以将硬件支持应用的安装限制为处于开发人员模式的计算机。

为此,在 Microsoft 对 SCCD 进行签名之前,添加 DeveloperModeOnly

<?xml version="1.0" encoding="utf-8"?>
<CustomCapabilityDescriptor xmlns="http://schemas.microsoft.com/appx/2016/sccd" xmlns:s="http://schemas.microsoft.com/appx/2016/sccd">
<CustomCapabilities>
    <CustomCapability Name="microsoft.hsaTestCustomCapability_q536wpkpf5cy2"></CustomCapability>
</CustomCapabilities>
<AuthorizedEntities>
    <AuthorizedEntity AppPackageFamilyName="MicrosoftHSATest.Microsoft.SDKSamples.Hsa.CPP_q536wpkpf5cy2" CertificateSignatureHash="ca9fc964db7e0c2938778f4559946833e7a8cfde0f3eaa07650766d4764e86c4"></AuthorizedEntity>
</AuthorizedEntities>
<Catalog>0000</Catalog>
<DeveloperModeOnly Value="true" />
</CustomCapabilityDescriptor>

生成的已签名 SCCD 仅适用于处于开发人员模式的设备。

允许任何应用使用自定义功能

建议指定可以使用自定义功能的授权实体(应用)。 但在某些情况下,可能希望允许任何应用包含 SCCD。 从 Windows 10 版本 1809 开始,可以通过将 AllowAny 添加到 AuthorizedEntities 元素来执行此操作。 由于最佳做法是在 SCCD 文件中声明授权实体,因此请在提交要由 Microsoft 进行签名的 SCCD 时,提供使用 AllowAny 的理由。

<?xml version="1.0" encoding="utf-8"?>
<CustomCapabilityDescriptor xmlns="http://schemas.microsoft.com/appx/2018/sccd" xmlns:s="http://schemas.microsoft.com/appx/2018/sccd">
<CustomCapabilities>
    <CustomCapability Name="microsoft.hsaTestCustomCapability_q536wpkpf5cy2"></CustomCapability>
</CustomCapabilities>
<AuthorizedEntities AllowAny="true"/>
<Catalog>0000</Catalog>
</CustomCapabilityDescriptor>

生成的已签名 SCCD 将在任何应用包中验证。

多个 SCCD

从 Windows 10 版本 1803 开始,应用可以从一个或多个 SCCD 文件声明自定义功能。 将 SCCD 文件放在应用包的根目录中。

SCCD XML 架构

下面是 SCCD 文件的正式 XML XSD 架构。 在提交 SCCD 以供审核之前,使用此架构验证 SCCD。 有关使用 IntelliSense 导入架构和进行验证的信息,请参阅架构缓存XML 文档验证

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
  xmlns:xs="https://www.w3.org/2001/XMLSchema"
  targetNamespace="http://schemas.microsoft.com/appx/2016/sccd"
  xmlns:s="http://schemas.microsoft.com/appx/2016/sccd"
  xmlns="http://schemas.microsoft.com/appx/2016/sccd">

  <xs:element name="CustomCapabilityDescriptor" type="CT_CustomCapabilityDescriptor">
    <xs:unique name="Unique_CustomCapability_Name">
      <xs:selector xpath="s:CustomCapabilities/s:CustomCapability"/>
      <xs:field xpath="@Name"/>
    </xs:unique>
  </xs:element>

  <xs:complexType name="CT_CustomCapabilityDescriptor">
    <xs:sequence>
      <xs:element ref="CustomCapabilities" minOccurs="1" maxOccurs="1"/>
      <xs:element ref="AuthorizedEntities" minOccurs="1" maxOccurs="1"/>
      <xs:element ref="DeveloperModeOnly" minOccurs="0" maxOccurs="1"/>
      <xs:element ref="Catalog" minOccurs="1" maxOccurs="1"/>
      <xs:any minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="CustomCapabilities" type="CT_CustomCapabilities" />

  <xs:complexType name="CT_CustomCapabilities">
    <xs:sequence>
      <xs:element ref="CustomCapability" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="CustomCapability">
    <xs:complexType>
      <xs:attribute name="Name" type="ST_CustomCapability" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name="ST_NonEmptyString">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="32767"/>
      <xs:pattern value="[^\s]|([^\s].*[^\s])"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="ST_CustomCapability">
    <xs:annotation>
      <xs:documentation>Custom capabilities should be a string in the form of Company.capabilityName_PublisherId</xs:documentation>
    </xs:annotation>
    <xs:restriction base="ST_NonEmptyString">
      <xs:pattern value="[A-Za-z0-9][-_.A-Za-z0-9]*_[a-hjkmnp-z0-9]{13}"/>
      <xs:minLength value="15"/>
      <xs:maxLength value="255"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="AuthorizedEntities" type="CT_AuthorizedEntities" />

  <xs:complexType name="CT_AuthorizedEntities">
    <xs:sequence>
      <xs:element ref="AuthorizedEntity" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="AuthorizedEntity" type="CT_AuthorizedEntity" />

  <xs:complexType name="CT_AuthorizedEntity">
    <xs:attribute name="CertificateSignatureHash" type="ST_CertificateSignatureHash" use="required"/>
    <xs:attribute name="AppPackageFamilyName" type="ST_NonEmptyString" use="required"/>
  </xs:complexType>

  <xs:simpleType name="ST_CertificateSignatureHash">
    <xs:restriction base="ST_NonEmptyString">
      <xs:pattern value="[A-Fa-f0-9]+"/>
      <xs:minLength value="64"/>
      <xs:maxLength value="64"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="DeveloperModeOnly">
    <xs:complexType>
      <xs:attribute name="Value" type="xs:boolean" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="Catalog" type="ST_Catalog" />

  <xs:simpleType name="ST_Catalog">
    <xs:restriction base="xs:string">
      <xs:pattern value="[A-Za-z0-9\+\/\=]+"/>
      <xs:minLength value="4"/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

从 Windows 10 版本 1809 开始,以下架构也有效。 该架构使 SCCD 能够将任何应用包声明为授权实体。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
  xmlns:xs="https://www.w3.org/2001/XMLSchema"
  targetNamespace="http://schemas.microsoft.com/appx/2018/sccd"
  xmlns:s="http://schemas.microsoft.com/appx/2018/sccd"
  xmlns="http://schemas.microsoft.com/appx/2018/sccd">

  <xs:element name="CustomCapabilityDescriptor" type="CT_CustomCapabilityDescriptor">
    <xs:unique name="Unique_CustomCapability_Name">
      <xs:selector xpath="s:CustomCapabilities/s:CustomCapability"/>
      <xs:field xpath="@Name"/>
    </xs:unique>
  </xs:element>

  <xs:complexType name="CT_CustomCapabilityDescriptor">
    <xs:sequence>
      <xs:element ref="CustomCapabilities" minOccurs="1" maxOccurs="1"/>
      <xs:element ref="AuthorizedEntities" minOccurs="1" maxOccurs="1"/>
      <xs:element ref="DeveloperModeOnly" minOccurs="0" maxOccurs="1"/>
      <xs:element ref="Catalog" minOccurs="1" maxOccurs="1"/>
      <xs:any minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
  
  <xs:element name="CustomCapabilities" type="CT_CustomCapabilities" />

  <xs:complexType name="CT_CustomCapabilities">
    <xs:sequence>
      <xs:element ref="CustomCapability" minOccurs="1" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="CustomCapability">
    <xs:complexType>
      <xs:attribute name="Name" type="ST_CustomCapability" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name="ST_NonEmptyString">
    <xs:restriction base="xs:string">
      <xs:minLength value="1"/>
      <xs:maxLength value="32767"/>
      <xs:pattern value="[^\s]|([^\s].*[^\s])"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="ST_CustomCapability">
    <xs:annotation>
      <xs:documentation>Custom capabilities should be a string in the form of Company.capabilityName_PublisherId</xs:documentation>
    </xs:annotation>
    <xs:restriction base="ST_NonEmptyString">
      <xs:pattern value="[A-Za-z0-9][-_.A-Za-z0-9]*_[a-hjkmnp-z0-9]{13}"/>
      <xs:minLength value="15"/>
      <xs:maxLength value="255"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="AuthorizedEntities" type="CT_AuthorizedEntities" />

  <xs:complexType name="CT_AuthorizedEntities">
    <xs:sequence>
      <xs:element ref="AuthorizedEntity" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="AllowAny" type="xs:boolean" use="optional"/>
  </xs:complexType>
  
  <xs:element name="AuthorizedEntity" type="CT_AuthorizedEntity" />
  
  <xs:complexType name="CT_AuthorizedEntity">
    <xs:attribute name="CertificateSignatureHash" type="ST_CertificateSignatureHash" use="required"/>
    <xs:attribute name="AppPackageFamilyName" type="ST_NonEmptyString" use="required"/>
  </xs:complexType>

  <xs:simpleType name="ST_CertificateSignatureHash">
    <xs:restriction base="ST_NonEmptyString">
      <xs:pattern value="[A-Fa-f0-9]+"/>
      <xs:minLength value="64"/>
      <xs:maxLength value="64"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="DeveloperModeOnly">
    <xs:complexType>
      <xs:attribute name="Value" type="xs:boolean" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="Catalog" type="ST_Catalog" />

  <xs:simpleType name="ST_Catalog">
    <xs:restriction base="xs:string">
      <xs:pattern value="[A-Za-z0-9\+\/\=]+"/>
      <xs:minLength value="4"/>
    </xs:restriction>
  </xs:simpleType>
  
</xs:schema>

另请参阅

Windows 驱动程序开发入门

通用 Windows 平台简介

通用 Windows 平台 (UWP)

应用功能

使用 Visual Studio 开发 UWP 应用

将驱动程序与通用 Windows 平台 (UWP) 应用配对

开发 UWP 应用

使用 Desktop App Converter 将应用打包(桌面桥)

自定义功能示例应用

自定义功能驱动程序示例

在 Windows 10 中旁加载应用

有关自定义功能的常见问题解答