In my post about a basic driver shell, I assumed that the driver was built into the system including the registry settings to cause the device manager to load the driver when the system booted. Sometimes there is a reason to load a driver when an application starts. For that there are several functions that can be used including; RegisterDevice, ActivateDevice and ActivateDeviceEx.
RegisterDevice is maintained for backward compatibility, but for future compatibility you probably should start using ActivateDevice or ActivateDeviceEx.
The precondition for using ActiveateDeviceEx is that the registry contains settings for the driver and that the driver is in the system path; for more on the system path see the documentation for LoadLibrary(). Through trial and error, I found that the applications launch directory is not a valid location for the driver when using ActivateDeviceEx().
I want my application to not only load the driver but also unload it when finished, so I will keep a global variable with the driver handle. The following function will load DriverShell.dll:
#define DRIVERSHELL_REG_KEY (TEXT("Drivers\\Builtin\\DriverShell"))
HANDLE hDriverShell = INVALID_HANDLE_VALUE;
BOOL LoadDriverShell()
{
                BOOL RetVal = FALSE;
 
                if( hDriverShell == INVALID_HANDLE_VALUE )
                {
                                hDriverShell = ActivateDeviceEx( DRIVERSHELL_REG_KEY,
                                                                                                NULL,
                                                                                                0,
                                                                                                NULL
                                                                                                );
                                if (hDriverShell != INVALID_HANDLE_VALUE && hDriverShell != 0)
                                                RetVal = TRUE;
                                else
                                {
                                                // Note: the driver may have succeded to load if the handle is zero
                                                RETAILMSG( 1, (TEXT("Failed to activate driver %d\n"), GetLastError() ));
                                }
                }
                return RetVal;
}
The documentation states that the return value from ActivateDeviceEx is a valid handle if it succeeds or INVALID_HANDLE_VALUE on failure, but then goes on to discuss that the return could be zero under certain conditions. What I found when I had the driver in a folder that wasn’t in the system path was that the return value is zero for failure.
To then unload the driver:
void UnloadDriverShell()
{
                if( hDriverShell != INVALID_HANDLE_VALUE )
                {
                                DeactivateDevice( hDriverShell );
                                hDriverShell = INVALID_HANDLE_VALUE;
                }
}
I am running this on a headless system, so I found it was much simpler to include the registry settings in my code and put together the following to add the registry settings for the driver:
typedef struct {
                TCHAR *ValueName;
                DWORD Type;
                DWORD DwordValue;
                TCHAR *StringValue;
} RegEntry ;
 
 
RegEntry RegEntries[] = {
    {TEXT("Dll"), REG_SZ, 0, TEXT("DriverShell.dll") },
    {TEXT("Prefix"), REG_SZ, 0, TEXT("XXX") },
    {TEXT("Order"), REG_DWORD, 4, NULL },
                {NULL, 0, 0, NULL}
                };
 
void AddDriverShellToRegistry()
{
                HKEY      hTargetKey;
                DWORD                dwDisposition;
                DWORD                RetVal;
                DWORD Index=0;
                BYTE * Value;
                DWORD uSize;
 
                RetVal = RegCreateKeyEx(           HKEY_LOCAL_MACHINE,
                                                                                                DRIVERSHELL_REG_KEY,
                                                                                                0,
                                                                                                NULL,
                                                                                                REG_OPTION_NON_VOLATILE,
                                                                                                KEY_ALL_ACCESS ,
                                                                                                NULL,
                                                                                                &hTargetKey,
                                                                                                &dwDisposition
                                                                                                );
                if (RetVal == ERROR_SUCCESS)
                {
                                while( RegEntries[Index].ValueName != NULL )
                                {
                                                if( RegEntries[Index].Type == REG_DWORD )
                                                {
                                                                Value = (BYTE *)&RegEntries[Index].DwordValue;
                                                                uSize = sizeof( DWORD );
                                                }
                                                else
                                                {
                                                                Value = (BYTE *)RegEntries[Index].StringValue;
                                                                uSize = (wcslen( RegEntries[Index].StringValue ) + 1 ) * sizeof( TCHAR );
                                                }
                                               
                                                RetVal = RegSetValueEx(hTargetKey,
                                                                                                RegEntries[Index].ValueName,
                                                                                                0,
                                                                                                RegEntries[Index].Type,
                                                                                                (CONST BYTE *)Value,
                                                                                                uSize
                                                                                                );
                                                Index++;
                                }
                }
               
}
So now if you add a call to AddDriverShellToRegistry before calling ActivateDeviceEx the registry settings will be added and ready to use.
You can use the code in Windows CE: Listing Running Drivers to verify that the driver loaded successfully, or you can use ReadFile, WriteFile or DeviceIoControl to test that you can access the driver from your application.
For a nice dialog based example of this please see Checko's blog at Source : Load Unload Device Driver.

Tags:

Copyright © 2008 – Bruce Eitman
All Rights Reserved