Hardware Support App (HSA): Steps for Driver Developers
Article
A Hardware Support App (HSA) is a device-specific app that is paired with a specific driver or RPC (Remote Procedure Call) endpoint.
To associate a Store app with a driver, first reserve a special value called a custom capability. Then permit access to apps that advertise the capability and provide the capability to the app developer. This page describes these steps for the driver developer.
Email Microsoft Hardware Support Apps Review (HSAReview@microsoft.com) with the following information:
Contact information
Company name
Name of the capability (must be unique and reference the owner)
What resources does capability need to access?
Any security or privacy concerns
What data events will be processed to the partner?
Would the events include personal identifiers such as precise user locations, passwords, IP address, PUID, device ID , CID, username and contact data)?
Do the data events stay on the users device, or is it sent to partner?
What data does your capability provide access to?
What is the benefit to the end user of this capability?
Include the Microsoft Store App Publisher ID. To get one, create a skeleton app entry on the Microsoft Store page. For more info on reserving your App PFN, see Create your app by reserving a name.
If the request is approved, Microsoft emails back a unique custom capability string name in the format CompanyName.capabilityName_PublisherID.
Now you can use the custom capability to allow access to either an RPC endpoint or a driver.
Allowing access to an RPC endpoint to a UWP app using the custom capability
To allow access to an RPC endpoint to a UWP app that has the custom capability, follow these steps:
Replace zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz with the GUID for the interface to expose. Replace CompanyName with your company name, myCustomCapabilityName with a name that is unique within your company, and MyStorePubId with your publisher store ID.
To set the property in kernel mode, use code like the following:
C++
#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.//staticconstwchar_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
Preparing the Signed Custom Capability Descriptor (SCCD) file
A Signed Custom Capability Descriptor (SCCD) file is a signed XML file authorizing the use of one or more custom capabilities. The owner of the driver or RPC endpoint grants the custom capability to the app developer by providing this file.
To prepare the SCCD file, first update the custom capability string. Use the following example as a starting point:
Next, the custom capability owner obtains the Package Family Name (PFN) and the signature hash from the app developer and updates those strings in the SCCD file.
Note
The app does not have to be signed directly with the certificate, but the specified certificate must be part of the cert chain that signs the app.
After completing the SCCD, the capability owner emails it to Microsoft for signing. Microsoft returns the signed SCCD to the capability owner.
The capability owner then sends the SCCD to the app developer. The app developer includes the signed SCCD in the app manifest. To learn what the app developer needs to do, see Hardware Support App (HSA): Steps for App Developers.
Limiting the scope of an SCCD
For testing purposes, a custom capability owner can restrict installation of a hardware support app to computers in developer mode.
To do so, before getting the SCCD signed by Microsoft, add DeveloperModeOnly:
The resulting signed SCCD works only on devices in Developer Mode.
Allowing any app to use a custom capability
We recommend specifying authorized entities (apps) that can use a custom capability. In some cases, however, you might want to permit any app to include an SCCD. Starting in Windows 10 version 1809, you can do this by adding AllowAny to the AuthorizedEntities element. Because the best practice is to declare authorized entities in the SCCD file, please provide a justification for using AllowAny when submitting your SCCD to be signed by Microsoft.
The resulting signed SCCD will validate in any app package.
Multiple SCCDs
Starting in Windows 10 version 1803, apps can declare custom capabilities from one or more SCCD files. Place the SCCD files in the root of the app package.
SCCD XML Schema
The following is the formal XML XSD schema for an SCCD file. Use this schema to validate your SCCD before submitting it for review. See Schema Cache and XML Document validation for info on importing a schema and validating with IntelliSense.
XML
<?xml version="1.0" encoding="UTF-8"?><xs:schemaattributeFormDefault="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:elementname="CustomCapabilityDescriptor"type="CT_CustomCapabilityDescriptor"><xs:uniquename="Unique_CustomCapability_Name"><xs:selectorxpath="s:CustomCapabilities/s:CustomCapability"/><xs:fieldxpath="@Name"/></xs:unique></xs:element><xs:complexTypename="CT_CustomCapabilityDescriptor"><xs:sequence><xs:elementref="CustomCapabilities"minOccurs="1"maxOccurs="1"/><xs:elementref="AuthorizedEntities"minOccurs="1"maxOccurs="1"/><xs:elementref="DeveloperModeOnly"minOccurs="0"maxOccurs="1"/><xs:elementref="Catalog"minOccurs="1"maxOccurs="1"/><xs:anyminOccurs="0"/></xs:sequence></xs:complexType><xs:elementname="CustomCapabilities"type="CT_CustomCapabilities" /><xs:complexTypename="CT_CustomCapabilities"><xs:sequence><xs:elementref="CustomCapability"minOccurs="1"maxOccurs="unbounded"/></xs:sequence></xs:complexType><xs:elementname="CustomCapability"><xs:complexType><xs:attributename="Name"type="ST_CustomCapability"use="required"/></xs:complexType></xs:element><xs:simpleTypename="ST_NonEmptyString"><xs:restrictionbase="xs:string"><xs:minLengthvalue="1"/><xs:maxLengthvalue="32767"/><xs:patternvalue="[^\s]|([^\s].*[^\s])"/></xs:restriction></xs:simpleType><xs:simpleTypename="ST_CustomCapability"><xs:annotation><xs:documentation>Custom capabilities should be a string in the form of Company.capabilityName_PublisherId</xs:documentation></xs:annotation><xs:restrictionbase="ST_NonEmptyString"><xs:patternvalue="[A-Za-z0-9][-_.A-Za-z0-9]*_[a-hjkmnp-z0-9]{13}"/><xs:minLengthvalue="15"/><xs:maxLengthvalue="255"/></xs:restriction></xs:simpleType><xs:elementname="AuthorizedEntities"type="CT_AuthorizedEntities" /><xs:complexTypename="CT_AuthorizedEntities"><xs:sequence><xs:elementref="AuthorizedEntity"minOccurs="1"maxOccurs="unbounded"/></xs:sequence></xs:complexType><xs:elementname="AuthorizedEntity"type="CT_AuthorizedEntity" /><xs:complexTypename="CT_AuthorizedEntity"><xs:attributename="CertificateSignatureHash"type="ST_CertificateSignatureHash"use="required"/><xs:attributename="AppPackageFamilyName"type="ST_NonEmptyString"use="required"/></xs:complexType><xs:simpleTypename="ST_CertificateSignatureHash"><xs:restrictionbase="ST_NonEmptyString"><xs:patternvalue="[A-Fa-f0-9]+"/><xs:minLengthvalue="64"/><xs:maxLengthvalue="64"/></xs:restriction></xs:simpleType><xs:elementname="DeveloperModeOnly"><xs:complexType><xs:attributename="Value"type="xs:boolean"use="required"/></xs:complexType></xs:element><xs:elementname="Catalog"type="ST_Catalog" /><xs:simpleTypename="ST_Catalog"><xs:restrictionbase="xs:string"><xs:patternvalue="[A-Za-z0-9\+\/\=]+"/><xs:minLengthvalue="4"/></xs:restriction></xs:simpleType></xs:schema>
The following schema is also valid as of Windows 10, version 1809. It enables a SCCD to declare any app package to be an authorized entity.
XML
<?xml version="1.0" encoding="UTF-8"?><xs:schemaattributeFormDefault="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:elementname="CustomCapabilityDescriptor"type="CT_CustomCapabilityDescriptor"><xs:uniquename="Unique_CustomCapability_Name"><xs:selectorxpath="s:CustomCapabilities/s:CustomCapability"/><xs:fieldxpath="@Name"/></xs:unique></xs:element><xs:complexTypename="CT_CustomCapabilityDescriptor"><xs:sequence><xs:elementref="CustomCapabilities"minOccurs="1"maxOccurs="1"/><xs:elementref="AuthorizedEntities"minOccurs="1"maxOccurs="1"/><xs:elementref="DeveloperModeOnly"minOccurs="0"maxOccurs="1"/><xs:elementref="Catalog"minOccurs="1"maxOccurs="1"/><xs:anyminOccurs="0"/></xs:sequence></xs:complexType><xs:elementname="CustomCapabilities"type="CT_CustomCapabilities" /><xs:complexTypename="CT_CustomCapabilities"><xs:sequence><xs:elementref="CustomCapability"minOccurs="1"maxOccurs="unbounded"/></xs:sequence></xs:complexType><xs:elementname="CustomCapability"><xs:complexType><xs:attributename="Name"type="ST_CustomCapability"use="required"/></xs:complexType></xs:element><xs:simpleTypename="ST_NonEmptyString"><xs:restrictionbase="xs:string"><xs:minLengthvalue="1"/><xs:maxLengthvalue="32767"/><xs:patternvalue="[^\s]|([^\s].*[^\s])"/></xs:restriction></xs:simpleType><xs:simpleTypename="ST_CustomCapability"><xs:annotation><xs:documentation>Custom capabilities should be a string in the form of Company.capabilityName_PublisherId</xs:documentation></xs:annotation><xs:restrictionbase="ST_NonEmptyString"><xs:patternvalue="[A-Za-z0-9][-_.A-Za-z0-9]*_[a-hjkmnp-z0-9]{13}"/><xs:minLengthvalue="15"/><xs:maxLengthvalue="255"/></xs:restriction></xs:simpleType><xs:elementname="AuthorizedEntities"type="CT_AuthorizedEntities" /><xs:complexTypename="CT_AuthorizedEntities"><xs:sequence><xs:elementref="AuthorizedEntity"minOccurs="0"maxOccurs="unbounded"/></xs:sequence><xs:attributename="AllowAny"type="xs:boolean"use="optional"/></xs:complexType><xs:elementname="AuthorizedEntity"type="CT_AuthorizedEntity" /><xs:complexTypename="CT_AuthorizedEntity"><xs:attributename="CertificateSignatureHash"type="ST_CertificateSignatureHash"use="required"/><xs:attributename="AppPackageFamilyName"type="ST_NonEmptyString"use="required"/></xs:complexType><xs:simpleTypename="ST_CertificateSignatureHash"><xs:restrictionbase="ST_NonEmptyString"><xs:patternvalue="[A-Fa-f0-9]+"/><xs:minLengthvalue="64"/><xs:maxLengthvalue="64"/></xs:restriction></xs:simpleType><xs:elementname="DeveloperModeOnly"><xs:complexType><xs:attributename="Value"type="xs:boolean"use="required"/></xs:complexType></xs:element><xs:elementname="Catalog"type="ST_Catalog" /><xs:simpleTypename="ST_Catalog"><xs:restrictionbase="xs:string"><xs:patternvalue="[A-Za-z0-9\+\/\=]+"/><xs:minLengthvalue="4"/></xs:restriction></xs:simpleType></xs:schema>