#ifdef __GNUC__
#if !defined(WINVER)
#define WINVER 0x0500
#endif
#if !defined(_WIN32_IE)
#define _WIN32_IE 0x0501
#endif
#endif
#define INITGUID
#include "libusb-win32_version.h"
#include "libwdi.h"
#include "msapi_utf8.h"
#include <windows.h>
#include <commdlg.h>
#include <dbt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <initguid.h>
#include <commctrl.h>
#include <setupapi.h>
#include <time.h>
#define __INF_WIZARD_C__
#include "inf_wizard_rc.rc"
#define MAX_TEXT_LENGTH 256
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_sprintf _snprintf
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
#define safe_swprintf _snwprintf
#define safe_strdup _strdup
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
#define _IGNORE(expr) do { (void)(expr); } while(0)
DEFINE_GUID(GUID_DEVINTERFACE_USB_HUB, 0xf18a0e88, 0xc30c, 0x11d0, 0x88, \
0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8);
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, \
0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
typedef struct
{
struct wdi_device_info* wdi;
char description[MAX_PATH];
char manufacturer[MAX_PATH];
char inf_name[MAX_PATH];
char inf_dir [MAX_PATH];
char inf_path[MAX_PATH];
BOOL user_allocated_wdi;
BOOL modified;
VS_FIXEDFILEINFO driver_info;
} device_context_t;
typedef struct
{
UINT controlID;
const char* message;
}create_tooltip_t;
const char info_text_0[] =
"This program will create an .inf file for your device.\n\n"
"Before clicking \"Next\" make sure that your device is connected to the "
"system.\n";
const char info_text_1[] =
"A windows driver installation package has been created for the following "
"device:";
const char package_contents_fmt_0[] =
"This package contains %s v%d.%d.%d.%d drivers and support for the following platforms: %s.";
const char package_contents_fmt_1[] =
"This package contains an inf file only.";
const char list_header_text[] =
"Select your device from the list of detected devices below. "
"If your device isn't listed then either connect it or click \"Next\" "
"and enter your device description manually.";
create_tooltip_t tooltips_dlg2[]=
{
{ID_TEXT_VID,
"A VID is a 16-bit vendor number (Vendor ID). A vendor ID is "
"necessary for developing a USB product. The USB-IF is responsible "
"for issuing USB vendor ID's to product manufacturers."},
{ID_TEXT_PID,
"A PID is a 16-bit product number (Product ID)."},
{ID_TEXT_MI,
"If not blank, creates a driver package targeting a specific interface."},
{ID_TEXT_MANUFACTURER,
"Manufacturer or vendor string."},
{ID_TEXT_DEV_NAME,
"Name or description."},
{0,NULL}
};
create_tooltip_t tooltips_dlg3[]=
{
{ID_BUTTON_INSTALLNOW,
"Install this driver package now."},
{ID_BUTTON_NEXT,
"Finish without installing."},
{0,NULL}
};
create_tooltip_t tooltips_dlg1[]=
{
{ID_LIST,
LPSTR_TEXTCALLBACK},
{0,NULL}
};
HICON mIcon;
struct wdi_device_info* wdi_dev_list = NULL;
HINSTANCE g_hInst = NULL;
WNDPROC device_list_wndproc_orig;
TOOLINFO g_toolItem;
HWND g_hwndTrackingTT = NULL;
BOOL g_TrackingMouse = FALSE;
HWND create_tooltip(HWND hMain, HINSTANCE hInstance, UINT max_tip_width, create_tooltip_t tool_tips[]);
HWND CreateTrackingToolTip(HWND hDlg, TCHAR* pText);
HWND create_label(char* text, HWND hParent, HINSTANCE hInstance, UINT x, UINT y, UINT cx, UINT cy, DWORD dwStyle, UINT uID);
HWND create_labeled_text(char* label, char* text,
HWND hParent, HINSTANCE hInstance,
UINT left, UINT top, UINT height,
UINT label_width, UINT text_width,
UINT uIDLabel, UINT uIDText);
BOOL CALLBACK dialog_proc_0(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam);
BOOL CALLBACK dialog_proc_1(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam);
BOOL CALLBACK dialog_proc_2(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam);
BOOL CALLBACK dialog_proc_3(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam);
static void device_list_init(HWND list);
static void device_list_refresh(HWND list);
static void device_list_add(HWND list, device_context_t *device);
static void device_list_clean(HWND list);
static int save_file(HWND dialog, device_context_t *device);
void close_file(FILE** file);
int infwizard_install_driver(HWND dialog, device_context_t *device);
int infwizard_prepare_driver(HWND dialog, device_context_t *device);
void output_debug(char* format,...)
{
va_list args;
char msg[256];
va_start (args, format);
vsprintf(msg, format, args);
va_end (args);
OutputDebugStringA(msg);
}
int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev_instance,
LPSTR cmd_line, int cmd_show)
{
device_context_t device;
int next_dialog;
LoadLibrary("comctl32.dll");
InitCommonControls();
memset(&device, 0, sizeof(device));
next_dialog = ID_DIALOG_0;
mIcon = LoadIcon(instance, MAKEINTRESOURCE(IDR_MAIN_ICON));
g_hInst = instance;
while (next_dialog)
{
g_TrackingMouse = FALSE;
switch (next_dialog)
{
case ID_DIALOG_0:
next_dialog = (int)DialogBoxParam(instance,
MAKEINTRESOURCE(next_dialog),
NULL, (DLGPROC)dialog_proc_0,
(LPARAM)&device);
break;
case ID_DIALOG_1:
next_dialog = (int)DialogBoxParam(instance,
MAKEINTRESOURCE(next_dialog),
NULL, (DLGPROC)dialog_proc_1,
(LPARAM)&device);
break;
case ID_DIALOG_2:
next_dialog = (int)DialogBoxParam(instance,
MAKEINTRESOURCE(next_dialog),
NULL, (DLGPROC)dialog_proc_2,
(LPARAM)&device);
break;
case ID_DIALOG_3:
next_dialog = (int)DialogBoxParam(instance,
MAKEINTRESOURCE(next_dialog),
NULL, (DLGPROC)dialog_proc_3,
(LPARAM)&device);
break;
default:
;
}
}
if (device.user_allocated_wdi)
{
device.user_allocated_wdi = FALSE;
if (device.wdi)
{
free(device.wdi);
device.wdi = NULL;
}
}
if (wdi_dev_list)
{
wdi_destroy_list(wdi_dev_list);
wdi_dev_list = NULL;
}
if (mIcon)
{
DestroyIcon(mIcon);
mIcon = NULL;
}
return 0;
}
BOOL CALLBACK dialog_proc_0(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
SendMessage(dialog,WM_SETICON,ICON_BIG, (LPARAM)mIcon);
SetWindowText(GetDlgItem(dialog, ID_INFO_TEXT), info_text_0);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON_NEXT:
EndDialog(dialog, ID_DIALOG_1);
return TRUE ;
case ID_BUTTON_CANCEL:
case IDCANCEL:
EndDialog(dialog, 0);
return TRUE ;
}
}
return FALSE;
}
INT_PTR CALLBACK device_list_wndproc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
TCHAR tipText[80];
POINT pt;
static int oldX, oldY;
int newX, newY;
LVHITTESTINFO hitTestInfo;
LVITEM lvitem;
device_context_t* dev_context;
switch(message)
{
case WM_MOUSELEAVE:
SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)&g_toolItem);
g_TrackingMouse = FALSE;
return FALSE;
case WM_MOUSEMOVE:
if (!g_TrackingMouse)
{
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = hDlg;
tme.dwFlags = TME_LEAVE;
TrackMouseEvent(&tme);
SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE,
(WPARAM)TRUE, (LPARAM)&g_toolItem);
g_TrackingMouse = TRUE;
}
newX = LOWORD(lParam);
newY = HIWORD(lParam);
if ((newX != oldX) || (newY != oldY))
{
oldX = newX;
oldY = newY;
memset(&hitTestInfo,0,sizeof(hitTestInfo));
hitTestInfo.pt.x = newX;
hitTestInfo.pt.y = newY;
if ((ListView_HitTest(hDlg, &hitTestInfo) == -1) || newX > ListView_GetColumnWidth(hDlg, 0))
{
safe_sprintf(tipText, sizeof(tipText) - 1, TEXT("%s"), TEXT(""));
SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE,FALSE, (LPARAM)&g_toolItem);
}
else
{
SendMessage(g_hwndTrackingTT, TTM_SETDELAYTIME,TTDT_INITIAL, 1000);
memset(&lvitem, 0 , sizeof(lvitem));
lvitem.iItem = hitTestInfo.iItem;
lvitem.mask = LVIF_PARAM;
_IGNORE(ListView_GetItem(hDlg,&lvitem));
dev_context = (device_context_t*)lvitem.lParam;
safe_sprintf(tipText, sizeof(tipText)-1 , TEXT("%s"), wdi_get_vendor_name(dev_context->wdi->vid));
SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE,TRUE, (LPARAM)&g_toolItem);
}
g_toolItem.lpszText = tipText;
SendMessage(g_hwndTrackingTT, TTM_SETTOOLINFO, 0, (LPARAM)&g_toolItem);
pt.x = newX;
pt.y = newY;
ClientToScreen(hDlg, &pt);
SendMessage(g_hwndTrackingTT, TTM_TRACKPOSITION,
0, (LPARAM)MAKELONG(pt.x + 10, pt.y - 20));
}
break;
}
return CallWindowProc(device_list_wndproc_orig, hDlg, message, wParam, lParam);
}
BOOL CALLBACK dialog_proc_1(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam)
{
static HDEVNOTIFY notification_handle_hub = NULL;
static HDEVNOTIFY notification_handle_dev = NULL;
DEV_BROADCAST_HDR *hdr = (DEV_BROADCAST_HDR *) lParam;
DEV_BROADCAST_DEVICEINTERFACE dev_if;
static device_context_t *device = NULL;
HWND list = GetDlgItem(dialog, ID_LIST);
LVITEM item;
switch (message)
{
case WM_INITDIALOG:
SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
SendMessage(dialog,WM_SETICON,ICON_BIG, (LPARAM)mIcon);
device = (device_context_t *)lParam;
if (!device) {
EndDialog(dialog, 0);
return TRUE;
}
if (device->user_allocated_wdi)
{
if (device->wdi)
{
free(device->wdi);
device->wdi = NULL;
}
device->user_allocated_wdi = FALSE;
}
g_hwndTrackingTT = CreateTrackingToolTip(list, TEXT(" "));
#if defined(_WIN64)
device_list_wndproc_orig = (WNDPROC)SetWindowLongPtr(list, GWLP_WNDPROC, (UINT_PTR)device_list_wndproc);
#else
device_list_wndproc_orig = (WNDPROC)SetWindowLongPtr(list, GWL_WNDPROC, (UINT_PTR)device_list_wndproc);
#endif
if (device != NULL) memset(device, 0, sizeof(*device));
SetWindowText(GetDlgItem(dialog, ID_LIST_HEADER_TEXT), list_header_text);
device_list_init(list);
device_list_refresh(list);
dev_if.dbcc_size = sizeof(dev_if);
dev_if.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_HUB;
notification_handle_hub = RegisterDeviceNotification(dialog, &dev_if, 0);
dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
notification_handle_dev = RegisterDeviceNotification(dialog, &dev_if, 0);
return TRUE;
case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVICEREMOVECOMPLETE:
if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
device_list_refresh(list);
break;
case DBT_DEVICEARRIVAL:
if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
device_list_refresh(list);
break;
default:
;
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON_NEXT:
if (device) {
if (notification_handle_hub)
UnregisterDeviceNotification(notification_handle_hub);
if (notification_handle_dev)
UnregisterDeviceNotification(notification_handle_dev);
memset(&item, 0, sizeof(item));
item.mask = LVIF_TEXT | LVIF_PARAM;
item.iItem = ListView_GetNextItem(list, -1, LVNI_SELECTED);
memset(device, 0, sizeof(*device));
if (item.iItem >= 0)
{
if (ListView_GetItem(list, &item))
{
if (item.lParam)
{
memcpy(device, (void *)item.lParam, sizeof(*device));
}
}
}
if (!device->wdi)
{
device->user_allocated_wdi = TRUE;
device->wdi = malloc(sizeof(struct wdi_device_info));
memset(device->wdi,0,sizeof(struct wdi_device_info));
device->wdi->vid = 0x12AB;
device->wdi->pid = 0x12AB;
}
if (!device->manufacturer[0])
strcpy(device->manufacturer, "Insert manufacturer name");
if (!device->description[0])
strcpy(device->description, "Insert device description");
if (notification_handle_hub)
UnregisterDeviceNotification(notification_handle_hub);
if (notification_handle_dev)
UnregisterDeviceNotification(notification_handle_dev);
device_list_clean(list);
EndDialog(dialog, ID_DIALOG_2);
}
return TRUE;
case ID_BUTTON_BACK:
device_list_clean(list);
if (notification_handle_hub)
UnregisterDeviceNotification(notification_handle_hub);
if (notification_handle_dev)
UnregisterDeviceNotification(notification_handle_dev);
EndDialog(dialog, ID_DIALOG_0);
return TRUE ;
case ID_BUTTON_CANCEL:
case IDCANCEL:
device_list_clean(list);
if (notification_handle_hub)
UnregisterDeviceNotification(notification_handle_hub);
if (notification_handle_dev)
UnregisterDeviceNotification(notification_handle_dev);
EndDialog(dialog, 0);
return TRUE ;
}
}
return FALSE;
}
BOOL CALLBACK dialog_proc_2(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam)
{
static device_context_t *device = NULL;
char tmp[MAX_TEXT_LENGTH];
int val;
switch (message)
{
case WM_INITDIALOG:
SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
SendMessage(dialog,WM_SETICON,ICON_BIG, (LPARAM)mIcon);
device = (device_context_t *)lParam;
if (device)
{
wdi_is_driver_supported(WDI_LIBUSB0, &device->driver_info);
create_tooltip(dialog, g_hInst, 300, tooltips_dlg2);
memset(tmp, 0, sizeof(tmp));
safe_sprintf(tmp,sizeof(tmp) - 1, "0x%04X", device->wdi->vid);
SetWindowText(GetDlgItem(dialog, ID_TEXT_VID), tmp);
memset(tmp, 0, sizeof(tmp));
safe_sprintf(tmp,sizeof(tmp) - 1, "0x%04X", device->wdi->pid);
SetWindowText(GetDlgItem(dialog, ID_TEXT_PID), tmp);
memset(tmp, 0, sizeof(tmp));
if (device->wdi->is_composite)
safe_sprintf(tmp,sizeof(tmp) - 1, "0x%02X", device->wdi->mi);
SetWindowText(GetDlgItem(dialog, ID_TEXT_MI), tmp);
SetWindowTextU(GetDlgItem(dialog, ID_TEXT_MANUFACTURER),
device->manufacturer);
SetWindowTextU(GetDlgItem(dialog, ID_TEXT_DEV_NAME),
device->description);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON_NEXT:
if (device) {
device->wdi->is_composite=false;
GetWindowTextU(GetDlgItem(dialog, ID_TEXT_MANUFACTURER),
device->manufacturer, sizeof(tmp));
GetWindowTextU(GetDlgItem(dialog, ID_TEXT_DEV_NAME),
device->description, sizeof(tmp));
GetWindowText(GetDlgItem(dialog, ID_TEXT_VID), tmp, sizeof(tmp));
if(sscanf(tmp, "0x%04x", &val) == 1)
device->wdi->vid = (WORD)val;
GetWindowText(GetDlgItem(dialog, ID_TEXT_PID), tmp, sizeof(tmp));
if(sscanf(tmp, "0x%04x", &val) == 1)
device->wdi->pid = (WORD)val;
GetWindowText(GetDlgItem(dialog, ID_TEXT_MI), tmp, sizeof(tmp));
if (sscanf(tmp, "0x%02x", &val) == 1)
{
device->wdi->mi = (BYTE)val;
device->wdi->is_composite=true;
}
if (save_file(dialog, device))
EndDialog(dialog, ID_DIALOG_3);
}
return TRUE ;
case ID_BUTTON_BACK:
EndDialog(dialog, ID_DIALOG_1);
return TRUE ;
case ID_BUTTON_CANCEL:
case IDCANCEL:
EndDialog(dialog, 0);
return TRUE ;
}
}
return FALSE;
}
HWND create_label(char* text, HWND hParent, HINSTANCE hInstance, UINT x, UINT y, UINT cx, UINT cy, DWORD dwStyle, UINT uID)
{
return CreateWindowU("Static", text, WS_CHILD | WS_VISIBLE | dwStyle,
x, y, cx, cy,
hParent, (HMENU)((UINT_PTR)uID), hInstance, 0);
}
HWND create_labeled_text(char* label, char* text,
HWND hParent, HINSTANCE hInstance,
UINT left, UINT top, UINT height,
UINT label_width, UINT text_width,
UINT uIDLabel, UINT uIDText)
{
HWND hwnd = NULL;
HFONT dlgFont;
LOGFONT logFont;
HFONT labelFont;
dlgFont = (HFONT)SendMessage(hParent,WM_GETFONT,0,0);
if (label)
{
GetObject(dlgFont,sizeof(logFont),&logFont);
logFont.lfWeight*=2;
labelFont = CreateFontIndirectA(&logFont);
}
else
{
labelFont = dlgFont;
}
if (label)
{
hwnd = create_label(label, hParent, hInstance, left, top, label_width, height, SS_LEFT, uIDLabel);
SendMessage(hwnd, WM_SETFONT, (WPARAM)labelFont, TRUE);
}
if (text)
{
if (label)
{
text_width-=5;
left+=label_width+5;
}
hwnd = create_label(text, hParent, hInstance, left, top, text_width, height, SS_LEFT, uIDText);
SendMessage(hwnd,WM_SETFONT, (WPARAM)dlgFont, TRUE);
}
return hwnd;
}
BOOL CALLBACK dialog_proc_3(HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam)
{
static device_context_t *device = NULL;
char* bufferLabel = NULL;
char* bufferText = NULL;
int ret;
UINT x,y;
UINT TXT_WIDTH = 200;
UINT LBL_WIDTH = 150;
UINT LBL_HEIGHT = 15;
UINT LBL_SEP = 5;
static HBRUSH hBrushStatic = NULL;
RECT rect;
switch (message)
{
case WM_INITDIALOG:
SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
SendMessage(dialog,WM_SETICON,ICON_BIG, (LPARAM)mIcon);
device = (device_context_t *)lParam;
create_tooltip(dialog, g_hInst, 300, tooltips_dlg3);
bufferLabel = malloc(MAX_TEXT_LENGTH*2);
bufferText = bufferLabel+MAX_TEXT_LENGTH;
if (bufferLabel)
{
GetWindowRect(GetDlgItem(dialog,IDG_MAIN),&rect);
TXT_WIDTH = rect.right-rect.left-30-LBL_WIDTH;
y = 40;
x = 30;
safe_sprintf(bufferLabel, MAX_TEXT_LENGTH, "%s", info_text_1);
create_labeled_text(bufferLabel,NULL, dialog, g_hInst, x, y, LBL_HEIGHT * 2,LBL_WIDTH+TXT_WIDTH,0, ID_TEXT_HIGHLIGHT_INFO, ID_TEXT_HIGHLIGHT_INFO);
y += LBL_HEIGHT*2+LBL_SEP*2;
safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Vendor ID:");
safe_sprintf(bufferText, MAX_TEXT_LENGTH, "0x%04X", device->wdi->vid);
create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);
y += LBL_HEIGHT+LBL_SEP;
safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Product ID:");
safe_sprintf(bufferText, MAX_TEXT_LENGTH, "0x%04X", device->wdi->pid);
create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);
if (device->wdi->is_composite)
{
y += LBL_HEIGHT+LBL_SEP;
safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Interface # (MI):");
safe_sprintf(bufferText, MAX_TEXT_LENGTH, "0x%02X", device->wdi->mi);
create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);
}
y += LBL_HEIGHT+LBL_SEP;
safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Device description:");
safe_sprintf(bufferText, MAX_TEXT_LENGTH, "%s", device->description);
create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);
y += LBL_HEIGHT+LBL_SEP;
safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Manufacturer:");
safe_sprintf(bufferText, MAX_TEXT_LENGTH, "%s", device->manufacturer);
create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);
y += LBL_HEIGHT+LBL_SEP*2;
if (device->driver_info.dwSignature)
{
safe_sprintf(bufferLabel, MAX_TEXT_LENGTH, package_contents_fmt_0, "libusb-win32",
(int)device->driver_info.dwFileVersionMS>>16, (int)device->driver_info.dwFileVersionMS&0xFFFF,
(int)device->driver_info.dwFileVersionLS>>16, (int)device->driver_info.dwFileVersionLS&0xFFFF,
"x86, x64, ia64");
}
else
{
safe_sprintf(bufferLabel, MAX_TEXT_LENGTH, "%s", package_contents_fmt_1);
}
create_labeled_text(NULL,bufferLabel,dialog,g_hInst,x,y,LBL_HEIGHT*2, 0, LBL_WIDTH+TXT_WIDTH, ID_TEXT_HIGHLIGHT_INFO, ID_TEXT_HIGHLIGHT_INFO);
free(bufferLabel);
}
if ((device->driver_info.dwSignature) && GetFileAttributesU(device->inf_path)!=INVALID_FILE_ATTRIBUTES)
EnableWindow(GetDlgItem(dialog, ID_BUTTON_INSTALLNOW), TRUE);
else
EnableWindow(GetDlgItem(dialog, ID_BUTTON_INSTALLNOW), FALSE);
return TRUE;
case WM_CTLCOLORSTATIC:
{
if(ID_TEXT_HIGHLIGHT_INFO == GetDlgCtrlID((HWND)lParam))
{
SetBkColor((HDC) wParam, (COLORREF) GetSysColor(COLOR_BTNFACE));
SetTextColor((HDC) wParam, GetSysColor(COLOR_ACTIVECAPTION));
SetBkMode((HDC) wParam, TRANSPARENT);
if(!hBrushStatic)
{
hBrushStatic = CreateSolidBrush( (COLORREF) GetSysColor(COLOR_BTNFACE));
}
return PtrToUlong(hBrushStatic);
}
return FALSE;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_BUTTON_INSTALLNOW:
EnableWindow(GetDlgItem(dialog,ID_BUTTON_INSTALLNOW),FALSE);
SetCursor(LoadCursor(NULL,IDC_WAIT));
SetWindowText(GetDlgItem(dialog, IDL_INSTALLING_TEXT), "Installing driver, please wait..");
ret = infwizard_install_driver(dialog, device);
SetWindowText(GetDlgItem(dialog, IDL_INSTALLING_TEXT), "");
SetCursor(LoadCursor(NULL,IDC_ARROW));
if (ret == ERROR_SUCCESS)
{
MessageBoxA(dialog,"Installation successful.",
"Driver Install Complete", MB_OK | MB_APPLMODAL);
EndDialog(dialog, 0);
}
return TRUE;
case ID_BUTTON_NEXT:
case IDCANCEL:
EndDialog(dialog, 0);
return TRUE ;
}
}
return FALSE;
}
static void device_list_init(HWND list)
{
LVCOLUMN lvc;
_IGNORE(ListView_SetExtendedListViewStyle(list, LVS_EX_FULLROWSELECT));
memset(&lvc, 0, sizeof(lvc));
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = 70;
lvc.iSubItem = 0;
lvc.pszText = "Vendor ID";
_IGNORE(ListView_InsertColumn(list, 1, &lvc));
lvc.cx = 70;
lvc.iSubItem = 1;
lvc.pszText = "Product ID";
_IGNORE(ListView_InsertColumn(list, 2, &lvc));
lvc.cx = 260;
lvc.iSubItem = 2;
lvc.pszText = "Description";
_IGNORE(ListView_InsertColumn(list, 3, &lvc));
lvc.cx = 40;
lvc.iSubItem = 3;
lvc.pszText = "MI";
_IGNORE(ListView_InsertColumn(list, 4, &lvc));
}
static void device_list_refresh(HWND list)
{
int ret;
device_context_t *device;
struct wdi_device_info* wdi_dev_info;
struct wdi_options_create_list options;
const char* vendor_name;
memset(&options,0,sizeof(options));
options.list_all=TRUE;
options.list_hubs=FALSE;
options.trim_whitespaces=TRUE;
device_list_clean(list);
if (wdi_dev_list)
wdi_destroy_list(wdi_dev_list);
ret = wdi_create_list(&wdi_dev_list,&options);
if (ret == WDI_SUCCESS)
{
for(wdi_dev_info=wdi_dev_list; wdi_dev_info!=NULL; wdi_dev_info=wdi_dev_info->next)
{
device = (device_context_t *) malloc(sizeof(device_context_t));
memset(device, 0, sizeof(*device));
device->wdi=wdi_dev_info;
safe_strcpy(device->description,MAX_PATH,device->wdi->desc);
if ((vendor_name = wdi_get_vendor_name(device->wdi->vid)))
{
safe_strcpy(device->manufacturer,MAX_PATH, vendor_name);
}
device_list_add(list, device);
}
}
}
static void device_list_add(HWND list, device_context_t *device)
{
LVITEM item;
char vid[32];
char pid[32];
char mi[32];
memset(&item, 0, sizeof(item));
memset(vid, 0, sizeof(vid));
memset(pid, 0, sizeof(pid));
memset(mi, 0, sizeof(mi));
sprintf(vid, "0x%04X", device->wdi->vid);
sprintf(pid, "0x%04X", device->wdi->pid);
if (device->wdi->is_composite)
{
sprintf(mi, "0x%02X", device->wdi->mi);
}
item.mask = LVIF_TEXT | LVIF_PARAM;
item.lParam = (LPARAM)device;
_IGNORE(ListView_InsertItem(list, &item));
ListView_SetItemText(list, 0, 0, vid);
ListView_SetItemText(list, 0, 1, pid);
ListView_SetItemTextU(list, 0, 2, device->description);
ListView_SetItemText(list, 0, 3, mi);
}
static void device_list_clean(HWND list)
{
LVITEM item;
memset(&item, 0, sizeof(LVITEM));
while (ListView_GetItem(list, &item))
{
if (item.lParam)
free((void *)item.lParam);
_IGNORE(ListView_DeleteItem(list, 0));
memset(&item, 0, sizeof(LVITEM));
}
}
static char* to_valid_filename(char* name, char* ext)
{
size_t i, j, k;
bool found;
char* ret;
wchar_t unauthorized[] = L"\x0001\x0002\x0003\x0004\x0005\x0006\x0007\x0008\x000a"
L"\x000b\x000c\x000d\x000e\x000f\x0010\x0011\x0012\x0013\x0014\x0015\x0016\x0017"
L"\x0018\x0019\x001a\x001b\x001c\x001d\x001e\x001f\x007f\"*/:<>?\\|";
wchar_t to_underscore[] = L" \t";
wchar_t *wname, *wext, *wret;
if ((name == NULL) || (ext == NULL)) {
return NULL;
}
if (strlen(name) > WDI_MAX_STRLEN) return NULL;
wname = utf8_to_wchar(name);
wext = utf8_to_wchar(ext);
if ((wname == NULL) || (wext == NULL)) {
safe_free(wname); safe_free(wext); return NULL;
}
wret = calloc(2*(wcslen(wname) + wcslen(wext) + 2), 1);
if (wret == NULL) {
safe_free(wname); safe_free(wext); return NULL;
}
wcscpy(wret, wname);
safe_free(wname);
wcscat(wret, wext);
safe_free(wext);
for (i=0, k=0; i<wcslen(wret); i++) {
found = false;
for (j=0; j<wcslen(unauthorized); j++) {
if (wret[i] == unauthorized[j]) {
found = true; break;
}
}
if (found) continue;
found = false;
for (j=0; j<wcslen(to_underscore); j++) {
if (wret[i] == to_underscore[j]) {
wret[k++] = '_';
found = true; break;
}
}
if (found) continue;
wret[k++] = wret[i];
}
wret[k] = 0;
ret = wchar_to_utf8(wret);
safe_free(wret);
return ret;
}
static int save_file(HWND dialog, device_context_t *device)
{
OPENFILENAME open_file;
char* valid_name;
int length;
char ofd_filter[MAX_PATH];
memset(&open_file, 0, sizeof(open_file));
memset(device->inf_path, 0, sizeof(device->inf_path));
memset(device->inf_dir,0,sizeof(device->inf_dir));
memset(device->inf_name,0,sizeof(device->inf_name));
if (strlen(device->description))
{
if (_stricmp(device->description,"Insert device description")!=0)
{
valid_name = to_valid_filename(device->description, ".inf");
if (valid_name != NULL)
{
strncpy(device->inf_path, valid_name, MAX_PATH);
free(valid_name);
}
}
}
if (!strlen(device->inf_path))
strcpy(device->inf_path, "your_file.inf");
memcpy(ofd_filter,
"inf files (*.inf)\0*.inf\0\0",
sizeof("inf files (*.inf)\0*.inf\0\0"));
open_file.lStructSize = sizeof(OPENFILENAME);
open_file.hwndOwner = dialog;
open_file.lpstrFile = device->inf_path;
open_file.nMaxFile = sizeof(device->inf_path);
open_file.lpstrFilter = ofd_filter;
open_file.nFilterIndex = 1;
open_file.lpstrFileTitle = device->inf_name;
open_file.nMaxFileTitle = sizeof(device->inf_name);
open_file.lpstrInitialDir = NULL;
open_file.Flags = OFN_PATHMUSTEXIST;
open_file.lpstrDefExt = "inf";
if (GetSaveFileNameU(&open_file))
{
safe_strcpy(device->inf_dir, MAX_PATH, device->inf_path);
length = (int)strlen(device->inf_dir);
while (length)
{
length--;
if (device->inf_dir[length]=='\\' || device->inf_dir[length]=='/')
{
device->inf_dir[length]='\0';
break;
}
device->inf_dir[length]='\0';
}
return infwizard_prepare_driver(dialog, device) == WDI_SUCCESS;
}
return FALSE;
}
int infwizard_prepare_driver(HWND dialog, device_context_t *device)
{
struct wdi_options_prepare_driver options;
int ret;
memset(&options,0,sizeof(options));
options.driver_type = WDI_LIBUSB0;
options.vendor_name = device->manufacturer;
if (device->wdi->desc)
free(device->wdi->desc);
device->wdi->desc = safe_strdup(device->description);
if ((ret = wdi_prepare_driver(device->wdi, device->inf_dir, device->inf_name, &options) != WDI_SUCCESS))
{
MessageBoxA(dialog, wdi_strerror(ret),"Error Preparing Driver", MB_OK|MB_ICONWARNING);
}
return ret;
}
int infwizard_install_driver(HWND dialog, device_context_t *device)
{
struct wdi_options_install_driver options;
int ret;
memset(&options,0,sizeof(options));
options.hWnd = dialog;
if ((ret = wdi_install_driver(device->wdi, device->inf_dir, device->inf_name, &options)) != WDI_SUCCESS)
{
MessageBoxA(dialog, wdi_strerror(ret),"Error Installing Driver", MB_OK|MB_ICONWARNING);
}
return ret;
}
HWND create_tooltip(HWND hMain, HINSTANCE hInstance, UINT max_tip_width, create_tooltip_t tool_tips[])
{
HWND hTip;
TOOLINFO toolInfo = {0};
int i;
hTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hMain, NULL,
hInstance, NULL);
if (hTip == NULL) {
return (HWND)NULL;
}
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hMain;
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
for (i=0; tool_tips[i].controlID != 0 && tool_tips[i].message != NULL; i++)
{
toolInfo.uId =(UINT_PTR)GetDlgItem(hMain,tool_tips[i].controlID);
toolInfo.lpszText = (LPSTR)tool_tips[i].message;
SendMessage(hTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
}
SendMessage(hTip, TTM_SETMAXTIPWIDTH, 0, max_tip_width);
return hTip;
}
HWND CreateTrackingToolTip(HWND hDlg, TCHAR* pText)
{
HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST,
TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hDlg, NULL, g_hInst,NULL);
if (!hwndTT)
{
return NULL;
}
g_toolItem.cbSize = sizeof(TOOLINFO);
g_toolItem.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
g_toolItem.hwnd = hDlg;
g_toolItem.hinst = g_hInst;
g_toolItem.lpszText = pText;
g_toolItem.uId = (UINT_PTR)hDlg;
GetClientRect (hDlg, &g_toolItem.rect);
SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &g_toolItem);
SendMessage(hwndTT, TTM_SETMAXTIPWIDTH, 0, 300);
return hwndTT;
}
enum driver_type {
DT_SYSTEM,
DT_LIBUSB,
DT_UNKNOWN,
DT_NONE,
NB_DRIVER_TYPES,
};
int get_driver_type(struct wdi_device_info* dev)
{
int i;
const char* libusb_name[] = { "WinUSB", "libusb0" };
const char* system_name[] = { "usbhub", "usbccgp", "USBSTOR", "HidUsb"};
if ((dev == NULL) || (dev->driver == NULL)) {
return DT_NONE;
}
for (i=0; i<sizeof(libusb_name)/sizeof(libusb_name[0]); i++) {
if (safe_strcmp(dev->driver, libusb_name[i]) == 0) {
return DT_LIBUSB;
}
}
for (i=0; i<sizeof(system_name)/sizeof(system_name[0]); i++) {
if (safe_strcmp(dev->driver, system_name[i]) == 0) {
return DT_SYSTEM;
}
}
return DT_UNKNOWN;
}