SmartcardleserInstaller

From
Jump to navigation Jump to search

Ziel des Projektes war die Erstellung eines Installers mittels des Windows Installer Frameworks als msi Installationspacket. Zusätzlich wurden die zugehörigen Projekte auf die neuesten Microsoft WDK, Windows SDK upgegradet und in einer zusammenhängenden Visual Studio 2015 Solution integriert. Zuletzt wurde das AppVeyor continuous integration script angepasst.

Technische Grundlagen

SmartcardTreiberArchitekturInstaller.png
Bei dem von Frank Morgner entwickelten Virtuelle Smartkarten Treiber (vpcd) handelt es sich um einen Microsoft Windows user-mode Treiber, welcher aufgrund seiner virtuellen Natur nicht über gängige Plug-and-Play (PnP) Mechanismen installiert werden kann. Daher muss zunächst ein devnode angelegt werden, zu dem das Betriebssystem dann den zughörigen Treiber benötigt und in diesen installiert.

Projektdokumentation

In der Prozessdokumentation wird der Projektverlauf beschrieben, während die Produktdokumentation eine Beschreibung der bearbeiteten Komponenten und eine Anleitung zur Benutzung dieser enthält.

Prozessdokumentation

Um den devnode anzulegen benutzen wir zunächst das devcon binary, welches jedoch aufgrund von Lizenzbestimmungen nicht weiterverteilt werden darf. Das alternative binary dpinst wurde vor kurzem deprecated, und Microsoft empfiehlt den Windows Update Mechanismus als Mittel der Wahl zur Verteilung von Treiber. Da vpcd jedoch keine PnP Mechanismen zur Installation nutzen kann, mussten wir auf die SetupAPI zurückgreifen. Dazu modifizierten wir das DevMsi Projekt um es an die aktuellen SDK Versionen anzupassen. Das Herzstück unseres Projektes bildet das WiX Toolkit Installationsscript, welches die Installationslogik des MSI Packets beschreibt:

<?xml version="1.0" encoding="UTF-8"?>

<?define BinaryFolder="../binaries"?>

<?if $(sys.BUILDARCH)="x86"?>
  <?define ProgramFilesARCHFolder="ProgramFilesFolder"?>
  <?define DriverFolderARCH="Win8.1Debug_win32"?>
<?elseif $(sys.BUILDARCH)="x64"?>
  <?define ProgramFilesARCHFolder="ProgramFiles64Folder"?>
  <?define DriverFolderARCH="Win8.1Debug_x64"?>
<?else?>
  <?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?>
<?endif?>
    
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
	<Product Id="*" Name="BixVReaderInstaller-$(sys.BUILDARCH)" Language="1033" Version="1.0.0.0" Manufacturer="FrankMorgner" UpgradeCode="6d60b0e4-c325-4d3b-b727-2f3e0b0a8afa">
		<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

		<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
		<MediaTemplate EmbedCab="yes" />
    
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="$(var.ProgramFilesARCHFolder)">
        <Directory Id="INSTALLDIR" Name="BixVReader">          
            <Component Id="BixVReaderDriver" Guid="60FF3BFF-E235-4F84-8A25-E22CB3164FB1">
              <File Id="BixVReader.dll" Source="$(var.BixVReader.TargetDir)BixVReader\BixVReader.dll" />
              <File Id="BixVReader.inf" Source="$(var.BixVReader.TargetDir)BixVReader\BixVReader.inf" />
              <File Id="WudfUpdate_01009.dll" Source="$(var.BixVReader.TargetDir)BixVReader\WudfUpdate_01011.dll" />
              <File Id="wudf.cat" Source="$(var.BixVReader.TargetDir)BixVReader\bixvreader.cat" />
            </Component>         
        </Directory>
      </Directory>

      <Directory Id="WindowsFolder">
        <Component Id="BixVReaderConfiguration">
          <File Id="BixVReader.ini" Source="BixVReader.ini.template" Name="BixVReader.ini" />
        </Component>
      </Directory>
    </Directory>
    
    <Binary Id="DevMsi" SourceFile="$(var.DevMsi.TargetPath)" />

    <CustomAction Id="AddDevice" BinaryKey="DevMsi" DllEntry="CreateDevnode" Execute="deferred" Impersonate="no" />
    <CustomAction Id="AddDevice.SetParam" Return="check" Property="AddDevice" Value='"[INSTALLDIR]BixVReader.inf" root\BixVirtualReader' />
    
    <CustomAction Id="DelDevice" Return="ignore" BinaryKey="DevMsi" DllEntry="RemoveDevnode" Execute="deferred" Impersonate="no" />
    <CustomAction Id="DelDevice.SetParam" Return="check" Property="DelDevice" Value="root\BixVirtualReader" />

		<Feature Id="ProductFeature" Title="BixVReader" Level="1">
      <ComponentRef Id="BixVReaderDriver" />
      <ComponentRef Id="BixVReaderConfiguration" />
		</Feature>

    <InstallExecuteSequence>
      <!-- Custom Actions that will be executed if "Installed" -->
      <Custom Action ="DelDevice.SetParam" After="InstallFiles">Installed</Custom>
      <Custom Action='DelDevice' After="DelDevice.SetParam">Installed</Custom>

      <!-- Custom Actions that will be executed if "NOT Installed" -->
      <Custom Action ="AddDevice.SetParam" After="DelDevice">NOT REMOVE</Custom>
      <Custom Action='AddDevice' After="AddDevice.SetParam">NOT REMOVE</Custom> 
    </InstallExecuteSequence>
	</Product>
