Esempio n. 1
0
BOOL installDriver(HWND hWnd)
{
	TCHAR DriverPath[MAX_PATH];
	unsigned int i;

	EnableWindow(GetDlgItem(hWnd, IDB_INSTALL), FALSE);

	if (GetModuleFileName(NULL, DriverPath, MAX_PATH) == 0) {
		PrintLastError("DriverPackageInstall()");
		EnableWindow(GetDlgItem(hWnd, IDB_INSTALL), TRUE);
		return FALSE;
	}
	*_tcsrchr(DriverPath, _T('\\')) = _T('\0');
	*_tcscat(DriverPath, _T("\\CM8738.inf"));

	for (i=0;i<devArraySize;i++) {
		if (UpdateDriverForPlugAndPlayDevices(hWnd, devIDs[i], DriverPath, INSTALLFLAG_FORCE, NULL)) {
			EnableWindow(GetDlgItem(hWnd, IDB_INSTALL), TRUE);
			return TRUE;
		}
	}

	PrintLastError("DriverPackageInstall()");
	EnableWindow(GetDlgItem(hWnd, IDB_INSTALL), TRUE);
	return FALSE;
}
Esempio n. 2
0
BOOL eIDUpdateDriver(HWND hwndParent, char* hardwareID, char* infFilePath, DWORD flags, BOOL* bootRequired,DWORD* pLastErrorCode) {

	// make sure no driver install is in progress
	if (IsDeviceInstallInprogress(5000)) 
	{
		*pLastErrorCode = GetLastError();
		return FALSE;
	}
	// inform Windows & PnP about the new driver, so it can be installed when the device is plugged in
	if (!CopyInf(infFilePath)) 
	{
		*pLastErrorCode = GetLastError();
		return FALSE;
	}

	if (UpdateDriverForPlugAndPlayDevices(hwndParent, hardwareID, infFilePath, flags, bootRequired)) 
	{
		return TRUE;
	} 
	else 
	{
		*pLastErrorCode = GetLastError();
		if ( (*pLastErrorCode == ERROR_NO_SUCH_DEVINST) ||  (*pLastErrorCode == ERROR_NO_MORE_ITEMS) )
		{
			return TRUE;
		}
		return FALSE;
	}

}
Esempio n. 3
0
NDASDI_API
BOOL 
WINAPI 
NdasDiUpdateDeviceDriver(
	IN HWND hwnd,
	IN LPCTSTR szInfPath, 
	IN LPCTSTR szHardwareId,
	IN DWORD InstallFlags,
	IN PBOOL pbRebootRequired OPTIONAL)
{
	_ASSERTE(NULL == pbRebootRequired || !IsBadWritePtr(pbRebootRequired, sizeof(BOOL)));

	BOOL fReturn = FALSE;
	BOOL fSuccess = FALSE;

	LPTSTR lpszFullInfPath = ResolveFullPath(szInfPath);

	if (NULL == lpszFullInfPath) {
		goto cleanup;
	}

    fSuccess = UpdateDriverForPlugAndPlayDevices(
		hwnd,
		szHardwareId,
		lpszFullInfPath,
		InstallFlags,
		pbRebootRequired);
	
	if (!fSuccess) {
		goto cleanup;
	}

	fReturn = TRUE;

cleanup:

	// save the last error
	DWORD err = GetLastError();

	if (NULL != lpszFullInfPath) {
		LocalFree(lpszFullInfPath);
	}
	
	// restore the last error
	SetLastError(err);
	
	return fReturn;
}
Esempio n. 4
0
int installCMUDriver()
{
	LPCSTR compatibleIDList[3] = {
		"1394\\A02D&100",
		"1394\\A02D&101",
		"1394\\A02D&102"
	};

    HKEY hKey = OpenCameraSettingsKey("",0,KEY_READ);
    if(hKey != NULL)
    {
        char installPath[4096];
        DWORD dwFoo = 0,dwType = 0, dwSize = 4096;
        DWORD dwRet = RegQueryValueEx(hKey,"InstallPath",0,&dwType,(LPBYTE)installPath,&dwSize);
	    if(dwRet != ERROR_SUCCESS)
        {
            printf("Failed to load install path from registry!");
            return -1;
        }

        printf("Install path is:\n  '%s' (%d bytes long)\n",installPath,dwSize);
        strncpy(&(installPath[dwSize-1]),"\\Driver\\1394Camera.inf",4096 - dwSize);

	    BOOL rebootRequired = FALSE;
	    for(int ii = 0; ii < 3; ++ii)
	    {
		    BOOL reboot = FALSE;
    	    printf("\nUpdating Driver For CompatibleID '%s'\n  -> '%s'...\n",compatibleIDList[ii],installPath);
		    if(!UpdateDriverForPlugAndPlayDevices(NULL,compatibleIDList[ii],installPath,INSTALLFLAG_FORCE,&reboot))
		    {
                printf(" -> Failed to Update Driver! - %08x (%d)\n",GetLastError(),GetLastError() & 0x0000FFFF);
            } else {
                printf(" -> Success!\n");
            }
		    rebootRequired |= reboot;
	    }

	    if(rebootRequired)
	    {
		    printf("... technically speaking, you must now reboot!\n");
	    }
	    return 0;

    } else {
        printf("Failed to load camera registry key!");
        return -1;
    }
}
Esempio n. 5
0
int
InstallRootEnumeratedDriver(
    IN HWND hWnd,
    IN LPTSTR HardwareId,
    IN LPTSTR INFFile
    )
{
    HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
    SP_DEVINFO_DATA DeviceInfoData;
    GUID ClassGUID;
    TCHAR ClassName[MAX_CLASS_NAME_LEN];
    DWORD Err = NO_ERROR;
    BOOL reboot;
    LPTSTR MultiSzHardwareId = NULL;
    DWORD cbMultiSzHardwareId;

    //
    // SPDRP_HARDWAREID needs to be a multi_sz string so allocate a buffer that is
    // two characters more than the HardwareId passed in and use that buffer.
    //
    cbMultiSzHardwareId = (lstrlen(HardwareId) + 2) * sizeof(TCHAR);
    MultiSzHardwareId = malloc(cbMultiSzHardwareId);
    if (!MultiSzHardwareId) {
        MessageBox(hWnd, "Cannot allocate memory", "Error", MB_OK);
        Err = ERROR_NOT_ENOUGH_MEMORY;
        goto clean;
    }
    ZeroMemory(MultiSzHardwareId, cbMultiSzHardwareId);
    StringCbCopy(MultiSzHardwareId, cbMultiSzHardwareId, HardwareId);


    //
    // Use the INF File to extract the Class GUID. 
    //
    if (!SetupDiGetINFClass(INFFile, &ClassGUID, ClassName, sizeof(ClassName), 0)) {
        Err = GetLastError();
        DisplayError(hWnd, TEXT("GetINFClass"));
        DisplayError(hWnd, TEXT(INFFile));
        goto clean;
    }
    
    //
    // Create the container for the to-be-created Device Information Element.
    //
    DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID, 0);
    if(DeviceInfoSet == INVALID_HANDLE_VALUE) {
        Err = GetLastError();
        DisplayError(hWnd, TEXT("CreateDeviceInfoList"));
        goto clean;
    }
    
    // 
    // Now create the element. 
    // Use the Class GUID and Name from the INF file.
    //
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    if (!SetupDiCreateDeviceInfo(DeviceInfoSet,
                                 ClassName,
                                 &ClassGUID,
                                 NULL,
                                 0,
                                 DICD_GENERATE_ID,
                                 &DeviceInfoData)) {
        Err = GetLastError();
        DisplayError(hWnd, TEXT("CreateDeviceInfo"));
        goto clean;
    }
    
    //
    // Add the HardwareID to the Device's HardwareID property.
    //
    if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
                                         &DeviceInfoData,
                                         SPDRP_HARDWAREID,
                                         (LPBYTE)MultiSzHardwareId,
                                         cbMultiSzHardwareId)) {
        Err = GetLastError();
        DisplayError(hWnd, TEXT("SetDeviceRegistryProperty"));
        goto clean;
    }
    
    //
    // Transform the registry element into an actual devnode 
    // in the PnP HW tree.
    //
    if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
                                   DeviceInfoSet,
                                   &DeviceInfoData)) {
        Err = GetLastError();
        DisplayError(hWnd, TEXT("CallClassInstaller(REGISTERDEVICE)"));
        goto clean;
    }
    
    //
    // The element is now registered. We must explicitly remove the 
    // device using DIF_REMOVE, if we encounter any failure from now on.
    //
    
    //
    // Install the Driver.  We don't actually care about @reboot, but
    // supplying it avoids an annoying popup on Windows 2000.
    //
    if (!UpdateDriverForPlugAndPlayDevices(hWnd,
                                           HardwareId,
                                           INFFile,
                                           INSTALLFLAG_FORCE,
                                           &reboot))
    {
        Err = GetLastError();
        DisplayError(hWnd, TEXT("UpdateDriverForPlugAndPlayDevices"));
        
        if (!SetupDiCallClassInstaller(DIF_REMOVE,
                                       DeviceInfoSet,
                                       &DeviceInfoData)) {
            DisplayError(hWnd, TEXT("CallClassInstaller(REMOVE)"));
        }
    }
    
    //
    //  Cleanup.
    //    
