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

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

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

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

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

保留自定义功能

首先,保留自定义功能:

  1. 通过电子邮件Microsoft硬件支持应用评审(HSAReview@microsoft.com),其中包含以下信息:

    • 联系信息

    • 公司名称

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

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

    • 任何安全或隐私问题

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

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

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

    • 功能提供哪些数据可以访问?

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

    • 包括Microsoft应用商店应用发布者 ID。 若要获取一个,请在“Microsoft应用商店”页上创建一个主干应用条目。 有关保留应用 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 签名序列摘要

下图总结了上述序列:

获取已签名的 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 应用

使用桌面应用转换器打包应用(桌面桥)

自定义功能示例应用

自定义功能驱动程序示例

Windows 10 中的旁加载应用

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