Showing posts with label windows. Show all posts
Showing posts with label windows. Show all posts

Using DPInst

Someday you may need to install a driver on a windows system. If you are in an enterprise environment, you may have a few requirements. First, you don't want the end-user prompted to install drivers. They may actually do it and end up installing something you don't want them to install. That brings us to a second need, a silent install. We don't want the user to be interupted. Lastly, it is important to have some flexibility on what were installing. For instance, maybe we only want to install the driver if the device is installed. OR maybe we want to pre-install a driver for later use. Whatever our case may be, DPInst is a good solution in most cases.

First things first, you can download DPInst as part of the Driver Installation Framework from Microsoft's WHDC site. You may instead want to install the full Windows Driver Kit (WDK) which will include future updates to DPInst.

You can refer to the command-line switches for more info, but here are some of the more useful switches.

/path

This switch changes the DPInst working directory. Normally DPInst will only search the directory it is ran from.

/s

Switches to silent mode. This will quietly install drivers.

/LM

Uses Legacy mode to install drivers. That allows you to install drivers that aren't signed.

/sh

Scans your hardware and installs only if the device is present and the new driver is better than what is already installed.

/se /sa /sw

These are for suppressing EULA, Add/Remove Programs Entry, and the Wizard in that order. The silent switch should take care of the first and last switch. The Add/Remove Programs Entry you may want to remove.

My five VBScript 'best practices'

I've been programming in VBScript for a while now. Over that time I've seen some things that for better or worse made me take note. I thought that I would share those, in an attempt to at worst open a dialogue on some level and at best convince some VBScripters to slightly modify their actions.


1. Misuse of On Error Resume Next


The On Error Resume Next statement can be quite useful, but all too often it finds its way to the top of a VBScript. Doing this will basically render the entire script free of errors. The statement does have its uses though. Lets say that I want to open a file for writing. Lets consider the things that could go wrong

  • No Permission to write there
  • File exists already
  • File is locked
  • Disk is full
  • User doesn't have enough disk quota space
  • Saving to Network Drive that is offline
We could spend half a day and code around each one of these items. Instead we could do the following:

On Error Resume Next

If Err Then
HandleError
Err.Clear
End If
On Error Goto 0

What happens here is that everything between the On Error Resume Next and the On Error Goto 0 statement don't raise errors. Everything before and after will still cause issues. We can test for errors by checking the Err variable. It returns true for non-zero numbers. So if we have an error code we enter the condition and handle the error. Once done handling our error we call Err.Clear. This clears out the error code so when we test it later in the code we don't get this error. The last statement simply turns error suppression back off.

Also, if you call On Error Resume Next in a function or subroutine then it will only stay in effect for that function and all calls made by that function.

I prefer the second option, just because I like knowing where error suppression starts and stops. With the second option, you can turn on error suppression in one function, call a second function and still have error suppression turned on.

My main point in all of this, is that you have to know where your script is failing. Covering up the problems will curse you sooner or later. Its ok to use error suppression, but so long as you are handling the problems when they arise.

2. Not using Option Explicit

I'd almost like to say as a general rule, you should take both this and the previous rule together and for every script that has On Error Resume Next as the first line of code, should be replaced with Option Explicit. In fact most every script should have Option Explicit as the first line.

What Option Explicit will do for you, is make sure your variables are declared. It does this, by not allowing undeclared variables in your code. So if I said

Option Explicit

i = 0

I'd get an error of "Variable is undefined 'i'"

I'd have to add

Option Explicit

dim i
i = 0

You can add multiple variables by separating them by commas

dim LastName, FirstName, BirthDate

All this will save you the hassle of debugging your code only to find out that you mistyped your variable name.

This may seem like a lot of work to do. Ultimately though, it is only really 2 lines of code. Once to turn this option on and a second to declare your variables. What you gain is completely eliminating one of the more common reasons why scripts fail.

