From 38f48203af08d5a7b1253ff7951059b54b4ec9a8 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Thu, 26 Jul 2018 15:33:20 +0100 Subject: [PATCH] fix Zadig HTTPS download and file selection issues --- examples/wdi-simple.rc | 8 +- examples/zadic.rc | 8 +- examples/zadig.c | 282 ++++++++++++------------ examples/zadig.h | 41 +++- examples/zadig.rc | 8 +- examples/zadig_README.creole | 2 +- examples/zadig_net.c | 127 +++++++---- examples/zadig_stdlg.c | 310 +++++++++++++++++--------- libwdi/libwdi.c | 8 +- libwdi/libwdi.rc | 8 +- libwdi/msapi_utf8.h | 412 ++++++++++++++++++++++++++++++++++- 11 files changed, 891 insertions(+), 323 deletions(-) diff --git a/examples/wdi-simple.rc b/examples/wdi-simple.rc index e245fa54..f2aed546 100644 --- a/examples/wdi-simple.rc +++ b/examples/wdi-simple.rc @@ -7,8 +7,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,719,0 - PRODUCTVERSION 1,3,719,0 + FILEVERSION 1,3,720,0 + PRODUCTVERSION 1,3,720,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -25,13 +25,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "WDI-Simple" - VALUE "FileVersion", "1.3.719" + VALUE "FileVersion", "1.3.720" VALUE "InternalName", "WDI-Simple" VALUE "LegalCopyright", "© 2010-2018 Pete Batard (LGPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/lesser.html" VALUE "OriginalFilename", "wdi-simple.exe" VALUE "ProductName", "WDI-Simple" - VALUE "ProductVersion", "1.3.719" + VALUE "ProductVersion", "1.3.720" VALUE "Comments", "http://libwdi.akeo.ie" END END diff --git a/examples/zadic.rc b/examples/zadic.rc index 679a6eb1..f5a2911e 100644 --- a/examples/zadic.rc +++ b/examples/zadic.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,719,0 - PRODUCTVERSION 1,3,719,0 + FILEVERSION 1,3,720,0 + PRODUCTVERSION 1,3,720,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,13 +74,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Zadic" - VALUE "FileVersion", "1.3.719" + VALUE "FileVersion", "1.3.720" VALUE "InternalName", "Zadic" VALUE "LegalCopyright", "© 2010-2018 Pete Batard (LGPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/lesser.html" VALUE "OriginalFilename", "zadic.exe" VALUE "ProductName", "Zadic" - VALUE "ProductVersion", "1.3.719" + VALUE "ProductVersion", "1.3.720" VALUE "Comments", "http://libwdi.akeo.ie" END END diff --git a/examples/zadig.c b/examples/zadig.c index d590b1fc..8e4d3a60 100644 --- a/examples/zadig.c +++ b/examples/zadig.c @@ -61,7 +61,7 @@ BOOL parse_ini(void); OPENED_LIBRARIES_VARS; HINSTANCE main_instance; HWND hDeviceList; -HWND hMain; +HWND hMainDialog; HWND hInfo; HWND hStatus; HWND hVIDToolTip = NULL, hArrowToolTip = NULL; @@ -80,7 +80,7 @@ COLORREF arrow_color = ARROW_GREEN; float fScale = 1.0f; WORD application_version[4]; char app_dir[MAX_PATH], driver_text[64]; -char extraction_path[MAX_PATH]; +char szFolderPath[MAX_PATH]; const char* driver_display_name[WDI_NB_DRIVERS] = { "WinUSB", "libusb-win32", "libusbK", "USB Serial (CDC)", "Custom (extract only)" }; const char* driver_name[WDI_NB_DRIVERS-1] = { "WinUSB", "libusb0", "libusbK", "usbser" }; struct wdi_options_create_list cl_options = { 0 }; @@ -109,6 +109,8 @@ BOOL exit_on_success = FALSE; enum wcid_state has_wcid = WCID_NONE; int wcid_type = WDI_USER; UINT64 target_driver_version = 0; +EXT_DECL(log_ext, "Zadig.log", __VA_GROUP__("*.log"), __VA_GROUP__("Zadig log")); +EXT_DECL(cfg_ext, "sample.cfg", __VA_GROUP__("*.cfg"), __VA_GROUP__("Zadig device config")); /* * On screen logging and status @@ -137,7 +139,7 @@ void w_printf_v(BOOL update_status, const char *format, va_list args) Edit_SetSel(hInfo, MAX_LOG_SIZE, MAX_LOG_SIZE); Edit_ReplaceSelU(hInfo, str); if (update_status) { - SetDlgItemTextU(hMain, IDC_STATUS, str); + SetDlgItemTextU(hMainDialog, IDC_STATUS, str); } } @@ -160,8 +162,8 @@ static void CALLBACK PrintStatusTimeout(HWND hwnd, UINT uMsg, UINT_PTR idEvent, { bStatusTimerArmed = FALSE; // potentially display lower priority message that was overridden - SetDlgItemTextU(hMain, IDC_STATUS, szStatusMessage); - KillTimer(hMain, TID_MESSAGE); + SetDlgItemTextU(hMainDialog, IDC_STATUS, szStatusMessage); + KillTimer(hMainDialog, TID_MESSAGE); } void print_status(unsigned int duration, BOOL debug, const char* message) @@ -173,11 +175,11 @@ void print_status(unsigned int duration, BOOL debug, const char* message) dprintf("%s\n", szStatusMessage); if ((duration) || (!bStatusTimerArmed)) { - SetDlgItemTextU(hMain, IDC_STATUS, szStatusMessage); + SetDlgItemTextU(hMainDialog, IDC_STATUS, szStatusMessage); } if (duration) { - SetTimer(hMain, TID_MESSAGE, duration, PrintStatusTimeout); + SetTimer(hMainDialog, TID_MESSAGE, duration, PrintStatusTimeout); bStatusTimerArmed = TRUE; } } @@ -257,7 +259,7 @@ void __cdecl notification_delay_thread(void* param) { DWORD delay = (DWORD)(uintptr_t)param; Sleep(delay); - PostMessage(hMain, UM_DEVICE_EVENT, 0, 0); + PostMessage(hMainDialog, UM_DEVICE_EVENT, 0, 0); _endthread(); } @@ -323,24 +325,24 @@ int install_driver(void) safe_sprintf(dev->desc, 128, "%s Generic Device", driver_display_name[pd_options.driver_type]); } else { // Retrieve the various device parameters - if (ComboBox_GetTextU(GetDlgItem(hMain, IDC_DEVICEEDIT), str_buf, STR_BUFFER_SIZE) == 0) { + if (ComboBox_GetTextU(GetDlgItem(hMainDialog, IDC_DEVICEEDIT), str_buf, STR_BUFFER_SIZE) == 0) { notification(MSG_ERROR, NULL, "Driver Installation", "The description string cannot be empty."); r = WDI_ERROR_INVALID_PARAM; goto out; } dev->desc = safe_strdup(str_buf); - GetDlgItemTextA(hMain, IDC_VID, str_buf, STR_BUFFER_SIZE); + GetDlgItemTextA(hMainDialog, IDC_VID, str_buf, STR_BUFFER_SIZE); if (sscanf(str_buf, "%4x", &tmp) != 1) { dprintf("could not convert VID string - aborting"); r = WDI_ERROR_INVALID_PARAM; goto out; } dev->vid = (unsigned short)tmp; - GetDlgItemTextA(hMain, IDC_PID, str_buf, STR_BUFFER_SIZE); + GetDlgItemTextA(hMainDialog, IDC_PID, str_buf, STR_BUFFER_SIZE); if (sscanf(str_buf, "%4x", &tmp) != 1) { dprintf("could not convert PID string - aborting"); r = WDI_ERROR_INVALID_PARAM; goto out; } dev->pid = (unsigned short)tmp; - GetDlgItemTextA(hMain, IDC_MI, str_buf, STR_BUFFER_SIZE); + GetDlgItemTextA(hMainDialog, IDC_MI, str_buf, STR_BUFFER_SIZE); if ( (safe_strlen(str_buf) != 0) && (sscanf(str_buf, "%2x", &tmp) == 1) ) { dev->is_composite = TRUE; @@ -364,7 +366,7 @@ int install_driver(void) // Perform extraction/installation if (id_options.install_filter_driver) { - if ((!has_filter_driver) && (MessageBoxA(hMain, "WARNING:\n" + if ((!has_filter_driver) && (MessageBoxA(hMainDialog, "WARNING:\n" "Improper use of the filter driver can cause devices to malfunction\n" "and, in some cases, complete system failure.\n\n" "THE AUTHOR(S) OF THIS SOFTWARE ACCEPT NO LIABILITY FOR\n" @@ -374,26 +376,26 @@ int install_driver(void) r = WDI_ERROR_USER_CANCEL; goto out; } } - r = wdi_prepare_driver(dev, extraction_path, inf_name, &pd_options); + r = wdi_prepare_driver(dev, szFolderPath, inf_name, &pd_options); if (r == WDI_SUCCESS) { dsprintf("Successfully extracted driver files."); // Perform the install if not extracting the files only if ((pd_options.driver_type != WDI_USER) && (!extract_only)) { if ( (get_driver_type(dev) == DT_SYSTEM) - && (MessageBoxA(hMain, "You are about to modify a system driver.\n" + && (MessageBoxA(hMainDialog, "You are about to modify a system driver.\n" "Are you sure this is what you want?", "Warning - System Driver", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDNO) ) { r = WDI_ERROR_USER_CANCEL; goto out; } dsprintf("Installing driver. Please wait..."); - id_options.hWnd = hMain; - r = wdi_install_driver(dev, extraction_path, inf_name, &id_options); + id_options.hWnd = hMainDialog; + r = wdi_install_driver(dev, szFolderPath, inf_name, &id_options); // Switch to non driverless-only mode and set hw ID to show the newly installed device current_device_hardware_id = (dev != NULL)?safe_strdup(dev->hardware_id):NULL; if ((r == WDI_SUCCESS) && (!cl_options.list_all) && (!pd_options.use_wcid_driver)) { toggle_driverless(FALSE); } - PostMessage(hMain, WM_DEVICECHANGE, 0, 0); // Force a refresh + PostMessage(hMainDialog, WM_DEVICECHANGE, 0, 0); // Force a refresh } } else { dsprintf("Could not extract files"); @@ -417,11 +419,11 @@ int install_driver(void) void combo_breaker(BOOL edit) { if (edit) { - ShowWindow(GetDlgItem(hMain, IDC_DEVICELIST), SW_HIDE); - ShowWindow(GetDlgItem(hMain, IDC_DEVICEEDIT), SW_SHOW); + ShowWindow(GetDlgItem(hMainDialog, IDC_DEVICELIST), SW_HIDE); + ShowWindow(GetDlgItem(hMainDialog, IDC_DEVICEEDIT), SW_SHOW); } else { - ShowWindow(GetDlgItem(hMain, IDC_DEVICEEDIT), SW_HIDE); - ShowWindow(GetDlgItem(hMain, IDC_DEVICELIST), SW_SHOW); + ShowWindow(GetDlgItem(hMainDialog, IDC_DEVICEEDIT), SW_HIDE); + ShowWindow(GetDlgItem(hMainDialog, IDC_DEVICELIST), SW_SHOW); } } @@ -437,7 +439,7 @@ void set_filter_menu(BOOL display) // Find if a filter driver is in use has_filter_driver = (device != NULL) && (safe_stricmp(driver_name[WDI_LIBUSB0], device->upper_filter) == 0); - ShowWindow(GetDlgItem(hMain, IDC_FILTER_ICON), has_filter_driver?TRUE:FALSE); + ShowWindow(GetDlgItem(hMainDialog, IDC_FILTER_ICON), has_filter_driver?TRUE:FALSE); mi_filter.dwTypeData = itemddesc[has_filter_driver?1:0]; mi_filter.cch = (UINT)strlen(itemddesc[has_filter_driver?1:0]); @@ -472,7 +474,7 @@ void set_default_driver(void) { if (i==WDI_NB_DRIVERS) { notification(MSG_ERROR, NULL, "No Driver Available", "No driver is available for installation with this application.\n" "The application will close"); - EndDialog(hMain, 0); + EndDialog(hMainDialog, 0); } dprintf("falling back to '%s' for default driver", driver_display_name[default_driver_type]); } else { @@ -505,7 +507,7 @@ void set_driver(void) safe_sprintf(target_text, 64, "%s", driver_display_name[pd_options.driver_type]); } } - SetDlgItemTextA(hMain, IDC_TARGET, target_text); + SetDlgItemTextA(hMainDialog, IDC_TARGET, target_text); } @@ -539,14 +541,14 @@ void display_mi(BOOL show) POINT point, origin; if (show == mi_shown) return; - ShowWindow(GetDlgItem(hMain, IDC_MI), cmd); + ShowWindow(GetDlgItem(hMainDialog, IDC_MI), cmd); // Move the VID report button if MI is not shown - GetWindowRect(GetDlgItem(hMain, IDC_VID_REPORT), &rect); + GetWindowRect(GetDlgItem(hMainDialog, IDC_VID_REPORT), &rect); origin.x = rect.left; origin.y = rect.top; - ScreenToClient(hMain, &origin); + ScreenToClient(hMainDialog, &origin); point.x = (rect.right - rect.left); point.y = (rect.bottom - rect.top); - MoveWindow(GetDlgItem(hMain, IDC_VID_REPORT), origin.x - (show?-report_shift:+report_shift), + MoveWindow(GetDlgItem(hMainDialog, IDC_VID_REPORT), origin.x - (show?-report_shift:+report_shift), origin.y, point.x, point.y, TRUE); mi_shown = show; } @@ -568,36 +570,36 @@ void toggle_advanced(void) advanced_mode = !(GetMenuState(hMenuOptions, IDM_ADVANCEDMODE, MF_CHECKED) & MF_CHECKED); // Increase or decrease the Install button size - GetWindowRect(GetDlgItem(hMain, IDC_INSTALL), &rect); + GetWindowRect(GetDlgItem(hMainDialog, IDC_INSTALL), &rect); origin.x = rect.left; origin.y = rect.top; - ScreenToClient(hMain, &origin); + ScreenToClient(hMainDialog, &origin); point.x = (rect.right - rect.left); point.y = (rect.bottom - rect.top); - MoveWindow(GetDlgItem(hMain, IDC_INSTALL), origin.x, origin.y, + MoveWindow(GetDlgItem(hMainDialog, IDC_INSTALL), origin.x, origin.y, point.x + (int)(fScale*(advanced_mode?-install_widen:+install_widen)), point.y, TRUE); // Increase or decrease the Window size - GetWindowRect(hMain, &rect); + GetWindowRect(hMainDialog, &rect); point.x = (rect.right - rect.left); point.y = (rect.bottom - rect.top); - MoveWindow(hMain, rect.left, rect.top, point.x, + MoveWindow(hMainDialog, rect.left, rect.top, point.x, point.y + (int)(fScale*(advanced_mode?dialog_shift:-dialog_shift)), TRUE); // Move the status bar up or down GetWindowRect(hStatus, &rect); point.x = rect.left; point.y = rect.top; - ScreenToClient(hMain, &point); + ScreenToClient(hMainDialog, &point); GetClientRect(hStatus, &rect); MoveWindow(hStatus, point.x, point.y + (int)(fScale*(advanced_mode?dialog_shift:-dialog_shift)), (rect.right - rect.left), (rect.bottom - rect.top), TRUE); // Hide or show the various advanced options toggle = advanced_mode?SW_SHOW:SW_HIDE; - ShowWindow(GetDlgItem(hMain, IDC_BROWSE), toggle); - ShowWindow(GetDlgItem(hMain, IDC_GROUPLOG), toggle); - ShowWindow(GetDlgItem(hMain, IDC_INFO), toggle); + ShowWindow(GetDlgItem(hMainDialog, IDC_BROWSE), toggle); + ShowWindow(GetDlgItem(hMainDialog, IDC_GROUPLOG), toggle); + ShowWindow(GetDlgItem(hMainDialog, IDC_INFO), toggle); // Toggle the menu checkmark CheckMenuItem(hMenuOptions, IDM_ADVANCEDMODE, advanced_mode?MF_CHECKED:MF_UNCHECKED); @@ -606,7 +608,7 @@ void toggle_advanced(void) // Toggle edit description void toggle_edit(void) { - if ((IsDlgButtonChecked(hMain, IDC_EDITNAME) == BST_CHECKED) && (device != NULL)) { + if ((IsDlgButtonChecked(hMainDialog, IDC_EDITNAME) == BST_CHECKED) && (device != NULL)) { combo_breaker(TRUE); if (editable_desc != NULL) { dprintf("program assertion failed - editable_desc != NULL"); @@ -615,15 +617,15 @@ void toggle_edit(void) editable_desc = (char*)malloc(STR_BUFFER_SIZE); if (editable_desc == NULL) { dprintf("could not allocate buffer to edit description"); - CheckDlgButton(hMain, IDC_EDITNAME, BST_UNCHECKED); + CheckDlgButton(hMainDialog, IDC_EDITNAME, BST_UNCHECKED); combo_breaker(FALSE); return; } safe_strcpy(editable_desc, STR_BUFFER_SIZE, device->desc); free(device->desc); // No longer needed device->desc = editable_desc; - SetDlgItemTextU(hMain, IDC_DEVICEEDIT, editable_desc); - SetFocus(GetDlgItem(hMain, IDC_DEVICEEDIT)); + SetDlgItemTextU(hMainDialog, IDC_DEVICEEDIT, editable_desc); + SetFocus(GetDlgItem(hMainDialog, IDC_DEVICEEDIT)); } else { combo_breaker(FALSE); display_devices(); @@ -639,16 +641,16 @@ void update_ui(void) switch (has_wcid) { case WCID_TRUE: - ShowWindow(GetDlgItem(hMain, IDC_WCID), TRUE); - SendMessage(GetDlgItem(hMain, IDC_WCID_ICON), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIconTickOK); + ShowWindow(GetDlgItem(hMainDialog, IDC_WCID), TRUE); + SendMessage(GetDlgItem(hMainDialog, IDC_WCID_ICON), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIconTickOK); break; case WCID_FALSE: - ShowWindow(GetDlgItem(hMain, IDC_WCID), FALSE); - SendMessage(GetDlgItem(hMain, IDC_WCID_ICON), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIconTickNOK); + ShowWindow(GetDlgItem(hMainDialog, IDC_WCID), FALSE); + SendMessage(GetDlgItem(hMainDialog, IDC_WCID_ICON), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIconTickNOK); break; case WCID_NONE: - ShowWindow(GetDlgItem(hMain, IDC_WCID), FALSE); - SendMessage(GetDlgItem(hMain, IDC_WCID_ICON), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)NULL); + ShowWindow(GetDlgItem(hMainDialog, IDC_WCID), FALSE); + SendMessage(GetDlgItem(hMainDialog, IDC_WCID_ICON), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)NULL); break; } @@ -681,34 +683,34 @@ void toggle_create(BOOL refresh) if (create_device) { device = NULL; // Disable Edit Desc. if selected - if (IsDlgButtonChecked(hMain, IDC_EDITNAME) == BST_CHECKED) { - CheckDlgButton(hMain, IDC_EDITNAME, BST_UNCHECKED); + if (IsDlgButtonChecked(hMainDialog, IDC_EDITNAME) == BST_CHECKED) { + CheckDlgButton(hMainDialog, IDC_EDITNAME, BST_UNCHECKED); toggle_edit(); } combo_breaker(TRUE); has_wcid = WCID_NONE; update_ui(); - EnableWindow(GetDlgItem(hMain, IDC_EDITNAME), FALSE); - SetDlgItemTextA(hMain, IDC_VID, ""); - SetDlgItemTextA(hMain, IDC_PID, ""); - SetDlgItemTextA(hMain, IDC_MI, ""); - SetDlgItemTextA(hMain, IDC_DRIVER, ""); - SetDlgItemTextA(hMain, IDC_DEVICEEDIT, ""); - PostMessage(GetDlgItem(hMain, IDC_VID), EM_SETREADONLY, (WPARAM)FALSE, 0); - PostMessage(GetDlgItem(hMain, IDC_PID), EM_SETREADONLY, (WPARAM)FALSE, 0); - PostMessage(GetDlgItem(hMain, IDC_MI), EM_SETREADONLY, (WPARAM)FALSE, 0); + EnableWindow(GetDlgItem(hMainDialog, IDC_EDITNAME), FALSE); + SetDlgItemTextA(hMainDialog, IDC_VID, ""); + SetDlgItemTextA(hMainDialog, IDC_PID, ""); + SetDlgItemTextA(hMainDialog, IDC_MI, ""); + SetDlgItemTextA(hMainDialog, IDC_DRIVER, ""); + SetDlgItemTextA(hMainDialog, IDC_DEVICEEDIT, ""); + PostMessage(GetDlgItem(hMainDialog, IDC_VID), EM_SETREADONLY, (WPARAM)FALSE, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_PID), EM_SETREADONLY, (WPARAM)FALSE, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_MI), EM_SETREADONLY, (WPARAM)FALSE, 0); destroy_tooltip(hVIDToolTip); hVIDToolTip = NULL; unknown_vid = FALSE; display_mi(TRUE); - SetFocus(GetDlgItem(hMain, IDC_DEVICEEDIT)); + SetFocus(GetDlgItem(hMainDialog, IDC_DEVICEEDIT)); } else { combo_breaker(FALSE); - PostMessage(GetDlgItem(hMain, IDC_VID), EM_SETREADONLY, (WPARAM)TRUE, 0); - PostMessage(GetDlgItem(hMain, IDC_PID), EM_SETREADONLY, (WPARAM)TRUE, 0); - PostMessage(GetDlgItem(hMain, IDC_MI), EM_SETREADONLY, (WPARAM)TRUE, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_VID), EM_SETREADONLY, (WPARAM)TRUE, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_PID), EM_SETREADONLY, (WPARAM)TRUE, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_MI), EM_SETREADONLY, (WPARAM)TRUE, 0); if (refresh) { - PostMessage(hMain, UM_REFRESH_LIST, 0, 0); + PostMessage(hMainDialog, UM_REFRESH_LIST, 0, 0); } } CheckMenuItem(hMenuDevice, IDM_CREATE, create_device?MF_CHECKED:MF_UNCHECKED); @@ -728,11 +730,11 @@ void toggle_hubs(BOOL refresh) CheckMenuItem(hMenuOptions, IDM_IGNOREHUBS, cl_options.list_hubs?MF_UNCHECKED:MF_CHECKED); // Reset Edit button - CheckDlgButton(hMain, IDC_EDITNAME, BST_UNCHECKED); + CheckDlgButton(hMainDialog, IDC_EDITNAME, BST_UNCHECKED); // Reset Combo combo_breaker(FALSE); if (refresh) { - PostMessage(hMain, UM_REFRESH_LIST, 0, 0); + PostMessage(hMainDialog, UM_REFRESH_LIST, 0, 0); } } @@ -748,11 +750,11 @@ void toggle_driverless(BOOL refresh) CheckMenuItem(hMenuOptions, IDM_LISTALL, cl_options.list_all?MF_CHECKED:MF_UNCHECKED); // Reset Edit button - CheckDlgButton(hMain, IDC_EDITNAME, BST_UNCHECKED); + CheckDlgButton(hMainDialog, IDC_EDITNAME, BST_UNCHECKED); // Reset Combo combo_breaker(FALSE); if (refresh) { - PostMessage(hMain, UM_REFRESH_LIST, 0, 0); + PostMessage(hMainDialog, UM_REFRESH_LIST, 0, 0); } } @@ -795,7 +797,7 @@ void set_install_button(void) } qualifier = pd_options.use_wcid_driver?"WCID ":(id_options.install_filter_driver?"Filter ":""); safe_sprintf(label, 64, "%s %s%s", action, qualifier, object); - SetDlgItemTextA(hMain, IDC_INSTALL, label); + SetDlgItemTextA(hMainDialog, IDC_INSTALL, label); } // Change the log level @@ -825,10 +827,10 @@ void init_dialog(HWND hDlg) } bi = {0}; // BUTTON_IMAGELIST // Quite a burden to carry around as parameters - hMain = hDlg; + hMainDialog = hDlg; hDeviceList = GetDlgItem(hDlg, IDC_DEVICELIST); hInfo = GetDlgItem(hDlg, IDC_INFO); - hArrow = GetDlgItem(hMain, IDC_RARR); + hArrow = GetDlgItem(hMainDialog, IDC_RARR); hMenuDevice = GetSubMenu(GetMenu(hDlg), 0); hMenuOptions = GetSubMenu(GetMenu(hDlg), 1); hMenuLogLevel = GetSubMenu(hMenuOptions, 7); @@ -856,35 +858,35 @@ void init_dialog(HWND hDlg) SendMessageA(GetDlgItem(hDlg, IDC_STATUS), SB_SETTEXTA, SBT_OWNERDRAW | 1, (LPARAM)APP_VERSION); // Create various tooltips - create_tooltip(GetDlgItem(hMain, IDC_EDITNAME), + create_tooltip(GetDlgItem(hMainDialog, IDC_EDITNAME), "Change the device name", -1); - create_tooltip(GetDlgItem(hMain, IDC_VIDPID), + create_tooltip(GetDlgItem(hMainDialog, IDC_VIDPID), "VID:PID[:MI]", -1); - create_tooltip(GetDlgItem(hMain, IDC_DRIVER), + create_tooltip(GetDlgItem(hMainDialog, IDC_DRIVER), "Current Driver", -1); - create_tooltip(GetDlgItem(hMain, IDC_TARGET), + create_tooltip(GetDlgItem(hMainDialog, IDC_TARGET), "Target Driver", -1); - create_tooltip(GetDlgItem(hMain, IDC_STATIC_WCID), + create_tooltip(GetDlgItem(hMainDialog, IDC_STATIC_WCID), "Windows Compatible ID\nClick '?' for more info.", -1); - create_tooltip(GetDlgItem(hMain, IDC_WCID_BOX), + create_tooltip(GetDlgItem(hMainDialog, IDC_WCID_BOX), "Windows Compatible ID\nClick '?' for more info.", -1); - create_tooltip(GetDlgItem(hMain, IDC_WCID_ICON), + create_tooltip(GetDlgItem(hMainDialog, IDC_WCID_ICON), "Windows Compatible ID\nClick '?' for more info.", -1); - create_tooltip(GetDlgItem(hMain, IDC_BROWSE), + create_tooltip(GetDlgItem(hMainDialog, IDC_BROWSE), "Directory to extract/install files to", -1); - create_tooltip(GetDlgItem(hMain, IDC_WCID_URL), + create_tooltip(GetDlgItem(hMainDialog, IDC_WCID_URL), "Online information about WCID", -1); - create_tooltip(GetDlgItem(hMain, IDC_VID_REPORT), + create_tooltip(GetDlgItem(hMainDialog, IDC_VID_REPORT), "Submit Vendor to the USB ID Repository", -1); - create_tooltip(GetDlgItem(hMain, IDC_FILTER_ICON), + create_tooltip(GetDlgItem(hMainDialog, IDC_FILTER_ICON), "This device also has the\nlibusb-win32 filter driver", -1); - create_tooltip(GetDlgItem(hMain, IDC_LIBUSB_URL), + create_tooltip(GetDlgItem(hMainDialog, IDC_LIBUSB_URL), "Find out more about libusb online", -1); - create_tooltip(GetDlgItem(hMain, IDC_LIBUSB0_URL), + create_tooltip(GetDlgItem(hMainDialog, IDC_LIBUSB0_URL), "Find out more about libusb-win32 online", -1); - create_tooltip(GetDlgItem(hMain, IDC_LIBUSBK_URL), + create_tooltip(GetDlgItem(hMainDialog, IDC_LIBUSBK_URL), "Find out more about libusbK online", -1); - create_tooltip(GetDlgItem(hMain, IDC_WINUSB_URL), + create_tooltip(GetDlgItem(hMainDialog, IDC_WINUSB_URL), "Find out more about WinUSB online", -1); // Load system icons for various items (NB: Use the excellent http://www.nirsoft.net/utils/iconsext.html to find icon IDs) @@ -925,13 +927,13 @@ void init_dialog(HWND hDlg) GetWindowRect(hArrow, &rect); arrow_origin.x = rect.left; arrow_origin.y = rect.top; arrow_width = rect.right - rect.left; arrow_height = i24; - ScreenToClient(hMain, &arrow_origin); + ScreenToClient(hMainDialog, &arrow_origin); arrow_origin.x += 1; // Some fixup is needed DestroyWindow(hArrow); // We need SS_CENTERIMAGE to be able to increase the control height by two and achieve pixel positioning hArrow = CreateWindowExA(0, "STATIC", NULL, SS_ICON | SS_NOTIFY | SS_CENTERIMAGE | SS_REALSIZEIMAGE | WS_GROUP | WS_CHILD | WS_VISIBLE, - arrow_origin.x, arrow_origin.y, arrow_width, arrow_height, hMain, NULL, main_instance, NULL); + arrow_origin.x, arrow_origin.y, arrow_width, arrow_height, hMainDialog, NULL, main_instance, NULL); SendMessage(hArrow, STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIconArrowGreen); } while (0); if (!use_arrow_icons) { @@ -962,7 +964,7 @@ void init_dialog(HWND hDlg) CheckMenuItem(hMenuOptions, IDM_ADVANCEDMODE, MF_CHECKED); // Setup logging - err = wdi_register_logger(hMain, UM_LOGGER_EVENT, 0); + err = wdi_register_logger(hMainDialog, UM_LOGGER_EVENT, 0); if (err != WDI_SUCCESS) { dprintf("Unable to access log output - logging will be disabled (%s)", wdi_strerror(err)); } @@ -973,9 +975,9 @@ void init_dialog(HWND hDlg) dprintf(WindowsVersionStr); // Limit the input size of VID, PID, MI - PostMessage(GetDlgItem(hMain, IDC_VID), EM_SETLIMITTEXT, 4, 0); - PostMessage(GetDlgItem(hMain, IDC_PID), EM_SETLIMITTEXT, 4, 0); - PostMessage(GetDlgItem(hMain, IDC_MI), EM_SETLIMITTEXT, 2, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_VID), EM_SETLIMITTEXT, 4, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_PID), EM_SETLIMITTEXT, 4, 0); + PostMessage(GetDlgItem(hMainDialog, IDC_MI), EM_SETLIMITTEXT, 2, 0); // Parse the ini file and set the startup options accordingly parse_ini(); @@ -1035,14 +1037,14 @@ BOOL parse_ini(void) { // Set the default extraction dir if ((profile_get_string(profile, "driver", "default_dir", NULL, NULL, &tmp) == 0) && (tmp != NULL)) { - safe_strcpy(extraction_path, sizeof(extraction_path), tmp); + safe_strcpy(szFolderPath, sizeof(szFolderPath), tmp); } // Set the certificate name to install, if any if ( (profile_get_string(profile, "security", "install_cert", NULL, NULL, &tmp) == 0) && (tmp != NULL) ) { if (wdi_is_file_embedded(NULL, (char*)tmp)) { - ic_options.hWnd = hMain; + ic_options.hWnd = hMainDialog; wdi_install_trusted_certificate((char*)tmp, &ic_options); } else { dprintf("certificate '%s' not found in this application", tmp); @@ -1094,23 +1096,23 @@ BOOL parse_preset(char* filename) } safe_sprintf(str_tmp, 5, "%04X", tmp); - SetDlgItemTextA(hMain, IDC_VID, str_tmp); + SetDlgItemTextA(hMainDialog, IDC_VID, str_tmp); profile_get_string(profile, "device", "Description", NULL, NULL, &desc); if (desc != NULL) { - SetDlgItemTextU(hMain, IDC_DEVICEEDIT, (char*)desc); + SetDlgItemTextU(hMainDialog, IDC_DEVICEEDIT, (char*)desc); } profile_get_uint(profile, "device", "PID", NULL, 0x10000, &tmp); if (tmp <= 0xFFFF) { safe_sprintf(str_tmp, 5, "%04X", tmp); - SetDlgItemTextA(hMain, IDC_PID, str_tmp); + SetDlgItemTextA(hMainDialog, IDC_PID, str_tmp); } profile_get_uint(profile, "device", "MI", NULL, 0x100, &tmp); if (tmp <= 0xFF) { safe_sprintf(str_tmp, 5, "%02X", tmp); - SetDlgItemTextA(hMain, IDC_MI, str_tmp); + SetDlgItemTextA(hMainDialog, IDC_MI, str_tmp); } profile_get_string(profile, "device", "GUID", NULL, NULL, &pd_options.device_guid); @@ -1236,7 +1238,7 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP NOT_DURING_INSTALL; notification_delay_thid = -1L; if (create_device) { - if (MessageBoxA(hMain, "The USB device list has been modified.\n" + if (MessageBoxA(hMainDialog, "The USB device list has been modified.\n" "Do you want to refresh the application?\n(you will lose all your modifications)", "USB Event Notification", MB_YESNO | MB_ICONINFORMATION) == IDYES) { if (create_device) { @@ -1244,10 +1246,10 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP } CheckMenuItem(hMenuDevice, IDM_CREATE, MF_UNCHECKED); combo_breaker(FALSE); - PostMessage(hMain, UM_REFRESH_LIST, 0, 0); + PostMessage(hMainDialog, UM_REFRESH_LIST, 0, 0); } } else { - PostMessage(hMain, UM_REFRESH_LIST, 0, 0); + PostMessage(hMainDialog, UM_REFRESH_LIST, 0, 0); } return (INT_PTR)TRUE; @@ -1300,9 +1302,9 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP case UM_REFRESH_LIST: NOT_DURING_INSTALL; // Reset edit mode if selected - if (IsDlgButtonChecked(hMain, IDC_EDITNAME) == BST_CHECKED) { + if (IsDlgButtonChecked(hMainDialog, IDC_EDITNAME) == BST_CHECKED) { combo_breaker(FALSE); - CheckDlgButton(hMain, IDC_EDITNAME, BST_UNCHECKED); + CheckDlgButton(hMainDialog, IDC_EDITNAME, BST_UNCHECKED); } id_options.install_filter_driver = FALSE; if (list != NULL) wdi_destroy_list(list); @@ -1315,16 +1317,16 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP if (r == WDI_SUCCESS) { nb_devices = display_devices(); // Send a dropdown selection message to update fields - PostMessage(hMain, WM_COMMAND, MAKELONG(IDC_DEVICELIST, CBN_SELCHANGE), + PostMessage(hMainDialog, WM_COMMAND, MAKELONG(IDC_DEVICELIST, CBN_SELCHANGE), (LPARAM)hDeviceList); } else { nb_devices = -1; _IGNORE(ComboBox_ResetContent(hDeviceList)); - SetDlgItemTextA(hMain, IDC_VID, ""); - SetDlgItemTextA(hMain, IDC_PID, ""); - SetDlgItemTextA(hMain, IDC_DRIVER, ""); + SetDlgItemTextA(hMainDialog, IDC_VID, ""); + SetDlgItemTextA(hMainDialog, IDC_PID, ""); + SetDlgItemTextA(hMainDialog, IDC_DRIVER, ""); display_mi(FALSE); - EnableWindow(GetDlgItem(hMain, IDC_EDITNAME), FALSE); + EnableWindow(GetDlgItem(hMainDialog, IDC_EDITNAME), FALSE); has_wcid = WCID_NONE; pd_options.use_wcid_driver = TRUE; update_ui(); @@ -1380,28 +1382,28 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP SetTextColor((HDC)wParam, arrow_color); return (INT_PTR)CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); } - if ( (hCtrl == GetDlgItem(hMain, IDC_LIBUSB0_URL)) - || (hCtrl == GetDlgItem(hMain, IDC_LIBUSB_URL)) - || (hCtrl == GetDlgItem(hMain, IDC_LIBUSBK_URL)) - || (hCtrl == GetDlgItem(hMain, IDC_WINUSB_URL)) - || (hCtrl == GetDlgItem(hMain, IDC_WCID_URL)) ) { + if ( (hCtrl == GetDlgItem(hMainDialog, IDC_LIBUSB0_URL)) + || (hCtrl == GetDlgItem(hMainDialog, IDC_LIBUSB_URL)) + || (hCtrl == GetDlgItem(hMainDialog, IDC_LIBUSBK_URL)) + || (hCtrl == GetDlgItem(hMainDialog, IDC_WINUSB_URL)) + || (hCtrl == GetDlgItem(hMainDialog, IDC_WCID_URL)) ) { create_static_fonts((HDC)wParam); SelectObject((HDC)wParam, hyperlink_font); SetTextColor((HDC)wParam, DARK_BLUE); return (INT_PTR)GetStockObject(NULL_BRUSH); } - if (hCtrl == GetDlgItem(hMain, IDC_LINKS)) { + if (hCtrl == GetDlgItem(hMainDialog, IDC_LINKS)) { create_static_fonts((HDC)wParam); SelectObject((HDC)wParam, bold_font); SetTextColor((HDC)wParam, GetSysColor(COLOR_3DDKSHADOW)); return (INT_PTR)GetStockObject(NULL_BRUSH); } - if (hCtrl == GetDlgItem(hMain, IDC_WCID_ICON)) { + if (hCtrl == GetDlgItem(hMainDialog, IDC_WCID_ICON)) { // Ensures that the WCID background field is not drawn on top of the WCID icon - SendMessage(GetDlgItem(hMain, IDC_WCID_BOX), (WPARAM)WM_SETREDRAW, TRUE, 0); - InvalidateRect(GetDlgItem(hMain, IDC_WCID_BOX), NULL, TRUE); - UpdateWindow(GetDlgItem(hMain, IDC_WCID_BOX)); - SendMessage(GetDlgItem(hMain, IDC_WCID_BOX), (WPARAM)WM_SETREDRAW, FALSE, 0); + SendMessage(GetDlgItem(hMainDialog, IDC_WCID_BOX), (WPARAM)WM_SETREDRAW, TRUE, 0); + InvalidateRect(GetDlgItem(hMainDialog, IDC_WCID_BOX), NULL, TRUE); + UpdateWindow(GetDlgItem(hMainDialog, IDC_WCID_BOX)); + SendMessage(GetDlgItem(hMainDialog, IDC_WCID_BOX), (WPARAM)WM_SETREDRAW, FALSE, 0); } // Restore transparency if we don't change the background SetBkMode((HDC)wParam, OPAQUE); @@ -1430,7 +1432,7 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP pt.x = pDropDown->rcButton.left; pt.y = pDropDown->rcButton.bottom; ClientToScreen(pDropDown->hdr.hwndFrom, &pt); - TrackPopupMenuEx(hMenuSplit, TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y, hMain, NULL); + TrackPopupMenuEx(hMenuSplit, TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y, hMainDialog, NULL); break; } break; @@ -1463,7 +1465,7 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP case IDC_DEVICEEDIT: // edit: device description switch (HIWORD(wParam)) { case EN_CHANGE: - GetDlgItemTextU(hMain, IDC_DEVICEEDIT, editable_desc, STR_BUFFER_SIZE); + GetDlgItemTextU(hMainDialog, IDC_DEVICEEDIT, editable_desc, STR_BUFFER_SIZE); break; default: return (INT_PTR)FALSE; @@ -1498,10 +1500,10 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP } else { safe_strcpy(driver_text, sizeof(driver_text), "(NONE)"); } - SetDlgItemTextU(hMain, IDC_DRIVER, driver_text); + SetDlgItemTextU(hMainDialog, IDC_DRIVER, driver_text); // Display the VID,PID,MI safe_sprintf(str_tmp, 5, "%04X", device->vid); - SetDlgItemTextA(hMain, IDC_VID, str_tmp); + SetDlgItemTextA(hMainDialog, IDC_VID, str_tmp); // Display the vendor string as a tooltip destroy_tooltip(hVIDToolTip); vid_string = wdi_get_vendor_name(device->vid); @@ -1511,13 +1513,13 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP "the name of this vendor, please consider submitting it to " "the USB ID Repository, by clicking the button on the right."; }; - hVIDToolTip = create_tooltip(GetDlgItem(hMain, IDC_VID), (char*)vid_string, unknown_vid?20000:-1); - ShowWindow(GetDlgItem(hMain, IDC_VID_REPORT), unknown_vid?SW_SHOW:SW_HIDE); + hVIDToolTip = create_tooltip(GetDlgItem(hMainDialog, IDC_VID), (char*)vid_string, unknown_vid?20000:-1); + ShowWindow(GetDlgItem(hMainDialog, IDC_VID_REPORT), unknown_vid?SW_SHOW:SW_HIDE); safe_sprintf(str_tmp, 5, "%04X", device->pid); - SetDlgItemTextA(hMain, IDC_PID, str_tmp); + SetDlgItemTextA(hMainDialog, IDC_PID, str_tmp); if (device->is_composite) { safe_sprintf(str_tmp, 5, "%02X", device->mi); - SetDlgItemTextA(hMain, IDC_MI, str_tmp); + SetDlgItemTextA(hMainDialog, IDC_MI, str_tmp); display_mi(TRUE); } else { display_mi(FALSE); @@ -1526,7 +1528,7 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP pd_options.use_wcid_driver = (safe_strncmp(device->compatible_id, ms_comp_hdr, safe_strlen(ms_comp_hdr)) == 0); has_wcid = (pd_options.use_wcid_driver)?WCID_TRUE:WCID_FALSE; if (has_wcid == WCID_TRUE) { - SetDlgItemTextA(hMain, IDC_WCID, device->compatible_id + safe_strlen(ms_comp_hdr)); + SetDlgItemTextA(hMainDialog, IDC_WCID, device->compatible_id + safe_strlen(ms_comp_hdr)); // Select the driver according to the WCID (will be set to WDI_USER = unsupported if no match) for (wcid_type=WDI_WINUSB; wcid_typecompatible_id + safe_strlen(ms_comp_hdr), driver_name[wcid_type]) == 0) { @@ -1546,7 +1548,7 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP } } } - EnableWindow(GetDlgItem(hMain, IDC_EDITNAME), TRUE); + EnableWindow(GetDlgItem(hMainDialog, IDC_EDITNAME), TRUE); } else { has_wcid = WCID_NONE; } @@ -1570,7 +1572,7 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP notification(MSG_INFO, NULL, "Driver Installation", "The driver was installed successfully."); } if (exit_on_success) - PostMessage(hMain, WM_CLOSE, 0, 0); + PostMessage(hMainDialog, WM_CLOSE, 0, 0); } else if (r == WDI_ERROR_USER_CANCEL) { dsprintf("Driver Installation: Cancelled by User"); notification(MSG_WARNING, NULL, "Driver Installation", "Driver installation cancelled by user."); @@ -1580,8 +1582,8 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP } break; case IDC_BROWSE: // button: "Browse..." - browse_for_folder(); - dprintf("Using '%s' as extraction directory.", extraction_path); + BrowseForFolder(); + dprintf("Using '%s' as extraction directory.", szFolderPath); break; case IDC_CLEAR: // button: "Clear Log" SetWindowTextA(hInfo, ""); @@ -1592,14 +1594,14 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP break; log_buffer = (char*)malloc(log_size); if (log_buffer != NULL) { - log_size = GetDlgItemTextU(hMain, IDC_INFO, log_buffer, log_size); + log_size = GetDlgItemTextU(hMainDialog, IDC_INFO, log_buffer, log_size); if (log_size == 0) { dprintf("unable to read log text"); } else { log_size--; // remove NULL terminator - filepath = file_dialog(TRUE, app_dir, "zadig.log", "log", "Zadig log"); + filepath = FileDialog(TRUE, app_dir, &log_ext, 0); if (filepath != NULL) { - file_io(TRUE, filepath, &log_buffer, &log_size); + FileIo(TRUE, filepath, &log_buffer, &log_size); } safe_free(filepath); } @@ -1610,7 +1612,7 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP break; case IDC_WCID_BOX: // prevent focus if (HIWORD(wParam) == EN_SETFOCUS) { - SetFocus(hMain); + SetFocus(hMainDialog); return (INT_PTR)TRUE; } break; @@ -1624,14 +1626,14 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP toggle_create(TRUE); break; case IDM_OPEN: - filepath = file_dialog(FALSE, app_dir, "sample.cfg", "cfg", "Zadig device config"); + filepath = FileDialog(FALSE, app_dir, &cfg_ext, 0); parse_preset(filepath); break; case IDM_ABOUT: - DialogBoxW(main_instance, MAKEINTRESOURCEW(IDD_ABOUTBOX), hMain, about_callback); + DialogBoxW(main_instance, MAKEINTRESOURCEW(IDD_ABOUTBOX), hMainDialog, about_callback); break; case IDM_UPDATES: - DialogBoxW(main_instance, MAKEINTRESOURCEW(IDD_UPDATE_POLICY), hMain, UpdateCallback); + DialogBoxW(main_instance, MAKEINTRESOURCEW(IDD_UPDATE_POLICY), hMainDialog, UpdateCallback); break; case IDM_CERTMGR: memset(&si, 0, sizeof(si)); @@ -1766,7 +1768,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine // Retrieve the current application directory and set the extraction directory from the user's GetCurrentDirectoryU(MAX_PATH, app_dir); tmp = getenvU("USERPROFILE"); - safe_sprintf(extraction_path, sizeof(extraction_path), "%s\\usb_driver", tmp); + safe_sprintf(szFolderPath, sizeof(szFolderPath), "%s\\usb_driver", tmp); safe_free(tmp); // Create the main Window diff --git a/examples/zadig.h b/examples/zadig.h index 32855b5b..d252ef3f 100644 --- a/examples/zadig.h +++ b/examples/zadig.h @@ -59,7 +59,7 @@ #define FIELD_ORANGE RGB(255,240,200) #define ARROW_GREEN RGB(92,228,65) #define ARROW_ORANGE RGB(253,143,56) -#define APP_VERSION "Zadig 2.4.719" +#define APP_VERSION "Zadig 2.4.720" // These are used to flag end users about the driver they are going to replace enum driver_type { @@ -110,11 +110,35 @@ typedef struct { char* release_notes; } APPLICATION_UPDATE; +/* + * Structure and macros used for the extensions specification of FileDialog() + * You can use: + * EXT_DECL(my_extensions, "default.std", __VA_GROUP__("*.std", "*.other"), __VA_GROUP__("Standard type", "Other Type")); + * to define an 'ext_t my_extensions' variable initialized with the relevant attributes. + */ +typedef struct ext_t { + const size_t count; + const char* filename; + const char** extension; + const char** description; +} ext_t; + +#ifndef __VA_GROUP__ +#define __VA_GROUP__(...) __VA_ARGS__ +#endif +#define EXT_X(prefix, ...) const char* _##prefix##_x[] = { __VA_ARGS__ } +#define EXT_D(prefix, ...) const char* _##prefix##_d[] = { __VA_ARGS__ } +#define EXT_DECL(var, filename, extensions, descriptions) \ + EXT_X(var, extensions); \ + EXT_D(var, descriptions); \ + ext_t var = { ARRAYSIZE(_##var##_x), filename, _##var##_x, _##var##_d } + #define safe_free(p) do {if ((void*)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 static_strcpy(dst, src) safe_strcpy(dst, sizeof(dst), src) #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)?"":str1), ((str2==NULL)?"":str2)) @@ -122,6 +146,7 @@ typedef struct { #define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2), count) #define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0) #define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0) +#define static_sprintf(dst, ...) safe_sprintf(dst, sizeof(dst), __VA_ARGS__) #define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str)) #define safe_strdup _strdup #define MF_CHECK(cond) ((cond)?MF_CHECKED:MF_UNCHECKED) @@ -143,9 +168,9 @@ typedef struct { void print_status(unsigned int duration, BOOL debug, const char* message); int detect_windows_version(void); void w_printf(BOOL update_status, const char *format, ...); -void browse_for_folder(void); -char* file_dialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc); -BOOL file_io(BOOL save, char* path, char** buffer, DWORD* size); +void BrowseForFolder(void); +char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options); +BOOL FileIo(BOOL save, char* path, char** buffer, DWORD* size); INT_PTR CALLBACK about_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); void create_status_bar(void); @@ -160,7 +185,7 @@ void set_title_bar_icon(HWND hDlg); const char *WindowsErrorString(void); void download_new_version(void); void parse_update(char* buf, size_t len); -BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog); +DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog); HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog); BOOL SetUpdateCheck(void); BOOL CheckForUpdates(BOOL force); @@ -170,12 +195,12 @@ BOOL CheckForUpdates(BOOL force); */ extern HINSTANCE main_instance; extern HWND hDeviceList; -extern HWND hMain; +extern HWND hMainDialog; extern HWND hInfo; extern HWND hStatus; extern WORD application_version[4]; -extern DWORD download_error; -extern char extraction_path[MAX_PATH], app_dir[MAX_PATH]; +extern DWORD error_code; +extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH]; extern int dialog_showing; extern BOOL installation_running; extern APPLICATION_UPDATE update; diff --git a/examples/zadig.rc b/examples/zadig.rc index 6ef07732..f7778b53 100644 --- a/examples/zadig.rc +++ b/examples/zadig.rc @@ -246,8 +246,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,4,719,0 - PRODUCTVERSION 2,4,719,0 + FILEVERSION 2,4,720,0 + PRODUCTVERSION 2,4,720,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -264,13 +264,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Zadig" - VALUE "FileVersion", "2.4.719" + VALUE "FileVersion", "2.4.720" VALUE "InternalName", "Zadig" VALUE "LegalCopyright", "© 2010-2018 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "zadig.exe" VALUE "ProductName", "Zadig" - VALUE "ProductVersion", "2.4.719" + VALUE "ProductVersion", "2.4.720" VALUE "Comments", "http://libwdi.akeo.ie" END END diff --git a/examples/zadig_README.creole b/examples/zadig_README.creole index 0bd071c5..917973ec 100644 --- a/examples/zadig_README.creole +++ b/examples/zadig_README.creole @@ -1,5 +1,5 @@ === v2.4 (2018.07.26) === -* Update URLs +* Fix HTTPS download and update URLs * Improve error reporting * Fix Windows 7 showing a "Trusted Publisher" dialog * Embedded drivers: WinUSB v6.1.7600.16385, libusb-win32 v1.2.6.0, libusbK v3.0.7.0 & usbser (native) diff --git a/examples/zadig_net.c b/examples/zadig_net.c index 2b3ca9a1..0b6cb80a 100644 --- a/examples/zadig_net.c +++ b/examples/zadig_net.c @@ -41,12 +41,12 @@ /* Default delay between update checks (1 day) */ #define DEFAULT_UPDATE_INTERVAL (24*3600) -BOOL force_update; -DWORD download_error; +DWORD error_code; APPLICATION_UPDATE update = { {0,0,0,0}, {0,0}, NULL, NULL }; -static BOOL update_check_in_progress = FALSE; +static BOOL force_update = FALSE; static BOOL force_update_check = FALSE; +static BOOL update_check_in_progress = FALSE; /* MinGW is missing some of those */ #if !defined(ERROR_INTERNET_DISCONNECTED) @@ -79,12 +79,12 @@ static BOOL force_update_check = FALSE; /* * FormatMessage does not handle internet errors - * http://support.microsoft.com/kb/193625 + * https://docs.microsoft.com/en-us/windows/desktop/wininet/wininet-errors */ const char* WinInetErrorString(void) { static char error_string[256]; - DWORD error_code, size = sizeof(error_string); + DWORD size = sizeof(error_string); error_code = HRESULT_CODE(GetLastError()); @@ -123,7 +123,7 @@ const char* WinInetErrorString(void) case ERROR_INTERNET_INVALID_OPERATION: return "The requested operation is invalid."; case ERROR_INTERNET_OPERATION_CANCELLED: - return "The operation was canceled, usually because the handle on which the request was operating was closed before the operation completed."; + return "The operation was cancelled, usually because the handle on which the request was operating was closed before the operation completed."; case ERROR_INTERNET_INCORRECT_HANDLE_TYPE: return "The type of handle supplied is incorrect for this operation."; case ERROR_INTERNET_INCORRECT_HANDLE_STATE: @@ -158,10 +158,18 @@ const char* WinInetErrorString(void) return "The request to the proxy was invalid."; case ERROR_INTERNET_HANDLE_EXISTS: return "The request failed because the handle already exists."; + case ERROR_INTERNET_SEC_INVALID_CERT: + return "The SSL certificate is invalid."; case ERROR_INTERNET_SEC_CERT_DATE_INVALID: return "SSL certificate date that was received from the server is bad. The certificate is expired."; case ERROR_INTERNET_SEC_CERT_CN_INVALID: return "SSL certificate common name (host name field) is incorrect."; + case ERROR_INTERNET_SEC_CERT_ERRORS: + return "The SSL certificate contains errors."; + case ERROR_INTERNET_SEC_CERT_NO_REV: + return "The SSL certificate was not revoked."; + case ERROR_INTERNET_SEC_CERT_REV_FAILED: + return "The revocation check of the SSL certificate failed."; case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR: return "The application is moving from a non-SSL to an SSL connection because of a redirect."; case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR: @@ -230,7 +238,7 @@ const char* WinInetErrorString(void) InternetGetLastResponseInfoA(&error_code, error_string, &size); return error_string; default: - safe_sprintf(error_string, sizeof(error_string), "Unknown internet error 0x%08lX", error_code); + static_sprintf(error_string, "Unknown internet error 0x%08lX", error_code); return error_string; } } @@ -242,21 +250,24 @@ const char* WinInetErrorString(void) * to the dialog in question, with WPARAM being set to nonzero for EXIT on success * and also attempt to indicate progress using an IDC_PROGRESS control */ -BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) +DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog) { HWND hProgressBar = NULL; BOOL r = FALSE; - DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; - FILE* fd = NULL; LONG progress_style; + DWORD dwFlags, dwSize, dwWritten, dwDownloaded, dwTotalSize; + DWORD DownloadStatus; + HANDLE hFile = INVALID_HANDLE_VALUE; + const char* accept_types[] = {"*/*\0", NULL}; unsigned char buf[DOWNLOAD_BUFFER_SIZE]; - char agent[64], hostname[64], urlpath[128]; + char agent[64], hostname[64], urlpath[128], msg[MAX_PATH]; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; + size_t last_slash; int i; - char msg[MAX_PATH]; + DownloadStatus = 404; if (hProgressDialog != NULL) { // Use the progress control provided, if any hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS); @@ -268,13 +279,23 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) SendMessage(hProgressDialog, UM_DOWNLOAD_INIT, 0, 0); } + if (file == NULL) + goto out; + + for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) { + if ((file[last_slash] == '/') || (file[last_slash] == '\\')) { + last_slash++; + break; + } + } + safe_sprintf(msg, sizeof(msg), "Downloading %s: Connecting...", file); print_status(0, FALSE, msg); dprintf("Downloading %s from %s\n", file, url); if ( (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { - dprintf("Unable to decode URL: %s\n", WindowsErrorString()); + dprintf("Unable to decode URL: %s\n", WinInetErrorString()); goto out; } hostname[sizeof(hostname)-1] = 0; @@ -289,12 +310,12 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) dprintf("Network is unavailable: %s\n", WinInetErrorString()); goto out; } - safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", + static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", application_version[0], application_version[1], application_version[2], - nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : ""); + nWindowsVersion>>4, nWindowsVersion&0x0F, is_x64()?"; WOW64":""); hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (hSession == NULL) { - dprintf("Could not open internet session: %s\n", WinInetErrorString()); + dprintf("Could not open Internet session: %s\n", WinInetErrorString()); goto out; } @@ -304,11 +325,12 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) goto out; } - hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, (const char**)"*/*\0", - INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES| - INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL); + hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS| + INTERNET_FLAG_NO_COOKIES|INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_HYPERLINK| + ((UrlParts.nScheme==INTERNET_SCHEME_HTTPS)?INTERNET_FLAG_SECURE:0), (DWORD_PTR)NULL); if (hRequest == NULL) { - dprintf("Could not open url %s: %s\n", url, WindowsErrorString()); + dprintf("Could not open URL %s: %s\n", url, WinInetErrorString()); goto out; } @@ -318,12 +340,11 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) } // Get the file size - dwSize = sizeof(dwStatus); - dwStatus = 404; - HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL); - if (dwStatus != 200) { - download_error = ERROR_SEVERITY_ERROR|ERROR_INTERNET_ITEM_NOT_FOUND; - dprintf("Unable to access file: Server status %d\n", dwStatus); + dwSize = sizeof(DownloadStatus); + HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); + if (DownloadStatus != 200) { + error_code = ERROR_SEVERITY_ERROR|ERROR_INTERNET_ITEM_NOT_FOUND; + dprintf("Unable to access file: %d\n", DownloadStatus); goto out; } dwSize = sizeof(dwTotalSize); @@ -333,16 +354,16 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) } dprintf("File length: %d bytes\n", dwTotalSize); - fd = fopenU(file, "wb"); - if (fd == NULL) { - dprintf("Unable to create file '%s': %s\n", file, WinInetErrorString()); + hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + dprintf("Unable to create file '%s': %s\n", &file[last_slash], WinInetErrorString()); goto out; } // Keep checking for data until there is nothing left. dwSize = 0; while (1) { - if (download_error) + if (IS_ERROR(error_code)) goto out; if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0)) @@ -351,36 +372,47 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0); safe_sprintf(msg, sizeof(msg), "Downloading: %0.1f%%", (100.0f*dwSize)/(1.0f*dwTotalSize)); print_status(0, FALSE, msg); - if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) { - dprintf("Error writing file '%s': %s\n", file, WinInetErrorString()); + if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) { + dprintf("Error writing file '%s': %s\n", &file[last_slash], WinInetErrorString()); + goto out; + } else if (dwDownloaded != dwWritten) { + dprintf("Error writing file '%s': Only %d/%d bytes written\n", dwWritten, dwDownloaded); goto out; } } if (dwSize != dwTotalSize) { dprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize); - download_error = ERROR_WRITE_FAULT; + error_code = ERROR_SEVERITY_ERROR|ERROR_WRITE_FAULT; goto out; } else { r = TRUE; - dprintf("Successfully downloaded '%s'\n", file); + dprintf("Successfully downloaded '%s'\n", &file[last_slash]); } out: if (hProgressDialog != NULL) SendMessage(hProgressDialog, UM_DOWNLOAD_EXIT, (WPARAM)r, 0); - if (fd != NULL) fclose(fd); + if (hFile != INVALID_HANDLE_VALUE) { + // Force a flush - May help with the PKI API trying to process downloaded updates too early... + FlushFileBuffers(hFile); + CloseHandle(hFile); + } if (!r) { - _unlink(file); + if (file != NULL) + _unlinkU(file); print_status(0, FALSE, "Failed to download file."); - SetLastError(download_error); - MessageBoxU(hMain, WinInetErrorString(), "File download", MB_OK|MB_ICONERROR); + SetLastError(error_code); + MessageBoxU(hMainDialog, WinInetErrorString(), "File download", MB_OK|MB_ICONERROR); } - if (hRequest) InternetCloseHandle(hRequest); - if (hConnection) InternetCloseHandle(hConnection); - if (hSession) InternetCloseHandle(hSession); - - return r; + if (hRequest) + InternetCloseHandle(hRequest); + if (hConnection) + InternetCloseHandle(hConnection); + if (hSession) + InternetCloseHandle(hSession); + + return r?dwSize:0; } /* Threaded download */ @@ -432,6 +464,8 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) update_check_in_progress = TRUE; verbose = ReadRegistryKey32(REGKEY_HKCU, REGKEY_VERBOSE_UPDATES); + // Without this the FileDialog will produce error 0x8001010E when compiled for Vista or later + IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); // Unless the update was forced, wait a while before performing the update check if (!force_update_check) { // TODO: Also check on inactivity @@ -514,8 +548,9 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) for (i=0; ilpVtbl->SetOptions(pfod, FOS_PICKFOLDERS); if (FAILED(hr)) { dprintf("Failed to set folder option for FileOpenDialog: error %X", hr); - goto out; + goto fallback; } // Set the initial folder (if the path is invalid, will simply use last) - wpath = utf8_to_wchar(extraction_path); + wpath = utf8_to_wchar(szFolderPath); // The new IFileOpenDialog makes us split the path fname = NULL; if ((wpath != NULL) && (wcslen(wpath) >= 1)) { - for (i=wcslen(wpath)-1; i!=0; i--) { + for (i = wcslen(wpath) - 1; i != 0; i--) { if (wpath[i] == L'\\') { wpath[i] = 0; - fname = &wpath[i+1]; + fname = &wpath[i + 1]; break; } } @@ -311,7 +321,7 @@ void browse_for_folder(void) { } safe_free(wpath); - hr = pfod->lpVtbl->Show(pfod, hMain); + hr = pfod->lpVtbl->Show(pfod, hMainDialog); if (SUCCEEDED(hr)) { hr = pfod->lpVtbl->GetResult(pfod, &psi); if (SUCCEEDED(hr)) { @@ -321,7 +331,7 @@ void browse_for_folder(void) { if (tmp_path == NULL) { dprintf("Could not convert path"); } else { - safe_strcpy(extraction_path, MAX_PATH, tmp_path); + static_strcpy(szFolderPath, tmp_path); safe_free(tmp_path); } } else { @@ -329,11 +339,28 @@ void browse_for_folder(void) { } } else if ((hr & 0xFFFF) != ERROR_CANCELLED) { // If it's not a user cancel, assume the dialog didn't show and fallback - dprintf("could not show FileOpenDialog: error %X", hr); + dprintf("Could not show FileOpenDialog: error %X", hr); + goto fallback; } -out: - if ((pfod != NULL) && (pfod->lpVtbl != NULL)) + pfod->lpVtbl->Release(pfod); + dialog_showing--; + return; +fallback: + if (pfod != NULL) { pfod->lpVtbl->Release(pfod); + } + + memset(&bi, 0, sizeof(BROWSEINFOW)); + bi.hwndOwner = hMainDialog; + bi.lpszTitle = L"Please select folder"; + bi.lpfn = BrowseInfoCallback; + // BIF_NONEWFOLDERBUTTON = 0x00000200 is unknown on MinGW + bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS | + BIF_DONTGOBELOWDOMAIN | BIF_EDITBOX | 0x00000200; + pidl = SHBrowseForFolderW(&bi); + if (pidl != NULL) { + CoTaskMemFree(pidl); + } dialog_showing--; } @@ -341,7 +368,7 @@ void browse_for_folder(void) { * read or write I/O to a file * buffer is allocated by the procedure. path is UTF-8 */ -BOOL file_io(BOOL save, char* path, char** buffer, DWORD* size) +BOOL FileIo(BOOL save, char* path, char** buffer, DWORD* size) { SECURITY_ATTRIBUTES s_attr, *ps = NULL; SECURITY_DESCRIPTOR s_desc; @@ -351,7 +378,7 @@ BOOL file_io(BOOL save, char* path, char** buffer, DWORD* size) BOOL ret = FALSE; // Change the owner from admin to regular user - sid = get_sid(); + sid = GetSid(); if ( (sid != NULL) && InitializeSecurityDescriptor(&s_desc, SECURITY_DESCRIPTOR_REVISION) && SetSecurityDescriptorOwner(&s_desc, sid, FALSE) ) { @@ -407,84 +434,165 @@ BOOL file_io(BOOL save, char* path, char** buffer, DWORD* size) } /* - * Return the UTF8 path of a file selected through a load or save dialog - * using the newer IFileOpenDialog. All string parameters are UTF-8. - */ -char* file_dialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc) +* Return the UTF8 path of a file selected through a load or save dialog +* All string parameters are UTF-8 +* IMPORTANT NOTE: Remember that you need to call CoInitializeEx() for +* *EACH* thread you invoke FileDialog from, as GetDisplayName() will +* return error 0x8001010E otherwise. +*/ +char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options) { - char *ext_filter, *filepath = NULL; - wchar_t *wpath = NULL, *wfilename = NULL; + DWORD tmp; + OPENFILENAMEA ofn; + char selected_name[MAX_PATH]; + char *ext_string = NULL, *all_files = NULL; + size_t i, j, ext_strlen; + BOOL r; + char* filepath = NULL; HRESULT hr = FALSE; IFileDialog *pfd = NULL; IShellItem *psiResult; - COMDLG_FILTERSPEC filter_spec[2]; + COMDLG_FILTERSPEC* filter_spec = NULL; + wchar_t *wpath = NULL, *wfilename = NULL; IShellItem *si_path = NULL; // Automatically freed + if ((ext == NULL) || (ext->count == 0) || (ext->extension == NULL) || (ext->description == NULL)) + return NULL; dialog_showing++; - // Setup the file extension filter table - ext_filter = (char*)malloc(strlen(ext)+3); - if (ext_filter != NULL) { - safe_sprintf(ext_filter, strlen(ext)+3, "*.%s", ext); - filter_spec[0].pszSpec = utf8_to_wchar(ext_filter); - safe_free(ext_filter); - filter_spec[0].pszName = utf8_to_wchar(ext_desc); - filter_spec[1].pszSpec = L"*.*"; - filter_spec[1].pszName = L"All files"; - } - hr = CoCreateInstance(save?&CLSID_FileSaveDialog:&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, - &IID_IFileDialog, (LPVOID)&pfd); + filter_spec = (COMDLG_FILTERSPEC*)calloc(ext->count + 1, sizeof(COMDLG_FILTERSPEC)); + if (filter_spec != NULL) { + // Setup the file extension filter table + for (i = 0; i < ext->count; i++) { + filter_spec[i].pszSpec = utf8_to_wchar(ext->extension[i]); + filter_spec[i].pszName = utf8_to_wchar(ext->description[i]); + } + filter_spec[i].pszSpec = L"*.*"; + filter_spec[i].pszName = L"All files"; - if (FAILED(hr)) { - dprintf("CoCreateInstance for FileOpenDialog failed: error %X", hr); - pfd = NULL; // Just in case - goto out; - } + hr = CoCreateInstance(save ? &CLSID_FileSaveDialog : &CLSID_FileOpenDialog, NULL, CLSCTX_INPROC, + &IID_IFileDialog, (LPVOID)&pfd); - // Set the file extension filters - pfd->lpVtbl->SetFileTypes(pfd, 2, filter_spec); + if (FAILED(hr)) { + SetLastError(hr); + dprintf("CoCreateInstance for FileOpenDialog failed: %s\n", WindowsErrorString()); + pfd = NULL; // Just in case + goto fallback; + } - // Set the default directory - wpath = utf8_to_wchar(path); - hr = SHCreateItemFromParsingName(wpath, NULL, &IID_IShellItem, (LPVOID) &si_path); - if (SUCCEEDED(hr)) { - pfd->lpVtbl->SetFolder(pfd, si_path); - } - safe_free(wpath); + // Set the file extension filters + pfd->lpVtbl->SetFileTypes(pfd, (UINT)ext->count + 1, filter_spec); - // Set the default filename - wfilename = utf8_to_wchar(filename); - if (wfilename != NULL) { - pfd->lpVtbl->SetFileName(pfd, wfilename); - } + // Set the default directory + wpath = utf8_to_wchar(path); + hr = SHCreateItemFromParsingName(wpath, NULL, &IID_IShellItem, (LPVOID)&si_path); + if (SUCCEEDED(hr)) { + pfd->lpVtbl->SetFolder(pfd, si_path); + } + safe_free(wpath); + + // Set the default filename + wfilename = utf8_to_wchar((ext->filename == NULL) ? "" : ext->filename); + if (wfilename != NULL) { + pfd->lpVtbl->SetFileName(pfd, wfilename); + } - // Display the dialog - hr = pfd->lpVtbl->Show(pfd, hMain); + // Display the dialog + hr = pfd->lpVtbl->Show(pfd, hMainDialog); - // Cleanup - safe_free(wfilename); - safe_free(filter_spec[0].pszSpec); - safe_free(filter_spec[0].pszName); + // Cleanup + safe_free(wfilename); + for (i = 0; i < ext->count; i++) { + safe_free(filter_spec[i].pszSpec); + safe_free(filter_spec[i].pszName); + } + safe_free(filter_spec); - if (SUCCEEDED(hr)) { - // Obtain the result of the user's interaction with the dialog. - hr = pfd->lpVtbl->GetResult(pfd, &psiResult); if (SUCCEEDED(hr)) { - hr = psiResult->lpVtbl->GetDisplayName(psiResult, SIGDN_FILESYSPATH, &wpath); + // Obtain the result of the user's interaction with the dialog. + hr = pfd->lpVtbl->GetResult(pfd, &psiResult); if (SUCCEEDED(hr)) { - filepath = wchar_to_utf8(wpath); - CoTaskMemFree(wpath); + hr = psiResult->lpVtbl->GetDisplayName(psiResult, SIGDN_FILESYSPATH, &wpath); + if (SUCCEEDED(hr)) { + filepath = wchar_to_utf8(wpath); + CoTaskMemFree(wpath); + } else { + SetLastError(hr); + dprintf("Unable to access file path: %s\n", WindowsErrorString()); + } + psiResult->lpVtbl->Release(psiResult); } - psiResult->lpVtbl->Release(psiResult); + } else if ((hr & 0xFFFF) != ERROR_CANCELLED) { + // If it's not a user cancel, assume the dialog didn't show and fallback + SetLastError(hr); + dprintf("Could not show FileOpenDialog: %s\n", WindowsErrorString()); + goto fallback; } - } else if ((hr & 0xFFFF) != ERROR_CANCELLED) { - // If it's not a user cancel, assume the dialog didn't show and fallback - dprintf("could not show FileOpenDialog: error %X", hr); + pfd->lpVtbl->Release(pfd); + dialog_showing--; + return filepath; } -out: - if ((pfd != NULL) && (pfd->lpVtbl != NULL)) +fallback: + safe_free(filter_spec); + if (pfd != NULL) { pfd->lpVtbl->Release(pfd); + } + + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hMainDialog; + // Selected File name + static_sprintf(selected_name, "%s", (ext->filename == NULL) ? "" : ext->filename); + ofn.lpstrFile = selected_name; + ofn.nMaxFile = MAX_PATH; + // Set the file extension filters + all_files = "All files"; + ext_strlen = 0; + for (i = 0; icount; i++) { + ext_strlen += safe_strlen(ext->description[i]) + 2 * safe_strlen(ext->extension[i]) + sizeof(" ()\r\r"); + } + ext_strlen += safe_strlen(all_files) + sizeof(" (*.*)\r*.*\r"); + ext_string = (char*)malloc(ext_strlen + 1); + if (ext_string == NULL) + return NULL; + ext_string[0] = 0; + for (i = 0, j = 0; icount; i++) { + j += _snprintf(&ext_string[j], ext_strlen - j, "%s (%s)\r%s\r", ext->description[i], ext->extension[i], ext->extension[i]); + } + j = _snprintf(&ext_string[j], ext_strlen - j, "%s (*.*)\r*.*\r", all_files); + // Microsoft could really have picked a better delimiter! + for (i = 0; i0)&&(update.download_url[i]!='/'); i--); - filepath = file_dialog(TRUE, app_dir, (char*)&update.download_url[i+1], "exe", "Application"); + exe_ext.filename = PathFindFileNameU(update.download_url); + filepath = FileDialog(TRUE, app_dir, &exe_ext, OFN_NOCHANGEDIR); if (filepath == NULL) { print_status(0, TRUE, "Could not get save path\n"); break; @@ -1115,7 +1225,7 @@ INT_PTR CALLBACK new_version_callback(HWND hDlg, UINT message, WPARAM wParam, LP } break; case UM_DOWNLOAD_INIT: - download_error = 0; + error_code = 0; download_status = 1; SetWindowTextU(GetDlgItem(hDlg, IDC_DOWNLOAD), "Abort"); return (INT_PTR)TRUE; @@ -1134,7 +1244,7 @@ INT_PTR CALLBACK new_version_callback(HWND hDlg, UINT message, WPARAM wParam, LP void download_new_version(void) { - DialogBoxW(main_instance, MAKEINTRESOURCEW(IDD_NEW_VERSION), hMain, new_version_callback); + DialogBoxW(main_instance, MAKEINTRESOURCEW(IDD_NEW_VERSION), hMainDialog, new_version_callback); } void set_title_bar_icon(HWND hDlg) diff --git a/libwdi/libwdi.c b/libwdi/libwdi.c index c6c20f01..5dcf909a 100644 --- a/libwdi/libwdi.c +++ b/libwdi/libwdi.c @@ -220,7 +220,7 @@ static char err_string[STR_BUFFER_SIZE]; // Retrieve the SID of the current user. The returned PSID must be freed by the caller using LocalFree() -static PSID get_sid(void) { +static PSID GetSid(void) { TOKEN_USER* tu = NULL; DWORD len; HANDLE token; @@ -308,7 +308,7 @@ static int check_dir(const char* path, BOOL create) } // Change the owner from admin to regular user - sid = get_sid(); + sid = GetSid(); if ( (sid != NULL) && InitializeSecurityDescriptor(&s_desc, SECURITY_DESCRIPTOR_REVISION) && SetSecurityDescriptorOwner(&s_desc, sid, FALSE) ) { @@ -385,7 +385,7 @@ static FILE *fopen_as_userU(const char *filename, const char *mode) } // Change the owner from admin to regular user - sid = get_sid(); + sid = GetSid(); if ( (sid != NULL) && InitializeSecurityDescriptor(&s_desc, SECURITY_DESCRIPTOR_REVISION) && SetSecurityDescriptorOwner(&s_desc, sid, FALSE) ) { @@ -1415,7 +1415,7 @@ static int process_message(char* buffer, DWORD size) wdi_dbg("installer process completed"); break; case IC_GET_USER_SID: - if (ConvertSidToStringSidA(get_sid(), &sid_str)) { + if (ConvertSidToStringSidA(GetSid(), &sid_str)) { WriteFile(pipe_handle, sid_str, (DWORD)safe_strlen(sid_str), &tmp, NULL); LocalFree(sid_str); } else { diff --git a/libwdi/libwdi.rc b/libwdi/libwdi.rc index 303ff529..2134e05d 100644 --- a/libwdi/libwdi.rc +++ b/libwdi/libwdi.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,719,0 - PRODUCTVERSION 1,3,719,0 + FILEVERSION 1,3,720,0 + PRODUCTVERSION 1,3,720,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,13 +68,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "libwdi: Windows Driver Installer Library" - VALUE "FileVersion", "1.3.719" + VALUE "FileVersion", "1.3.720" VALUE "InternalName", "libwdi" VALUE "LegalCopyright", "© 2010-2017 Pete Batard (LGPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/lesser.html" VALUE "OriginalFilename", "libwdi" VALUE "ProductName", "libwdi" - VALUE "ProductVersion", "1.3.719" + VALUE "ProductVersion", "1.3.720" VALUE "Comments", "http://libwdi.akeo.ie" END END diff --git a/libwdi/msapi_utf8.h b/libwdi/msapi_utf8.h index b032ec29..388fdfd2 100644 --- a/libwdi/msapi_utf8.h +++ b/libwdi/msapi_utf8.h @@ -1,6 +1,7 @@ /* * MSAPI_UTF8: Common API calls using UTF-8 strings * Compensating for what Microsoft should have done a long long time ago. + * Also see http://utf8everywhere.org/ * * Copyright © 2010-2017 Pete Batard * @@ -21,10 +22,18 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include #pragma once #if defined(_MSC_VER) @@ -53,9 +62,18 @@ extern "C" { _ms_wlvi.pszText = utf8_to_wchar(pszText_); \ SNDMSG((hwndLV),LVM_SETITEMTEXTW,(WPARAM)(i),(LPARAM)&_ms_wlvi); sfree(_ms_wlvi.pszText);} +// Never ever use isdigit() or isspace(), etc. on UTF-8 strings! +// These calls take an int and char is signed so MS compilers will produce an assert error on anything that's > 0x80 +#define isasciiU(c) isascii((unsigned char)(c)) +#define iscntrlU(c) iscntrl((unsigned char)(c)) +#define isdigitU(c) isdigit((unsigned char)(c)) +#define isspaceU(c) isspace((unsigned char)(c)) +#define isxdigitU(c) isxdigit((unsigned char)(c)) +// NB: other issomething() calls are not implemented as they may require multibyte UTF-8 sequences to be converted + #define sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0) #define wconvert(p) wchar_t* w ## p = utf8_to_wchar(p) -#define walloc(p, size) wchar_t* w ## p = (wchar_t*)calloc(size, sizeof(wchar_t)) +#define walloc(p, size) wchar_t* w ## p = (p == NULL)?NULL:(wchar_t*)calloc(size, sizeof(wchar_t)) #define wfree(p) sfree(w ## p) /* @@ -92,6 +110,9 @@ static __inline wchar_t* utf8_to_wchar(const char* str) int size = 0; wchar_t* wstr = NULL; + if (str == NULL) + return NULL; + // Find out the size we need to allocate for our converted string size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); if (size <= 1) // An empty string would be size 1 @@ -107,6 +128,31 @@ static __inline wchar_t* utf8_to_wchar(const char* str) return wstr; } +/* +* Converts an non NUL-terminated UTF-16 string of length len to UTF8 (allocate returned string) +* Returns NULL on error +*/ +static __inline char* wchar_len_to_utf8(const wchar_t* wstr, int wlen) +{ + int size = 0; + char* str = NULL; + + // Find out the size we need to allocate for our converted string + size = WideCharToMultiByte(CP_UTF8, 0, wstr, wlen, NULL, 0, NULL, NULL); + if (size <= 1) // An empty string would be size 1 + return NULL; + + if ((str = (char*)calloc(size, 1)) == NULL) + return NULL; + + if (WideCharToMultiByte(CP_UTF8, 0, wstr, wlen, str, size, NULL, NULL) != size) { + sfree(str); + return NULL; + } + + return str; +} + static __inline DWORD FormatMessageU(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, char* lpBuffer, DWORD nSize, va_list *Arguments) { @@ -182,6 +228,22 @@ static __inline HWND CreateWindowU(char* lpClassName, char* lpWindowName, return ret; } +static __inline HWND CreateWindowExU(DWORD dwExStyle, char* lpClassName, char* lpWindowName, + DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, + HINSTANCE hInstance, LPVOID lpParam) +{ + HWND ret = NULL; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpClassName); + wconvert(lpWindowName); + ret = CreateWindowExW(dwExStyle, wlpClassName, wlpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + err = GetLastError(); + wfree(lpClassName); + wfree(lpWindowName); + SetLastError(err); + return ret; +} + static __inline int MessageBoxU(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) { int ret; @@ -196,6 +258,65 @@ static __inline int MessageBoxU(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT return ret; } +static __inline int MessageBoxExU(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId) +{ + int ret; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpText); + wconvert(lpCaption); + ret = MessageBoxExW(hWnd, wlpText, wlpCaption, uType, wLanguageId); + err = GetLastError(); + wfree(lpText); + wfree(lpCaption); + SetLastError(err); + return ret; +} + +static __inline int LoadStringU(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax) +{ + int ret; + DWORD err = ERROR_INVALID_DATA; + if (nBufferMax == 0) { + // read-only pointer to resource mode is not supported + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + // coverity[returned_null] + walloc(lpBuffer, nBufferMax); + ret = LoadStringW(hInstance, uID, wlpBuffer, nBufferMax); + err = GetLastError(); + if ((ret > 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferMax)) == 0)) { + err = GetLastError(); + } + wfree(lpBuffer); + SetLastError(err); + return ret; +} + +static __inline HMODULE LoadLibraryU(LPCSTR lpFileName) +{ + HMODULE ret; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpFileName); + ret = LoadLibraryW(wlpFileName); + err = GetLastError(); + wfree(lpFileName); + SetLastError(err); + return ret; +} + +static __inline int DrawTextU(HDC hDC, LPCSTR lpText, int nCount, LPRECT lpRect, UINT uFormat) +{ + int ret; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpText); + ret = DrawTextW(hDC, wlpText, nCount, lpRect, uFormat); + err = GetLastError(); + wfree(lpText); + SetLastError(err); + return ret; +} + static __inline int GetWindowTextU(HWND hWnd, char* lpString, int nMaxCount) { int ret = 0; @@ -284,6 +405,18 @@ static __inline BOOL SetDlgItemTextU(HWND hDlg, int nIDDlgItem, const char* lpSt return ret; } +static __inline BOOL InsertMenuU(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const char* lpNewItem) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpNewItem); + ret = InsertMenuW(hMenu, uPosition, uFlags, uIDNewItem, wlpNewItem); + err = GetLastError(); + wfree(lpNewItem); + SetLastError(err); + return ret; +} + static __inline int ComboBox_GetLBTextU(HWND hCtrl, int index, char* lpString) { int size; @@ -304,6 +437,19 @@ static __inline int ComboBox_GetLBTextU(HWND hCtrl, int index, char* lpString) return size; } +static __inline DWORD CharUpperBuffU(char* lpString, DWORD len) +{ + DWORD ret; + wchar_t *wlpString = calloc(len, sizeof(wchar_t)); + if (wlpString == NULL) + return 0; + utf8_to_wchar_no_alloc(lpString, wlpString, len); + ret = CharUpperBuffW(wlpString, len); + wchar_to_utf8_no_alloc(wlpString, lpString, len); + free(wlpString); + return ret; +} + static __inline HANDLE CreateFileU(const char* lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) @@ -319,6 +465,20 @@ static __inline HANDLE CreateFileU(const char* lpFileName, DWORD dwDesiredAccess return ret; } +static __inline BOOL CopyFileU(const char* lpExistingFileName, const char* lpNewFileName, BOOL bFailIfExists) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpExistingFileName); + wconvert(lpNewFileName); + ret = CopyFileW(wlpExistingFileName, wlpNewFileName, bFailIfExists); + err = GetLastError(); + wfree(lpExistingFileName); + wfree(lpNewFileName); + SetLastError(err); + return ret; +} + static __inline BOOL DeleteFileU(const char* lpFileName) { BOOL ret = FALSE; @@ -331,6 +491,43 @@ static __inline BOOL DeleteFileU(const char* lpFileName) return ret; } +static __inline BOOL PathFileExistsU(char* szPath) +{ + BOOL ret; + wconvert(szPath); + ret = PathFileExistsW(wszPath); + wfree(szPath); + return ret; +} + +static __inline int PathGetDriveNumberU(char* lpPath) +{ + int ret = 0; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpPath); + ret = PathGetDriveNumberW(wlpPath); + err = GetLastError(); + wfree(lpPath); + SetLastError(err); + return ret; +} + +// This one is tricky since we can't blindly convert a +// UTF-16 position to a UTF-8 one. So we do it manually. +static __inline const char* PathFindFileNameU(const char* szPath) +{ + size_t i; + if (szPath == NULL) + return NULL; + for (i = strlen(szPath); i != 0; i--) { + if ((szPath[i] == '/') || (szPath[i] == '\\')) { + i++; + break; + } + } + return &szPath[i]; +} + // This function differs from regular GetTextExtentPoint in that it uses a zero terminated string static __inline BOOL GetTextExtentPointU(HDC hdc, const char* lpString, LPSIZE lpSize) { @@ -361,6 +558,70 @@ static __inline DWORD GetCurrentDirectoryU(DWORD nBufferLength, char* lpBuffer) return ret; } +static __inline UINT GetSystemDirectoryU(char* lpBuffer, UINT uSize) +{ + UINT ret = 0, err = ERROR_INVALID_DATA; + // coverity[returned_null] + walloc(lpBuffer, uSize); + ret = GetSystemDirectoryW(wlpBuffer, uSize); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, uSize)) == 0)) { + err = GetLastError(); + } + wfree(lpBuffer); + SetLastError(err); + return ret; +} + +static __inline UINT GetSystemWindowsDirectoryU(char* lpBuffer, UINT uSize) +{ + UINT ret = 0, err = ERROR_INVALID_DATA; + // coverity[returned_null] + walloc(lpBuffer, uSize); + ret = GetSystemWindowsDirectoryW(wlpBuffer, uSize); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, uSize)) == 0)) { + err = GetLastError(); + } + wfree(lpBuffer); + SetLastError(err); + return ret; +} + +static __inline DWORD GetTempPathU(DWORD nBufferLength, char* lpBuffer) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + // coverity[returned_null] + walloc(lpBuffer, nBufferLength); + ret = GetTempPathW(nBufferLength, wlpBuffer); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) { + err = GetLastError(); + } + wfree(lpBuffer); + SetLastError(err); + return ret; +} + +static __inline DWORD GetTempFileNameU(char* lpPathName, char* lpPrefixString, UINT uUnique, char* lpTempFileName) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + wconvert(lpPathName); + wconvert(lpPrefixString); + // coverity[returned_null] + walloc(lpTempFileName, MAX_PATH); + ret = GetTempFileNameW(wlpPathName, wlpPrefixString, uUnique, wlpTempFileName); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpTempFileName, lpTempFileName, MAX_PATH)) == 0)) { + err = GetLastError(); + } + wfree(lpTempFileName); + wfree(lpPrefixString); + wfree(lpPathName); + SetLastError(err); + return ret; +} + static __inline DWORD GetModuleFileNameU(HMODULE hModule, char* lpFilename, DWORD nSize) { DWORD ret = 0, err = ERROR_INVALID_DATA; @@ -376,6 +637,22 @@ static __inline DWORD GetModuleFileNameU(HMODULE hModule, char* lpFilename, DWOR return ret; } +static __inline DWORD GetModuleFileNameExU(HANDLE hProcess, HMODULE hModule, char* lpFilename, DWORD nSize) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + // coverity[returned_null] + walloc(lpFilename, nSize); + ret = GetModuleFileNameExW(hProcess, hModule, wlpFilename, nSize); + err = GetLastError(); + if ((ret != 0) + && ((ret = wchar_to_utf8_no_alloc(wlpFilename, lpFilename, nSize)) == 0)) { + err = GetLastError(); + } + wfree(lpFilename); + SetLastError(err); + return ret; +} + static __inline DWORD GetFullPathNameU(const char* lpFileName, DWORD nBufferLength, char* lpBuffer, char** lpFilePart) { DWORD ret = 0, err = ERROR_INVALID_DATA; @@ -404,13 +681,7 @@ static __inline DWORD GetFileAttributesU(const char* lpFileName) { DWORD ret = 0xFFFFFFFF, err = ERROR_INVALID_DATA; wconvert(lpFileName); - // Unlike Microsoft's version, ours doesn't fail if the string is quoted - if ((wlpFileName[0] == L'"') && (wlpFileName[wcslen(wlpFileName) - 1] == L'"')) { - wlpFileName[wcslen(wlpFileName) - 1] = 0; - ret = GetFileAttributesW(&wlpFileName[1]); - } else { - ret = GetFileAttributesW(wlpFileName); - } + ret = GetFileAttributesW(wlpFileName); err = GetLastError(); wfree(lpFileName); SetLastError(err); @@ -429,6 +700,22 @@ static __inline int SHCreateDirectoryExU(HWND hwnd, const char* pszPath, SECURIT return ret; } +static __inline int SHDeleteDirectoryExU(HWND hwnd, const char* pszPath, FILEOP_FLAGS fFlags) +{ + int ret; + // String needs to be double NULL terminated, so we just use the length of the UTF-8 string + // which is always expected to be larger than our UTF-16 one, and add 2 chars for good measure. + size_t wpszPath_len = strlen(pszPath) + 2; + // coverity[returned_null] + walloc(pszPath, wpszPath_len); + SHFILEOPSTRUCTW shfo = { hwnd, FO_DELETE, wpszPath, NULL, fFlags, FALSE, NULL, NULL }; + utf8_to_wchar_no_alloc(pszPath, wpszPath, (int)wpszPath_len); + // FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION, + ret = SHFileOperationW(&shfo); + wfree(pszPath); + return ret; +} + static __inline BOOL ShellExecuteExU(SHELLEXECUTEINFOA* lpExecInfo) { BOOL ret = FALSE; @@ -642,6 +929,7 @@ static __inline int _chdirU(const char *dirname) return ret; } +#if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x501) static __inline FILE* fopenU(const char* filename, const char* mode) { FILE* ret = NULL; @@ -653,6 +941,60 @@ static __inline FILE* fopenU(const char* filename, const char* mode) return ret; } +static __inline int _openU(const char *filename, int oflag, int pmode) +{ + int ret = -1; + wconvert(filename); + ret = _wopen(wfilename, oflag, pmode); + wfree(filename); + return ret; +} +#else +static __inline FILE* fopenU(const char* filename, const char* mode) +{ + FILE* ret = NULL; + wconvert(filename); + wconvert(mode); + _wfopen_s(&ret, wfilename, wmode); + wfree(filename); + wfree(mode); + return ret; +} + +static __inline int _openU(const char *filename, int oflag , int pmode) +{ + int ret = -1; + int shflag = _SH_DENYNO; + wconvert(filename); + // Try to match the share flag to the oflag + if ((oflag & 0x03) == _O_RDONLY) + shflag = _SH_DENYWR; + else if ((oflag & 0x03) == _O_WRONLY) + shflag = _SH_DENYRD; + _wsopen_s(&ret, wfilename, oflag, shflag, pmode); + wfree(filename); + return ret; +} +#endif + +static __inline int _unlinkU(const char *path) +{ + int ret; + wconvert(path); + ret = _wunlink(wpath); + wfree(path); + return ret; +} + +static __inline int _stat64U(const char *path, struct __stat64 *buffer) +{ + int ret; + wconvert(path); + ret = _wstat64(wpath, buffer); + wfree(path); + return ret; +} + // returned UTF-8 string must be freed static __inline char* getenvU(const char* varname) { @@ -681,6 +1023,60 @@ static __inline int _mkdirU(const char* dirname) return ret; } +// The following expects PropertyBuffer to contain a single Unicode string +static __inline BOOL SetupDiGetDeviceRegistryPropertyU(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, + DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + // coverity[returned_null] + walloc(PropertyBuffer, PropertyBufferSize); + + ret = SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, Property, + PropertyRegDataType, (PBYTE)wPropertyBuffer, PropertyBufferSize, RequiredSize); + err = GetLastError(); + if ((ret != 0) && (wchar_to_utf8_no_alloc(wPropertyBuffer, + (char*)(uintptr_t)PropertyBuffer, PropertyBufferSize) == 0)) { + err = GetLastError(); + ret = FALSE; + } + wfree(PropertyBuffer); + SetLastError(err); + return ret; +} + +static __inline BOOL GetVolumeInformationU(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpRootPathName); + // coverity[returned_null] + walloc(lpVolumeNameBuffer, nVolumeNameSize); + // coverity[returned_null] + walloc(lpFileSystemNameBuffer, nFileSystemNameSize); + + ret = GetVolumeInformationW(wlpRootPathName, wlpVolumeNameBuffer, nVolumeNameSize, + lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, + wlpFileSystemNameBuffer, nFileSystemNameSize); + err = GetLastError(); + if (ret) { + if ( ((lpVolumeNameBuffer != NULL) && (wchar_to_utf8_no_alloc(wlpVolumeNameBuffer, + lpVolumeNameBuffer, nVolumeNameSize) == 0)) + || ((lpFileSystemNameBuffer != NULL) && (wchar_to_utf8_no_alloc(wlpFileSystemNameBuffer, + lpFileSystemNameBuffer, nFileSystemNameSize) == 0)) ) { + err = GetLastError(); + ret = FALSE; + } + } + wfree(lpVolumeNameBuffer); + wfree(lpFileSystemNameBuffer); + wfree(lpRootPathName); + SetLastError(err); + return ret; +} + #ifdef __cplusplus } #endif