/**
 * Install the VBox video driver.
 *
 * @returns TRUE on success.
 * @returns FALSE on failure.
 * @param   szDriverDir     The base directory where we find the INF.
 */
BOOL installVideoDriver(TCHAR* szDriverDir)
{
  HDEVINFO hDevInfo;
  SP_DEVINSTALL_PARAMS DeviceInstallParams={0};
  SP_DRVINFO_DATA drvInfoData={0};
  SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0};

  DWORD cbReqSize;

  /* Vars used for reading the INF */
  HINF hInf;
  TCHAR szServiceSection[LINE_LEN];
  INFCONTEXT serviceContext;
  TCHAR szServiceData[LINE_LEN];
  TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody...

  SP_DEVINFO_DATA deviceInfoData;
  DWORD configFlags;

  HKEY hkey;
  DWORD disp;
  TCHAR regKeyName[LINE_LEN];

  BOOL rc;

  /* Create an empty list */
  hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY,
                                         NULL);

  if (hDevInfo == INVALID_HANDLE_VALUE)
    return FALSE;

  memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
  DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

  rc=SetupDiGetDeviceInstallParams(hDevInfo,
                                   NULL,
                                   &DeviceInstallParams);

  if(!rc)
    return FALSE;

  DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */
    DI_DONOTCALLCONFIGMG |
    DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */


  /* Path to inf file */
  wsprintf(DeviceInstallParams.DriverPath,
           TEXT("%ws\\%ws"),
           szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));

  rc=SetupDiSetDeviceInstallParams(hDevInfo,
                                   NULL,
                                   &DeviceInstallParams);
  if(!rc)
    return FALSE;

  /* Read the drivers from the inf file */
  if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
    {
      SetupDiDestroyDeviceInfoList(hDevInfo);
      return FALSE;
    }

  /* Get the first found driver.
     Our Inf file only contains one so this is fine  */
  drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
                                  0, &drvInfoData)){
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return FALSE;
  }

  /* Get necessary driver details */
  DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  if (!(!SetupDiGetDriverInfoDetail(hDevInfo,
                                    NULL,
                                    &drvInfoData,
                                    &DriverInfoDetailData,
                                    DriverInfoDetailData.cbSize,
                                    &cbReqSize)
        &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) )
    {
      SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
      SetupDiDestroyDeviceInfoList(hDevInfo);
      return FALSE;
    }

  hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
                          NULL, INF_STYLE_WIN4, NULL);

  if (hInf == INVALID_HANDLE_VALUE)
    {
      SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
      SetupDiDestroyDeviceInfoList(hDevInfo);
      return FALSE;
    }

  /* First install the service */
  wsprintf(szServiceSection, TEXT("%ws.Services"),
           DriverInfoDetailData.SectionName);

  if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext))
    {
      /* No service line?? Can't be... */
      closeAndDestroy(hDevInfo, hInf);
      return FALSE;
    }

  /* Get the name */
  SetupGetStringField(&serviceContext,
                      1,
                      szServiceData,
                      sizeof(szServiceData),
                      NULL);

  wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData);

  memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
  deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

  if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing
      ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr,                      //Create new
                                 (LPGUID) &GUID_DEVCLASS_DISPLAY,
                                 NULL, //Do we need a description here?
                                 NULL, //No user interface
                                 0,
                                 &deviceInfoData) &&
         SetupDiRegisterDeviceInfo(hDevInfo,
                                   &deviceInfoData,
                                   0,
                                   NULL,
                                   NULL,
                                   NULL)) )
    {
      /* We created a new key in the registry */

      memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS));
      DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

      SetupDiGetDeviceInstallParams(hDevInfo,
                                    &deviceInfoData,
                                    &DeviceInstallParams);

      DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files
        DI_DONOTCALLCONFIGMG |
        DI_ENUMSINGLEINF; //Use our INF file only

      /* Path to inf file */
      wsprintf(DeviceInstallParams.DriverPath,
               TEXT("%ws\\%ws"),
               szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));

      SetupDiSetDeviceInstallParams(hDevInfo,
                                    &deviceInfoData,
                                    &DeviceInstallParams);


      if(!SetupDiBuildDriverInfoList(hDevInfo,
                                     &deviceInfoData,
                                     SPDIT_CLASSDRIVER))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
      if (!SetupDiEnumDriverInfo(hDevInfo,
                                 &deviceInfoData,
                                 SPDIT_CLASSDRIVER,
                                 0,
                                 &drvInfoData))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      if(!SetupDiSetSelectedDriver(hDevInfo,
                                   &deviceInfoData,
                                   &drvInfoData))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      if(!SetupDiInstallDevice(hDevInfo,
                               &deviceInfoData))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }
    }

  /* Make sure the device is enabled */
  if (SetupDiGetDeviceRegistryProperty(hDevInfo,
                                       &deviceInfoData, SPDRP_CONFIGFLAGS,
                                       NULL, (LPBYTE) &configFlags,
                                       sizeof(DWORD),
                                       NULL)
      && (configFlags & CONFIGFLAG_DISABLED))
    {
      configFlags &= ~CONFIGFLAG_DISABLED;

      SetupDiSetDeviceRegistryProperty(hDevInfo,
                                       &deviceInfoData,
                                       SPDRP_CONFIGFLAGS,
                                       (LPBYTE) &configFlags,
                                       sizeof(DWORD));
    }

  wsprintf(regKeyName,
           TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"),
           szServiceData, 0); //We only have one device

  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     regKeyName,
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      /* Insert description */
      RegSetValueEx(hkey,
                    TEXT("Device Description"),
                    0,
                    REG_SZ,
                    (LPBYTE) DriverInfoDetailData.DrvDescription,
                    (lstrlen(DriverInfoDetailData.DrvDescription) + 1) *
                    sizeof(TCHAR) );

      TCHAR szSoftwareSection[LINE_LEN];

      wsprintf(szSoftwareSection,
               TEXT("%ws.SoftwareSettings"),
               szServiceData);

      if (!SetupInstallFromInfSection(NULL,
                                      hInf,
                                      szSoftwareSection,
                                      SPINST_REGISTRY,
                                      hkey,
                                      NULL,
                                      0,
                                      NULL,
                                      NULL,
                                      NULL,
                                      NULL))
        {
          RegCloseKey(hkey);
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      RegCloseKey(hkey);
    }

  /* Install OpenGL stuff */
  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"),
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      /* Do installation here if ever necessary. Currently there is no OpenGL stuff */

      RegCloseKey(hkey);
    }


  /* Cleanup */
  closeAndDestroy(hDevInfo, hInf);