clean:
    if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
        SetupDiDestroyDeviceInfoList(DeviceInfoSet);
    }

    if (MultiSzHardwareId) {
        free(MultiSzHardwareId);
    }
    
    if (Err == NO_ERROR) {
        return 0;
    } else {
        return 1;
    }
}
Esempio n. 6
0
int
InstallPnPDriver(
    IN HWND hWnd,
    PTSTR HardwareId, 
    PTSTR Inf,
    BOOL DelayInstall,
    BOOL ForceUpdateDriver
    )
{
    DWORD Err = NO_ERROR;
    SP_DEVINFO_DATA DeviceInfoData;
    HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
    TCHAR DeviceIds[REGSTR_VAL_MAX_HCID_LEN];
    DWORD memberIndex;
    PTSTR singleDeviceId;

    DeviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_ALLCLASSES);
    if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
        Err = GetLastError();
        goto clean;
    }

    memberIndex = 0;
    DeviceInfoData.cbSize = sizeof(DeviceInfoData);
    while (SetupDiEnumDeviceInfo(DeviceInfoSet,
                                 memberIndex++,
                                 &DeviceInfoData)) {
        if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
                                             &DeviceInfoData,
                                             SPDRP_HARDWAREID,
                                             NULL,
                                             (PBYTE)DeviceIds,
                                             sizeof(DeviceIds),
                                             NULL)) {
            for (singleDeviceId = DeviceIds;
                 *singleDeviceId;
                 singleDeviceId += lstrlen(singleDeviceId) + 1) {

                if (!lstrcmpi(HardwareId, singleDeviceId)) {
                    //
                    // Found a match.  Check if it is a phantom if PhantomOnly is
                    // TRUE
                    //
                    if (InstallInfOnDevice(hWnd, 
                                           DeviceInfoSet,
                                           &DeviceInfoData,
                                           Inf,
                                           DelayInstall) != NO_ERROR) {
                        MessageBox(hWnd, "Failed to install drivers on one of the devices", "Install Error", MB_OK);
                    }
                    if (ForceUpdateDriver)
                    {
                        BOOL reboot;
                        if (!UpdateDriverForPlugAndPlayDevices(
                                               hWnd,
                                               HardwareId,
                                               Inf,
                                               INSTALLFLAG_FORCE,
                                               &reboot))
                            MessageBox(hWnd, "Failed to force update driver for one of the devices", "Install Error", MB_OK);
                    }
                }
            }
        }
    }

