started implementation of device driver installation wizard
Modified: trunk/reactos/lib/newdev/De.rc
Modified: trunk/reactos/lib/newdev/En.rc
Modified: trunk/reactos/lib/newdev/newdev.c
Modified: trunk/reactos/lib/newdev/newdev.h
Modified: trunk/reactos/lib/newdev/newdev.xml
Modified: trunk/reactos/lib/newdev/resource.h

Modified: trunk/reactos/lib/newdev/De.rc
--- trunk/reactos/lib/newdev/De.rc	2005-11-08 22:04:46 UTC (rev 19069)
+++ trunk/reactos/lib/newdev/De.rc	2005-11-08 22:25:29 UTC (rev 19070)
@@ -6,15 +6,15 @@
 CAPTION "Hardwareinstallation"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT           "Willkommen",IDC_WELCOMETITLE,115,8,195,24
+    LTEXT           "Willkommen",IDC_WELCOMETITLE,120,8,195,24
     LTEXT           "Dieser Assistent installiert einen neuen Gerõtetreiber f³r:",
-                    IDC_STATIC,115,40,195,16
-    LTEXT           "Klicken Sie auf Weiter um fortzufahren.",IDC_STATIC,115,169,195,17
-    LTEXT           "UNKNOWN DEVICE",IDC_DEVICE,129,55,164,11
+                    IDC_STATIC,120,40,195,16
+    LTEXT           "Klicken Sie auf Weiter um fortzufahren.",IDC_STATIC,120,169,195,17
+    LTEXT           "UNKNOWN DEVICE",IDC_DEVICE,134,55,164,11
     CONTROL         "Treiber automatisch installieren",IDC_RADIO_AUTO,"Button",
-                    BS_AUTORADIOBUTTON,115,112,178,13
+                    BS_AUTORADIOBUTTON,120,112,178,13
     CONTROL         "Treiber von einer bestimmten Position installieren",IDC_RADIO_MANUAL,
-                    "Button",BS_AUTORADIOBUTTON,115,133,164,14
+                    "Button",BS_AUTORADIOBUTTON,120,133,164,14
 END
 
 IDD_NODRIVER DIALOG DISCARDABLE  0, 0, 317, 193
@@ -23,13 +23,13 @@
 CAPTION "Hardwareinstallation"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT           "Installation fehlgeschlagen",IDC_FINISHTITLE,115,8,195,24
+    LTEXT           "Installation fehlgeschlagen",IDC_FINISHTITLE,120,8,195,24
     LTEXT           "Der Gerõt konnte nicht installiert werden, da kein passender Treiber gefunden werden konnte.",
-                    IDC_STATIC,115,40,195,19
+                    IDC_STATIC,120,40,195,19
     LTEXT           "Klicken Sie auf Zur³ck, wenn Sie eine Treiber CD oder Diskette haben oder den Pfad zum Treiber kennen.",
-                    IDC_STATIC,113,98,181,24
+                    IDC_STATIC,120,98,181,24
     CONTROL         "Diesen Dialog nicht mehr anzeigen",IDC_DONOTSHOWDLG,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,114,170,180,11
+                    BS_AUTOCHECKBOX | WS_TABSTOP,120,170,180,11
 END
 
 IDD_CHSOURCE DIALOG DISCARDABLE  0, 0, 317, 143
@@ -45,7 +45,7 @@
                     BS_AUTOCHECKBOX | WS_TABSTOP,47,33,163,9
     CONTROL         "Diesen Pfad ebenfalls durchsuchen",IDC_CHECK_PATH,"Button",BS_AUTOCHECKBOX | 
                     WS_TABSTOP,50,54,162,10
-    PUSHBUTTON      "Durchsuchen",IDC_BROWSE,248,69,45,14
+    PUSHBUTTON      "Durchsuchen",IDC_BROWSE,248,69,50,14
     COMBOBOX        IDC_COMBO_PATH,64,71,176,12,CBS_DROPDOWN | CBS_SORT | 
                     WS_VSCROLL | WS_TABSTOP
 END
