Files
EF3-Interface/PcDmis/ThirdParty/UsbSupport/libusb-win32-src-1.2.4.0/src/install.c
T
2013-05-09 20:29:54 +08:00

2736 lines
71 KiB
C

/* libusb-win32, Generic Windows USB Library
* Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
* Copyright (c) 2010 Travis Robinson <libusbdotnet@gmail.com>
* Parts of the code from libwdi by Pete Batard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <windows.h>
#include <winsvc.h>
#include <setupapi.h>
#include <stdio.h>
#include <regstr.h>
#include <wchar.h>
#include <string.h>
#include <process.h>
#include <richedit.h>
#include <conio.h>
#include <ctype.h>
#ifdef __GNUC__
#if defined(_WIN64)
#include <cfgmgr32.h>
#else
#include <ddk/cfgmgr32.h>
#endif
#else
#include <cfgmgr32.h>
#define strlwr(p) _strlwr(p)
#endif
#include "usb.h"
#include "registry.h"
#include "error.h"
#include "driver_api.h"
#include "libusb-win32_version.h"
#define LIBUSB_DRIVER_PATH "system32\\drivers\\libusb0.sys"
#define LIBUSB_OLD_SERVICE_NAME_NT "libusbd"
#define INSTALLFLAG_FORCE 0x00000001
#define IDC_PROGRESS_TEXT 10001
#define IDC_PROGRESS_BAR 10002
// #define IDC_INFO_PANE 10003
#define UM_PROGRESS_STOP (0x7000 - 1)
#define UM_PROGRESS_START (0x7000 - 2)
#define DISPLAY_NAME "libusb-win32 installer"
#define DISPLAY_RUNNING "libusb-win32 installer running.."
#define DISPLAY_DONE "libusb-win32 installer finished"
#define DISPLAY_DONE_WITH_ERRORS "libusb-win32 installer errors!"
#define COLOR_RED RGB(128,0,0)
#define COLOR_LTRED RGB(255,64,64)
#define COLOR_ORANGE RGB(255, 102, 0)
#define safe_free(p) do { if (p) free(p); p = NULL; }while(0)
#define safe_strlen(p) (p ? strlen(p) : 0)
#define MOVE_CONTROL(ParentHwnd, ControlID, Rect, Repaint, TopZOrder) \
SetWindowPos(GetDlgItem(ParentHwnd, ControlID), HWND_TOP, Rect.left, Rect.top, abs(Rect.right - Rect.left), abs(Rect.bottom - Rect.top), \
(Repaint ? 0 : SWP_NOREDRAW) | (TopZOrder ? 0 : SWP_NOZORDER))
// transform coordinates in a RECT from client to screen coordiantes
#define ClientToScreenRC(hwnd, prect) do{ClientToScreen(hwnd,(LPPOINT)&prect->left); ClientToScreen(hwnd,(LPPOINT)&prect->right); }while(0)
// transform coordinates in a RECT from screen to client coordiantes
#define ScreenToClientRC(hwnd, prect) do{ScreenToClient(hwnd,(LPPOINT)&prect->left); ScreenToClient(hwnd,(LPPOINT)&prect->right); }while(0)
// fills a pointer to a TRIVERTEX structure
#define TRIVERTEX_FILL(TriVertex, XPos, YPos, RedC16, GreenC16, BlueC16, AlphaC16) do { \
(TriVertex)->x = XPos; \
(TriVertex)->y = YPos; \
(TriVertex)->Red = RedC16; \
(TriVertex)->Green = GreenC16; \
(TriVertex)->Blue = BlueC16; \
(TriVertex)->Alpha = AlphaC16; \
}while(0)
#define COLOR16_MAX 0xff00
#define RBG_TO_C16(rgb, add, RField, GField, BField) do { \
if (((int)((GetRValue(rgb) + (add)) * 256)) > COLOR16_MAX) \
RField = COLOR16_MAX; \
else if (((int)((GetRValue(rgb) + (add)) * 256)) < 0) \
RField = 0; \
else \
RField = ((GetRValue(rgb) + (add)) * 256); \
\
\
if (((int)((GetGValue(rgb) + (add)) * 256)) > COLOR16_MAX) \
GField = COLOR16_MAX; \
else if (((int)((GetGValue(rgb) + (add)) * 256)) < 0) \
GField = 0; \
else \
GField = ((GetGValue(rgb) + (add)) * 256); \
\
\
if (((int)((GetBValue(rgb) + (add)) * 256)) > COLOR16_MAX) \
BField = COLOR16_MAX; \
else if (((int)((GetBValue(rgb) + (add)) * 256)) < 0) \
BField = 0; \
else \
BField = ((GetBValue(rgb) + (add)) * 256); \
\
\
}while(0)
LPCSTR install_lock_sem_name = "libusb-win32-installer-{1298B356-F6E3-4455-9FEC-3932714AF49B}";
LPCSTR install_warning = "This will add libusb-win32 as a driver for all usb devices on the PC. "
"This function is for development purposes only. Improper use of the "
"libusb-win32 filter driver can cause devices to malfunction and in some "
"cases complete system failure.";
LPCSTR install_wait = "Press any key to exit..";
/* commands */
LPCWSTR paramcmd_list[] = {
L"list",
L"-l",
L"l",
0
};
LPCWSTR paramcmd_install[] = {
L"install",
L"-i",
L"i",
0
};
LPCWSTR paramcmd_uninstall[] = {
L"uninstall",
L"-u",
L"u",
0
};
LPCWSTR paramcmd_help[] = {
L"--help",
L"help",
L"-h",
L"/?",
L"-?",
L"h",
0
};
/* switches */
LPCWSTR paramsw_all_classes[] = {
L"--all-classes",
L"-ac",
0
};
LPCWSTR paramsw_all_devices[] = {
L"--all-devices",
L"-ad",
0
};
LPCWSTR paramsw_device_classes[] = {
L"--device-classes",
L"-dc",
0
};
LPCWSTR paramsw_class[] = {
L"--class=",
L"-c=",
0
};
LPCWSTR paramsw_device_upper[] = {
L"--device=",
L"-d=",
0
};
LPCWSTR paramsw_device_upper_by_devinst[] = {
L"--device-id=",
L"-di=",
0
};
LPCWSTR paramsw_inf[] = {
L"--inf=",
L"-f=",
0
};
LPCWSTR paramsw_prompt[] = {
L"--prompt=",
L"-p=",
L"-p",
0
};
LPCWSTR paramsw_wait[] = {
L"--wait=",
L"-w=",
L"-w",
0
};
typedef struct _LONGGUID {
unsigned int Data1;
unsigned int Data2;
unsigned int Data3;
unsigned int Data4[ 8 ];
} LONGGUID;
typedef struct _install_progress_context_t
{
HINSTANCE hInstance;
HWND progress_hwnd;
bool_t progress_window_ready;
filter_context_t* filter_context;
uintptr_t thread_id;
int ret;
DWORD progress_textlength;
LONG progress_ind_ofs;
bool_t stopped;
int error_count;
} install_progress_context_t;
static install_progress_context_t g_install_progress_context;
static bool_t usb_install_get_argument(LPWSTR param_value, LPCWSTR* out_param, LPCWSTR* out_value, LPCWSTR* param_names);
void usb_install_report(filter_context_t* filter_context);
void usage(void);
/* riched32.dll */
#define INIT_RICHED32() if (riched32_dll == NULL) riched32_dll = LoadLibrary("riched32")
/* msimg32.dll exports */
typedef BOOL (WINAPI * gradient_fill_t)(HDC,
PTRIVERTEX,
ULONG,
PVOID,
ULONG,
ULONG);
#define INIT_MSIMG32() if (msimg32_dll == NULL) msimg32_dll = LoadLibrary("msimg32")
#define INIT_GRADIENTFILL() if (gradient_fill == NULL) do { \
INIT_MSIMG32(); if (msimg32_dll) gradient_fill = (gradient_fill_t) GetProcAddress(msimg32_dll, "GradientFill"); \
}while(0)
/* shell32.dll exports */
typedef LPWSTR* (WINAPI * commandline_to_argvw_t)(LPCWSTR, int*);
#define INIT_SHELL32() if (shell32_dll == NULL) shell32_dll = LoadLibrary("shell32")
#define INIT_COMMANDLINE_TO_ARGVW() if (commandline_to_argvw == NULL) do { \
INIT_SHELL32(); if (shell32_dll) commandline_to_argvw = (commandline_to_argvw_t) GetProcAddress(shell32_dll, "CommandLineToArgvW"); \
}while(0)
/* kernel32.dll exports */
typedef BOOL (WINAPI * is_wow64_process_t)(HANDLE, PBOOL);
/* newdev.dll exports */
typedef BOOL (WINAPI * update_driver_for_plug_and_play_devices_t)(HWND,
LPCSTR,
LPCSTR,
DWORD,
PBOOL);
typedef BOOL (WINAPI * rollback_driver_t)(HDEVINFO,
PSP_DEVINFO_DATA,
HWND,
DWORD,
PBOOL);
typedef BOOL (WINAPI * uninstall_device_t)(HWND,
HDEVINFO,
PSP_DEVINFO_DATA,
DWORD,
PBOOL);
/* setupapi.dll exports */
typedef BOOL (WINAPI * setup_copy_oem_inf_t)(PCSTR, PCSTR, DWORD, DWORD,
PSTR, DWORD, PDWORD, PSTR*);
/* advapi32.dll exports */
typedef SC_HANDLE (WINAPI * open_sc_manager_t)(LPCTSTR, LPCTSTR, DWORD);
typedef SC_HANDLE (WINAPI * open_service_t)(SC_HANDLE, LPCTSTR, DWORD);
typedef BOOL (WINAPI * change_service_config_t)(SC_HANDLE, DWORD, DWORD,
DWORD, LPCTSTR, LPCTSTR,
LPDWORD, LPCTSTR, LPCTSTR,
LPCTSTR, LPCTSTR);
typedef BOOL (WINAPI * close_service_handle_t)(SC_HANDLE);
typedef SC_HANDLE (WINAPI * create_service_t)(SC_HANDLE, LPCTSTR, LPCTSTR,
DWORD, DWORD, DWORD, DWORD,
LPCTSTR, LPCTSTR, LPDWORD,
LPCTSTR, LPCTSTR, LPCTSTR);
typedef BOOL (WINAPI * delete_service_t)(SC_HANDLE);
typedef BOOL (WINAPI * start_service_t)(SC_HANDLE, DWORD, LPCTSTR);
typedef BOOL (WINAPI * query_service_status_t)(SC_HANDLE, LPSERVICE_STATUS);
typedef BOOL (WINAPI * control_service_t)(SC_HANDLE, DWORD, LPSERVICE_STATUS);
static HINSTANCE riched32_dll = NULL;
static HINSTANCE shell32_dll = NULL;
static HINSTANCE msimg32_dll = NULL;
static HINSTANCE gdi32_dll = NULL;
static HINSTANCE advapi32_dll = NULL;
static commandline_to_argvw_t commandline_to_argvw = NULL;
static gradient_fill_t gradient_fill = NULL;
static open_sc_manager_t open_sc_manager = NULL;
static open_service_t open_service = NULL;
static change_service_config_t change_service_config = NULL;
static close_service_handle_t close_service_handle = NULL;
static create_service_t create_service = NULL;
static delete_service_t delete_service = NULL;
static start_service_t start_service = NULL;
static query_service_status_t query_service_status = NULL;
static control_service_t control_service = NULL;
static bool_t usb_service_load_dll(void);
static bool_t usb_service_free_dll(void);
static bool_t usb_service_create(const char *name, const char *display_name,
const char *binary_path, unsigned long type,
unsigned long start_type);
static bool_t usb_service_stop(const char *name);
static bool_t usb_service_delete(const char *name);
static bool_t usb_install_iswow64(void);
static BOOL usb_install_admin_check(void);
static BOOL usb_install_log_handler(enum USB_LOG_LEVEL level,
const char* app_name,
const char* prefix,
const char* func,
int app_prefix_func_end,
char* message,
int message_length);
int usb_install_window(HWND hWnd, HINSTANCE instance, filter_context_t* filter_context);
int usb_install_console(filter_context_t* filter_context);
void usb_install_destroy_filter_context(filter_context_t** filter_context);
bool_t usb_progress_context_create(install_progress_context_t* install_progress_context,
HINSTANCE hInstance,
filter_context_t* filter_context);
void usb_progress_context_destroy(install_progress_context_t* install_progress_context);
bool_t usb_progress_add_text(HWND hwnd, const char* message, COLORREF crNewColor, bool_t bold, bool_t italic);
BOOL sem_create_lock(HANDLE* sem_handle_out, LPCSTR unique_name, LONG remaining, LONG max);
BOOL sem_destroy_lock(HANDLE* sem_handle_in);
BOOL sem_release_lock(HANDLE sem_handle);
BOOL sem_try_lock(HANDLE sem_handle, DWORD dwMilliseconds);
static void detect_version(void);
// Detect Windows version
/*
* Windows versions
*/
enum windows_version {
WINDOWS_UNDEFINED,
WINDOWS_UNSUPPORTED,
WINDOWS_2K,
WINDOWS_XP,
WINDOWS_2003_XP64,
WINDOWS_VISTA,
WINDOWS_7
};
enum windows_version windows_version = WINDOWS_UNDEFINED;
#define GET_WINDOWS_VERSION do{ if (windows_version == WINDOWS_UNDEFINED) detect_version(); } while(0)
static void detect_version(void)
{
OSVERSIONINFO os_version;
memset(&os_version, 0, sizeof(OSVERSIONINFO));
os_version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
windows_version = WINDOWS_UNSUPPORTED;
if ((GetVersionEx(&os_version) != 0) && (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
if ((os_version.dwMajorVersion == 5) && (os_version.dwMinorVersion == 0)) {
windows_version = WINDOWS_2K;
} else if ((os_version.dwMajorVersion == 5) && (os_version.dwMinorVersion == 1)) {
windows_version = WINDOWS_XP;
} else if ((os_version.dwMajorVersion == 5) && (os_version.dwMinorVersion == 2)) {
windows_version = WINDOWS_2003_XP64;
} else if (os_version.dwMajorVersion >= 6) {
if (os_version.dwBuildNumber < 7000) {
windows_version = WINDOWS_VISTA;
} else {
windows_version = WINDOWS_7;
}
}
}
}
BOOL sem_create_lock(HANDLE* sem_handle_out, LPCSTR unique_name, LONG remaining, LONG max)
{
SECURITY_ATTRIBUTES sem_attributes;
memset(&sem_attributes, 0, sizeof(sem_attributes));
sem_attributes.nLength = sizeof(sem_attributes);
sem_attributes.bInheritHandle = TRUE;
*sem_handle_out = CreateSemaphoreA(&sem_attributes, remaining, max, unique_name);
return *sem_handle_out != NULL;
}
BOOL sem_destroy_lock(HANDLE* sem_handle_in)
{
if (sem_handle_in && *sem_handle_in)
{
return CloseHandle(*sem_handle_in);
*sem_handle_in = NULL;
}
return FALSE;
}
BOOL sem_release_lock(HANDLE sem_handle)
{
if (!sem_handle) return FALSE;
return ReleaseSemaphore(sem_handle, 1, NULL);
}
BOOL sem_try_lock(HANDLE sem_handle, DWORD dwMilliseconds)
{
if (!sem_handle) return FALSE;
return WaitForSingleObject(sem_handle, dwMilliseconds) == WAIT_OBJECT_0;
}
void CALLBACK usb_touch_inf_file_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show);
void CALLBACK usb_install_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show)
{
usb_install_service_np();
}
void CALLBACK usb_uninstall_service_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show)
{
usb_uninstall_service_np();
}
void CALLBACK usb_install_driver_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show)
{
usb_install_driver_np(cmd_line);
}
int usb_install_service(filter_context_t* filter_context)
{
char display_name[MAX_PATH];
int ret = 0;
const char* driver_name = LIBUSB_DRIVER_NAME_NT;
/* stop devices that are handled by libusb's device driver */
usb_registry_stop_libusb_devices();
/* the old driver is unloaded now */
if (usb_registry_is_nt())
{
memset(display_name, 0, sizeof(display_name));
/* create the Display Name */
_snprintf(display_name, sizeof(display_name) - 1,
"libusb-win32 - Kernel Driver, Version %d.%d.%d.%d",
VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, VERSION_NANO);
/* create the kernel service */
USBMSG("creating %s service..\n", driver_name);
if (!usb_service_create(driver_name, display_name,
LIBUSB_DRIVER_PATH,
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START))
{
USBERR("failed creating service %s\n", driver_name);
ret = -1;
return ret;
}
}
/* restart devices that are handled by libusb's device driver */
usb_registry_start_libusb_devices();
/* insert device filter drivers */
usb_registry_insert_device_filters(filter_context);
/* insert class filter driver */
usb_registry_insert_class_filter(filter_context);
if (filter_context->class_filters_modified)
{
/* restart the whole USB system so that the new drivers will be loaded */
usb_registry_restart_all_devices();
filter_context->class_filters_modified = FALSE;
}
return ret;
}
int usb_install_service_np(void)
{
return usb_install_npA(NULL, NULL, "i -dc", 0);
}
int usb_uninstall_service(filter_context_t* filter_context)
{
if (!usb_registry_is_nt()) return -1;
/* older version of libusb used a system service, just remove it */
usb_service_stop(LIBUSB_OLD_SERVICE_NAME_NT);
usb_service_delete(LIBUSB_OLD_SERVICE_NAME_NT);
/* remove user specified device filters */
if (filter_context->device_filters || filter_context->remove_all_device_filters)
{
usb_registry_remove_device_filter(filter_context);
}
/* remove class filter driver */
usb_registry_remove_class_filter(filter_context);
/* unload filter drivers */
if (filter_context->class_filters_modified)
{
usb_registry_restart_all_devices();
filter_context->class_filters_modified = FALSE;
}
return 0;
}
int usb_uninstall_service_np(void)
{
return usb_install_npA(NULL, NULL, "u -ac", 0);
}
BOOL usb_install_find_model_section(HINF inf_handle, PINFCONTEXT inf_context)
{
// find the .inf file's model-section. This is normally a [Devices]
// section, but could be anything.
char tmp[MAX_PATH];
char* model[8];
BOOL success = FALSE;
DWORD field_index;
// first find [Manufacturer]. The models are listeed in this section.
if (SetupFindFirstLine(inf_handle, "Manufacturer", NULL, inf_context))
{
memset(model, 0, sizeof(model));
for (field_index = 1; field_index < ( sizeof(model) / sizeof(model[0]) ); field_index++)
{
success = SetupGetStringField(inf_context, field_index, tmp, sizeof(tmp), NULL);
if (!success) break;
model[(field_index-1)] = _strdup(tmp);
switch(field_index)
{
case 1: // The first field is the base model-section-name, "Devices" for example.
USBDBG("model-section-name=%s\n", tmp);
break;
default: // These are the target OS field(s), "NT" or "NTX86" for example.
USBDBG("target-os-version=%s\n", tmp);
}
}
// if the base model-section-name was found..
if (field_index > 1)
{
// find the model-section
field_index = 0;
strcpy(tmp, model[0]);
while (!(success = SetupFindFirstLine(inf_handle, tmp, NULL, inf_context)))
{
field_index++;
if (!model[field_index]) break;
sprintf(tmp, "%s.%s", model[0], model[field_index]);
}
}
// these were allocated with _strdup above.
for (field_index = 0; model[field_index] != NULL; field_index++)
free(model[field_index]);
// model-section-name or model-section not found
if (!success)
{
USBERR0(".inf file does not contain a valid model-section-name\n");
}
}
else
{
USBERR0(".inf file does not contain a valid Manufacturer section\n");
}
return success;
}
int usb_install_inf_np(const char *inf_file,
bool_t remove_mode,
bool_t copy_oem_inf_mode)
{
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;
CONFIGRET cr;
update_driver_for_plug_and_play_devices_t UpdateDriverForPlugAndPlayDevices;
rollback_driver_t RollBackDriver;
uninstall_device_t UninstallDevice;
bool_t usb_reset_required = FALSE;
int field_index;
setup_copy_oem_inf_t SetupCopyOEMInf;
if (usb_install_iswow64())
{
USBERR0("This is a 64bit operating system and requires the 64bit " DISPLAY_NAME " application.\n");
return -1;
}
newdev_dll = LoadLibrary("newdev.dll");
if (!newdev_dll)
{
USBERR0("loading newdev.dll failed\n");
return -1;
}
UpdateDriverForPlugAndPlayDevices = (update_driver_for_plug_and_play_devices_t)GetProcAddress(newdev_dll, "UpdateDriverForPlugAndPlayDevicesA");
if (!UpdateDriverForPlugAndPlayDevices)
{
USBERR0("loading newdev.dll failed\n");
return -1;
}
UninstallDevice = (uninstall_device_t)GetProcAddress(newdev_dll, "DiUninstallDevice");
RollBackDriver = (rollback_driver_t)GetProcAddress(newdev_dll, "DiRollbackDriver");
setupapi_dll = GetModuleHandle("setupapi.dll");
if (!setupapi_dll)
{
USBERR0("loading setupapi.dll failed\n");
return -1;
}
SetupCopyOEMInf = (setup_copy_oem_inf_t)GetProcAddress(setupapi_dll, "SetupCopyOEMInfA");
if (!SetupCopyOEMInf)
{
USBERR0("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))
{
USBERR(".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)
{
USBERR("unable to open .inf file %s\n",
inf_file);
return -1;
}
if (!usb_install_find_model_section(inf_handle, &inf_context))
{
SetupCloseInfFile(inf_handle);
return -1;
}
do
{
/* get the device ID from the .inf file */
field_index = 2;
while(SetupGetStringField(&inf_context, field_index++, id, sizeof(id), NULL))
{
/* convert the string to lowercase */
strlwr(id);
if (strncmp(id, "usb\\", 4) != 0)
{
USBERR("invalid hardware id %s\n", id);
SetupCloseInfFile(inf_handle);
return -1;
}
USBMSG("%s device %s..\n",
remove_mode ? "removing" : "installing", id + 4);
reboot = FALSE;
if (!remove_mode)
{
if (copy_oem_inf_mode)
{
/* copy the .inf file to the system directory so that is will be found */
/* when new devices are plugged in */
if (SetupCopyOEMInf(inf_path, NULL, SPOST_PATH, 0, NULL, 0, NULL, NULL))
{
USBDBG("SetupCopyOEMInf failed for %s\n", inf_path);
}
else
{
USBDBG(".inf file %s copied to system directory\n", inf_path);
copy_oem_inf_mode = FALSE;
}
}
/* force an update of all connected devices matching this ID */
UpdateDriverForPlugAndPlayDevices(NULL, id, inf_path, INSTALLFLAG_FORCE, &reboot);
}
/* now search the registry for device nodes representing currently */
/* unattached devices or remove devices depending on the mode */
/* 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);
return -1;
}
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))
{
if (remove_mode)
{
if (RollBackDriver)
{
if (RollBackDriver(dev_info, &dev_info_data, NULL, 0, &reboot))
{
break;
}
else
{
USBERR("failed RollBackDriver for device %s\n", p);
}
}
if (UninstallDevice)
{
if (UninstallDevice(NULL, dev_info, &dev_info_data, 0, &reboot))
{
usb_reset_required = TRUE;
break;
}
else
{
USBERR("failed UninstallDevice for device %s\n", p);
}
}
if (SetupDiRemoveDevice(dev_info, &dev_info_data))
{
usb_reset_required = TRUE;
break;
}
else
{
USBERR("failed RemoveDevice for device %s\n", p);
}
}
else
{
cr = CM_Get_DevNode_Status(&status,
&problem,
dev_info_data.DevInst,
0);
/* is this device disconnected? */
if (cr == 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);
if (usb_reset_required)
{
usb_registry_restart_all_devices();
}
else if (!remove_mode)
{
usb_registry_stop_libusb_devices(); /* stop all libusb devices */
usb_registry_start_libusb_devices(); /* restart all libusb devices */
}
return 0;
}
int usb_install_driver_np(const char *inf_file)
{
return usb_install_inf_np(inf_file, FALSE, TRUE);
}
bool_t usb_service_load_dll()
{
if (usb_registry_is_nt())
{
advapi32_dll = LoadLibrary("advapi32.dll");
if (!advapi32_dll)
{
USBERR0("loading DLL advapi32.dll failed\n");
return FALSE;
}
open_sc_manager = (open_sc_manager_t)
GetProcAddress(advapi32_dll, "OpenSCManagerA");
open_service = (open_service_t)
GetProcAddress(advapi32_dll, "OpenServiceA");
change_service_config = (change_service_config_t)
GetProcAddress(advapi32_dll, "ChangeServiceConfigA");
close_service_handle = (close_service_handle_t)
GetProcAddress(advapi32_dll, "CloseServiceHandle");
create_service = (create_service_t)
GetProcAddress(advapi32_dll, "CreateServiceA");
delete_service = (delete_service_t)
GetProcAddress(advapi32_dll, "DeleteService");
start_service = (start_service_t)
GetProcAddress(advapi32_dll, "StartServiceA");
query_service_status = (query_service_status_t)
GetProcAddress(advapi32_dll, "QueryServiceStatus");
control_service = (control_service_t)
GetProcAddress(advapi32_dll, "ControlService");
if (!open_sc_manager || !open_service || !change_service_config
|| !close_service_handle || !create_service || !delete_service
|| !start_service || !query_service_status || !control_service)
{
FreeLibrary(advapi32_dll);
USBERR0("loading exported functions of advapi32.dll failed");
return FALSE;
}
}
return TRUE;
}
bool_t usb_service_free_dll()
{
if (advapi32_dll)
{
FreeLibrary(advapi32_dll);
}
return TRUE;
}
bool_t usb_service_create(const char *name, const char *display_name,
const char *binary_path, unsigned long type,
unsigned long start_type)
{
SC_HANDLE scm = NULL;
SC_HANDLE service = NULL;
bool_t ret = FALSE;
if (!usb_service_load_dll())
{
return FALSE;
}
do
{
scm = open_sc_manager(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_ALL_ACCESS);
if (!scm)
{
USBERR("opening service control "
"manager failed: %s", usb_win_error_to_string());
break;
}
service = open_service(scm, name, SERVICE_ALL_ACCESS);
if (service)
{
if (!change_service_config(service,
type,
start_type,
SERVICE_ERROR_NORMAL,
binary_path,
NULL,
NULL,
NULL,
NULL,
NULL,
display_name))
{
USBERR("changing config of "
"service '%s' failed: %s",
name, usb_win_error_to_string());
break;
}
ret = TRUE;
break;
}
if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
{
service = create_service(scm,
name,
display_name,
GENERIC_EXECUTE,
type,
start_type,
SERVICE_ERROR_NORMAL,
binary_path,
NULL, NULL, NULL, NULL, NULL);
if (!service)
{
USBERR("creating "
"service '%s' failed: %s",
name, usb_win_error_to_string());
}
ret = TRUE;
}
}
while (0);
if (service)
{
close_service_handle(service);
}
if (scm)
{
close_service_handle(scm);
}
usb_service_free_dll();
return ret;
}
bool_t usb_service_stop(const char *name)
{
bool_t ret = FALSE;
SC_HANDLE scm = NULL;
SC_HANDLE service = NULL;
SERVICE_STATUS status;
if (!usb_service_load_dll())
{
return FALSE;
}
USBMSG("stopping %s service..\n", name);
do
{
scm = open_sc_manager(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_ALL_ACCESS);
if (!scm)
{
USBERR("opening service control "
"manager failed: %s", usb_win_error_to_string());
break;
}
service = open_service(scm, name, SERVICE_ALL_ACCESS);
if (!service)
{
ret = TRUE;
break;
}
if (!query_service_status(service, &status))
{
USBERR("getting status of "
"service '%s' failed: %s",
name, usb_win_error_to_string());
break;
}
if (status.dwCurrentState == SERVICE_STOPPED)
{
ret = TRUE;
break;
}
if (!control_service(service, SERVICE_CONTROL_STOP, &status))
{
USBERR("stopping service '%s' failed: %s",
name, usb_win_error_to_string());
break;
}
do
{
int wait = 0;
if (!query_service_status(service, &status))
{
USBERR("getting status of "
"service '%s' failed: %s",
name, usb_win_error_to_string());
break;
}
Sleep(500);
wait += 500;
if (wait > 20000)
{
USBERR("stopping "
"service '%s' failed, timeout", name);
ret = FALSE;
break;
}
ret = TRUE;
}
while (status.dwCurrentState != SERVICE_STOPPED);
}
while (0);
if (service)
{
close_service_handle(service);
}
if (scm)
{
close_service_handle(scm);
}
usb_service_free_dll();
return ret;
}
bool_t usb_service_delete(const char *name)
{
bool_t ret = FALSE;
SC_HANDLE scm = NULL;
SC_HANDLE service = NULL;
if (!usb_service_load_dll())
{
return FALSE;
}
USBMSG("deleting %s service..\n", name);
do
{
scm = open_sc_manager(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_ALL_ACCESS);
if (!scm)
{
USBERR("opening service control "
"manager failed: %s", usb_win_error_to_string());
break;
}
service = open_service(scm, name, SERVICE_ALL_ACCESS);
if (!service)
{
ret = TRUE;
break;
}
if (!delete_service(service))
{
USBERR("deleting "
"service '%s' failed: %s",
name, usb_win_error_to_string());
break;
}
ret = TRUE;
}
while (0);
if (service)
{
close_service_handle(service);
}
if (scm)
{
close_service_handle(scm);
}
usb_service_free_dll();
return ret;
}
void CALLBACK usb_touch_inf_file_np_rundll(HWND wnd, HINSTANCE instance,
LPSTR cmd_line, int cmd_show)
{
usb_touch_inf_file_np(cmd_line);
}
int usb_touch_inf_file_np(const char *inf_file)
{
const char inf_comment[] = ";added by libusb to break this file's digital "
"signature";
const wchar_t inf_comment_uni[] = L";added by libusb to break this file's "
L"digital signature";
char buf[1024];
wchar_t wbuf[1024];
int found = 0;
OSVERSIONINFO version;
FILE *f;
version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&version))
return -1;
/* XP system */
if ((version.dwMajorVersion == 5) && (version.dwMinorVersion >= 1))
{
f = fopen(inf_file, "rb");
if (!f)
return -1;
while (fgetws(wbuf, sizeof(wbuf) / 2, f))
{
if (wcsstr(wbuf, inf_comment_uni))
{
found = 1;
break;
}
}
fclose(f);
if (!found)
{
f = fopen(inf_file, "ab");
/* fputwc(0x000d, f); */
/* fputwc(0x000d, f); */
fputws(inf_comment_uni, f);
fclose(f);
}
}
else
{
f = fopen(inf_file, "r");
if (!f)
return -1;
while (fgets(buf, sizeof(buf), f))
{
if (strstr(buf, inf_comment))
{
found = 1;
break;
}
}
fclose(f);
if (!found)
{
f = fopen(inf_file, "a");
fputs("\n", f);
fputs(inf_comment, f);
fputs("\n", f);
fclose(f);
}
}
return 0;
}
int usb_install_needs_restart_np(void)
{
HDEVINFO dev_info;
SP_DEVINFO_DATA dev_info_data;
int dev_index = 0;
SP_DEVINSTALL_PARAMS install_params;
int ret = FALSE;
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
dev_info = SetupDiGetClassDevs(NULL, NULL, NULL,
DIGCF_ALLCLASSES | DIGCF_PRESENT);
SetEnvironmentVariable("LIBUSB_NEEDS_REBOOT", "1");
if (dev_info == INVALID_HANDLE_VALUE)
{
USBERR0("getting device info set failed\n");
return ret;
}
while (SetupDiEnumDeviceInfo(dev_info, dev_index, &dev_info_data))
{
memset(&install_params, 0, sizeof(SP_PROPCHANGE_PARAMS));
install_params.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
if (SetupDiGetDeviceInstallParams(dev_info, &dev_info_data,
&install_params))
{
if (install_params.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))
{
USBMSG0("restart needed\n");
ret = TRUE;
}
}
dev_index++;
}
SetupDiDestroyDeviceInfoList(dev_info);
return ret;
}
bool_t usb_install_parse_filter_context(filter_context_t* filter_context,
LPCWSTR cmd_line,
int arg_start,
int* arg_cnt)
{
#define GET_ARG(Params) usb_install_get_argument(argv[arg_pos], &arg_param, &arg_value, Params)
LONGGUID class_guid;
int arg_pos;
LPWSTR* argv = NULL;
LPCWSTR arg_param, arg_value;
bool_t success = TRUE;
size_t length;
char tmp[MAX_PATH+1];
filter_device_t* found_device;
filter_class_t* found_class;
filter_file_t* found_inf;
*arg_cnt = 0;
INIT_COMMANDLINE_TO_ARGVW();
if (!commandline_to_argvw)
{
USBERR("failed CommandLineToArgvW:%X", GetLastError());
success = FALSE;
goto Done;
}
if (!(argv = commandline_to_argvw(cmd_line, arg_cnt)))
{
USBERR("failed CommandLineToArgvW:%X", GetLastError());
success = FALSE;
goto Done;
}
if (*arg_cnt <= arg_start)
{
success = FALSE;
goto Done;
}
for(arg_pos = arg_start; arg_pos < *arg_cnt; arg_pos++)
{
if (GET_ARG(paramcmd_help))
{
filter_context->show_help_only = TRUE;
break;
}
else if (GET_ARG(paramcmd_list))
{
if (filter_context->filter_mode)
{
USBERR("multiple commands not allowed: %ls\n", argv[arg_pos]);
success = FALSE;
break;
}
filter_context->filter_mode = FM_LIST;
}
else if (GET_ARG(paramcmd_install))
{
if (filter_context->filter_mode)
{
USBERR("multiple commands not allowed: %ls\n", argv[arg_pos]);
success = FALSE;
break;
}
filter_context->filter_mode = FM_INSTALL;
}
else if (GET_ARG(paramcmd_uninstall))
{
if (filter_context->filter_mode)
{
USBERR("multiple commands not allowed: %ls\n", argv[arg_pos]);
success = FALSE;
break;
}
filter_context->filter_mode = FM_REMOVE;
}
else if (GET_ARG(paramsw_all_classes))
{
filter_context->switches.add_all_classes = TRUE;
}
else if (GET_ARG(paramsw_device_classes))
{
filter_context->switches.add_device_classes = TRUE;
}
else if (GET_ARG(paramsw_all_devices))
{
filter_context->remove_all_device_filters = TRUE;
}
else if ( GET_ARG(paramsw_device_upper) || GET_ARG(paramsw_device_upper_by_devinst) )
{
length = wcstombs(tmp, arg_value, MAX_PATH);
if (length < 1)
{
success = FALSE;
USBERR("invalid argument %ls\n", argv[arg_pos]);
break;
}
tmp[length] = 0;
if (GET_ARG(paramsw_device_upper))
{
usb_registry_add_filter_device_keys(&filter_context->device_filters, "", tmp, "", "", "", "", &found_device);
}
else if (GET_ARG(paramsw_device_upper_by_devinst))
{
usb_registry_add_filter_device_keys(&filter_context->device_filters, tmp, "", "", "", "", "", &found_device);
}
// upper device filter
if (!found_device)
{
success = FALSE;
USBERR("failed adding device upper filter key %ls\n", argv[arg_pos]);
break;
}
else
{
found_device->action |= FT_DEVICE_UPPERFILTER;
}
}
else if (GET_ARG(paramsw_class))
{
memset(tmp, 0, sizeof(tmp));
length = wcstombs(tmp, arg_value, MAX_PATH);
if (length < 1)
{
success = FALSE;
USBERR("invalid argument %ls\n", argv[arg_pos]);
break;
}
tmp[length] = 0;
if ((length != 38 || tmp[0] != '{' || tmp[length-1] != '}') ||
sscanf(tmp, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
&class_guid.Data1, &class_guid.Data2, &class_guid.Data3,
&class_guid.Data4[0], &class_guid.Data4[1], &class_guid.Data4[2], &class_guid.Data4[3],
&class_guid.Data4[4], &class_guid.Data4[5], &class_guid.Data4[6], &class_guid.Data4[7]) != 11)
{
// assume arg_value is a class name
success = usb_registry_add_class_key(&filter_context->class_filters,
"", tmp, "", &found_class, FALSE);
if (!success)
{
USBERR("failed adding class name at argument %ls\n", argv[arg_pos]);
break;
}
}
else
{
sprintf(tmp, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
class_guid.Data1, class_guid.Data2, class_guid.Data3,
class_guid.Data4[0], class_guid.Data4[1], class_guid.Data4[2], class_guid.Data4[3],
class_guid.Data4[4], class_guid.Data4[5], class_guid.Data4[6], class_guid.Data4[7]);
// assume arg_value is a class guid
success = usb_registry_add_usb_class_key(filter_context, tmp);
if (!success)
{
USBERR("failed adding class guid at argument %ls\n", argv[arg_pos]);
break;
}
}
}
else if (GET_ARG(paramsw_inf))
{
memset(tmp, 0, sizeof(tmp));
length = wcstombs(tmp, arg_value, MAX_PATH);
if (length < 1)
{
success = FALSE;
USBERR("invalid argument %ls\n", argv[arg_pos]);
break;
}
tmp[length] = 0;
usb_registry_add_filter_file_keys(&filter_context->inf_files, tmp, &found_inf);
if (!found_inf)
{
success = FALSE;
USBERR("failed adding inf %ls\n", argv[arg_pos]);
break;
}
}
else if (GET_ARG(paramsw_prompt))
{
if (arg_value && wcslen(arg_value))
{
length = wcstombs(NULL, arg_value, 4096);
if (length < 1)
{
success = FALSE;
USBERR("failed wcstombs %ls\n", argv[arg_pos]);
break;
}
length+=3;
filter_context->prompt_string = (char*)malloc(length);
length = wcstombs(filter_context->prompt_string, arg_value, length);
if (length < 1)
{
success = FALSE;
USBERR("failed wcstombs %ls\n", argv[arg_pos]);
break;
}
filter_context->prompt_string[length] = 0;
}
else
{
filter_context->prompt_string = (char*)malloc(strlen(install_warning)+1);
strcpy(filter_context->prompt_string, install_warning);
}
}
else if (GET_ARG(paramsw_wait))
{
if (arg_value && wcslen(arg_value))
{
length = wcstombs(NULL, arg_value, 4096);
if (length < 1)
{
success = FALSE;
USBERR("failed wcstombs %ls\n", argv[arg_pos]);
break;
}
length+=3;
filter_context->wait_string = (char*)malloc(length);
length = wcstombs(filter_context->wait_string, arg_value, length);
if (length < 1)
{
success = FALSE;
USBERR("failed wcstombs %ls\n", argv[arg_pos]);
break;
}
filter_context->wait_string[length] = 0;
}
else
{
filter_context->wait_string = (char*)malloc(strlen(install_wait)+1);
strcpy(filter_context->wait_string, install_wait);
}
}
else
{
USBERR("invalid argument %ls\n", argv[arg_pos]);
success = FALSE;
break;
}
}
Done:
if (success && filter_context->class_filters)
{
// find class keys (fill in the blanks)
usb_registry_lookup_class_keys_by_name(&filter_context->class_filters);
}
if (argv)
{
LocalFree(argv);
}
return success;
}
int usb_install_npA(HWND hwnd, HINSTANCE instance, LPCSTR cmd_line, int starg_arg)
{
WCHAR* cmd_line_w;
size_t length;
int ret;
if (!cmd_line || !strlen(cmd_line))
{
return -1;
}
length = (strlen(cmd_line) * sizeof(WCHAR)) + sizeof(WCHAR);
cmd_line_w = malloc(length);
if (!cmd_line_w)
return -1;
memset(cmd_line_w, 0, length);
if ((length = mbstowcs(cmd_line_w, cmd_line, length / sizeof(WCHAR))) < 1)
{
free(cmd_line_w);
return -1;
}
cmd_line_w[length] = 0;
ret = usb_install_npW(hwnd, instance, cmd_line_w, starg_arg);
free(cmd_line_w);
return ret;
}
int usb_install_npW(HWND hwnd, HINSTANCE instance, LPCWSTR cmd_line_w, int starg_arg)
{
filter_context_t* filter_context;
int ret = ERROR_SUCCESS;
HANDLE sem_handle = NULL;
int arg_cnt;
// create a named semaphore
if (!sem_create_lock(&sem_handle, install_lock_sem_name, 1, 1))
return -1;
// lock the semaphore
if (!sem_try_lock(sem_handle, 0))
{
sem_destroy_lock(&sem_handle);
return -1;
}
// use the log handler to report progress status
if (!usb_log_get_handler())
{
usb_log_set_handler(usb_install_log_handler);
usb_log_set_level(LOG_DEBUG);
}
else
{
ret = -1;
goto Done;
}
// allocate the filter context
filter_context = (filter_context_t*)malloc(sizeof(filter_context_t));
if (!filter_context)
{
USBERR0("memory allocation failure\n");
ret = -1;
goto Done;
}
memset(filter_context, 0, sizeof(filter_context_t));
// Fill the filter context from the command line arguments.
if (!(usb_install_parse_filter_context(filter_context, cmd_line_w, starg_arg, &arg_cnt)))
{
if (arg_cnt <= starg_arg)
{
usage();
}
ret = -1;
if (hwnd)
{
MessageBoxA(hwnd, usb_strerror(), DISPLAY_NAME " error", MB_OK | MB_ICONERROR);
}
goto Done;
}
if (filter_context->show_help_only)
{
usage();
ret = -1;
goto Done;
}
if (hwnd && instance)
{
// Using windowed install mode.
if (safe_strlen(filter_context->prompt_string))
{
const char* msg_title = DISPLAY_NAME;
if (MessageBox(hwnd, filter_context->prompt_string, msg_title, MB_OKCANCEL) != IDOK)
{
ret = -1;
}
}
if (ret == ERROR_SUCCESS)
{
ret = usb_install_window(hwnd, instance, filter_context);
}
}
else
{
// Using console install mode.
if (ret == ERROR_SUCCESS)
{
ret = usb_install_console(filter_context);
if (safe_strlen(filter_context->wait_string))
{
printf(filter_context->wait_string);
_getch();
}
}
}
Done:
// Free the filter context.
usb_install_destroy_filter_context(&filter_context);
// Restore the default log handler.
usb_log_set_handler(NULL);
// Close (release) the semaphore lock.
sem_destroy_lock(&sem_handle);
return ret;
}
void CALLBACK usb_install_np_rundll(HWND wnd, HINSTANCE instance, LPSTR cmd_line, int cmd_show)
{
usb_install_npA(wnd, instance, cmd_line, 0);
}
void usb_install_destroy_filter_context(filter_context_t** filter_context)
{
filter_context_t* p = *filter_context;
if (filter_context && p)
{
usb_registry_free_class_keys(&p->class_filters);
usb_registry_free_filter_devices(&p->device_filters);
usb_registry_free_filter_files(&p->inf_files);
safe_free(p->prompt_string);
safe_free(p->wait_string);
free(p);
*filter_context = NULL;
}
}
static void center_dialog(HWND hWndToCenterOn, HWND hWndSubDialog)
{
RECT rectToCenterOn;
RECT rectSubDialog;
int xLeft, yTop;
if (hWndSubDialog == NULL)
return;
if (hWndToCenterOn == NULL)
hWndToCenterOn = GetDesktopWindow();
GetWindowRect(hWndToCenterOn, &rectToCenterOn);
GetWindowRect(hWndSubDialog, &rectSubDialog);
if ((rectToCenterOn.right - rectToCenterOn.left) < (rectSubDialog.right - rectSubDialog.left) ||
rectToCenterOn.left < 0 ||
rectToCenterOn.top < 0 ||
(rectToCenterOn.bottom - rectToCenterOn.top) < (rectSubDialog.bottom - rectSubDialog.top))
{
hWndToCenterOn = GetDesktopWindow();
GetWindowRect(hWndToCenterOn, &rectToCenterOn);
}
xLeft = (rectToCenterOn.left + rectToCenterOn.right) / 2 - (rectSubDialog.right - rectSubDialog.left) / 2;
yTop = (rectToCenterOn.top + rectToCenterOn.bottom) / 2 - (rectSubDialog.bottom - rectSubDialog.top) / 2;
// Move the window to the correct coordinates with SetWindowPos()
SetWindowPos(hWndSubDialog, HWND_TOP, xLeft, yTop, -1, -1, SWP_NOSIZE | SWP_SHOWWINDOW);
}
static BOOL usb_install_log_handler(enum USB_LOG_LEVEL level,
const char* app_name,
const char* prefix,
const char* func,
int app_prefix_func_end,
char* message,
int message_length)
{
HANDLE std_handle;
DWORD req_length;
HWND hDlg, hWnd;
if (g_install_progress_context.progress_window_ready && g_install_progress_context.progress_hwnd)
{
hDlg = g_install_progress_context.progress_hwnd;
hWnd = GetDlgItem(hDlg, IDC_PROGRESS_TEXT);
if (!hWnd)
{
// use default log handler
return FALSE;
}
//strip the app, func, and prefix
message += app_prefix_func_end;
message_length -= app_prefix_func_end;
// trim right '\n'
while(message_length > 0 && message[message_length-1] == '\n')
{
message[message_length-1] = 0;
message_length--;
}
// trim left '\n'
while(message_length > 0 && message[0] == '\n')
{
message++;
message_length--;
}
switch(level & LOG_LEVEL_MASK)
{
case LOG_ERROR:
g_install_progress_context.error_count++;
usb_progress_add_text(hWnd, message, COLOR_RED, FALSE, FALSE);
break;
case LOG_WARNING:
usb_progress_add_text(hWnd, message, COLOR_ORANGE, FALSE, TRUE);
break;
default:
usb_progress_add_text(hWnd, message, GetSysColor(COLOR_BTNTEXT), FALSE, FALSE);
break;
}
return TRUE;
}
else if (((std_handle = GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE) && std_handle)
{
if ((level & LOG_LEVEL_MASK) == LOG_ERROR)
std_handle = GetStdHandle(STD_ERROR_HANDLE);
if (std_handle && std_handle != INVALID_HANDLE_VALUE)
{
WriteConsoleA(std_handle, message, (DWORD)message_length, &req_length, NULL);
return TRUE;
}
// use default log handler
return FALSE;
}
// use default log handler
return FALSE;
}
int usb_install_console(filter_context_t* filter_context)
{
filter_file_t* filter_file;
int ret = 0;
if (!usb_install_admin_check())
{
USBERR0(DISPLAY_NAME " requires administrative privileges.\n");
ret = -1;
goto Done;
}
if (usb_install_iswow64())
{
USBERR0("This is a 64bit operating system and requires the 64bit " DISPLAY_NAME " application.\n");
ret = -1;
goto Done;
}
if (!filter_context->filter_mode)
{
USBERR("command not specified. Use %ls, %ls, or %ls.\n",
paramcmd_list[0], paramcmd_install[0], paramcmd_uninstall[0]);
ret = -1;
goto Done;
}
/* only add the default class keys if there is nothing else to do. */
if (filter_context->class_filters ||
filter_context->device_filters ||
filter_context->inf_files ||
filter_context->switches.add_all_classes ||
filter_context->switches.add_device_classes ||
filter_context->remove_all_device_filters)
{
filter_context->switches.add_default_classes = FALSE;
}
else
{
filter_context->switches.add_default_classes = TRUE;
}
USBRAWMSG("\n" DISPLAY_NAME " (v%u.%u.%u.%u)\n",
VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO, VERSION_NANO);
do
{
bool_t refresh_only;
// if the user specified class keys and the -ac or -dc switch, remove the users keys.
if (filter_context->class_filters && (filter_context->switches.add_all_classes || filter_context->switches.add_device_classes))
{
USBWRN0("-ac and -dc switches are incompatible with -c=<class> switch\n");
usb_registry_free_class_keys(&filter_context->class_filters);
}
if (filter_context->filter_mode == FM_REMOVE)
{
if (filter_context->switches.switches_value ||
filter_context->class_filters ||
filter_context->device_filters)
{
if (filter_context->switches.add_all_classes || filter_context->switches.add_device_classes)
refresh_only = FALSE;
else
refresh_only = TRUE;
if (!usb_registry_get_usb_class_keys(filter_context, refresh_only))
{
ret = -1;
break;
}
if (!usb_registry_get_all_class_keys(filter_context, refresh_only))
{
ret = -1;
break;
}
}
// uninstall class & device filters
ret = usb_uninstall_service(filter_context);
if (ret < 0)
{
break;
}
// rollback/uninstall devices using inf files
filter_file = filter_context->inf_files;
while (filter_file)
{
USBMSG("uninstalling inf %s..\n", filter_file->name);
if (usb_install_inf_np(filter_file->name, TRUE, TRUE) < 0)
{
ret = -1;
break;
}
filter_file = filter_file->next;
}
if (ret == -1)
break;
}
else if (filter_context->filter_mode == FM_INSTALL)
{
if (filter_context->remove_all_device_filters)
{
USBWRN("invalid switch for install operation (%ls)\n",paramsw_all_devices[0]);
}
if (filter_context->switches.switches_value ||
filter_context->class_filters ||
filter_context->device_filters)
{
if (filter_context->switches.add_all_classes || filter_context->switches.add_device_classes)
refresh_only = FALSE;
else
refresh_only = TRUE;
if (!usb_registry_get_usb_class_keys(filter_context, refresh_only))
{
ret = -1;
break;
}
if (!usb_registry_get_all_class_keys(filter_context, refresh_only))
{
ret = -1;
break;
}
ret = usb_install_service(filter_context);
if (ret < 0)
{
break;
}
}
filter_file = filter_context->inf_files;
while (filter_file)
{
USBMSG("installing inf %s..\n", filter_file->name);
if (usb_install_inf_np(filter_file->name, FALSE, TRUE) < 0)
{
ret = -1;
break;
}
filter_file = filter_file->next;
}
if (ret == -1)
break;
}
else if (filter_context->filter_mode == FM_LIST)
{
if (!usb_registry_get_usb_class_keys(filter_context, TRUE))
{
ret = -1;
break;
}
if (!usb_registry_get_all_class_keys(filter_context, TRUE))
{
ret = -1;
break;
}
usb_install_report(filter_context);
}
else
{
USBERR0("unknown filter_mode command\n");
}
}while(FALSE);
Done:
return ret;
}
void __cdecl usb_progress_thread(void* param)
{
install_progress_context_t* context = (install_progress_context_t*)param;
context->ret = usb_install_console(context->filter_context);
PostMessage(context->progress_hwnd, UM_PROGRESS_STOP, (WPARAM)context->ret, 0);
_endthread();
}
bool_t usb_progress_add_text(HWND hwnd, const char* message, COLORREF crNewColor, bool_t bold, bool_t italic)
{
static const char crlf[] = "\r\n";
CHARFORMAT cf;
char* text = (char *)malloc(strlen(message) + sizeof(crlf));
int iTotalTextLength = GetWindowTextLength(hwnd);
if (!text)
{
printf("%s\n", "memory allocation failure");
return FALSE;
}
if (iTotalTextLength > 0)
{
strcpy(text, crlf);
strcpy(&text[strlen(crlf)], message);
}
else
{
strcpy(text, message);
}
// set the selection to the end
SendMessage(hwnd, EM_SETSEL, (WPARAM)(int)iTotalTextLength, (LPARAM)(int)iTotalTextLength);
// set the color
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_COLOR | CFM_UNDERLINE | CFM_BOLD;
cf.dwEffects = (unsigned long)~(CFE_AUTOCOLOR | CFE_UNDERLINE | CFE_BOLD);
cf.crTextColor = crNewColor;
if (bold)
cf.dwEffects |= CFE_BOLD;
if (italic)
cf.dwEffects |= CFE_ITALIC;
SendMessage(hwnd, EM_SETCHARFORMAT, (WPARAM)(UINT)SCF_SELECTION, (LPARAM)&cf);
// set the text
SendMessage(hwnd, EM_REPLACESEL, (WPARAM)(BOOL)FALSE, (LPARAM)(LPCSTR)text);
free(text);
// keep it scrolled to the bottom
SendMessage(hwnd, WM_VSCROLL, (WPARAM)LOWORD(SB_BOTTOM), (LPARAM)0);
return TRUE;
}
bool_t usb_progress_size(HWND hDlg)
{
RECT rect_client, rect_text, rect_bar;
int pad_x = GetSystemMetrics(SM_CXEDGE) * 2;
int pad_y = GetSystemMetrics(SM_CYEDGE) * 2;
GetClientRect(hDlg, &rect_client);
// adjust the bar label
rect_bar = rect_client;
rect_bar.top = rect_bar.bottom - 4;
OffsetRect(&rect_bar, 0, -pad_y);
InflateRect(&rect_bar, -pad_x, 0);
// adjust the textbox
rect_text.top = pad_y;
rect_text.left = pad_x;
rect_text.bottom = rect_bar.top - pad_y;
rect_text.right = rect_client.right - pad_y;
// resize the progress textbox
MOVE_CONTROL(hDlg, IDC_PROGRESS_TEXT, rect_text, TRUE, FALSE);
// resize the bar label
MOVE_CONTROL(hDlg, IDC_PROGRESS_BAR, rect_bar, TRUE, FALSE);
// keep it scrolled to the bottom
SendMessage(GetDlgItem(hDlg, IDC_PROGRESS_TEXT), WM_VSCROLL, (WPARAM)LOWORD(SB_BOTTOM), (LPARAM)0);
// repaint
// InvalidateRect(hDlg, NULL, TRUE);
// PostMessageA(hDlg, WM_PAINT, (WPARAM)NULL, (LPARAM)0);
return TRUE;
}
bool_t usb_progress_init_children(install_progress_context_t* progress_context, HWND hDlg)
{
HWND hWnd;
CHARFORMAT cf;
DWORD style;
style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | ES_MULTILINE | ES_LEFT | ES_READONLY | ES_AUTOVSCROLL | ES_AUTOHSCROLL;
if (progress_context->filter_context->filter_mode == FM_LIST)
{
style |= WS_VSCROLL | WS_HSCROLL;
}
// create rich textbox
hWnd = CreateWindowEx(WS_EX_STATICEDGE, RICHEDIT_CLASS, NULL,
style,
5, 5, 5, 5,
hDlg, (HMENU)((UINT_PTR)IDC_PROGRESS_TEXT),
g_install_progress_context.hInstance, NULL);
memset(&cf, 0 , sizeof(cf));
cf.cbSize = sizeof(cf);
// set rich textbox font and size
cf.dwMask = CFM_FACE | CFM_SIZE;
cf.yHeight = 170;
strcpy(cf.szFaceName, "Tahoma");
SendMessage(hWnd, EM_SETCHARFORMAT, (WPARAM)SCF_ALL, (LPARAM)&cf);
SendMessage(hWnd, EM_SETWORDBREAKPROCEX, (WPARAM)0, (LPARAM)NULL);
SendMessage(hWnd, EM_SETBKGNDCOLOR, (WPARAM)0, (LPARAM)GetSysColor(COLOR_BTNFACE));
// create custom progress bar
hWnd = CreateWindowA("STATIC", NULL,
WS_CHILD | WS_VISIBLE | SS_OWNERDRAW,
5, 5, 5, 5,
hDlg, (HMENU)((UINT_PTR)IDC_PROGRESS_BAR),
g_install_progress_context.hInstance, NULL);
usb_progress_size(hDlg);
return TRUE;
}
LRESULT CALLBACK usb_progress_wndproc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
#define PROGRESS_BLOCK_SIZE 66
CREATESTRUCT* cs;
DRAWITEMSTRUCT* ds;
int wmId, wmEvent;
MINMAXINFO* minmaxinfo;
HWND hwnd;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
if (g_install_progress_context.stopped && wmId == IDCLOSE && wmEvent == BN_CLICKED)
{
PostMessageA(hDlg, UM_PROGRESS_STOP, 0, 0);
}
break;
case WM_CREATE:
cs = (LPCREATESTRUCT)lParam;
g_install_progress_context.progress_hwnd = hDlg;
g_install_progress_context.hInstance = cs->hInstance;
usb_progress_init_children(&g_install_progress_context, hDlg);
center_dialog(GetParent(hDlg), hDlg);
if (InterlockedIncrement(&g_install_progress_context.progress_ind_ofs) == 1)
{
PostMessage(hDlg, UM_PROGRESS_START, 0, 0);
g_install_progress_context.progress_window_ready = TRUE;
// Send a WM_TIMER message every 1/10th second
SetTimer(hDlg, 1, 10, NULL);
}
return (INT_PTR)0;
case WM_TIMER:
InterlockedIncrement(&g_install_progress_context.progress_ind_ofs);
InvalidateRect(GetDlgItem(hDlg, IDC_PROGRESS_BAR), NULL, FALSE);
return (INT_PTR)TRUE;
break;
case UM_PROGRESS_START:
g_install_progress_context.stopped = FALSE;
if (g_install_progress_context.thread_id == 0)
{
// Using a thread prevents application freezout on security warning
if ( (hwnd = GetDlgItem(hDlg, IDOK)) != NULL)
EnableWindow(hwnd, FALSE);
SetWindowTextA(hDlg, DISPLAY_RUNNING);
g_install_progress_context.error_count = 0;
g_install_progress_context.thread_id = _beginthread(usb_progress_thread, 0, &g_install_progress_context);
if (g_install_progress_context.thread_id != -1L)
{
return (INT_PTR)TRUE;
}
}
// Fall through and return an error
wParam = (WPARAM) - 1;
case UM_PROGRESS_STOP:
if (!g_install_progress_context.stopped)
{
g_install_progress_context.stopped = TRUE;
if ( (hwnd = GetDlgItem(hDlg, IDC_PROGRESS_TEXT)) != NULL)
{
if (g_install_progress_context.error_count != 0)
{
usb_progress_add_text(hwnd,"", COLOR_RED, TRUE, FALSE);
usb_progress_add_text(hwnd, "Operation completed with errors!", COLOR_RED, TRUE, FALSE);
}
else
{
usb_progress_add_text(hwnd, "Operation completed successfuly.", GetSysColor(COLOR_BTNTEXT), TRUE, FALSE);
}
}
// enable the close button
SetWindowLongPtr(hDlg, GWL_STYLE, (GetWindowLongPtr(hDlg, GWL_STYLE) | WS_SYSMENU));
// enable ok button
if ( (hwnd = GetDlgItem(hDlg, IDOK)) != NULL)
EnableWindow(hwnd, TRUE);
if (g_install_progress_context.error_count == 0)
{
SetWindowTextA(hDlg, DISPLAY_DONE);
}
else
{
SetWindowTextA(hDlg, DISPLAY_DONE_WITH_ERRORS);
}
if (safe_strlen(g_install_progress_context.filter_context->wait_string))
{
const char* wait_string = g_install_progress_context.filter_context->wait_string;
if (strcmp(install_wait, wait_string) == 0)
{
wait_string = "Click the [X] close button to exit.";
}
usb_progress_add_text(GetDlgItem(hDlg, IDC_PROGRESS_TEXT),
wait_string,
GetSysColor(COLOR_BTNTEXT), TRUE, FALSE);
}
else if (g_install_progress_context.error_count == 0)
{
PostQuitMessage((int)wParam);
DestroyWindow(hDlg);
return (INT_PTR)TRUE;
}
// redraw everything
RedrawWindow(hDlg, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE);
}
else
{
PostQuitMessage((int)wParam);
DestroyWindow(hDlg);
}
return (INT_PTR)TRUE;
case WM_CLOSE:
if (!g_install_progress_context.stopped)
{
// prevent closure using Alt-F4 while running
return (INT_PTR)TRUE;
}
PostQuitMessage((int)wParam);
DestroyWindow(hDlg);
break;
case WM_DESTROY: // close application
g_install_progress_context.progress_window_ready = FALSE;
return (INT_PTR)FALSE;
case WM_SIZE:
if (wParam == SIZE_RESTORED)
{
usb_progress_size(hDlg);
}
break;
case WM_GETMINMAXINFO:
minmaxinfo = (MINMAXINFO*)lParam;
if (minmaxinfo != NULL)
{
// set min extent
minmaxinfo->ptMinTrackSize.x = 320;
minmaxinfo->ptMinTrackSize.y = 140;
// set max extent
minmaxinfo->ptMaxTrackSize.x = 800;
minmaxinfo->ptMaxTrackSize.y = 600;
}
break;
case WM_DRAWITEM:
wmId = (int)wParam;
switch (wmId)
{
case IDC_PROGRESS_BAR:
ds = (DRAWITEMSTRUCT*)lParam;
if ( (ds != NULL) )
{
TRIVERTEX vertex[4] ;
GRADIENT_RECT gRect;
COLORREF clr, clr2;
USHORT r, g, b;
WORD offset_pos;
DWORD offset;
double actual_offset;
HDC hdc;
HBITMAP memBM;
RECT rect;
rect = ds->rcItem;
hdc = CreateCompatibleDC(ds->hDC);
memBM = CreateCompatibleBitmap (ds->hDC, rect.right - rect.left, rect.bottom - rect.top );
SelectObject(hdc, memBM);
DrawEdge(hdc, &rect, EDGE_ETCHED, BF_RECT);
InflateRect(&rect, -1, -1);
if (g_install_progress_context.stopped)
{
if (g_install_progress_context.error_count)
{
HBRUSH hbr_fill = CreateSolidBrush(COLOR_LTRED);
FillRect(hdc, &rect, hbr_fill);
DeleteObject(hbr_fill);
}
else
{
FillRect(hdc, &rect, GetSysColorBrush(COLOR_INACTIVEBORDER));
}
// Copy back buffer into screen device context for display.
BitBlt(ds->hDC, ds->rcItem.left, ds->rcItem.top,
ds->rcItem.right, ds->rcItem.bottom, hdc, 0, 0, SRCCOPY);
DeleteDC(hdc); // Free resources.
DeleteObject(memBM); // Free resources.
return (INT_PTR)TRUE;
}
offset = (DWORD)g_install_progress_context.progress_ind_ofs;
clr = GetSysColor(COLOR_ACTIVECAPTION);
clr2 = GetSysColor(COLOR_WINDOW);
if (offset & 0x40)
offset_pos = (WORD)(((64 - (offset & 63))));
else
offset_pos = (WORD)(offset & 63);
actual_offset = offset_pos;
actual_offset /= 64.0;
offset_pos = (WORD)(actual_offset * rect.right);
RBG_TO_C16(clr2, 0, r, g, b);
TRIVERTEX_FILL(&vertex[0], rect.left, rect.top, r, g, b, 0x0000);
RBG_TO_C16(clr, 0, r, g, b);
TRIVERTEX_FILL(&vertex[1], offset_pos, rect.bottom, r, g, b, 0x0000);
RBG_TO_C16(clr, 0, r, g, b);
TRIVERTEX_FILL(&vertex[2], offset_pos, rect.top, r, g, b, 0x0000);
RBG_TO_C16(clr2, 0, r, g, b);
TRIVERTEX_FILL(&vertex[3], rect.right, rect.bottom, r, g, b, 0x0000);
// Create a GRADIENT_RECT structure that
// references the TRIVERTEX vertices.
gRect.UpperLeft = 0;
gRect.LowerRight = 1;
INIT_GRADIENTFILL();
if (gradient_fill)
{
// Draw a shaded rectangle.
gradient_fill(hdc, &vertex[0], 2, &gRect, 1, GRADIENT_FILL_RECT_H);
gradient_fill(hdc, &vertex[2], 2, &gRect, 1, GRADIENT_FILL_RECT_H);
// Copy back buffer into screen device context for display.
BitBlt(ds->hDC, ds->rcItem.left, ds->rcItem.top, ds->rcItem.right,
ds->rcItem.bottom, hdc, 0, 0, SRCCOPY);
DeleteDC(hdc); // Free resources.
DeleteObject(memBM); // Free resources.
return (INT_PTR)TRUE;
}
else
{
// fallback for no GradientFill api
FillRect(hdc, &rect, GetSysColorBrush(COLOR_ACTIVECAPTION));
DeleteDC(hdc); // Free resources.
DeleteObject(memBM); // Free resources.
return (INT_PTR)TRUE;
}
}
break;
}
break;
}
return DefWindowProc(hDlg, message, wParam, lParam);
}
// initialize progress context
bool_t usb_progress_context_create(install_progress_context_t* install_progress_context,
HINSTANCE hInstance,
filter_context_t* filter_context)
{
memset(install_progress_context, 0, sizeof(*install_progress_context));
install_progress_context->hInstance = hInstance;
install_progress_context->filter_context = filter_context;
return TRUE;
}
// deinitialize progress context
void usb_progress_context_destroy(install_progress_context_t* install_progress_context)
{
memset(install_progress_context, 0, sizeof(*install_progress_context));
}
// run the installer through a progress window
int usb_install_window(HWND hWnd, HINSTANCE instance, filter_context_t* filter_context)
{
MSG msg;
WNDCLASSEX wc;
BOOL bRet;
HWND hDlg;
int ret;
if (!hWnd || !instance)
return -1;
INIT_RICHED32();
if (!usb_progress_context_create(&g_install_progress_context, instance, filter_context))
{
return -1;
}
memset(&wc, 0, sizeof(wc));
// First we create Window class if it doesn't already exist
if (!GetClassInfoExA(instance, "libusbwin32_progress_class", &wc))
{
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_DBLCLKS | CS_SAVEBITS;
wc.lpfnWndProc = usb_progress_wndproc;
wc.cbClsExtra = wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "libusbwin32_progress_class";
wc.lpszMenuName = NULL;
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
if (!RegisterClassExA(&wc))
{
USBERR0("can't register class\n");
usb_progress_context_destroy(&g_install_progress_context);
return -1;
}
}
// Then we create the dialog base
hDlg = CreateWindowExA(WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT,
"libusbwin32_progress_class", DISPLAY_NAME,
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CAPTION | WS_POPUP | WS_THICKFRAME,
100, 100, 320, 140, hWnd, NULL, instance, NULL);
if (hDlg == NULL)
{
USBERR0("Unable to create progress dialog\n");
usb_progress_context_destroy(&g_install_progress_context);
return -1;
}
g_install_progress_context.progress_hwnd = hDlg;
if (GetDesktopWindow() != hWnd)
EnableWindow(hWnd, FALSE); // Start modal (disable main Window)
UpdateWindow(hDlg);
// ...and handle the message processing loop
while( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
//wdi_err("GetMessage error");
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (GetDesktopWindow() != hWnd)
EnableWindow(hWnd, TRUE); // end modal (enable main Window)
ret = g_install_progress_context.ret;
usb_progress_context_destroy(&g_install_progress_context);
return ret;
}
static bool_t usb_install_get_argument(LPWSTR param_value, LPCWSTR* out_param, LPCWSTR* out_value, LPCWSTR* param_names)
{
LPCWSTR param_name;
int param_name_length;
int param_name_pos = 0;
int ret;
if (!param_value || !out_param || !out_value)
return FALSE;
*out_param = 0;
*out_value = 0;
while((param_name = param_names[param_name_pos]))
{
if (!(param_name_length = (int)wcslen(param_name)))
return FALSE;
if (param_name[param_name_length-1] == '=')
{
ret = _wcsnicmp(param_value, param_name, param_name_length);
}
else
{
ret = _wcsicmp(param_value, param_name);
}
if (ret == 0)
{
*out_param = param_names[param_name_pos];
*out_value = param_value + param_name_length;
return TRUE;
}
param_name_pos++;
}
return FALSE;
}
void usb_install_report(filter_context_t* filter_context)
{
filter_class_t* next_class;
filter_device_t* next_device;
next_class = filter_context->class_filters;
while (next_class)
{
if (next_class->class_filter_devices)
{
USBRAWMSG0("\n");
}
USBRAWMSG("%s (%s)\n", next_class->class_guid, next_class->class_name);
if (strlen(next_class->class_uppers))
{
if (usb_registry_mz_to_sz(next_class->class_uppers, ','))
{
USBRAWMSG(" class upper filters:%s\n", next_class->class_uppers);
}
}
if (strlen(next_class->class_lowers))
{
if (usb_registry_mz_to_sz(next_class->class_lowers, ','))
{
USBRAWMSG(" class lower filters:%s\n", next_class->class_lowers);
}
}
next_device = next_class->class_filter_devices;
while(next_device)
{
USBRAWMSG(" %s - %s (%s)\n",
next_device->device_hwid, next_device->device_name, next_device->device_mfg);
USBRAWMSG(" %s\n", next_device->device_id);
if (strlen(next_device->device_uppers))
{
if (usb_registry_mz_to_sz(next_device->device_uppers, ','))
{
USBRAWMSG(" device upper filters:%s\n", next_device->device_uppers);
}
}
if (strlen(next_device->device_lowers))
{
if (usb_registry_mz_to_sz(next_device->device_lowers, ','))
{
USBRAWMSG(" device lower filters:%s\n", next_device->device_lowers);
}
}
next_device = next_device->next;
}
next_class = next_class->next;
}
}
static bool_t usb_install_iswow64(void)
{
HMODULE kernel_dll;
is_wow64_process_t IsWow64Process;
BOOL IsWow64 = FALSE;
kernel_dll = GetModuleHandleA("kernel32.dll");
if (!kernel_dll)
{
USBERR0("loading kernel32.dll failed\n");
return FALSE;
}
IsWow64Process = (is_wow64_process_t) GetProcAddress(kernel_dll, "IsWow64Process");
if (IsWow64Process)
{
if (!IsWow64Process(GetCurrentProcess(), &IsWow64))
{
// handle error
IsWow64 = FALSE;
}
}
return IsWow64;
}
static BOOL usb_install_admin_check(void)
/*++
Routine Description: This routine returns TRUE if the caller's
process is a member of the Administrators local group. Caller is NOT
expected to be impersonating anyone and is expected to be able to
open its own process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group. --
*/
{
BOOL b;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
PSID AdministratorsGroup;
GET_WINDOWS_VERSION;
if (windows_version <= WINDOWS_XP)
{
return TRUE;
}
b = AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&AdministratorsGroup);
if(b)
{
if (!CheckTokenMembership( NULL, AdministratorsGroup, &b))
{
b = FALSE;
}
FreeSid(AdministratorsGroup);
}
return(b);
}
void usage(void)
{
#define ID_HELP_TEXT 10020
#define ID_DOS_TEXT 300
CONST CHAR* src;
DWORD src_count, charsWritten;
HGLOBAL res_data;
HANDLE handle;
HRSRC hSrc;
if ((handle = GetStdHandle(STD_ERROR_HANDLE)) == INVALID_HANDLE_VALUE)
return;
hSrc = FindResourceA(NULL, MAKEINTRESOURCEA(ID_HELP_TEXT), MAKEINTRESOURCEA(ID_DOS_TEXT));
if (!hSrc) return;
src_count = SizeofResource(NULL, hSrc);
res_data = LoadResource(NULL, hSrc);
if (!res_data) return;
src = (char*) LockResource(res_data);
if (!src) return;
WriteConsoleA(handle, src, src_count, &charsWritten, NULL);
}