clean:
    if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
        SetupDiDestroyDeviceInfoList(DeviceInfoSet);
    }

    if (Err == NO_ERROR) {
        return 0;
    }
    return 1;
}
Esempio n. 7
0
NDASDI_API
BOOL 
WINAPI 
NdasDiInstallRootEnumeratedDevice(
	IN HWND hwndParent,
	IN LPCTSTR szInfPath, 
	IN LPCTSTR szHardwareId,
	IN DWORD InstallFlags,
	IN LPBOOL pbRebootRequired OPTIONAL)
{
	_ASSERTE(NULL == pbRebootRequired || !IsBadWritePtr(pbRebootRequired, sizeof(BOOL)));

	BOOL fReturn = FALSE;
	BOOL fSuccess = FALSE;

    DWORD len;

    SP_DEVINFO_DATA DeviceInfoData;
    GUID ClassGuid;
    TCHAR ClassName[MAX_CLASS_NAME_LEN];
	
	LPTSTR lpszFullInfPath = ResolveFullPath(szInfPath, NULL, NULL, 0);
	if (NULL == lpszFullInfPath) {
		goto cleanup;
	}

    //
    // List of hardware ID's must be double zero-terminated
    //
    TCHAR hardwareIdList[LINE_LEN+4] = {0};
	size_t cchHardwareIdList = RTL_NUMBER_OF(hardwareIdList);
	size_t cchRemaining = cchHardwareIdList;
	
	HRESULT hr = StringCchCopyNEx(
		hardwareIdList, 
		LINE_LEN + 4, 
		szHardwareId, 
		LINE_LEN,
		NULL,
		&cchRemaining,
		STRSAFE_FILL_BEHIND_NULL);

	_ASSERTE(SUCCEEDED(hr));

	cchHardwareIdList -= cchRemaining - 1;

    //
    // Use the INF File to extract the Class GUID.
    //
    fSuccess = SetupDiGetINFClass(
		lpszFullInfPath,
		&ClassGuid,
		ClassName,
		RTL_NUMBER_OF(ClassName),
		NULL);

	if (!fSuccess) {
		goto cleanup;
	}
	
    //
    // Create the container for the to-be-created Device Information Element.
    //
    HDEVINFO DeviceInfoSet = SetupDiCreateDeviceInfoList(
		&ClassGuid,
		hwndParent);

    if(INVALID_HANDLE_VALUE == DeviceInfoSet) {
		goto cleanup;
    }

    //
    // Now create the element.
    // Use the Class GUID and Name from the INF file.
    //
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    fSuccess = SetupDiCreateDeviceInfo(
		DeviceInfoSet,
        ClassName,
        &ClassGuid,
        NULL,
        hwndParent,
        DICD_GENERATE_ID,
        &DeviceInfoData);

	if (!fSuccess) {
		goto cleanup;
	}

    //
    // Add the HardwareID to the Device's HardwareID property.
    //
    fSuccess = SetupDiSetDeviceRegistryProperty(
		DeviceInfoSet,
        &DeviceInfoData,
        SPDRP_HARDWAREID,
        (LPBYTE)hardwareIdList,
        cchHardwareIdList * sizeof(TCHAR));
	
	if (!fSuccess) {
		goto cleanup;
	}

    //
    // Transform the registry element into an actual devnode
    // in the PnP HW tree.
    //
	fSuccess = SetupDiCallClassInstaller(
		DIF_REGISTERDEVICE,
        DeviceInfoSet,
        &DeviceInfoData);
	
	if (!fSuccess) {
		goto cleanup;
	}

	//
	// The element is now registered.
	// You must explicitly remove the device using DIF_REMOVE,
	// if any failure is encountered from now on.
	//

	//
    // update the driver for the device we just created
    //

	fSuccess = UpdateDriverForPlugAndPlayDevices(
		hwndParent,
		szHardwareId,
		lpszFullInfPath,
		InstallFlags,
		pbRebootRequired);

	if (!fSuccess) {
		DWORD err = GetLastError();
		fSuccess = SetupDiCallClassInstaller(
			DIF_REMOVE,
			DeviceInfoSet,
			&DeviceInfoData);
		//
		// BUGBUG: If it may still require reboot?
		//
		SetLastError(err);
		goto cleanup;
	}

	fReturn = TRUE;
	
cleanup:

	// save the last error
	DWORD err = GetLastError();

	if (INVALID_HANDLE_VALUE != DeviceInfoSet) {
		SetupDiDestroyDeviceInfoList(DeviceInfoSet);
	}

	if (NULL != lpszFullInfPath) {
		LocalFree(lpszFullInfPath);
	}

	// restore the last error
	SetLastError(err);

	return fReturn;
}
Esempio n. 8
0
int UpdateDriver(
    const char *pInfFilePath,
    const char *pHardwareId,
    DWORD flags,
    bool mandatory,
    BOOL *pRebootRequired)
{
  DWORD updateErr = ERROR_SUCCESS;

  for (int i = 0 ; i < 10 ; i++) {
    if (UpdateDriverForPlugAndPlayDevices(0, pHardwareId, pInfFilePath, flags, pRebootRequired))
    {
      updateErr = ERROR_SUCCESS;
    } else {
      updateErr = GetLastError();

      if (updateErr == ERROR_SHARING_VIOLATION) {
        Trace(".");
        Sleep(1000);
        continue;
      }
      else
      if (!mandatory) {
        if (updateErr == ERROR_NO_SUCH_DEVINST) {
          updateErr = ERROR_SUCCESS;
        }
        else
        if (updateErr == ERROR_NO_MORE_ITEMS && (flags & INSTALLFLAG_FORCE) == 0) {
          updateErr = ERROR_SUCCESS;
        }
      }
    }

    if (i)
      Trace("\n");

    break;
  }

  if (updateErr != ERROR_SUCCESS) {
    if (updateErr == ERROR_FILE_NOT_FOUND) {
      LONG err;
      HKEY hKey;

      err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNONCE, 0, KEY_READ, &hKey);

      if (err == ERROR_SUCCESS)
        RegCloseKey(hKey);

      if (err == ERROR_FILE_NOT_FOUND) {
        int res = ShowMsg(MB_CANCELTRYCONTINUE,
                          "Can't update driver. Possible it's because your Windows registry is corrupted and\n"
                          "there is not the following key:\n"
                          "\n"
                          "HKEY_LOCAL_MACHINE\\" REGSTR_PATH_RUNONCE "\n"
                          "\n"
                          "Continue to add the key to the registry.\n");

        if (res == 0)
          return IDCANCEL;

        if (res == IDCONTINUE) {
          err = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNONCE, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL);

          if (err == ERROR_SUCCESS) {
            RegCloseKey(hKey);
            return IDTRYAGAIN;
          } else {
            ShowLastError(MB_OK|MB_ICONSTOP, "RegCreateKeyEx()");
            return IDCANCEL;
          }
        }

        return res;
      }
    }

    return ShowError(MB_CANCELTRYCONTINUE, updateErr,
                     "UpdateDriverForPlugAndPlayDevices(\"%s\", \"%s\", 0x%lX)",
                     pHardwareId, pInfFilePath, (long)flags);
  }

  return IDCONTINUE;
}
Esempio n. 9
0
DWORD
WINAPI
UpdateDriverThreadProc(
    _In_ LPVOID ThreadData
)