@@ -64,10 +64,10 @@
 CAPTION "Hardwareinstallation"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT           "Installation abgeschlossen",IDC_FINISHTITLE,115,8,195,11
+    LTEXT           "Installation abgeschlossen",IDC_FINISHTITLE,120,8,195,11
     LTEXT           "Der Assistent hat die Installation erfolgreich abgeschlossen.",
-                    IDC_STATIC,115,32,195,19
-    LTEXT           "Klicken Sie zum Beenden der Installation auf Fertigstellen.",IDC_STATIC,115,174,
+                    IDC_STATIC,120,32,195,19
+    LTEXT           "Klicken Sie zum Beenden der Installation auf Fertigstellen.",IDC_STATIC,120,174,
                     190,11
     LTEXT           "UNKNOWN DEVICE",IDC_DEVICE,148,53,147,12
 END

Modified: trunk/reactos/lib/newdev/En.rc
--- trunk/reactos/lib/newdev/En.rc	2005-11-08 22:04:46 UTC (rev 19069)
+++ trunk/reactos/lib/newdev/En.rc	2005-11-08 22:25:29 UTC (rev 19070)
@@ -6,15 +6,15 @@
 CAPTION "Device installation"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT           "Welcome",IDC_WELCOMETITLE,115,8,195,24
+    LTEXT           "Welcome",IDC_WELCOMETITLE,120,8,195,24
     LTEXT           "This wizard installs a new device driver for:",
-                    IDC_STATIC,115,40,195,16
-    LTEXT           "Click Next to continue.",IDC_STATIC,115,169,195,17
-    LTEXT           "UNKNOWN DEVICE",IDC_DEVICE,129,55,164,11
+                    IDC_STATIC,120,40,195,16
+    LTEXT           "Click Next to continue.",IDC_STATIC,120,169,195,17
+    LTEXT           "UNKNOWN DEVICE",IDC_DEVICE,134,55,164,11
     CONTROL         "Install driver automatically",IDC_RADIO_AUTO,"Button",
-                    BS_AUTORADIOBUTTON,115,112,178,13
+                    BS_AUTORADIOBUTTON,120,112,178,13
     CONTROL         "Install driver from specific location",IDC_RADIO_MANUAL,
-                    "Button",BS_AUTORADIOBUTTON,115,133,164,14
+                    "Button",BS_AUTORADIOBUTTON,120,133,164,14
 END
 
 IDD_NODRIVER DIALOG DISCARDABLE  0, 0, 317, 193
@@ -23,13 +23,13 @@
 CAPTION "Device installation"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT           "Installation failed",IDC_FINISHTITLE,115,8,195,24
+    LTEXT           "Installation failed",IDC_FINISHTITLE,120,8,195,24
     LTEXT           "The device could not be installed because the driver could not be found.",
-                    IDC_STATIC,115,40,195,19
+                    IDC_STATIC,120,40,195,19
     LTEXT           "Click on Back if you have a driver disk or know the path to the driver.",
-                    IDC_STATIC,113,98,181,24
+                    IDC_STATIC,120,98,181,24
     CONTROL         "Do not show this dialog anymore",IDC_DONOTSHOWDLG,"Button",
-                    BS_AUTOCHECKBOX | WS_TABSTOP,114,170,180,11
+                    BS_AUTOCHECKBOX | WS_TABSTOP,120,170,180,11
 END
 
 IDD_CHSOURCE DIALOG DISCARDABLE  0, 0, 317, 143
@@ -45,7 +45,7 @@
                     BS_AUTOCHECKBOX | WS_TABSTOP,47,33,163,9
     CONTROL         "Include this path",IDC_CHECK_PATH,"Button",BS_AUTOCHECKBOX | 
                     WS_TABSTOP,47,54,162,10
-    PUSHBUTTON      "Browse",IDC_BROWSE,248,69,45,14
+    PUSHBUTTON      "Browse",IDC_BROWSE,248,69,50,14
     COMBOBOX        IDC_COMBO_PATH,61,71,176,12,CBS_DROPDOWN | CBS_SORT | 
                     WS_VSCROLL | WS_TABSTOP
 END
