welcome to my blog of various technical solutions, experiences and tutorials.

Please feel free to use the Archive menu to go through my articles.

Thursday, March 29, 2018

XPS driver certification for Windows 10

If you follow Microsoft's Attestation signing a kernel driver for public release guide and try to get your driver signed, you may encouter some troubles as I did. Unfortunately, MS guide does not cover all steps required (and possible errors), neither is there any other resource to read and follow, so I went the hard way through the darkness of the signing process alone and wrote down some notes, which I would like to share with you now.

NOTE: If you have some knowledge of (or experience working with) INF installation files, you may find this article stupid or useless. I do not have any, so I was writing it from my point of view.

After uploading your CAB file in the Dashboard's first step, you have to specify the W10 versions the driver has been tested on. You may be confused as I was when seeing RS2 and RS3 options for the first time:

So here is a little light for this darkness:
Windows 10 RS2 means Redstone 2 which is a codename for build 1703, known as Creators Update
RS3 = build 1709 - Fall Creators Update

The Preparing stage starts and there is an error almost immediately: "Could not load the Inf file install.inf due to Version section is missing from inf"
First lesson learned: Well, apparently the INF file that you use for CAB creation must have a Version section
 (https://docs.microsoft.com/en-us/windows-hardware/drivers/install/inf-version-section)Where is this mentioned in your guide, Microsoft??!

Specifying just the two mandatory attributes Signature and DriverVer seems to be enough for now to eliminate this error:

Signature="$Windows NT$"

(But there is a lot more on this. See below.)

As you may have noticed, when the process fails dashboard allows you to download a file with an error message. Pity that sometimes that file is empty... Thanks, Microsoft! REALLY HELPFUL!!!
Second lesson learnedDo not forget to specify the DestinationDir attribute in your ddf script, otherwise the resulting CAB file will contain no folder and the driver files will be placed in the "root", which is a no-go. Cab file must contain a folder with the driver files.
.Set DestinationDir=XPS

- If you are lucky enough and make it to the Catalog creation stage, it may fail saying
No installation INF found in the root path of the driver. For the driver to be digitally signed, and for it to install properly the installation inf must be in the root of each driver path you have provided. If you have separate folders with different driver packages for different languages, operating systems or device categories then specify each driver set as a separate driver. Each driver package must be selected separately and must contain an installation INF.
Oh, well. So my Inf is not an Inf or what? Should it be in CAB root or inside a folder? After a while spent with unsuccessful attempts, I decided to only work with just one platform (x86) at once - no mixed CAB.

Catalog creation stage sometimes recommends using Inf2Cat utility to check your INF file used in created CAB. And it turns out, it is quite a good thing,
(https://docs.microsoft.com/en-us/windows-hardware/drivers/install/using-inf2cat-to-create-a-catalog-file). I did not manage to find its W10 version on my system, so I used W8.0 version - just to check what it does and what the result is (c:\Program Files (x86)\Windows Kits\8.0\bin\x86\) - it works fine, just don't forget you need to set the OS parameter to Win8, not Win10.

So I took the bunch of files I use for CAB creation (specified in ddf script file), put them in a folder and ran inf2cat:

inf2cat /driver:c:\development\xpsdriver\files /os:8_X86

...and it leads to the exact same error as in Dashboard's Catalog creation stage: No installation INF found in the root path of the driver...
Fine, I can now get the error prior to uploading, which saves some time, but hey, what now...?!

Being more and more desperate I decided to run the Inf2Cat over a Microsoft XPSDrvSample from WDK directory (WinDDK\7600.16385.1\src\print\XPSDrvSmpl\install\) - and wow, the error changes to just some file not found complaints! So now it can find the INF, apparently there must be something special I am missing!

ATTENTION: Here comes a few hours trial-error part where I just desperately tried some things without even knowing why and what it would result in (having no experience with or knowledge of INF). So I can say for sure that I will NOT be able to help you with your questions, should there be any.

NOTE: I can do it this way because of the way I install my printer - I use c++ code to process driver files "manually" and call Windows API, so the INF file works rather as a list of needed files, than an installation script. The parts taken from sample INF file are just for making Inf2Cat (and the Dashboard) happy.

Long story short - I was trying to use parts of xdsmpl.inf file in my own INF file. Turned out that the "right" (read "working") parts are these:



CoreDriverSections="{D20EA372-DD35-4950-9ED8-A6335AFE79F0},UNIDRV.OEM", "{D20EA372-DD35-4950-9ED8-A6335AFE79F5},XPSDRV.OEM,XPSGPD.OEM"


(the Strings section is mostly placed at the end of the INF file, so don't forget it, otherwise the signing process will fail).

After I added this block to my INF file, Inf2Cat stopped complaining - just printed out some warning. This looked promising. So i uploaded yet another submission to the Dashboard, and after few minutes - Heureka! All stages are green and my driver files are now finally signed by Microsoft!

My resulting INF file follows (highlighted are parts that needed to be added - and Microsoft did not consider it important to tell us in the guide). Just please note company name has been changed to ACME.


Signature="$Windows NT$"
DriverVer=mm/dd/yyyy,1.2.345.6 ;use your date and version number
Provider="<your_company_name_here>" ;not sure if it has to match your name in EV cert
Class=Printer ;oh yes, we are "installing" printer
ClassGuid={4d36e979-e325-11ce-bfc1-08002be10318} ;Windows defined guid for printers
CatalogFile=xps.cat ;this is IMPORTANT for INF2CAT - the named file gets created but is not necessary for your CAB; if you do not specify this, inf2cat will fail with "CatalogFile not specified in Version section" (or something like that)





CoreDriverSections="{D20EA372-DD35-4950-9ED8-A6335AFE79F0},UNIDRV.OEM", "{D20EA372-DD35-4950-9ED8-A6335AFE79F5},XPSDRV.OEM,XPSGPD.OEM"

MonitorName=ACME XPS port monitor
MonitorEnv=Windows NT x86

DriverName=ACME XPS printer driver
DriverEnv=Windows NT x86

;WinPrint can be used on XP as well

PrinterName=ACME XPS Printer
PrinterEnv=Windows x86


DDF file for CAB creation:

.OPTION EXPLICIT     ; Generate errors
.Set CabinetFileCountThreshold=0
.Set FolderFileCountThreshold=0
.Set FolderSizeThreshold=0
.Set MaxCabinetSize=0
.Set MaxDiskFileCount=0
.Set MaxDiskSize=0
.Set CompressionType=MSZIP
.Set Cabinet=on
.Set Compress=on
;Specify file name for new cab file
.Set CabinetNameTemplate=xps.cab
; Specify the subdirectory for the files.
; Your cab file should not have files at the root level,
; and each driver package must be in a separate subfolder.
.Set DestinationDir=XPS
;Specify files to be included in cab file

64bit driver 

For attestation signing of a 64bit driver use NTamd64 decorated model section in your INF file (using NTia64 leads to an error "Inf does not have NTAMD64 decorated model sections" in Inf2Cat and Dashboards also fails):



CoreDriverSections="{D20EA372-DD35-4950-9ED8-A6335AFE79F0},UNIDRV.OEM", "{D20EA372-DD35-4950-9ED8-A6335AFE79F5},XPSDRV.OEM,XPSGPD.OEM"

Hope you will get the whole sh*t working too soon!