3. Don't repeat yourself

I've seen a lot of scripts that are three or even four times longer than they need to be. This happens because they are simply copying and pasting their code and only modifying one or two parts. Whenever you find yourself in this situation, you should immediately start thinking of sub routines. Sometimes you may not notice until after you've written your script. In those cases, if you ever think that you'll need to modify this script you should go back and refactor it correctly.

Here is an example of what we can refactor.

ItemToWrite = Items(ItemOne)
WshShell.RegWrite "HKLM\Software\MyProduct\ItemOne", ItemToWrite

ItemToWrite = Items(ItemTwo)
WshShell.RegWrite "HKLM\Software\MyProduct\ItemTwo", ItemToWrite

ItemToWrite = Items(ItemThree)
WshShell.RegWrite "HKLM\Software\MyProduct\ItemThree", ItemToWrite

This gets refactored into

WriteKey "HKLM\Software\MyProduct\ItemOne",Items(ItemOne)
WriteKey "HKLM\Software\MyProduct\ItemTwo",Items(ItemTwo)
WriteKey "HKLM\Software\MyProduct\ItemThree",Items(ItemThree)

Sub WriteKey(KeyPath,ItemToWrite)
WshShell.Regwrite KeyPath,ItemToWrite
End Sub

Now we have one line per item instead of two and a single point where we are writing to the registry.

But, lets go a bit further. In this code we repeat "HKLM\Software\MyProduct\" three times. What happens if we misspelled one of those lines. Worse is if we need to change it. We now have to change three lines. Lets change this to

Const MYKEY = "HKLM\Software\MyProduct\"
WriteKey MYKEY & "ItemOne",Items(ItemOne)
WriteKey MYKEY & "ItemTwo",Items(ItemTwo)
WriteKey MYKEY & "ItemThree",Items(ItemThree)

Sub WriteKey(KeyPath,ItemToWrite)
WshShell.Regwrite KeyPath,ItemToWrite
End Sub

We did add a line, but in turn we saved our self the trouble of changing three lines whenever we change that key path.

Whenever you intend to use a string or a number several times, it is best to simply put it in a constant and simply reference it. If you need to modify the string once and then use it multiple times, I'd recommend just using a variable instead of a constant. Either way it will help you when modifying your code.

4. Not using descriptive variable names

In some of my examples, you may see me using a single letter for a variable (Such as i). In practice though this is only good in a few specific examples. Many scripts that are giving examples of some technique will often use a non-descriptive variable(s). I think this leads to individuals using non-descriptive variables in their actual code. Your script will determine your level of descriptiveness, but sometimes just saying 'Name' can be good. Othertimes you'll need "LastName'. Either is better than 'n'.

I deviate from this in one distinct way. When using a loop that has a variable to be used as the index of an array I'll likely use just 'i'. This is fairly common. Sometimes nested for loops for will i and then j. At this point you may be better off using 'Row' and 'Col'. Again, that all depends on your situation. In those situations though, you are using a variable in a single location and not interspersed throughout your code.

5. Not using Comments

I look at programming/scripting languages as a compromise in communicating your actions with the computer and with other users. Comments allow us to extend our communication with the user. By user, I don't just mean you. I also mean the next person who gets the 'joy' of reading your code.

A lot of people do believe in writing comments, but still don't get it right. A comment should be used to say why you did something, not what you did. Most mediocre scripters will be able to take your script and decipher what you did. What they won't be able to do, is figure out why you wrote the code you did.

Taking this approach can sometimes mean writing less comments than you normally would. Jeff Atwood expanded on the idea of commenting on why you did something and had some excellent suggestions on what you can do to be more descriptive with your intent.

Using Devcon

A while back I wrote about using SetupAPI functions in VB.NET. The goal was to be able to work with devices and ultimately enable and disable a device.

