dpinst / DifX won't install signed driver silently - windows-7

When installing a signed driver (i.e. with a properly signed .CAB) on Windows 7 through DpInst, unless it's a WHQL-signed driver, you cannot install it silently. If you run DpInst in the non-silent mode, it'll prompt you to trust the "publisher". If you run DpInst in silent mode, it would fail with a signing-related error code (something like 0x800b0109 -- check your setupapi.app.log).

While ilya's answer is good, the solution on Windows 7 is even easier. The command below deploys the certificate to both the current user and the system trusted publisher certificate stores. It requires administrative privileges and is provided by Microsoft.
For Windows 7
certutil.exe -addstore TrustedPublisher cert.cer
I verified that this works on Windows 7 64-bit to deploy signed, but not WHQL-certified, drivers - without prompting the user.
Windows XP
WHQL Certification
It appears that on XP you still need to have the drivers WHQL-certified in order to avoid prompts on install.
Pre-Installing SPC on Windows XP
For Windows XP you'll need to download the Windows Server 2003 Admin Tools Pack from Microsoft and extract certutil.exe and certadm.dll. Then the command above will work on XP as well.
Admin Tools Pack: http://www.microsoft.com/download/en/details.aspx?DisplayLang=en&id=16770
Note that the extracted msi file can be inspected by 7-zip, so you don't need to install it to obtain the exe and dll you need.

The straightforward way to do it is to add the signing certificate to the TrustedPublishers. You can do it programatically (the implementation of win32exception is left as an exercise to the reader):
#include <windows.h>
#include <wincrypt.h>
#include "win32exception.h"
void InstallTrustedPublisherCertificate(LPCTSTR CertificateFilePath)
{
DWORD dwContentType;
PCCERT_CONTEXT pCertContext = NULL;
if (!CryptQueryObject(
CERT_QUERY_OBJECT_FILE,
CertificateFilePath,
CERT_QUERY_CONTENT_FLAG_ALL,
CERT_QUERY_FORMAT_FLAG_ALL,
0,
NULL,
&dwContentType,
NULL,
NULL,
NULL,
(const void **)&pCertContext))
throw win32exception("CryptQueryObject");
if (dwContentType != CERT_QUERY_CONTENT_CERT)
throw exception("Incorrect content type of crypto object.");
__try
{
HCERTSTORE hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
0,
CERT_STORE_OPEN_EXISTING_FLAG |
CERT_SYSTEM_STORE_CURRENT_USER,
_T("TrustedPublisher"));
if (hCertStore == NULL)
throw win32exception("CertOpenStore");
__try
{
if (CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_NEWER, NULL))
{
// Added certificate to TrustedPublisher store.
}
else
{
DWORD err = GetLastError();
if (err == CRYPT_E_EXISTS)
{
// Certificate already exists in TrustedPublisher store.
}
else
throw win32exception("CertAddCertificateContextToStore", err);
}
}
__finally
{
CertCloseStore (hCertStore, 0);
}
}
__finally
{
CertFreeCertificateContext(pCertContext);
}
}

And the question is? If the driver is not WHQL-certified, it can't be installed silently. This is a security measure of Windows.

The Drivers have to go through WHQL Certification to avoid any kind of un-signed pop-ups.
If you are looking for any third-party WHQLTesting Service providers let us know, we would be happy to help you in this regards.

Related

Invoking GetProcAddress resulting procedure reports ERROR_FILE_NOT_FOUND