#if 0
  /* If this key is inserted into the registry, windows will show the desktop
     applet on next boot. We decide in the installer if we want that so the code
     is disabled here. */
  /* Set registry keys so windows picks up the changes */
  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"),
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      RegCloseKey(hkey);
    }
#endif

  /* We must reboot at some point */
  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"),
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      RegCloseKey(hkey);
    }

  return TRUE;
}
Exemple #2
0
BOOL FindCurrentDriver(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ PSP_DRVINFO_DATA DriverInfoData)
/*++

Routine Description:

    Find the driver that is associated with the current device
    We can do this either the quick way (available in WinXP)
    or the long way that works in Win2k.

Arguments:

    Devs    )_ uniquely identify device
    DevInfo )

Return Value:

    TRUE if we managed to determine and select current driver

--*/
{
    SP_DEVINSTALL_PARAMS deviceInstallParams;
    WCHAR SectionName[LINE_LEN];
    WCHAR DrvDescription[LINE_LEN];
    WCHAR MfgName[LINE_LEN];
    WCHAR ProviderName[LINE_LEN];
    HKEY hKey = NULL;
    DWORD RegDataLength;
    DWORD RegDataType;
    DWORD c;
    BOOL match = FALSE;
    long regerr;

    ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams));
    deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

    if(!SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
        return FALSE;
    }

#ifdef DI_FLAGSEX_INSTALLEDDRIVER
    //
    // Set the flags that tell SetupDiBuildDriverInfoList to just put the
    // currently installed driver node in the list, and that it should allow
    // excluded drivers. This flag introduced in WinXP.
    //
    deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);

    if(SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
        //
        // we were able to specify this flag, so proceed the easy way
        // we should get a list of no more than 1 driver
        //
        if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) {
            return FALSE;
        }
        if (!SetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER,
                                   0, DriverInfoData)) {
            return FALSE;
        }
        //
        // we've selected the current driver
        //
        return TRUE;
    }
    deviceInstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