</Wix>

In einer neu angelegten Visual Studio Solution wurden das vpcd Projekt, DevMsi und den MSI Installer integriert. Im Abschluss sendeten wir Frank Morgner einen Pull Request auf GitHub, wobei klar wurde, dass das continuous integration script angepasst werden musste. Ein Fehler im image des appveyor konnte gefunden und behoben werden:

platform:
 - x86
 - x64

os: Visual Studio 2015

install:
 - date /T & time /T
 - ps: >-
     If ($env:Platform -Match "x86") {
       $env:MSBUILD_PLATFORM="x86"
     } Else {
       $env:MSBUILD_PLATFORM="x64"
     }
 - git submodule update --init --recursive

 # BUGFIX: wdf directory was renamed to 00wdf, rename it back (see github.com/appveyor/ci/issues/414)
 - ps: ren 'C:\Program Files (x86)\Windows Kits\10\include\00wdf' 'wdf'

build_script:
 - msbuild virtualsmartcard\win32\BixVReader.sln /p:Configuration=Release;Platform=%MSBUILD_PLATFORM%

Produktdokumentation

Es wurde eine Visual-Studio-2015-Solution zur Erstellung des Treiberinstallers erstellt. Sie befindet sich unter vsmartcard/virtualsmartcard/win32. Die Solution enthält mehrere Teilprojekte:

  • BixVReader: ist ein UMDF-1.9-Treiber für Windows 10.0.14393. Die VS2015-Lösung enthält den existierenden Treibercode, baut aber nicht auf das alte NMAKE auf (sources-Datei).
  • DevMsi: erstellt eine Bibliothek mit mehreren Custom Actions zur Installation und Deinstallation von Treibern. Diese wird im Installer verwendet. Das Projekt wurde ausgehend von https://github.com/SergiusTheBest/DevMsi/commit/beb00eded598cb66de319fa2fe52620969dc1e01 adaptiert, um auch unter VS2015 und aktuellen WiX-Versionen zu funktionieren. Die Bibliothek erstellt Einträge im Windows-Installer-Log, um eventuelles Fehlverhalten nachvollziehen zu können.
  • BixVReaderInstaller: ist ein WiX-Projekt, das ein Windows-Installer-Paket bauen kann. Dieses ist in der Lage, die Treiberdateien ins Programme-Verzeichnis zu kopieren, das Treiberpaket im System zu registrieren und per DevMsi einen DevNode für den virtueller Smartcard-Leser anzulegen.

Bei Deinstallationen wird der Treiber sauber deinstalliert, bei Reparaturinstallationen de- und wieder installiert.

Die Solution baut vollständig auf MSBuild auf und kann somit auch per Kommandozeile komplett gebaut werden. Beispiel für x86 (Release):

msbuild BixVReader.sln /p:Configuration=Release;Platform=x86

Es werden getrennte Installerdateien für x86- und x64-Architektur gebaut, dies entspricht dem Microsoft-Design. Die Installationspakete betten alle benötigten Inhalte ein und sind unabhängig lauffähig.

Zur Ausführung werden Visual Studio Community 2015, das Windows Software Development Kit 10.0.14393.33, das Windows Driver Development Kit 10.0.14393.0 sowie das WiX Toolset 3.10.3.3007 verwendet.