I am accessing a c++ dll library (I don't have the source code) from c++ code. I use this library to mount a usb device so I can access the files on the device. This code worked well in VS2010 but since we updated to VS2013 it no longer works. Here is my question. What differences between VS2010 and VS2013 might cause this to fail or what settings might cause this to fail?
Here is what I observe when running the code:
The LoadLibary call returns a module handle
The GetProcAddress seems to return a valid procedure address
Invoking the dyn_Open_Device always returns false with VS2013 it
almost always returned true in VS2010.
After calling dyn_Open_Device, GetLastError returns 2
(ERROR_FILE_NOT_FOUND)
Here is the code:
typedef bool(*PFUNC_Open_Device)();
DWORD dwError = GetLastError();
BOOL bSuccess = SetDllDirectory(_T("C:\\Users\\steve epp\\Desktop\\EH16\\sdk1.1\\lib\\"));
// Step 2: Dynamically load the dll
HMODULE m_hModule = LoadLibrary("eeyelog_protocol_v1.0.dll");
dwError = GetLastError();
// Handle the case that the dll is not found
if (m_hModule == NULL)
{
dwError = GetLastError();
if (dwError == ERROR_MOD_NOT_FOUND)
{
CString msg = "Unable to load eeyelog_protocol_v1.0.dll.";
AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION);
}
}
PFUNC_Open_Device dyn_Open_Device = (PFUNC_Open_Device)GetProcAddress(m_hModule, "Open_Device");
dwError = GetLastError();
bool ret = dyn_Open_Device();
dwError = GetLastError();
Here is the DUMPBIN results:
DUMPBIN /EXPORTS "C:\Users\steve epp\Desktop\EH16\sdk1.1\lib\eeyelog_protocol_v1.0.dll"
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Users\steve epp\Desktop\EH16\sdk1.1\lib\eeyelog_protocol_v1.0.dll
File Type: DLL
Section contains the following exports for eeyelog_protocol_v1.0.dll
00000000 characteristics
59CC4F90 time date stamp Wed Sep 27 18:25:36 2017
0.00 version
1 ordinal base
33 number of functions
33 number of names
ordinal hint RVA name
1 0 000010A0 Check_Device_state
2 1 000011D0 Close_Device
3 2 000012E0 Login
4 3 000011A0 Open_Device
I solved the problem with the help of Process Monitor. In the Process Monitor’s Event Properties dialog under the Process tab I could see that eeyelog_protocol_v1.0.dll was running and its dependency libusb0.dll was also running. However, the running libusb0.dll was the wrong version an older version. Once I ran the correct version then everything worked again. Running the code through the debugger it was picking up the wrong version of libusb0.dll from the directory containing the executable. So make sure you are loading and running the right version. I had the correct version in the path I set with SetDllDirectory but it was using the wrong version because it found that one first.
I had never used Process Monitor before. It is a very helpful Microsoft SysInternals tool. It can be found downloaded from https://learn.microsoft.com/en-us/sysinternals/downloads/procmon

KMDF WdfDriverCreate function returns "insufficient resources"