@@ -64,10 +64,10 @@
 CAPTION "Device installation"
 FONT 8, "MS Shell Dlg"
 BEGIN
-    LTEXT           "Installation complete",IDC_FINISHTITLE,115,8,195,11
+    LTEXT           "Installation complete",IDC_FINISHTITLE,120,8,195,11
     LTEXT           "The wizard has finished installing the driver for:",
-                    IDC_STATIC,115,32,195,19
-    LTEXT           "Click Finish to close the wizard.",IDC_STATIC,115,174,
+                    IDC_STATIC,120,32,195,19
+    LTEXT           "Click Finish to close the wizard.",IDC_STATIC,120,174,
                     179,11
     LTEXT           "UNKNOWN DEVICE",IDC_DEVICE,148,53,147,12
 END

Modified: trunk/reactos/lib/newdev/newdev.c
--- trunk/reactos/lib/newdev/newdev.c	2005-11-08 22:04:46 UTC (rev 19069)
+++ trunk/reactos/lib/newdev/newdev.c	2005-11-08 22:25:29 UTC (rev 19070)
@@ -1,227 +1,922 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS New devices installation
- * FILE:            lib/newdev/newdev.c
- * PURPOSE:         New devices installation
- *
- * PROGRAMMERS:     HervÚ Poussineau (hpoussin@reactos.org)
- */
+* COPYRIGHT:       See COPYING in the top level directory
+* PROJECT:         ReactOS New devices installation
+* FILE:            lib/newdev/newdev.c
+* PURPOSE:         New devices installation
+*
+* PROGRAMMERS:     HervÚ Poussineau (hpoussin@reactos.org)
+*/
 
-#define NDEBUG
+
+//#define NDEBUG
 #include <debug.h>
+#include <tchar.h>
+#include <windows.h>
+#include <commctrl.h>
+#include <regstr.h>
 
+#include <stdio.h>
+
 #include "newdev.h"
+#include "resource.h"
 