/*++

Routine Description:

    This function updates the drivers for any existing toasters.  If there are
    no toasters currently connected to the computer, it installs the INF/CAT so
    that the system will be ready to automatically install toasters that are
    plugged in later.  This routine will also mark any non-present (aka,
    "phantom") toasters as needs-reinstall, so that they'll be updated to the
    new driver if they're ever plugged in again.

Arguments:

    ThreadData - Supplies a pointer to a SHAREDWIZDATA structure that's used
        both by this thread, and by the wizard in the main thread.

Return Value:

    If successful, the function returns NO_ERROR.

    Otherwise, the function returns a Win32 error code indicating the cause of
    failure.

--*/

{
    DWORD Err;
    LPSHAREDWIZDATA pdata;
    WCHAR FullInfPath[MAX_PATH];
    HDEVINFO ExistingNonPresentDevices;


    pdata = (LPSHAREDWIZDATA)ThreadData;
    Err = NO_ERROR;

    //
    // First, attempt to update any present devices to our driver...
    //
    if (FAILED(StringCchCopy(FullInfPath, MAX_PATH, pdata->MediaRootDirectory))) {
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    if (FAILED(StringCchCat(FullInfPath, MAX_PATH, DEVICE_INF_NAME))) {
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    if(UpdateDriverForPlugAndPlayDevices(GetParent(pdata->hwndDlg),
                                         HW_ID_TO_UPDATE,
                                         FullInfPath,
                                         0,
                                         &pdata->RebootRequired)) {
        //
        // We know that at least one device existed, and was upgraded.
        //
        pdata->HwInsertedFirst = TRUE;

    } else {

        Err = GetLastError();

        //
        // We failed to update the driver.  If we failed simply because
        // there were no toasters currently attached to the computer, then
        // we still want to install the INF.
        //
        if(Err == ERROR_NO_SUCH_DEVINST) {

            pdata->HwInsertedFirst = FALSE;

            //
            // Since we didn't do any device installs, the INF (and CAT)
            // didn't get automatically installed.  We'll install them now,
            // so that they'll be present when the user subsequently plugs
            // their hardware in.
            //
            if(!SetupCopyOEMInf(FullInfPath,
                                NULL,
                                SPOST_PATH,
                                0,
                                NULL,
                                0,
                                NULL,
                                NULL)) {
                //
                // Failure to install the INF is more important (worse) than
                // the absence of any devices!
                //
                Err = GetLastError();
            }

        } else {
            //
            // Apparently there _were_ existing devices--we just failed to
            // upgrade their drivers.  This might be due to an installation
            // problem, or perhaps because the devices already have drivers
            // newer than the one we offered.
            //
            pdata->HwInsertedFirst = TRUE;
        }
    }

    if((Err == NO_ERROR) || (Err == ERROR_NO_SUCH_DEVINST)) {
        //
        // Either we successfully upgraded one or more toasters, or there were
        // no present toasters but we successfully installed our INF and CAT.
        //
        // There may exist, however, devices that were once connected to the
        // computer, but presently are not.  If such devices are connected
        // again in the future, we want to ensure they go through device
        // installation.  We will retrieve the list of non-present devices, and
        // mark each as "needs re-install" to kick them back through the "New
        // Hardware Found" process if they ever show up again.  (Note that this
        // doesn't destroy any device-specific settings they may have, so this
        // is just forcing an upgrade, not an uninstall/re-install.)
        //
        // (The HardwareID used is the one defined for the toaster sample,
        // BUS_HARDWARE_IDS in src\general\toaster\bus\common.h.  We also take
        // advantage of the fact that we know these devices will always be
        // enumerated under the "{b85b7c50-6a01-11d2-b841-00c04fad5171}"
        // enum namespace.)
        //
        ExistingNonPresentDevices = GetNonPresentDevices(ENUMERATOR_NAME,
                                    HW_ID_TO_UPDATE
                                                        );

        if(ExistingNonPresentDevices != INVALID_HANDLE_VALUE) {

            MarkDevicesAsNeedReinstall(ExistingNonPresentDevices);

            SetupDiDestroyDeviceInfoList(ExistingNonPresentDevices);
        }
    }

    PostMessage(pdata->hwndDlg, WMX_UPDATE_DRIVER_DONE, 0, 0);

    return Err;
}
Esempio n. 10
0
int usb_install_driver_np(const char *inf_file)
{
  HDEVINFO dev_info;
  SP_DEVINFO_DATA dev_info_data;
  INFCONTEXT inf_context;
  HINF inf_handle;
  DWORD config_flags, problem, status;
  BOOL reboot;
  char inf_path[MAX_PATH];
  char id[MAX_PATH];
  char tmp_id[MAX_PATH];
  char *p;
  int dev_index;
  HINSTANCE newdev_dll = NULL;
  HMODULE setupapi_dll = NULL;

  update_driver_for_plug_and_play_devices_t UpdateDriverForPlugAndPlayDevices;
  setup_copy_oem_inf_t SetupCopyOEMInf;
  newdev_dll = LoadLibrary("newdev.dll");

  if(!newdev_dll)
    {
      usb_error("usb_install_driver(): loading newdev.dll failed\n");
      return -1;
    }
  
  UpdateDriverForPlugAndPlayDevices =  
    (update_driver_for_plug_and_play_devices_t) 
    GetProcAddress(newdev_dll, "UpdateDriverForPlugAndPlayDevicesA");

  if(!UpdateDriverForPlugAndPlayDevices)
    {
      usb_error("usb_install_driver(): loading newdev.dll failed\n");
      return -1;
    }

  setupapi_dll = GetModuleHandle("setupapi.dll");
  
  if(!setupapi_dll)
    {
      usb_error("usb_install_driver(): loading setupapi.dll failed\n");
      return -1;
    }
  SetupCopyOEMInf = (setup_copy_oem_inf_t)
    GetProcAddress(setupapi_dll, "SetupCopyOEMInfA");
  
  if(!SetupCopyOEMInf)
    {
      usb_error("usb_install_driver(): loading setupapi.dll failed\n");
      return -1;
    }

  dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);


  /* retrieve the full .inf file path */
  if(!GetFullPathName(inf_file, MAX_PATH, inf_path, NULL))
    {
      usb_error("usb_install_driver(): .inf file %s not found\n", 
                inf_file);
      return -1;
    }

  /* open the .inf file */
  inf_handle = SetupOpenInfFile(inf_path, NULL, INF_STYLE_WIN4, NULL);

  if(inf_handle == INVALID_HANDLE_VALUE)
    {
      usb_error("usb_install_driver(): unable to open .inf file %s\n", 
                inf_file);
      return -1;
    }

  /* find the .inf file's device description section marked "Devices" */
  if(!SetupFindFirstLine(inf_handle, "Devices", NULL, &inf_context))
    {
      usb_error("usb_install_driver(): .inf file %s does not contain "
                "any device descriptions\n", inf_file);
      SetupCloseInfFile(inf_handle);
      return -1;
    }


  do {
    /* get the device ID from the .inf file */
    if(!SetupGetStringField(&inf_context, 2, id, sizeof(id), NULL))
      {
        continue;
      }

    /* convert the string to lowercase */
    strlwr(id);

    reboot = FALSE;

    /* copy the .inf file to the system directory so that is will be found */
    /* when new devices are plugged in */
    SetupCopyOEMInf(inf_path, NULL, SPOST_PATH, 0, NULL, 0, NULL, NULL);

    /* update all connected devices matching this ID, but only if this */
    /* driver is better or newer */
    UpdateDriverForPlugAndPlayDevices(NULL, id, inf_path, INSTALLFLAG_FORCE, 
                                      &reboot);
    

    /* now search the registry for device nodes representing currently  */
    /* unattached devices */


    /* get all USB device nodes from the registry, present and non-present */
    /* devices */
    dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES);
    
    if(dev_info == INVALID_HANDLE_VALUE)
      {
        SetupCloseInfFile(inf_handle);
        break;
      }
 
    dev_index = 0;

    /* enumerate the device list to find all attached and unattached */
    /* devices */
    while(SetupDiEnumDeviceInfo(dev_info, dev_index, &dev_info_data))
      {
        /* get the harware ID from the registry, this is a multi-zero string */
        if(SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
                                            SPDRP_HARDWAREID, NULL,  
                                            (BYTE *)tmp_id, 
                                            sizeof(tmp_id), NULL))
          {
            /* check all possible IDs contained in that multi-zero string */
            for(p = tmp_id; *p; p += (strlen(p) + 1))
              {
                /* convert the string to lowercase */
                strlwr(p);
		
                /* found a match? */
                if(strstr(p, id))
                  {
                    /* is this device disconnected? */
                    if(CM_Get_DevNode_Status(&status,
                                             &problem,
                                             dev_info_data.DevInst,
                                             0) == CR_NO_SUCH_DEVINST)
                      {
                        /* found a device node that represents an unattached */
                        /* device */
                        if(SetupDiGetDeviceRegistryProperty(dev_info, 
                                                            &dev_info_data,
                                                            SPDRP_CONFIGFLAGS, 
                                                            NULL,  
                                                            (BYTE *)&config_flags, 
                                                            sizeof(config_flags),
                                                            NULL))
                          {
                            /* mark the device to be reinstalled the next time it is */
                            /* plugged in */
                            config_flags |= CONFIGFLAG_REINSTALL;
			    
                            /* write the property back to the registry */
                            SetupDiSetDeviceRegistryProperty(dev_info, 
                                                             &dev_info_data,
                                                             SPDRP_CONFIGFLAGS,
                                                             (BYTE *)&config_flags, 
                                                             sizeof(config_flags));
                          }
                      }
                    /* a match was found, skip the rest */
                    break;
                  }
              }
          }
        /* check the next device node */
        dev_index++;
      }
    
    SetupDiDestroyDeviceInfoList(dev_info);

    /* get the next device ID from the .inf file */ 
  } while(SetupFindNextLine(&inf_context, &inf_context));

  /* we are done, close the .inf file */
  SetupCloseInfFile(inf_handle);

  usb_registry_stop_libusb_devices(); /* stop all libusb devices */
  usb_registry_start_libusb_devices(); /* restart all libusb devices */

  return 0;
}