I'm trying to write a kmdf driver to target a custom PCIe board. On following the default project that Microsoft provides, I made a few minor changes to the .inf file, mainly changing the names of strings and providing the hardware ID of our PCIe board.
Deploying the driver works as it should. The driver installs and shows up on the device manager, but it says that it didn't install correctly or it may be corrupted.
On debugging, I see that WdfDriverCreate fails with an error of 0xC000009A, which means insufficient resources.
For reference, this is the generated code that the kmdf template project makes for you, which is what I am currently running:
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
//
// Initialize WPP Tracing
//
WPP_INIT_TRACING( DriverObject, RegistryPath );
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
//
// Register a cleanup callback so that we can call WPP_CLEANUP when
// the framework driver object is deleted during driver unload.
//
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
attributes.EvtCleanupCallback = CIPDriverEvtDriverContextCleanup;
WDF_DRIVER_CONFIG_INIT(&config,
CIPDriverEvtDeviceAdd
);
KdPrint(("CIP: Driver Entry\n"));
status = WdfDriverCreate(DriverObject,
RegistryPath,
&attributes,
&config,
WDF_NO_HANDLE
);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
KdPrint(("CIP: WdfDriverCreate failed with status - 0x%x\n", status));
WPP_CLEANUP(DriverObject);
return status;
}
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
return status;
}
My first question is, What would cause this?
I attempted to dump a log after the error is raised by running
!wdfkd.wdflogdump mydriver.sys
But it never works. I ensured that all symbol paths are loaded properly, as shown below
fffff880`05fdd000 fffff880`05fe6000 CIPDriver (private pdb symbols) C:\Users\jimmyjoebobby\Documents\Visual Studio 2013\Projects\CIPDriver\x64\Win7Debug\CIPDriver.pdb
22: kd> lm m wdf*
start end module name
fffff880`00e5e000 fffff880`00f20000 Wdf01000 (pdb symbols) c:\winsymbols\Wdf01000.pdb\03FC6AA4329F4372BE924775887225632\Wdf01000.pdb
fffff880`00f20000 fffff880`00f30000 WDFLDR (pdb symbols) c:\winsymbols\wdfldr.pdb\9674B20D2E5B4E7AA2DE143F642A176E2\wdfldr.pdb
Where "CIPDriver" is my driver.
On running the dump command, this is the output:
22: kd> !wdfkd.wdflogdump CIPDriver.sys
Trace searchpath is:
Trace format prefix is: %7!u!: %!FUNC! -
TMF file used for formatting log is: C:\WinDDK\7600.16385.1\tools\tracing\amd64\wdf01000.tmf
Log at fffffa80356232f8
Gather log: Please wait, this may take a moment (reading 0 bytes).
% read so far ...
warn: The log could not be accessed
hint: Are the symbols the WDF library available?
hint: The log is inaccessable after driver unload.
And the output of .sympath
22: kd> .sympath
Symbol search path is: C:\Users\jimmyjoebobby\Documents\Visual Studio 2013\Projects\CIPDriver\Win7Debug;C:\winsymbols
Expanded Symbol search path is: c:\users\jimmyjoebobby\documents\visual studio 2013\projects\cipdriver\win7debug;c:\winsymbols
Where C:\winsymbols is a cache of Microsofts's symbols which I acquired by following the guide here: https://msdn.microsoft.com/en-us/library/windows/hardware/ff558829(v=vs.85).aspx
My second question is, how do I correctly setup the debugger to dump out the logs?
Thanks
I don't quite understand why this helps, but if I turned off KMDF verifier under
[DriverName] Package -> Properties -> Configuration Properties -> Driver Install -> KMDF Verifier -> Enable KMDF Verifier
And deploy the driver, it works. If I turn that on, it fails. I deployed my driver a few times toggling that option on and off and it always fails when it's on.
I posted this question along with my findings. Maybe someone there could answer why this is the case: https://www.osronline.com/showthread.cfm?link=277793

com0com virtual port not found