-BOOL WINAPI
-DevInstallW(
-	IN HWND hWndParent,
-	IN HINSTANCE hInstance,
-	IN LPCWSTR InstanceId,
-	IN INT Show)
+static DEVINSTDATA DevInstData;
+HINSTANCE hDllInstance;
+HANDLE hThread; 
+
+static HFONT
+CreateTitleFont(VOID)
 {
-	HDEVINFO hDevInfo;
-	SP_DEVINFO_DATA devInfoData;
-	DWORD requiredSize;
-	DWORD regDataType;
-	PBYTE buffer = NULL;
-	SP_DRVINFO_DATA drvInfoData;
-	BOOL ret;
+	NONCLIENTMETRICS ncm;
+	LOGFONT LogFont;
+	HDC hdc;
+	INT FontSize;
+	HFONT hFont;
 
-	devInfoData.cbSize = 0; /* Tell if the devInfoData is valid */
+	ncm.cbSize = sizeof(NONCLIENTMETRICS);
+	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
 
-	hDevInfo = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
-	if (hDevInfo == INVALID_HANDLE_VALUE)
+	LogFont = ncm.lfMessageFont;
+	LogFont.lfWeight = FW_BOLD;
+	_tcscpy(LogFont.lfFaceName, _T("MS Shell Dlg"));
+
+	hdc = GetDC(NULL);
+	FontSize = 12;
+	LogFont.lfHeight = 0 - GetDeviceCaps (hdc, LOGPIXELSY) * FontSize / 72;
+	hFont = CreateFontIndirect(&LogFont);
+	ReleaseDC(NULL, hdc);
+
+	return hFont;
+}
+
+static VOID
+CenterWindow(HWND hWnd)
+{
+	HWND hWndParent;
+	RECT rcParent;
+	RECT rcWindow;
+
+	hWndParent = GetParent(hWnd);
+	if (hWndParent == NULL)
+		hWndParent = GetDesktopWindow();
+
+	GetWindowRect(hWndParent, &rcParent);
+	GetWindowRect(hWnd, &rcWindow);
+
+	SetWindowPos(hWnd,
+		HWND_TOP,
+		((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
+		((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
+		0,
+		0,
+		SWP_NOSIZE);
+}
+
+INT_PTR CALLBACK
+WelcomeDlgProc(HWND hwndDlg,
+			   UINT uMsg,
+			   WPARAM wParam,
+			   LPARAM lParam)
+{
+
+	PDEVINSTDATA DevInstData;
+
+	/* Retrieve pointer to the global setup data */
+	DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
+
+	switch (uMsg)
 	{
-		DPRINT("SetupDiCreateDeviceInfoListExW() failed with error 0x%lx\n", GetLastError());
-		ret = FALSE;
-		goto cleanup;
+	case WM_INITDIALOG:
+		{
+			HWND hwndControl;
+			DWORD dwStyle;
+
+			/* Get pointer to the global setup data */
+			DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+			SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
+
+			hwndControl = GetParent(hwndDlg);
+
+			/* Center the wizard window */
+			CenterWindow (hwndControl);
+
+			/* Hide the system menu */
+			dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
+			SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
+
+			/* Set title font */
+			SendDlgItemMessage(hwndDlg,
+				IDC_WELCOMETITLE,
+				WM_SETFONT,
+				(WPARAM)DevInstData->hTitleFont,
+				(LPARAM)TRUE);
+
+			SendDlgItemMessage(hwndDlg,
+				IDC_DEVICE,
+				WM_SETTEXT,
+				0,
+				(LPARAM) DevInstData->buffer);
+
+			SendDlgItemMessage(hwndDlg,
+				IDC_RADIO_AUTO,
+				BM_SETCHECK,
+				(WPARAM) TRUE,
+				(LPARAM) 0);
+
+
+		}
+		break;
+
+
+	case WM_NOTIFY:
+		{
+			LPNMHDR lpnm = (LPNMHDR)lParam;
+
+			switch (lpnm->code)
+			{
+			case PSN_SETACTIVE:
+				/* Enable the Next button */
+				PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
+				break;
+
+			case PSN_WIZNEXT:
+				/* Handle a Next button click, if necessary */
+
+				if (SendDlgItemMessage(hwndDlg, IDC_RADIO_AUTO, BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED)
+					PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_SEARCHDRV);
+
+				break;
+
+			default:
+				break;
+			}
+		}
+		break;
+
+	default:
+		break;
 	}
 
-	devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
-	ret = SetupDiOpenDeviceInfoW(
-		hDevInfo,
-		InstanceId,
-		NULL,
-		0, /* Open flags */
-		&devInfoData);
-	if (!ret)
+	return FALSE;
+}
+
+INT_PTR CALLBACK
+CHSourceDlgProc(HWND hwndDlg,
+				UINT uMsg,
+				WPARAM wParam,
+				LPARAM lParam)
+{
+
+	PDEVINSTDATA DevInstData;
+
+	/* Retrieve pointer to the global setup data */
+	DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
+
+	switch (uMsg)
 	{
-		DPRINT("SetupDiOpenDeviceInfoW() failed with error 0x%lx\n", GetLastError());
-		devInfoData.cbSize = 0;
-		goto cleanup;
+	case WM_INITDIALOG:
+		{
+			HWND hwndControl;
+			DWORD dwStyle;
+
+			/* Get pointer to the global setup data */
+			DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+			SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
+
+			hwndControl = GetParent(hwndDlg);
+
+			/* Center the wizard window */
+			CenterWindow (hwndControl);
+
+			/* Hide the system menu */
+			dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
+			SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
+
+			SendDlgItemMessage(hwndDlg,
+				IDC_RADIO_SEARCHHERE,
+				BM_SETCHECK,
+				(WPARAM) TRUE,
+				(LPARAM) 0); 
+
+
+		}
+		break;
+
+
+	case WM_NOTIFY:
+		{
+			LPNMHDR lpnm = (LPNMHDR)lParam;
+
+			switch (lpnm->code)
+			{
+			case PSN_SETACTIVE:
+				/* Enable the Next and Back buttons */
+				PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
+				break;
+
+			case PSN_WIZNEXT:
+				/* Handle a Next button click, if necessary */
+				PropSheet_SetCurSel(GetParent(hwndDlg), 0, 4);
+				break;
+
+			default:
+				break;
+			}
+		}
+		break;
+
+	default:
+		break;
 	}
 
-	SetLastError(ERROR_GEN_FAILURE);
-	ret = SetupDiGetDeviceRegistryProperty(
-		hDevInfo,
-		&devInfoData,
-		SPDRP_DEVICEDESC,
-		&regDataType,
-		NULL, 0,
-		&requiredSize);
-	if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && regDataType == REG_SZ)
+	return FALSE;
+}
+
+INT_PTR CALLBACK
+SearchDrvDlgProc(HWND hwndDlg,
+				 UINT uMsg,
+				 WPARAM wParam,
+				 LPARAM lParam)
+{
+
+	PDEVINSTDATA DevInstData;
+    DWORD dwThreadId;
+
+	/* Retrieve pointer to the global setup data */
+	DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
+
+	switch (uMsg)
 	{
-		buffer = HeapAlloc(GetProcessHeap(), 0, requiredSize);
-		if (!buffer)
+	case WM_INITDIALOG:
 		{
-			DPRINT("HeapAlloc() failed\n");
-			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+			HWND hwndControl;
+			DWORD dwStyle;
+
+			/* Get pointer to the global setup data */
+			DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+			SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
+
+			DevInstData->hDialog = hwndDlg;
+			hwndControl = GetParent(hwndDlg);
+
+			/* Center the wizard window */
+			CenterWindow (hwndControl);
+
+			SendDlgItemMessage(hwndDlg,
+				IDC_DEVICE,
+				WM_SETTEXT,
+				0,
+				(LPARAM) DevInstData->buffer);
+
+			/* Hide the system menu */
+			dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
+			SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
 		}
-		else
+		break;
+
+	case WM_SEARCH_FINISHED:
 		{
-			ret = SetupDiGetDeviceRegistryProperty(
-				hDevInfo,
-				&devInfoData,
-				SPDRP_DEVICEDESC,
-				&regDataType,
-				buffer, requiredSize,
-				&requiredSize);
+			CloseHandle(hThread);
+			hThread = 0;
+			if (wParam == 0)
+				PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_NODRIVER);
+			else
+				PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_FINISHPAGE);
+			break;
 		}
+	case WM_NOTIFY:
+		{
+			LPNMHDR lpnm = (LPNMHDR)lParam;
+
+			switch (lpnm->code)
+			{
+			case PSN_SETACTIVE:
+				PropSheet_SetWizButtons(GetParent(hwndDlg), !PSWIZB_NEXT | !PSWIZB_BACK);
+				hThread = CreateThread( NULL, 0, FindDriverProc, DevInstData, 0, &dwThreadId);
+				break;
+
+			case PSN_KILLACTIVE:
+				if (hThread != 0) {
+					SetWindowLong ( hwndDlg, DWL_MSGRESULT, TRUE);
+					return TRUE;
+				}
+				break;
+			case PSN_WIZNEXT:
+				/* Handle a Next button click, if necessary */
+				break;
+
+			default:
+				break;
+			}
+		}
+		break;
+
+	default:
+		break;
 	}
-	if (!ret)
+
+	return FALSE;
+}
+
+DWORD WINAPI FindDriverProc( LPVOID lpParam ) 
+{ 
+	TCHAR drive[] = {'?',':',0};
+	size_t nType;
+	DWORD dwDrives;
+	PDEVINSTDATA DevInstData;
+	UINT i = 1;
+
+	DevInstData = (PDEVINSTDATA)lpParam;
+
+	dwDrives = GetLogicalDrives();		
+	for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++) {
+		if (dwDrives & i) {
+			nType = GetDriveType( drive );
+			if ((nType == DRIVE_CDROM) || (nType == DRIVE_FIXED)) {
+				/* search for inf file */
+				if (SearchDriver ( DevInstData, drive )) { 
+					/* if we found a valid driver inf... */
+					if (FindDriver ( DevInstData )) {
+						InstallDriver ( DevInstData );
+						PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0);
+						return 0;
+					}
+				}
+			}
+		}
+		i <<= 1;
+	}
+	
+	PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 0, 0);
+	return 0;
+}
+
+INT_PTR CALLBACK
+FinishDlgProc(HWND hwndDlg,
+			  UINT uMsg,
+			  WPARAM wParam,
+			  LPARAM lParam)
+{
+
+	PDEVINSTDATA DevInstData;
+
+	/* Retrieve pointer to the global setup data */
+	DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
+
+	switch (uMsg)
 	{
-		DPRINT("SetupDiGetDeviceRegistryProperty() failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+	case WM_INITDIALOG:
+		{
+			HWND hwndControl;
+
+			/* Get pointer to the global setup data */
+			DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+			SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
+
+			hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
+			ShowWindow (hwndControl, SW_HIDE);
+			EnableWindow (hwndControl, FALSE);
+
+			SendDlgItemMessage(hwndDlg,
+				IDC_DEVICE,
+				WM_SETTEXT,
+				0,
+				(LPARAM) DevInstData->buffer);
+
+			/* Set title font */
+			SendDlgItemMessage(hwndDlg,
+				IDC_FINISHTITLE,
+				WM_SETFONT,
+				(WPARAM)DevInstData->hTitleFont,
+				(LPARAM)TRUE);
+		}
+		break;
+
+	case WM_NOTIFY:
+		{
+			LPNMHDR lpnm = (LPNMHDR)lParam;
+
+			switch (lpnm->code)
+			{
+			case PSN_SETACTIVE:
+				/* Enable the correct buttons on for the active page */
+				PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
+				break;
+
+			case PSN_WIZBACK:
+				/* Handle a Back button click, if necessary */
+				break;
+
+			case PSN_WIZFINISH:
+				/* Handle a Finish button click, if necessary */
+				break;
+
+			default:
+				break;
+			}
+		}
+		break;
+
+	default:
+		break;
 	}
 
-	DPRINT("Installing %s (%S)\n", buffer, InstanceId);
+	return FALSE;
+}
 
-	ret = SetupDiBuildDriverInfoList(hDevInfo, &devInfoData, SPDIT_COMPATDRIVER);
+INT_PTR CALLBACK
+InstFailDlgProc(HWND hwndDlg,
+				UINT uMsg,
+				WPARAM wParam,
+				LPARAM lParam)
+{
+
+	PDEVINSTDATA DevInstData;
+
+	/* Get pointer to the global setup data */
+	DevInstData = (PDEVINSTDATA)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
+
+	switch (uMsg)
+	{
+	case WM_INITDIALOG:
+		{
+			HWND hwndControl;
+
+			DevInstData = (PDEVINSTDATA)((LPPROPSHEETPAGE)lParam)->lParam;
+			SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)DevInstData);
+
+			hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
+			ShowWindow (hwndControl, SW_HIDE);
+			EnableWindow (hwndControl, FALSE);
+
+			/* Set title font */
+			SendDlgItemMessage(hwndDlg,
+				IDC_FINISHTITLE,
+				WM_SETFONT,
+				(WPARAM)DevInstData->hTitleFont,
+				(LPARAM)TRUE);
+		}
+		break;
+
+	case WM_NOTIFY:
+		{
+			LPNMHDR lpnm = (LPNMHDR)lParam;
+			DWORD config_flags;
+			BOOL ret;
+
+			switch (lpnm->code)
+			{
+			case PSN_SETACTIVE:
+				/* Enable the correct buttons on for the active page */
+				PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_FINISH);
+				break;
+
+			case PSN_WIZBACK:
+				PropSheet_SetCurSel(GetParent(hwndDlg), 0, IDD_WELCOMEPAGE);
+				/* Handle a Back button click, if necessary */
+				break;
+
+			case PSN_WIZFINISH:
+				/* Handle a Finish button click, if necessary */
+				if (SendDlgItemMessage(hwndDlg, IDC_DONOTSHOWDLG, BM_GETCHECK, (WPARAM) 0, (LPARAM) 0) == BST_CHECKED) {
+
+					if(SetupDiGetDeviceRegistryProperty(DevInstData->hDevInfo, 
+						&DevInstData->devInfoData,
+						SPDRP_CONFIGFLAGS, 
+						NULL,  
+						(BYTE *)&config_flags, 
+						sizeof(config_flags),
+						NULL))
+					{
+						config_flags |= CONFIGFLAG_FAILEDINSTALL;
+						ret = SetupDiSetDeviceRegistryProperty(
+							DevInstData->hDevInfo,
+							&DevInstData->devInfoData,
+							SPDRP_CONFIGFLAGS,
+							NULL, 0 );
+					}
+
+				}
+				break;
+
+			default:
+				break;
+			}
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return FALSE;
+}
+
+
+BOOL FindDriver ( PDEVINSTDATA DevInstData ) {
+	BOOL ret;
+
+	ret = SetupDiBuildDriverInfoList(DevInstData->hDevInfo, &DevInstData->devInfoData, SPDIT_COMPATDRIVER);
 	if (!ret)
 	{
 		DPRINT("SetupDiBuildDriverInfoList() failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
-	drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
+	DevInstData->drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
 	ret = SetupDiEnumDriverInfo(
-		hDevInfo,
-		&devInfoData,
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData,
 		SPDIT_COMPATDRIVER,
 		0,
-		&drvInfoData);
+		&DevInstData->drvInfoData);
 	if (!ret)
 	{
+		if (GetLastError() == ERROR_NO_MORE_ITEMS)
+			return FALSE;
 		DPRINT("SetupDiEnumDriverInfo() failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
-	DPRINT("Installing driver %s: %s\n", drvInfoData.MfgName, drvInfoData.Description);
+	DPRINT("Installing driver %S: %S\n", DevInstData->drvInfoData.MfgName, DevInstData->drvInfoData.Description);
 
+	return TRUE;
+}
+
+
+BOOL IsDots(const TCHAR* str) {
+	if(_tcscmp(str, _T(".")) && _tcscmp(str, _T(".."))) return FALSE;
+	return TRUE;
+}
+
+TCHAR* GetFileExt(TCHAR* FileName)
+{
+	if (FileName == 0)
+		return _T("");
+
+	int i = _tcsclen(FileName);
+	while ((i >= 0) && (FileName[i] != _T('.')))
+		i--;
+
+	FileName = _tcslwr(FileName);
+
+	if (i >= 0)
+		return &FileName[i];
+	else
+		return _T("");
+}
+
+BOOL SearchDriver ( PDEVINSTDATA DevInstData, const TCHAR* Path ) {
+	WIN32_FIND_DATA wfd;
+	SP_DEVINSTALL_PARAMS DevInstallParams;
+	TCHAR DirPath[MAX_PATH];
+	TCHAR FileName[MAX_PATH];
+	TCHAR FullPath[MAX_PATH];
+	TCHAR LastDirPath[MAX_PATH] = _T("");
+	TCHAR PathWithPattern[MAX_PATH];
+	BOOL ok = TRUE;
+	BOOL ret;
+	HANDLE hFindFile;
+
+	_tcscpy(DirPath, Path);
+
+	if (DirPath[_tcsclen(DirPath) - 1] != '\\')
+		_tcscat(DirPath, _T("\\"));
+
+	_tcscpy(PathWithPattern, DirPath);
+	_tcscat(PathWithPattern, _T("\\*"));
+
+	for (hFindFile = FindFirstFile(PathWithPattern, &wfd); ((hFindFile != INVALID_HANDLE_VALUE) && ok); ok = FindNextFile(hFindFile, &wfd))
+	{
+
+		_tcscpy(FileName, wfd.cFileName);
+		if(IsDots(FileName)) continue;   
+
+		if((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+			_tcscpy(FullPath, DirPath);
+			_tcscat(FullPath, FileName);
+			if(SearchDriver(DevInstData, FullPath))
+				break;
+		}
+		else {
+			TCHAR* pszExtension = GetFileExt(FileName);
+
+			if ((_tcscmp(pszExtension, _T(".inf")) == 0) && (_tcscmp(LastDirPath, DirPath) != 0)){
+				_tcscpy(LastDirPath, DirPath);
+				ZeroMemory (&DevInstallParams, sizeof(SP_DEVINSTALL_PARAMS));
+				DevInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+
+				ret = SetupDiGetDeviceInstallParams(
+					DevInstData->hDevInfo,
+					&DevInstData->devInfoData,
+					&DevInstallParams);
+
+				if (_tcsclen(DirPath) <= MAX_PATH) {
+					memcpy(DevInstallParams.DriverPath, DirPath, (_tcsclen(DirPath) + 1) *  sizeof(TCHAR));
+				}
+
+				ret = SetupDiSetDeviceInstallParams(
+					DevInstData->hDevInfo,
+					&DevInstData->devInfoData,
+					&DevInstallParams);
+
+				if ( FindDriver ( DevInstData ) ) {
+					if (hFindFile != INVALID_HANDLE_VALUE)
+						FindClose(hFindFile);
+					return TRUE;
+				}
+				
+			}
+		}
+	}
+		
+	if (hFindFile != INVALID_HANDLE_VALUE)
+		FindClose(hFindFile);
+
+	return FALSE;
+}
+
+BOOL InstallDriver ( PDEVINSTDATA DevInstData ) {
+	BOOL ret;
+
 	ret = SetupDiCallClassInstaller(
 		DIF_SELECTBESTCOMPATDRV,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_ALLOW_INSTALL,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_ALLOW_INSTALL) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_NEWDEVICEWIZARD_PREANALYZE,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_PREANALYZE) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_NEWDEVICEWIZARD_POSTANALYZE,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_POSTANALYZE) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_INSTALLDEVICEFILES,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_REGISTER_COINSTALLERS,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_INSTALLINTERFACES,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_INSTALLINTERFACES) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_INSTALLDEVICE,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_INSTALLDEVICE) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_NEWDEVICEWIZARD_FINISHINSTALL,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_NEWDEVICEWIZARD_FINISHINSTALL) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
 	ret = SetupDiCallClassInstaller(
 		DIF_DESTROYPRIVATEDATA,
-		hDevInfo,
-		&devInfoData);
+		DevInstData->hDevInfo,
+		&DevInstData->devInfoData);
 	if (!ret)
 	{
 		DPRINT("SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA) failed with error 0x%lx\n", GetLastError());
-		goto cleanup;
+		return FALSE;
 	}
 
-cleanup:
-	if (devInfoData.cbSize != 0)
+	return TRUE;
+
+}
+
+void CleanUp ( void ) {
+
+	if (DevInstData.devInfoData.cbSize != 0)
 	{
-		if (!SetupDiDestroyDriverInfoList(hDevInfo, &devInfoData, SPDIT_COMPATDRIVER))
+		if (!SetupDiDestroyDriverInfoList(DevInstData.hDevInfo, &DevInstData.devInfoData, SPDIT_COMPATDRIVER))
 			DPRINT("SetupDiDestroyDriverInfoList() failed with error 0x%lx\n", GetLastError());
 	}
 
-	if (hDevInfo != INVALID_HANDLE_VALUE)
+	if (DevInstData.hDevInfo != INVALID_HANDLE_VALUE)
 	{
-		if (!SetupDiDestroyDeviceInfoList(hDevInfo))
+		if (!SetupDiDestroyDeviceInfoList(DevInstData.hDevInfo))
[truncated at 1000 lines; 248 more skipped]