The code was what I would eventually use, but initially I used Devcon. Devcon is essentially the Device Manager over a command line. It is freely available. You can even get the source code from the Windows Server 2003 Driver Development Kit (DDK). It may be available in the newer Windows Driver Kit (WDK) as well.

To demonstrate the usefulness of devcon, we can look at some examples from my blog and see how they coorelate to devcon commands

Retrieving Device Setup Class Names and Getting Friendly Class Names:
We can use the following command

devcon classes

This would give us output similar to:

Listing 53 setup class(es).
WCEUSBS : Windows CE USB Devices
USB : Universal Serial Bus controllers
PnpPrinters : IEEE 1394 and SCSI printers
Dot4 : IEEE 1284.4 devices
Dot4Print : IEEE 1284.4 compatible printers
CDROM : DVD/CD-ROM drives
Computer : Computer
DiskDrive : Disk drives
Display : Display adapters
fdc : Floppy disk controllers
hdc : IDE ATA/ATAPI controllers
Keyboard : Keyboards
MEDIA : Sound, video and game controllers
Modem : Modems
Monitor : Monitors
Mouse : Mice and other pointing devices
MTD : PCMCIA and Flash memory devices
MultiFunction : Multifunction adapters
Net : Network adapters
NetClient : Network Client
NetService : Network Service
NetTrans : Network Protocol
PCMCIA : PCMCIA adapters
Ports : Ports (COM & LPT)
Printer : Printers
SCSIAdapter : SCSI and RAID controllers
System : System devices
Unknown : Other devices
FloppyDisk : Floppy disk drives
Processor : Processors
MultiPortSerial : Multi-port serial adapters
SmartCardReader : Smart card readers
VolumeSnapshot : Storage volume shadow copies
1394Debug : 1394 Debugger Device
1394 : IEEE 1394 Bus host controllers
Infrared : Infrared devices
Image : Imaging devices
TapeDrive : Tape drives
Volume : Storage volumes
Battery : Batteries
HIDClass : Human Interface Devices
61883 : 61883 Device Class
LegacyDriver : Non-Plug and Play Drivers
SDHost : Secure Digital host controllers
UsbPcCardReader : USB PC-Card Readers
Avc : AVC Device Class
Enum1394 : IEEE 1394 IP Network Enumerator
MediumChanger : Medium Changers
NtApm : NT Apm/Legacy Support
SBP2 : SBP2 IEEE 1394 Devices
Bluetooth : Bluetooth Radios
WPD : Windows Portable Devices
USB : Motorola USB Device

You'll note that we aren't receiving the Class Guid. I'm not sure if this is that important anyway.

Actually Getting to the Devices and Getting Device Names:

There are a couple of ways we can do this. The first option is to simply specify a class. That happens with the = argument

devcon find =net

PCI\VEN_14E4&DEV_169D&SUBSYS_105E147B&REV_11\4&1B41B794&0&00E0: Broadcom NetLink (TM) Gigabit Ethernet
ROOT\CNTX_VPCNETS2_MP\0000 : Linksys Wireless-G USB Network Adapter #9 - Virtual Machine Network Services Driver
ROOT\CNTX_VPCNETS2_MP\0009 : Broadcom NetLink (TM) Gigabit Ethernet - Virtual Machine Network Services Driver
ROOT\CNTX_VPCNETS2_MP\0010 : Linksys Wireless-G USB Network Adapter #10 - Virtual Machine Network Services Driver
ROOT\MS_L2TPMINIPORT\0000 : WAN Miniport (L2TP)
ROOT\MS_NDISWANBH\0000 : WAN Miniport (Network Monitor)
ROOT\MS_PSCHEDMP\0001 : Broadcom NetLink (TM) Gigabit Ethernet - Packet Scheduler Miniport
ROOT\MS_PSCHEDMP\0002 : Linksys Wireless-G USB Network Adapter - Packet Scheduler Miniport
ROOT\MS_PTIMINIPORT\0000 : Direct Parallel
...
31 matching device(s) found.