I have installed, apparently successfully, com0com v2.2.2.0 on a 64bit Windows 7 machine.
I run the command utility, like this:
command> install PortName=COM9 PortName=COM8
CNCA0 PortName=COM9
CNCB0 PortName=COM8
ComDB: COM8 - logged as "in use"
ComDB: COM9 - logged as "in use"
command> busynames COM?*
COM3
COM4
COM5
COM6
COM8
COM9
COMPOSITEBATTERY
Note: logged as "in use" is NOT an error message?
Then I try to open COM8 like this
m_hIDComDev = CreateFileA( szCodedPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hIDComDev == NULL || m_hIDComDev == INVALID_HANDLE_VALUE ) {
wchar_t * lpMsgBuf;
DWORD dw = ::GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
myErrorMsg = (char*)malloc( 200 );
sprintf(myErrorMsg,"Error creating connection %s ( %s ) %S",
szPort,szCodedPort,lpMsgBuf);
This fails with
Error creating connection COM8 ( COM8 ) The system cannot find the file specified.
I have tried both "COM8" and "\\.\COM8".
Note that the exact same call to CreateFileA works perfectly on a 'real' COM port.
Q: Can someone tell me what the problem is?
A: On windows 7 64 bit you have to enable testing of unsigned drivers.
Run a command prompt as administrator. ( It is not enough just to run from an account with admin privileges. See here for details of how to do this. )
Type in the command bcdedit -set TESTSIGNING ON
reboot. ( Windows will place a "test Mode" note on the bottom right of the desktop )
For Windows 8 this method does not work satisfactorily or easily. Here is some discussion of the issues and workarounds.
Alternatively you might want to try a signed version - I have NOT tried this myself.
In case anyone is referencing this, and interested in this topic, the 2.2.2.0 version of com0com is signed for 64-bit Windows. This removes the need to jump through the hoops of putting Windows in "test" mode.
Here are my points:
Microsoft requires 64-bit drivers to be signed.
com0com.sys (64bit) is a mere unsigned kernel-mode driver.
SoftWx has written an interesting tutorial on installing it on a 64 bit Windows 7 machine. You can fetch it here.
This is a very old post, but just to add some help if somebody stumbles across it like I did.
After Windows 10 Version 2004 you may need to disable Secure Boot in your BIOS.
I got a signed version 3.0 of the app from SourceForge, this worked perfectly on my one PC (Windows 10 Pro Version 2004). I just installed the app and two pairs of linked ports were immediately created.
On my laptop (Windows 10 Pro Version 20H2), I did not get the same results. No COM ports were created and in the device manager the devices could not be configured. After changing the BIOS setting, I reinstalled and all went smoothly.
Links for reference:
https://sourceforge.net/projects/com0com/
https://sourceforge.net/projects/signed-drivers/files/com0com/v3.0/
To answer #DaAwesomeP above (I do not have the rep to put it in the comments), there is a repo on GitHub https://github.com/paulakg4/com0com where I can see a changes.txt. If I compare the dates, it looks like the same version 3.0 in there.

How to check if Expression Encoder 4 is already install?

I faced a problem of checking a specific application is already installed.
I know that I can check from the registry key for which application that is already installed but I cannot find Expression Encoder4 (window 64bit) in HKLM registry key.
Any ideas?
thanks
The registry key to check is:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Expression\Encoder\4.0
I use the following code to check the encoder version and my dev computer is Windows 7 64bit:
string encoderVersion = string.Empty;
RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Default);
localKey = localKey.OpenSubKey(#"SOFTWARE\Microsoft\Expression\Encoder\4.0");
if (localKey != null)
{
encoderVersion = localKey.GetValue("Version").ToString();
}

Error printing from 16-bit applications in Windows 2008 Server

I'm having problems trying to run a bunch of old 16-bit applications in Windows 2008 Server.
The applications ran fine up to Windows 2003 Server, but when I try to print from any of
them, all show printing errors (Unable to create printer driver / TERM error / etc)
The LPT1 port is redirected to a shared printer via NET USE LPT1 \ServerName\SharedPrinter
DIR > LPT1 (or any shell redirection to the printer) is working fine.
I'm using an Administrator account, so it shouldn't be a permissions problem, right?
To reproduce the behavior, I made a small test program in C (TCC 1.01 for DOS). It runs fine
in XP / 2003 Server, but on 2008 Server it shows the handle opening (5) but when is trying
to write in that handle, issues an error (Write fault error writing device LPT1, Abort, Retry,
Ignore, Fail)
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
int main(void)
{
int handle, status;
char* sbuff;
handle = open("LPT1", O_WRONLY, S_IFBLK);
printf("%d\n", handle);
if (!handle)
{
printf("open failed\n");
exit(1);
}
sbuff = "[print test]\n";
write(handle, sbuff, strlen(sbuff));
close(handle);
getch();
return 0;
}
Any clues?
TIA,
Pablo
Mike A - I have discovered that syntax 'print /d:{lpt?} {filename}' is not working on Win2008, not from within a 16bit app OR from the command line. This syntax has been supported for years and we run it in 10 Win2003 servers. Might there be a configuration setting in Win2008 that would make it syntax compatible with previous versions of Windows? BTW, here is Microsoft Tech Bulletin that was updated April 2012 that list the syntax as being compatible with Win2008... http://technet.microsoft.com/en-us/library/cc731623.

Resources