#endif
    //
    // The following method works in Win2k, but it's slow and painful.
    //
    // First, get driver key - if it doesn't exist, no driver
    //
    hKey = SetupDiOpenDevRegKey(Devs,
                                DevInfo,
                                DICS_FLAG_GLOBAL,
                                0,
                                DIREG_DRV,
                                KEY_READ
                               );

    if(hKey == INVALID_HANDLE_VALUE) {
        //
        // no such value exists, so there can't be an associated driver
        //
        RegCloseKey(hKey);
        return FALSE;
    }

    //
    // obtain path of INF - we'll do a search on this specific INF
    //
    RegDataLength = sizeof(deviceInstallParams.DriverPath); // bytes!!!
    regerr = RegQueryValueEx(hKey,
                             REGSTR_VAL_INFPATH,
                             NULL,
                             &RegDataType,
                             (PBYTE)deviceInstallParams.DriverPath,
                             &RegDataLength
                             );

    if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
        //
        // no such value exists, so no associated driver
        //
        RegCloseKey(hKey);
        return FALSE;
    }

    //
    // obtain name of Provider to fill into DriverInfoData
    //
    RegDataLength = sizeof(ProviderName); // bytes!!!
    regerr = RegQueryValueEx(hKey,
                             REGSTR_VAL_PROVIDER_NAME,
                             NULL,
                             &RegDataType,
                             (PBYTE)ProviderName,
                             &RegDataLength
                             );

    if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
        //
        // no such value exists, so we don't have a valid associated driver
        //
        RegCloseKey(hKey);
        return FALSE;
    }

    //
    // obtain name of section - for final verification
    //
    RegDataLength = sizeof(SectionName); // bytes!!!
    regerr = RegQueryValueEx(hKey,
                             REGSTR_VAL_INFSECTION,
                             NULL,
                             &RegDataType,
                             (PBYTE)SectionName,
                             &RegDataLength
                             );

    if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
        //
        // no such value exists, so we don't have a valid associated driver
        //
        RegCloseKey(hKey);
        return FALSE;
    }

    //
    // driver description (need not be same as device description)
    // - for final verification
    //
    RegDataLength = sizeof(DrvDescription); // bytes!!!
    regerr = RegQueryValueEx(hKey,
                             REGSTR_VAL_DRVDESC,
                             NULL,
                             &RegDataType,
                             (PBYTE)DrvDescription,
                             &RegDataLength
                             );

    RegCloseKey(hKey);

    if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) {
        //
        // no such value exists, so we don't have a valid associated driver
        //
        return FALSE;
    }

    //
    // Manufacturer (via SPDRP_MFG, don't access registry directly!)
    //

    if(!SetupDiGetDeviceRegistryProperty(Devs,
                                        DevInfo,
                                        SPDRP_MFG,
                                        NULL,      // datatype is guaranteed to always be REG_SZ.
                                        (PBYTE)MfgName,
                                        sizeof(MfgName), // bytes!!!
                                        NULL)) {
        //
        // no such value exists, so we don't have a valid associated driver
        //
        return FALSE;
    }

    //
    // now search for drivers listed in the INF
    //
    //
    deviceInstallParams.Flags |= DI_ENUMSINGLEINF;
    deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;

    if(!SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) {
        return FALSE;
    }
    if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) {
        return FALSE;
    }

    //
    // find the entry in the INF that was used to install the driver for
    // this device
    //
    for(c=0;SetupDiEnumDriverInfo(Devs,DevInfo,SPDIT_CLASSDRIVER,c,DriverInfoData);c++) {
        if((_tcscmp(DriverInfoData->MfgName,MfgName)==0)
            &&(_tcscmp(DriverInfoData->ProviderName,ProviderName)==0)) {
            //
            // these two fields match, try more detailed info
            // to ensure we have the exact driver entry used
            //
            SP_DRVINFO_DETAIL_DATA detail;
            detail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
            if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,DriverInfoData,&detail,sizeof(detail),NULL)
                    && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
                continue;
            }
            if((_tcscmp(detail.SectionName,SectionName)==0) &&
                (_tcscmp(detail.DrvDescription,DrvDescription)==0)) {
                match = TRUE;
                break;
            }
        }
    }
    if(!match) {
        SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_CLASSDRIVER);
    }
    return match;
}
/**
 * Do some cleanup of data we used. Called by installVideoDriver()
 */