We can also use

devcon listclass Net

To find all devices, even those that aren't present, we type

devcon findall =Net

We can also filter based on how the device is connected. This command will show just PCI devices in the net class

devcon find =Net PCI\*

You can do this without even specifying the class as well.

devcon find PCI\*

Getting Status on a Device:

Similar to the last set of commands we can use

devcon status =Net

PCI\VEN_14E4&DEV_169D&SUBSYS_105E147B&REV_11\4&1B41B794&0&00E0
Name: Broadcom NetLink (TM) Gigabit Ethernet
Driver is running.
ROOT\CNTX_VPCNETS2_MP\0000
Name: Linksys Wireless-G USB Network Adapter #9 - Virtual Machine Network Se
rvices Driver
Driver is running.
ROOT\CNTX_VPCNETS2_MP\0009
Name: Broadcom NetLink (TM) Gigabit Ethernet - Virtual Machine Network Servi
ces Driver
Driver is running.
ROOT\MS_L2TPMINIPORT\0000
Name: WAN Miniport (L2TP)
Driver is running.
ROOT\MS_NDISWANBH\0000
Name: WAN Miniport (Network Monitor)
Driver is running.
ROOT\MS_PSCHEDMP\0001
Name: Broadcom NetLink (TM) Gigabit Ethernet - Packet Scheduler Miniport
Driver is running.
ROOT\MS_PSCHEDMP\0002
Name: Linksys Wireless-G USB Network Adapter - Packet Scheduler Miniport
Driver is running.
ROOT\MS_PSCHEDMP\0010
Name: Linksys Wireless-G USB Network Adapter #7 - Packet Scheduler Miniport
Driver is running.
ROOT\MS_PTIMINIPORT\0000
Name: Direct Parallel
Driver is running.
...
31 matching device(s) found.

The same arguments as last time can be used.

Enabling/Disabling a device:

You can use wildcards again, although I usually am very explicit with what I am enabling or disabling.


devcon disable @"HDAUDIO\FUNC_01&VEN_10EC&DEV_0880&SUBSYS_147B9B01&REV_1008\4&EEB356C&0&0001"
HDAUDIO\FUNC_01&VEN_10EC&DEV_0880&SUBSYS_147B9B01&REV_1008\4&EEB356C&0&0001: Disabled
1 device(s) disabled.

devcon enable @"HDAUDIO\FUNC_01&VEN_10EC&DEV_0880&SUBSYS_147B9B01&REV_1008\4&EEB356C&0&0001"
HDAUDIO\FUNC_01&VEN_10EC&DEV_0880&SUBSYS_147B9B01&REV_1008\4&EEB356C&0&0001: Enabled
1 device(s) enabled.



All this works quite well in most situations. There were a couple reasons why I eventually opted with the VB.NET way of doing things. First, efficiency. There is a lot of overhead to enabling and disabling a device with Devcon. This can slow down a program, especially when enabling and disabling a device can be quite time consuming in a computers way of imagining time. 500 milliseconds can be an eternity. 2-3 seconds can be a long time for a user to look at no progress.

The Second reason is just the nature of devcon. Since it is meant to be similar to the Device Manager itself, it acts like the Device Manager. This means devices are disabled on a per-profile basis. So, if you diable a device in one hardware profile and then boot in a different profile, it won't continue to be disabled. In my particular project, this wasn't ideal.

If these reasons aren't compelling enough for you to code this in .NET or C++, then you should look at using Devcon to accomplish your task.

Using RunOnceEx

Last week we figured out how to run something once per user. This week, we will look at running something once on a computer. I'm sure that there are fifty different ways to do this. Personally I like this method, because of three features:

  1. Easily able to run multiple items
  2. Easily able to sequence items
  3. Shows progress with a GUI
RunOnceEx provides us with all of that. We'll start with the registry key.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx

Inside of that is a value name you will create called TITLE (REG_SZ). This will be the title displayed on the window showing the progress of our installation.

We then create keys under that. For convenience sake most people number them. This also will help to sequence installs. Inside each key, the default value will be the string that will be displayed when installing items in the key. You create values (REG_SZ), each will be ran in alphabetical/numeric order. The data can be pretty much anything. MSI, EXE, BAT, VBS. I'm not sure what else you'd need, but I think its covered.

Once you've populated this registry structure you can reboot/logoff. The next login that has rights to modify the RunOnceEx registry key will execute the keys in order. Alternatively you can execute the RunOnceEx Process anytime with the following command:

rundll32.exe iernonce.dll,RunOnceExProcess

Please note that the DLL used here is from Internet Explorer. At one point this command did not work when running IE7. I believe this issue may have been addressed. If not, the common workaround I've seen, is the use of the original IE6 dll and simply explicitly calling its path. Regardless, simply logging in will kick off the process.

Here is a sample of the registry for RunOnceEx. Simply copy this into a file and save with a .REG extension.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx]
"TITLE"="Installing Stuff"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx\1]
@="Notepad"
"1"="C:\\WINDOWS\\notepad.exe"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx\2]
@="Calculator x 2"
"1"="C:\\WINDOWS\\System32\\calc.exe"
"2"="C:\\WINDOWS\\System32\\calc.exe"



Here is what the above item will look like











What will happen with the above example is Notepad will run, followed by two calculator processes. Each process must end, before the next process begins.

References:
MSFN

Using Active Setup

On more than one occasion I've had the need to change a user setting. These settings may be replacing a file or a registry key.

Possibly the first idea in solving this problem is to simply go through each user folder in Documents and Settings and work with each folder in sequence. By doing this, you'll likely have some permission problems and also, if working with the registry, have the overhead of loading each registry hive for each user. I've also found that depending on your environment you may be modifying profiles that are stale or completely obsolete.

What we can use instead, is Active Setup. In a nutshell, Active Setup runs when a user logs into the workstation and compares their registry with the local machine. For each entry found missing with the user's registry, it is executed. Normally an entry will be executed once per user and at the time the user logs in. You'll know it is running based on a small window in the top left corner popping up when the user logs in.

To get started You should add the following


[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\UniqueID]
"Version"=""
"Stubpath"=""
@=""

The UniqueID is just that. If you look you'll see this is mostly Guids, but it doesn't have to be. Of course you'll want this to be unique.

Version is the version of what you'll be running. Typically you won't have to change this. Where it comes in handy is if you want to update this script and run it again under the same UniqueID. If you update the version then the entry will be ran again.

The Stubpath (Command) is the command that will be executed. I have seen MSIs, EXEs, and VBScripts all run without issue. I've also seen RunDll calls as well.

The default valuename (@) is what will be displayed when the command is being executed.


References:
Active Setup - WikiDesktop
etlengineering.com

10 Tools every Desktop Engineer should have.

While working on various projects and troubleshooting more than a few problems, I have found a few tools that are an absolute necessity to perform my typical duties. All but one of these tools are free. I'd like to present them here in no particular order.

1. Process Monitor
Some people may have used FileMon or RegMon. This tool consolidates both tools into one. For those who haven't used either, Process Monitor adds itself as a low level device and allows you to monitor all activity on your disk and registry. I do mean all activity. Running this for a matter of 5 seconds can generate over fifty thousand entries easily. Luckily for us, there are excellent filters that allow us to comb through all this data. Also, Mark Russinovich has several recorded sessions showing how to use Process Monitor.

2. Process Explorer
This is a task manager replacement with a ton of extra features. You can simply check an option to actually replace the task manager. I should point out that this tool and the above tool were created by SysInternals and were eventually acquired by Microsoft. At the SysInternals site you can find more tools that are just as useful as these two tools.

