Install/update driver from Windows service - windows

To install a driver, you typically send the command:
DefaultInstall 128 {inf path}
to the InstallHinfSection via direct call or RunDLL.
This works wonderfully. I can install my driver anywhere (including 64-bit Win 2008 R2, which means I've got all the code signing right too).
HOWEVER, the above fails when launched from a Windows service. I've read about service vs client installs, and hoped I had met all the requirements for a silent service install (built a .CAT file, it is signed along with the driver, etc).
But no dice - it just fails. Comparing the errors in SetupAPI.log between an interactive install and the install from the service doesn't show any differences (other than the interactive takes the steps of copying the driver file and succeeds, where the other doesn't).
The driver itself is not in use (my service is the only one that uses it). Is there ANY way for a service to silently update a driver without requiring user interaction?

I called Microsoft and discussed this with a support engineer.
Turns out that using DefaultInstall with InstallHinfSection is somewhat obsolete, but still works. And it just happens to work without prompting the user if the driver is signed by a certificate that they recognize because DefaultInstall is 'dumb'. Yet the driver itself is still allowed to launch because it's cross-signed with the Microsoft cert. A nice little loop-hole I guess. The trick is it has to be installed by a service that is set to Interact with Desktop (a requirement). Using something like PsExec or RemCom is a way to do this if your service isn't currently running in that way.
In the future, this might not continue to work. At that point, get the driver's .cat file into the Windows\System32\Catroot{F7... folder but it can't just be copied directly in -- there is an API.
If the .cat was put in first, then the driver theoretically shouldn't need to prompt to ask if the certificate for the driver is acceptable to the user, because catroot is the 'acceptable to the user' list of certs and drivers.
Also, having the catalog file installed before attempting the driver install might help since the catalog contains the security certificate that the driver will present (though not necessarily in this case -- but it might help in the future (and possibly with Win 2003)
Basically the support engineer was surprised this worked at all and we went around and around on how it might be working... Hopefully this helps someone else.

Related

Windows 10 Service Start Error 2 (The system cannot find the path specified)

I am developing a kernel mode driver for Windows 10 and I am stuck on the service start it always gave me this error:
"0x2 The system cannot find the path specified"
to install it I have tried by the following ways:
Using "sc create svname binpath="pathtodriver" type=kernel".
Creating a service from my c++ a`` with CreateService API and Kernel Mode flag.
Both return the same error for me, but here's the most stranger thing looks I have a desktop (from I am writing this and I develop my apps, study etc) in this desktop I can install the driver without any problem using both ways, Now on my laptop what I use to test some of my software it installed the first time and after that I couldn't start anymore the driver service, the path is correct
I have checked it a lot of times and tried almost everything.
Also I have other Kernel Mode driver which loads on both computers anytime without any problem its stranger really i have been trying all...
What I have tried to solve this problem:
Deleting the service from sc using "sc delete svname".
Deleting the service directly from registry.
Restoring registry.
Repairing windows.
Installing almost every Visual C++ Runtimes.
Install the driver with another service name, file name and different path.
Nothing of the list solves my problem.
(I am on Test Signing to test my driver without DSE)
EDIT: Solved was my DriverEntry it was returning 0x2 cause it was not compatible with all optical devices.

Unload a minifilter driver with no unload routine?

This is probably a pretty easy question to answer for someone that is experienced with FS minifilters. I am trying to script the removal of a filter driver and device.
Some background... this driver is running on Windows 8/10 x64. The vendor that created the driver has not been helpful in fulfilling my request for a removal tool. Unfortunately their MSI uninstall is buggy and only works about half the time you run it... They want us to upgrade to their newest version that doesn't have the bug we are encountering during uninstallation. We aren't interested in continuing use of this software so a paid upgrade seems frivolous... Their only suggestion has been to reimage the computers without the software that includes the FS minifilter device... That's out of the questions because it is on 1000+ computers...
Basically, their official uninstaller does an API callback to one of their servers and verifies the machines eligibility to uninstall:
Does the MAC address of the primary network adapter exist in their
database?
Does the password you entered for uninstallation match
what is set in their database?
If you are eligible, it runs an MSI uninstallation and disables the FS filter, removes the driver file, service files, configuration, and restarts... The bug that is keeping us from doing a normal bulk removal (their way) is that the MSI freezes during the removal process (after checking eligibility) and requires us to restart a client computer up to 3 times to finish the uninstall.
I have been able to successfully remove the software and device/driver by externally mounting the Windows file system and manually removing the driver file under System32/Drivers and also removing all of the actual program files/services. I have not been able to do this booted onto the same partition where the minifilter is loaded. The minifilter driver that is running is protecting those program files, a registry key, and the actual .sys file under System32...
I've done some basic reverse engineering of their MSI... They are using custom actions to perform the removal... First step is the removal of the service, second step is the removal of the minifilter. Both actions are done via an executable that is packaged in the MSI... I've extracted that and attempted to use it by running the same commands that they do during the MSI... I haven't had any luck. The minifilter just doesn't want to die.
They have some other custom actions that are loaded via DLL. Initial investigation makes me think its all of their custom uninstall eligibility craziness.
It looks like their minifilter doesn't have an unload routine built in. Using FLTMC I get this error attempting to detach and/or unload:
0x801f0010 Do not detach the filter from the volume at this time.
0x801f0014 Do not detach the filter from the volume at this time.
Does anyone know of a good way to unload a minifilter that is throwing those errors?
Try to kick out FltMgr.sys of the kernel by:
Renaming %SystemRoot%\sytem32\drivers\FltMgr.sys
Or changing HKLM\SYSTEM\CurrentControlSet\Services\FltMgr\Type to 0x4 (Disabled)
Reboot
Minifilters can't work without Filter Manager.
If you are desperate enough, look into Windows PE, available as part of the Windows Assessment and Deployment Kit.
A Windows PE image can be remotely installed onto a machine's hard disk and configured to perform whatever task you need done and then automatically reboot back into the original operating system. Doing it this way gives you the same access as externally mounting the infected file system, but can be automated. I've used this approach in the past to automate offline maintenance tasks on several hundred machines (e.g., changing a registry setting that Symantec Endpoint Protection was "protecting") and while getting it working is fiddly, once it is working it works well.
My email address is in my profile, you're welcome to contact me if you decide on this approach and have questions about implementing it.
Alternatively, depending on your jurisdiction and circumstances, you might want to consider threatening the vendor with a lawsuit if they refuse to provide a proper solution. They broke your computers, it should be their job to fix it. From the sounds of it, they wouldn't even need to do any work, just let you have the upgraded version for a few weeks free of charge.

How can I find out if a USB device driver is installed by querying the registry?

I am trying to check if drivers are installed for a particular USB device as part of an installation process. Unfortunately the manufacturer has several different installers for the same driver and there seems to be no consistent place in the registry to check if the driver is installed. However it's obvious that Windows must know if a driver is installed for a given USB device ID (Eg VID and PID) and I presume this is recorded in the registry?
How can I check to see if the driver is installed only by querying the registry, without relying on looking for installer-specific keys such as references to the uninstaller (which is unreliable) or calling Windows API functions?
Don't query the registry. There's no documented location for this, and it changes. Definitely between versions, possibly with service packs.
The proper way is to use Windows API functions, and it's unclear why you would reject this solution.
I faced the same Problem as you as I wanted to check in Installshield if a device driver was already installed.
I first tried the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\ path as mentioned in USB Device Registry Entries, and it worked on 2 Windows 10 systems I tried but on a 3rd System it was not located here anymore but in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceMigration\Devices\USB\, I assume it has with a Windows 10 update to do but I am not sureā€¦
I finally found out, that on all Systems I was able to find the VID/PID text (in my case VID_0483&PID_DF11) in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class, which is pretty much what people programmatically do here .
Anyway as MSaters suggested I would rather use a C# Windows query like System.Management.SelectQuery query = new System.Management.SelectQuery("Win32_SystemDriver"); (see How to check whether a driver is installed?) as I am not sure, that the registry query allways work but it is in my case not possible.
Edit:
I found out, that Windows creates the registry entry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\ as soon as the device is connected, even without drivers installed, that means that it is an incorrect way to check if the driver is installed.
There is another way though, the registry entry contains "VID_XXXX&PID_YYYY" then a "SERIAL" as subfolder, in my case (VID=1FC9, PID=000C, SERIAL=ABCD) \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_1FC9&PID_000C\ABCD, you can then check the presence of an entry called Driver, it seems like it is only created after you install your Driver.
And for some reason the entry to look for under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceMigration\Devices\USB\VID_1FC9&PID_000C\ABCD seems not to be Driver but DriverInfName

Adding PostgreSQL installer to my own application installer

I created a Visual Studio 2010 installer project and added the postgresql-9.2.401-windows.exe file to it. In the "Commit" custom action, I added that file, removed any arguments and set InstallerClass to False.
Now, when I run my application's installer, the PostgreSQL setup starts up, shows its splash screen and then jumps to 100% CPU usage and starts leaking memory for a long time (certainly longer than a few minutes), after which it bails out. Running the .exe on that computer works just fine.
How should I package PostgreSQL in my installer?
Personally I don't like programs that silently install the standard PostgreSQL for Windows. It's deeply annoying to get mailing list posts from people who're asking "What's this PostgreSQL thing and why is it using 88 bajillion megabytes of RAM, I didn't ask for it, remove it now!".
(Yes, I'm mostly talking about a certain annoying gambling card-counting program with the initials PT whose name I will not mention directly).
If you're going to bundle PostgreSQL it'd be great if you could use a non-default port and non-default data directory. If you install a service to auto-start it, don't use the default service name postgresql-[version] but something like myapp-database or myapp-postgres.
This is all done much more easily if you just bundle the PostgreSQL binaries in your installer then create the service yourself with your installer tools or via sc.exe. You may choose to simply pg_ctl start/stop the server from within your program, though this requires some thought about access permissions to the data directory.
The downside is that when there are PostgreSQL updates you need to update your installer. On the other hand, you probably don't want people upgrading PostgreSQL independently of your software updates.
I suggest using the .zip binaries from here and bundling them into your installer directly.
If you really must use the executable installer the documentation contains instructions on silent installation.

How to Install Driver with a cat file?

I have kernel driver. When installing on 32 bit systems and Windows XP and below, I had no problem and used SetupCopyOEMInf, but 64 bit drivers are required to be signed. I have signed it and I need to have a cat file with the driver copied somewhere on the computer, and this method of install doesn't work. How should I install it?
EDIT: Clarified the question.
In Windows Vista and Windows 7 there a new utility for handling drivers setup call PnPUtil. It handles exactly this kind of work. Just copy all your driver relevant files(*.inf, *.cat, *.sys) to a directory on the target computer and use PnPUtil -i -a <InfName>.inf
Note: You will need to be in an administrator context to successfully use this tool.
You need to get an Authenticode signature, create a catalog file, and sign it with that. Microsoft decided that, for 64-bit systems, it will require the driver to come untampered from the vendor, by checking it signature.
(Note: This is not the same as WHQL, which tests the quality of the driver. Authenticode merely indicates that the driver hasn't been tampered with by some malicious user or virus; it doesn't say anything about what the driver does, so it's a relatively easy -- although pricey -- signature to obtain.)
Another solution is test-signing, if you don't plan on redistributing your program.
https://technet.microsoft.com/library/dd919230.aspx

Resources