Programatically installing WDF Driver

If you had to program the installation of a WDF driver, you might found the same problems that I had. When installing using driver.inf it works. But when trying to install calling CreateService the driver sometimes is corrupted. After a long research I found that happens because WdfCoInstaller is missing.

The documentation says that before install a driver using CreateService you have to surround with WdfPreDeviceInstall and WdfPostDeviceInstall. The same when removing it using DeleteService, in this case surrounding with WdfPreDeviceRemove and WdfPostDeviceRemove. Those function are defined in <wdfinstaller.h> and implemented inside the WdfCoInstaller.dll. But no .lib is available to static link your program to the dll.

The only way to use those methods is linking in runtime using LoadLibrary and access those function through function pointer. Thankfully, Microsoft already provide the definition of those function pointer as  PFN_WDF[FUNCTION]. I couldn’t find any example of it, so I showing below an example about how to use it.

#include <Windows.h>
#include <wdfinstaller.h>

#define DRIVER_SERVICE_NAME L"MyDriver"
#define DRIVER_DISPLAY_NAME L"MyDriver Device"
#define DRIVER_SYS_LOCATION L"\system32\DRIVERS\MyDriver.sys"

DWORD install_driver(
    LPCWSTR infPath,
    LPCWSTR infWdfSection,
    SC_HANDLE serviceManager) {
  // Load Dll
  auto wdfCoInstallerDll = LoadLibrary("WdfCoInstaller01009.dll");

  if (!wdfCoInstallerDll)
  {
    return GetLastError();
  }

  auto fpWdfPreDeviceInstall =
    reinterpret_cast<PFN_WDFPREDEVICEINSTALL>(
      GetProcAddress(wdfCoInstallerDll, "WdfPreDeviceInstall"));
  auto fpWdfPostDeviceInstall =
    reinterpret_cast<PFN_WDFPOSTDEVICEINSTALL>(
      GetProcAddress(wdfCoInstallerDll, "WdfPostDeviceInstall"));

  auto preInstallStatus = fpWdfPreDeviceInstall(infPath, infWdfSection);

  auto driverService = CreateService(
                          serviceManager,
                          DRIVER_SERVICE_NAME,
                          DRIVER_DISPLAY_NAME,
                          SC_MANAGER_ALL_ACCESS,
                          SERVICE_KERNEL_DRIVER,
                          SERVICE_DEMAND_START,
                          SERVICE_ERROR_NORMAL,
                          DRIVER_SYS_LOCATION,
                          NULL,
                          NULL,
                          NULL,
                          NULL);

  DWORD installStatus = ERROR_SUCCESS;
  if (driverService)
    CloseServiceHandle(driverService);
  else
    installStatus = GetLastError():

  auto postInstallStatus = fpWdfPostDeviceInstall(infPath, infWdfSection);

  // Release Dll
  FreeLibrary(wdfCoInstallerDll);

  return installStatus;
}

DWORD uninstall_driver(
    LPCWSTR infPath,
    LPCWSTR infWdfSection,
    SC_HANDLE driverService) {
  // Load Dll
  auto wdfCoInstallerDll = LoadLibrary("WdfCoInstaller01009.dll");

  if (!wdfCoInstallerDll)
  {
    return GetLastError();
  }

  auto fpWdfPreDeviceRemove =
    reinterpret_cast<PFN_WDFPREDEVICEREMOVE>(
      GetProcAddress(wdfCoInstallerDll, "WdfPreDeviceRemove"));
  auto fpWdfPostDeviceRemove =
    reinterpret_cast<PFN_WDFPOSTDEVICEREMOVE>(
      GetProcAddress(wdfCoInstallerDll, "WdfPostDeviceRemove"));

  auto preRemoveStatus = fpWdfPreDeviceRemove(infPath, infWdfSection);
  BOOL deleted = DeleteService(driverService);
  DWORD removeStatus = ERROR_SUCCESS;

  if (!deleted)
    removeStatus = GetLastError();

  auto postRemoveStatus = fpWdfPostDeviceRemove(infPath, infWdfSection);

  // Release Dll
  FreeLibrary(wdfCoInstallerDll);

  return removeStatus ? ERROR_SUCCESS : GetLastError();
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s