3. Wireshark
Just as Process Monitor showed you events on your system. Wireshark shows you events going across your network connection. This application was previously called Ethereal. You can break down every packet coming from your system and see exactly what is being sent across the wire.

4. Beyond Compare
This is the only application that isn't free. You may be able to find other applications to do this work, but this application is great. Beyond Compare allows you to compare files and folders. You can look line-by-line and see what is different in an individual file, or look at a folder structure looking for files that are different.

5. Irfanview
If your work is anything like mine, you likely need to write a decent amount of documenation. A lot of my documentation contains screenshots. This application will help by taking a jpg screen capture anytime you hit a hotkey you define (Ctrl-F11 by default). it saves the file in a directory. You can save the whole screen or just the foreground window.

6. Notepad++
I used notepad a lot. Until I came across this application. It has a tabbed interface, allowing for multiple documents. It will detect when a file is updated and prompt you to reload. It also includes syntax highlighting for a ton of languages. It provides Regular Expression support, but probably not as much as you may find in vim. Nevertheless, it is a good replacement for Notepad.

7. VMWare Player
Testing and retesting, is a daily routine for me. Because of that, it is important to have something to easily test with. VMWare solves that problem. You may say that this only plays existing images. That problem is easily solved with EasyVMX, which allows you to create VMWare disks for use in the VMWare player. If this is more work, then you can buy the actual VMWare Workstation, but for me this works well.

8. Orca
This is the free tool provided by Microsoft to view MSI files. It is quick and dirty way to see MSIs and their tables. The biggest drawback is that you have to get it off the Windows SDK in order to get the MSI to install.

9. WScript Shell Documentation
I make it a point with scripting and writing code in general to not memorize code. I do this for a few reasons. First, I have enough junk to remember that I shouldn't bother stuff that is easily found in a book or a help file. Secondly, I should always be aware that my code can be better. If I simply remember a way to do task X, then I'll never bother to improve that task. For those reasons, I always have the documentation for VBScript readily available.

10. TortoiseSVN
Anyone who scripts should have some way at looking at where they came from with any particular script. Too many times I've seen a script in a directory that has about 10 different types of backups for that one script. You'll see script.vbs. Then script2.vbs, script.old, script.bak, or scriptREALLYOLD.vbs. Why bother when you can use free source control. Sure you have to learn how to use Source control, but shouldn't you do that anyway? Besides, learning the basics, can be done off of YouTube if you wanted. Personally I like Jeff Atwood's blog entry on setting up source control.

So, that does it. This is not an exhaustive list and perhaps one day I'll compose an addendum to it. But, I really think that each of these tools are essential to a normal Desktop Engineer.

When an exploit is not an exploit

Lately, I've stumbled (literally) onto sites claiming Vista's security flaws. It seems like the post originated from the McAfee Avert Labs Blog. The claim is that an executable, sethc.exe, can be replaced and allow for system access. The executable is associated with the Sticky Keys feature and can be activated by pressing a modifier key five times in a row. Once done the malicious sethc.exe file is launched.

This file isn't new, it was available in 2000 and XP and it isn't an exploit.

One of my favorite bloggers is Raymond Chen. He has taken 'exploits' similar to these to task for a while now. (1, 2, 3, and 4 for example) I think that the 10 Immutable Laws of Security, written by Microsoft Security Response Center has it put best:

Law #1: If a bad guy can persuade you to run his program on your computer, it's not your computer anymore


If you are able to modify system files, then you have all the access that you need. The exploit could be compared to a scenario such as this:

You have a locked room and I want inside. So, I take your key and bring it to a friend who goes into his secret lair (or Lowes) and makes a copy of it. Then I skydive back to you and plant the key back. I then unlock your door.

Great, so why didn't I just use the key? Sometimes when these 'exploits' are described, the extra steps mearly obfuscate the true nature of what is going on.

I take your key.