void closeAndDestroy(HDEVINFO hDevInfo, HINF hInf)
{
  SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
  SetupDiDestroyDeviceInfoList(hDevInfo);
  SetupCloseInfFile(hInf);
}
Exemple #4
0
static HRESULT vboxDrvCfgCollectInfsSetupDi(const GUID * pGuid, LPCWSTR pPnPId, VBoxDrvCfgStringList & list)
{
    DWORD dwErr = ERROR_SUCCESS;
    HDEVINFO hDevInfo = SetupDiCreateDeviceInfoList(
                            pGuid, /* IN LPGUID ClassGuid, OPTIONAL */
                            NULL /*IN HWND hwndParent OPTIONAL */
                            );
    if (hDevInfo != INVALID_HANDLE_VALUE)
    {
        if (SetupDiBuildDriverInfoList(hDevInfo,
                    NULL, /*IN OUT PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
                    SPDIT_CLASSDRIVER  /*IN DWORD DriverType*/
                    ))
        {
            SP_DRVINFO_DATA DrvInfo;
            DrvInfo.cbSize = sizeof(SP_DRVINFO_DATA);
            char DetailBuf[16384];
            PSP_DRVINFO_DETAIL_DATA pDrvDetail = (PSP_DRVINFO_DETAIL_DATA)DetailBuf;

            for (DWORD i = 0; ; i++)
            {
                if (SetupDiEnumDriverInfo(hDevInfo,
                        NULL, /* IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
                        SPDIT_CLASSDRIVER , /*IN DWORD DriverType,*/
                        i, /*IN DWORD MemberIndex,*/
                        &DrvInfo /*OUT PSP_DRVINFO_DATA DriverInfoData*/
                        ))
                {
                    DWORD dwReq;
                    pDrvDetail->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
                    if (SetupDiGetDriverInfoDetail(
                            hDevInfo, /*IN HDEVINFO DeviceInfoSet,*/
                            NULL, /*IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
                            &DrvInfo, /*IN PSP_DRVINFO_DATA DriverInfoData,*/
                            pDrvDetail, /*OUT PSP_DRVINFO_DETAIL_DATA DriverInfoDetailData, OPTIONAL*/
                            sizeof(DetailBuf), /*IN DWORD DriverInfoDetailDataSize,*/
                            &dwReq /*OUT PDWORD RequiredSize OPTIONAL*/
                            ))
                    {
                        for (WCHAR * pHwId = pDrvDetail->HardwareID; pHwId && *pHwId && pHwId < (TCHAR*)(DetailBuf + sizeof(DetailBuf)/sizeof(DetailBuf[0])) ;pHwId += wcslen(pHwId) + 1)
                        {
                            if (!wcsicmp(pHwId, pPnPId))
                            {
                                NonStandardAssert(pDrvDetail->InfFileName[0]);
                                if (pDrvDetail->InfFileName)
                                {
                                    list.add(pDrvDetail->InfFileName);
                                    NonStandardLogRelCrap((__FUNCTION__": %S added to list", pDrvDetail->InfFileName));
                                }
                            }
                        }
                    }
                    else
                    {
                        DWORD dwErr = GetLastError();
                        NonStandardLogRelCrap((__FUNCTION__": SetupDiGetDriverInfoDetail fail dwErr=%ld, size(%d)", dwErr, dwReq));
//                        NonStandardAssert(0);
                    }

                }
                else
                {
                    DWORD dwErr = GetLastError();
                    if (dwErr == ERROR_NO_MORE_ITEMS)
                    {
                        NonStandardLogRelCrap((__FUNCTION__": dwErr == ERROR_NO_MORE_ITEMS -> search was finished "));
                        break;
                    }

                    NonStandardAssert(0);
                }
            }

            SetupDiDestroyDriverInfoList(hDevInfo,
                      NULL, /*IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL*/
                      SPDIT_CLASSDRIVER/*IN DWORD DriverType*/
                      );
        }
        else
        {
            dwErr = GetLastError();
            NonStandardAssert(0);
        }

        SetupDiDestroyDeviceInfoList(hDevInfo);
    }
    else
    {
        dwErr = GetLastError();
        NonStandardAssert(0);
    }

    return HRESULT_FROM_WIN32(dwErr);
}