This is also reminds me of those number tricks relatives spam you with. Take a number, do a bunch of confusing things to it, and end up with a number or a symbol or whatever.

In the end, giving admin access to someone (whether you chose to or not) grants them administrative actions.

Working with Devices: General Overview

So lets take a look at what is the most common view of devices on windows

On the left you see the Device Manager. To get to this just right click on My Computer and click Manage then click on Device Manager. You can also add it to the mmc console like I did.

It shows a tree view with your computer listed at the root and devices under neath that.

Each Item under your computer is called a Device Setup Class. Your devices are members of a Device Setup Class.

So you can see the Printer Port device is a member of the Ports Setup Class.

Another Class that is used is called the Device Interface Class. This class basically defines how the device is connected to the computer.

Imagine that you have two CD-ROM Drives. One drive is connected through an IDE Cable to your motherboard and the other is connected by USB. This means that one CD-ROM drive would be in the USB Device interface Class and the other would be in a different Device Interface Class (IDE I guess). But, BOTH would be in the CD-ROM Setup Class.

In my limited experience it seems that for interacting with devices for actions such as getting information on them and disabling/enabling then you'll be using the Device Setup Classes. In the case of registering your application for notifications on devices being inserted and removed then you would be using the Device Interface Classes.

I'll also say that the Device Interface Classes aren't defined in one single location. I think that the issue is that the developer should know the Class that he'll be working with and therefore know things like the GUID and whatnot.

By comparison, the Device Setup Classes' GUIDs are quite readily accessible in one single location. That is what we'll be going over on the next post.

For more information on the Device Classes take a look at Microsoft's MSDN Article.

Unsigned Driver Problem

Well its been a while since I wrote in this thing. Had a problem earlier this week that I was working on with the rest of the team. Drivers were being preinstalled on a workstation for use by devices that would be plugged in at a later point by a locked-down user. These drivers weren't being used and the user is then being prompted for an Admin account to finish the install.

So we started looking into it. I eventually made my way to the SetupAPI log file @ C:\Windows\SetupApi.log. In it I noticed that where it was showing the driver fail to install it gave in parenthesis about a server side installation. I thought that was odd until I found this Microsoft Article. I noticed that the log had entries stating that the driver wasn't signed.

I went into VB.NET and modified a hash compute program I had. Instead of using an MD5 Hash, I chose Sha1. I then used it to compute the hash on the files and compared them to the tag of the inf file. Sure enough the hash was different. Additionally the hash on the system files was different as well. I then noticed that other drivers that worked had hashes that matched for the inf and ini files, but failed for the sys and dll files. More on that later.

Our team decided that we should just sign them ourself. None of us are certain on how kosher this is, but none the less we proceeded. We found a Microsoft Doc that walked through the basics of signing a driver. What we found was that we needed the Windows Driver Kit. It just so happens that Microsoft has the RTM version of the Vista WDK @ Microsoft Connect.

To summarize how it is done:

  1. Use MakeCert to make a certificate
  2. Import that cert into the Trusted Root and Trusted Publishers sections using CertMgr
  3. Use Signability to create an unsigned Catalog file.
  4. Use Signtool to sign the Catalog file.
Note: all these tools we in the %WDK Directory%\bin\SelfSign\ Your results may differ.


Now all we have to do is import that cert that we created and then pre-install the drivers.


Everything sailed smoothly after that. One thing I couldn't understand was why the sys and dll files came up with different Sha1 hashes then what I would compute them out to be, but they would still be considered valid by the Install process.

I cleared up my confusion by finding this Microsoft Article. It stated the following

"A flat file hash is not used for files, such as drivers, that use the portable executable (PE) file format. Instead, relevant sections such as the PE header, executable data, and authenticated attributes are selectively hashed."

I next found a useful API Call, CryptCatAdminCalcHashFromFileHandle. I used this to make another VB.NET app and verified that the hash was correct for the PE file formats.

Cool Stuff