diff --git a/.amend.cmd b/.amend.cmd deleted file mode 100644 index bd37740f..00000000 --- a/.amend.cmd +++ /dev/null @@ -1,2 +0,0 @@ -echo off -echo .>.amend \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 97283bde..398a2312 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,6 +8,9 @@ *.inf.in eol=crlf *.rc eol=crlf *.def eol=crlf +*.creole export-ignore .gitattributes export-ignore .gitignore export-ignore -*.creole export-ignore \ No newline at end of file +_*.sh export-ignore +_*.cmd export-ignore +appveyor.yml export-ignore diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..667c0a85 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,73 @@ +name: CodeQL + +on: + push: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.md' + - 'AUTHORS' + - 'NEWS' + - 'ChangeLog' + pull_request: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.md' + - 'AUTHORS' + - 'NEWS' + - 'ChangeLog' + +env: + WDK_URL: https://go.microsoft.com/fwlink/p/?LinkID=253170 + LIBUSB0_URL: https://github.com/mcuee/libusb-win32/releases/download/release_1.4.0.0/libusb-win32-bin-1.4.0.0.zip + LIBUSBK_URL: https://github.com/mcuee/libusbk/releases/download/V3.1.0.0/libusbK-3.1.0.0-bin.7z + SOLUTION_FILE_PATH: ./libwdi.sln + TARGET_PLATFORM: x64 + BUILD_CONFIGURATION: Debug + BUILD_MACROS: '"WDK_DIR=\"../wdk/Windows Kits/8.0\";LIBUSB0_DIR=\"../libusb0\";LIBUSBK_DIR=\"../libusbk/bin\""' + +jobs: + CodeQL-Build: + runs-on: windows-latest + + permissions: + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + + - name: Download support files + shell: cmd + run: | + curl -L ${{ env.WDK_URL }} -o wdk-redist.msi + curl -L ${{ env.LIBUSB0_URL }} -o libusb0-redist.zip + curl -L ${{ env.LIBUSBK_URL }} -o libusbk-redist.7z + msiexec /a wdk-redist.msi /qn TARGETDIR=%CD%\wdk + 7z x libusb0-redist.zip + 7z x libusbk-redist.7z + del *.zip + del *.7z + move libusb-win32* libusb0 + move libusbK* libusbk + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: cpp + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v2 + + - name: Build + shell: cmd + run: msbuild ${{ env.SOLUTION_FILE_PATH }} /m /p:Configuration=${{ env.BUILD_CONFIGURATION}},Platform=${{ env.TARGET_PLATFORM }},BuildMacros=${{ env.BUILD_MACROS }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml new file mode 100644 index 00000000..a12ea6bb --- /dev/null +++ b/.github/workflows/coverity.yml @@ -0,0 +1,64 @@ +name: Coverity + +on: + push: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.md' + - 'AUTHORS' + - 'NEWS' + - 'ChangeLog' + +env: + WDK_URL: https://go.microsoft.com/fwlink/p/?LinkID=253170 + LIBUSB0_URL: https://github.com/mcuee/libusb-win32/releases/download/release_1.4.0.0/libusb-win32-bin-1.4.0.0.zip + LIBUSBK_URL: https://github.com/mcuee/libusbk/releases/download/V3.1.0.0/libusbK-3.1.0.0-bin.7z + SOLUTION_FILE_PATH: ./libwdi.sln + EMAIL: pete@akeo.ie + BUILD_MACROS: '"WDK_DIR=\"../wdk/Windows Kits/8.0\";LIBUSB0_DIR=\"../libusb0\";LIBUSBK_DIR=\"../libusbk/bin\""' + +jobs: + Coverity-Build: + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + - name: Download Coverity + run: | + curl -d "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=pbatard%2Flibwdi" -L https://scan.coverity.com/download/cxx/win64 -o cov-analysis-win64.zip + 7z x cov-analysis-win64.zip + del cov-analysis-win64.zip + move cov-analysis-win64* cov-analysis-win64 + - name: Add Coverity to PATH + shell: bash + run: echo "${{ github.workspace }}/cov-analysis-win64/bin" >> $GITHUB_PATH + - name: Download support files + shell: cmd + run: | + curl -L ${{ env.WDK_URL }} -o wdk-redist.msi + curl -L ${{ env.LIBUSB0_URL }} -o libusb0-redist.zip + curl -L ${{ env.LIBUSBK_URL }} -o libusbk-redist.7z + msiexec /a wdk-redist.msi /qn TARGETDIR=%CD%\wdk + 7z x libusb0-redist.zip + 7z x libusbk-redist.7z + del *.zip + del *.7z + move libusb-win32* libusb0 + move libusbK* libusbk + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v2 + - name: Build with Coverity + shell: cmd + run: | + cov-configure --msvc + cov-build.exe --dir cov-int msbuild ${{ env.SOLUTION_FILE_PATH }} /m /p:Configuration=Release,Platform=x64,BuildMacros=${{ env.BUILD_MACROS }} + - name: Upload Coverity build for analysis + run: | + 7z a -r cov-int.zip cov-int + curl --form email=${{ env.EMAIL }} --form token=${{ secrets.COVERITY_SCAN_TOKEN }} --form file=@cov-int.zip --form version="${{ env.GITHUB_SHA }}" --form description="libwdi" https://scan.coverity.com/builds?project=pbatard%2Flibwdi diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml new file mode 100644 index 00000000..cee6030d --- /dev/null +++ b/.github/workflows/mingw.yml @@ -0,0 +1,100 @@ +name: MinGW + +on: + push: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.md' + - 'AUTHORS' + - 'NEWS' + - 'ChangeLog' + pull_request: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.md' + - 'AUTHORS' + - 'NEWS' + - 'ChangeLog' + +env: + WDK_URL: https://go.microsoft.com/fwlink/p/?LinkID=253170 + LIBUSB0_URL: https://github.com/mcuee/libusb-win32/releases/download/release_1.4.0.0/libusb-win32-bin-1.4.0.0.zip + LIBUSBK_URL: https://github.com/mcuee/libusbk/releases/download/V3.1.0.0/libusbK-3.1.0.0-bin.7z + BUILD_OPTIONS: '--enable-toggable-debug --enable-examples-build --disable-debug --disable-shared' + DRIVERS_PATHS: '--with-wdkdir="wdk/Windows Kits/8.0" --with-wdfver=1011 --with-libusb0="libusb0" --with-libusbk="libusbk/bin"' + +jobs: + MinGW-Build: + runs-on: windows-latest + + strategy: + matrix: + include: + - { sys: mingw64, env: x86_64 } + - { sys: mingw32, env: i686 } + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Install MinGW + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.sys }} + update: true + install: >- + mingw-w64-${{ matrix.env }}-toolchain + base-devel + autotools + git + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + - name: Download support files + shell: cmd + run: | + curl -L ${{ env.WDK_URL }} -o wdk-redist.msi + curl -L ${{ env.LIBUSB0_URL }} -o libusb0-redist.zip + curl -L ${{ env.LIBUSBK_URL }} -o libusbk-redist.7z + msiexec /a wdk-redist.msi /qn TARGETDIR=%CD%\wdk + 7z x libusb0-redist.zip + 7z x libusbk-redist.7z + del *.zip + del *.7z + move libusb-win32* libusb0 + move libusbK* libusbk + - name: Build + run: | + ./bootstrap.sh + [ "${{ matrix.env }}" == "x86_64" ] && EXTRA_OPTION=--disable-32bit + ./configure --build=${{ matrix.env }}-w64-mingw32 --host=${{ matrix.env }}-w64-mingw32 ${{ env.BUILD_OPTIONS }} $EXTRA_OPTION ${{ env.DRIVERS_PATHS }} + make + mkdir -p artifacts/${{ matrix.env }} + mv examples/*.exe artifacts/${{ matrix.env }} + - name: Display SHA-256 + if: ${{ github.event_name == 'push' }} + run: sha256sum artifacts/${{ matrix.env }}/*.exe + - name: Upload artifacts + uses: actions/upload-artifact@v4 + if: ${{ github.event_name == 'push' }} + with: + name: ${{ matrix.sys }} + path: ./artifacts/*/*.exe + + Merge-Artifacts: + runs-on: windows-latest + needs: MinGW-Build + steps: + - name: Merge Artifacts + uses: actions/upload-artifact/merge@v4 + if: ${{ github.event_name == 'push' }} + with: + name: MinGW + delete-merged: true \ No newline at end of file diff --git a/.github/workflows/vs2022.yml b/.github/workflows/vs2022.yml new file mode 100644 index 00000000..e17843d7 --- /dev/null +++ b/.github/workflows/vs2022.yml @@ -0,0 +1,101 @@ +name: VS2022 + +on: + push: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.md' + - 'AUTHORS' + - 'NEWS' + - 'ChangeLog' + pull_request: + paths-ignore: + - '.gitignore' + - '.gitattributes' + - '**.cmd' + - '**.md' + - 'AUTHORS' + - 'NEWS' + - 'ChangeLog' + +env: + WDK_URL: https://go.microsoft.com/fwlink/p/?LinkID=253170 + LIBUSB0_URL: https://github.com/mcuee/libusb-win32/releases/download/release_1.4.0.0/libusb-win32-bin-1.4.0.0.zip + LIBUSBK_URL: https://github.com/mcuee/libusbk/releases/download/V3.1.0.0/libusbK-3.1.0.0-bin.7z + SOLUTION_FILE_PATH: ./libwdi.sln + BUILD_MACROS: '"WDK_DIR=\"../wdk/Windows Kits/8.0\";LIBUSB0_DIR=\"../libusb0\";LIBUSBK_DIR=\"../libusbk/bin\""' + +jobs: + VS2022-Build: + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + + - name: Download support files + shell: cmd + run: | + curl -L ${{ env.WDK_URL }} -o wdk-redist.msi + curl -L ${{ env.LIBUSB0_URL }} -o libusb0-redist.zip + curl -L ${{ env.LIBUSBK_URL }} -o libusbk-redist.7z + msiexec /a wdk-redist.msi /qn TARGETDIR=%CD%\wdk + 7z x libusb0-redist.zip + 7z x libusbk-redist.7z + del *.zip + del *.7z + move libusb-win32* libusb0 + move libusbK* libusbk + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v2 + + - name: Build + shell: cmd + run: | + for %%P in (Win32 x64) do ( + for %%B in (Debug Release) do ( + msbuild ${{ env.SOLUTION_FILE_PATH }} /m /p:Configuration=%%B,Platform=%%P,BuildMacros=${{ env.BUILD_MACROS }} + ) + ) + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + if: ${{ github.event_name == 'push' }} + with: + name: VS2022 + path: ./*/*/examples/*.exe + + - name: Display SHA-256 + if: ${{ github.event_name == 'push' }} + run: sha256sum ./*/*/examples/*.exe + + - name: Compress release-ready version of Zadig + uses: crazy-max/ghaction-upx@v3 + if: startsWith(github.ref, 'refs/tags/') + with: + version: latest + files: ./Win32/Release/examples/zadig.exe + args: --lzma --best + + - name: Rename release-ready version of Zadig + if: startsWith(github.ref, 'refs/tags/') + shell: cmd + run: | + for /f "tokens=3" %%i in ('findstr FileVersion examples\zadig.rc') do set "ver=%%i" + set ver=%ver:"=% + for /f "tokens=1,2 delims=." %%i in ("%ver%") do set "ZADIG_VERSION=%%i.%%j" + copy Win32\Release\examples\zadig.exe zadig-%ZADIG_VERSION%.exe + sha256sum zadig-*.exe + + - name: Upload release-ready version of Zadig + uses: actions/upload-artifact@v4 + if: startsWith(github.ref, 'refs/tags/') + with: + name: Zadig + path: ./zadig-*.exe diff --git a/AUTHORS b/AUTHORS index d0e64ad2..3d4319e4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,16 +1,28 @@ -Copyright © 2010-2016 Pete Batard -Copyright © 2010-2011 Travis Robinson +Copyright © 2010-2023 Pete Batard +Copyright © 2010-2011 Travis Robinson Other contributors: Alexander Sashnov Bob Paddock +Fred Sundvik +Georg Vienna +Giovanni Bajo +Jacob Alexander JaggedJax +Jasper van Bourgognie +Jeorg Fischer Jerome-PS +Joel Holdsworth Joseph Marshall +Josh Soerf +Karel Bilek Liam Staskawicz Louie Caulfield PhracturedBlue Ryan Pavlik +Spiro Trikaliotis +Stanley Elliott +Tim Gates Uri Lublin Vitali Lovich -Xiaofan Chen \ No newline at end of file +Xiaofan Chen diff --git a/ChangeLog b/ChangeLog index 111b6d5d..5c76d75c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,57 @@ For the latest changes, please visit: https://github.com/pbatard/libwdi/commits/master +o v1.5.1 (2024.06.13) + New features: + - libusb-win32 ARM64 driver installation support (courtesy of Peter Dons Tychsen) + Bugfixes: + - fix filter installer being potentially overwritten (courtesy of Peter Dons Tychsen) + Improvements: + - improve Windows edition and platform reporting + +o v1.5.0 (2023.03.01) + New features: + - ARM64 driver installation support (WinUSB, USBSer with MSVC only) + Bugfixes: + - fix MSVC compilation of the shared library + - fix MinGW compilation when using the shared library (with thanks to Joel Holdsworth) + Improvements: + - avoid symbol conflicts by using library specific prefixes where needed + - improve Zadig network support + +o v1.4.1 (2021.11.01) + New features: + - add a new 'external_inf' boolean option to wdi_options_prepare_driver + to allow the use of an external .inf instead of the embedded ones + Bugfixes: + - prevent an infinite loop when a certificate cannot be deleted + - fix the use of -w option in wdi-simple + - fix error when trying to install libusb0.sys as a filter-driver + Improvements: + - improve Windows version reporting for Windows 11 + - stop on .cat signing error if test signing is not enabled + - add an explicit error for code 0x109 (for Windows 11 Insider builds) + +o v1.4.0 (2021.09.04) + Bugfixes: + - fix breakage when providing a user driver + - work around Windows corrupting the key containers + - don't populate empty device descriptors + Improvements: + - more error reporting improvements + - remove the zadic sample + +o v1.3.1 (2020.03.30) + Bugfixes: + - fix handling of non western paths during cat file generation + - fix Windows 7 showing a "Trusted Publisher" dialog + - fix memory leaks + Improvements: + - update project files to VS2019 + - improve error reporting + - allow interface 0 for wdi-simple + - increase RSA bit key size + o v1.3.0 (2017.04.18) Bugfixes: - fix issues with extended characters in current user directory diff --git a/README.md b/README.md index 5a16034d..6c738157 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,21 @@ libwdi: A Windows Driver Installation library for USB devices ============================================================= -[![Build status](https://ci.appveyor.com/api/projects/status/p9q869jayrnbfkkt?svg=true)](https://ci.appveyor.com/project/pbatard/libwdi) -[![Coverity Scan Build Status](https://scan.coverity.com/projects/2174/badge.svg)](https://scan.coverity.com/projects/pbatard-libwdi) -[![Licence](https://img.shields.io/badge/license-LGPLv3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0.en.html) +[![Build status](https://img.shields.io/github/actions/workflow/status/pbatard/libwdi/vs2022.yml?style=flat-square&label=VS2022)](https://github.com/pbatard/libwdi/actions/workflows/vs2022.yml) +[![Build status](https://img.shields.io/github/actions/workflow/status/pbatard/libwdi/mingw.yml?style=flat-square&label=MinGW)](https://github.com/pbatard/libwdi/actions/workflows/mingw.yml) +[![Coverity Scan Build Status](https://img.shields.io/coverity/scan/2174.svg?style=flat-square&label=Coverity)](https://scan.coverity.com/projects/pbatard-libwdi) +[![Github stats](https://img.shields.io/github/downloads/pbatard/libwdi/total.svg?style=flat-square&label=Downloads)](https://github.com/pbatard/libwdi/releases) +[![Licence](https://img.shields.io/badge/license-LGPLv3-blue.svg?style=flat-square&label=License)](https://www.gnu.org/licenses/lgpl-3.0.en.html) Main features ------------- * Automated inf creation, using reported USB device name * Automated catalog file creation and signing, using autogenerated certificate -* Automated driver files extraction, for both 32 and 64 bit platforms +* Automated driver files extraction, for `x86_32`, `x86_64` and `ARM64` platforms * Automated driver installation, including UAC elevation where necessary * Single library embedding all the required files -* Supports Windows platform from Windows 7 to Windows 10 +* Supports Windows platform from Windows 7 to Windows 11 Additional features ------------------- @@ -24,7 +26,7 @@ Additional features * Resolution of USB Vendor IDs, based on the data maintained by Stephen J. Gowdy at http://www.linux-usb.org/usb.ids * Fully Open Source (LGPL v3), with multiple sample applications -* Supports MinGW32, MinGW-w64, Visual Studio, WDK +* Supports MinGW32, MinGW-w64, Visual Studio Installation and Compilation ---------------------------- diff --git a/_bm.sh b/_bm.sh deleted file mode 100755 index 9d4fb79a..00000000 --- a/_bm.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -# Create and upload a Zadig release -# !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!! - -type -P git &>/dev/null || { echo "Git not found. Aborting." >&2; exit 1; } -type -P sed &>/dev/null || { echo "Sed not found. Aborting." >&2; exit 1; } -type -P upx &>/dev/null || { echo "UPX executable not found. Aborting." >&2; exit 1; } - -git clean -fdx -./autogen.sh --disable-shared - -zadig_version=`sed -n 's/^.*\"FileVersion\", \"\(.*\)\..*\"/\1/p' examples/zadig.rc` -echo Building Zadig v$zadig_version... - -make -j12 -make zadig_release \ No newline at end of file diff --git a/_bump.sh b/_bump.sh deleted file mode 100755 index 37d5fdde..00000000 --- a/_bump.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh -# This script bumps the version and updates the rc files and git tree accordingly -# !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!! - -type -P sed &>/dev/null || { echo "sed command not found. Aborting." >&2; exit 1; } -type -P git &>/dev/null || { echo "git command not found. Aborting." >&2; exit 1; } - -if [ ! -n "$1" ]; then - TAG=$(git describe --tags --abbrev=0 2>/dev/null) - if [ ! -n "$TAG" ]; then - echo Unable to read tag - aborting. - exit 1 - fi -else - TAG=$1 -fi -if [ ! ${TAG:0:1} = 'b' ]; then - echo Tag "$TAG" does not start with 'b' - aborting - exit 1 -fi -TAGVER=${TAG:1} -case $TAGVER in *[!0-9]*) - echo "$TAGVER is not a number - aborting" - exit 1 -esac -TAGVER=`expr $TAGVER + 1` -echo Bumping version to w$TAGVER - -cat > cmd.sed <<\_EOF -s/^[ \t]*FILEVERSION[ \t]*\(.*\),\(.*\),\(.*\),.*/ FILEVERSION \1,\2,\3,@@TAGVER@@/ -s/^[ \t]*PRODUCTVERSION[ \t]*\(.*\),\(.*\),\(.*\),.*/ PRODUCTVERSION \1,\2,\3,@@TAGVER@@/ -s/^\([ \t]*\)VALUE[ \t]*"FileVersion",[ \t]*"\(.*\)\..*"/\1VALUE "FileVersion", "\2.@@TAGVER@@"/ -s/^\([ \t]*\)VALUE[ \t]*"ProductVersion",[ \t]*"\(.*\)\..*"/\1VALUE "ProductVersion", "\2.@@TAGVER@@"/ -s/^\(.*\)adig v\(.*\)\.\(.*\)"\(.*\)/\1adig v\2.@@TAGVER@@"\4/ -s/^zadig_version=\(.*\)\..*/zadig_version=\1.@@TAGVER@@/ -s/^\(.*\)"Version \(.*\) (Build \(.*\))"\(.*\)/\1"Version \2 (Build @@TAGVER@@)"\4/ -_EOF - -# First run sed to substitute our variable in the sed command file -sed -e "s/@@TAGVER@@/$TAGVER/g" cmd.sed > cmd.sed~ -mv cmd.sed~ cmd.sed - -# Run sed to update the .rc files minor version -sed -f cmd.sed libwdi/libwdi.rc > libwdi/libwdi.rc~ -mv libwdi/libwdi.rc~ libwdi/libwdi.rc -sed -f cmd.sed examples/zadic.rc > examples/zadic.rc~ -mv examples/zadic.rc~ examples/zadic.rc -sed -f cmd.sed examples/zadig.rc > examples/zadig.rc~ -mv examples/zadig.rc~ examples/zadig.rc -sed -f cmd.sed examples/zadig.h > examples/zadig.h~ -mv examples/zadig.h~ examples/zadig.h -sed -f cmd.sed examples/wdi-simple.rc > examples/wdi-simple.rc~ -mv examples/wdi-simple.rc~ examples/wdi-simple.rc -sed -f cmd.sed _bm.sh > _bm.sh~ -mv _bm.sh~ _bm.sh - -rm cmd.sed - -# Update VID data while we're at it -cd libwdi -. vid_data.sh -cd .. - -git commit -a -m "[internal] bumped internal version" -e -git tag "b$TAGVER" \ No newline at end of file diff --git a/_chlver.sh b/_chlver.sh index 5ab95919..1d098e9e 100755 --- a/_chlver.sh +++ b/_chlver.sh @@ -38,10 +38,6 @@ _EOF # First run sed to substitute our variable in the sed command file sed -i -e "s/@@MAJOR@@/$MAJOR/g" -e "s/@@MINOR@@/$MINOR/g" -e "s/@@MICRO@@/$MICRO/g" cmd.sed # Run sed to update the .rc version -sed -i -f cmd.sed libwdi/libwdi.rc -sed -i 's/$/\r/' libwdi/libwdi.rc -sed -i -f cmd.sed examples/zadic.rc -sed -i 's/$/\r/' examples/zadic.rc -sed -i -f cmd.sed examples/wdi-simple.rc -sed -i 's/$/\r/' examples/wdi-simple.rc +sed -b -i -f cmd.sed libwdi/libwdi.rc +sed -b -i -f cmd.sed examples/wdi-simple.rc rm cmd.sed diff --git a/_chzver.sh b/_chzver.sh index e0c2b745..54b80ed6 100644 --- a/_chzver.sh +++ b/_chzver.sh @@ -31,10 +31,8 @@ s/^\(.*\)"Zadig .*\..*\.\(.*\)"\(.*\)/\1"Zadig @@MAJOR@@.@@MINOR@@.\2"\3/ _EOF sed -i -e "s/@@MAJOR@@/$MAJOR/g" -e "s/@@MINOR@@/$MINOR/g" cmd.sed -sed -i -f cmd.sed examples/zadig.rc -sed -i 's/$/\r/' examples/zadig.rc -sed -i -f cmd.sed examples/zadig.h -sed -i 's/$/\r/' examples/zadig.h +sed -b -i -f cmd.sed examples/zadig.rc +sed -b -i -f cmd.sed examples/zadig.h rm cmd.sed diff --git a/_coverity.cmd b/_coverity.cmd deleted file mode 100644 index f82d2b0f..00000000 --- a/_coverity.cmd +++ /dev/null @@ -1,24 +0,0 @@ -@rem *** Internal developer script to run Coverity *** -@echo off -call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -set COV_DIR=D:\cov-analysis-win64-8.7.0 -set PATH=%PATH%;%COV_DIR%\bin -set PWD=%~dp0 -set TARGET=Win32 -rmdir cov-int /s /q >NUL 2>NUL -rmdir %TARGET% /s /q >NUL 2>NUL -del cov-int.zip >NUL 2>NUL -mkdir cov-int -cov-build --dir cov-int msbuild libwdi.sln /p:Configuration=Release,Platform=%TARGET% /maxcpucount -rem *** zip script by Peter Mortensen - http://superuser.com/a/111266/286681 -echo Set objArgs = WScript.Arguments> zip.vbs -echo InputFolder = objArgs(0)>> zip.vbs -echo ZipFile = objArgs(1)>> zip.vbs -echo CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" ^& Chr(5) ^& Chr(6) ^& String(18, vbNullChar)>> zip.vbs -echo Set objShell = CreateObject("Shell.Application")>> zip.vbs -echo Set source = objShell.NameSpace(InputFolder)>> zip.vbs -echo objShell.NameSpace(ZipFile).CopyHere(source)>> zip.vbs -echo wScript.Sleep 8000>> zip.vbs -CScript zip.vbs %PWD%cov-int %PWD%cov-int.zip -del zip.vbs -pause diff --git a/_detect-amend.sh b/_detect-amend.sh new file mode 100644 index 00000000..286f57a3 --- /dev/null +++ b/_detect-amend.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# +# This script detects whether git commit is being executed in amend or regular mode +# Needed to determine whether the build number should be incremented or not. +# + +# Need to figure out if we are running on Windows or *NIX +if [ "$(uname -o)" = "Msys" ]; then + type -P PowerShell &>/dev/null || { echo "PowerShell command not found. Aborting." >&2; exit 1; } + type -P grep &>/dev/null || { echo "grep command not found. Aborting." >&2; exit 1; } + GITCMD=`PowerShell -command "Get-WmiObject win32_process -Filter \"name like '%git.exe'\" | select CommandLine"` + if $(echo $GITCMD | grep -q -- --amend); then + echo AMEND detected + touch ./.amend + fi +else + if $(ps -fp $PPID | grep -q -- --amend); then + echo AMEND detected + touch ./.amend + fi +fi diff --git a/_pre-commit.sh b/_pre-commit.sh index 1b6d1326..408b1842 100644 --- a/_pre-commit.sh +++ b/_pre-commit.sh @@ -6,44 +6,53 @@ # .git/hooks/ with the following content: # #!/bin/sh # if [ -x ./_pre-commit.sh ]; then -# source ./_pre-commit.sh +# . ./_pre-commit.sh # fi type -P sed &>/dev/null || { echo "sed command not found. Aborting." >&2; exit 1; } type -P git &>/dev/null || { echo "git command not found. Aborting." >&2; exit 1; } -VER=`git log --oneline | wc -l` +if [ -x ./_detect-amend.sh ]; then + . ./_detect-amend.sh +fi + +BUILD=`git rev-list HEAD --count` # adjust so that we match the github commit count -TAGVER=`expr $VER + 1` +((BUILD++)) # there may be a better way to prevent improper nano on amend. For now the detection # of a .amend file in the current directory will do if [ -f ./.amend ]; then - TAGVER=`expr $TAGVER - 1` + ((BUILD--)) rm ./.amend; fi -echo "setting nano to $TAGVER" +echo "setting nano to $BUILD" + +cat > _library.sed <<\_EOF +s/^[ \t]*FILEVERSION[ \t]*\(.*\),\(.*\),\(.*\),.*/ FILEVERSION \1,\2,\3,@@BUILD@@/ +s/^[ \t]*PRODUCTVERSION[ \t]*\(.*\),\(.*\),\(.*\),.*/ PRODUCTVERSION \1,\2,\3,@@BUILD@@/ +s/^\([ \t]*\)VALUE[ \t]*"FileVersion",[ \t]*"\(.*\)\..*"/\1VALUE "FileVersion", "\2.@@BUILD@@"/ +s/^\([ \t]*\)VALUE[ \t]*"ProductVersion",[ \t]*"\(.*\)\..*"/\1VALUE "ProductVersion", "\2.@@BUILD@@"/ +_EOF -cat > cmd.sed <<\_EOF -s/^[ \t]*FILEVERSION[ \t]*\(.*\),\(.*\),.*,0/ FILEVERSION \1,\2,@@TAGVER@@,0/ -s/^[ \t]*PRODUCTVERSION[ \t]*\(.*\),\(.*\),.*,0/ PRODUCTVERSION \1,\2,@@TAGVER@@,0/ -s/^\([ \t]*\)VALUE[ \t]*"FileVersion",[ \t]*"\(.*\)\..*"/\1VALUE "FileVersion", "\2.@@TAGVER@@"/ -s/^\([ \t]*\)VALUE[ \t]*"ProductVersion",[ \t]*"\(.*\)\..*"/\1VALUE "ProductVersion", "\2.@@TAGVER@@"/ -s/^\(.*\)"Zadig \(.*\)\..*"\(.*\)/\1"Zadig \2.@@TAGVER@@"\3/ +cat > _zadig.sed <<\_EOF +s/^[ \t]*FILEVERSION[ \t]*\(.*\),\(.*\),.*,0/ FILEVERSION \1,\2,@@BUILD@@,0/ +s/^[ \t]*PRODUCTVERSION[ \t]*\(.*\),\(.*\),.*,0/ PRODUCTVERSION \1,\2,@@BUILD@@,0/ +s/^\([ \t]*\)VALUE[ \t]*"FileVersion",[ \t]*"\(.*\)\..*"/\1VALUE "FileVersion", "\2.@@BUILD@@"/ +s/^\([ \t]*\)VALUE[ \t]*"ProductVersion",[ \t]*"\(.*\)\..*"/\1VALUE "ProductVersion", "\2.@@BUILD@@"/ +s/^\(.*\)"Zadig \(.*\)\..*"\(.*\)/\1"Zadig \2.@@BUILD@@"\3/ _EOF # First run sed to substitute our variable in the sed command file -sed -i -e "s/@@TAGVER@@/$TAGVER/g" cmd.sed +sed -i -e "s/@@BUILD@@/$BUILD/g" _library.sed +sed -i -e "s/@@BUILD@@/$BUILD/g" _zadig.sed # Run sed to update the nano version, and add the modified files -sed -i -f cmd.sed libwdi/libwdi.rc -sed -i 's/$/\r/' libwdi/libwdi.rc -sed -i -f cmd.sed examples/zadic.rc -sed -i 's/$/\r/' examples/zadic.rc -sed -i -f cmd.sed examples/zadig.rc -sed -i 's/$/\r/' examples/zadig.rc -sed -i -f cmd.sed examples/zadig.h -sed -i 's/$/\r/' examples/zadig.h -sed -i -f cmd.sed examples/wdi-simple.rc -sed -i 's/$/\r/' examples/wdi-simple.rc -git add libwdi/libwdi.rc examples/zadic.rc examples/zadig.rc examples/zadig.h examples/wdi-simple.rc -rm cmd.sed +sed -b -i -f _library.sed libwdi/libwdi.rc +sed -b -i -f _library.sed examples/wdi-simple.rc +# SED is an ass when it comes to replacing at the end of a line and preserving the EOL sequence +unix2dos -q libwdi/libwdi.rc +unix2dos -q examples/wdi-simple.rc +sed -b -i -f _zadig.sed examples/zadig.rc +sed -b -i -f _zadig.sed examples/zadig.h +rm _library.sed _zadig.sed +git add libwdi/libwdi.rc examples/zadig.rc examples/zadig.h examples/wdi-simple.rc diff --git a/_sign.cmd b/_sign.cmd index 7b74a33c..e8c149b3 100644 --- a/_sign.cmd +++ b/_sign.cmd @@ -1,6 +1,2 @@ @echo off -"C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool" sign /v /sha1 655f6413a8f721e3286ace95025c9e0ea132a984 /fd SHA1 /tr http://timestamp.comodoca.com/rfc3161 /td SHA1 %1 -if ERRORLEVEL 1 goto out -"C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool" sign /as /v /sha1 5759b23dc8f45e9120a7317f306e5b6890b612f0 /fd SHA256 /tr http://timestamp.comodoca.com/rfc3161 /td SHA256 %1 -:out -exit +"C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\signtool" sign /v /sha1 3dbc3a2a0e9ce8803b422cfdbc60acd33164965d /fd SHA256 /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 %1 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index f032f384..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,52 +0,0 @@ -os: Visual Studio 2017 - -init: - - ps: >- - if ($env:appveyor_repo_tag -eq "true") { - Update-AppveyorBuild -Version "$env:appveyor_repo_tag_name" - } else { - Update-AppveyorBuild -Version "dev-$($env:appveyor_repo_commit.substring(0,7))" - } - - git config --global core.autocrlf input - -environment: - global: - BITS: 32 - matrix: - - CONFIGURATION: Release - COMPILER: MinGW - PLATFORM: i686 - - CONFIGURATION: Release - COMPILER: MinGW - PLATFORM: x86_64 - - CONFIGURATION: Debug - COMPILER: MSVC - PLATFORM: Win32 - - CONFIGURATION: Debug - COMPILER: MSVC - PLATFORM: x64 - - CONFIGURATION: Release - COMPILER: MSVC - PLATFORM: Win32 - - CONFIGURATION: Release - COMPILER: MSVC - PLATFORM: x64 - -build: - project: libwdi.sln - parallel: true - verbosity: detailed - -install: - - curl -o wdk10-redist.7z -L http://files.akeo.ie/appveyor/libwdi/wdk10-redist.7z - - curl -o libusb-win32-bin-1.2.6.0.zip -L http://files.akeo.ie/appveyor/libwdi/libusb-win32-bin-1.2.6.0.zip - - curl -o libusbK-3.0.7.0-bin.7z -L http://files.akeo.ie/appveyor/libwdi/libusbK-3.0.7.0-bin.7z - - 7z x wdk10-redist.7z - - 7z x libusb-win32-bin-1.2.6.0.zip - - 7z x libusbK-3.0.7.0-bin.7z - - if [%PLATFORM%]==[x86_64] set BITS=64 - - if [%PLATFORM%]==[x86_64] set EXTRA_OPTS=--disable-32bit - -build_script: - - if [%COMPILER%]==[MSVC] msbuild libwdi.sln /m /p:Configuration=%CONFIGURATION%,Platform=%PLATFORM%,BuildMacros="WDK_DIR=\"c:/projects/libwdi/wdk\";LIBUSB0_DIR=\"c:/projects/libwdi/libusb-win32-bin-1.2.6.0\";LIBUSBK_DIR=\"c:/projects/libwdi/libusbK-3.0.7.0-bin/bin\"" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - - if [%COMPILER%]==[MinGW] C:\msys64\usr\bin\bash -lc "export PATH=/mingw%BITS%/bin:$PATH; cd /c/projects/libwdi; ./bootstrap.sh; ./configure --build=%PLATFORM%-w64-mingw32 --host=%PLATFORM%-w64-mingw32 --enable-toggable-debug --enable-examples-build --disable-debug --disable-shared %EXTRA_OPTS% --with-wdkdir=\"C:/Projects/libwdi/wdk\" --with-wdfver=1011 --with-libusb0=\"C:/Projects/libwdi/libusb-win32-bin-1.2.6.0\" --with-libusbk=\"C:/Projects/libwdi/libusbK-3.0.7.0-bin/bin\"; make -j4" diff --git a/autogen.sh b/autogen.sh index 69cf22de..0240a25f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -3,7 +3,7 @@ # rebuilds the Windows def file by exporting all LIBDWI API calls create_def() { - echo "rebuidling libwdi.def file" + echo "rebuilding libwdi.def file" echo 'LIBRARY "libwdi.dll"' > libwdi/libwdi.def echo "EXPORTS" >> libwdi/libwdi.def sed -n -e "s/.*LIBWDI_API.*\([[:blank:]]\)\(wdi.*\)(.*/ \2/p" libwdi/libwdi.c libwdi/vid_data.c libwdi/logging.c >> libwdi/libwdi.def @@ -23,6 +23,6 @@ create_def() set -e ./bootstrap.sh -./configure --enable-toggable-debug --enable-examples-build --disable-debug --with-wdkdir="C:/Program Files (x86)/Windows Kits/10" --with-wdfver=1011 --with-libusb0="D:/libusb-win32" --with-libusbk="D:/libusbK/bin" $* +./configure --enable-toggable-debug --enable-examples-build --disable-debug --with-wdkdir="C:/Program Files (x86)/Windows Kits/8.0" --with-wdfver=1011 --with-libusb0="D:/libusb-win32" --with-libusbk="D:/libusbK/bin" $* # rebuild .def, if sed is available type -P sed &>/dev/null && create_def diff --git a/configure.ac b/configure.ac index 297e8bbf..2ca98f2d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,16 +1,17 @@ -AC_INIT([libwdi], [1.3.0], [libwdi-devel@lists.sourceforge.net], [libwdi], [http://libwdi.akeo.ie]) +AC_INIT([libwdi],[1.3.1],[libwdi-devel@lists.sourceforge.net],[libwdi],[http://libwdi.akeo.ie]) AM_INIT_AUTOMAKE([-Wno-portability 1.11 foreign]) AC_CONFIG_SRCDIR([libwdi/libwdi.c]) AC_CONFIG_MACRO_DIR([m4]) -AM_CONFIG_HEADER([config.h]) +AC_CONFIG_HEADERS(config.h) # Enable silent build rules by default (Automake v1.11 or later). # Disable by either passing --disable-silent-rules to configure or passing V=1 to make m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])]) -AC_PREREQ([2.50]) +AC_PREREQ([2.71]) AC_PROG_CC -AC_PROG_LIBTOOL +AC_CHECK_TOOL(WINDRES, windres, :) +LT_INIT LT_LANG([Windows Resource]) AC_C_INLINE AM_PROG_CC_C_O @@ -65,14 +66,14 @@ case $host in create_import_lib="yes" LIBCONFIG_LIBADD="" LIBCONFIG_CFLAGS="" - AM_CFLAGS="-Wshadow" + AM_CFLAGS="-Wshadow -Wno-stringop-truncation" AM_LDFLAGS="-Wl,--add-stdcall-alias" ;; *) AC_MSG_ERROR([unsupported development environment]) esac -AM_CFLAGS="${AM_CFLAGS} -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0700" +AM_CFLAGS="${AM_CFLAGS} -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0700 -DCOBJMACROS" AM_LDFLAGS="${AM_LDFLAGS} -no-undefined -avoid-version" AM_CONDITIONAL([CREATE_IMPORT_LIB], [test "x$create_import_lib" = "xyes"]) @@ -108,19 +109,17 @@ CFLAGS="${saved_CFLAGS}" LDFLAGS="${saved_LDFLAGS}" cross_compiling=$saved_cross_compiling if test "x$cc_for_build_ok" != "xyes"; then - AC_ERROR([The build compiler cannot produce executables for this + AC_MSG_ERROR(The build compiler cannot produce executables for this platform. You might have to define the CC_FOR_BUILD environment variable. For instance, on 32 bit Windows, if using a multilib MinGW-w64 that defaults - to 64 bit executables, you would need: export CC_FOR_BUILD="gcc -m32"]) + to 64 bit executables, you would need: export CC_FOR_BUILD="gcc -m32") fi # 32 bit support saved_CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS} -m32" AC_MSG_CHECKING([whether the compiler can produce 32 bit binaries]) -AC_TRY_COMPILE([], [;], - [compiler_has_m32=yes], - [compiler_has_m32=no]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[;]])],[compiler_has_m32=yes],[compiler_has_m32=no]) if test "x$compiler_has_m32" == "xyes"; then AC_MSG_RESULT([yes]) else @@ -132,9 +131,7 @@ CFLAGS="${saved_CFLAGS}" saved_CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS} -m64" AC_MSG_CHECKING([whether the compiler can produce 64 bit binaries]) -AC_TRY_COMPILE([], [;], - [compiler_has_m64=yes], - [compiler_has_m64=no]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[;]])],[compiler_has_m64=yes],[compiler_has_m64=no]) if test "x$compiler_has_m64" == "xyes"; then AC_MSG_RESULT([yes]) else diff --git a/examples/.msvc/wdi-simple.vcxproj b/examples/.msvc/wdi-simple.vcxproj index d4ab42f2..703716d1 100644 --- a/examples/.msvc/wdi-simple.vcxproj +++ b/examples/.msvc/wdi-simple.vcxproj @@ -29,23 +29,23 @@ Application Unicode true - v141 + v143 Application Unicode - v141 + v143 Application Unicode true - v141 + v143 Application Unicode - v141 + v143 @@ -87,7 +87,7 @@ CompileAsC - setupapi.lib;newdev.lib;%(AdditionalDependencies) + setupapi.lib;newdev.lib;ntdll.lib;%(AdditionalDependencies) %(AdditionalLibraryDirectories) true $(TargetDir)$(ProjectName).pdb @@ -112,7 +112,7 @@ CompileAsC - setupapi.lib;newdev.lib;%(AdditionalDependencies) + setupapi.lib;newdev.lib;ntdll.lib;%(AdditionalDependencies) %(AdditionalLibraryDirectories) true $(TargetDir)$(ProjectName).pdb @@ -132,7 +132,7 @@ CompileAsC - setupapi.lib;newdev.lib;%(AdditionalDependencies) + setupapi.lib;newdev.lib;ntdll.lib;%(AdditionalDependencies) %(AdditionalLibraryDirectories) false Console @@ -157,7 +157,7 @@ CompileAsC - setupapi.lib;newdev.lib;%(AdditionalDependencies) + setupapi.lib;newdev.lib;ntdll.lib;%(AdditionalDependencies) %(AdditionalLibraryDirectories) false Console @@ -182,6 +182,10 @@ false + + + + diff --git a/examples/.msvc/wdi-simple.vcxproj.filters b/examples/.msvc/wdi-simple.vcxproj.filters index 28351fab..44c0e25f 100644 --- a/examples/.msvc/wdi-simple.vcxproj.filters +++ b/examples/.msvc/wdi-simple.vcxproj.filters @@ -8,6 +8,9 @@ {da31138d-56fc-4ef9-bea2-68f46be07623} + + {cac8a2f4-ad03-4bd7-9219-846a23f7392a} + @@ -19,4 +22,12 @@ Resource Files + + + Header Files + + + Header Files + + \ No newline at end of file diff --git a/examples/.msvc/wdi-simple_sources b/examples/.msvc/wdi-simple_sources deleted file mode 100644 index e2c0c601..00000000 --- a/examples/.msvc/wdi-simple_sources +++ /dev/null @@ -1,26 +0,0 @@ -TARGETNAME=wdi-simple -TARGETTYPE=PROGRAM -UMTYPE=console -UMENTRY=main - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -INCLUDES=..\msvc;..\libwdi;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - $(SDK_LIB_PATH)\shell32.lib \ - ..\libwdi\libwdi.lib \ - .\getopt\getopt.lib - -SXS_APPLICATION_MANIFEST=common_controls.manifest - -SOURCES=wdi-simple.c \ - wdi-simple.rc diff --git a/examples/.msvc/zadic.vcxproj b/examples/.msvc/zadic.vcxproj deleted file mode 100644 index 39b18a78..00000000 --- a/examples/.msvc/zadic.vcxproj +++ /dev/null @@ -1,190 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - zadic - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} - zadic - Win32Proj - - - - Application - Unicode - true - v141 - - - Application - Unicode - v141 - - - Application - Unicode - true - v141 - - - Application - Unicode - v141 - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Platform)\$(Configuration)\examples\ - $(SolutionDir)$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)$(Platform)\$(Configuration)\examples\ - $(SolutionDir)$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)$(Platform)\$(Configuration)\examples\ - $(SolutionDir)$(Platform)\$(Configuration)\examples\$(ProjectName)\ - $(SolutionDir)$(Platform)\$(Configuration)\examples\ - $(SolutionDir)$(Platform)\$(Configuration)\examples\$(ProjectName)\ - - - - $(IntDir)$(ProjectName).htm - - - ..\..\libwdi;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - CompileAsC - - - setupapi.lib;newdev.lib;%(AdditionalDependencies) - %(AdditionalLibraryDirectories) - RequireAdministrator - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - ..\..\libwdi;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDebug - Level3 - ProgramDatabase - CompileAsC - - - setupapi.lib;newdev.lib;%(AdditionalDependencies) - %(AdditionalLibraryDirectories) - RequireAdministrator - true - $(TargetDir)$(ProjectName).pdb - Console - MachineX64 - - - - - $(IntDir)$(ProjectName).htm - - - ..\..\libwdi;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - CompileAsC - - - setupapi.lib;newdev.lib;%(AdditionalDependencies) - %(AdditionalLibraryDirectories) - RequireAdministrator - false - Console - true - true - MachineX86 - - - - - $(IntDir)$(ProjectName).htm - - - X64 - - - ..\..\libwdi;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - Level3 - CompileAsC - - - setupapi.lib;newdev.lib;%(AdditionalDependencies) - %(AdditionalLibraryDirectories) - RequireAdministrator - false - Console - true - true - MachineX64 - - - - - - - - - - - {9aa0e745-1a0a-4700-8ecb-6a6de9dbf8b9} - false - - - {ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e} - false - - - - - - \ No newline at end of file diff --git a/examples/.msvc/zadic_sources b/examples/.msvc/zadic_sources deleted file mode 100644 index 4f9ea964..00000000 --- a/examples/.msvc/zadic_sources +++ /dev/null @@ -1,27 +0,0 @@ -TARGETNAME=zadic -TARGETTYPE=PROGRAM -UMTYPE=console -UMENTRY=main - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -INCLUDES=..\msvc;..\libwdi;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - $(SDK_LIB_PATH)\shell32.lib \ - ..\libwdi\libwdi.lib \ - .\getopt\getopt.lib - -# http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/ -SXS_APPLICATION_MANIFEST=elevation.manifest - -SOURCES=zadic.c \ - zadic.rc diff --git a/examples/.msvc/zadig.vcxproj b/examples/.msvc/zadig.vcxproj index 8ec04cbf..3fe452c1 100644 --- a/examples/.msvc/zadig.vcxproj +++ b/examples/.msvc/zadig.vcxproj @@ -29,23 +29,23 @@ Application Unicode true - v141 + v143 Application Unicode - v141 + v143 Application Unicode true - v141 + v143 Application Unicode - v141 + v143 @@ -80,7 +80,7 @@ ..\..\msvc;..\..\libwdi;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;COBJMACROS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug Level3 ProgramDatabase @@ -88,7 +88,7 @@ 4091 - setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;wininet.lib;ntdll.lib;%(AdditionalDependencies) RequireAdministrator true Windows @@ -104,7 +104,7 @@ ..\..\msvc;..\..\libwdi;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;COBJMACROS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug Level3 ProgramDatabase @@ -112,7 +112,7 @@ 4091 - setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;wininet.lib;ntdll.lib;%(AdditionalDependencies) RequireAdministrator true Windows @@ -125,7 +125,7 @@ ..\..\msvc;..\..\libwdi;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;COBJMACROS;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase @@ -133,7 +133,7 @@ 4091 - setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;wininet.lib;ntdll.lib;%(AdditionalDependencies) RequireAdministrator false Windows @@ -151,14 +151,14 @@ ..\..\msvc;..\..\libwdi;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;ISOLATION_AWARE_ENABLED;COBJMACROS;%(PreprocessorDefinitions) MultiThreaded Level3 CompileAsC 4091 - setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies) + setupapi.lib;comctl32.lib;wininet.lib;ntdll.lib;%(AdditionalDependencies) D:\libwdi\x64\Release\lib;%(AdditionalLibraryDirectories) RequireAdministrator false diff --git a/examples/.msvc/zadig_sources b/examples/.msvc/zadig_sources deleted file mode 100644 index 14f6bec2..00000000 --- a/examples/.msvc/zadig_sources +++ /dev/null @@ -1,32 +0,0 @@ -TARGETNAME=zadig -TARGETTYPE=PROGRAM -UMTYPE=windows -UMENTRY=winmain - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -INCLUDES=..\msvc;..\libwdi;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD /DISOLATION_AWARE_ENABLED - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - $(SDK_LIB_PATH)\shell32.lib \ - $(SDK_LIB_PATH)\uuid.lib \ - $(SDK_LIB_PATH)\wininet.lib \ - ..\libwdi\libwdi.lib \ - -# http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/ -SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest - -SOURCES=zadig.c \ - zadig_net.c \ - zadig_parser.c \ - zadig_stdlg.c \ - profile.c \ - zadig.rc diff --git a/examples/Makefile.am b/examples/Makefile.am index f4b9dae1..44c1f3db 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,31 +1,20 @@ AM_CPPFLAGS = -I$(top_srcdir) -noinst_PROGRAMS = zadic zadig wdi-simple +noinst_PROGRAMS = zadig wdi-simple -pkg_v_rc = $(pkg_v_rc_$(V)) -pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY)) -pkg_v_rc_0 = @echo " RC $@"; +AM_V_WINDRES_0 = @echo " RC $@";$(WINDRES) +AM_V_WINDRES_1 = $(WINDRES) +AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY)) +AM_V_WINDRES = $(AM_V_WINDRES_$(V)) -zadic_rc.o: zadic.rc - $(pkg_v_rc)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(ARCH_RCFLAGS) -i $< -o $@ - -zadic_SOURCES = zadic.c -zadic_CFLAGS = -I../libwdi $(ARCH_CFLAGS) $(AM_CFLAGS) -# static ensures that the exe can be shared as a standalone, and still allow driver installation -zadic_LDFLAGS = $(AM_LDFLAGS) -static -zadic_LDADD = zadic_rc.o -L../libwdi/.libs -lwdi - -zadig_rc.o: zadig.rc zadig_resource.h - $(pkg_v_rc)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(ARCH_RCFLAGS) -i $< -o $@ +%_rc.o: %.rc + $(AM_V_WINDRES) $(AM_RCFLAGS) -i $< -o $@ zadig_SOURCES = zadig.c zadig_net.c zadig_parser.c zadig_stdlg.c profile.c zadig_CFLAGS = -I../libwdi $(ARCH_CFLAGS) $(AM_CFLAGS) zadig_LDFLAGS = -mwindows $(AM_LDFLAGS) -static zadig_LDADD = zadig_rc.o -L../libwdi/.libs -lwdi -lwininet -luuid -lcomctl32 -wdi-simple_rc.o: wdi-simple.rc - $(pkg_v_rc)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(ARCH_RCFLAGS) -i $< -o $@ - wdi_simple_SOURCES = wdi-simple.c wdi_simple_CFLAGS = -I../libwdi $(ARCH_CFLAGS) $(AM_CFLAGS) wdi_simple_LDFLAGS = $(AM_LDFLAGS) -static diff --git a/examples/getopt/.msvc/getopt.vcproj b/examples/getopt/.msvc/getopt.vcproj deleted file mode 100644 index ecbe9c27..00000000 --- a/examples/getopt/.msvc/getopt.vcproj +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/getopt/.msvc/getopt.vcxproj b/examples/getopt/.msvc/getopt.vcxproj index 847fa18c..e09f2663 100644 --- a/examples/getopt/.msvc/getopt.vcxproj +++ b/examples/getopt/.msvc/getopt.vcxproj @@ -27,23 +27,23 @@ StaticLibrary Unicode true - v141 + v143 StaticLibrary Unicode - v141 + v143 StaticLibrary Unicode true - v141 + v143 StaticLibrary Unicode - v141 + v143 @@ -75,7 +75,6 @@ HAVE_STRING_H;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true MultiThreadedDebug Level3 ProgramDatabase diff --git a/examples/getopt/.msvc/getopt_sources b/examples/getopt/.msvc/getopt_sources deleted file mode 100644 index 3bc533df..00000000 --- a/examples/getopt/.msvc/getopt_sources +++ /dev/null @@ -1,17 +0,0 @@ -TARGETTYPE=LIBRARY -TARGETNAME=getopt - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -INCLUDES=$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD /DHAVE_STRING_H - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib - -SOURCES=getopt1.c \ - getopt.c diff --git a/examples/profile.c b/examples/profile.c index e4793c4a..20cd976d 100644 --- a/examples/profile.c +++ b/examples/profile.c @@ -770,7 +770,7 @@ long profile_create_node(const char *name, const char *value, } /* - * This function verifies that all of the representation invarients of + * This function verifies that all of the representation invariants of * the profile are true. If not, we have a programming bug somewhere, * probably in this file. */ @@ -849,7 +849,7 @@ long profile_add_node(struct profile_node *section, const char *name, /* * Iterate through the section, returning the nodes which match - * the given name. If name is NULL, then interate through all the + * the given name. If name is NULL, then iterate through all the * nodes in the section. If section_flag is non-zero, only return the * section which matches the name; don't return relations. If value * is non-NULL, then only return relations which match the requested @@ -1382,7 +1382,7 @@ const char* profile_errtostr(long error_code) case PROF_BAD_LINK_LIST: return "Bad linked list in profile structures"; case PROF_BAD_GROUP_LVL: - return "Bad group level in profile strctures"; + return "Bad group level in profile structures"; case PROF_BAD_PARENT_PTR: return "Bad parent pointer in profile structures"; case PROF_MAGIC_ITERATOR: diff --git a/examples/wdi-simple.c b/examples/wdi-simple.c index cc942557..b3496d22 100644 --- a/examples/wdi-simple.c +++ b/examples/wdi-simple.c @@ -1,6 +1,6 @@ /* * wdi-simple.c: Console Driver Installer for a single USB device -* Copyright (c) 2010-2016 Pete Batard +* Copyright (c) 2010-2021 Pete Batard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -62,6 +62,8 @@ void usage(void) printf(" one (WinUSB, libusb-win32 or libusbK only)\n"); printf(" --filter use the libusb-win32 filter driver (requires -t1)\n"); printf("-d, --dest set the extraction directory\n"); + printf("-e, --external use the external inf specified by as source\n"); + printf(" (overrides the internal embedded inf)\n"); printf("-x, --extract extract files only (don't install)\n"); printf("-c, --cert install certificate from the\n"); printf(" embedded user files as a trusted publisher\n"); @@ -69,8 +71,8 @@ void usage(void) printf("-s, --silent silent mode\n"); printf("-b, --progressbar=[HWND] display a progress bar during install\n"); printf(" an optional HWND can be specified\n"); - printf("-o, --timeout timeout (in millis) to wait for any pending installations\n"); - printf("-l, --log set log level (0 = debug, 4 = none)\n"); + printf("-o, --timeout set a timeout (in ms) to wait for any pending installations\n"); + printf("-l, --log set log level (0=debug, 4=none)\n"); printf("-h, --help display usage\n"); printf("\n"); } @@ -123,6 +125,7 @@ int __cdecl main(int argc, char** argv) {"progressbar", optional_argument, 0, 'b'}, {"log", required_argument, 0, 'l'}, {"timeout", required_argument, 0, 'o'}, + {"external", required_argument, 0, 'e'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; @@ -134,7 +137,7 @@ int __cdecl main(int argc, char** argv) while(1) { - c = getopt_long(argc, argv, "n:f:m:d:c:v:p:i:l:t:o:hxsb", long_options, NULL); + c = getopt_long(argc, argv, "bc:d:e:f:hi:l:m:n:o:p:st:v:wx", long_options, NULL); if (c == -1) break; switch(c) { @@ -144,23 +147,39 @@ int __cdecl main(int argc, char** argv) case 2: // --filter oid.install_filter_driver = TRUE; break; - case 'n': - dev.desc = optarg; + case 'b': + oid.hWnd = (optarg) ? (HWND)(uintptr_t)strtol(optarg, NULL, 0) : GetConsoleHwnd(); + oic.hWnd = oid.hWnd; break; - case 'm': - opd.vendor_name = optarg; + case 'c': + cert_name = optarg; + break; + case 'd': + ext_dir = optarg; + break; + case 'e': + inf_name = optarg; + opd.external_inf = TRUE; break; case 'f': inf_name = optarg; break; - case 'd': - ext_dir = optarg; + case 'h': + usage(); + exit(0); break; - case 'c': - cert_name = optarg; + case 'i': + dev.is_composite = TRUE; + dev.mi = (unsigned char)strtol(optarg, NULL, 0); break; - case 'v': - dev.vid = (unsigned short)strtol(optarg, NULL, 0); + case 'l': + log_level = (int)strtol(optarg, NULL, 0); + break; + case 'm': + opd.vendor_name = optarg; + break; + case 'n': + dev.desc = optarg; break; case 'o': oid.pending_install_timeout = (DWORD)strtoul(optarg, NULL, 0); @@ -168,34 +187,22 @@ int __cdecl main(int argc, char** argv) case 'p': dev.pid = (unsigned short)strtol(optarg, NULL, 0); break; - case 'i': - dev.is_composite = TRUE; - dev.mi = (unsigned char)strtol(optarg, NULL, 0); + case 's': + opt_silent = 1; + log_level = WDI_LOG_LEVEL_NONE; break; case 't': opd.driver_type = (int)strtol(optarg, NULL, 0); break; + case 'v': + dev.vid = (unsigned short)strtol(optarg, NULL, 0); + break; case 'w': opd.use_wcid_driver = TRUE; break; - case 'h': - usage(); - exit(0); - break; case 'x': opt_extract = 1; break; - case 's': - opt_silent = 1; - log_level = WDI_LOG_LEVEL_NONE; - break; - case 'b': - oid.hWnd = (optarg)?(HWND)strtol(optarg, NULL, 0):GetConsoleHwnd(); - oic.hWnd = oid.hWnd; - break; - case 'l': - log_level = (int)strtol(optarg, NULL, 0); - break; default: usage(); exit(0); @@ -223,7 +230,8 @@ int __cdecl main(int argc, char** argv) if (wdi_create_list(&ldev, &ocl) == WDI_SUCCESS) { r = WDI_SUCCESS; for (; (ldev != NULL) && (r == WDI_SUCCESS); ldev = ldev->next) { - if ( (ldev->vid == dev.vid) && (ldev->pid == dev.pid) && (ldev->mi == dev.mi) ) { + if ( (ldev->vid == dev.vid) && (ldev->pid == dev.pid) && (ldev->mi == dev.mi) &&(ldev->is_composite == dev.is_composite) ) { + dev.hardware_id = ldev->hardware_id; dev.device_id = ldev->device_id; matching_device_found = TRUE; diff --git a/examples/wdi-simple.iss b/examples/wdi-simple.iss index d13c796f..f87f0ff0 100644 --- a/examples/wdi-simple.iss +++ b/examples/wdi-simple.iss @@ -1,5 +1,5 @@ ; This examples demonstrates how libwdi can be used in an installer script -; to automatically intall USB drivers along with your application. +; to automatically install USB drivers along with your application. ; ; Requirements: Inno Setup (http://www.jrsoftware.org/isdl.php) ; @@ -23,7 +23,7 @@ SolidCompression = yes ; Win2000 or higher MinVersion = 5,5 -; This installation requires admin priviledges. This is needed to install +; This installation requires admin privileges. This is needed to install ; drivers on windows vista and later. PrivilegesRequired = admin @@ -45,7 +45,7 @@ Name: "{group}\Uninstall YourApplication"; Filename: "{uninstallexe}" ; -p, --pid set the product ID (PID) ; -i, --iid set the interface ID (MI) ; -t, --type set the driver to install -; (0=WinUSB, 1=libusb0, 2=libusbK, 3=custom) +; (0=WinUSB, 1=libusb0, 2=libusbK, 3=usbser, 4=custom) ; -d, --dest set the extraction directory ; -x, --extract extract files only (don't install) ; -c, --cert install certificate from the @@ -54,8 +54,10 @@ Name: "{group}\Uninstall YourApplication"; Filename: "{uninstallexe}" ; -s, --silent silent mode ; -b, --progressbar=[HWND] display a progress bar during install ; an optional HWND can be specified -; -l, --log set log level (0 = debug, 4 = none) +; -o, --timeout set timeout (in ms) to wait for any +; pending installations +; -l, --log set log level (0=debug, 4=none) ; -h, --help display usage ; -Filename: "{app}\wdi-simple.exe"; Flags: "runhidden"; Parameters: " --name ""XBox Controller"" --vid 0x045e --pid 0x0289 --progressbar={wizardhwnd}"; StatusMsg: "Installing YourApplication driver (this may take a few seconds) ..."; +Filename: "{app}\wdi-simple.exe"; Flags: "runhidden"; Parameters: " --name ""XBox Controller"" --vid 0x045e --pid 0x0289 --progressbar={wizardhwnd} --timeout 120000"; StatusMsg: "Installing YourApplication driver (this may take a few seconds) ..."; diff --git a/examples/wdi-simple.nsi b/examples/wdi-simple.nsi index 27d707bb..9039bb18 100644 --- a/examples/wdi-simple.nsi +++ b/examples/wdi-simple.nsi @@ -1,5 +1,5 @@ ; This examples demonstrates how libwdi can be used in an installer script -; to automatically intall USB drivers along with your application. +; to automatically install USB drivers along with your application. ; ; Requirements: Nullsoft Scriptable Install System (http://nsis.sourceforge.net/) ; @@ -53,7 +53,7 @@ SectionEnd ; -p, --pid set the product ID (PID) ; -i, --iid set the interface ID (MI) ; -t, --type set the driver to install -; (0=WinUSB, 1=libusb0, 2=libusbK, 3=custom) +; (0=WinUSB, 1=libusb0, 2=libusbK, 3=usbser, 4=custom) ; -d, --dest set the extraction directory ; -x, --extract extract files only (don't install) ; -c, --cert install certificate from the @@ -62,11 +62,13 @@ SectionEnd ; -s, --silent silent mode ; -b, --progressbar=[HWND] display a progress bar during install ; an optional HWND can be specified -; -l, --log set log level (0 = debug, 4 = none) +; -o, --timeout set timeout (in ms) to wait for any +; pending installations +; -l, --log set log level (0=debug, 4=none) ; -h, --help display usage Section "wdi-simple" DetailPrint "Running $INSTDIR\wdi-simple.exe" - nsExec::ExecToLog '"$INSTDIR\wdi-simple.exe" --name "XBox Controller" --vid 0x045e --pid 0x0289 --progressbar=$HWNDPARENT' + nsExec::ExecToLog '"$INSTDIR\wdi-simple.exe" --name "XBox Controller" --vid 0x045e --pid 0x0289 --progressbar=$HWNDPARENT --timeout 120000' SectionEnd ; Uninstaller diff --git a/examples/wdi-simple.rc b/examples/wdi-simple.rc index 93d09161..376f8417 100644 --- a/examples/wdi-simple.rc +++ b/examples/wdi-simple.rc @@ -7,8 +7,8 @@ #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,709,0 - PRODUCTVERSION 1,3,709,0 + FILEVERSION 1,5,1,788 + PRODUCTVERSION 1,5,1,788 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -25,13 +25,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "WDI-Simple" - VALUE "FileVersion", "1.3.709" + VALUE "FileVersion", "1.5.1.788" VALUE "InternalName", "WDI-Simple" - VALUE "LegalCopyright", "© 2010-2017 Pete Batard (LGPL v3)" - VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/lesser.html" + VALUE "LegalCopyright", "� 2010-2023 Pete Batard (LGPL v3)" + VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/lesser.html" VALUE "OriginalFilename", "wdi-simple.exe" VALUE "ProductName", "WDI-Simple" - VALUE "ProductVersion", "1.3.709" + VALUE "ProductVersion", "1.5.1.788" VALUE "Comments", "http://libwdi.akeo.ie" END END diff --git a/examples/zadic.c b/examples/zadic.c deleted file mode 100644 index 84e4ee59..00000000 --- a/examples/zadic.c +++ /dev/null @@ -1,214 +0,0 @@ - -/* -* Zadic: Automated Driver Installer for USB devices (Console version) -* Copyright (c) 2010-2016 Pete Batard -* Copyright (c) 2015 PhracturedBlue <6xtc2h7upj@snkmail.com> -* Copyright (c) 2010 Joseph Marshall -* -* 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -* WARNING: if any part of the resulting executable name contains "setup" or "instal(l)" -* it will require UAC elevation on Vista and later, and, when run from an MSYS shell, -* will produce a "sh: Bad file number" message. -* See the paragraph on Automatic Elevation at http://helpware.net/VistaCompat.htm -*/ - -#include -#include -#include -#ifdef _MSC_VER -#include "getopt/getopt.h" -#else -#include -#endif -#include "libwdi.h" - -#define FLUSHER while(getchar() != 0x0A) -#define INF_NAME "libusb_device.inf" - -void usage(void) -{ - printf("\n"); - printf("--noprompt allows the program to end without prompting the user\n"); - printf("--usealldevices lists all usb devices instead of only driverless ones\n"); - printf("--iface sets the interface number\n"); - printf("--vid sets the VID number. You must put 0x infront of vid number\n"); - printf("--pid sets the PID number. You must put 0x infront of pid number\n"); - printf("--useinf use supplied .inf if it exists in the correct directory\n"); - printf("--create create device even if USB device is not attached. Requires a description\n"); - printf("\n"); -} - -// The following is necessary when compiled from a WDK/DDK environment -int __cdecl main(int argc, char *argv[]) -{ - int c; - struct wdi_device_info *device, *list; - char* path = "usb_driver"; - static struct wdi_options_create_list cl_options = { 0 }; - static struct wdi_options_prepare_driver pd_options = { 0 }; - - static int prompt_flag = 1; - static unsigned char iface = 0; - static unsigned short vid = 0, pid = 0; - static int verbose_flag = 3; - static char *desc = NULL; - static int use_supplied_inf_flag = 0; - int r = WDI_ERROR_OTHER, option_index = 0; - - cl_options.trim_whitespaces = TRUE; - - // Parse command-line options - while(1) - { - static struct option long_options[] = { - // These options set a flag. - {"noprompt", no_argument, &prompt_flag, 0}, - {"usealldevices", no_argument, &cl_options.list_all, 1}, - {"useinf", no_argument, &use_supplied_inf_flag, 1}, - {"iface", required_argument, 0, 'a'}, - {"vid", required_argument, 0, 'b'}, - {"pid", required_argument, 0, 'c'}, - {"help", no_argument, 0, 'd'}, - {"verbose", no_argument, &verbose_flag, 0}, - {"create", required_argument,0, 'e'}, - {0, 0, 0, 0} - }; - - c = getopt_long(argc, argv, "abc:d:e:",long_options, &option_index); - // Detect the end of the options. - if (c == -1) - break; - - switch(c) - { - case 0: - // If this option set a flag, do nothing else now. - if (long_options[option_index].flag != 0) { - break; - } - printf("option %s", long_options[option_index].name); - if (optarg) { - printf (" with arg %s", optarg); - } - printf("\n"); - break; - case 'a': - iface = (unsigned char)atoi(optarg); - printf("OPT: interface number %d\n", iface); - break; - case 'b': - vid = (unsigned short)strtol(optarg, NULL, 0); - printf("OPT: VID number %d\n", vid); - break; - case 'c': - pid = (unsigned short)strtol(optarg, NULL, 0); - printf("OPT: PID number %d\n", pid); - break; - case 'd': // getopt_long already printed an error message. - usage(); - exit(0); - break; - case 'e': //create requires a description argument - desc = optarg; - break; - default: - usage(); - abort(); - } - } - - if (desc) { - // If the device is created from scratch, override the existing device - if (vid == 0 || pid == 0) { - printf("Must specify both --vid and --pid with --create\n"); - return 1; - } - device = (struct wdi_device_info*)calloc(1, sizeof(struct wdi_device_info)); - if (device == NULL) { - printf("could not create new device_info struct for installation"); - return 1; - } - device->desc = desc; - device->vid = vid; - device->pid = pid; - printf("Creating USB device: device: \"%s\" (%04X:%04X)\n", device->desc, device->vid, device->pid); - wdi_set_log_level(verbose_flag); - if (wdi_prepare_driver(device, path, INF_NAME, &pd_options) == WDI_SUCCESS) { - printf("installing wdi driver with <%s> at <%s>\n", INF_NAME, path); - r = wdi_install_driver(device, path, INF_NAME, NULL); - if (r != WDI_SUCCESS) { - printf("Failed to install driver: %s\n", wdi_strerror(r)); - } - } - free(device); - return (r == WDI_SUCCESS) ? 0 : 1; - } - - r = wdi_create_list(&list, &cl_options); - switch (r) { - case WDI_SUCCESS: - break; - case WDI_ERROR_NO_DEVICE: - printf("No driverless USB devices were found.\n"); - return 0; - default: - printf("wdi_create_list: error %s\n", wdi_strerror(r)); - return 0; - } - - for (device = list; device != NULL; device = device->next) { - printf("Found USB device: \"%s\" (%04X:%04X)\n", device->desc, device->vid, device->pid); - wdi_set_log_level(verbose_flag); - // If vid and pid have not been initialized - // prompt user to install driver for each device - if (vid == 0 || pid == 0) { - printf("Do you want to install a driver for this device (y/n)?\n"); - c = (char) getchar(); - FLUSHER; - if ((c != 'y') && (c != 'Y')) { - continue; - } - // Otherwise a specific vid and pid have been given - // so drivers will install automatically - } else { - // Is VID and PID a match for our device - if ( (device->vid != vid) || (device->pid != pid) - || (device->mi != iface) ) { - continue; - } - } - // Does the user want to use a supplied .inf - if (use_supplied_inf_flag == 0) { - if (wdi_prepare_driver(device, path, INF_NAME, &pd_options) == WDI_SUCCESS) { - printf("installing wdi driver with <%s> at <%s>\n",INF_NAME, path); - wdi_install_driver(device, path, INF_NAME, NULL); - } - } else { - printf("installing wdi driver with <%s> at <%s>\n",INF_NAME, path); - wdi_install_driver(device, path, INF_NAME, NULL); - } - } - wdi_destroy_list(list); - - // This is needed when ran in UAC mode - if (prompt_flag) { - printf("\nPress Enter to exit this program\n"); - FLUSHER; - } - return 0; -} diff --git a/examples/zadic.rc b/examples/zadic.rc deleted file mode 100644 index 33efab6f..00000000 --- a/examples/zadic.rc +++ /dev/null @@ -1,112 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "zadic_resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "zadic_resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "// Must reference a manifest for visual styles and elevation\r\n" - "// Oh, and it must happen at the end, or MinGW will ignore it!\r\n" - "#if defined(__GNUC__)\r\n" - "CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""elevation.manifest""\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,709,0 - PRODUCTVERSION 1,3,709,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "CompanyName", "akeo.ie" - VALUE "FileDescription", "Zadic" - VALUE "FileVersion", "1.3.709" - VALUE "InternalName", "Zadic" - VALUE "LegalCopyright", "© 2010-2017 Pete Batard (LGPL v3)" - VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/lesser.html" - VALUE "OriginalFilename", "zadic.exe" - VALUE "ProductName", "Zadic" - VALUE "ProductVersion", "1.3.709" - VALUE "Comments", "http://libwdi.akeo.ie" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END - -#endif // English resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - -// Must reference a manifest for visual styles and elevation -// Oh, and it must happen at the end, or MinGW will ignore it! -#if defined(__GNUC__) -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "elevation.manifest" -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/examples/zadic_resource.h b/examples/zadic_resource.h deleted file mode 100644 index c353fbce..00000000 --- a/examples/zadic_resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by zadic.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/examples/zadig.c b/examples/zadig.c index d590b1fc..c1048f9e 100644 --- a/examples/zadig.c +++ b/examples/zadig.c @@ -1,6 +1,6 @@ /* * Zadig: Automated Driver Installer for USB devices (GUI version) - * Copyright (c) 2010-2017 Pete Batard + * Copyright (c) 2010-2023 Pete Batard * For more info, please visit http://libwdi.akeo.ie * * This program is free software: you can redistribute it and/or modify @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -61,7 +62,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,15 +81,17 @@ 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" }; +const char* driver_name[WDI_NB_DRIVERS] = { "WinUSB", "libusb0", "libusbK", "usbser", "custom" }; struct wdi_options_create_list cl_options = { 0 }; struct wdi_options_prepare_driver pd_options = { 0 }; struct wdi_options_install_cert ic_options = { 0 }; struct wdi_options_install_driver id_options = { 0 }; struct wdi_device_info *device, *list = NULL; int current_device_index = CB_ERR; +int windows_version = WINDOWS_UNDEFINED; +char windows_version_str[128]; char* current_device_hardware_id = NULL; char* editable_desc = NULL; int default_driver_type = WDI_WINUSB; @@ -109,6 +112,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 +142,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 +165,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 +178,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 +262,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 +328,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 +369,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 +379,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 +422,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,13 +442,13 @@ 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]); if (filter_is_displayed) { - // Always perform delete + display for Delete <-> Install toggle after successfull install/delete + // Always perform delete + display for Delete <-> Install toggle after successful install/delete DeleteMenu(hMenuSplit, IDM_SPLIT_FILTER, MF_BYCOMMAND); if (display) { InsertMenuItemA(hMenuSplit, IDM_SPLIT_EXTRACT, FALSE, &mi_filter); @@ -472,7 +477,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 { @@ -483,12 +488,14 @@ void set_default_driver(void) { void set_driver(void) { VS_FIXEDFILEINFO file_info; - char target_text[64]; + char target_text[64] = { 0 }; if ((pd_options.driver_type == WDI_CDC) || (pd_options.driver_type >= WDI_USER)) { - safe_sprintf(target_text, 64, "%s", driver_display_name[pd_options.driver_type]); - EnableMenuItem(hMenuOptions, IDM_CREATECAT, MF_GRAYED); - EnableMenuItem(hMenuOptions, IDM_SIGNCAT, MF_GRAYED); + if (pd_options.driver_type < WDI_NB_DRIVERS) { + static_sprintf(target_text, "%s", driver_display_name[pd_options.driver_type]); + EnableMenuItem(hMenuOptions, IDM_CREATECAT, MF_GRAYED); + EnableMenuItem(hMenuOptions, IDM_SIGNCAT, MF_GRAYED); + } } else { EnableMenuItem(hMenuOptions, IDM_CREATECAT, MF_ENABLED); EnableMenuItem(hMenuOptions, IDM_SIGNCAT, pd_options.disable_cat?MF_GRAYED:MF_ENABLED); @@ -496,16 +503,16 @@ void set_driver(void) target_driver_version = file_info.dwFileVersionMS; target_driver_version <<= 32; target_driver_version += file_info.dwFileVersionLS; - safe_sprintf(target_text, 64, "%s (v%d.%d.%d.%d)", driver_display_name[pd_options.driver_type], + static_sprintf(target_text, "%s (v%d.%d.%d.%d)", driver_display_name[pd_options.driver_type], (int)file_info.dwFileVersionMS >> 16, (int)file_info.dwFileVersionMS & 0xFFFF, (int)file_info.dwFileVersionLS >> 16, (int)file_info.dwFileVersionLS & 0xFFFF); pd_options.use_wcid_driver = (nb_devices < 0) || ((has_wcid == WCID_TRUE) && (pd_options.driver_type == wcid_type)); } else { - safe_sprintf(target_text, 64, "%s", driver_display_name[pd_options.driver_type]); + static_sprintf(target_text, "%s", driver_display_name[pd_options.driver_type]); } } - SetDlgItemTextA(hMain, IDC_TARGET, target_text); + SetDlgItemTextA(hMainDialog, IDC_TARGET, target_text); } @@ -539,14 +546,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 +575,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 +613,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 +622,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 +646,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 +688,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 +735,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 +755,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); } } @@ -794,8 +801,8 @@ 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); + static_sprintf(label, "%s %s%s", action, qualifier, object); + SetDlgItemTextA(hMainDialog, IDC_INSTALL, label); } // Change the log level @@ -807,6 +814,308 @@ void set_loglevel(DWORD menu_cmd) wdi_set_log_level(log_level); } +static __inline USHORT get_application_arch(void) +{ +#if defined(_M_AMD64) + return IMAGE_FILE_MACHINE_AMD64; +#elif defined(_M_IX86) + return IMAGE_FILE_MACHINE_I386; +#elif defined(_M_ARM64) + return IMAGE_FILE_MACHINE_ARM64; +#elif defined(_M_ARM) + return IMAGE_FILE_MACHINE_ARM; +#else + return IMAGE_FILE_MACHINE_UNKNOWN; +#endif +} + +static __inline const char* get_arch_name(USHORT uArch) +{ + switch (uArch) { + case IMAGE_FILE_MACHINE_AMD64: + return "x64"; + case IMAGE_FILE_MACHINE_I386: + return "x86"; + case IMAGE_FILE_MACHINE_ARM64: + return "arm64"; + case IMAGE_FILE_MACHINE_ARM: + return "arm"; + default: + return "unknown"; + } +} + +// Detect the underlying platform arch. +static USHORT get_platform_arch(void) +{ + BOOL is_64bit = FALSE, is_wow64 = FALSE; + USHORT ProcessMachine = IMAGE_FILE_MACHINE_UNKNOWN, NativeMachine = IMAGE_FILE_MACHINE_UNKNOWN; + + PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process2, (HANDLE, USHORT*, USHORT*)); + PF_INIT(IsWow64Process2, Kernel32); + + if ((pfIsWow64Process2 == NULL) || + !pfIsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine)) { + // Assume same arch as the app + NativeMachine = get_application_arch(); + // Fix the Arch if we have a 32-bit app running under WOW64 + if ((sizeof(uintptr_t) < 8) && IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64) { + if (NativeMachine == IMAGE_FILE_MACHINE_I386) + NativeMachine = IMAGE_FILE_MACHINE_AMD64; + else if (NativeMachine == IMAGE_FILE_MACHINE_ARM) + NativeMachine = IMAGE_FILE_MACHINE_ARM64; + else // I sure wanna be made aware of this scenario... + assert(FALSE); + } + dprintf("Note: Underlying Windows architecture was guessed and may be incorrect..."); + } + + return NativeMachine; +} + +static const char* get_edition(DWORD ProductType) +{ + static char unknown_edition_str[64]; + + // From: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getproductinfo + // These values can be found in the winnt.h header. + switch (ProductType) { + case 0x00000000: return ""; // Undefined + case 0x00000001: return "Ultimate"; + case 0x00000002: return "Home Basic"; + case 0x00000003: return "Home Premium"; + case 0x00000004: return "Enterprise"; + case 0x00000005: return "Home Basic N"; + case 0x00000006: return "Business"; + case 0x00000007: return "Server Standard"; + case 0x00000008: return "Server Datacenter"; + case 0x00000009: return "Smallbusiness Server"; + case 0x0000000A: return "Server Enterprise"; + case 0x0000000B: return "Starter"; + case 0x0000000C: return "Server Datacenter (Core)"; + case 0x0000000D: return "Server Standard (Core)"; + case 0x0000000E: return "Server Enterprise (Core)"; + case 0x00000010: return "Business N"; + case 0x00000011: return "Web Server"; + case 0x00000012: return "HPC Edition"; + case 0x00000013: return "Storage Server (Essentials)"; + case 0x0000001A: return "Home Premium N"; + case 0x0000001B: return "Enterprise N"; + case 0x0000001C: return "Ultimate N"; + case 0x00000022: return "Home Server"; + case 0x00000024: return "Server Standard without Hyper-V"; + case 0x00000025: return "Server Datacenter without Hyper-V"; + case 0x00000026: return "Server Enterprise without Hyper-V"; + case 0x00000027: return "Server Datacenter without Hyper-V (Core)"; + case 0x00000028: return "Server Standard without Hyper-V (Core)"; + case 0x00000029: return "Server Enterprise without Hyper-V (Core)"; + case 0x0000002A: return "Hyper-V Server"; + case 0x0000002F: return "Starter N"; + case 0x00000030: return "Pro"; + case 0x00000031: return "Pro N"; + case 0x00000034: return "Server Solutions Premium"; + case 0x00000035: return "Server Solutions Premium (Core)"; + case 0x00000040: return "Server Hyper Core V"; + case 0x00000042: return "Starter E"; + case 0x00000043: return "Home Basic E"; + case 0x00000044: return "Premium E"; + case 0x00000045: return "Pro E"; + case 0x00000046: return "Enterprise E"; + case 0x00000047: return "Ultimate E"; + case 0x00000048: return "Enterprise (Eval)"; + case 0x0000004F: return "Server Standard (Eval)"; + case 0x00000050: return "Server Datacenter (Eval)"; + case 0x00000054: return "Enterprise N (Eval)"; + case 0x00000057: return "Thin PC"; + case 0x00000058: case 0x00000059: case 0x0000005A: case 0x0000005B: case 0x0000005C: return "Embedded"; + case 0x00000062: return "Home N"; + case 0x00000063: return "Home China"; + case 0x00000064: return "Home Single Language"; + case 0x00000065: return "Home"; + case 0x00000067: return "Pro with Media Center"; + case 0x00000069: case 0x0000006A: case 0x0000006B: case 0x0000006C: return "Embedded"; + case 0x0000006F: return "Home Connected"; + case 0x00000070: return "Pro Student"; + case 0x00000071: return "Home Connected N"; + case 0x00000072: return "Pro Student N"; + case 0x00000073: return "Home Connected Single Language"; + case 0x00000074: return "Home Connected China"; + case 0x00000079: return "Education"; + case 0x0000007A: return "Education N"; + case 0x0000007D: return "Enterprise LTSB"; + case 0x0000007E: return "Enterprise LTSB N"; + case 0x0000007F: return "Pro S"; + case 0x00000080: return "Pro S N"; + case 0x00000081: return "Enterprise LTSB (Eval)"; + case 0x00000082: return "Enterprise LTSB N (Eval)"; + case 0x0000008A: return "Pro Single Language"; + case 0x0000008B: return "Pro China"; + case 0x0000008C: return "Enterprise Subscription"; + case 0x0000008D: return "Enterprise Subscription N"; + case 0x00000091: return "Server Datacenter SA (Core)"; + case 0x00000092: return "Server Standard SA (Core)"; + case 0x00000095: return "Utility VM"; + case 0x000000A1: return "Pro for Workstations"; + case 0x000000A2: return "Pro for Workstations N"; + case 0x000000A4: return "Pro for Education"; + case 0x000000A5: return "Pro for Education N"; + case 0x000000AB: return "Enterprise G"; // I swear Microsoft are just making up editions... + case 0x000000AC: return "Enterprise G N"; + case 0x000000B2: return "Cloud"; + case 0x000000B3: return "Cloud N"; + case 0x000000B6: return "Home OS"; + case 0x000000B7: case 0x000000CB: return "Cloud E"; + case 0x000000B9: return "IoT OS"; + case 0x000000BA: case 0x000000CA: return "Cloud E N"; + case 0x000000BB: return "IoT Edge OS"; + case 0x000000BC: return "IoT Enterprise"; + case 0x000000BD: return "Lite"; + case 0x000000BF: return "IoT Enterprise S"; + case 0x000000C0: case 0x000000C2: case 0x000000C3: case 0x000000C4: case 0x000000C5: case 0x000000C6: return "XBox"; + case 0x000000C7: case 0x000000C8: case 0x00000196: case 0x00000197: case 0x00000198: return "Azure Server"; + case 0xABCDABCD: return "(Unlicensed)"; + default: + static_sprintf(unknown_edition_str, "(Unknown Edition 0x%02X)", (uint32_t)ProductType); + return unknown_edition_str; + } +} + +/* + * Modified from smartmontools' os_win32.cpp + */ +int get_windows_version(char* WindowsVersionStr, size_t WindowsVersionStrSize) +{ + OSVERSIONINFOEXA vi, vi2; + DWORD dwProductType; + const char* w = NULL; + const char* arch_name; + char* vptr; + size_t vlen; + unsigned major, minor; + int nWindowsVersion = WINDOWS_UNDEFINED, nWindowsBuildNumber = 0; + ULONGLONG major_equal, minor_equal; + BOOL ws; + + if (WindowsVersionStr == NULL || WindowsVersionStrSize < 32) + return nWindowsVersion; + safe_strcpy(WindowsVersionStr, WindowsVersionStrSize, "Windows Undefined"); + + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionExA((OSVERSIONINFOA*)&vi)) { + memset(&vi, 0, sizeof(vi)); + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); + if (!GetVersionExA((OSVERSIONINFOA*)&vi)) + return nWindowsVersion; + } + + if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { + + if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { + // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx + // And starting with Windows 10 Preview 2, Windows enforces the use of the application/supportedOS + // manifest in order for VerSetConditionMask() to report the ACTUAL OS major and minor... + + major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); + for (major = vi.dwMajorVersion; major <= 9; major++) { + memset(&vi2, 0, sizeof(vi2)); + vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major; + if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) + continue; + if (vi.dwMajorVersion < major) { + vi.dwMajorVersion = major; vi.dwMinorVersion = 0; + } + + minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); + for (minor = vi.dwMinorVersion; minor <= 9; minor++) { + memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); + vi2.dwMinorVersion = minor; + if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) + continue; + vi.dwMinorVersion = minor; + break; + } + + break; + } + } + + if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { + ws = (vi.wProductType <= VER_NT_WORKSTATION); + nWindowsVersion = vi.dwMajorVersion << 4 | vi.dwMinorVersion; + switch (nWindowsVersion) { + case WINDOWS_XP: w = "XP"; + break; + case WINDOWS_2003: w = (ws ? "XP_64" : (!GetSystemMetrics(89) ? "Server 2003" : "Server 2003_R2")); + break; + case WINDOWS_VISTA: w = (ws ? "Vista" : "Server 2008"); + break; + case WINDOWS_7: w = (ws ? "7" : "Server 2008_R2"); + break; + case WINDOWS_8: w = (ws ? "8" : "Server 2012"); + break; + case WINDOWS_8_1: w = (ws ? "8.1" : "Server 2012_R2"); + break; + case WINDOWS_10_PREVIEW1: w = (ws ? "10 (Preview 1)" : "Server 10 (Preview 1)"); + break; + // Starting with Windows 10 Preview 2, the major is the same as the public-facing version + case WINDOWS_10: + if (vi.dwBuildNumber < 20000) { + w = (ws ? "10" : ((vi.dwBuildNumber < 17763) ? "Server 2016" : "Server 2019")); + break; + } + nWindowsVersion = WINDOWS_11; + // Fall through + case WINDOWS_11: w = (ws ? "11" : "Server 2022"); + break; + default: + if (nWindowsVersion < WINDOWS_XP) + nWindowsVersion = WINDOWS_UNSUPPORTED; + else + w = "12 or later"; + break; + } + } + } + + arch_name = get_arch_name(get_platform_arch()); + + GetProductInfo(vi.dwMajorVersion, vi.dwMinorVersion, vi.wServicePackMajor, vi.wServicePackMinor, &dwProductType); + vptr = &WindowsVersionStr[sizeof("Windows ") - 1]; + vlen = WindowsVersionStrSize - sizeof("Windows ") - 1; + if (!w) + safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), + (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, arch_name); + else if (vi.wServicePackMinor) + safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch_name); + else if (vi.wServicePackMajor) + safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, arch_name); + else + safe_sprintf(vptr, vlen, "%s%s%s, %s", + w, (dwProductType != PRODUCT_UNDEFINED) ? " " : "", get_edition(dwProductType), arch_name); + + // Add the build number (including UBR if available) for Windows 8.0 and later + nWindowsBuildNumber = vi.dwBuildNumber; + if (nWindowsVersion >= 0x62) { + HKEY hCurrentVersion; + DWORD dwType = REG_DWORD, dwSize = sizeof(DWORD), dwUbr = 0; + if (RegOpenKeyExA(REGKEY_HKLM, "Software\\Microsoft\\Windows NT\\CurrentVersion", + 0, KEY_READ, &hCurrentVersion) == ERROR_SUCCESS) { + RegQueryValueExA(hCurrentVersion, "UBR", NULL, &dwType, (LPBYTE)&dwUbr, &dwSize); + RegCloseKey(hCurrentVersion); + } + + vptr = &WindowsVersionStr[safe_strlen(WindowsVersionStr)]; + vlen = WindowsVersionStrSize - safe_strlen(WindowsVersionStr) - 1; + if (dwUbr != 0) + safe_sprintf(vptr, vlen, " (Build %d.%d)", nWindowsBuildNumber, (int)dwUbr); + else + safe_sprintf(vptr, vlen, " (Build %d)", nWindowsBuildNumber); + } + return nWindowsVersion; +} + void init_dialog(HWND hDlg) { int i, err; @@ -825,10 +1134,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 +1165,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 +1234,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 +1271,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)); } @@ -970,12 +1279,12 @@ void init_dialog(HWND hDlg) PostMessage(hInfo, EM_LIMITTEXT, MAX_LOG_SIZE , 0); dprintf(APP_VERSION); - dprintf(WindowsVersionStr); + dprintf(windows_version_str); // 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(); @@ -1005,7 +1314,7 @@ BOOL parse_ini(void) { // Check if the ini file exists if (GetFileAttributesU(INI_NAME) == INVALID_FILE_ATTRIBUTES) { - dprintf("ini file '%s' not found - default parameters will be used", INI_NAME); + dprintf("ini file '%s' not found in '%s' - default parameters will be used", INI_NAME, app_dir); return FALSE; } @@ -1029,24 +1338,26 @@ BOOL parse_ini(void) { // Set the log level profile_get_integer(profile, "general", "log_level", NULL, WDI_LOG_LEVEL_INFO, &log_level); - if ((log_level < WDI_LOG_LEVEL_DEBUG) && (log_level > WDI_LOG_LEVEL_NONE)) { + if ((log_level < WDI_LOG_LEVEL_DEBUG) || (log_level > WDI_LOG_LEVEL_NONE)) { log_level = WDI_LOG_LEVEL_INFO; } // 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); + free(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); } + free(tmp); } // Set the default driver @@ -1093,24 +1404,25 @@ BOOL parse_preset(char* filename) toggle_create(FALSE); } - safe_sprintf(str_tmp, 5, "%04X", tmp); - SetDlgItemTextA(hMain, IDC_VID, str_tmp); + static_sprintf(str_tmp, "%04X", 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); + free(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); + static_sprintf(str_tmp, "%04X", 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); + static_sprintf(str_tmp, "%02X", tmp); + SetDlgItemTextA(hMainDialog, IDC_MI, str_tmp); } profile_get_string(profile, "device", "GUID", NULL, NULL, &pd_options.device_guid); @@ -1236,7 +1548,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 +1556,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 +1612,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 +1627,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 +1692,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 +1742,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 +1775,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; @@ -1491,17 +1803,17 @@ INT_PTR CALLBACK main_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP if (device->driver_version == 0) { safe_strcpy(driver_text, sizeof(driver_text), device->driver); } else { - safe_sprintf(driver_text, sizeof(driver_text), "%s (v%d.%d.%d.%d)", device->driver, + static_sprintf(driver_text, "%s (v%d.%d.%d.%d)", device->driver, (int)((device->driver_version>>48)&0xffff), (int)((device->driver_version>>32)&0xffff), (int)((device->driver_version>>16)&0xffff), (int)(device->driver_version & 0xffff)); } } 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); + static_sprintf(str_tmp, "%04X", device->vid); + 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 +1823,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); - safe_sprintf(str_tmp, 5, "%04X", device->pid); - SetDlgItemTextA(hMain, IDC_PID, str_tmp); + 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); + static_sprintf(str_tmp, "%04X", device->pid); + SetDlgItemTextA(hMainDialog, IDC_PID, str_tmp); if (device->is_composite) { - safe_sprintf(str_tmp, 5, "%02X", device->mi); - SetDlgItemTextA(hMain, IDC_MI, str_tmp); + static_sprintf(str_tmp, "%02X", device->mi); + SetDlgItemTextA(hMainDialog, IDC_MI, str_tmp); display_mi(TRUE); } else { display_mi(FALSE); @@ -1526,7 +1838,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 +1858,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 +1882,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 +1892,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 +1904,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 +1922,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 +1936,15 @@ 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); + safe_free(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)); @@ -1744,10 +2057,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } // Set the Windows version - GetWindowsVersion(); + windows_version = get_windows_version(windows_version_str, sizeof(windows_version_str)); // Alert users if they are running versions older than Windows 7 - if (nWindowsVersion < WINDOWS_7) { + if (windows_version < WINDOWS_7) { MessageBoxA(NULL, "This version of Zadig can only be run on Windows 7 or later", "Incompatible version", MB_ICONSTOP); CloseHandle(mutex); @@ -1766,7 +2079,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); + static_sprintf(szFolderPath, "%s\\usb_driver", tmp); safe_free(tmp); // Create the main Window diff --git a/examples/zadig.h b/examples/zadig.h index db5f3400..f8effb05 100644 --- a/examples/zadig.h +++ b/examples/zadig.h @@ -1,226 +1,259 @@ -/* - * Zadig: Automated Driver Installer for USB devices (GUI version) - * Copyright (c) 2010-2017 Pete Batard - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#if defined(_MSC_VER) -// disable MSVC warnings that are benign -#pragma warning(disable:4100) // unreferenced formal parameter -#pragma warning(disable:4127) // conditional expression is constant -#pragma warning(disable:4201) // nameless struct/union -#pragma warning(disable:4214) // bit field types other than int -#pragma warning(disable:4996) // deprecated API calls -#pragma warning(disable:28159) // more deprecated API calls -#endif - -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -#endif -#define _IGNORE(expr) do { (void)(expr); } while(0) - -#define APPLICATION_NAME "Zadig" -#define COMPANY_NAME "Akeo Consulting" -#define APPLICATION_URL "http://zadig.akeo.ie" -#define STR_BUFFER_SIZE 512 -#define NOTIFICATION_DELAY 1000 -#define MAX_TOOLTIPS 32 -#define MAX_LOG_SIZE 0x7FFFFFFE -#define MAX_PROGRESS (0xFFFF-1) -#define INI_NAME "zadig.ini" -#define LIBWDI_URL "http://libwdi.akeo.ie" -#define LIBUSB_URL "http://windows.libusb.info" -#define LIBUSB0_URL "http://sourceforge.net/apps/trac/libusb-win32/wiki" -#define LIBUSBK_URL "http://libusbk.sourceforge.net/UsbK3/index.html" -#define WINUSB_URL "https://msdn.microsoft.com/en-us/library/windows/hardware/ff540174.aspx" -#define HELP_URL "https://github.com/pbatard/libwdi/wiki/Zadig" -#define WCID_URL "https://github.com/pbatard/libwdi/wiki/WCID-Devices" -#define USB_IDS_URL "http://www.linux-usb.org/usb-ids.html" -#define DARK_BLUE RGB(0,0,125) -#define BLACK RGB(0,0,0) -#define WHITE RGB(255,255,255) -#define LIGHT_GREY RGB(248,248,248) -#define SEPARATOR_GREY RGB(223,223,223) -#define FIELD_GREEN RGB(232,255,232) -#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.3.709" - -// These are used to flag end users about the driver they are going to replace -enum driver_type { - DT_SYSTEM, - DT_LIBUSB, - DT_UNKNOWN, - DT_NONE, - NB_DRIVER_TYPES, -}; - -// For our custom notifications -enum notification_type { - MSG_INFO, - MSG_WARNING, - MSG_ERROR, - MSG_QUESTION, -}; -typedef INT_PTR (CALLBACK *Callback_t)(HWND, UINT, WPARAM, LPARAM); -typedef struct { - WORD id; - Callback_t callback; -} notification_info; // To provide a "More info..." on notifications - -// WM_APP is not sent on focus, unlike WM_USER -enum user_message_type { - UM_REFRESH_LIST = WM_APP, - UM_DEVICE_EVENT, - UM_LOGGER_EVENT, - UM_DOWNLOAD_INIT, - UM_DOWNLOAD_EXIT, - UM_NO_UPDATE -}; - -// WCID states -enum wcid_state { - WCID_NONE, - WCID_FALSE, - WCID_TRUE, -}; - -// Timers -#define TID_MESSAGE 0x1000 - -typedef struct { - WORD version[4]; - DWORD platform_min[2]; // minimum platform version required - char* download_url; - char* release_notes; -} APPLICATION_UPDATE; - -#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 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)) -#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) -#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 safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str)) -#define safe_strdup _strdup -#define MF_CHECK(cond) ((cond)?MF_CHECKED:MF_UNCHECKED) -#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0) - -#if defined(_MSC_VER) -#define safe_vsnprintf(buf, size, format, arg) _vsnprintf_s(buf, size, _TRUNCATE, format, arg) -#else -#define safe_vsnprintf vsnprintf -#endif - -/* - * Shared prototypes - */ -#define dprintf(...) w_printf(FALSE, __VA_ARGS__) -#define dsprintf(...) w_printf(TRUE, __VA_ARGS__) -#define vuprintf(...) if (verbose) w_printf(FALSE, __VA_ARGS__) -#define vvuprintf(...) if (verbose > 1) w_printf(FALSE, __VA_ARGS__) -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); -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); -BOOL is_x64(void); -BOOL notification(int type, const notification_info* more_info, char* title, char* format, ...); -int run_with_progress_bar(int(*function)(void)); -char* to_valid_filename(char* name, char* ext); -HWND create_tooltip(HWND hWnd, char* message, int duration); -void destroy_tooltip(HWND hWnd); -void destroy_all_tooltips(void); -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); -HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog); -BOOL SetUpdateCheck(void); -BOOL CheckForUpdates(BOOL force); - -/* - * Globals - */ -extern HINSTANCE main_instance; -extern HWND hDeviceList; -extern HWND hMain; -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 int dialog_showing; -extern BOOL installation_running; -extern APPLICATION_UPDATE update; - -/* - * typedefs for the function prototypes. Use the something like: - * PF_DECL(FormatEx); - * which translates to: - * FormatEx_t pfFormatEx = NULL; - * in your code, to declare the entrypoint and then use: - * PF_INIT(FormatEx, Fmifs); - * which translates to: - * pfFormatEx = (FormatEx_t) GetProcAddress(GetLibraryHandle("fmifs"), "FormatEx"); - * to make it accessible. - */ -#define MAX_LIBRARY_HANDLES 32 -extern HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; -extern WORD OpenedLibrariesHandleSize; -#define OPENED_LIBRARIES_VARS HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; WORD OpenedLibrariesHandleSize = 0 -static __inline void FreeAllLibraries(void) { - while (OpenedLibrariesHandleSize > 0) - FreeLibrary(OpenedLibrariesHandle[--OpenedLibrariesHandleSize]); -} -static __inline HMODULE GetLibraryHandle(char* szLibraryName) { - HMODULE h = NULL; - if ((h = GetModuleHandleA(szLibraryName)) == NULL) { - if (OpenedLibrariesHandleSize >= MAX_LIBRARY_HANDLES) { - dprintf("Error: MAX_LIBRARY_HANDLES is too small\n"); - } else { - h = LoadLibraryA(szLibraryName); - if (h != NULL) - OpenedLibrariesHandle[OpenedLibrariesHandleSize++] = h; - } - } - return h; -} -#define PF_TYPE(api, ret, proc, args) typedef ret (api *proc##_t)args -#define PF_DECL(proc) static proc##_t pf##proc = NULL -#define PF_TYPE_DECL(api, ret, proc, args) PF_TYPE(api, ret, proc, args); PF_DECL(proc) -#define PF_INIT(proc, name) if (pf##proc == NULL) pf##proc = \ - (proc##_t) GetProcAddress(GetLibraryHandle(#name), #proc) -#define PF_INIT_OR_OUT(proc, name) do {PF_INIT(proc, name); \ - if (pf##proc == NULL) {dprintf("Unable to locate %s() in %s.dll: %s\n", \ - #proc, #name, WindowsErrorString()); goto out;} } while(0) - -#ifndef ARRAYSIZE -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -#endif +/* + * Zadig: Automated Driver Installer for USB devices (GUI version) + * Copyright (c) 2010-2023 Pete Batard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#if defined(_MSC_VER) +// disable MSVC warnings that are benign +#pragma warning(disable:4100) // unreferenced formal parameter +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit field types other than int +#pragma warning(disable:4996) // deprecated API calls +#pragma warning(disable:28159) // more deprecated API calls +#endif + +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif +#define _IGNORE(expr) do { (void)(expr); } while(0) + +#define APPLICATION_NAME "Zadig" +#define COMPANY_NAME "Akeo Consulting" +#define APPLICATION_URL "https://zadig.akeo.ie" +#define STR_BUFFER_SIZE 512 +#define NOTIFICATION_DELAY 1000 +#define NET_SESSION_TIMEOUT 3500 +#define MAX_TOOLTIPS 32 +#define MAX_LOG_SIZE 0x7FFFFFFE +#define MAX_PROGRESS (0xFFFF-1) +#define INI_NAME "zadig.ini" +#define LIBWDI_URL "https://github.com/pbatard/libwdi" +#define LIBUSB_URL "https://github.com/libusb/libusb/wiki/Windows" +#define LIBUSB0_URL "https://sourceforge.net/p/libusb-win32/wiki/Home/" +#define LIBUSBK_URL "http://libusbk.sourceforge.net/UsbK3/index.html" +#define WINUSB_URL "https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb" +#define HELP_URL "https://github.com/pbatard/libwdi/wiki/Zadig" +#define WCID_URL "https://github.com/pbatard/libwdi/wiki/WCID-Devices" +#define USB_IDS_URL "http://www.linux-usb.org/usb-ids.html" +#define DARK_BLUE RGB(0,0,125) +#define BLACK RGB(0,0,0) +#define WHITE RGB(255,255,255) +#define LIGHT_GREY RGB(248,248,248) +#define SEPARATOR_GREY RGB(223,223,223) +#define FIELD_GREEN RGB(232,255,232) +#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.9.788" + +// These are used to flag end users about the driver they are going to replace +enum driver_type { + DT_SYSTEM, + DT_LIBUSB, + DT_UNKNOWN, + DT_NONE, + NB_DRIVER_TYPES, +}; + +// For our custom notifications +enum notification_type { + MSG_INFO, + MSG_WARNING, + MSG_ERROR, + MSG_QUESTION, +}; +typedef INT_PTR (CALLBACK *Callback_t)(HWND, UINT, WPARAM, LPARAM); +typedef struct { + WORD id; + Callback_t callback; +} notification_info; // To provide a "More info..." on notifications + +// WM_APP is not sent on focus, unlike WM_USER +enum user_message_type { + UM_REFRESH_LIST = WM_APP, + UM_DEVICE_EVENT, + UM_LOGGER_EVENT, + UM_DOWNLOAD_INIT, + UM_DOWNLOAD_EXIT, + UM_NO_UPDATE +}; + +// WCID states +enum wcid_state { + WCID_NONE, + WCID_FALSE, + WCID_TRUE, +}; + +// Timers +#define TID_MESSAGE 0x1000 + +typedef struct { + WORD version[4]; + DWORD platform_min[2]; // minimum platform version required + char* download_url; + 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 {free((void*)p); p = NULL;} while(0) +#define safe_min(a, b) min((size_t)(a), (size_t)(b)) +static __inline void safe_strcp(char* dst, const size_t dst_max, const char* src, const size_t count) { + memmove(dst, src, min(count, dst_max)); + dst[min(count, dst_max) - 1] = 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_strcat(dst, dst_max, src) strncat_s(dst, dst_max, src, _TRUNCATE) +#define static_strcat(dst, src) safe_strcat(dst, sizeof(dst), (src)) +#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) +#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) +#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2), count) +#define safe_closehandle(h) do {if ((h != INVALID_HANDLE_VALUE) && (h != NULL)) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0) +#define safe_sprintf(dst, count, ...) do { size_t _count = count; char* _dst = dst; _snprintf_s(_dst, _count, _TRUNCATE, __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 static_sprintf(dst, ...) safe_sprintf(dst, sizeof(dst), __VA_ARGS__) +#define safe_swprintf(dst, count, ...) do { size_t _count = count; wchar_t* _dst = dst; _snwprintf_s(_dst, _count, _TRUNCATE, __VA_ARGS__); \ + _dst[(_count) - 1] = 0; } while(0) +#define safe_strdup(str) ((((char*)(str))==NULL) ? NULL : _strdup(str)) +#define MF_CHECK(cond) ((cond)?MF_CHECKED:MF_UNCHECKED) +#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0) + +#if defined(_MSC_VER) +#define safe_vsnprintf(buf, size, format, arg) _vsnprintf_s(buf, size, _TRUNCATE, format, arg) +#else +#define safe_vsnprintf vsnprintf +#endif + +/* + * Shared prototypes + */ +#define dprintf(...) w_printf(FALSE, __VA_ARGS__) +#define dsprintf(...) w_printf(TRUE, __VA_ARGS__) +#define vuprintf(...) if (verbose) w_printf(FALSE, __VA_ARGS__) +#define vvuprintf(...) if (verbose > 1) w_printf(FALSE, __VA_ARGS__) +void print_status(unsigned int duration, BOOL debug, const char* message); +int get_windows_version(char* WindowsVersionStr, size_t WindowsVersionStrSize); +void w_printf(BOOL update_status, const char *format, ...); +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); +BOOL is_x64(void); +BOOL notification(int type, const notification_info* more_info, char* title, char* format, ...); +char* to_valid_filename(char* name, char* ext); +HWND create_tooltip(HWND hWnd, char* message, int duration); +void destroy_tooltip(HWND hWnd); +void destroy_all_tooltips(void); +void set_title_bar_icon(HWND hDlg); +const char *WindowsErrorString(void); +void download_new_version(void); +void parse_update(char* buf, size_t len); +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); + +/* + * Globals + */ +extern HINSTANCE main_instance; +extern HWND hDeviceList; +extern HWND hMainDialog; +extern HWND hInfo; +extern HWND hStatus; +extern WORD application_version[4]; +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; +extern int windows_version; +extern char windows_version_str[128]; + +/* + * typedefs for the function prototypes. Use the something like: + * PF_DECL(FormatEx); + * which translates to: + * FormatEx_t pfFormatEx = NULL; + * in your code, to declare the entrypoint and then use: + * PF_INIT(FormatEx, Fmifs); + * which translates to: + * pfFormatEx = (FormatEx_t) GetProcAddress(GetLibraryHandle("fmifs"), "FormatEx"); + * to make it accessible. + */ +#define MAX_LIBRARY_HANDLES 32 +extern HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; +extern WORD OpenedLibrariesHandleSize; +#define OPENED_LIBRARIES_VARS HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; WORD OpenedLibrariesHandleSize = 0 +static __inline void FreeAllLibraries(void) { + while (OpenedLibrariesHandleSize > 0) + FreeLibrary(OpenedLibrariesHandle[--OpenedLibrariesHandleSize]); +} +static __inline HMODULE GetLibraryHandle(char* szLibraryName) { + HMODULE h = NULL; + if ((h = GetModuleHandleA(szLibraryName)) == NULL) { + if (OpenedLibrariesHandleSize >= MAX_LIBRARY_HANDLES) { + dprintf("Error: MAX_LIBRARY_HANDLES is too small\n"); + } else { + h = LoadLibraryA(szLibraryName); + if (h != NULL) + OpenedLibrariesHandle[OpenedLibrariesHandleSize++] = h; + } + } + return h; +} +#define PF_TYPE(api, ret, proc, args) typedef ret (api *proc##_t)args +#define PF_DECL(proc) static proc##_t pf##proc = NULL +#define PF_TYPE_DECL(api, ret, proc, args) PF_TYPE(api, ret, proc, args); PF_DECL(proc) +#define PF_INIT(proc, name) if (pf##proc == NULL) pf##proc = \ + (proc##_t) GetProcAddress(GetLibraryHandle(#name), #proc) +#define PF_INIT_OR_OUT(proc, name) do {PF_INIT(proc, name); \ + if (pf##proc == NULL) {dprintf("Unable to locate %s() in %s.dll: %s\n", \ + #proc, #name, WindowsErrorString()); goto out;} } while(0) + +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif diff --git a/examples/zadig.rc b/examples/zadig.rc index e64dfa0d..b7b89301 100644 --- a/examples/zadig.rc +++ b/examples/zadig.rc @@ -151,7 +151,7 @@ BEGIN LTEXT "WCID",IDC_STATIC_WCID,14,84,18,9,SS_NOTIFY EDITTEXT IDC_WCID_BOX,40,82,14,14,ES_READONLY | NOT WS_TABSTOP EDITTEXT IDC_WCID,55,82,44,14,ES_READONLY | NOT WS_VISIBLE | NOT WS_TABSTOP,WS_EX_TRANSPARENT - LTEXT "ð",IDC_RARR,142,44,17,14,SS_NOTIFY | SS_CENTERIMAGE | NOT WS_VISIBLE + LTEXT "�",IDC_RARR,142,44,17,14,SS_NOTIFY | SS_CENTERIMAGE | NOT WS_VISIBLE EDITTEXT IDC_TARGET,162,44,98,14,ES_READONLY | NOT WS_TABSTOP CONTROL "",IDC_TARGETSPIN,"msctls_updown32",UDS_ARROWKEYS,260,44,11,14,WS_EX_TRANSPARENT CONTROL IDB_ZADIG,IDC_THIS_SPACE_FOR_RENT,"Static",SS_BITMAP | SS_CENTERIMAGE | SS_REALSIZEIMAGE,278,37,97,66 @@ -246,8 +246,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,3,709,0 - PRODUCTVERSION 2,3,709,0 + FILEVERSION 2,9,788,0 + PRODUCTVERSION 2,9,788,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -264,14 +264,14 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Zadig" - VALUE "FileVersion", "2.3.709" + VALUE "FileVersion", "2.9.788" VALUE "InternalName", "Zadig" - VALUE "LegalCopyright", "© 2010-2017 Pete Batard (GPL v3)" - VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" + VALUE "LegalCopyright", "� 2010-2023 Pete Batard (GPL v3)" + VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "zadig.exe" VALUE "ProductName", "Zadig" - VALUE "ProductVersion", "2.3.709" - VALUE "Comments", "http://libwdi.akeo.ie" + VALUE "ProductVersion", "2.9.788" + VALUE "Comments", "https://zadig.akeo.ie" END END BLOCK "VarFileInfo" diff --git a/examples/zadig_README.creole b/examples/zadig_README.creole index 86c02092..47971f61 100644 --- a/examples/zadig_README.creole +++ b/examples/zadig_README.creole @@ -1,3 +1,15 @@ +=== v2.5 (2020.03.28) === +* Fix cat generation for some user directories with non western characters +* Fix update check +* Improve error reporting +* Embedded drivers: WinUSB v6.1.7600.16385, libusb-win32 v1.2.6.0, libusbK v3.0.7.0 & usbser (native) + +=== v2.4 (2018.07.26) === +* 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) + === v2.3 (2017.04.18) === * Fix issues with extended characters in current user directory * Drop Windows XP and Windows Vista support diff --git a/examples/zadig_license.h b/examples/zadig_license.h index 4ab40bfe..73789d56 100644 --- a/examples/zadig_license.h +++ b/examples/zadig_license.h @@ -1,6 +1,6 @@ /* * Zadig: Automated Driver Installer for USB devices (GUI version) - * Copyright (c) 2010-2017 Pete Batard + * Copyright (c) 2010-2024 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ const char* about_blurb_format = "{\\b\\fs20Zadig - The Automated Driver Installer}\\line\n" "\\fs18Version %d.%d (Build %d)\\line\n" "\\line\n" -"Copyright © 2010-2017 Pete Batard / Akeo\\line\n" +"Copyright © 2010-2024 Pete Batard / Akeo\\line\n" APPLICATION_URL "\\line\n" "\\line\n" "Report bugs or request enhancements at:\\line\n" @@ -32,21 +32,21 @@ APPLICATION_URL "\\line\n" const char* additional_copyrights = "{\\rtf1\\ansi\n" "Windows Driver Installer library, libwdi:\\line\n" -"Copyright © 2010-2017 by Pete Batard et al.\\line\n" +"Copyright © 2010-2024 by Pete Batard et al.\\line\n" "GNU Lesser General Public License (LGPL) v3 or later\\line\n" "https://github.com/pbatard/libwdi/wiki\\line\n" "\\line\n" "Configuration file parsing based on profile.c:\\line\n" -"Copyright © 2005-2006, Theodore Ts'o.\\line\n" -"Copyright © 2006-2011, the Kerberos Team.\\line\n" +"Copyright © 2005-2006, Theodore Ts'o.\\line\n" +"Copyright © 2006-2011, the Kerberos Team.\\line\n" "Redistributable under the GNU General Public License (GPL)\\line\n" "\\line\n" "VID identification from the USB ID Repository\\line\n" -"Copyright © Stephen J. Gowdy et al., Public Domain\\line\n" +"Copyright © Stephen J. Gowdy et al., Public Domain\\line\n" "http://www.linux-usb.org/usb-ids.html\\line\n" "\\line\n" "About and License dialogs inspired by WinSCP\\line\n" -"Copyright © 2000-2013 Martin Prikryl.\\line\n" +"Copyright © 2000-2013 Martin Prikryl.\\line\n" "GNU General Public License (GPL) v3 or later\\line\n" "\\line\n" "All other references can be found in the source.\\line\n}"; diff --git a/examples/zadig_net.c b/examples/zadig_net.c index 84754950..2878be6c 100644 --- a/examples/zadig_net.c +++ b/examples/zadig_net.c @@ -1,7 +1,7 @@ /* * Zadig: Automated Driver Installer for USB devices (GUI version) * Networking functionality (web file download, check for update, etc.) - * Copyright © 2012-2017 Pete Batard + * Copyright © 2012-2024 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -36,17 +37,35 @@ #include "zadig_registry.h" #include "zadig_resource.h" +#if defined(__MINGW32__) +#define INetworkListManager_get_IsConnectedToInternet INetworkListManager_IsConnectedToInternet +#endif + /* Maximum download chunk size, in bytes */ #define DOWNLOAD_BUFFER_SIZE 10240 /* Default delay between update checks (1 day) */ -#define DEFAULT_UPDATE_INTERVAL (24*3600) +#define DEFAULT_UPDATE_INTERVAL (24 * 3600) -BOOL force_update; -DWORD download_error; -APPLICATION_UPDATE update = { {0,0,0,0}, {0,0}, NULL, NULL }; +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; + +static const char* GetAppArchName(void) { +#if defined(_M_AMD64) + return "x64"; +#elif defined(_M_IX86) + return "x86"; +#elif defined(_M_ARM64) + return "arm64"; +#elif defined(_M_ARM) + return "arm"; +#else + return "unknown"; +#endif +} /* MinGW is missing some of those */ #if !defined(ERROR_INTERNET_DISCONNECTED) @@ -79,12 +98,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 +142,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 +177,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: @@ -200,6 +227,8 @@ const char* WinInetErrorString(void) return "The header could not be added because it already exists."; case ERROR_HTTP_REDIRECT_FAILED: return "The redirection failed because either the scheme changed or all attempts made to redirect failed."; + case ERROR_INTERNET_SECURITY_CHANNEL_ERROR: + return "This system's SSL library is too old to be able to access this website."; case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED: return "Client Authentication certificate needed"; case ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT: @@ -228,11 +257,74 @@ 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; } } +static __inline BOOL is_WOW64(void) +{ + BOOL ret = FALSE; + IsWow64Process(GetCurrentProcess(), &ret); + return ret; +} + +/* + * Open an Internet session + */ +static HINTERNET GetInternetSession(int num_retries) +{ + int i; + char agent[64]; + BOOL decodingSupport = TRUE; + VARIANT_BOOL InternetConnection = VARIANT_FALSE; + DWORD dwFlags, dwTimeout = NET_SESSION_TIMEOUT, dwProtocolSupport = HTTP_PROTOCOL_FLAG_HTTP2; + HINTERNET hSession = NULL; + HRESULT hr = S_FALSE; + INetworkListManager* pNetworkListManager; + + // Create a NetworkListManager Instance to check the network connection + IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)); + hr = CoCreateInstance(&CLSID_NetworkListManager, NULL, CLSCTX_ALL, + &IID_INetworkListManager, (LPVOID*)&pNetworkListManager); + if (hr == S_OK) { + for (i = 0; i <= num_retries; i++) { + hr = INetworkListManager_get_IsConnectedToInternet(pNetworkListManager, &InternetConnection); + if (hr == S_OK && InternetConnection == VARIANT_TRUE) + break; + // INetworkListManager may fail with ERROR_SERVICE_DEPENDENCY_FAIL if the DHCP service + // is not running, in which case we must fall back to using InternetGetConnectedState(). + // See https://github.com/pbatard/rufus/issues/1801. + if (hr == HRESULT_FROM_WIN32(ERROR_SERVICE_DEPENDENCY_FAIL)) { + if (InternetGetConnectedState(&dwFlags, 0)) { + InternetConnection = VARIANT_TRUE; + break; + } + } + Sleep(1000); + } + } + if (InternetConnection == VARIANT_FALSE) { + SetLastError(ERROR_INTERNET_DISCONNECTED); + goto out; + } + static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", + application_version[0], application_version[1], application_version[2], + windows_version >> 4, windows_version & 0x0F, is_WOW64() ? "; WOW64" : ""); + hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + // Set the timeouts + InternetSetOptionA(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout)); + InternetSetOptionA(hSession, INTERNET_OPTION_SEND_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout)); + InternetSetOptionA(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout)); + // Enable gzip and deflate decoding schemes + InternetSetOptionA(hSession, INTERNET_OPTION_HTTP_DECODING, (LPVOID)&decodingSupport, sizeof(decodingSupport)); + // Enable HTTP/2 protocol support + InternetSetOptionA(hSession, INTERNET_OPTION_ENABLE_HTTP_PROTOCOL, (LPVOID)&dwProtocolSupport, sizeof(dwProtocolSupport)); + +out: + return hSession; +} + /* * Download a file from an URL * Mostly taken from http://support.microsoft.com/kb/234913 @@ -240,21 +332,23 @@ 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 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 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}; - int i; - char msg[MAX_PATH]; + size_t last_slash; + DownloadStatus = 404; if (hProgressDialog != NULL) { // Use the progress control provided, if any hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS); @@ -266,33 +360,31 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) SendMessage(hProgressDialog, UM_DOWNLOAD_INIT, 0, 0); } - safe_sprintf(msg, sizeof(msg), "Downloading %s: Connecting...", file); + 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; + } + } + + static_sprintf(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; // Open an Internet session - for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) { - Sleep(1000); - } - if (i <= 0) { - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong... - SetLastError(ERROR_INTERNET_NOT_INITIALIZED); - dprintf("Network is unavailable: %s\n", WinInetErrorString()); - goto out; - } - safe_sprintf(agent, ARRAYSIZE(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" : ""); - hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + hSession = GetInternetSession(5); if (hSession == NULL) { - dprintf("Could not open internet session: %s\n", WinInetErrorString()); + dprintf("Could not open Internet session: %s\n", WinInetErrorString()); goto out; } @@ -302,11 +394,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; } @@ -316,12 +409,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); @@ -331,54 +423,65 @@ 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)) break; dwSize += dwDownloaded; 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)); + static_sprintf(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", &file[last_slash], 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 */ @@ -400,8 +503,8 @@ HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDia static __inline uint64_t to_uint64_t(uint16_t x[4]) { int i; uint64_t ret = 0; - for (i=0; i<4; i++) - ret = (ret<<16) + x[i]; + for (i = 0; i < 4; i++) + ret = (ret << 16) + x[i]; return ret; } @@ -414,29 +517,31 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) int status = 0; const char* server_url = APPLICATION_URL "/"; int i, j, k, verbose = 0, verpos[4]; - static const char* archname[] = {"win_x86", "win_x64"}; - static const char* channel[] = {"release", "beta"}; // release channel - const char* accept_types[] = {"*/*\0", NULL}; - DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; + static const char* archname[] = { "win_x86", "win_x64" }; + static const char* channel[] = { "release", "beta" }; // release channel + const char* accept_types[] = { "*/*\0", NULL }; + DWORD dwSize, dwDownloaded, dwTotalSize, dwStatus; char* buf = NULL; - char agent[64], hostname[64], urlpath[128], mime[32]; - OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""}; + char hostname[64], urlpath[128]; + OSVERSIONINFOA os_version = { sizeof(OSVERSIONINFOA), 0, 0, 0, 0, "" }; 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}; + URL_COMPONENTSA UrlParts = { sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, + hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1 }; SYSTEMTIME ServerTime, LocalTime; FILETIME FileTime; int64_t local_time = 0, reg_time, server_time, update_interval; 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 // It would of course be a lot nicer to use a timer and wake the thread, but my // development time is limited and this is FASTER to implement. do { - for (i=0; (i<30) && (!force_update_check); i++) + for (i = 0; (i < 30) && (!force_update_check); i++) Sleep(500); } while ((!force_update_check) && ((installation_running || (dialog_showing>0)))); if (!force_update_check) { @@ -470,14 +575,10 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) goto out; } - if ((!InternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) || (!InternetGetConnectedState(&dwFlags, 0))) + if (!InternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) goto out; - hostname[sizeof(hostname)-1] = 0; - - safe_sprintf(agent, ARRAYSIZE(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" : ""); - hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + hostname[sizeof(hostname) - 1] = 0; + hSession = GetInternetSession(5); if (hSession == NULL) goto out; hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); @@ -487,17 +588,17 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) status++; // 2 releases_only = !GetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS); - for (k=0; (k<(releases_only?1:(int)ARRAYSIZE(channel))) && (!found_new_version); k++) { + for (k = 0; (k < (releases_only ? 1 : (int)ARRAYSIZE(channel))) && (!found_new_version); k++) { dprintf("Checking %s channel...\n", channel[k]); // At this stage we can query the server for various update version files. // We first try to lookup for "___.ver" // and then remove each each of the components until we find our match. For instance, we may first // look for _win_x64_6.2.ver (Win8 x64) but only get a match for _win_x64_6.ver (Vista x64 or later) // This allows sunsetting OS versions (eg XP) or providing different downloads for different archs/groups. - safe_sprintf(urlpath, sizeof(urlpath), "%s%s%s_%s_%ld.%ld.ver", APPLICATION_NAME, (k==0)?"":"_", - (k==0)?"":channel[k], archname[is_x64()?1:0], os_version.dwMajorVersion, os_version.dwMinorVersion); + static_sprintf(urlpath, "%s%s%s_win_%s_%lu.%lu.ver", APPLICATION_NAME, (k == 0) ? "" : "_", + (k == 0) ? "" : channel[k], GetAppArchName(), os_version.dwMajorVersion, os_version.dwMinorVersion); vuprintf("Base update check: %s\n", urlpath); - for (i=0, j=(int)safe_strlen(urlpath)-5; (j>0)&&(i0) && (i= ARRAYSIZE(channel))) + if ((releases_only) || (k + 1 >= ARRAYSIZE(channel))) goto out; continue; } vuprintf("Found match for %s on server %s", urlpath, server_url); - dwSize = sizeof(mime); - HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_TYPE, (LPVOID)&mime, &dwSize, NULL); - if (strncmp(mime, "text/plain", sizeof("text/plain")-1) != 0) - goto out; - // We also get a date from Apache, which we'll use to avoid out of sync check, // in case some set their clock way into the future and back. // On the other hand, if local clock is set way back in the past, we will never check. @@ -548,7 +645,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) if ( (!HttpQueryInfoA(hRequest, HTTP_QUERY_DATE|HTTP_QUERY_FLAG_SYSTEMTIME, (LPVOID)&ServerTime, &dwSize, NULL)) || (!SystemTimeToFileTime(&ServerTime, &FileTime)) ) goto out; - server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; + server_time = ((((int64_t)FileTime.dwHighDateTime) << 32) + FileTime.dwLowDateTime) / 10000000; vvuprintf("Server time: %" PRId64 "\n", server_time); // Always store the server response time - the only clock we trust! WriteRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE, server_time); @@ -592,15 +689,18 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) out: safe_free(buf); - if (hRequest) InternetCloseHandle(hRequest); - if (hConnection) InternetCloseHandle(hConnection); - if (hSession) InternetCloseHandle(hSession); + if (hRequest) + InternetCloseHandle(hRequest); + if (hConnection) + InternetCloseHandle(hConnection); + if (hSession) + InternetCloseHandle(hSession); switch(status) { case 1: print_status(3000, TRUE, "Updates: Unable to connect to the internet"); break; case 2: - print_status(3000, TRUE, "Updates: Unable to acces version data"); + print_status(3000, TRUE, "Updates: Unable to access version data"); break; case 3: case 4: @@ -617,7 +717,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) } download_new_version(); } else if (force_update_check) { - PostMessage(hMain, UM_NO_UPDATE, 0, 0); + PostMessage(hMainDialog, UM_NO_UPDATE, 0, 0); } force_update_check = FALSE; update_check_in_progress = FALSE; diff --git a/examples/zadig_stdlg.c b/examples/zadig_stdlg.c index 69d644f3..4e3ee370 100644 --- a/examples/zadig_stdlg.c +++ b/examples/zadig_stdlg.c @@ -54,14 +54,22 @@ static char* szMessageText = NULL; static char* szMessageTitle = NULL; extern HFONT bold_font; extern float fScale; -static HWND browse_edit; -static WNDPROC org_browse_wndproc; +static HWND hBrowseEdit; +static WNDPROC pOrgBrowseWndproc; static const SETTEXTEX friggin_microsoft_unicode_amateurs = {ST_DEFAULT, CP_UTF8}; static BOOL notification_is_question; static const notification_info* notification_more_info; static BOOL reg_commcheck = FALSE; static WNDPROC original_wndproc = NULL; +/* + * https://blogs.msdn.microsoft.com/oldnewthing/20040802-00/?p=38283/ + */ +void SetDialogFocus(HWND hDlg, HWND hCtrl) +{ + SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hCtrl, TRUE); +} + /* * Converts a name + ext UTF-8 pair to a valid MS filename. * Returned string is allocated and needs to be freed manually @@ -130,35 +138,35 @@ char* to_valid_filename(char* name, char* ext) */ const char *WindowsErrorString(void) { -static char err_string[256] = {0}; + static char err_string[256] = { 0 }; DWORD size; - DWORD error_code, format_error; + DWORD errcode, format_error; - error_code = GetLastError(); + errcode = GetLastError(); - safe_sprintf(err_string, sizeof(err_string), "[0x%08lX] ", error_code); + static_sprintf(err_string, "[0x%08lX] ", errcode); - size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, HRESULT_CODE(error_code), + size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, HRESULT_CODE(errcode), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[strlen(err_string)], - sizeof(err_string)-(DWORD)strlen(err_string), NULL); + sizeof(err_string) - (DWORD)strlen(err_string), NULL); if (size == 0) { format_error = GetLastError(); if ((format_error) && (format_error != 0x13D)) // 0x13D, decode error, is returned for unknown codes - safe_sprintf(err_string, sizeof(err_string), - "Windows error code 0x%08lX (FormatMessage error code 0x%08lX)", error_code, format_error); + static_sprintf(err_string, "Windows error code 0x%08lX (FormatMessage error code 0x%08lX)", + errcode, format_error); else - safe_sprintf(err_string, sizeof(err_string), "Unknown error 0x%08lX", error_code); + static_sprintf(err_string, "Unknown error 0x%08lX", errcode); } - SetLastError(error_code); // Make sure we don't change the errorcode on exit + SetLastError(errcode); // Make sure we don't change the errorcode on exit return err_string; } /* * 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; @@ -211,20 +219,20 @@ static PSID get_sid(void) { * our path, else if what the user typed does match the selection, it is discarded. * Talk about a convoluted way of producing an intuitive folder selection dialog */ -INT CALLBACK browsedlg_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +INT CALLBACK BrowseDlgCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY: - GetWindowTextU(browse_edit, extraction_path, sizeof(extraction_path)); + GetWindowTextU(hBrowseEdit, szFolderPath, sizeof(szFolderPath)); break; } - return (INT)CallWindowProc(org_browse_wndproc, hDlg, message, wParam, lParam); + return (INT)CallWindowProc(pOrgBrowseWndproc, hDlg, message, wParam, lParam); } /* - * Main browseinfo callback to set the initial directory and populate the edit control + * Main BrowseInfo callback to set the initial directory and populate the edit control */ -INT CALLBACK browseinfo_callback(HWND hDlg, UINT message, LPARAM lParam, LPARAM pData) +INT CALLBACK BrowseInfoCallback(HWND hDlg, UINT message, LPARAM lParam, LPARAM pData) { char dir[MAX_PATH]; wchar_t* wpath; @@ -232,14 +240,14 @@ INT CALLBACK browseinfo_callback(HWND hDlg, UINT message, LPARAM lParam, LPARAM switch(message) { case BFFM_INITIALIZED: - org_browse_wndproc = (WNDPROC)SetWindowLongPtr(hDlg, GWLP_WNDPROC, (LONG_PTR)browsedlg_callback); + pOrgBrowseWndproc = (WNDPROC)SetWindowLongPtr(hDlg, GWLP_WNDPROC, (LONG_PTR)BrowseDlgCallback); // Windows hides the full path in the edit box by default, which is bull. // Get a handle to the edit control to fix that - browse_edit = FindWindowExA(hDlg, NULL, "Edit", NULL); - SetWindowTextU(browse_edit, extraction_path); - SetFocus(browse_edit); + hBrowseEdit = FindWindowExA(hDlg, NULL, "Edit", NULL); + SetWindowTextU(hBrowseEdit, szFolderPath); + SetDialogFocus(hDlg, hBrowseEdit); // On Windows 7, MinGW only properly selects the specified folder when using a pidl - wpath = utf8_to_wchar(extraction_path); + wpath = utf8_to_wchar(szFolderPath); pidl = SHSimpleIDListFromPath(wpath); safe_free(wpath); // NB: see http://connect.microsoft.com/VisualStudio/feedback/details/518103/bffm-setselection-does-not-work-with-shbrowseforfolder-on-windows-7 @@ -252,7 +260,7 @@ INT CALLBACK browseinfo_callback(HWND hDlg, UINT message, LPARAM lParam, LPARAM // Update the status if (SHGetPathFromIDListU((LPITEMIDLIST)lParam, dir)) { SendMessageLU(hDlg, BFFM_SETSTATUSTEXT, 0, dir); - SetWindowTextU(browse_edit, dir); + SetWindowTextU(hBrowseEdit, dir); } break; } @@ -260,10 +268,12 @@ INT CALLBACK browseinfo_callback(HWND hDlg, UINT message, LPARAM lParam, LPARAM } /* - * Browse for a folder and update the folder edit box using IFileOpenDialog + * Browse for a folder and update the folder edit box */ -void browse_for_folder(void) { +void BrowseForFolder(void) { + BROWSEINFOW bi; + LPITEMIDLIST pidl; WCHAR *wpath; size_t i; HRESULT hr; @@ -279,22 +289,22 @@ void browse_for_folder(void) { if (FAILED(hr)) { dprintf("CoCreateInstance for FileOpenDialog failed: error %X", hr); pfod = NULL; // Just in case - goto out; + goto fallback; } hr = pfod->lpVtbl->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.sln b/libwdi.sln index 550384fb..c5f15f9d 100644 --- a/libwdi.sln +++ b/libwdi.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33414.496 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{CE152D17-B7D5-4ECA-9C6B-BFA86ACBFF75}" EndProject @@ -12,8 +12,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "embedder", "libwdi\.msvc\em EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wdi-simple", "examples\.msvc\wdi-simple.vcxproj", "{84C746FC-0B8B-40C5-9FB0-5EDC8377506D}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zadic", "examples\.msvc\zadic.vcxproj", "{F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zadig", "examples\.msvc\zadig.vcxproj", "{F7F7842F-2912-454E-ADF5-0B22987946E2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwdi (dll)", "libwdi\.msvc\libwdi_dll.vcxproj", "{79275348-41A4-4D07-8990-4068C9594A2C}" @@ -22,6 +20,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer_x86", "libwdi\.ms EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer_x64", "libwdi\.msvc\installer_x64.vcxproj", "{E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer_arm64", "libwdi\.msvc\installer_arm64.vcxproj", "{6AC16F78-F266-4AE0-BD63-550A55F54C15}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "examples\getopt\.msvc\getopt.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "detect_64build", "libwdi\.msvc\detect_64build.vcxproj", "{5FAEF8F7-C809-4A68-862F-F8BC6E775B61}" @@ -58,14 +58,6 @@ Global {84C746FC-0B8B-40C5-9FB0-5EDC8377506D}.Release|Win32.Build.0 = Release|Win32 {84C746FC-0B8B-40C5-9FB0-5EDC8377506D}.Release|x64.ActiveCfg = Release|x64 {84C746FC-0B8B-40C5-9FB0-5EDC8377506D}.Release|x64.Build.0 = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|Win32.Build.0 = Debug|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.ActiveCfg = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Debug|x64.Build.0 = Debug|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.ActiveCfg = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|Win32.Build.0 = Release|Win32 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.ActiveCfg = Release|x64 - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87}.Release|x64.Build.0 = Release|x64 {F7F7842F-2912-454E-ADF5-0B22987946E2}.Debug|Win32.ActiveCfg = Debug|Win32 {F7F7842F-2912-454E-ADF5-0B22987946E2}.Debug|Win32.Build.0 = Debug|Win32 {F7F7842F-2912-454E-ADF5-0B22987946E2}.Debug|x64.ActiveCfg = Debug|x64 @@ -92,6 +84,14 @@ Global {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Release|Win32.Build.0 = Release|x64 {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Release|x64.ActiveCfg = Release|x64 {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Release|x64.Build.0 = Release|x64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Debug|Win32.ActiveCfg = Debug|ARM64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Debug|Win32.Build.0 = Debug|ARM64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Debug|x64.ActiveCfg = Debug|ARM64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Debug|x64.Build.0 = Debug|ARM64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Release|Win32.ActiveCfg = Release|ARM64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Release|Win32.Build.0 = Release|ARM64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Release|x64.ActiveCfg = Release|ARM64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15}.Release|x64.Build.0 = Release|ARM64 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.ActiveCfg = Debug|Win32 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|Win32.Build.0 = Debug|Win32 {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64 @@ -115,8 +115,10 @@ Global GlobalSection(NestedProjects) = preSolution {B1F3B94A-4EC4-406E-9CBF-056E1EA03DE0} = {CE152D17-B7D5-4ECA-9C6B-BFA86ACBFF75} {84C746FC-0B8B-40C5-9FB0-5EDC8377506D} = {CE152D17-B7D5-4ECA-9C6B-BFA86ACBFF75} - {F4938DB0-3DE7-4737-9C5A-EAD1BE819F87} = {CE152D17-B7D5-4ECA-9C6B-BFA86ACBFF75} {F7F7842F-2912-454E-ADF5-0B22987946E2} = {CE152D17-B7D5-4ECA-9C6B-BFA86ACBFF75} {AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E} = {B1F3B94A-4EC4-406E-9CBF-056E1EA03DE0} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {31CAC804-E47E-4336-B896-016DFB1117CB} + EndGlobalSection EndGlobal diff --git a/libwdi/.msvc/detect_64build.vcxproj b/libwdi/.msvc/detect_64build.vcxproj index 789f41ed..8dab22df 100644 --- a/libwdi/.msvc/detect_64build.vcxproj +++ b/libwdi/.msvc/detect_64build.vcxproj @@ -27,22 +27,22 @@ Utility Unicode - v141 + v143 Utility Unicode - v141 + v143 Utility Unicode - v141 + v143 Utility Unicode - v141 + v143 diff --git a/libwdi/.msvc/embedder.vcxproj b/libwdi/.msvc/embedder.vcxproj index e470ce18..dbf8e2bf 100644 --- a/libwdi/.msvc/embedder.vcxproj +++ b/libwdi/.msvc/embedder.vcxproj @@ -21,12 +21,12 @@ Application Unicode true - v141 + v143 Application Unicode - v141 + v143 diff --git a/libwdi/.msvc/embedder_sources b/libwdi/.msvc/embedder_sources deleted file mode 100644 index d4646a52..00000000 --- a/libwdi/.msvc/embedder_sources +++ /dev/null @@ -1,19 +0,0 @@ -TARGETNAME=embedder -TARGETTYPE=PROGRAM - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -UMTYPE=console -UMBASE=0x01000000 - -INCLUDES=..\msvc;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib - -SOURCES=embedder.c diff --git a/libwdi/.msvc/installer_arm64.vcxproj b/libwdi/.msvc/installer_arm64.vcxproj new file mode 100644 index 00000000..f6646ee7 --- /dev/null +++ b/libwdi/.msvc/installer_arm64.vcxproj @@ -0,0 +1,110 @@ + + + + + Debug + ARM64 + + + Release + ARM64 + + + + installer_arm64 + {6AC16F78-F266-4AE0-BD63-550A55F54C15} + installerarm64 + + + + Application + Unicode + true + v143 + + + Application + Unicode + v143 + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\helper\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\installer_arm64\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\installer_arm64\ + + + + ARM64 + + + Disabled + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level3 + ProgramDatabase + CompileAsC + + + newdev.lib;setupapi.lib;%(AdditionalDependencies) + $(OutDir)installer_arm64.exe + true + Console + + + + + ARM64 + + + MinSpace + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + Level3 + CompileAsC + + + newdev.lib;setupapi.lib;%(AdditionalDependencies) + $(OutDir)installer_arm64.exe + false + Console + true + true + + + + + CompileAsC + + + + + CompileAsC + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/.msvc/zadic.vcxproj.filters b/libwdi/.msvc/installer_arm64.vcxproj.filters similarity index 57% rename from examples/.msvc/zadic.vcxproj.filters rename to libwdi/.msvc/installer_arm64.vcxproj.filters index c9163e03..6f4141ba 100644 --- a/examples/.msvc/zadic.vcxproj.filters +++ b/libwdi/.msvc/installer_arm64.vcxproj.filters @@ -5,18 +5,22 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - {7cc83e36-4fef-4def-ae65-6698cd4ecdad} + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd - + Source Files - - Resource Files - + + Header Files + + + Header Files + \ No newline at end of file diff --git a/libwdi/.msvc/installer_x64.vcxproj b/libwdi/.msvc/installer_x64.vcxproj index 0f8aafbd..db0c8ec0 100644 --- a/libwdi/.msvc/installer_x64.vcxproj +++ b/libwdi/.msvc/installer_x64.vcxproj @@ -1,18 +1,10 @@  - - Debug - Win32 - Debug x64 - - Release - Win32 - Release x64 @@ -22,39 +14,22 @@ installer_x64 {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26} installerx64 - Win32Proj - - Application - v141 - - - Application - v141 - Application Unicode true - v141 + v143 Application Unicode - v141 + v143 - - - - - - - - @@ -78,7 +53,7 @@ Disabled ..\..\msvc;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS; _WIN64;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_WIN64;%(PreprocessorDefinitions) MultiThreadedDebug Level3 ProgramDatabase @@ -99,7 +74,7 @@ MinSpace ..\..\msvc;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS; _WIN64;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;_WIN64;%(PreprocessorDefinitions) MultiThreaded Level3 CompileAsC diff --git a/libwdi/.msvc/installer_x64_sources b/libwdi/.msvc/installer_x64_sources deleted file mode 100644 index 7ff972bb..00000000 --- a/libwdi/.msvc/installer_x64_sources +++ /dev/null @@ -1,24 +0,0 @@ -TARGETNAME=installer_x64 -TARGETTYPE=PROGRAM - -_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -UMTYPE=console -UMBASE=0x01000000 - -INCLUDES=..\msvc;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\newdev.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - $(SDK_LIB_PATH)\setupapi.lib - -SOURCES=installer.c diff --git a/libwdi/.msvc/installer_x86.vcxproj b/libwdi/.msvc/installer_x86.vcxproj index cb11409b..315abc9f 100644 --- a/libwdi/.msvc/installer_x86.vcxproj +++ b/libwdi/.msvc/installer_x86.vcxproj @@ -14,19 +14,18 @@ installer_x86 {9B1C561E-F95B-4849-A7AA-A4350E227C20} installerx86 - Win32Proj Application Unicode true - v141 + v143 Application Unicode - v141 + v143 @@ -52,7 +51,6 @@ Disabled ..\..\msvc;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true MultiThreadedDebug Level3 ProgramDatabase diff --git a/libwdi/.msvc/installer_x86_sources b/libwdi/.msvc/installer_x86_sources deleted file mode 100644 index c9e41817..00000000 --- a/libwdi/.msvc/installer_x86_sources +++ /dev/null @@ -1,24 +0,0 @@ -TARGETNAME=installer_x86 -TARGETTYPE=PROGRAM - -_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -UMTYPE=console -UMBASE=0x01000000 - -INCLUDES=..\msvc;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\newdev.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - $(SDK_LIB_PATH)\setupapi.lib - -SOURCES=installer.c diff --git a/libwdi/.msvc/libwdi_dll.vcxproj b/libwdi/.msvc/libwdi_dll.vcxproj index 6c9c8d11..2616d841 100644 --- a/libwdi/.msvc/libwdi_dll.vcxproj +++ b/libwdi/.msvc/libwdi_dll.vcxproj @@ -28,22 +28,22 @@ DynamicLibrary Unicode true - v141 + v143 DynamicLibrary Unicode - v141 + v143 DynamicLibrary Unicode - v141 + v143 DynamicLibrary Unicode - v141 + v143 @@ -89,11 +89,10 @@ embedder embedded.h Disabled ..\..\msvc;%(AdditionalIncludeDirectories) - DEBUG;_DEBUG;_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + DEBUG;_DEBUG;_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;LIBWDI_DLL_EXPORT;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level3 ProgramDatabase - false CompileAsC @@ -115,11 +114,10 @@ embedder embedded.h Disabled ..\..\msvc;%(AdditionalIncludeDirectories) - DEBUG;_DEBUG;_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + DEBUG;_DEBUG;_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;LIBWDI_DLL_EXPORT;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level3 ProgramDatabase - false CompileAsC @@ -141,10 +139,9 @@ embedder embedded.h MinSpace ..\..\msvc;%(AdditionalIncludeDirectories) - _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;LIBWDI_DLL_EXPORT;%(PreprocessorDefinitions) MultiThreadedDLL Level3 - false CompileAsC @@ -166,10 +163,9 @@ embedder embedded.h MinSpace ..\..\msvc;%(AdditionalIncludeDirectories) - _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;LIBWDI_DLL_EXPORT;%(PreprocessorDefinitions) MultiThreadedDLL Level3 - false CompileAsC @@ -217,6 +213,9 @@ embedder embedded.h {792d44d5-28a7-4eb3-b84b-8021fe3189f9} false + + {6ac16f78-f266-4ae0-bd63-550a55f54c15} + {e5a56ee0-182f-470f-8cdc-8c1b7b86ee26} false diff --git a/libwdi/.msvc/libwdi_sources b/libwdi/.msvc/libwdi_sources deleted file mode 100644 index 8938310e..00000000 --- a/libwdi/.msvc/libwdi_sources +++ /dev/null @@ -1,32 +0,0 @@ -#TARGETTYPE is not defined, to allow selection between static lib or DLL with ddk_build -TARGETNAME=libwdi -DLLDEF=libwdi.def - -!IFNDEF MSC_WARNING_LEVEL -MSC_WARNING_LEVEL=/W3 -!ENDIF - -USE_MSVCRT=1 - -INCLUDES=..\msvc;$(DDK_INC_PATH) -C_DEFINES = $(C_DEFINES) /DDDKBUILD $(DLL_DEFINES) -LINKER_FLAGS=/ignore:4006 - -# naked calls to 'build' ignores SOURCELIBS => we can't create a static lib -# that includes dependencies without calling the linker externally :( - -TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ - $(SDK_LIB_PATH)\advapi32.lib \ - $(SDK_LIB_PATH)\user32.lib \ - $(SDK_LIB_PATH)\shell32.lib \ - $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib - -SOURCES= \ - logging.c \ - libwdi.c \ - libwdi_dlg.c \ - pki.c \ - tokenizer.c \ - vid_data.c \ - libwdi.rc diff --git a/libwdi/.msvc/libwdi_static.vcxproj b/libwdi/.msvc/libwdi_static.vcxproj index 93a37c7d..ca3be11f 100644 --- a/libwdi/.msvc/libwdi_static.vcxproj +++ b/libwdi/.msvc/libwdi_static.vcxproj @@ -28,22 +28,22 @@ StaticLibrary Unicode true - v141 + v143 StaticLibrary Unicode - v141 + v143 StaticLibrary Unicode - v141 + v143 StaticLibrary Unicode - v141 + v143 @@ -89,7 +89,6 @@ embedder embedded.h ..\..\msvc;%(AdditionalIncludeDirectories) DEBUG;_DEBUG;_WIN32;_CRTDBG_MAP_ALLOC;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true MultiThreadedDebug Level3 ProgramDatabase @@ -203,6 +202,9 @@ embedder embedded.h {792d44d5-28a7-4eb3-b84b-8021fe3189f9} false + + {6ac16f78-f266-4ae0-bd63-550a55f54c15} + {e5a56ee0-182f-470f-8cdc-8c1b7b86ee26} false diff --git a/libwdi/Makefile.am b/libwdi/Makefile.am index 404b01c7..21965888 100644 --- a/libwdi/Makefile.am +++ b/libwdi/Makefile.am @@ -50,7 +50,7 @@ libwdi_rc.lo: libwdi.rc libwdi_la_CFLAGS = $(ARCH_CFLAGS) $(VISIBILITY_CFLAGS) $(AM_CFLAGS) libwdi_la_LDLAGS = $(AM_LDFLAGS) -libwdi_la_LIBADD = libwdi_rc.lo -lsetupapi -lole32 +libwdi_la_LIBADD = libwdi_rc.lo -lsetupapi -lole32 -lntdll libwdi_la_SOURCES = $(LIB_SRC) libwdi_la_HEADERS = $(LIB_HDR) libwdi_ladir = $(includedir) diff --git a/libwdi/embedder.c b/libwdi/embedder.c index e5d7c50c..ba65b3e6 100644 --- a/libwdi/embedder.c +++ b/libwdi/embedder.c @@ -89,7 +89,7 @@ void dump_buffer_hex(FILE* fd, unsigned char *buffer, size_t size) fprintf(fd, "0x00"); } - for (i=0; i + * Copyright (c) 2010-2023 Pete Batard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -52,9 +52,11 @@ #if defined(_DEBUG) #define INSTALLER_PATH_32 SOLUTIONDIR "\\Win32\\Debug\\helper" #define INSTALLER_PATH_64 SOLUTIONDIR "\\x64\\Debug\\helper" +#define INSTALLER_PATH_ARM SOLUTIONDIR "\\arm64\\Debug\\helper" #else #define INSTALLER_PATH_32 SOLUTIONDIR "\\Win32\\Release\\helper" #define INSTALLER_PATH_64 SOLUTIONDIR "\\x64\\Release\\helper" +#define INSTALLER_PATH_ARM SOLUTIONDIR "\\arm64\\Release\\helper" #endif #else #if !defined(SOLUTIONDIR) @@ -64,4 +66,5 @@ // as it won't run from ANYWHERE ELSE! Use the one from .libs instead. #define INSTALLER_PATH_32 SOLUTIONDIR #define INSTALLER_PATH_64 SOLUTIONDIR +#define INSTALLER_PATH_ARM SOLUTIONDIR #endif diff --git a/libwdi/embedder_files.h b/libwdi/embedder_files.h index 9b8bb121..001a3540 100644 --- a/libwdi/embedder_files.h +++ b/libwdi/embedder_files.h @@ -1,7 +1,7 @@ /* * embedder : converts binary resources into a .h include * "If you can think of a better way to get ice, I'd like to hear it." - * Copyright (c) 2010-2017 Pete Batard + * Copyright (c) 2010-2023 Pete Batard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -55,8 +55,8 @@ struct emb embeddable_fixed[] = { // libusb0 #if defined(LIBUSB0_DIR) - { 0, LIBUSB0_DIR "\\bin\\x86\\libusb0_x86.dll", "x86" }, { 0, LIBUSB0_DIR "\\bin\\x86\\install-filter.exe", "x86" }, + { 0, LIBUSB0_DIR "\\bin\\x86\\libusb0_x86.dll", "x86" }, # if defined(LIBUSBK_DIR) # if defined(OPT_M32) { 1, "libusb0.dll", "x86" }, // reuse @@ -73,6 +73,11 @@ struct emb embeddable_fixed[] = { { 0, LIBUSB0_DIR "\\bin\\amd64\\libusb0.sys", "amd64" }, { 0, LIBUSB0_DIR "\\bin\\amd64\\install-filter.exe", "amd64" }, # endif // OPT_M64 +# if defined(OPT_ARM) + { 0, LIBUSB0_DIR "\\bin\\arm64\\libusb0.dll", "arm64" }, + { 0, LIBUSB0_DIR "\\bin\\arm64\\libusb0.sys", "arm64" }, + { 0, LIBUSB0_DIR "\\bin\\arm64\\install-filter.exe", "arm64" }, +# endif // OPT_ARM { 0, LIBUSB0_DIR "\\installer_license.txt", "license\\libusb0" }, #endif // LIBUSB0_DIR @@ -125,6 +130,9 @@ struct emb embeddable_fixed[] = { #if defined(OPT_M64) { 0, INSTALLER_PATH_64 "\\installer_x64.exe", "." }, #endif +#if defined(OPT_ARM) + { 0, INSTALLER_PATH_ARM "\\installer_arm64.exe", "." }, +#endif // inf templates for the tokenizer ("" directory means no extraction) { 0, "winusb.inf.in", "" }, { 0, "libusb0.inf.in", "" }, diff --git a/libwdi/installer.c b/libwdi/installer.c index 63573719..89599803 100644 --- a/libwdi/installer.c +++ b/libwdi/installer.c @@ -1,6 +1,6 @@ /* - * Library for WinUSB/libusb automated driver installation - * Copyright (c) 2010-2013 Pete Batard + * Library for USB automated driver installation + * Copyright (c) 2010-2022 Pete Batard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -365,12 +365,12 @@ static __inline char* xlocale_to_utf8(const char* str) } // +1 for extra leading byte - if ((ustr = (char*)calloc(size+1, 1)) == NULL) { + if ((ustr = (char*)calloc((size_t)size + 1, 1)) == NULL) { free(wstr); return NULL; } - if (wchar_to_utf8_no_alloc(wstr, ustr+1, size) != size) { + if (wchar_to_utf8_no_alloc(wstr, ustr + 1, size) != size) { free(ustr); free(wstr); return NULL; @@ -480,7 +480,7 @@ void __cdecl syslog_reader_thread(void* param) if (size != 0) { // Read from file and add a zero terminator - buffer = malloc(size+1); + buffer = malloc((size_t)size + 1); if (buffer == NULL) { plog("could not allocate buffer to read syslog"); goto out; @@ -526,7 +526,7 @@ void __cdecl syslog_reader_thread(void* param) _endthread(); } -static char *windows_error_str(uint32_t retval) +static char *wdi_windows_error_str(uint32_t retval) { static char err_string[STR_BUFFER_SIZE]; @@ -575,6 +575,7 @@ static char err_string[STR_BUFFER_SIZE]; * Convert various installation errors to their WDI counterpart */ static __inline int process_error(DWORD r, char* path) { + // https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/DrvPkg_Errors.doc // Will fail if inf not signed, unless DRIVER_PACKAGE_LEGACY_MODE is specified. // r = 87 ERROR_INVALID_PARAMETER on path == NULL or hardware_id empty string // r = 2 ERROR_FILE_NOT_FOUND => failed to open inf @@ -591,72 +592,92 @@ static __inline int process_error(DWORD r, char* path) { // r = 0x800B0100 ERROR_WRONG_INF_STYLE => missing cat entry in inf // r = 0xE000022F ERROR_NO_CATALOG_FOR_OEM_INF => "reject unsigned driver" policy is enforced // r = 0xE0000243 ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED => user doesn't trust the cert that signed the cat + // r = 0xE0000246 ERROR_DEVICE_INSTALLER_NOT_READY => Windows is already running an installer. // r = 0xE000024B ERROR_FILE_HASH_NOT_IN_CATALOG => can happen if the cat contains SHA-256 hashes, but its header says SHA-1 // r = 0xB7 => missing DRIVER_PACKAGE_REPAIR flag switch(r) { case ERROR_NO_MORE_ITEMS: - plog("more recent driver was found (force option required)"); + plog("A more recent driver was found (force option required)."); return WDI_ERROR_EXISTS; case ERROR_NO_SUCH_DEVINST: - plog("device not detected (copying driver files for next time device is plugged in)"); + plog("Device was not detected (Copying driver files for next time device is plugged in)."); return WDI_SUCCESS; case ERROR_INVALID_PARAMETER: - plog("invalid path or hardware ID (%s)", path); + plog("Invalid path or hardware ID (%s).", path); return WDI_ERROR_INVALID_PARAM; case ERROR_FILE_NOT_FOUND: - plog("the system can not find the file specified (%s)", path); + case ERROR_PATH_NOT_FOUND: + case ERROR_OPEN_FAILED: + plog("The system can not find the file or path specified (%s).", path); return WDI_ERROR_NOT_FOUND; case ERROR_FILE_HASH_NOT_IN_CATALOG: - plog("unable to locate the file hashes in cat file"); + plog("Unable to locate the file hashes in the CAT file."); return WDI_ERROR_NOT_FOUND; case ERROR_ACCESS_DENIED: - plog("this process needs to be run with administrative privileges"); + plog("This process needs to be run with administrative privileges."); return WDI_ERROR_NEEDS_ADMIN; case ERROR_IN_WOW64: - plog("attempted to use a 32 bit installer on a 64 bit machine"); + plog("Attempted to use a 32 bit installer on a 64 bit machine."); return WDI_ERROR_WOW64; case ERROR_INVALID_DATA: case ERROR_WRONG_INF_STYLE: case ERROR_GENERAL_SYNTAX: - plog("the syntax of the inf is invalid"); + case SPAPI_E_INVALID_TARGET: + plog("The syntax of the INF file is invalid."); return WDI_ERROR_INF_SYNTAX; case ERROR_BAD_SERVICE_INSTALLSECT: - plog("a section of the inf has a problem"); + case SPAPI_E_BAD_SERVICE_INSTALLSECT: + case SPAPI_E_NO_ASSOCIATED_SERVICE: + plog("A section of the INF file has a problem."); return WDI_ERROR_INF_SYNTAX; case ERROR_INVALID_CATALOG_DATA: - plog("unable to locate cat file"); + plog("Unable to locate the CAT file"); return WDI_ERROR_CAT_MISSING; case ERROR_NO_AUTHENTICODE_CATALOG: case ERROR_DRIVER_STORE_ADD_FAILED: - case ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED: - plog("operation cancelled by the user"); + plog("Invalid CAT file signature or operation cancelled by user."); return WDI_ERROR_USER_CANCEL; + case ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED: + case ERROR_CERTIFICATE_AUTHORITY_NOT_TRUSTED: + plog("This version of Windows is refusing to trust the installed certificate."); + return WDI_ERROR_NOT_SUPPORTED; case ERROR_NO_DRIVER_SELECTED: - plog("the driver is not compatible with this version of Windows"); + plog("The driver is not compatible with this version of Windows."); return WDI_ERROR_NOT_SUPPORTED; case ERROR_ALREADY_EXISTS: - plog("driver already exists"); + plog("This driver already exists."); return WDI_ERROR_EXISTS; case ERROR_NO_CATALOG_FOR_OEM_INF: - plog("your system policy has been modified from Windows defaults, and"); + plog("Your system policy has been modified from Windows defaults, and"); plog("is set to reject unsigned drivers. You must revert the driver"); plog("installation policy to default if you want to install this driver."); - plog("see http://articles.techrepublic.com.com/5100-10878_11-5875443.html"); return WDI_ERROR_UNSIGNED; // From https://github.com/Microsoft/Windows-driver-samples/blob/master/general/installwdf/Install.cpp#L180-L193 case ERROR_SERVICE_DISABLED: case WU_E_WU_DISABLED: - plog("the \"Windows Update\" service is disabled. Please enable that service."); + plog("The \"Windows Update\" service is disabled. Please enable that service."); return WDI_ERROR_OTHER; case WU_S_ALREADY_INSTALLED: - plog("the driver is already installed"); + plog("This driver is already installed."); return WDI_SUCCESS; case ERROR_SUCCESS_REBOOT_REQUIRED: - plog("the driver was installed successfully, but a reboot is required."); + plog("The driver was installed successfully, but a reboot is required."); return WDI_SUCCESS; + case ERROR_DEVICE_INSTALLER_NOT_READY: + plog("Another system installer is running. Please wait for that installer to complete."); + return WDI_ERROR_PENDING_INSTALLATION; + case ERROR_TIMEOUT: + plog("The driver installation timed out"); + return WDI_ERROR_TIMEOUT; + case ERROR_DRIVER_NONNATIVE: + plog("A driver component being installed does not match this platform's architecture."); + return WDI_ERROR_NOT_SUPPORTED; + case ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION: + plog("The driver installation requires an interactive window."); + return WDI_ERROR_OTHER; default: - plog("unhandled error 0x%X (%d)", r, r); - plog(windows_error_str(r)); + plog("Unhandled error 0x%X (%d)", r, r); + plog(wdi_windows_error_str(r)); return WDI_ERROR_OTHER; } } @@ -668,7 +689,7 @@ BOOL disable_system_restore(BOOL enabled) LONG r; DWORD disp, regtype, val, val_size=sizeof(DWORD); HRESULT hr; - IGroupPolicyObject* pLGPO; + IGroupPolicyObject* pLGPO = NULL; static DWORD original_val = -1; // -1 = key doesn't exist HKEY machine_key = NULL, disable_system_restore_key = NULL; // MSVC is finicky about these ones => redefine them diff --git a/libwdi/installer.h b/libwdi/installer.h index 41716d54..3e210e2b 100644 --- a/libwdi/installer.h +++ b/libwdi/installer.h @@ -1,6 +1,7 @@ /* - * Library for WinUSB/libusb automated driver installation - * Copyright (c) 2010-2013 Pete Batard + * Library for USB automated driver installation + * Copyright (c) 2010-2022 Pete Batard + * For more info, please visit http://libwdi.akeo.ie * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,24 +40,28 @@ #define INSTALLER_PIPE_NAME "\\\\.\\pipe\\libwdi-installer" -#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0) +#define safe_free(p) do {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) +static __inline void safe_strcp(char* dst, const size_t dst_max, const char* src, const size_t count) { + memmove(dst, src, min(count, dst_max)); + dst[min(count, dst_max) - 1] = 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 static_strcat(dst, src) safe_strcat(dst, sizeof(dst), src) +#define safe_strcat(dst, dst_max, src) strncat_s(dst, dst_max, src, _TRUNCATE) +#define static_strcat(dst, src) safe_strcat(dst, sizeof(dst), (src)) #define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) #define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"":str1), ((str2==NULL)?"":str2)) #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 safe_closehandle(h) do {if ((h != INVALID_HANDLE_VALUE) && (h != NULL)) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0) +#define safe_sprintf(dst, count, ...) do { size_t _count = count; char* _dst = dst; _snprintf_s(_dst, _count, _TRUNCATE, __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 static_sprintf(dest, format, ...) safe_sprintf(dest, sizeof(dest), format, __VA_ARGS__) -#define safe_swprintf _snwprintf -#define safe_strdup _strdup +#define static_sprintf(dst, ...) safe_sprintf(dst, sizeof(dst), __VA_ARGS__) +#define safe_swprintf(dst, count, ...) do { size_t _count = count; wchar_t* _dst = dst; _snwprintf_s(_dst, _count, _TRUNCATE, __VA_ARGS__); \ + _dst[(_count) - 1] = 0; } while(0) +#define safe_strdup(str) ((((char*)(str))==NULL) ? NULL : _strdup(str)) #ifndef ARRAYSIZE #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) #endif @@ -83,6 +88,17 @@ enum installer_code { IC_INSTALLER_COMPLETED, }; +/* Helper function to isolate a filename from a path */ +static __inline const char* filename(const char* path) +{ + int i; + if (path == NULL) + return NULL; + i = (int)strlen(path); + while ((--i >= 0) && (path[i] != '\\') && (path[i] != '/')); + return (const char*)&path[i + 1]; +} + /* Helper functions to access DLLs */ static __inline HMODULE GetLibraryHandle(char* szDLLName) { @@ -142,9 +158,15 @@ typedef RETURN_TYPE CONFIGRET; #ifndef ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED #define ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED 0xE0000243 #endif +#ifndef ERROR_CERTIFICATE_AUTHORITY_NOT_TRUSTED +#define ERROR_CERTIFICATE_AUTHORITY_NOT_TRUSTED 0x00000109 +#endif #ifndef ERROR_FILE_HASH_NOT_IN_CATALOG #define ERROR_FILE_HASH_NOT_IN_CATALOG 0xE000024B #endif +#ifndef ERROR_DEVICE_INSTALLER_NOT_READY +#define ERROR_DEVICE_INSTALLER_NOT_READY 0xE0000246 +#endif typedef enum { DIFXAPI_SUCCESS, diff --git a/libwdi/libusb0.inf.in b/libwdi/libusb0.inf.in index 3a6d9fdc..ad0efc3a 100644 --- a/libwdi/libusb0.inf.in +++ b/libwdi/libusb0.inf.in @@ -23,7 +23,7 @@ HKR,,,0,"libusb-win32 devices" HKR,,Icon,,-20 [Manufacturer] -%VendorName% = Devices, NT, NTAMD64 +%VendorName% = Devices, NT, NTAMD64, NTARM64 ;-------------------------------------------------------------------------- ; libusb-win32 files @@ -42,7 +42,10 @@ libusb0.sys = 1,amd64 libusb0.dll = 1,amd64 #LK_DLL# #LK_EQ_X64# libusb0_x86.dll = 1,x86 -#LK_X86_DLL# #LK_EQ_X86# + +[SourceDisksFiles.arm64] +libusb0.sys = 1,arm64 +libusb0.dll = 1,arm64 [DestinationDirs] libusb_files_sys = 10,system32\drivers @@ -73,6 +76,8 @@ CopyFiles = libusb_files_sys, libusb_files_dll_x86 [LIBUSB_WIN32_DEV.NTAMD64] CopyFiles = libusb_files_sys, libusb_files_dll, libusb_files_dll_wow64 +[LIBUSB_WIN32_DEV.NTARM64] +CopyFiles = libusb_files_sys, libusb_files_dll [LIBUSB_WIN32_DEV.NT.HW] DelReg = libusb_del_reg_hw AddReg = libusb_add_reg_hw @@ -81,12 +86,19 @@ AddReg = libusb_add_reg_hw DelReg = libusb_del_reg_hw AddReg = libusb_add_reg_hw +[LIBUSB_WIN32_DEV.NTARM64.HW] +DelReg = libusb_del_reg_hw +AddReg = libusb_add_reg_hw + [LIBUSB_WIN32_DEV.NT.Services] AddService = libusb0, 0x00000002, libusb_add_service [LIBUSB_WIN32_DEV.NTAMD64.Services] AddService = libusb0, 0x00000002, libusb_add_service +[LIBUSB_WIN32_DEV.NTARM64.Services] +AddService = libusb0, 0x00000002, libusb_add_service + ; Older versions of this .inf file installed filter drivers. They are not ; needed any more and must be removed [libusb_del_reg_hw] @@ -129,3 +141,6 @@ ServiceBinary = %12%\libusb0.sys [Devices.NTAMD64] %DeviceName% = LIBUSB_WIN32_DEV.NTAMD64, USB\%DeviceID% + +[Devices.NTARM64] +%DeviceName% = LIBUSB_WIN32_DEV.NTARM64, USB\%DeviceID% diff --git a/libwdi/libusbk.inf.in b/libwdi/libusbk.inf.in index 5707984d..c6351d3e 100644 --- a/libwdi/libusbk.inf.in +++ b/libwdi/libusbk.inf.in @@ -58,7 +58,7 @@ AddReg=#USE_DEVICE_INTERFACE_GUID# [AddDeviceInterfaceGUID] HKR,,DeviceInterfaceGUIDs, 0x10000,%DeviceGUID% -; ========== Driver/Servce section ============== +; ========== Driver/Service section ============== [LUsbK_Device.NT.Services] Addservice=libusbK,2,LUsbK_AddService diff --git a/libwdi/libwdi.c b/libwdi/libwdi.c index c6c20f01..1501b45d 100644 --- a/libwdi/libwdi.c +++ b/libwdi/libwdi.c @@ -1,6 +1,6 @@ /* * Library for USB automated driver installation - * Copyright (c) 2010-2017 Pete Batard + * Copyright (c) 2010-2023 Pete Batard * Parts of the code from libusb by Daniel Drake, Johannes Erdfelt et al. * For more info, please visit http://libwdi.akeo.ie * @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "installer.h" #include "libwdi.h" @@ -54,49 +56,210 @@ static BOOL filter_driver = FALSE; static DWORD timeout = DEFAULT_TIMEOUT; static HANDLE pipe_handle = INVALID_HANDLE_VALUE; static VS_FIXEDFILEINFO driver_version[WDI_NB_DRIVERS-1] = { {0}, {0}, {0}, {0} }; -static const char* driver_name[WDI_NB_DRIVERS-1] = {"winusbcoinstaller2.dll", "libusb0.sys", "libusbK.sys", ""}; +static const char* driver_name[WDI_NB_DRIVERS-1] = {"winusbcoinstaller2.dll", "libusb0.dll", "libusbK.dll", ""}; static const char* inf_template[WDI_NB_DRIVERS-1] = {"winusb.inf.in", "libusb0.inf.in", "libusbk.inf.in", "usbser.inf.in"}; static const char* cat_template[WDI_NB_DRIVERS-1] = {"winusb.cat.in", "libusb0.cat.in", "libusbk.cat.in", "usbser.cat.in"}; static const char* ms_compat_id[WDI_NB_DRIVERS-1] = {"MS_COMP_WINUSB", "MS_COMP_LIBUSB0", "MS_COMP_LIBUSBK", "MS_COMP_USBSER"}; int nWindowsVersion = WINDOWS_UNDEFINED; +int nWindowsBuildNumber = -1; char WindowsVersionStr[128] = "Windows "; // Detect Windows version #define GET_WINDOWS_VERSION do { if (nWindowsVersion == WINDOWS_UNDEFINED) GetWindowsVersion(); } while(0) -BOOL is_x64(void) +static __inline USHORT GetApplicationArch(void) { - BOOL ret = FALSE; - // Detect if we're running a 32 or 64 bit system - if (sizeof(uintptr_t) < 8) { - IsWow64Process(GetCurrentProcess(), &ret); - } else { - ret = TRUE; +#if defined(_M_AMD64) + return IMAGE_FILE_MACHINE_AMD64; +#elif defined(_M_IX86) + return IMAGE_FILE_MACHINE_I386; +#elif defined(_M_ARM64) + return IMAGE_FILE_MACHINE_ARM64; +#elif defined(_M_ARM) + return IMAGE_FILE_MACHINE_ARM; +#else + return IMAGE_FILE_MACHINE_UNKNOWN; +#endif +} + +static __inline const char* GetArchName(USHORT uArch) +{ + switch (uArch) { + case IMAGE_FILE_MACHINE_AMD64: + return "x64"; + case IMAGE_FILE_MACHINE_I386: + return "x86"; + case IMAGE_FILE_MACHINE_ARM64: + return "arm64"; + case IMAGE_FILE_MACHINE_ARM: + return "arm"; + default: + return "unknown"; } - return ret; } -// From smartmontools os_win32.cpp +// Detect the underlying platform arch. +static USHORT GetPlatformArch(void) +{ + BOOL is_64bit = FALSE, is_wow64 = FALSE; + USHORT ProcessMachine = IMAGE_FILE_MACHINE_UNKNOWN, NativeMachine = IMAGE_FILE_MACHINE_UNKNOWN; + + PF_DECL_LIBRARY(Kernel32); + PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process2, (HANDLE, USHORT*, USHORT*)); + PF_LOAD_LIBRARY(Kernel32); + PF_INIT(IsWow64Process2, Kernel32); + + if ((pfIsWow64Process2 == NULL) || + !pfIsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine)) { + // Assume same arch as the app + NativeMachine = GetApplicationArch(); + // Fix the Arch if we have a 32-bit app running under WOW64 + if ((sizeof(uintptr_t) < 8) && IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64) { + if (NativeMachine == IMAGE_FILE_MACHINE_I386) + NativeMachine = IMAGE_FILE_MACHINE_AMD64; + else if (NativeMachine == IMAGE_FILE_MACHINE_ARM) + NativeMachine = IMAGE_FILE_MACHINE_ARM64; + else // I sure wanna be made aware of this scenario... + assert(FALSE); + } + wdi_warn("Note: Underlying Windows architecture was guessed and may be incorrect..."); + } + + PF_FREE_LIBRARY(Kernel32); + return NativeMachine; +} + +static const char* GetEdition(DWORD ProductType) +{ + static char unknown_edition_str[64]; + + // From: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getproductinfo + // These values can be found in the winnt.h header. + switch (ProductType) { + case 0x00000000: return ""; // Undefined + case 0x00000001: return "Ultimate"; + case 0x00000002: return "Home Basic"; + case 0x00000003: return "Home Premium"; + case 0x00000004: return "Enterprise"; + case 0x00000005: return "Home Basic N"; + case 0x00000006: return "Business"; + case 0x00000007: return "Server Standard"; + case 0x00000008: return "Server Datacenter"; + case 0x00000009: return "Smallbusiness Server"; + case 0x0000000A: return "Server Enterprise"; + case 0x0000000B: return "Starter"; + case 0x0000000C: return "Server Datacenter (Core)"; + case 0x0000000D: return "Server Standard (Core)"; + case 0x0000000E: return "Server Enterprise (Core)"; + case 0x00000010: return "Business N"; + case 0x00000011: return "Web Server"; + case 0x00000012: return "HPC Edition"; + case 0x00000013: return "Storage Server (Essentials)"; + case 0x0000001A: return "Home Premium N"; + case 0x0000001B: return "Enterprise N"; + case 0x0000001C: return "Ultimate N"; + case 0x00000022: return "Home Server"; + case 0x00000024: return "Server Standard without Hyper-V"; + case 0x00000025: return "Server Datacenter without Hyper-V"; + case 0x00000026: return "Server Enterprise without Hyper-V"; + case 0x00000027: return "Server Datacenter without Hyper-V (Core)"; + case 0x00000028: return "Server Standard without Hyper-V (Core)"; + case 0x00000029: return "Server Enterprise without Hyper-V (Core)"; + case 0x0000002A: return "Hyper-V Server"; + case 0x0000002F: return "Starter N"; + case 0x00000030: return "Pro"; + case 0x00000031: return "Pro N"; + case 0x00000034: return "Server Solutions Premium"; + case 0x00000035: return "Server Solutions Premium (Core)"; + case 0x00000040: return "Server Hyper Core V"; + case 0x00000042: return "Starter E"; + case 0x00000043: return "Home Basic E"; + case 0x00000044: return "Premium E"; + case 0x00000045: return "Pro E"; + case 0x00000046: return "Enterprise E"; + case 0x00000047: return "Ultimate E"; + case 0x00000048: return "Enterprise (Eval)"; + case 0x0000004F: return "Server Standard (Eval)"; + case 0x00000050: return "Server Datacenter (Eval)"; + case 0x00000054: return "Enterprise N (Eval)"; + case 0x00000057: return "Thin PC"; + case 0x00000058: case 0x00000059: case 0x0000005A: case 0x0000005B: case 0x0000005C: return "Embedded"; + case 0x00000062: return "Home N"; + case 0x00000063: return "Home China"; + case 0x00000064: return "Home Single Language"; + case 0x00000065: return "Home"; + case 0x00000067: return "Pro with Media Center"; + case 0x00000069: case 0x0000006A: case 0x0000006B: case 0x0000006C: return "Embedded"; + case 0x0000006F: return "Home Connected"; + case 0x00000070: return "Pro Student"; + case 0x00000071: return "Home Connected N"; + case 0x00000072: return "Pro Student N"; + case 0x00000073: return "Home Connected Single Language"; + case 0x00000074: return "Home Connected China"; + case 0x00000079: return "Education"; + case 0x0000007A: return "Education N"; + case 0x0000007D: return "Enterprise LTSB"; + case 0x0000007E: return "Enterprise LTSB N"; + case 0x0000007F: return "Pro S"; + case 0x00000080: return "Pro S N"; + case 0x00000081: return "Enterprise LTSB (Eval)"; + case 0x00000082: return "Enterprise LTSB N (Eval)"; + case 0x0000008A: return "Pro Single Language"; + case 0x0000008B: return "Pro China"; + case 0x0000008C: return "Enterprise Subscription"; + case 0x0000008D: return "Enterprise Subscription N"; + case 0x00000091: return "Server Datacenter SA (Core)"; + case 0x00000092: return "Server Standard SA (Core)"; + case 0x00000095: return "Utility VM"; + case 0x000000A1: return "Pro for Workstations"; + case 0x000000A2: return "Pro for Workstations N"; + case 0x000000A4: return "Pro for Education"; + case 0x000000A5: return "Pro for Education N"; + case 0x000000AB: return "Enterprise G"; // I swear Microsoft are just making up editions... + case 0x000000AC: return "Enterprise G N"; + case 0x000000B2: return "Cloud"; + case 0x000000B3: return "Cloud N"; + case 0x000000B6: return "Home OS"; + case 0x000000B7: case 0x000000CB: return "Cloud E"; + case 0x000000B9: return "IoT OS"; + case 0x000000BA: case 0x000000CA: return "Cloud E N"; + case 0x000000BB: return "IoT Edge OS"; + case 0x000000BC: return "IoT Enterprise"; + case 0x000000BD: return "Lite"; + case 0x000000BF: return "IoT Enterprise S"; + case 0x000000C0: case 0x000000C2: case 0x000000C3: case 0x000000C4: case 0x000000C5: case 0x000000C6: return "XBox"; + case 0x000000C7: case 0x000000C8: case 0x00000196: case 0x00000197: case 0x00000198: return "Azure Server"; + case 0xABCDABCD: return "(Unlicensed)"; + default: + static_sprintf(unknown_edition_str, "(Unknown Edition 0x%02X)", (uint32_t)ProductType); + return unknown_edition_str; + } +} + +/* + * Modified from smartmontools' os_win32.cpp + */ void GetWindowsVersion(void) { OSVERSIONINFOEXA vi, vi2; - const char* w = 0; - const char* w64 = "32 bit"; - char *vptr, build_number[10] = ""; + DWORD dwProductType; + const char* w = NULL; + const char* arch_name; + char* vptr; size_t vlen; unsigned major, minor; ULONGLONG major_equal, minor_equal; BOOL ws; nWindowsVersion = WINDOWS_UNDEFINED; - safe_strcpy(WindowsVersionStr, sizeof(WindowsVersionStr), "Windows Undefined"); + static_strcpy(WindowsVersionStr, "Windows Undefined"); memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(vi); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { + if (!GetVersionExA((OSVERSIONINFOA*)&vi)) { memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); - if (!GetVersionExA((OSVERSIONINFOA *)&vi)) + if (!GetVersionExA((OSVERSIONINFOA*)&vi)) return; } @@ -136,91 +299,115 @@ void GetWindowsVersion(void) ws = (vi.wProductType <= VER_NT_WORKSTATION); nWindowsVersion = vi.dwMajorVersion << 4 | vi.dwMinorVersion; switch (nWindowsVersion) { - case 0x61: w = (ws ? "7" : "2008_R2"); + case WINDOWS_XP: w = "XP"; + break; + case WINDOWS_2003: w = (ws ? "XP_64" : (!GetSystemMetrics(89) ? "Server 2003" : "Server 2003_R2")); break; - case 0x62: w = (ws ? "8" : "2012"); + case WINDOWS_VISTA: w = (ws ? "Vista" : "Server 2008"); break; - case 0x63: w = (ws ? "8.1" : "2012_R2"); + case WINDOWS_7: w = (ws ? "7" : "Server 2008_R2"); break; - case 0x64: w = (ws ? "10 (Preview 1)" : "Server 10 (Preview 1)"); + case WINDOWS_8: w = (ws ? "8" : "Server 2012"); + break; + case WINDOWS_8_1: w = (ws ? "8.1" : "Server 2012_R2"); + break; + case WINDOWS_10_PREVIEW1: w = (ws ? "10 (Preview 1)" : "Server 10 (Preview 1)"); break; // Starting with Windows 10 Preview 2, the major is the same as the public-facing version - case 0xA0: w = (ws ? "10" : "Server 10"); + case WINDOWS_10: + if (vi.dwBuildNumber < 20000) { + w = (ws ? "10" : ((vi.dwBuildNumber < 17763) ? "Server 2016" : "Server 2019")); + break; + } + nWindowsVersion = WINDOWS_11; + // Fall through + case WINDOWS_11: w = (ws ? "11" : "Server 2022"); break; default: - if (nWindowsVersion < 0x61) + if (nWindowsVersion < WINDOWS_XP) nWindowsVersion = WINDOWS_UNSUPPORTED; else - w = "11 or later"; + w = "12 or later"; break; } } } - if (is_x64()) - w64 = "64-bit"; + arch_name = GetArchName(GetPlatformArch()); + GetProductInfo(vi.dwMajorVersion, vi.dwMinorVersion, vi.wServicePackMajor, vi.wServicePackMinor, &dwProductType); vptr = &WindowsVersionStr[sizeof("Windows ") - 1]; vlen = sizeof(WindowsVersionStr) - sizeof("Windows ") - 1; if (!w) safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), - (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64); + (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, arch_name); else if (vi.wServicePackMinor) - safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); + safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch_name); else if (vi.wServicePackMajor) - safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64); + safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, arch_name); else - safe_sprintf(vptr, vlen, "%s %s", w, w64); + safe_sprintf(vptr, vlen, "%s%s%s, %s", + w, (dwProductType != PRODUCT_UNDEFINED) ? " " : "", GetEdition(dwProductType), arch_name); - // Add the build number for Windows 8.0 and later + // Add the build number (including UBR if available) for Windows 8.0 and later + nWindowsBuildNumber = vi.dwBuildNumber; if (nWindowsVersion >= 0x62) { - ReadRegistryStr(REGKEY_HKLM, "Microsoft\\Windows NT\\CurrentVersion\\CurrentBuildNumber", build_number, sizeof(build_number)); - if (build_number[0] != 0) { - safe_strcat(WindowsVersionStr, sizeof(WindowsVersionStr), " (Build "); - safe_strcat(WindowsVersionStr, sizeof(WindowsVersionStr), build_number); - safe_strcat(WindowsVersionStr, sizeof(WindowsVersionStr), ")"); - } + HKEY hCurrentVersion; + DWORD dwType = REG_DWORD, dwSize = sizeof(DWORD), dwUbr = 0; + if (RegOpenKeyExA(REGKEY_HKLM, "Software\\Microsoft\\Windows NT\\CurrentVersion", + 0, KEY_READ, &hCurrentVersion) == ERROR_SUCCESS) { + RegQueryValueExA(hCurrentVersion, "UBR", NULL, &dwType, (LPBYTE)&dwUbr, &dwSize); + RegCloseKey(hCurrentVersion); + } + + vptr = &WindowsVersionStr[safe_strlen(WindowsVersionStr)]; + vlen = sizeof(WindowsVersionStr) - safe_strlen(WindowsVersionStr) - 1; + if (dwUbr != 0) + safe_sprintf(vptr, vlen, " (Build %d.%d)", nWindowsBuildNumber, (int)dwUbr); + else + safe_sprintf(vptr, vlen, " (Build %d)", nWindowsBuildNumber); } - } + /* * Converts a windows error to human readable string * uses retval as errorcode, or, if 0, use GetLastError() */ -char *windows_error_str(uint32_t retval) +char *wdi_windows_error_str(DWORD retval) { -static char err_string[STR_BUFFER_SIZE]; - - DWORD size; - size_t i; - uint32_t error_code, format_error; + static char err_string[STR_BUFFER_SIZE]; + DWORD size, presize, error_code, format_error; - error_code = retval?retval:GetLastError(); + error_code = retval ? retval : GetLastError(); - safe_sprintf(err_string, STR_BUFFER_SIZE, "[#%08X] ", error_code); + static_sprintf(err_string, "[0x%08lX] ", error_code); + presize = (DWORD)strlen(err_string); - size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)], - STR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL); + size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + HRESULT_CODE(error_code), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + &err_string[presize], (DWORD)(sizeof(err_string) - strlen(err_string)), NULL); if (size == 0) { format_error = GetLastError(); - if (format_error) - safe_sprintf(err_string, STR_BUFFER_SIZE, - "Windows error code %u (FormatMessage error code %u)", error_code, format_error); + if ((format_error) && (format_error != ERROR_MR_MID_NOT_FOUND) && (format_error != ERROR_MUI_FILE_NOT_LOADED)) + static_sprintf(err_string, "Windows error code 0x%08lX (FormatMessage error code 0x%08lX)", + error_code, format_error); else - safe_sprintf(err_string, STR_BUFFER_SIZE, "Unknown error code %u", error_code); + static_sprintf(err_string, "Windows error code 0x%08lX", error_code); } else { - // Remove CR/LF terminators - for (i=safe_strlen(err_string)-1; ((err_string[i]==0x0A) || (err_string[i]==0x0D)); i--) { - err_string[i] = 0; - } + // Microsoft may suffix CRLF to error messages, which we need to remove... + assert(presize > 2); + size += presize - 2; + // Cannot underflow if the above assert passed since our first char is neither of the following + while ((err_string[size] == 0x0D) || (err_string[size] == 0x0A) || (err_string[size] == 0x20)) + err_string[size--] = 0; } + + SetLastError(error_code); // Make sure we don't change the errorcode on exit return err_string; } - // 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; @@ -228,13 +415,13 @@ static PSID get_sid(void) { char* psid_string = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { - wdi_err("OpenProcessToken failed: %s", windows_error_str(0)); + wdi_err("OpenProcessToken failed: %s", wdi_windows_error_str(0)); return NULL; } if (!GetTokenInformation(token, TokenUser, tu, 0, &len)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - wdi_err("GetTokenInformation (pre) failed: %s", windows_error_str(0)); + wdi_err("GetTokenInformation (pre) failed: %s", wdi_windows_error_str(0)); return NULL; } tu = (TOKEN_USER*)calloc(1, len); @@ -250,11 +437,11 @@ static PSID get_sid(void) { * The workaround? Convert to string then back to PSID */ if (!ConvertSidToStringSidA(tu->User.Sid, &psid_string)) { - wdi_err("unable to convert SID to string: %s", windows_error_str(0)); + wdi_err("Unable to convert SID to string: %s", wdi_windows_error_str(0)); ret = NULL; } else { if (!ConvertStringSidToSidA(psid_string, &ret)) { - wdi_err("unable to convert string back to SID: %s", windows_error_str(0)); + wdi_err("Unable to convert string back to SID: %s", wdi_windows_error_str(0)); ret = NULL; } // MUST use LocalFree() @@ -262,7 +449,7 @@ static PSID get_sid(void) { } } else { ret = NULL; - wdi_err("GetTokenInformation (real) failed: %s", windows_error_str(0)); + wdi_err("GetTokenInformation (real) failed: %s", wdi_windows_error_str(0)); } free(tu); return ret; @@ -288,7 +475,7 @@ static int check_dir(const char* path, BOOL create) case ERROR_PATH_NOT_FOUND: break; default: - wdi_err("unable to read file attributes %s", windows_error_str(0)); + wdi_err("Unable to read file attributes %s", wdi_windows_error_str(0)); return WDI_ERROR_ACCESS; } } else { @@ -297,18 +484,18 @@ static int check_dir(const char* path, BOOL create) return WDI_SUCCESS; } else { // File with the same name as the dir we want to create - wdi_err("%s is a file, not a directory", path); + wdi_err("'%s' is a file, not a directory", path); return WDI_ERROR_ACCESS; } } if (!create) { - wdi_err("%s doesn't exist", path); + wdi_err("'%s' does not exist", path); return WDI_ERROR_ACCESS; } // 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) ) { @@ -317,7 +504,7 @@ static int check_dir(const char* path, BOOL create) s_attr.lpSecurityDescriptor = &s_desc; ps = &s_attr; } else { - wdi_err("could not set security descriptor: %s", windows_error_str(0)); + wdi_err("Could not set security descriptor: %s", wdi_windows_error_str(0)); } // SHCreateDirectoryEx creates subdirectories as required @@ -326,7 +513,7 @@ static int check_dir(const char* path, BOOL create) // A relative path was used => Convert to full full_path = (char*)malloc(MAX_PATH); if (full_path == NULL) { - wdi_err("could not allocate buffer to convert relative path"); + wdi_err("Could not allocate buffer to convert relative path"); if (sid != NULL) LocalFree(sid); return WDI_ERROR_RESOURCE; } @@ -342,10 +529,10 @@ static int check_dir(const char* path, BOOL create) case ERROR_SUCCESS: return WDI_SUCCESS; case ERROR_FILENAME_EXCED_RANGE: - wdi_err("directory name is too long %s", path); + wdi_err("Directory name '%s' is too long", path); return WDI_ERROR_INVALID_PARAM; default: - wdi_err("unable to create directory %s (%s)", path, windows_error_str(0)); + wdi_err("Unable to create directory '%s' (%s)", path, wdi_windows_error_str(0)); return WDI_ERROR_ACCESS; } @@ -385,7 +572,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) ) { @@ -394,7 +581,7 @@ static FILE *fopen_as_userU(const char *filename, const char *mode) s_attr.lpSecurityDescriptor = &s_desc; ps = &s_attr; } else { - wdi_err("could not set security descriptor: %s", windows_error_str(0)); + wdi_err("Could not set security descriptor: %s", wdi_windows_error_str(0)); } handle = CreateFileU(filename, access_mode, FILE_SHARE_READ, @@ -462,7 +649,7 @@ int get_version_info(int driver_type, VS_FIXEDFILEINFO* driver_info) // First, we need a physical file => extract it tmpdir = getenvU("TEMP"); if (tmpdir == NULL) { - wdi_warn("unable to use TEMP to extract file"); + wdi_warn("Unable to use TEMP to extract file"); r = WDI_ERROR_RESOURCE; goto out; } @@ -480,7 +667,7 @@ int get_version_info(int driver_type, VS_FIXEDFILEINFO* driver_info) fd = fopen_as_userU(filename, "w"); if (fd == NULL) { - wdi_warn("failed to create file '%s' (%s)", filename, windows_error_str(0)); + wdi_warn("Failed to create file '%s' (%s)", filename, wdi_windows_error_str(0)); r = WDI_ERROR_RESOURCE; goto out; } @@ -503,7 +690,7 @@ int get_version_info(int driver_type, VS_FIXEDFILEINFO* driver_info) memcpy(&driver_version[driver_type], file_info, sizeof(VS_FIXEDFILEINFO)); memcpy(driver_info, file_info, sizeof(VS_FIXEDFILEINFO)); } else { - wdi_warn("unable to allocate buffer for version info"); + wdi_warn("Unable to allocate buffer for version info"); r = WDI_ERROR_RESOURCE; } safe_free(wfilename); @@ -517,8 +704,13 @@ int get_version_info(int driver_type, VS_FIXEDFILEINFO* driver_info) // Find out if the driver selected is actually embedded in this version of the library +// or supported by the underlying platform architecture. BOOL LIBWDI_API wdi_is_driver_supported(int driver_type, VS_FIXEDFILEINFO* driver_info) { +#if (defined(LIBUSB0_DIR) || defined(LIBUSBK_DIR)) + USHORT platform_arch = GetPlatformArch(); +#endif + if (driver_type < WDI_USER) { // github issue #40 if (driver_type != WDI_CDC) { // The CDC driver does not have embedded binaries @@ -538,13 +730,13 @@ BOOL LIBWDI_API wdi_is_driver_supported(int driver_type, VS_FIXEDFILEINFO* drive #endif case WDI_LIBUSB0: #if defined(LIBUSB0_DIR) - return TRUE; + return (platform_arch == IMAGE_FILE_MACHINE_ARM64 || platform_arch == IMAGE_FILE_MACHINE_AMD64 || platform_arch == IMAGE_FILE_MACHINE_I386); #else return FALSE; #endif case WDI_LIBUSBK: #if defined(LIBUSBK_DIR) - return TRUE; + return (platform_arch == IMAGE_FILE_MACHINE_AMD64 || platform_arch == IMAGE_FILE_MACHINE_I386); #else return FALSE; #endif @@ -557,7 +749,7 @@ BOOL LIBWDI_API wdi_is_driver_supported(int driver_type, VS_FIXEDFILEINFO* drive case WDI_CDC: return TRUE; default: - wdi_err("unknown driver type"); + wdi_err("Unknown driver type"); return FALSE; } } @@ -570,7 +762,7 @@ BOOL LIBWDI_API wdi_is_file_embedded(const char* path, const char* name) { int i; - for (i=0; idriver != NULL) { // Only produce a warning for non-driverless devices - wdi_warn("could not read driver version"); + wdi_warn("Could not read driver version"); } // Retrieve device ID. This is needed to re-enumerate our device and force // the final driver installation cr = pfCM_Get_Device_IDA(dev_info_data.DevInst, strbuf, STR_BUFFER_SIZE, 0); if (cr != CR_SUCCESS) { - wdi_err("could not retrieve simple path for device %d: CR error %d", i, cr); + wdi_err("Could not retrieve simple path for device %d: CR error %d", i, cr); continue; } else { wdi_dbg("%s USB device (%d): %s", @@ -843,13 +1036,14 @@ int LIBWDI_API wdi_create_list(struct wdi_device_info** list, // The information we want ("Bus reported device description") is accessed // through DEVPKEY_Device_BusReportedDeviceDesc + desc[0] = 0; if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &DEVPKEY_Device_BusReportedDeviceDesc, &devprop_type, (BYTE*)desc, 2*MAX_DESC_LENGTH, &size, 0)) { // fallback to SPDRP_DEVICEDESC (USB hubs still use it) if (!SetupDiGetDeviceRegistryPropertyW(dev_info, &dev_info_data, SPDRP_DEVICEDESC, - ®_type, (BYTE*)desc, 2*MAX_DESC_LENGTH, &size)) { - wdi_dbg("could not read device description for %d: %s", - i, windows_error_str(0)); + ®_type, (BYTE*)desc, 2*MAX_DESC_LENGTH, &size) || (desc[0] == 0)) { + wdi_dbg("Could not read device description for %d: %s", + i, wdi_windows_error_str(0)); safe_swprintf(desc, MAX_DESC_LENGTH, L"Unknown Device #%d", unknown_count++); } } @@ -864,7 +1058,7 @@ int LIBWDI_API wdi_create_list(struct wdi_device_info** list, switch(j) { case 0: if (sscanf(token, "VID_%04X", &tmp) != 1) { - wdi_err("could not convert VID string"); + wdi_err("Could not convert VID string"); } else { device_info->vid = (unsigned short)tmp; } @@ -872,14 +1066,14 @@ int LIBWDI_API wdi_create_list(struct wdi_device_info** list, break; case 1: if (sscanf(token, "PID_%04X", &tmp) != 1) { - wdi_err("could not convert PID string"); + wdi_err("Could not convert PID string"); } else { device_info->pid = (unsigned short)tmp; } break; case 2: if (sscanf(token, "MI_%02X", &tmp) != 1) { - wdi_err("could not convert MI string"); + wdi_err("Could not convert MI string"); } else { device_info->is_composite = TRUE; device_info->mi = (unsigned char)tmp; @@ -890,7 +1084,7 @@ int LIBWDI_API wdi_create_list(struct wdi_device_info** list, } break; default: - wdi_err("unexpected case"); + wdi_err("Program assertion failed - Unexpected case"); break; } } @@ -983,13 +1177,13 @@ static int extract_binaries(const char* path) safe_strcat(filename, MAX_PATH, resource[i].name); if ( (safe_strlen(path) + safe_strlen(resource[i].subdir) + safe_strlen(resource[i].name)) > (MAX_PATH - 3)) { - wdi_err("qualified path is too long: '%s'", filename); + wdi_err("Qualified path is too long: '%s'", filename); return WDI_ERROR_RESOURCE; } fd = fopen_as_userU(filename, "w"); if (fd == NULL) { - wdi_err("failed to create file '%s' (%s)", filename, windows_error_str(0)); + wdi_err("Could not create file '%s' (%s)", filename, wdi_windows_error_str(0)); return WDI_ERROR_RESOURCE; } @@ -997,13 +1191,13 @@ static int extract_binaries(const char* path) fclose(fd); } - wdi_info("successfully extracted driver files to %s", path); + wdi_info("Successfully extracted driver files to '%s'", path); return WDI_SUCCESS; } -// tokenizes a resource stored in resource.h -static long tokenize_internal(const char* resource_name, char** dst, const token_entity_t* token_entities, - const char* tok_prefix, const char* tok_suffix, int recursive) +// tokenizes a resource stored in resource.h and write it to file +static long wdi_tokenize_resource(const char* resource_name, char** dst, const token_entity_t* token_entities, + const char* tok_prefix, const char* tok_suffix, int recursive) { int i; @@ -1020,11 +1214,50 @@ static long tokenize_internal(const char* resource_name, char** dst, const token return -ERROR_RESOURCE_DATA_NOT_FOUND; } +// tokenizes an external file pointed by into destination file +static long wdi_tokenize_file(const char* src, char** dst, const token_entity_t* token_entities, + const char* tok_prefix, const char* tok_suffix, int recursive) +{ + FILE* fd = NULL; + long size, ret = -ERROR_RESOURCE_DATA_NOT_FOUND; + char* buffer = NULL; + + fd = fopen(src, "r"); + if (fd == NULL) + goto out; + fseek(fd, 0L, SEEK_END); + size = ftell(fd); + if (size < 0) + goto out; + fseek(fd, 0L, SEEK_SET); + // +1 for NUL terminator since we pass the whole file as a text string + buffer = (char*)calloc(size + 1, 1); + if (buffer == NULL) { + wdi_err("Could not allocate tokenization buffer"); + ret = WDI_ERROR_RESOURCE; + goto out; + } + if (fread(buffer, 1, size, fd) != size) { + wdi_err("Could not read file to tokenize"); + ret = -ERROR_RESOURCE_DATA_NOT_FOUND; + goto out; + } + ret = tokenize_string(buffer, size, dst, token_entities, tok_prefix, tok_suffix, recursive); + +out: + free(buffer); + if (fd) + fclose(fd); + return ret; +} + #define CAT_LIST_MAX_ENTRIES 16 // Create an inf and extract coinstallers in the directory pointed by path int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const char* path, - const char* inf_name, struct wdi_options_prepare_driver* options) + const char* inf, struct wdi_options_prepare_driver* options) { + PF_DECL_LIBRARY(Ntdll); + PF_TYPE_DECL(NTAPI, NTSTATUS, NtQuerySystemInformation, (SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG)); const wchar_t bom = 0xFEFF; #if defined(ENABLE_DEBUG_LOGGING) || defined(INCLUDE_DEBUG_LOGGING) const char* driver_display_name[WDI_NB_DRIVERS] = { "WinUSB", "libusb0.sys", "libusbK.sys", "Generic USB CDC", "user driver" }; @@ -1033,34 +1266,39 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha const char* vendor_name = NULL; const char* cat_list[CAT_LIST_MAX_ENTRIES+1]; char drv_path[MAX_PATH], inf_path[MAX_PATH], cat_path[MAX_PATH], hw_id[40], cert_subject[64]; - char *strguid, *token, *cat_name = NULL, *dst = NULL, *cat_in_copy = NULL; + char *strguid, *token, *cat_name = NULL, *dst = NULL, *inf_name; wchar_t *wdst = NULL; int i, nb_entries, driver_type = WDI_WINUSB, r = WDI_ERROR_OTHER; long inf_file_size, cat_file_size; - BOOL is_android_device = FALSE; + BOOL is_android_device = FALSE, is_test_signing_enabled = FALSE; FILE* fd; GUID guid; SYSTEMTIME system_time; FILETIME file_time, local_time; + SYSTEM_CODEINTEGRITY_INFORMATION sci = { 0 }; + ULONG dwcbSz = 0; MUTEX_START; GET_WINDOWS_VERSION; if (nWindowsVersion < WINDOWS_7) { - wdi_err("this version of Windows is no longer supported"); + wdi_err("This version of Windows is no longer supported"); r = WDI_ERROR_NOT_SUPPORTED; goto out; } - if ((device_info == NULL) || (inf_name == NULL)) { - wdi_err("one of the required parameter is NULL"); + if ((device_info == NULL) || (inf == NULL)) { + wdi_err("One of the required parameter is NULL"); r = WDI_ERROR_INVALID_PARAM; goto out; } + // If we are dealing with a path (e.g. option 'external_inf'), remove the directory part + inf_name = (char*)filename(inf); + // Check the inf file provided and create the cat file name - if (strcmp(inf_name+safe_strlen(inf_name)-4, inf_ext) != 0) { - wdi_err("inf name provided must have a '.inf' extension"); + if (strcmp(inf_name + safe_strlen(inf_name) - 4, inf_ext) != 0) { + wdi_err("Inf name provided must have a '.inf' extension"); r = WDI_ERROR_INVALID_PARAM; goto out; } @@ -1071,13 +1309,13 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha // Try to use the user's temp dir char* tmp = getenvU("TEMP"); if (tmp == NULL) { - wdi_err("no path provided and unable to use TEMP"); + wdi_err("No path provided and unable to use TEMP"); r = WDI_ERROR_INVALID_PARAM; goto out; } else { static_strcpy(drv_path, tmp); free(tmp); - wdi_info("no path provided - extracting to '%s'", drv_path); + wdi_info("No path provided - extracting to '%s'", drv_path); } } @@ -1092,14 +1330,14 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha } // Ensure driver_type is what we expect - if ( (driver_type < 0) || (driver_type > WDI_USER) ) { - wdi_err("unknown type"); + if ((driver_type < 0) || (driver_type > WDI_USER)) { + wdi_err("Program assertion failed - Unknown driver type"); r = WDI_ERROR_INVALID_PARAM; goto out; } if (!wdi_is_driver_supported(driver_type, &driver_version[driver_type])) { - for (driver_type=0; driver_typedesc == NULL) { - wdi_err("no device ID was given for the device - aborting"); + wdi_err("No device ID was given for the device - aborting"); r = WDI_ERROR_INVALID_PARAM; goto out; } @@ -1144,7 +1382,7 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha // Populate the inf and cat names & paths if ( (strlen(drv_path) >= MAX_PATH) || (strlen(inf_name) >= MAX_PATH) || ((strlen(drv_path) + strlen(inf_name)) > (MAX_PATH - 2)) ) { - wdi_err("qualified path for inf file is too long: '%s\\%s", drv_path, inf_name); + wdi_err("Qualified path for inf file is too long: '%s\\%s", drv_path, inf_name); r = WDI_ERROR_RESOURCE; goto out; } @@ -1153,7 +1391,7 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha safe_strcat(inf_path, sizeof(inf_path), inf_name); safe_strcpy(cat_path, sizeof(cat_path), inf_path); if (safe_strlen(cat_path) < 4) { - wdi_err("qualified path for inf file is too short: '%s", cat_path); + wdi_err("Qualified path for inf file is too short: '%s", cat_path); r = WDI_ERROR_RESOURCE; goto out; } @@ -1203,7 +1441,7 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha } else if ((options != NULL) && (options->device_guid != NULL)) { strguid = options->device_guid; } else if (is_android_device) { - wdi_info("using Android Device Interface GUID"); + wdi_info("Using Android Device Interface GUID"); strguid = (char*)android_device_guid; } else { IGNORE_RETVAL(CoCreateGuid(&guid)); @@ -1228,7 +1466,7 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha // Extra check, in case somebody modifies our code if ((driver_type < 0) && (driver_type >= WDI_USER)) { - wdi_err("program assertion failed - driver_version[] index out of range"); + wdi_err("Program assertion failed - driver_version[] index out of range"); r = WDI_ERROR_OTHER; goto out; } @@ -1247,12 +1485,15 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha (int)driver_version[driver_type].dwFileVersionMS>>16, (int)driver_version[driver_type].dwFileVersionMS&0xFFFF, (int)driver_version[driver_type].dwFileVersionLS>>16, (int)driver_version[driver_type].dwFileVersionLS&0xFFFF); - // Tokenize the file - if ((inf_file_size = tokenize_internal(inf_template[driver_type], - &dst, inf_entities, "#", "#", 0)) > 0) { + // Tokenize the inf + if ((options != NULL) && (options->external_inf)) + inf_file_size = wdi_tokenize_file(inf, &dst, inf_entities, "#", "#", 0); + else + inf_file_size = wdi_tokenize_resource(inf_template[driver_type], &dst, inf_entities, "#", "#", 0); + if (inf_file_size > 0) { fd = fopen_as_userU(inf_path, "w"); if (fd == NULL) { - wdi_err("failed to create file: %s", inf_path); + wdi_err("Failed to create file: %s", inf_path); r = WDI_ERROR_ACCESS; goto out; } @@ -1260,7 +1501,7 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha // non-English locale to display properly in device manager. UTF-8 will not do. wdst = utf8_to_wchar(dst); if (wdst == NULL) { - wdi_err("could not convert '%s' to UTF-16", dst); + wdi_err("Could not convert '%s' to UTF-16", dst); safe_free(dst); r = WDI_ERROR_RESOURCE; goto out; @@ -1271,11 +1512,11 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha safe_free(wdst); safe_free(dst); } else { - wdi_err("could not tokenize inf file (%d)", inf_file_size); + wdi_err("Could not tokenize inf file (%d)", inf_file_size); r = WDI_ERROR_ACCESS; goto out; } - wdi_info("successfully created '%s'", inf_path); + wdi_info("Successfully created '%s'", inf_path); if (IsUserAnAdmin()) { // Try to create and self-sign the cat file to remove security prompts @@ -1287,9 +1528,9 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha wdi_info("Creating and self-signing a .cat file..."); // Tokenize the cat file (for WDF version) - if ((cat_file_size = tokenize_internal(cat_template[driver_type], + if ((cat_file_size = wdi_tokenize_resource(cat_template[driver_type], &dst, inf_entities, "#", "#", 0)) <= 0) { - wdi_err("could not tokenize inf file (%d)", inf_file_size); + wdi_err("Could not tokenize cat file (%d)", cat_file_size); r = WDI_ERROR_ACCESS; goto out; } @@ -1302,10 +1543,11 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha while (isspace(*token)) token++; while (strlen(token) && isspace(token[strlen(token)-1])) token[strlen(token)-1] = 0; - if ((*token == '#') || (*token == 0)) continue; + if ((*token == '#') || (*token == 0)) + continue; cat_list[nb_entries++] = token; if (nb_entries >= CAT_LIST_MAX_ENTRIES) { - wdi_warn("more than %d cat entries - ignoring the rest", CAT_LIST_MAX_ENTRIES); + wdi_warn("More than %d cat entries - ignoring the rest", CAT_LIST_MAX_ENTRIES); break; } } while ((token = strtok(NULL, "\n\r")) != NULL); @@ -1314,18 +1556,35 @@ int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const cha cat_list[nb_entries++] = inf_name; // the DEVICE_HARDWARE_ID is either "VID_####&PID_####[&MI_##]" or the MS Compatible ID - sprintf(hw_id, "USB\\%s", ((options != NULL) && (options->use_wcid_driver))? + static_sprintf(hw_id, "USB\\%s", ((options != NULL) && (options->use_wcid_driver))? ms_compat_id[driver_type]:inf_entities[DEVICE_HARDWARE_ID].replace); - sprintf(cert_subject, "CN=%s (libwdi autogenerated)", hw_id); + static_sprintf(cert_subject, "CN=%s (libwdi autogenerated)", hw_id); - // Failures on the following aren't fatal errors + // Check if testsigning is enabled + // https://social.msdn.microsoft.com/Forums/Windowsapps/en-US/e6c1be93-7003-4594-b8e4-18ab4a75d273/detecting-testsigning-onoff-via-api + PF_INIT(NtQuerySystemInformation, Ntdll); + if (pfNtQuerySystemInformation != NULL) { + sci.Length = sizeof(sci); + if (pfNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x67, &sci, sizeof(sci), &dwcbSz) >= 0 && dwcbSz == sizeof(sci)) + is_test_signing_enabled = !!(sci.CodeIntegrityOptions & 0x02); + wdi_info("Test signing is: %s", is_test_signing_enabled ? "Enabled" : "Disabled"); + } + + // Failures on the following are fatal on Windows 10 when test signing is not enabled if (!CreateCat(cat_path, hw_id, drv_path, cat_list, nb_entries)) { - wdi_warn("could not create cat file"); + if (nWindowsVersion >= WINDOWS_10 && !is_test_signing_enabled) { + wdi_err("Could not create cat file"); + return WDI_ERROR_CAT_MISSING; + } + wdi_warn("Could not create cat file"); } else if ((options != NULL) && (!options->disable_signing) && (!SelfSignFile(cat_path, (options->cert_subject != NULL)?options->cert_subject:cert_subject))) { - wdi_warn("could not sign cat file"); + if (nWindowsVersion >= WINDOWS_10 && !is_test_signing_enabled) { + wdi_err("Could not sign cat file"); + return WDI_ERROR_UNSIGNED; + } + wdi_warn("Could not sign cat file"); } - safe_free(cat_in_copy); safe_free(dst); } else { wdi_info("No .cat file generated (missing elevated privileges)"); @@ -1347,7 +1606,7 @@ static int process_message(char* buffer, DWORD size) return WDI_ERROR_INVALID_PARAM; if (current_device == NULL) { - wdi_err("program assertion failed - no current device"); + wdi_err("Program assertion failed - no current device"); return WDI_ERROR_NOT_FOUND; } @@ -1365,71 +1624,85 @@ static int process_message(char* buffer, DWORD size) switch(buffer[0]) { case IC_GET_DEVICE_ID: - wdi_dbg("got request for device_id"); + wdi_dbg("Got request for device_id"); if (current_device->device_id != NULL) { WriteFile(pipe_handle, current_device->device_id, (DWORD)safe_strlen(current_device->device_id), &tmp, NULL); } else { - wdi_dbg("no device_id - sending empty string"); + wdi_dbg("No device_id - sending empty string"); WriteFile(pipe_handle, "\0", 1, &tmp, NULL); } break; case IC_GET_HARDWARE_ID: - wdi_dbg("got request for hardware_id"); + wdi_dbg("Got request for hardware_id"); if (current_device->hardware_id != NULL) { WriteFile(pipe_handle, current_device->hardware_id, (DWORD)safe_strlen(current_device->hardware_id), &tmp, NULL); } else { - wdi_dbg("no hardware_id - sending empty string"); + wdi_dbg("No hardware_id - sending empty string"); WriteFile(pipe_handle, "\0", 1, &tmp, NULL); } break; case IC_PRINT_MESSAGE: if (size < 2) { - wdi_err("print_message: no data"); + wdi_err("Print_message: no data"); return WDI_ERROR_NOT_FOUND; } wdi_log(WDI_LOG_LEVEL_DEBUG, "installer process", "%s", buffer+1); break; case IC_SYSLOG_MESSAGE: if (size < 2) { - wdi_err("syslog_message: no data"); + wdi_err("Syslog_message: no data"); return WDI_ERROR_NOT_FOUND; } wdi_log(WDI_LOG_LEVEL_DEBUG, "syslog", "%s", buffer+1); break; case IC_SET_STATUS: if (size < 2) { - wdi_err("set status: no data"); + wdi_err("Set status: no data"); return WDI_ERROR_NOT_FOUND; } return (int)buffer[1]; break; case IC_SET_TIMEOUT_INFINITE: - wdi_dbg("switching timeout to infinite"); + wdi_dbg("Switching timeout to infinite"); timeout = INFINITE; break; case IC_SET_TIMEOUT_DEFAULT: - wdi_dbg("switching timeout back to finite"); + wdi_dbg("Switching timeout back to finite"); timeout = DEFAULT_TIMEOUT; break; case IC_INSTALLER_COMPLETED: - wdi_dbg("installer process completed"); + 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 { - wdi_warn("no user_sid - sending empty string"); + wdi_warn("No user_sid - sending empty string"); WriteFile(pipe_handle, "\0", 1, &tmp, NULL); } break; default: - wdi_err("unrecognized installer message"); + wdi_err("Unrecognized installer message"); return WDI_ERROR_NOT_FOUND; } return WDI_SUCCESS; } +static const char* get_installer_arch(USHORT uArch) +{ + switch (uArch) { + case IMAGE_FILE_MACHINE_AMD64: + return "x64"; + case IMAGE_FILE_MACHINE_I386: + return "x86"; + case IMAGE_FILE_MACHINE_ARM64: + return "arm64"; + default: + return "unknown_arch"; + } +} + // Run the elevated installer static int install_driver_internal(void* arglist) { @@ -1440,13 +1713,13 @@ static int install_driver_internal(void* arglist) STARTUPINFOA si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; - char path[MAX_PATH], exename[MAX_PATH], exeargs[MAX_PATH]; HANDLE stdout_w = INVALID_HANDLE_VALUE; HANDLE handle[3] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; OVERLAPPED overlapped; - int r; DWORD err, rd_count, to_read, offset, bufsize = LOGBUF_SIZE; - BOOL is_x64 = FALSE; + USHORT platform_arch = GetPlatformArch(); + int r; + char path[MAX_PATH], exename[MAX_PATH], exeargs[MAX_PATH], installer_name[32] = { 0 }; char *buffer = NULL, *new_buffer; const char* filter_name = "libusb0"; @@ -1454,7 +1727,7 @@ static int install_driver_internal(void* arglist) GET_WINDOWS_VERSION; if (nWindowsVersion < WINDOWS_7) { - wdi_err("this version of Windows is no longer supported"); + wdi_err("This version of Windows is no longer supported"); r = WDI_ERROR_NOT_SUPPORTED; goto out; } @@ -1473,13 +1746,13 @@ static int install_driver_internal(void* arglist) char* tmp = getenvU("TEMP"); static_strcpy(path, tmp); free(tmp); - wdi_info("no path provided - installing from '%s'", path); + wdi_info("No path provided - installing from '%s'", path); } else { static_strcpy(path, params->path); } if ((params->device_info == NULL) || (params->inf_name == NULL)) { - wdi_err("one of the required parameter is NULL"); + wdi_err("One of the required parameter is NULL"); r = WDI_ERROR_INVALID_PARAM; goto out; } @@ -1487,7 +1760,7 @@ static int install_driver_internal(void* arglist) // Detect if another installation is in process if ((params->options != NULL) && (pfCMP_WaitNoPendingInstallEvents != NULL)) { if (pfCMP_WaitNoPendingInstallEvents(params->options->pending_install_timeout) == WAIT_TIMEOUT) { - wdi_warn("timeout expired while waiting for another pending installation - aborting"); + wdi_warn("Timeout expired while waiting for another pending installation - aborting"); r = WDI_ERROR_PENDING_INSTALLATION; goto out; } @@ -1495,21 +1768,11 @@ static int install_driver_internal(void* arglist) wdi_dbg("CMP_WaitNoPendingInstallEvents not available"); } - // Detect whether if we should run the 64 bit installer, without - // relying on external libs - if (sizeof(uintptr_t) < 8) { - // This application is not 64 bit, but it might be 32 bit - // running in WOW64 - IsWow64Process(GetCurrentProcess(), &is_x64); - } else { - is_x64 = TRUE; - } - // Use a pipe to communicate with our installer pipe_handle = CreateNamedPipeA(INSTALLER_PIPE_NAME, PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE, 1, 4096, 4096, 0, NULL); if (pipe_handle == INVALID_HANDLE_VALUE) { - wdi_err("could not create read pipe: %s", windows_error_str(0)); + wdi_err("Could not create read pipe: %s", wdi_windows_error_str(0)); r = WDI_ERROR_RESOURCE; goto out; } @@ -1524,13 +1787,15 @@ static int install_driver_internal(void* arglist) overlapped.hEvent = handle[0]; if (!filter_driver) { - // Why do we need two installers? Glad you asked. If you try to run the x86 installer on an x64 + // Why do we need multiple installers? Glad you asked. If you try to run the x86 installer on an x64 // system, you will get a "System does not work under WOW64 and requires 64-bit version" message. - safe_sprintf(exename, sizeof(exename), "\"%s\\installer_x%s.exe\"", path, is_x64?"64":"86"); - safe_sprintf(exeargs, sizeof(exeargs), "\"%s\"", params->inf_name); + // And of course, Windows ARM64 won't let you use an x86 installer either... + static_sprintf(installer_name, "installer_%s.exe", get_installer_arch(platform_arch)); + static_sprintf(exeargs, "\"%s\"", params->inf_name); } else { // Use libusb-win32's filter driver installer - safe_sprintf(exename, sizeof(exename), "\"%s\\%s\\\\install-filter.exe\"", path, is_x64?"amd64":"x86"); + static_strcpy(installer_name, "install-filter.exe"); + static_strcat(path, (platform_arch == IMAGE_FILE_MACHINE_AMD64) ? "\\amd64" : "\\x86"); if (safe_stricmp(current_device->upper_filter, filter_name) == 0) { // Device already has the libusb-win32 filter => remove static_strcpy(exeargs, "uninstall -d="); @@ -1545,26 +1810,29 @@ static int install_driver_internal(void* arglist) stdout_w = CreateFileA(INSTALLER_PIPE_NAME, GENERIC_WRITE, FILE_SHARE_WRITE, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); if (stdout_w == INVALID_HANDLE_VALUE) { - wdi_err("could not create stdout endpoint: %s", windows_error_str(0)); + wdi_err("Could not create stdout endpoint: %s", wdi_windows_error_str(0)); r = WDI_ERROR_RESOURCE; goto out; } } - // At this stage, if either the 32 or 64 bit installer version is missing, + static_sprintf(exename, "\"%s\\%s\"", path, installer_name); + + // At this stage, if the installer for the relevant arch is missing, // it is the application developer's fault... if (GetFileAttributesU(exename) == INVALID_FILE_ATTRIBUTES) { - wdi_err("this application does not contain the required %s bit installer", is_x64?"64":"32"); - wdi_err("please contact the application provider for a %s bit compatible version", is_x64?"64":"32"); - r = WDI_ERROR_NOT_FOUND; goto out; + wdi_err("This application does not contain the required %s installer", installer_name); + wdi_err("Please contact the application provider for a compatible version"); + r = WDI_ERROR_NOT_FOUND; + goto out; } - if (IsUserAnAdmin()) { + if (!IsUserAnAdmin()) { // Take care of UAC with ShellExecuteEx + runas shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOA); shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; shExecInfo.hwnd = NULL; shExecInfo.lpVerb = "runas"; - shExecInfo.lpFile = filter_driver?"install-filter.exe":(is_x64?"installer_x64.exe":"installer_x86.exe"); + shExecInfo.lpFile = installer_name; shExecInfo.lpParameters = exeargs; shExecInfo.lpDirectory = path; shExecInfo.lpClass = NULL; @@ -1580,15 +1848,15 @@ static int install_driver_internal(void* arglist) case ERROR_SUCCESS: break; case ERROR_CANCELLED: - wdi_info("operation cancelled by the user"); + wdi_info("Operation cancelled by the user or due to missing data"); r = WDI_ERROR_USER_CANCEL; goto out; case ERROR_FILE_NOT_FOUND: - wdi_info("could not find installer executable"); + wdi_info("Could not find installer executable"); r = WDI_ERROR_NOT_FOUND; goto out; default: - wdi_err("ShellExecuteEx failed: %s", windows_error_str(err)); + wdi_err("ShellExecuteEx failed: %s", wdi_windows_error_str(err)); r = WDI_ERROR_NEEDS_ADMIN; goto out; } @@ -1610,7 +1878,7 @@ static int install_driver_internal(void* arglist) static_strcat(exename, " "); static_strcat(exename, exeargs); if (!CreateProcessU(NULL, exename, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, path, &si, &pi)) { - wdi_err("CreateProcess failed: %s", windows_error_str(0)); + wdi_err("CreateProcess failed: %s", wdi_windows_error_str(0)); r = WDI_ERROR_NEEDS_ADMIN; goto out; } handle[1] = pi.hProcess; @@ -1621,7 +1889,7 @@ static int install_driver_internal(void* arglist) offset = 0; buffer = (char*)malloc(bufsize); if (buffer == NULL) { - wdi_err("unable to alloc buffer: aborting"); + wdi_err("Unable to allocate buffer: aborting"); r = WDI_ERROR_RESOURCE; goto out; } @@ -1660,10 +1928,10 @@ static int install_driver_internal(void* arglist) r = check_completion(handle[1]); goto out; case ERROR_MORE_DATA: bufsize *= 2; - wdi_dbg("message overflow (async) - increasing buffer size to %d bytes", bufsize); + wdi_dbg("Message overflow (async) - increasing buffer size to %d bytes", bufsize); new_buffer = (char*)realloc(buffer, bufsize); if (new_buffer == NULL) { - wdi_err("unable to realloc buffer: aborting"); + wdi_err("Unable to realloc buffer: aborting"); r = WDI_ERROR_RESOURCE; } else { buffer = new_buffer; @@ -1671,21 +1939,21 @@ static int install_driver_internal(void* arglist) } break; default: - wdi_err("could not read from pipe (async): %s", windows_error_str(0)); + wdi_err("Could not read from pipe (async): %s", wdi_windows_error_str(0)); break; } } break; case WAIT_TIMEOUT: // Lost contact - wdi_err("installer failed to respond - aborting"); + wdi_err("Installer failed to respond - aborting"); TerminateProcess(handle[1], 0); r = WDI_ERROR_TIMEOUT; goto out; case WAIT_OBJECT_0+1: // installer process terminated r = check_completion(handle[1]); goto out; default: - wdi_err("could not read from pipe (wait): %s", windows_error_str(0)); + wdi_err("Could not read from pipe (wait): %s", wdi_windows_error_str(0)); break; } break; @@ -1702,7 +1970,7 @@ static int install_driver_internal(void* arglist) } break; default: - wdi_err("could not read from pipe (sync): %s", windows_error_str(0)); + wdi_err("Could not read from pipe (sync): %s", wdi_windows_error_str(0)); break; } } @@ -1723,19 +1991,21 @@ static int install_driver_internal(void* arglist) } int LIBWDI_API wdi_install_driver(struct wdi_device_info* device_info, const char* path, - const char* inf_name, struct wdi_options_install_driver* options) + const char* inf, struct wdi_options_install_driver* options) { struct install_driver_params params; params.device_info = device_info; - params.inf_name = inf_name; params.options = options; params.path = path; + // If we are dealing with a path (e.g. option 'external_inf'), remove the directory part + params.inf_name = filename(inf); + if ((options == NULL) || (options->hWnd == NULL)) { - wdi_dbg("using standard mode"); + wdi_dbg("Using standard mode"); return install_driver_internal((void*)¶ms); } - wdi_dbg("using progress bar mode"); + wdi_dbg("Using progress bar mode"); return run_with_progress_bar(options->hWnd, install_driver_internal, (void*)¶ms); } @@ -1750,7 +2020,7 @@ int LIBWDI_API wdi_install_trusted_certificate(const char* cert_name, GET_WINDOWS_VERSION; if (nWindowsVersion < WINDOWS_7) { - wdi_err("this version of Windows is no longer supported"); + wdi_err("This version of Windows is no longer supported"); r = WDI_ERROR_NOT_SUPPORTED; goto out; } @@ -1767,7 +2037,7 @@ int LIBWDI_API wdi_install_trusted_certificate(const char* cert_name, } } if (i == nb_resources) { - wdi_err("unable to locate certificate '%s' in embedded resources", cert_name); + wdi_err("Unable to locate certificate '%s' in embedded resources", cert_name); r = WDI_ERROR_NOT_FOUND; goto out; } @@ -1778,16 +2048,16 @@ int LIBWDI_API wdi_install_trusted_certificate(const char* cert_name, } if (!AddCertToTrustedPublisher((BYTE*)resource[i].data, (DWORD)resource[i].size, disable_warning, hWnd)) { - wdi_warn("could not add certificate '%s' as Trusted Publisher", cert_name); + wdi_warn("Could not add certificate '%s' as Trusted Publisher", cert_name); r = WDI_ERROR_RESOURCE; goto out; } - wdi_info("certificate '%s' successfully added as Trusted Publisher", cert_name); + wdi_info("Certificate '%s' successfully added as Trusted Publisher", cert_name); r = WDI_SUCCESS; goto out; } - wdi_err("this call must be run with elevated privileges"); + wdi_err("This call must be run with elevated privileges"); r = WDI_ERROR_NEEDS_ADMIN; out: return r; diff --git a/libwdi/libwdi.h b/libwdi/libwdi.h index da22ea4f..9e043cc3 100644 --- a/libwdi/libwdi.h +++ b/libwdi/libwdi.h @@ -1,6 +1,6 @@ /* * Library for USB automated driver installation - * Copyright (c) 2010-2017 Pete Batard + * Copyright (c) 2010-2021 Pete Batard * Parts of the code from libusb by Daniel Drake, Johannes Erdfelt et al. * * This library is free software; you can redistribute it and/or @@ -25,7 +25,7 @@ */ #define WDI_MAX_STRLEN 200 -#if defined(DLL_EXPORT) +#if defined(LIBWDI_DLL_EXPORT) #define LIBWDI_EXP __declspec(dllexport) #else #define LIBWDI_EXP @@ -201,6 +201,8 @@ struct wdi_options_prepare_driver { char* cert_subject; /** Install a generic driver, for WCID devices, to allow for automated installation */ BOOL use_wcid_driver; + /** Use an externally provided inf file */ + BOOL external_inf; }; // wdi_install_driver options: diff --git a/libwdi/libwdi.rc b/libwdi/libwdi.rc index 791f2023..5aeedfcd 100644 --- a/libwdi/libwdi.rc +++ b/libwdi/libwdi.rc @@ -50,8 +50,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,709,0 - PRODUCTVERSION 1,3,709,0 + FILEVERSION 1,5,1,788 + PRODUCTVERSION 1,5,1,788 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.709" + VALUE "FileVersion", "1.5.1.788" VALUE "InternalName", "libwdi" - VALUE "LegalCopyright", "© 2010-2017 Pete Batard (LGPL v3)" - VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/lesser.html" + VALUE "LegalCopyright", "� 2010-2023 Pete Batard (LGPL v3)" + VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/lesser.html" VALUE "OriginalFilename", "libwdi" VALUE "ProductName", "libwdi" - VALUE "ProductVersion", "1.3.709" + VALUE "ProductVersion", "1.5.1.788" VALUE "Comments", "http://libwdi.akeo.ie" END END diff --git a/libwdi/libwdi_dlg.c b/libwdi/libwdi_dlg.c index 56e5e9f3..8488cceb 100644 --- a/libwdi/libwdi_dlg.c +++ b/libwdi/libwdi_dlg.c @@ -87,12 +87,12 @@ static int (*progress_function)(void*); static void* progress_arglist; static HANDLE progress_mutex = INVALID_HANDLE_VALUE; -// Work around for GDI calls (would require end user apps linking with Gdi32 othwerwise) +// Work around for GDI calls (would require end user apps linking with Gdi32 otherwise) PF_TYPE_DECL(WINAPI, HFONT, CreateFontA, (int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCSTR)); PF_TYPE_DECL(WINAPI, HGDIOBJ, GetStockObject, (int)); PF_TYPE_DECL(WINAPI, int, SetBkMode, (HDC, int)); -extern char *windows_error_str(uint32_t retval); +extern char *wdi_windows_error_str(uint32_t retval); /* * Detect if a Windows Security prompt is active, by enumerating the @@ -189,7 +189,7 @@ static void init_children(HWND hDlg) app_instance, NULL); if (hProgressBar == NULL) { - wdi_err("Unable to create progress bar: %s", windows_error_str(0)); + wdi_err("Unable to create progress bar: %s", wdi_windows_error_str(0)); } // Start progress animation @@ -205,7 +205,7 @@ static void init_children(HWND hDlg) app_instance, NULL); if (hProgressBar == NULL) { - wdi_err("Unable to create progress text: %s", windows_error_str(0)); + wdi_err("Unable to create progress text: %s", wdi_windows_error_str(0)); } // Set the font to MS Dialog default @@ -383,7 +383,7 @@ int run_with_progress_bar(HWND hWnd, int(*function)(void*), void* arglist) { wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); if (!RegisterClassEx(&wc)) { - wdi_err("can't register class %s", windows_error_str(0)); + wdi_err("can't register class %s", wdi_windows_error_str(0)); msg.wParam = WDI_ERROR_RESOURCE; goto out; } @@ -395,7 +395,7 @@ int run_with_progress_bar(HWND hWnd, int(*function)(void*), void* arglist) { WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_THICKFRAME, 100, 100, 287, 102, hWnd, NULL, app_instance, NULL); if (hDlg == NULL) { - wdi_err("Unable to create progress dialog: %s", windows_error_str(0)); + wdi_err("Unable to create progress dialog: %s", wdi_windows_error_str(0)); msg.wParam = WDI_ERROR_RESOURCE; goto out; } diff --git a/libwdi/libwdi_i.h b/libwdi/libwdi_i.h index fb7d99d6..d86785a5 100644 --- a/libwdi/libwdi_i.h +++ b/libwdi/libwdi_i.h @@ -89,7 +89,7 @@ enum INF_TAGS LK_EQ_X64, }; -token_entity_t inf_entities[]= +static token_entity_t inf_entities[]= { {"INF_FILENAME",""}, {"CAT_FILENAME",""}, @@ -120,8 +120,8 @@ token_entity_t inf_entities[]= * installed automatically, which will only leave the driverless debug interface to pick * a driver for. */ -const char* android_device_guid = "{f72fe0d4-cbcb-407d-8814-9ed673d0dd6b}"; -const struct {uint16_t vid; uint16_t pid;} android_device[] = { +static const char* android_device_guid = "{f72fe0d4-cbcb-407d-8814-9ed673d0dd6b}"; +static const struct {uint16_t vid; uint16_t pid;} android_device[] = { {0x0451, 0xD022}, {0x0451, 0xD101}, {0x0489, 0xC001}, @@ -261,7 +261,7 @@ typedef struct { } DEVPROPKEY; #endif -const DEVPROPKEY DEVPKEY_Device_BusReportedDeviceDesc = { +static const DEVPROPKEY DEVPKEY_Device_BusReportedDeviceDesc = { { 0x540b947e, 0x8b40, 0x45bc, {0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2} }, 4 }; // Check the status of the installer process diff --git a/libwdi/logging.c b/libwdi/logging.c index 6f33c6be..15f18af2 100644 --- a/libwdi/logging.c +++ b/libwdi/logging.c @@ -47,7 +47,7 @@ static DWORD log_messages_pipe_size = 0; // Global debug level static int global_log_level = WDI_LOG_LEVEL_INFO; -extern char *windows_error_str(uint32_t retval); +extern char *wdi_windows_error_str(uint32_t retval); static void write_to_pipe(const char* buffer, DWORD size, enum wdi_log_level level) { @@ -204,7 +204,7 @@ static int create_logger(DWORD buffsize) logger_rd_handle = CreateNamedPipeA(LOGGER_PIPE_NAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE, 1, buffsize, buffsize, 0, NULL); if (logger_rd_handle == INVALID_HANDLE_VALUE) { - fprintf(stderr, "could not create logger pipe for reading: %s\n", windows_error_str(0)); + fprintf(stderr, "could not create logger pipe for reading: %s\n", wdi_windows_error_str(0)); return WDI_ERROR_RESOURCE; } @@ -212,7 +212,7 @@ static int create_logger(DWORD buffsize) logger_wr_handle = CreateFileA(LOGGER_PIPE_NAME, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (logger_wr_handle == INVALID_HANDLE_VALUE) { - fprintf(stderr, "could not create logger pipe for writing: %s\n", windows_error_str(0)); + fprintf(stderr, "could not create logger pipe for writing: %s\n", wdi_windows_error_str(0)); CloseHandle(logger_rd_handle); logger_rd_handle = INVALID_HANDLE_VALUE; return WDI_ERROR_RESOURCE; diff --git a/libwdi/msapi_utf8.h b/libwdi/msapi_utf8.h index b032ec29..71d8ebf7 100644 --- a/libwdi/msapi_utf8.h +++ b/libwdi/msapi_utf8.h @@ -1,8 +1,12 @@ /* * MSAPI_UTF8: Common API calls using UTF-8 strings - * Compensating for what Microsoft should have done a long long time ago. + * Compensating for what Microsoft should have done a long long time ago, that they + * ONLY started to do in mid-2019 (What the £%^& took them so long?!?), as per: + * https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/use-utf8-code-page * - * Copyright © 2010-2017 Pete Batard + * See also: https://utf8everywhere.org + * + * Copyright © 2010-2023 Pete Batard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,10 +25,19 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include #pragma once #if defined(_MSC_VER) @@ -53,9 +66,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) /* @@ -67,6 +89,10 @@ static __inline char* wchar_to_utf8(const wchar_t* wstr) int size = 0; char* str = NULL; + // Convert the empty string too + if (wstr[0] == 0) + return (char*)calloc(1, 1); + // Find out the size we need to allocate for our converted string size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); if (size <= 1) // An empty string would be size 1 @@ -92,6 +118,13 @@ static __inline wchar_t* utf8_to_wchar(const char* str) int size = 0; wchar_t* wstr = NULL; + if (str == NULL) + return NULL; + + // Convert the empty string too + if (str[0] == 0) + return (wchar_t*)calloc(1, sizeof(wchar_t)); + // 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 +140,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 +240,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,18 +270,93 @@ static __inline int MessageBoxU(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT return ret; } -static __inline int GetWindowTextU(HWND hWnd, char* lpString, int nMaxCount) +static __inline int MessageBoxExU(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId) { - int ret = 0; + 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 HMODULE LoadLibraryExU(LPCSTR lpFileName, HANDLE hFile, DWORD dwFlags) +{ + HMODULE ret; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpFileName); + ret = LoadLibraryExW(wlpFileName, hFile, dwFlags); + 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; + DWORD err = ERROR_INVALID_PARAMETER; + if (lpString == NULL || nMaxCount < 1) + goto out; + // Handle the empty string as GetWindowTextW() returns 0 then + lpString[0] = 0; walloc(lpString, nMaxCount); ret = GetWindowTextW(hWnd, wlpString, nMaxCount); err = GetLastError(); - if ( (ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpString, lpString, nMaxCount)) == 0) ) { + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpString, lpString, nMaxCount)) == 0)) err = GetLastError(); - } wfree(lpString); + lpString[nMaxCount - 1] = 0; +out: SetLastError(err); return ret; } @@ -234,7 +383,7 @@ static __inline int GetWindowTextLengthU(HWND hWnd) ret = GetWindowTextLengthW(hWnd); err = GetLastError(); if (ret == 0) goto out; - wbuf = calloc(ret, sizeof(wchar_t)); + wbuf = (wchar_t* )calloc(ret, sizeof(wchar_t)); err = GetLastError(); if (wbuf == NULL) { err = ERROR_OUTOFMEMORY; ret = 0; goto out; @@ -284,6 +433,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; @@ -294,7 +455,7 @@ static __inline int ComboBox_GetLBTextU(HWND hCtrl, int index, char* lpString) size = (int)SendMessageW(hCtrl, CB_GETLBTEXTLEN, (WPARAM)index, (LPARAM)0); if (size < 0) return size; - wlpString = (wchar_t*)calloc(size+1, sizeof(wchar_t)); + wlpString = (wchar_t*)calloc((size_t)size + 1, sizeof(wchar_t)); size = (int)SendMessageW(hCtrl, CB_GETLBTEXT, (WPARAM)index, (LPARAM)wlpString); err = GetLastError(); if (size > 0) @@ -304,9 +465,22 @@ 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 = (wchar_t*)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) + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { HANDLE ret = INVALID_HANDLE_VALUE; DWORD err = ERROR_INVALID_DATA; @@ -319,6 +493,32 @@ static __inline HANDLE CreateFileU(const char* lpFileName, DWORD dwDesiredAccess return ret; } +static __inline BOOL CreateDirectoryU(const char* lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpPathName); + ret = CreateDirectoryW(wlpPathName, lpSecurityAttributes); + err = GetLastError(); + wfree(lpPathName); + SetLastError(err); + 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 +531,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) { @@ -346,12 +583,71 @@ static __inline BOOL GetTextExtentPointU(HDC hdc, const char* lpString, LPSIZE l return ret; } +// A UTF-8 alternative to MS GetCurrentDirectory() since the latter is useless for +// apps installed from the App Store... static __inline DWORD GetCurrentDirectoryU(DWORD nBufferLength, char* lpBuffer) +{ + DWORD i, ret = 0, err = ERROR_INVALID_DATA; + // coverity[returned_null] + walloc(lpBuffer, nBufferLength); + if (wlpBuffer == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + return 0; + } + ret = GetModuleFileNameW(NULL, wlpBuffer, nBufferLength); + err = GetLastError(); + if (ret > 0) { + for (i = ret - 1; i > 0; i--) { + if (wlpBuffer[i] == L'\\') { + wlpBuffer[i] = 0; + break; + } + } + } + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) { + err = GetLastError(); + } + wfree(lpBuffer); + SetLastError(err); + 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 = GetCurrentDirectoryW(nBufferLength, wlpBuffer); + ret = GetTempPathW(nBufferLength, wlpBuffer); err = GetLastError(); if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) { err = GetLastError(); @@ -361,6 +657,25 @@ static __inline DWORD GetCurrentDirectoryU(DWORD nBufferLength, char* lpBuffer) 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 +691,63 @@ 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 GetFinalPathNameByHandleU(HANDLE hFile, char* lpszFilePath, DWORD cchFilePath, DWORD dwFlags) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + walloc(lpszFilePath, cchFilePath); + ret = GetFinalPathNameByHandleW(hFile, wlpszFilePath, cchFilePath, dwFlags); + err = GetLastError(); + if ((ret != 0) + && ((ret = wchar_to_utf8_no_alloc(wlpszFilePath, lpszFilePath, cchFilePath)) == 0)) { + err = GetLastError(); + } + wfree(lpszFilePath); + SetLastError(err); + return ret; +} + +static __inline DWORD GetFileVersionInfoSizeU(const char* lpFileName, LPDWORD lpdwHandle) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + wconvert(lpFileName); + ret = GetFileVersionInfoSizeW(wlpFileName, lpdwHandle); + err = GetLastError(); + wfree(lpFileName); + SetLastError(err); + return ret; +} + +static __inline BOOL GetFileVersionInfoU(const char* lpFileName, DWORD dwHandle, DWORD dwLen, LPVOID lpData) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpFileName); + if (dwHandle != 0) + SetLastError(ERROR_INVALID_PARAMETER); + else + ret = GetFileVersionInfoW(wlpFileName, dwHandle, dwLen, lpData); + 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; @@ -417,6 +789,23 @@ static __inline DWORD GetFileAttributesU(const char* lpFileName) return ret; } +static __inline BOOL SetFileAttributesU(const char* lpFileName, DWORD dwFileAttributes) +{ + BOOL ret = FALSE, 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 = SetFileAttributesW(&wlpFileName[1], dwFileAttributes); + } else { + ret = SetFileAttributesW(wlpFileName, dwFileAttributes); + } + err = GetLastError(); + wfree(lpFileName); + SetLastError(err); + return ret; +} + static __inline int SHCreateDirectoryExU(HWND hwnd, const char* pszPath, SECURITY_ATTRIBUTES *psa) { int ret = ERROR_INVALID_DATA; @@ -429,6 +818,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 = (pszPath == NULL) ? 0 : 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; @@ -544,10 +949,10 @@ static __inline BOOL WINAPI GetOpenSaveFileNameU(LPOPENFILENAMEA lpofn, BOOL sav } wofn.nMaxCustFilter = lpofn->nMaxCustFilter; wofn.nFilterIndex = lpofn->nFilterIndex; - wofn.lpstrFile = calloc(lpofn->nMaxFile, sizeof(wchar_t)); + wofn.lpstrFile = (LPWSTR)calloc(lpofn->nMaxFile, sizeof(wchar_t)); utf8_to_wchar_no_alloc(lpofn->lpstrFile, wofn.lpstrFile, lpofn->nMaxFile); wofn.nMaxFile = lpofn->nMaxFile; - wofn.lpstrFileTitle = calloc(lpofn->nMaxFileTitle, sizeof(wchar_t)); + wofn.lpstrFileTitle = (LPWSTR)calloc(lpofn->nMaxFileTitle, sizeof(wchar_t)); utf8_to_wchar_no_alloc(lpofn->lpstrFileTitle, wofn.lpstrFileTitle, lpofn->nMaxFileTitle); wofn.nMaxFileTitle = lpofn->nMaxFileTitle; wofn.lpstrInitialDir = utf8_to_wchar(lpofn->lpstrInitialDir); @@ -642,6 +1047,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 +1059,80 @@ 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; +} + +static __inline int _accessU(const char* path, int mode) +{ + int ret; + wconvert(path); + ret = _waccess(wpath, mode); + wfree(path); + return ret; +} + +static __inline const char* _filenameU(const char* path) +{ + int i; + if (path == NULL) + return NULL; + for (i = (int)strlen(path) - 1; i >= 0; i--) + if ((path[i] == '/') || (path[i] == '\\')) + return &path[i + 1]; + return path; +} + // returned UTF-8 string must be freed static __inline char* getenvU(const char* varname) { @@ -661,9 +1141,11 @@ static __inline char* getenvU(const char* varname) wchar_t* wbuf = NULL; // _wgetenv() is *BROKEN* in MS compilers => use GetEnvironmentVariableW() DWORD dwSize = GetEnvironmentVariableW(wvarname, wbuf, 0); - wbuf = calloc(dwSize, sizeof(wchar_t)); - if (wbuf == NULL) + wbuf = (wchar_t*)calloc(dwSize, sizeof(wchar_t)); + if (wbuf == NULL) { + wfree(varname); return NULL; + } dwSize = GetEnvironmentVariableW(wvarname, wbuf, dwSize); if (dwSize != 0) ret = wchar_to_utf8(wbuf); @@ -681,6 +1163,154 @@ static __inline int _mkdirU(const char* dirname) return ret; } +// This version of _mkdirU creates all needed directories along the way +static __inline int _mkdirExU(const char* dirname) +{ + int ret = -1, trailing_slash = -1; + size_t i, len; + wconvert(dirname); + len = wcslen(wdirname); + while (trailing_slash && (len > 0)) { + if ((wdirname[len - 1] == '\\') || (wdirname[len - 1] == '/')) + wdirname[--len] = 0; + else + trailing_slash = 0; + } + for (i = 0; i < len; i++) + if ((wdirname[i] == '\\') || (wdirname[i] == '/')) + wdirname[i] = 0; + for (i = 0; i < len; ) { + if ((_wmkdir(wdirname) < 0) && (errno != EEXIST) && (errno != EACCES)) + goto out; + i = wcslen(wdirname); + wdirname[i] = '\\'; + } + ret = 0; +out: + wfree(dirname); + return ret; +} + +static __inline int _rmdirU(const char* dirname) +{ + wconvert(dirname); + int ret; + ret = _wrmdir(wdirname); + wfree(dirname); + return ret; +} + +static __inline BOOL MoveFileU(const char* lpExistingFileName, const char* lpNewFileName) +{ + wconvert(lpExistingFileName); + wconvert(lpNewFileName); + BOOL ret = MoveFileW(wlpExistingFileName, wlpNewFileName); + wfree(lpNewFileName); + wfree(lpExistingFileName); + return ret; +} + +static __inline BOOL MoveFileExU(const char* lpExistingFileName, const char* lpNewFileName, DWORD dwFlags) +{ + wconvert(lpExistingFileName); + wconvert(lpNewFileName); + BOOL ret = MoveFileExW(wlpExistingFileName, wlpNewFileName, dwFlags); + wfree(lpNewFileName); + wfree(lpExistingFileName); + return ret; +} + +static __inline BOOL CreateSymbolicLinkU(const char* lpSymlinkFileName, const char* lpTargetFileName, DWORD dwFlags) +{ + wconvert(lpSymlinkFileName); + wconvert(lpTargetFileName); + BOOL ret = CreateSymbolicLinkW(wlpSymlinkFileName, wlpTargetFileName, dwFlags); + wfree(lpTargetFileName); + wfree(lpSymlinkFileName); + 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; +} + +// NB: This does not support the ERROR_INSUFFICIENT_BUFFER dance to retrieve the required buffer size +static __inline BOOL GetUserNameU(LPSTR lpBuffer, LPDWORD pcbBuffer) +{ + BOOL ret; + DWORD err, size; + if (lpBuffer == NULL || pcbBuffer == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + size = *pcbBuffer; + // coverity[returned_null] + walloc(lpBuffer, size); + ret = GetUserNameW(wlpBuffer, &size); + err = GetLastError(); + if (ret) { + *pcbBuffer = (DWORD)wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, size); + if (*pcbBuffer == 0) + err = GetLastError(); + else + // Reported size includes the NUL terminator + (*pcbBuffer)++; + } + wfree(lpBuffer); + 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 diff --git a/libwdi/pki.c b/libwdi/pki.c index 1ec18ee4..4dc2d243 100644 --- a/libwdi/pki.c +++ b/libwdi/pki.c @@ -1,6 +1,6 @@ /* * libwdi: Library for automated Windows Driver Installation - PKI part - * Copyright (c) 2011-2017 Pete Batard + * Copyright (c) 2011-2023 Pete Batard * For more info, please visit http://libwdi.akeo.ie * * This library is free software; you can redistribute it and/or @@ -28,22 +28,25 @@ #include #include #include -#include #include #include -#include #include "mssign32.h" #include +#include "msapi_utf8.h" #include "installer.h" #include "libwdi.h" #include "logging.h" +#include "stdfn.h" #define KEY_CONTAINER L"libwdi key container" #define PF_ERR wdi_err #ifndef CERT_STORE_PROV_SYSTEM_A #define CERT_STORE_PROV_SYSTEM_A ((LPCSTR) 9) #endif +#ifndef szOID_RSA_SHA1RSA +#define szOID_RSA_SHA1RSA "1.2.840.113549.1.1.5" +#endif #ifndef szOID_RSA_SHA256RSA #define szOID_RSA_SHA256RSA "1.2.840.113549.1.1.11" #endif @@ -183,17 +186,6 @@ typedef PCCERT_CONTEXT (WINAPI *CertCreateSelfSignCertificate_t)( #ifndef szOID_PKIX_POLICY_QUALIFIER_CPS #define szOID_PKIX_POLICY_QUALIFIER_CPS "1.3.6.1.5.5.7.2.1" #endif -typedef struct _CERT_ALT_NAME_ENTRY_URL { - DWORD dwAltNameChoice; - union { - LPWSTR pwszURL; - }; -} CERT_ALT_NAME_ENTRY_URL, *PCERT_ALT_NAME_ENTRY_URL; - -typedef struct _CERT_ALT_NAME_INFO_URL { - DWORD cAltEntry; - PCERT_ALT_NAME_ENTRY_URL rgAltEntry; -} CERT_ALT_NAME_INFO_URL, *PCERT_ALT_NAME_INFO_URL; typedef struct _CERT_POLICY_QUALIFIER_INFO_REDEF { LPSTR pszPolicyQualifierId; @@ -371,7 +363,118 @@ typedef BOOL (WINAPI *CryptCATAdminCalcHashFromFileHandle_t)( DWORD dwFlags ); -extern char *windows_error_str(uint32_t retval); +extern char *wdi_windows_error_str(uint32_t retval); +extern int nWindowsVersion; +extern void GetWindowsVersion(void); + +/* + * FormatMessage does not handle PKI errors + */ +char* winpki_error_str(uint32_t retval) +{ + static char error_string[64]; + uint32_t error_code = retval ? retval : GetLastError(); + + if (error_code == 0x800706D9) + return "This system is missing required cryptographic services."; + if (error_code == 0x80070020) + return "Sharing violation - Some data handles to this file are still open."; + + if ((error_code >> 16) != 0x8009) + return wdi_windows_error_str(error_code); + + switch (error_code) { + case NTE_BAD_UID: + return "Bad UID."; + case NTE_BAD_KEYSET: + return "Keyset does not exist."; + case NTE_KEYSET_ENTRY_BAD: + return "Keyset as registered is invalid."; + case NTE_BAD_FLAGS: + return "Invalid flags specified."; + case NTE_BAD_KEYSET_PARAM: + return "The Keyset parameter is invalid."; + case NTE_BAD_PROV_TYPE: + return "Invalid provider type specified."; + case NTE_EXISTS: + return "Object already exists."; + case NTE_BAD_SIGNATURE: + return "Invalid Signature."; + case NTE_PROVIDER_DLL_FAIL: + return "Provider DLL failed to initialize correctly."; + case NTE_SIGNATURE_FILE_BAD: + return "The digital signature file is corrupt."; + case NTE_PROV_DLL_NOT_FOUND: + return "Provider DLL could not be found."; + case NTE_KEYSET_NOT_DEF: + return "The keyset is not defined."; + case NTE_NO_MEMORY: + return "Insufficient memory available for the operation."; + case CRYPT_E_MSG_ERROR: + return "An error occurred while performing an operation on a cryptographic message."; + case CRYPT_E_UNKNOWN_ALGO: + return "Unknown cryptographic algorithm."; + case CRYPT_E_INVALID_MSG_TYPE: + return "Invalid cryptographic message type."; + case CRYPT_E_HASH_VALUE: + return "The hash value is not correct"; + case CRYPT_E_ISSUER_SERIALNUMBER: + return "Invalid issuer and/or serial number."; + case CRYPT_E_BAD_LEN: + return "The length specified for the output data was insufficient."; + case CRYPT_E_BAD_ENCODE: + return "An error occurred during encode or decode operation."; + case CRYPT_E_FILE_ERROR: + return "An error occurred while reading or writing to a file."; + case CRYPT_E_NOT_FOUND: + return "Cannot find object or property."; + case CRYPT_E_EXISTS: + return "The object or property already exists."; + case CRYPT_E_NO_PROVIDER: + return "No provider was specified for the store or object."; + case CRYPT_E_DELETED_PREV: + return "The previous certificate or CRL context was deleted."; + case CRYPT_E_NO_MATCH: + return "Cannot find the requested object."; + case CRYPT_E_UNEXPECTED_MSG_TYPE: + return "The certificate does not have a property that references a private key."; + case CRYPT_E_NO_KEY_PROPERTY: + return "Cannot find the private key to use for decryption."; + case CRYPT_E_NO_DECRYPT_CERT: + return "Cannot find the certificate to use for decryption."; + case CRYPT_E_BAD_MSG: + return "Not a cryptographic message."; + case CRYPT_E_NO_SIGNER: + return "The signed cryptographic message does not have a signer for the specified signer index."; + case CRYPT_E_REVOKED: + return "The certificate is revoked."; + case CRYPT_E_NO_REVOCATION_DLL: + return "No Dll or exported function was found to verify revocation."; + case CRYPT_E_NO_REVOCATION_CHECK: + return "The revocation function was unable to check revocation for the certificate."; + case CRYPT_E_REVOCATION_OFFLINE: + return "The revocation function was unable to check revocation because the revocation server was offline."; + case CRYPT_E_NOT_IN_REVOCATION_DATABASE: + return "The certificate is not in the revocation server's database."; + case CRYPT_E_INVALID_NUMERIC_STRING: + case CRYPT_E_INVALID_PRINTABLE_STRING: + case CRYPT_E_INVALID_IA5_STRING: + case CRYPT_E_INVALID_X500_STRING: + case CRYPT_E_NOT_CHAR_STRING: + return "Invalid string."; + case CRYPT_E_SECURITY_SETTINGS: + return "The cryptographic operation failed due to a local security option setting."; + case CRYPT_E_NO_VERIFY_USAGE_CHECK: + return "The called function was unable to do a usage check on the subject."; + case CRYPT_E_VERIFY_USAGE_OFFLINE: + return "Since the server was offline, the called function was unable to complete the usage check."; + case CRYPT_E_NO_TRUSTED_SIGNER: + return "None of the signers of the cryptographic message or certificate trust list is trusted."; + default: + static_sprintf(error_string, "Unknown PKI error 0x%08X", error_code); + return error_string; + } +} /* * Convert an UTF8 string to UTF-16 (allocate returned string) @@ -425,17 +528,17 @@ BOOL AddCertToStore(PCCERT_CONTEXT pCertContext, LPCSTR szStoreName) hSystemStore = pfCertOpenStore(CERT_STORE_PROV_SYSTEM_A, X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, szStoreName); if (hSystemStore == NULL) { - wdi_warn("failed to open system store '%s': %s", szStoreName, windows_error_str(0)); + wdi_warn("Failed to open system store '%s': %s", szStoreName, winpki_error_str(0)); goto out; } if (!pfCertSetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, 0, &libwdiNameBlob)) { - wdi_warn("coud not set friendly name: %s", windows_error_str(0)); + wdi_warn("Could not set friendly name: %s", winpki_error_str(0)); goto out; } if (!pfCertAddCertificateContextToStore(hSystemStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) { - wdi_warn("failed to add certificate to system store '%s': %s", szStoreName, windows_error_str(0)); + wdi_warn("Failed to add certificate to system store '%s': %s", szStoreName, winpki_error_str(0)); goto out; } r = TRUE; @@ -472,7 +575,7 @@ BOOL RemoveCertFromStore(LPCSTR szCertSubject, LPCSTR szStoreName) hSystemStore = pfCertOpenStore(CERT_STORE_PROV_SYSTEM_A, X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, szStoreName); if (hSystemStore == NULL) { - wdi_warn("failed to open system store '%s': %s", szStoreName, windows_error_str(0)); + wdi_warn("failed to open system store '%s': %s", szStoreName, winpki_error_str(0)); goto out; } @@ -480,15 +583,19 @@ BOOL RemoveCertFromStore(LPCSTR szCertSubject, LPCSTR szStoreName) if ( (!pfCertStrToNameA(X509_ASN_ENCODING, szCertSubject, CERT_X500_NAME_STR, NULL, NULL, &certNameBlob.cbData, NULL)) || ((certNameBlob.pbData = (BYTE*)malloc(certNameBlob.cbData)) == NULL) || (!pfCertStrToNameA(X509_ASN_ENCODING, szCertSubject, CERT_X500_NAME_STR, NULL, certNameBlob.pbData, &certNameBlob.cbData, NULL)) ) { - wdi_warn("failed to encode'%s': %s", szCertSubject, windows_error_str(0)); + wdi_warn("Failed to encode '%s': %s", szCertSubject, winpki_error_str(0)); goto out; } pCertContext = NULL; while ((pCertContext = pfCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, (const void*)&certNameBlob, NULL)) != NULL) { - pfCertDeleteCertificateFromStore(pCertContext); - wdi_info("deleted existing certificate '%s' from '%s' store", szCertSubject, szStoreName); + if (!pfCertDeleteCertificateFromStore(pCertContext)) { + wdi_warn("Failed to delete certificate '%s' from '%s' store: %s", + szCertSubject, szStoreName, winpki_error_str(0)); + goto out; + } + wdi_info("Deleted existing certificate '%s' from '%s' store", szCertSubject, szStoreName); } r = TRUE; @@ -533,7 +640,7 @@ BOOL AddCertToTrustedPublisher(BYTE* pbCertData, DWORD dwCertSize, BOOL bDisable 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher"); if (hSystemStore == NULL) { - wdi_warn("unable to open system store: %s", windows_error_str(0)); + wdi_warn("Unable to open system store: %s", winpki_error_str(0)); goto out; } @@ -544,7 +651,7 @@ BOOL AddCertToTrustedPublisher(BYTE* pbCertData, DWORD dwCertSize, BOOL bDisable pCertContext = pfCertCreateCertificateContext(X509_ASN_ENCODING, pbCertData, dwCertSize); if (pCertContext == NULL) { - wdi_warn("could not create context for certificate: %s", windows_error_str(0)); + wdi_warn("Could not create context for certificate: %s", winpki_error_str(0)); pfCertCloseStore(hSystemStore, 0); goto out; } @@ -557,7 +664,7 @@ BOOL AddCertToTrustedPublisher(BYTE* pbCertData, DWORD dwCertSize, BOOL bDisable org[0] = 0; org_unit[0] = 0; pfCertGetNameStringA(pCertContext, CERT_NAME_ATTR_TYPE, 0, szOID_ORGANIZATION_NAME, org, sizeof(org)); pfCertGetNameStringA(pCertContext, CERT_NAME_ATTR_TYPE, 0, szOID_ORGANIZATIONAL_UNIT_NAME, org_unit, sizeof(org_unit)); - safe_sprintf(msg_string, sizeof(msg_string), "Warning: this software is about to install the following organization\n" + static_sprintf(msg_string, "Warning: this software is about to install the following organization\n" "as a Trusted Publisher on your system:\n\n '%s%s%s%s'\n\n" "This will allow this Publisher to run software with elevated privileges,\n" "as well as install driver packages, without further security notices.\n\n" @@ -567,10 +674,10 @@ BOOL AddCertToTrustedPublisher(BYTE* pbCertData, DWORD dwCertSize, BOOL bDisable "Warning: Trusted Certificate installation", MB_OKCANCEL | MB_ICONWARNING); } if (user_input != IDOK) { - wdi_info("operation cancelled by the user"); + wdi_info("Operation cancelled by the user"); } else { if (!pfCertAddCertificateContextToStore(hSystemStore, pCertContext, CERT_STORE_ADD_NEWER, NULL)) { - wdi_warn("could not add certificate: %s", windows_error_str(0)); + wdi_warn("Could not add certificate: %s", winpki_error_str(0)); } else { r = TRUE; } @@ -601,7 +708,7 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) PF_DECL(CertCreateSelfSignCertificate); PF_DECL(CertFreeCertificateContext); - DWORD dwSize; + DWORD dwSize = 0; HCRYPTPROV hCSP = 0; HCRYPTKEY hKey = 0; PCCERT_CONTEXT pCertContext = NULL; @@ -616,9 +723,10 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) // Code Signing Enhanced Key Usage LPSTR szCertPolicyElementId = "1.3.6.1.5.5.7.3.3"; // szOID_PKIX_KP_CODE_SIGNING; CERT_ENHKEY_USAGE certEnhKeyUsage = { 1, &szCertPolicyElementId }; - // Alternate Name (URL) - CERT_ALT_NAME_ENTRY_URL certAltNameEntry = { CERT_ALT_NAME_URL, {L"http://libwdi.akeo.ie"} }; - CERT_ALT_NAME_INFO_URL certAltNameInfo = { 1, &certAltNameEntry }; + // Abuse Alt Name to insert ourselves in the e-mail field + CERT_ALT_NAME_ENTRY certAltNameEntry = { CERT_ALT_NAME_RFC822_NAME, + { (PCERT_OTHER_NAME)L"Created by libwdi (http://libwdi.akeo.ie)" } }; + CERT_ALT_NAME_INFO certAltNameInfo = { 1, &certAltNameEntry }; // Certificate Policies CERT_POLICY_QUALIFIER_INFO_REDEF certPolicyQualifier; CERT_POLICY_INFO_REDEF certPolicyInfo = { "1.3.6.1.5.5.7.2.1", 1, &certPolicyQualifier }; @@ -635,7 +743,7 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) if ( (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, (LPVOID)&certEnhKeyUsage, NULL, &dwSize)) || ((pbEnhKeyUsage = (BYTE*)malloc(dwSize)) == NULL) || (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, (LPVOID)&certEnhKeyUsage, pbEnhKeyUsage, &dwSize)) ) { - wdi_warn("could not setup EKU for code signing: %s", windows_error_str(0)); + wdi_warn("Could not setup EKU for code signing: %s", winpki_error_str(0)); goto out; } certExtension[0].pszObjId = szOID_ENHANCED_KEY_USAGE; @@ -643,11 +751,11 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) certExtension[0].Value.cbData = dwSize; certExtension[0].Value.pbData = pbEnhKeyUsage; - // Set URL as Alt Name parameter + // Set Alt Name parameter if ( (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_ALTERNATE_NAME, (LPVOID)&certAltNameInfo, NULL, &dwSize)) || ((pbAltNameInfo = (BYTE*)malloc(dwSize)) == NULL) || (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_ALTERNATE_NAME, (LPVOID)&certAltNameInfo, pbAltNameInfo, &dwSize)) ) { - wdi_warn("could not setup URL: %s", windows_error_str(0)); + wdi_warn("Could not set Alt Name: %s", winpki_error_str(0)); goto out; } certExtension[1].pszObjId = szOID_SUBJECT_ALT_NAME; @@ -662,7 +770,7 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) if ( (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_NAME_VALUE, (LPVOID)&certCPSValue, NULL, &dwSize)) || ((pbCPSNotice = (BYTE*)malloc(dwSize)) == NULL) || (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_NAME_VALUE, (LPVOID)&certCPSValue, pbCPSNotice, &dwSize)) ) { - wdi_warn("could not setup CPS: %s", windows_error_str(0)); + wdi_warn("Could not setup CPS: %s", winpki_error_str(0)); goto out; } @@ -672,7 +780,7 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) if ( (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_CERT_POLICIES, (LPVOID)&certPolicyInfoArray, NULL, &dwSize)) || ((pbPolicyInfo = (BYTE*)malloc(dwSize)) == NULL) || (!pfCryptEncodeObject(X509_ASN_ENCODING, X509_CERT_POLICIES, (LPVOID)&certPolicyInfoArray, pbPolicyInfo, &dwSize)) ) { - wdi_warn("could not setup Certificate Policies: %s", windows_error_str(0)); + wdi_warn("Could not setup Certificate Policies: %s", winpki_error_str(0)); goto out; } certExtension[2].pszObjId = szOID_CERT_POLICIES; @@ -682,30 +790,31 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) certExtensionsArray.cExtension = ARRAYSIZE(certExtension); certExtensionsArray.rgExtension = certExtension; - wdi_dbg("set Enhanced Key Usage, URL and CPS"); + wdi_dbg("Set Enhanced Key Usage, URL and CPS"); if (CryptAcquireContextW(&hCSP, wszKeyContainer, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_SILENT)) { - wdi_dbg("acquired existing key container"); - } else if ( (GetLastError() == NTE_BAD_KEYSET) + wdi_dbg("Acquired existing key container"); + } else if ( (GetLastError() == NTE_BAD_KEYSET || GetLastError() == NTE_KEYSET_ENTRY_BAD) && (CryptAcquireContextW(&hCSP, wszKeyContainer, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET|CRYPT_SILENT)) ) { - wdi_dbg("created new key container"); + wdi_dbg("Created new key container"); } else { - wdi_warn("could not obtain a key container: %s", windows_error_str(0)); + wdi_warn("Could not obtain a key container: %s (0x%08X)", winpki_error_str(0), GetLastError()); goto out; } - // Generate key pair (0x0400XXXX = RSA 1024 bit) - if (!CryptGenKey(hCSP, AT_SIGNATURE, 0x04000000 | CRYPT_EXPORTABLE, &hKey)) { - wdi_dbg("could not generate keypair: %s", windows_error_str(0)); + // Generate key pair using RSA 4096 + // (Key_size <<16) because key size is in upper 16 bits + if (!CryptGenKey(hCSP, AT_SIGNATURE, (4096U<<16) | CRYPT_EXPORTABLE, &hKey)) { + wdi_dbg("Could not generate keypair: %s", winpki_error_str(0)); goto out; } - wdi_dbg("generated new keypair"); + wdi_dbg("Generated new keypair..."); // Set the subject if ( (!pfCertStrToNameA(X509_ASN_ENCODING, szCertSubject, CERT_X500_NAME_STR, NULL, NULL, &SubjectIssuerBlob.cbData, NULL)) || ((SubjectIssuerBlob.pbData = (BYTE*)malloc(SubjectIssuerBlob.cbData)) == NULL) || (!pfCertStrToNameA(X509_ASN_ENCODING, szCertSubject, CERT_X500_NAME_STR, NULL, SubjectIssuerBlob.pbData, &SubjectIssuerBlob.cbData, NULL)) ) { - wdi_warn("could not encode subject name for self signed cert: %s", windows_error_str(0)); + wdi_warn("Could not encode subject name for self signed cert: %s", winpki_error_str(0)); goto out; } @@ -721,16 +830,19 @@ PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) // Prepare algorithm structure for self-signed certificate memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm)); - SignatureAlgorithm.pszObjId = szOID_RSA_SHA256RSA; + + // Windows 7 does not properly support SHA256 and may show a "Trusted Publisher" dialog unless SHA1 is used + GetWindowsVersion(); + SignatureAlgorithm.pszObjId = (nWindowsVersion > WINDOWS_7) ? szOID_RSA_SHA256RSA : szOID_RSA_SHA1RSA; // Create self-signed certificate pCertContext = pfCertCreateSelfSignCertificate((ULONG_PTR)NULL, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, NULL, &sExpirationDate, &certExtensionsArray); if (pCertContext == NULL) { - wdi_warn("could not create self signed certificate: %s", windows_error_str(0)); + wdi_warn("Could not create self signed certificate: %s", winpki_error_str(0)); goto out; } - wdi_info("created new self-signed certificate '%s'", szCertSubject); + wdi_info("Created new self-signed certificate '%s'", szCertSubject); out: free(pbEnhKeyUsage); @@ -777,12 +889,12 @@ BOOL DeletePrivateKey(PCCERT_CONTEXT pCertContext) PF_INIT_OR_OUT(CertFreeCertificateContext, Crypt32); if (!pfCryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, NULL, &hCSP, &dwKeySpec, &bFreeCSP)) { - wdi_warn("error getting CSP: %s", windows_error_str(0)); + wdi_warn("Error getting CSP: %s", winpki_error_str(0)); goto out; } if (!CryptAcquireContextW(&hCSP, wszKeyContainer, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_SILENT|CRYPT_DELETEKEYSET)) { - wdi_warn("failed to delete private key: %s", windows_error_str(0)); + wdi_warn("Failed to delete private key: %s", winpki_error_str(0)); } // This is optional, but unless we reimport the cert data after having deleted the key @@ -797,11 +909,11 @@ BOOL DeletePrivateKey(PCCERT_CONTEXT pCertContext) pCertContext->cbCertEncoded, CERT_STORE_ADD_REPLACE_EXISTING, &pCertContextUpdate)) && (pCertContextUpdate != NULL) ) { // The friendly name is lost in this operation - restore it if (!pfCertSetCertificateContextProperty(pCertContextUpdate, CERT_FRIENDLY_NAME_PROP_ID, 0, &libwdiNameBlob)) { - wdi_warn("coud not set friendly name: %s", windows_error_str(0)); + wdi_warn("Could not set friendly name: %s", winpki_error_str(0)); } pfCertFreeCertificateContext(pCertContextUpdate); } else { - wdi_warn("failed to update '%s': %s", szStoresToUpdate[i], windows_error_str(0)); + wdi_warn("Failed to update '%s': %s", szStoresToUpdate[i], winpki_error_str(0)); } pfCertCloseStore(hSystemStore, 0); } @@ -862,18 +974,18 @@ BOOL SelfSignFile(LPCSTR szFileName, LPCSTR szCertSubject) if (pCertContext == NULL) { goto out; } - wdi_dbg("successfully created certificate '%s'", szCertSubject); + wdi_dbg("Successfully created certificate '%s'", szCertSubject); if ( (!AddCertToStore(pCertContext, "Root")) || (!AddCertToStore(pCertContext, "TrustedPublisher")) ) { goto out; } - wdi_info("added certificate '%s' to 'Root' and 'TrustedPublisher' stores", szCertSubject); + wdi_info("Added certificate '%s' to 'Root' and 'TrustedPublisher' stores", szCertSubject); // Setup SIGNER_FILE_INFO struct signerFileInfo.cbSize = sizeof(SIGNER_FILE_INFO); wszFileName = UTF8toWCHAR(szFileName); if (wszFileName == NULL) { - wdi_warn("unable to convert '%s' to UTF16"); + wdi_warn("Unable to convert '%s' to UTF16", szFileName); goto out; } signerFileInfo.pwszFileName = wszFileName; @@ -923,11 +1035,11 @@ BOOL SelfSignFile(LPCSTR szFileName, LPCSTR szCertSubject) // Sign file with cert hResult = pfSignerSignEx(0, &signerSubjectInfo, &signerCert, &signerSignatureInfo, NULL, NULL, NULL, NULL, &pSignerContext); if (hResult != S_OK) { - wdi_warn("SignerSignEx failed. hResult #%X, error %s", hResult, windows_error_str(0)); + wdi_warn("SignerSignEx failed: %s", hResult, winpki_error_str(hResult)); goto out; } r = TRUE; - wdi_info("successfully signed file '%s'", szFileName); + wdi_info("Successfully signed file '%s'", szFileName); // Clean up out: @@ -937,7 +1049,7 @@ BOOL SelfSignFile(LPCSTR szFileName, LPCSTR szCertSubject) * by an attacker to self sign a malicious applications. */ if ((pCertContext != NULL) && (DeletePrivateKey(pCertContext))) { - wdi_info("successfully deleted private key"); + wdi_info("Successfully deleted private key"); } free((void*)wszFileName); if (pSignerContext != NULL) @@ -1025,7 +1137,7 @@ static BOOL AddFileHash(HANDLE hCat, LPCSTR szFileName, BYTE* pbFileHash) // Set the PE or CAB/INF type according to the extension for (szExt = &szFileName[strlen(szFileName)]; (szExt > szFileName) && (*szExt!='.'); szExt--); if (szExt == szFileName) { - wdi_warn("unhandled file type: '%s' - ignoring", szFileName); + wdi_warn("Unhandled file type: '%s' - ignoring", szFileName); goto out; } szExt++; @@ -1037,7 +1149,7 @@ static BOOL AddFileHash(HANDLE hCat, LPCSTR szFileName, BYTE* pbFileHash) wdi_dbg("'%s': INF type", szFileName); bPEType = FALSE; } else { - wdi_warn("unhandled file type: '%s' - ignoring", szFileName); + wdi_warn("Unhandled file type: '%s' - ignoring", szFileName); goto out; } @@ -1052,12 +1164,12 @@ static BOOL AddFileHash(HANDLE hCat, LPCSTR szFileName, BYTE* pbFileHash) sSPCImageData.Flags.pbData = (BYTE*)&fImageData; sSPCImageData.pFile = &sSPCLink; if (!pfCryptEncodeObject(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_OBJID, &sSPCImageData, pbEncoded, &cbEncoded)) { - wdi_warn("unable to encode SPC Image Data: %s", windows_error_str(0)); + wdi_warn("Unable to encode SPC Image Data: %s", winpki_error_str(0)); goto out; } } else { if (!pfCryptEncodeObject(X509_ASN_ENCODING, SPC_CAB_DATA_OBJID, &sSPCLink, pbEncoded, &cbEncoded)) { - wdi_warn("unable to encode SPC Image Data: %s", windows_error_str(0)); + wdi_warn("Unable to encode SPC Image Data: %s", winpki_error_str(0)); goto out; } } @@ -1074,7 +1186,7 @@ static BOOL AddFileHash(HANDLE hCat, LPCSTR szFileName, BYTE* pbFileHash) // Create the new member if ((pCatMember = pfCryptCATPutMemberInfo(hCat, NULL, wszHash, (GUID*)((bPEType)?&pe_guid:&inf_guid), 0x200, sizeof(sSIPData), (BYTE*)&sSIPData)) == NULL) { - wdi_warn("unable to create cat entry for file '%s': %s", szFileName, windows_error_str(0)); + wdi_warn("Unable to create cat entry for file '%s': %s", szFileName, winpki_error_str(0)); goto out; } @@ -1085,7 +1197,7 @@ static BOOL AddFileHash(HANDLE hCat, LPCSTR szFileName, BYTE* pbFileHash) || (pfCryptCATPutAttrInfo(hCat, pCatMember, L"OSAttr", CRYPTCAT_ATTR_AUTHENTICATED|CRYPTCAT_ATTR_NAMEASCII|CRYPTCAT_ATTR_DATAASCII, 2*((DWORD)wcslen(wszOSAttr)+1), (BYTE*)wszOSAttr) == NULL) ) { - wdi_warn("unable to create attributes for file '%s': %s", szFileName, windows_error_str(0)); + wdi_warn("Unable to create attributes for file '%s': %s", szFileName, winpki_error_str(0)); goto out; } r = TRUE; @@ -1123,13 +1235,9 @@ static BOOL GetFullPath(LPCSTR szSrc, LPSTR szDst, DWORD dwDstSize) if ((szSrcCopy = (LPSTR)malloc(strlen(szSrc) + 1)) == NULL) return 1; memcpy(szSrcCopy, szSrc, strlen(szSrc) + 1); HandleSeparators(szSrcCopy); - r = GetFullPathNameA(szSrcCopy, (DWORD)dwDstSize, szDst, NULL); + r = GetFullPathNameU(szSrcCopy, (DWORD)dwDstSize, szDst, NULL); free(szSrcCopy); - if ((r != 0) && (r <= dwDstSize)) { - return TRUE; - } - fprintf(stderr, "Unable to get full path for '%s'.\n", szSrc); - return FALSE; + return ((r != 0) && (r <= dwDstSize)); } // Modified from http://www.zemris.fer.hr/predmeti/os1/misc/Unix2Win.htm @@ -1148,10 +1256,10 @@ static void ScanDirAndHash(HANDLE hCat, LPCSTR szDirName, LPSTR* szFileList, DWO // Get the proper directory path if ( (strlen(szInitialDir) + strlen(szDirName) + 4) > sizeof(szDir) ) { - wdi_warn("path overflow"); + wdi_warn("Path overflow"); return; } - sprintf(szDir, "%s%c%s", szInitialDir, '\\', szDirName); + static_sprintf(szDir, "%s%c%s", szInitialDir, '\\', szDirName); // Get the first file strcat(szDir, "\\*"); @@ -1172,14 +1280,14 @@ static void ScanDirAndHash(HANDLE hCat, LPCSTR szDirName, LPSTR* szFileList, DWO FindClose(hList); return; } - sprintf(szSubDir, "%s%c%s", szDirName, '\\', szEntry); + static_sprintf(szSubDir, "%s%c%s", szDirName, '\\', szEntry); ScanDirAndHash(hCat, szSubDir, szFileList, cFileList); } } else { for (i=0; i +* Copyright (c) 2010-2023 Pete Batard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,19 +32,18 @@ enum WindowsVersion { WINDOWS_UNDEFINED = -1, WINDOWS_UNSUPPORTED = 0, - WINDOWS_7 = 0x61, - WINDOWS_8 = 0x62, - WINDOWS_8_1 = 0x63, + WINDOWS_XP = 0x51, + WINDOWS_2003 = 0x52, // Also XP_64 + WINDOWS_VISTA = 0x60, // Also Server 2008 + WINDOWS_7 = 0x61, // Also Server 2008_R2 + WINDOWS_8 = 0x62, // Also Server 2012 + WINDOWS_8_1 = 0x63, // Also Server 2012_R2 WINDOWS_10_PREVIEW1 = 0x64, - WINDOWS_10 = 0xA0, + WINDOWS_10 = 0xA0, // Also Server 2016, also Server 2019 + WINDOWS_11 = 0xB0, // Also Server 2022 WINDOWS_MAX }; -extern int nWindowsVersion; -extern char WindowsVersionStr[128]; - -void GetWindowsVersion(void); - /* Read a string registry key value */ static __inline BOOL ReadRegistryStr(HKEY key_root, const char* key_name, char* str, DWORD len) { diff --git a/libwdi/tokenizer.c b/libwdi/tokenizer.c index 1442a866..b82f2e95 100644 --- a/libwdi/tokenizer.c +++ b/libwdi/tokenizer.c @@ -77,8 +77,8 @@ long tokenize_string(const char* src, // text to bo tokenized long src_count, // length of src char** dst, // destination buffer (must be freed) const token_entity_t* token_entities, // match/replace token list - const char* tok_prefix, // the token prefix exmpl:"$(" - const char* tok_suffix, // the token suffix exmpl:")" + const char* tok_prefix, // the token prefix example:"$(" + const char* tok_suffix, // the token suffix example:")" int recursive) // allows tokenzing tokens in tokens { const token_entity_t* next_match; @@ -152,7 +152,7 @@ long tokenize_string(const char* src, // text to bo tokenized while ((next_match=&token_entities[match_replace_pos++])) { // the match and replace fields must both be set - if (!next_match->match || next_match->replace[0] == 0) + if (!next_match->match || (match_replace_pos == 0 && next_match->replace[0] == 0)) { break; } diff --git a/libwdi/usbser.inf.in b/libwdi/usbser.inf.in index 800b064b..afb87711 100644 --- a/libwdi/usbser.inf.in +++ b/libwdi/usbser.inf.in @@ -1,5 +1,5 @@ ; #INF_FILENAME# -; Copyright (c) 2016 Pete Batard (GNU LGPL) +; Copyright (c) 2016-2023 Pete Batard (GNU LGPL) ; Based on the USB CDC .inf sample file provided by James Stephanick ; at https://community.freescale.com/message/493287#493287 ; With acknowledgement to Sensics, Inc. , @@ -22,7 +22,7 @@ CatalogFile = #CAT_FILENAME# DriverVer = #DRIVER_DATE#, 1.0.0.0 [Manufacturer] -%VendorName% = DeviceList,NTx86,NTamd64,NTarm +%VendorName% = DeviceList,NTx86,NTamd64,NTarm64 [DeviceList.NTx86] %DeviceName% = UsbSer_Install, USB\%DeviceID% @@ -30,7 +30,7 @@ DriverVer = #DRIVER_DATE#, 1.0.0.0 [DeviceList.NTamd64] %DeviceName% = UsbSer_Install, USB\%DeviceID% -[DeviceList.NTarm] +[DeviceList.NTarm64] %DeviceName% = UsbSer_Install, USB\%DeviceID% [UsbSer_Install] diff --git a/libwdi/vid_data.c b/libwdi/vid_data.c index 6751a405..282ec20a 100644 --- a/libwdi/vid_data.c +++ b/libwdi/vid_data.c @@ -29,7 +29,7 @@ struct vendor_name { /* * http://www.linux-usb.org/usb.ids - * Version: 2017.02.12 + * Version: 2024.03.18 */ static struct vendor_name usb_vendor[] = { { 0x0001, "Fry's Electronics" }, @@ -37,8 +37,15 @@ static struct vendor_name usb_vendor[] = { { 0x0003, "Club Mac" }, { 0x0004, "Nebraska Furniture Mart" }, { 0x0011, "Unknown" }, + { 0x001f, "Walmart" }, + { 0x0040, "Anyware Corporation" }, + { 0x0042, "DMT" }, { 0x0053, "Planex" }, + { 0x0078, "Microntek" }, { 0x0079, "DragonRise Inc." }, + { 0x0080, "Unknown" }, + { 0x0085, "Boeye Technology Co., Ltd." }, + { 0x0102, "miniSTREAK" }, { 0x0105, "Trust International B.V." }, { 0x0127, "IBP" }, { 0x0145, "Unknown" }, @@ -46,13 +53,16 @@ static struct vendor_name usb_vendor[] = { { 0x0200, "TP-Link" }, { 0x0204, "Chipsbank Microelectronics Co., Ltd" }, { 0x0218, "Hangzhou Worlde" }, + { 0x0231, "Sonuus Limited" }, { 0x02ad, "HUMAX Co., Ltd." }, - { 0x0300, "MM300 eBook Reader" }, + { 0x0303, "Mini Automation Controller" }, { 0x0324, "OCZ Technology Inc" }, { 0x0325, "OCZ Technology Inc" }, { 0x0386, "LTS" }, + { 0x03c3, "ZWO" }, { 0x03d9, "Shenzhen Sinote Tech-Electron Co., Ltd" }, { 0x03da, "Bernd Walter Computer Technology" }, + { 0x03e7, "Intel" }, { 0x03e8, "EndPoints, Inc." }, { 0x03e9, "Thesys Microelectronics" }, { 0x03ea, "Data Broadcasting Corp." }, @@ -60,7 +70,7 @@ static struct vendor_name usb_vendor[] = { { 0x03ec, "Iwatsu America, Inc." }, { 0x03ed, "Mitel Corp." }, { 0x03ee, "Mitsumi" }, - { 0x03f0, "Hewlett-Packard" }, + { 0x03f0, "HP, Inc" }, { 0x03f1, "Genoa Technology" }, { 0x03f2, "Oak Technology, Inc." }, { 0x03f3, "Adaptec, Inc." }, @@ -105,7 +115,7 @@ static struct vendor_name usb_vendor[] = { { 0x0421, "Nokia Mobile Phones" }, { 0x0422, "ADI Systems, Inc." }, { 0x0423, "Computer Access Technology Corp." }, - { 0x0424, "Standard Microsystems Corp." }, + { 0x0424, "Microchip Technology, Inc. (formerly SMSC)" }, { 0x0425, "Motorola Semiconductors HK, Ltd" }, { 0x0426, "Integrated Device Technology, Inc." }, { 0x0427, "Motorola Electronics Taiwan, Ltd" }, @@ -117,7 +127,7 @@ static struct vendor_name usb_vendor[] = { { 0x042d, "Micronics" }, { 0x042e, "Acer, Inc." }, { 0x042f, "Molex, Inc." }, - { 0x0430, "Sun Microsystems, Inc." }, + { 0x0430, "Fujitsu Component Limited" }, { 0x0431, "Itac Systems, Inc." }, { 0x0432, "Unisys Corp." }, { 0x0433, "Alps Electric, Inc." }, @@ -164,7 +174,7 @@ static struct vendor_name usb_vendor[] = { { 0x0464, "AMP/Tycoelectronics Corp." }, { 0x0467, "AT&T Paradyne" }, { 0x0468, "Wieson Technologies Co., Ltd" }, - { 0x046a, "Cherry GmbH" }, + { 0x046a, "CHERRY" }, { 0x046b, "American Megatrends, Inc." }, { 0x046c, "Toshiba Corp., Digital Media Equipment" }, { 0x046d, "Logitech, Inc." }, @@ -482,7 +492,7 @@ static struct vendor_name usb_vendor[] = { { 0x05b5, "Dialogic Corp." }, { 0x05b6, "Proxima Corp." }, { 0x05b7, "Medianix Semiconductor, Inc." }, - { 0x05b8, "Agiler, Inc." }, + { 0x05b8, "SYSGRATION" }, { 0x05b9, "Philips Research Laboratories" }, { 0x05ba, "DigitalPersona, Inc." }, { 0x05bb, "Grey Cell Systems" }, @@ -584,7 +594,7 @@ static struct vendor_name usb_vendor[] = { { 0x0627, "Adomax Technology Co., Ltd" }, { 0x0628, "Tasking Software, Inc." }, { 0x0629, "Zida Technologies, Ltd" }, - { 0x062a, "Creative Labs" }, + { 0x062a, "MosArt Semiconductor Corp." }, { 0x062b, "Greatlink Electronics Taiwan, Ltd" }, { 0x062c, "Institute for Information Industry" }, { 0x062d, "Taiwan Tai-Hao Enterprises Co., Ltd" }, @@ -667,6 +677,7 @@ static struct vendor_name usb_vendor[] = { { 0x068a, "Pertech, Inc." }, { 0x068b, "Potrans International, Inc." }, { 0x068e, "CH Products, Inc." }, + { 0x068f, "Nihon KOHDEN" }, { 0x0690, "Golden Bridge Electech, Inc." }, { 0x0693, "Hagiwara Sys-Com Co., Ltd" }, { 0x0694, "Lego Group" }, @@ -760,6 +771,7 @@ static struct vendor_name usb_vendor[] = { { 0x071c, "Xionics Document Technologies, Inc." }, { 0x071d, "Eicon Networks Corp." }, { 0x071e, "Ariston Technologies" }, + { 0x0720, "Keyence Corp." }, { 0x0723, "Centillium Communications Corp." }, { 0x0726, "Vanguard International Semiconductor-America" }, { 0x0729, "Amitm" }, @@ -790,8 +802,9 @@ static struct vendor_name usb_vendor[] = { { 0x074e, "Digital Stream Corp." }, { 0x0755, "Aureal Semiconductor" }, { 0x0757, "Network Technologies, Inc." }, + { 0x0758, "Carl Zeiss Microscopy GmbH" }, { 0x075b, "Sophisticated Circuits, Inc." }, - { 0x0763, "Midiman" }, + { 0x0763, "M-Audio" }, { 0x0764, "Cyber Power System, Inc." }, { 0x0765, "X-Rite, Inc." }, { 0x0766, "Jess-Link Products Co., Ltd" }, @@ -812,11 +825,12 @@ static struct vendor_name usb_vendor[] = { { 0x0776, "Inalways Corp." }, { 0x0777, "Comda Enterprise Corp." }, { 0x0778, "Volex, Inc." }, - { 0x0779, "Fairchild Semiconductor" }, + { 0x0779, "ON Semiconductor (formerly Fairchild)" }, { 0x077a, "Sankyo Seiki Mfg. Co., Ltd" }, { 0x077b, "Linksys" }, { 0x077c, "Forward Electronics Co., Ltd" }, { 0x077d, "Griffin Technology" }, + { 0x077e, "Softing AG" }, { 0x077f, "Well Excellent & Most Corp." }, { 0x0780, "Sagem Monetel GmbH" }, { 0x0781, "SanDisk Corp." }, @@ -872,6 +886,7 @@ static struct vendor_name usb_vendor[] = { { 0x07cb, "Kingmax Technology, Inc." }, { 0x07cc, "Carry Computer Eng., Co., Ltd" }, { 0x07cd, "Elektor" }, + { 0x07ce, "Nidec Copal" }, { 0x07cf, "Casio Computer Co., Ltd" }, { 0x07d0, "Dazzle" }, { 0x07d1, "D-Link System" }, @@ -919,6 +934,7 @@ static struct vendor_name usb_vendor[] = { { 0x081b, "Indigita Corp." }, { 0x081c, "Mipsys" }, { 0x081e, "AlphaSmart, Inc." }, + { 0x081f, "Manta" }, { 0x0822, "Reudo Corp." }, { 0x0825, "GC Protronics" }, { 0x0826, "Data Transit" }, @@ -1093,7 +1109,7 @@ static struct vendor_name usb_vendor[] = { { 0x094f, "Yano" }, { 0x0951, "Kingston Technology" }, { 0x0954, "RPM Systems Corp." }, - { 0x0955, "NVidia Corp." }, + { 0x0955, "NVIDIA Corp." }, { 0x0956, "BSquare Corp." }, { 0x0957, "Agilent Technologies, Inc." }, { 0x0958, "CompuLink Research, Inc." }, @@ -1102,6 +1118,7 @@ static struct vendor_name usb_vendor[] = { { 0x095b, "Medialogic Corp." }, { 0x095c, "K-Tec Electronics" }, { 0x095d, "Polycom, Inc." }, + { 0x0964, "BITRAN" }, { 0x0967, "Acer NeWeb Corp." }, { 0x0968, "Catalyst Enterprises, Inc." }, { 0x096e, "Feitian Technologies, Inc." }, @@ -1141,6 +1158,7 @@ static struct vendor_name usb_vendor[] = { { 0x09aa, "Intersil Corp." }, { 0x09ab, "Japan Cash Machine Co., Ltd." }, { 0x09ae, "Tripp Lite" }, + { 0x09b0, "Fargo" }, { 0x09b2, "Franklin Electronic Publishers, Inc." }, { 0x09b3, "Altius Solutions, Inc." }, { 0x09b4, "MDS Telephone Systems" }, @@ -1151,7 +1169,7 @@ static struct vendor_name usb_vendor[] = { { 0x09c0, "Genpix Electronics, LLC" }, { 0x09c1, "Arris Interactive LLC" }, { 0x09c2, "Nisca Corp." }, - { 0x09c3, "ActivCard, Inc." }, + { 0x09c3, "HID Global" }, { 0x09c4, "ACTiSYS Corp." }, { 0x09c5, "Memory Corp." }, { 0x09ca, "BMC Messsysteme GmbH" }, @@ -1163,8 +1181,8 @@ static struct vendor_name usb_vendor[] = { { 0x09d1, "NeoMagic, Inc." }, { 0x09d2, "Vreelin Engineering, Inc." }, { 0x09d3, "Com One" }, - { 0x09d7, "NovAtel Inc." }, - { 0x09d8, "ELATEC" }, + { 0x09d7, "Hexagon NovAtel Inc." }, + { 0x09d8, "ELATEC GmbH" }, { 0x09d9, "KRF Tech, Ltd" }, { 0x09da, "A4Tech Co., Ltd." }, { 0x09db, "Measurement Computing Corp." }, @@ -1209,6 +1227,7 @@ static struct vendor_name usb_vendor[] = { { 0x0a2c, "AK-Modul-Bus Computer GmbH" }, { 0x0a34, "TG3 Electronics, Inc." }, { 0x0a35, "Radikal Technologies" }, + { 0x0a38, "IRIS sa" }, { 0x0a39, "Gilat Satellite Networks, Ltd" }, { 0x0a3a, "PentaMedia Co., Ltd" }, { 0x0a3c, "NTT DoCoMo, Inc." }, @@ -1232,7 +1251,7 @@ static struct vendor_name usb_vendor[] = { { 0x0a5b, "EAsics NV" }, { 0x0a5c, "Broadcom Corp." }, { 0x0a5d, "Diatrend Corp." }, - { 0x0a5f, "Zebra" }, + { 0x0a5f, "Zebra Technologies" }, { 0x0a62, "MPMan" }, { 0x0a66, "ClearCube Technology" }, { 0x0a67, "Medeli Electronics Co., Ltd" }, @@ -1443,6 +1462,7 @@ static struct vendor_name usb_vendor[] = { { 0x0bf6, "Addonics Technologies, Inc." }, { 0x0bf7, "Sunny Giken, Inc." }, { 0x0bf8, "Fujitsu Siemens Computers" }, + { 0x0bfb, "Grass Valley Group" }, { 0x0bfd, "Kvaser AB" }, { 0x0c00, "FireFly Mouse Mat" }, { 0x0c04, "MOTO Development Group, Inc." }, @@ -1462,6 +1482,7 @@ static struct vendor_name usb_vendor[] = { { 0x0c1a, "Silicon Motion, Inc." }, { 0x0c1b, "MIPS Technologies" }, { 0x0c1c, "Hang Zhou Silan Electronics Co., Ltd" }, + { 0x0c1f, "Magicard" }, { 0x0c22, "Tally Printer Corp." }, { 0x0c23, "Lernout + Hauspie" }, { 0x0c24, "Taiyo Yuden" }, @@ -1469,6 +1490,7 @@ static struct vendor_name usb_vendor[] = { { 0x0c26, "Prolific Technology Inc." }, { 0x0c27, "RFIDeas, Inc" }, { 0x0c2e, "Metrologic Instruments" }, + { 0x0c30, "Mutoh Industries Ltd" }, { 0x0c35, "Eagletron, Inc." }, { 0x0c36, "E Ink Corp." }, { 0x0c37, "e.Digital" }, @@ -1479,6 +1501,7 @@ static struct vendor_name usb_vendor[] = { { 0x0c3c, "Radius Co., Ltd" }, { 0x0c3d, "Innocom, Inc." }, { 0x0c3e, "Nextcell, Inc." }, + { 0x0c40, "ELMCU" }, { 0x0c44, "Motorola iDEN" }, { 0x0c45, "Microdia" }, { 0x0c46, "WaveRider Communications, Inc." }, @@ -1526,6 +1549,7 @@ static struct vendor_name usb_vendor[] = { { 0x0c99, "Innochips Co., Ltd" }, { 0x0c9a, "Hanwool Robotics Corp." }, { 0x0c9b, "Jobin Yvon, Inc." }, + { 0x0c9c, "Brand Innovators BV" }, { 0x0c9d, "SemTek" }, { 0x0ca2, "Zyfer" }, { 0x0ca3, "Sega Corp." }, @@ -1533,6 +1557,7 @@ static struct vendor_name usb_vendor[] = { { 0x0ca5, "BAE Systems Canada, Inc." }, { 0x0ca6, "Castles Technology Co., Ltd" }, { 0x0ca7, "Information Systems Laboratories" }, + { 0x0caa, "Allied Telesis KK." }, { 0x0cad, "Motorola CGISS" }, { 0x0cae, "Ascom Business Systems, Ltd" }, { 0x0caf, "Buslink" }, @@ -1599,6 +1624,7 @@ static struct vendor_name usb_vendor[] = { { 0x0d18, "coaXmedia" }, { 0x0d19, "Hank Connection Industrial Co., Ltd" }, { 0x0d28, "NXP" }, + { 0x0d2f, "Andamiro" }, { 0x0d32, "Leo Hui Electric Wire & Cable Co., Ltd" }, { 0x0d33, "AirSpeak, Inc." }, { 0x0d34, "Rearden Steel Technologies" }, @@ -1627,6 +1653,7 @@ static struct vendor_name usb_vendor[] = { { 0x0d55, "ASKA Technologies, Inc." }, { 0x0d56, "AVLAB Technology, Inc." }, { 0x0d57, "Solomon Microtech, Ltd" }, + { 0x0d59, "TRC Simulators b.v." }, { 0x0d5c, "SMC Networks, Inc." }, { 0x0d5e, "Myacom, Ltd" }, { 0x0d5f, "CSI, Inc." }, @@ -1739,12 +1766,14 @@ static struct vendor_name usb_vendor[] = { { 0x0e17, "Walex Electronic, Ltd" }, { 0x0e1a, "Unisys" }, { 0x0e1b, "Crewave" }, + { 0x0e1e, "Green Hills Software" }, { 0x0e20, "Pegasus Technologies Ltd." }, { 0x0e21, "Cowon Systems, Inc." }, { 0x0e22, "Symbian Ltd." }, { 0x0e23, "Liou Yuane Enterprise Co., Ltd" }, { 0x0e25, "VinChip Systems, Inc." }, { 0x0e26, "J-Phone East Co., Ltd" }, + { 0x0e2e, "Brady Worldwide, Inc." }, { 0x0e30, "HeartMath LLC" }, { 0x0e34, "Micro Computer Control Corp." }, { 0x0e35, "3Pea Technologies, Inc." }, @@ -1875,6 +1904,7 @@ static struct vendor_name usb_vendor[] = { { 0x0f41, "RDC Semiconductor Co., Ltd" }, { 0x0f42, "Nital Consulting Services, Inc." }, { 0x0f44, "Polhemus" }, + { 0x0f49, "Evolis SA" }, { 0x0f4b, "St. John Technology Co., Ltd" }, { 0x0f4c, "WorldWide Cable Opto Corp." }, { 0x0f4d, "Microtune, Inc." }, @@ -2017,6 +2047,7 @@ static struct vendor_name usb_vendor[] = { { 0x1060, "Easthome Industrial Co., Ltd" }, { 0x1063, "Motorola Electronics Taiwan, Ltd [hex]" }, { 0x1065, "CCYU Technology" }, + { 0x1068, "Micropi Elettronica" }, { 0x106a, "Loyal Legend, Ltd" }, { 0x106c, "Curitel Communications, Inc." }, { 0x106d, "San Chieh Manufacturing, Ltd" }, @@ -2034,6 +2065,7 @@ static struct vendor_name usb_vendor[] = { { 0x108b, "Grand-tek Technology Co., Ltd" }, { 0x108c, "Robert Bosch GmbH" }, { 0x108e, "Lotes Co., Ltd." }, + { 0x1091, "Numerik Jena" }, { 0x1099, "Surface Optics Corp." }, { 0x109a, "DATASOFT Systems GmbH" }, { 0x109b, "Hisense" }, @@ -2053,7 +2085,7 @@ static struct vendor_name usb_vendor[] = { { 0x10bd, "TMT Technology, Inc." }, { 0x10bf, "SmartHome" }, { 0x10c3, "Universal Laser Systems, Inc." }, - { 0x10c4, "Cygnal Integrated Products, Inc." }, + { 0x10c4, "Silicon Labs" }, { 0x10c5, "Sanei Electric, Inc." }, { 0x10c6, "Intec, Inc." }, { 0x10cb, "Eratech" }, @@ -2075,6 +2107,7 @@ static struct vendor_name usb_vendor[] = { { 0x10f0, "Nexio Co., Ltd" }, { 0x10f1, "Importek" }, { 0x10f5, "Turtle Beach" }, + { 0x10f8, "Cesys GmbH" }, { 0x10fb, "Pictos Technologies, Inc." }, { 0x10fd, "Anubis Electronics, Ltd" }, { 0x10fe, "Thrane & Thrane" }, @@ -2096,6 +2129,7 @@ static struct vendor_name usb_vendor[] = { { 0x1136, "CTS Electronincs" }, { 0x113c, "Arin Tech Co., Ltd" }, { 0x113d, "Mapower Electronics Co., Ltd" }, + { 0x113f, "Integrated Biometrics, LLC" }, { 0x1141, "V One Multimedia, Pte., Ltd" }, { 0x1142, "CyberScan Technologies, Inc." }, { 0x1145, "Japan Radio Company" }, @@ -2139,7 +2173,9 @@ static struct vendor_name usb_vendor[] = { { 0x11ac, "Nike" }, { 0x11b0, "ATECH FLASH TECHNOLOGY" }, { 0x11be, "R&D International NV" }, + { 0x11c0, "Betop" }, { 0x11c5, "Inmax" }, + { 0x11c9, "Nacon" }, { 0x11ca, "VeriFone Inc" }, { 0x11db, "Topfield Co., Ltd." }, { 0x11e6, "K.I. Technology Co. Ltd." }, @@ -2147,12 +2183,15 @@ static struct vendor_name usb_vendor[] = { { 0x11f6, "Prolific" }, { 0x11f7, "Alcatel (?)" }, { 0x1203, "TSC Auto ID Technology Co., Ltd" }, - { 0x1209, "InterBiometrics" }, + { 0x1209, "Generic" }, { 0x120e, "Hudson Soft Co., Ltd" }, { 0x120f, "Magellan" }, { 0x1210, "DigiTech" }, { 0x121e, "Jungsoft Co., Ltd" }, + { 0x121f, "Panini S.p.A." }, + { 0x1220, "TC Electronic" }, { 0x1221, "Unknown manufacturer" }, + { 0x1222, "TiPro" }, { 0x1223, "SKYCABLE ENTERPRISE. CO., LTD." }, { 0x1228, "Datapaq Limited" }, { 0x1230, "Chipidea-Microelectronica, S.A." }, @@ -2160,10 +2199,12 @@ static struct vendor_name usb_vendor[] = { { 0x1234, "Brain Actuated Technologies" }, { 0x1235, "Focusrite-Novation" }, { 0x1241, "Belkin" }, + { 0x1243, "Holtek Semiconductor, Inc." }, { 0x124a, "AirVast" }, { 0x124b, "Nyko (Honey Bee)" }, { 0x124c, "MXI - Memory Experts International, Inc." }, { 0x125c, "Apogee Inc." }, + { 0x125d, "JMicron" }, { 0x125f, "A-DATA Technology Co., Ltd." }, { 0x1260, "Standard Microsystems Corp." }, { 0x1264, "Covidien Energy-based Devices" }, @@ -2182,6 +2223,7 @@ static struct vendor_name usb_vendor[] = { { 0x1292, "Innomedia" }, { 0x1293, "Belkin Components [hex]" }, { 0x1294, "RISO KAGAKU CORP." }, + { 0x1297, "DekTec" }, { 0x129b, "CyberTAN Technology" }, { 0x12a7, "Trendchip Technologies Corp." }, { 0x12ab, "Honey Bee Electronic International Ltd." }, @@ -2193,21 +2235,25 @@ static struct vendor_name usb_vendor[] = { { 0x12cf, "DEXIN" }, { 0x12d1, "Huawei Technologies Co., Ltd." }, { 0x12d2, "LINE TECH INDUSTRIAL CO., LTD." }, + { 0x12d3, "LINAK" }, { 0x12d6, "EMS Dr. Thomas Wuensche" }, { 0x12d7, "BETTER WIRE FACTORY CO., LTD." }, { 0x12d8, "Araneus Information Systems Oy" }, { 0x12e6, "Waldorf Music GmbH" }, { 0x12ef, "Tapwave, Inc." }, + { 0x12f2, "ViewPlus Technologies, Inc." }, { 0x12f5, "Dynamic System Electronics Corp." }, { 0x12f7, "Memorex Products, Inc." }, { 0x12fd, "AIN Comm. Technology Co., Ltd" }, { 0x12ff, "Fascinating Electronics, Inc." }, + { 0x1306, "FM20 Barcode Scanner" }, { 0x1307, "Transcend Information, Inc." }, { 0x1308, "Shuttle, Inc." }, { 0x1310, "Roper" }, { 0x1312, "ICS Electronics" }, { 0x1313, "ThorLabs" }, { 0x131d, "Natural Point" }, + { 0x1325, "ams AG" }, { 0x132a, "Envara Inc." }, { 0x132b, "Konica Minolta" }, { 0x133e, "Kemper Digital GmbH" }, @@ -2219,6 +2265,7 @@ static struct vendor_name usb_vendor[] = { { 0x134c, "PanJit International Inc." }, { 0x134e, "Digby's Bitpile, Inc. DBA D Bit" }, { 0x1357, "P&E Microcomputer Systems" }, + { 0x135e, "Insta GmbH" }, { 0x135f, "Control Development Inc." }, { 0x1366, "SEGGER" }, { 0x136b, "STEC" }, @@ -2226,13 +2273,15 @@ static struct vendor_name usb_vendor[] = { { 0x1370, "Swissbit" }, { 0x1371, "CNet Technology Inc." }, { 0x1376, "Vimtron Electronics Co., Ltd." }, + { 0x1377, "Sennheiser electronic GmbH & Co. KG" }, { 0x137b, "SCAPS GmbH" }, + { 0x137c, "YASKAWA ELECTRIC CORP." }, { 0x1385, "Netgear, Inc" }, { 0x138a, "Validity Sensors, Inc." }, { 0x138e, "Jungo LTD" }, { 0x1390, "TOMTOM B.V." }, { 0x1391, "IdealTEK, Inc." }, - { 0x1395, "Sennheiser Communications" }, + { 0x1395, "DSEA A/S" }, { 0x1397, "BEHRINGER International GmbH" }, { 0x1398, "Q-tec" }, { 0x13ad, "Baltech" }, @@ -2258,16 +2307,18 @@ static struct vendor_name usb_vendor[] = { { 0x13ec, "Zydacron" }, { 0x13ee, "MosArt" }, { 0x13fd, "Initio Corporation" }, - { 0x13fe, "Kingston Technology Company Inc." }, + { 0x13fe, "Phison Electronics Corp." }, { 0x1400, "Axxion Group Corp." }, { 0x1402, "Bowe Bell & Howell" }, { 0x1403, "Sitronix" }, + { 0x1404, "Fundamental Software, Inc." }, { 0x1409, "IDS Imaging Development Systems GmbH" }, { 0x140e, "Telechips, Inc." }, { 0x1410, "Novatel Wireless" }, { 0x1415, "Nam Tai E&E Products Ltd. or OmniVision Technologies, Inc." }, { 0x1419, "ABILITY ENTERPRISE CO., LTD." }, { 0x1421, "Sensor Technology" }, + { 0x1424, "Posnet Polska S.A." }, { 0x1429, "Vega Technologies Industrial (Austria) Co." }, { 0x142a, "Thales E-Transactions" }, { 0x142b, "Arbiter Systems, Inc." }, @@ -2278,6 +2329,8 @@ static struct vendor_name usb_vendor[] = { { 0x143c, "Altek Corporation" }, { 0x1443, "Digilent" }, { 0x1446, "X.J.GROUP" }, + { 0x1451, "Force Dimension" }, + { 0x1452, "Dai Nippon Printing, Inc" }, { 0x1453, "Radio Shack" }, { 0x1456, "Extending Wire & Cable Co., Ltd." }, { 0x1457, "First International Computer, Inc." }, @@ -2285,6 +2338,7 @@ static struct vendor_name usb_vendor[] = { { 0x1460, "Tatung Co." }, { 0x1461, "Staccato Communications" }, { 0x1462, "Micro Star International" }, + { 0x146b, "BigBen Interactive" }, { 0x1472, "Huawei-3Com" }, { 0x147a, "Formosa Industrial Computing, Inc." }, { 0x147e, "Upek" }, @@ -2320,12 +2374,15 @@ static struct vendor_name usb_vendor[] = { { 0x14f7, "TechniSat Digital GmbH" }, { 0x1500, "Ellisys" }, { 0x1501, "Pine-Tum Enterprise Co., Ltd." }, + { 0x1504, "Bixolon CO LTD" }, + { 0x1508, "Fibocom" }, { 0x1509, "First International Computer, Inc." }, { 0x1513, "medMobile" }, { 0x1514, "Actel" }, { 0x1516, "CompUSA" }, { 0x1518, "Cheshire Engineering Corp." }, { 0x1519, "Comneon" }, + { 0x151f, "Opal Kelly Incorporated" }, { 0x1520, "Bitwire Corp." }, { 0x1524, "ENE Technology Inc" }, { 0x1527, "Silicon Portals" }, @@ -2364,7 +2421,7 @@ static struct vendor_name usb_vendor[] = { { 0x15ba, "Olimex Ltd." }, { 0x15c0, "XL Imaging" }, { 0x15c2, "SoundGraph Inc." }, - { 0x15c5, "Advance Multimedia Internet Technology Inc. (AMIT)" }, + { 0x15c5, "Pressure Profile Systems, Inc." }, { 0x15c6, "Laboratoires MXM" }, { 0x15c8, "KTF Technologies" }, { 0x15c9, "D-Box Technologies" }, @@ -2380,6 +2437,7 @@ static struct vendor_name usb_vendor[] = { { 0x15ec, "Belcarra Technologies Corp." }, { 0x15f4, "HanfTek" }, { 0x1604, "Tascam" }, + { 0x1605, "ACCES I/O Products, Inc." }, { 0x1606, "Umax" }, { 0x1608, "Inside Out Networks [hex]" }, { 0x160a, "VIA Technologies, Inc." }, @@ -2387,12 +2445,14 @@ static struct vendor_name usb_vendor[] = { { 0x1614, "Amoi Electronics" }, { 0x1617, "Sony Corp." }, { 0x1619, "L & K Precision Technology Co., Ltd." }, + { 0x161c, "Digitech Systems" }, { 0x1621, "Wionics Research" }, { 0x1628, "Stonestreet One, Inc." }, { 0x162a, "Airgo Networks Inc." }, { 0x162f, "WiQuest Communications, Inc." }, { 0x1630, "2Wire, Inc." }, { 0x1631, "Good Way Technology" }, + { 0x1633, "AIM GmbH" }, { 0x1645, "Entrega [hex]" }, { 0x1649, "SofTec Microsystems" }, { 0x164a, "ChipX" }, @@ -2407,6 +2467,7 @@ static struct vendor_name usb_vendor[] = { { 0x166a, "Clipsal" }, { 0x1677, "China Huada Integrated Circuit Design (Group) Co., Ltd. (CIDC Group)" }, { 0x1679, "Total Phase" }, + { 0x167b, "Pure Digital Technologies, Inc." }, { 0x1680, "Golden Bridge Electech Inc." }, { 0x1681, "Prevo Technologies, Inc." }, { 0x1682, "Maxwise Production Enterprise Ltd." }, @@ -2436,9 +2497,11 @@ static struct vendor_name usb_vendor[] = { { 0x16d6, "JABLOCOM s.r.o." }, { 0x16d8, "CMOTECH Co., Ltd." }, { 0x16dc, "Wiener, Plein & Baus" }, + { 0x16de, "Telemecanique" }, { 0x16df, "King Billion Electronics Co., Ltd." }, - { 0x16f0, "GN ReSound A/S" }, + { 0x16f0, "GN Hearing A/S" }, { 0x16f5, "Futurelogic Inc." }, + { 0x1702, "FDI-MATELEC" }, { 0x1706, "BlueView Technologies, Inc." }, { 0x1707, "ARTIMI" }, { 0x170b, "Swissonic" }, @@ -2450,7 +2513,8 @@ static struct vendor_name usb_vendor[] = { { 0x172f, "Waltop International Corp." }, { 0x1733, "Cellink Technology Co., Ltd" }, { 0x1736, "CANON IMAGING SYSTEM TECHNOLOGIES INC." }, - { 0x1737, "Linksys" }, + { 0x1737, "802.11g Adapter [Linksys WUSB54GC v3]" }, + { 0x173a, "Roche" }, { 0x173d, "QSENN" }, { 0x1740, "Senao" }, { 0x1743, "General Atomics" }, @@ -2461,14 +2525,17 @@ static struct vendor_name usb_vendor[] = { { 0x1756, "ENENSYS Technologies" }, { 0x1759, "LucidPort Technology, Inc." }, { 0x1761, "ASUSTek Computer, Inc. (wrong ID)" }, + { 0x1770, "MSI" }, { 0x1772, "System Level Solutions, Inc." }, { 0x1776, "Arowana" }, + { 0x1777, "Microscan Systems, Inc." }, { 0x177f, "Sweex" }, { 0x1781, "Multiple Vendors" }, { 0x1782, "Spreadtrum Communications Inc." }, { 0x1784, "TopSeed Technology Corp." }, { 0x1787, "ATI AIB" }, { 0x1788, "ShenZhen Litkconn Technology Co., Ltd." }, + { 0x178e, "ASUSTek Computer, Inc. (wrong ID)" }, { 0x1796, "Printrex, Inc." }, { 0x1797, "JALCO CO., LTD." }, { 0x1799, "Thales Norway A/S" }, @@ -2491,7 +2558,7 @@ static struct vendor_name usb_vendor[] = { { 0x17ef, "Lenovo" }, { 0x17f4, "WaveSense" }, { 0x17f5, "K.K. Rocky" }, - { 0x17f6, "Unicomp, Inc" }, + { 0x17f6, "Unicomp, Inc." }, { 0x1809, "Advantech" }, { 0x1822, "Twinhan" }, { 0x1831, "Gwo Jinn Industries Co., Ltd." }, @@ -2499,6 +2566,7 @@ static struct vendor_name usb_vendor[] = { { 0x183d, "VIVOphone" }, { 0x1843, "Vaisala" }, { 0x1849, "ASRock Incorporation" }, + { 0x184f, "K2L GmbH" }, { 0x1852, "GYROCOM C&C Co., LTD" }, { 0x1854, "Memory Devices Ltd." }, { 0x185b, "Compro" }, @@ -2530,6 +2598,7 @@ static struct vendor_name usb_vendor[] = { { 0x18e8, "Qcom" }, { 0x18ea, "Matrox Graphics, Inc." }, { 0x18ec, "Arkmicro Technologies Inc." }, + { 0x18ef, "ELV Elektronik AG" }, { 0x18f8, "[Maxxter]" }, { 0x18fb, "Scriptel Corporation" }, { 0x18fd, "FineArch Inc." }, @@ -2541,10 +2610,12 @@ static struct vendor_name usb_vendor[] = { { 0x191c, "Innovative Technology LTD" }, { 0x1923, "FitLinxx" }, { 0x1926, "NextWindow" }, + { 0x1928, "Proceq SA" }, { 0x192f, "Avago Technologies, Pte." }, { 0x1930, "Shenzhen Xianhe Technology Co., Ltd." }, { 0x1931, "Ningbo Broad Telecommunication Co., Ltd." }, { 0x1934, "Feature Integration Technology Inc. (Fintek)" }, + { 0x1935, "Elektron Music Machines" }, { 0x1938, "Meinberg Funkuhren GmbH & Co. KG" }, { 0x1941, "Dream Link" }, { 0x1943, "Sensoray Co., Inc." }, @@ -2554,22 +2625,27 @@ static struct vendor_name usb_vendor[] = { { 0x1953, "Ironkey Inc." }, { 0x1954, "Radiient Technologies" }, { 0x195d, "Itron Technology iONE" }, + { 0x1963, "IK Multimedia" }, { 0x1965, "Uniden Corporation" }, { 0x1967, "CASIO HITACHI Mobile Communications Co., Ltd." }, { 0x196b, "Wispro Technology Inc." }, { 0x1970, "Dane-Elec Corp. USA" }, + { 0x1973, "Spectralink Corporation" }, { 0x1975, "Dongguan Guneetal Wire & Cable Co., Ltd." }, { 0x1976, "Chipsbrand Microelectronics (HK) Co., Ltd." }, { 0x1977, "T-Logic" }, { 0x197d, "Leuze electronic" }, + { 0x1980, "Storage Appliance Corporation" }, { 0x1989, "Nuconn Technology Corp." }, { 0x198f, "Beceem Communications Inc." }, { 0x1990, "Acron Precision Industrial Co., Ltd." }, { 0x1995, "Trillium Technology Pty. Ltd." }, { 0x1996, "PixeLINK" }, + { 0x1997, "Shenzhen Riitek Technology Co., Ltd" }, { 0x199b, "MicroStrain, Inc." }, { 0x199e, "The Imaging Source Europe GmbH" }, { 0x199f, "Benica Corporation" }, + { 0x19a5, "HARRIS Corp." }, { 0x19a8, "Biforst Technology Inc." }, { 0x19ab, "Bodelin" }, { 0x19af, "S Life" }, @@ -2581,6 +2657,7 @@ static struct vendor_name usb_vendor[] = { { 0x19c2, "Futuba" }, { 0x19ca, "Mindtribe" }, { 0x19cf, "Parrot SA" }, + { 0x19d1, "BYD" }, { 0x19d2, "ZTE WCDMA Technologies MSM" }, { 0x19db, "KFI Printers" }, { 0x19e1, "WeiDuan Electronic Accessory (S.Z.) Co., Ltd." }, @@ -2588,6 +2665,7 @@ static struct vendor_name usb_vendor[] = { { 0x19ef, "Pak Heng Technology (Shenzhen) Co., Ltd." }, { 0x19f7, "RODE Microphones" }, { 0x19fa, "Gampaq Co.Ltd" }, + { 0x19fd, "MTI Instruments Inc." }, { 0x19ff, "Dynex" }, { 0x1a08, "Bellwood International, Inc." }, { 0x1a0a, "USB-IF non-workshop" }, @@ -2606,6 +2684,7 @@ static struct vendor_name usb_vendor[] = { { 0x1a4b, "SafeBoot International B.V." }, { 0x1a5a, "Tandberg Data" }, { 0x1a61, "Abbott Diabetes Care" }, + { 0x1a64, "Mastervolt" }, { 0x1a6a, "Spansion Inc." }, { 0x1a6d, "SamYoung Electronics Co., Ltd" }, { 0x1a6e, "Global Unichip Corp." }, @@ -2614,6 +2693,7 @@ static struct vendor_name usb_vendor[] = { { 0x1a79, "Bayer Health Care LLC" }, { 0x1a7b, "Lumberg Connect GmbH & Co. KG" }, { 0x1a7c, "Evoluent" }, + { 0x1a7e, "Meltec Systementwicklung" }, { 0x1a81, "Holtek Semiconductor, Inc." }, { 0x1a86, "QinHeng Electronics" }, { 0x1a89, "Dynalith Systems Co., Ltd." }, @@ -2623,25 +2703,31 @@ static struct vendor_name usb_vendor[] = { { 0x1aa4, "Data Drive Thru, Inc." }, { 0x1aa5, "UBeacon Technologies, Inc." }, { 0x1aa6, "eFortune Technology Corp." }, + { 0x1aab, "Silvercreations Software AG" }, { 0x1aad, "KeeTouch" }, { 0x1ab1, "Rigol Technologies" }, + { 0x1ab2, "Allied Vision" }, { 0x1acb, "Salcomp Plc" }, { 0x1acc, "Midiplus Co, Ltd." }, { 0x1ad1, "Desay Wire Co., Ltd." }, { 0x1ad4, "APS" }, - { 0x1adb, "SEL C662 Serial Cable" }, + { 0x1adb, "Schweitzer Engineering Laboratories, Inc" }, { 0x1ae4, "ic-design Reinhard Gottinger GmbH" }, { 0x1ae7, "X-TENSIONS" }, { 0x1aed, "High Top Precision Electronic Co., Ltd." }, { 0x1aef, "Conntech Electronic (Suzhou) Corporation" }, { 0x1af1, "Connect One Ltd." }, + { 0x1af3, "Kingsis Technology Corporation" }, { 0x1afe, "A. Eberle GmbH & Co. KG" }, { 0x1b04, "Meilhaus Electronic GmbH" }, { 0x1b0e, "BLUTRONICS S.r.l." }, + { 0x1b12, "Eventide" }, { 0x1b1c, "Corsair" }, + { 0x1b1e, "General Imaging / General Electric" }, { 0x1b1f, "eQ-3 Entwicklung GmbH" }, { 0x1b20, "MStar Semiconductor, Inc." }, { 0x1b22, "WiLinx Corp." }, + { 0x1b24, "Telegent Systems, Inc." }, { 0x1b26, "Cellex Power Products, Inc." }, { 0x1b27, "Current Electronics Inc." }, { 0x1b28, "NAVIsis Inc." }, @@ -2678,6 +2764,8 @@ static struct vendor_name usb_vendor[] = { { 0x1bad, "Harmonix Music" }, { 0x1bae, "Vuzix Corporation" }, { 0x1bbb, "T & A Mobile Phones" }, + { 0x1bbd, "Videology Imaging Solutions, Inc." }, + { 0x1bc0, "Beijing Senseshield Technology Co.,Ltd." }, { 0x1bc4, "Ford Motor Co." }, { 0x1bc5, "AVIXE Technology (China) Ltd." }, { 0x1bc7, "Telit Wireless Solutions" }, @@ -2685,6 +2773,7 @@ static struct vendor_name usb_vendor[] = { { 0x1bcf, "Sunplus Innovation Technology Inc." }, { 0x1bd0, "Hangzhou Riyue Electronic Co., Ltd." }, { 0x1bd5, "BG Systems, Inc." }, + { 0x1bda, "University Of Southampton" }, { 0x1bde, "P-TWO INDUSTRIES, INC." }, { 0x1bef, "Shenzhen Tongyuan Network-Communication Cables Co., Ltd" }, { 0x1bf0, "RealVision Inc." }, @@ -2693,9 +2782,11 @@ static struct vendor_name usb_vendor[] = { { 0x1bfd, "TouchPack" }, { 0x1c02, "Kreton Corporation" }, { 0x1c04, "QNAP System Inc." }, + { 0x1c05, "Shenxhen Stager Electric" }, { 0x1c0c, "Ionics EMS, Inc." }, { 0x1c0d, "Relm Wireless" }, { 0x1c10, "Lanterra Industrial Co., Ltd." }, + { 0x1c11, "Input Club Inc." }, { 0x1c13, "ALECTRONIC LIMITED" }, { 0x1c1a, "Datel Electronics Ltd." }, { 0x1c1b, "Volkswagen of America, Inc." }, @@ -2705,6 +2796,7 @@ static struct vendor_name usb_vendor[] = { { 0x1c22, "ZHONGSHAN CHIANG YU ELECTRIC CO., LTD." }, { 0x1c26, "Shanghai Haiying Electronics Co., Ltd." }, { 0x1c27, "HuiYang D & S Cable Co., Ltd." }, + { 0x1c28, "PMD Technologies" }, { 0x1c29, "Elster GmbH" }, { 0x1c31, "LS Cable Ltd." }, { 0x1c34, "SpringCard" }, @@ -2713,15 +2805,20 @@ static struct vendor_name usb_vendor[] = { { 0x1c3e, "Wep Peripherals" }, { 0x1c40, "EZPrototypes" }, { 0x1c49, "Cherng Weei Technology Corp." }, + { 0x1c4b, "Geratherm Medical AG" }, { 0x1c4f, "SiGma Micro" }, + { 0x1c57, "Zalman Tech Co., Ltd." }, { 0x1c6b, "Philips & Lite-ON Digital Solutions Corporation" }, { 0x1c6c, "Skydigital Inc." }, + { 0x1c71, "Humanware Inc" }, { 0x1c73, "AMT" }, + { 0x1c75, "Arturia" }, { 0x1c77, "Kaetat Industrial Co., Ltd." }, { 0x1c78, "Datascope Corp." }, { 0x1c79, "Unigen Corporation" }, { 0x1c7a, "LighTuning Technology Inc." }, { 0x1c7b, "LUXSHARE PRECISION INDUSTRY (SHENZHEN) CO., LTD." }, + { 0x1c82, "Atracsys" }, { 0x1c83, "Schomaecker GmbH" }, { 0x1c87, "2N TELEKOMUNIKACE a.s." }, { 0x1c88, "Somagic, Inc." }, @@ -2756,6 +2853,7 @@ static struct vendor_name usb_vendor[] = { { 0x1d09, "TechFaith Wireless Technology Limited" }, { 0x1d0a, "Johnson Controls, Inc. The Automotive Business Unit" }, { 0x1d0b, "HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD." }, + { 0x1d0d, "TDKMedia" }, { 0x1d0f, "Sonix Technology Co., Ltd." }, { 0x1d14, "ALPHA-SAT TECHNOLOGY LIMITED" }, { 0x1d17, "C-Thru Music Ltd." }, @@ -2769,34 +2867,53 @@ static struct vendor_name usb_vendor[] = { { 0x1d50, "OpenMoko, Inc." }, { 0x1d57, "Xenta" }, { 0x1d5b, "Smartronix, Inc." }, + { 0x1d5c, "Fresco Logic" }, { 0x1d6b, "Linux Foundation" }, + { 0x1d88, "Mahr GmbH" }, { 0x1d90, "Citizen" }, { 0x1d9d, "Sigma Sport" }, + { 0x1dd2, "Leo Bodnar Electronics Ltd" }, + { 0x1dd3, "Dajc Inc." }, { 0x1de1, "Actions Microelectronics Co." }, + { 0x1de6, "MICRORISC s.r.o." }, + { 0x1df7, "SDRplay" }, { 0x1e0e, "Qualcomm / Option" }, { 0x1e10, "Point Grey Research, Inc." }, { 0x1e17, "Mirion Technologies Dosimetry Services Division" }, - { 0x1e1d, "Lumension Security" }, + { 0x1e1d, "Kanguru Solutions" }, { 0x1e1f, "INVIA" }, { 0x1e29, "Festo AG & Co. KG" }, + { 0x1e2d, "Gemalto M2M GmbH" }, { 0x1e3d, "Chipsbank Microelectronics Co., Ltd" }, { 0x1e41, "Cleverscope" }, + { 0x1e44, "SHIMANO INC." }, { 0x1e4e, "Cubeternet" }, { 0x1e54, "TypeMatrix" }, { 0x1e68, "TrekStor GmbH & Co. KG" }, { 0x1e71, "NZXT" }, { 0x1e74, "Coby Electronics Corporation" }, + { 0x1e7b, "Zurich Instruments" }, { 0x1e7d, "ROCCAT" }, + { 0x1e8e, "Airbus Defence and Space" }, + { 0x1e91, "Other World Computing" }, + { 0x1ea7, "SHARKOON Technologies GmbH" }, + { 0x1eab, "Fujian Newland Computer Co., Ltd" }, + { 0x1eaf, "Leaflabs" }, + { 0x1eb8, "Modacom Co., Ltd." }, { 0x1ebb, "NuCORE Technology, Inc." }, + { 0x1ecb, "AMTelecom" }, + { 0x1ed8, "FENDER MUSICAL INSTRUMENTS CORPORATION" }, { 0x1eda, "AirTies Wireless Networks" }, { 0x1edb, "Blackmagic design" }, { 0x1ee8, "ONDA COMMUNICATION S.p.a." }, { 0x1ef6, "EADS Deutschland GmbH" }, + { 0x1f0c, "CMX Systems" }, { 0x1f28, "Cal-Comp" }, - { 0x1f3a, "Onda (unverified)" }, + { 0x1f3a, "Allwinner Technology" }, { 0x1f44, "The Neat Company" }, { 0x1f48, "H-TRONIC GmbH" }, { 0x1f4d, "G-Tek Electronics Group" }, + { 0x1f52, "Systems & Electronic Development FZCO (SEDCO)" }, { 0x1f6f, "Aliph" }, { 0x1f75, "Innostor Technology Corporation" }, { 0x1f82, "TANDBERG" }, @@ -2804,18 +2921,29 @@ static struct vendor_name usb_vendor[] = { { 0x1f87, "Stantum" }, { 0x1f9b, "Ubiquiti Networks, Inc." }, { 0x1fab, "Samsung Opto-Electroncs Co., Ltd." }, + { 0x1fac, "Franklin Wireless" }, + { 0x1fae, "Lumidigm" }, + { 0x1fb2, "Withings" }, + { 0x1fba, "DERMALOG Identification Systems GmbH" }, { 0x1fbd, "Delphin Technology AG" }, { 0x1fc9, "NXP Semiconductors" }, { 0x1fde, "ILX Lightwave Corporation" }, { 0x1fe7, "Vertex Wireless Co., Ltd." }, { 0x1ff7, "CVT Electronics.Co.,Ltd" }, + { 0x1ffb, "Pololu Corporation" }, { 0x1fff, "Ideofy Inc." }, + { 0x2000, "CMX Systems" }, { 0x2001, "D-Link Corp." }, { 0x2002, "DAP Technologies" }, { 0x2003, "detectomat" }, + { 0x2006, "LenovoMobile" }, + { 0x2009, "iStorage" }, { 0x200c, "Reloop" }, { 0x2013, "PCTV Systems" }, + { 0x2018, "Deutsche Telekom AG" }, { 0x2019, "PLANEX" }, + { 0x201e, "Haier" }, + { 0x203a, "PARALLELS" }, { 0x203d, "Encore Electronics Inc." }, { 0x2040, "Hauppauge" }, { 0x2047, "Texas Instruments" }, @@ -2828,78 +2956,376 @@ static struct vendor_name usb_vendor[] = { { 0x20b1, "XMOS Ltd" }, { 0x20b3, "Hanvon" }, { 0x20b7, "Qi Hardware" }, + { 0x20bc, "ShenZhen ShanWan Technology Co., Ltd." }, { 0x20ce, "Minicircuits" }, { 0x20df, "Simtec Electronics" }, + { 0x20f0, "L3Harris Technologies" }, { 0x20f1, "NET New Electronic Technology GmbH" }, { 0x20f4, "TRENDnet" }, { 0x20f7, "XIMEA" }, { 0x2100, "RT Systems" }, { 0x2101, "ActionStar" }, + { 0x2104, "Tobii Technology AB" }, + { 0x2107, "RDING TECH CO.,LTD" }, { 0x2109, "VIA Labs, Inc." }, { 0x2113, "Softkinetic" }, + { 0x2116, "KT Tech" }, + { 0x211f, "CELOT Corporation" }, + { 0x2123, "Cheeky Dream" }, + { 0x2125, "Fiberpro Inc." }, + { 0x2133, "signotec GmbH" }, { 0x2149, "Advanced Silicon S.A." }, - { 0x2162, "Creative (?)" }, + { 0x214b, "Huasheng Electronics" }, + { 0x214e, "Swiftpoint" }, + { 0x2162, "Broadxent (Creative Labs)" }, + { 0x2166, "JVC Kenwood" }, { 0x2184, "GW Instek" }, + { 0x2188, "No brand" }, + { 0x219c, "Seal One AG" }, { 0x21a1, "Emotiv Systems Pty. Ltd." }, + { 0x21a4, "Electronic Arts Inc." }, + { 0x21a9, "Saleae, Inc." }, + { 0x21ab, "Planeta Informatica" }, + { 0x21b4, "AudioQuest" }, { 0x21d6, "Agecodagis SARL" }, + { 0x2207, "Fuzhou Rockchip Electronics Company" }, + { 0x221a, "ZTEX GmbH" }, { 0x2222, "MacAlly" }, + { 0x2226, "Copper Mountain technologies" }, { 0x2227, "SAMWOO Enterprise" }, + { 0x222a, "ILI Technology Corp." }, + { 0x2230, "Plugable" }, { 0x2232, "Silicon Motion" }, { 0x2233, "RadioShack Corporation" }, { 0x2237, "Kobo Inc." }, + { 0x2245, "Aspeed Technology, Inc." }, + { 0x224f, "APDM" }, + { 0x2256, "Faderfox" }, { 0x225d, "Morpho" }, + { 0x226e, "DISPLAX" }, { 0x228d, "8D Technologies inc." }, + { 0x22a4, "VERZO Technology" }, { 0x22a6, "Pie Digital, Inc." }, + { 0x22a7, "Fortinet Technologies" }, + { 0x22b1, "Secret Labs LLC" }, { 0x22b8, "Motorola PCS" }, { 0x22b9, "eTurboTouch Technology, Inc." }, { 0x22ba, "Technology Innovation Holdings, Ltd" }, + { 0x22c9, "StepOver GmbH" }, + { 0x22cd, "Kinova Robotics Inc." }, + { 0x22d4, "Laview Technology" }, + { 0x22d9, "OPPO Electronics Corp." }, + { 0x22db, "Phase One" }, + { 0x22dc, "Mellanox Technologies" }, + { 0x22de, "WeTelecom Incorporated" }, + { 0x22df, "Medicom MTD, Ltd" }, + { 0x22e0, "secunet Security Networks AG" }, + { 0x22e8, "Cambridge Audio" }, { 0x2304, "Pinnacle Systems, Inc." }, + { 0x2309, "TimeLink Technology Co., Ltd" }, + { 0x230d, "Teracom" }, + { 0x2314, "INQ Mobile" }, { 0x2318, "Shining Technologies, Inc. [hex]" }, + { 0x2319, "Tronsmart" }, + { 0x232b, "Pantum Ltd." }, + { 0x232e, "EA Elektro-Automatik GmbH & Co. KG" }, + { 0x2340, "Teleepoch" }, { 0x2341, "Arduino SA" }, + { 0x2349, "P2 Engineering Group, LLC" }, + { 0x234b, "Free Software Initiative of Japan" }, + { 0x2357, "TP-Link" }, + { 0x2366, "Bitmanufaktur GmbH" }, + { 0x2367, "Teenage Engineering" }, + { 0x2368, "Peterson Electro-Musical Products Inc." }, + { 0x236a, "SiBEAM" }, { 0x2373, "Pumatronix Ltda" }, { 0x2375, "Digit@lway, Inc." }, + { 0x2378, "OnLive" }, + { 0x237d, "Cradlepoint" }, + { 0x2386, "Raydium Corporation" }, + { 0x238b, "Hytera Communications" }, + { 0x239a, "Adafruit" }, + { 0x23a0, "BIFIT" }, + { 0x23a6, "Tronical Components GmbH" }, + { 0x23b4, "Dental Wings Inc." }, + { 0x23c7, "Gemini" }, + { 0x23fc, "SesKion GmbH" }, + { 0x2405, "Custom Computer Services, Inc" }, { 0x2406, "SANHO Digital Electronics Co., Ltd." }, + { 0x2420, "IRiver" }, + { 0x242e, "Vossloh-Schwabe Deutschland GmbH" }, + { 0x2433, "ASETEK" }, { 0x2443, "Aessent Technology Ltd" }, + { 0x2457, "Ocean Optics Inc." }, + { 0x2458, "Bluegiga Technologies" }, + { 0x245f, "Chord Electronics Limited" }, + { 0x2464, "Nest" }, + { 0x2466, "Fractal Audio Systems" }, + { 0x2476, "YEI Technology" }, { 0x2478, "Tripp-Lite" }, { 0x248a, "Maxxter" }, { 0x249c, "M2Tech s.r.l." }, + { 0x24a4, "Primare AB" }, + { 0x24ae, "Shenzhen Rapoo Technology Co., Ltd." }, + { 0x24c0, "Chaney Instrument" }, + { 0x24c6, "ThrustMaster, Inc." }, + { 0x24cf, "Lytro, Inc." }, + { 0x24dc, "Aladdin R.D." }, + { 0x24e0, "Yoctopuce Sarl" }, { 0x24e1, "Paratronic" }, + { 0x24e3, "K-Touch" }, + { 0x24ea, "Meva" }, + { 0x24ed, "Zen Group" }, + { 0x24f0, "Metadot" }, + { 0x24ff, "Acroname Inc." }, + { 0x2500, "Ettus Research LLC" }, + { 0x2516, "Cooler Master Co., Ltd." }, + { 0x2520, "ANA-U GmbH" }, + { 0x2527, "Software Bisque" }, + { 0x2537, "Norelsys" }, + { 0x2544, "Energy Micro AS" }, + { 0x2546, "Ravensburger" }, + { 0x2548, "Pulse-Eight" }, + { 0x254e, "SHF Communication Technologies AG" }, + { 0x2554, "ASSA ABLOY AB" }, + { 0x2555, "Basis Science Inc." }, + { 0x255e, "Beijing Bonxeon Technology Co., Ltd." }, + { 0x2560, "e-con Systems" }, + { 0x2563, "ShenZhen ShanWan Technology Co., Ltd." }, + { 0x256b, "Perreaux Industries Ltd" }, + { 0x256f, "3Dconnexion" }, + { 0x2573, "ESI Audiotechnik GmbH" }, + { 0x2574, "AVer Information, Inc." }, + { 0x2575, "Weida Hi-Tech Co., Ltd." }, + { 0x2576, "AFO Co., Ltd." }, + { 0x2578, "Pluscom" }, + { 0x2581, "Plug-up" }, + { 0x258d, "Sequans Communications" }, + { 0x259a, "TriQuint Semiconductor" }, + { 0x25a7, "Areson Technology Corp" }, + { 0x25b5, "FlatFrog" }, + { 0x25bb, "Brunner Elektronik AG" }, + { 0x25bf, "Elegant Invention" }, + { 0x25c4, "ARCAM" }, + { 0x25c6, "Vitus Audio (AVA Group A/S)" }, + { 0x25c8, "Visual Planet Ltd" }, + { 0x25da, "Netatmo" }, + { 0x25dd, "Bit4id Srl" }, + { 0x25e3, "Lumigon" }, + { 0x25f0, "ShanWan" }, + { 0x25fb, "Pentax Ricoh Imaging Co., Ltd" }, + { 0x2604, "Tenda" }, + { 0x2625, "MilDef AB" }, + { 0x2626, "Aruba Networks" }, + { 0x262a, "SAVITECH Corp." }, { 0x2632, "TwinMOS" }, { 0x2639, "Xsens" }, + { 0x264a, "Thermaltake" }, { 0x2650, "Electronics For Imaging, Inc. [hex]" }, { 0x2659, "Sundtek" }, + { 0x2662, "Moog Music Inc." }, + { 0x266e, "Silicon Integrated Systems" }, + { 0x2672, "GoPro" }, { 0x2676, "Basler AG" }, + { 0x2685, "Cardo Peripheral Systems LTD" }, + { 0x2687, "Fitbit Inc." }, + { 0x2689, "StepOver International GmbH" }, + { 0x268b, "Dimension Engineering" }, + { 0x26a9, "Research Industrial Systems Engineering" }, + { 0x26aa, "Yaesu Musen" }, + { 0x26b5, "Electrocompaniet" }, + { 0x26bd, "Integral Memory" }, + { 0x26e2, "Ingenieurbuero Dietzsch und Thiele, PartG" }, + { 0x26f2, "Micromega" }, + { 0x2707, "Bardac Corporation" }, + { 0x270d, "Rosand Technologies" }, + { 0x2717, "Xiaomi Inc." }, + { 0x272a, "StarLeaf Ltd." }, + { 0x272c, "Signum Systems" }, { 0x2730, "Citizen" }, { 0x2735, "DigitalWay" }, { 0x273f, "Hughski Limited" }, + { 0x2756, "Victor Hasselblad AB" }, + { 0x2759, "Philip Morris Products S.A." }, + { 0x2765, "Firstbeat Technologies, Ltd." }, + { 0x2766, "LifeScan" }, { 0x2770, "NHJ, Ltd" }, + { 0x27a8, "Square, Inc." }, { 0x27b8, "ThingM" }, + { 0x27bd, "Codethink Ltd." }, + { 0x27c0, "Cadwell Laboratories, Inc." }, + { 0x27c6, "Shenzhen Goodix Technology Co.,Ltd." }, + { 0x27d4, "Blackstar Amplification Limited" }, + { 0x27dd, "Mindeo" }, + { 0x27f2, "Softnautics LLP" }, + { 0x2803, "StarLine LLC." }, + { 0x2806, "SIMPASS" }, + { 0x2817, "Signal Hound, Inc." }, + { 0x2818, "Codex Digital Limited" }, { 0x2821, "ASUSTek Computer Inc." }, + { 0x2822, "REFLEXdigital" }, + { 0x2833, "Oculus VR, Inc." }, + { 0x2836, "OUYA" }, + { 0x286b, "STANEO SAS" }, + { 0x2886, "Seeed Technology Co., Ltd." }, + { 0x2890, "Teknic, Inc" }, { 0x2899, "Toptronic Industrial Co., Ltd" }, { 0x289b, "Dracal/Raphnet technologies" }, + { 0x289d, "Seek Thermal, Inc." }, + { 0x28bd, "XP-Pen" }, + { 0x28c7, "Ultimaker B.V." }, + { 0x28d4, "Devialet" }, + { 0x28de, "Valve Software" }, + { 0x28e0, "PT. Prasimax Inovasi Teknologi" }, + { 0x28e9, "GDMicroelectronics" }, + { 0x28f3, "Clover Network, Inc." }, + { 0x28f9, "Profitap HQ BV" }, + { 0x290c, "R. Hamilton & Co. Ltd." }, + { 0x2912, "Audioengine" }, + { 0x2916, "Yota Devices" }, { 0x2931, "Jolla Oy" }, + { 0x2939, "Zaber Technologies Inc." }, + { 0x2957, "Obsidian Research Corporation" }, + { 0x2961, "Miselu" }, + { 0x296b, "Xacti Corporation" }, + { 0x2972, "FiiO Electronics Technology" }, + { 0x298d, "Next Biometrics" }, + { 0x29bd, "Silicon Works" }, + { 0x29c1, "Taztag" }, + { 0x29c2, "Lewitt GmbH" }, + { 0x29c3, "Noviga" }, + { 0x29e2, "Huatune Technology (Shanghai) Co., Ltd." }, + { 0x29e7, "Brunel University" }, + { 0x29e8, "4Links Limited" }, + { 0x29ea, "Kinesis Corporation" }, + { 0x29f1, "Canaan Creative Co., Ltd" }, { 0x2a03, "dog hunter AG" }, + { 0x2a0e, "Shenzhen DreamSource Technology Co., Ltd." }, + { 0x2a13, "Grabba International" }, + { 0x2a19, "Numato Systems Pvt. Ltd" }, + { 0x2a1d, "Oxford Nanopore Technologies plc" }, { 0x2a37, "RTD Embedded Technologies, Inc." }, + { 0x2a39, "RME" }, + { 0x2a3c, "Trinamic Motion Control GmbH & Co KG" }, { 0x2a45, "Meizu Corp." }, + { 0x2a47, "Mundo Reader, S.L." }, + { 0x2a4b, "EMULEX Corporation" }, + { 0x2a62, "Flymaster Avionics" }, + { 0x2a6e, "Bare Conductive" }, + { 0x2a70, "OnePlus Technology (Shenzhen) Co., Ltd." }, + { 0x2a88, "DFU Technology Ltd" }, + { 0x2a8d, "Keysight Technologies, Inc." }, + { 0x2ab6, "T+A elektroakustik GmbH & Co KG, Germany" }, + { 0x2ac7, "Ultrahaptics Ltd." }, + { 0x2ad1, "Picotronic GmbH" }, + { 0x2ae5, "Fairphone B.V." }, + { 0x2aec, "Ambiq Micro, Inc." }, + { 0x2af4, "ROLI Ltd." }, + { 0x2b03, "STEREOLABS" }, + { 0x2b0e, "LeEco" }, + { 0x2b23, "Red Hat, Inc." }, { 0x2b24, "KeepKey LLC" }, + { 0x2b3e, "NewAE Technology Inc." }, + { 0x2b4c, "ZUK" }, + { 0x2bc5, "Orbbec 3D Technology International, Inc" }, + { 0x2bcc, "InoTec GmbH Organisationssysteme" }, + { 0x2bd6, "Coroware, Inc." }, + { 0x2bd8, "ROPEX Industrie-Elektronik GmbH" }, { 0x2c02, "Planex Communications" }, { 0x2c1a, "Dolphin Peripherals" }, + { 0x2c23, "Supermicro Computer Incorporated" }, + { 0x2c4e, "Mercucys INC" }, + { 0x2c4f, "Canon Electronic Business Machines Co., Ltd." }, + { 0x2c55, "Magic Leap, Inc." }, + { 0x2c7c, "Quectel Wireless Solutions Co., Ltd." }, + { 0x2c97, "Ledger" }, + { 0x2c99, "Prusa" }, + { 0x2c9c, "Vayyar Imaging Ltd." }, + { 0x2c9d, "Nod Inc" }, + { 0x2ca3, "DJI Technology Co., Ltd." }, + { 0x2cb7, "Fibocom" }, + { 0x2cc0, "Hangzhou Zero Zero Infinity Technology Co., Ltd." }, + { 0x2cc2, "Lautsprecher Teufel GmbH" }, + { 0x2ccf, "Hypersecu" }, + { 0x2cd9, "Cambrionix Ltd" }, + { 0x2cdc, "Sea & Sun Technology GmbH" }, + { 0x2ce5, "InX8 Inc [AKiTiO]" }, + { 0x2cf0, "Nuand LLC" }, + { 0x2d1f, "Wacom Taiwan Information Co. Ltd." }, + { 0x2d25, "Kronegger GmbH." }, + { 0x2d2d, "proxmark.org" }, + { 0x2d37, "Zhuhai Poskey Technology Co.,Ltd" }, + { 0x2d6b, "NetUP Inc." }, + { 0x2d81, "Evollve Inc." }, + { 0x2d84, "Zhuhai Poskey Technology Co.,Ltd" }, + { 0x2dc8, "8BitDo" }, { 0x2dcf, "Dialog Semiconductor" }, + { 0x2def, "Kirale Technologies" }, + { 0x2df2, "LIPS Corporation" }, + { 0x2e04, "HMD Global" }, + { 0x2e0e, "Hatteland Display AS" }, + { 0x2e24, "Hyperkin" }, + { 0x2e3b, "uSens Inc." }, + { 0x2e57, "MEGWARE Computer Vertrieb und Service GmbH" }, + { 0x2e69, "Swift Navigation" }, + { 0x2e95, "SCUF Gaming" }, + { 0x2ecc, "ASR Microelectronics" }, + { 0x2f76, "KeyXentic Inc." }, + { 0x2fad, "Definium Technologies" }, + { 0x2fb0, "Infocrypt" }, { 0x2fb2, "Fujitsu, Ltd" }, + { 0x2fc0, "Sensidyne, LP" }, + { 0x2fc6, "Comtrue Inc." }, + { 0x2fe0, "Xaptum, Inc." }, + { 0x2fe3, "NordicSemiconductor" }, + { 0x2fe7, "ELGIN S.A." }, + { 0x2feb, "Beijing Veikk E-Commerce Co., Ltd." }, + { 0x2ff4, "Quixant Plc" }, + { 0x3016, "Boundary Devices, LLC" }, + { 0x3036, "Control iD" }, + { 0x3037, "Beijing Chushifengmang Technology Development Co.,Ltd." }, + { 0x3057, "Kingsis Corporation" }, + { 0x308f, "Input Club" }, + { 0x30a4, "Blues Wireless" }, + { 0x30c2, "UNPARALLEL Innovation, Lda" }, + { 0x30c9, "Luxvisions Innotech Limited" }, + { 0x30ee, "Fujitsu Connected Technologies Limited" }, + { 0x30f2, "Varex Imaging" }, + { 0x3111, "Hiperscan GmbH" }, + { 0x3112, "Meteca SA" }, { 0x3125, "Eagletron" }, { 0x3136, "Navini Networks" }, + { 0x3145, "SafeLogic Inc." }, + { 0x3147, "Tanvas, Inc." }, + { 0x316c, "SigmaSense, LLC" }, + { 0x316d, "Purism, SPC" }, + { 0x316e, "SPECINFOSYSTEMS" }, + { 0x3171, "8086 Consultancy" }, { 0x3176, "Whanam Electronics Co., Ltd" }, { 0x3195, "Link Instruments" }, + { 0x3197, "Katusha" }, + { 0x31c9, "BeiJing LanXum Computer Technology Co., Ltd." }, + { 0x3200, "Alcatel-Lucent Enterprise" }, + { 0x3219, "Smak Tecnologia e Automacao LTDA" }, + { 0x321c, "Premio, Inc." }, + { 0x324c, "CUPRIS Ltd." }, + { 0x326d, "Agile Display Solutions Co., Ltd" }, { 0x3275, "VidzMedia Pte Ltd" }, + { 0x3293, "Unhuman Inc." }, + { 0x32b3, "TEXA" }, + { 0x3310, "MUDITA Sp. z o.o." }, { 0x3333, "InLine" }, { 0x3334, "AEI" }, { 0x3340, "Yakumo" }, { 0x3344, "Leaguer Microelectronics (LME)" }, + { 0x3384, "System76" }, + { 0x348f, "ISY" }, { 0x3504, "Micro Star" }, { 0x3538, "Power Quotient International Co., Ltd" }, { 0x3579, "DIVA" }, { 0x357d, "Sharkoon" }, { 0x3636, "InVibro" }, + { 0x3767, "Fanatec" }, { 0x3838, "WEM" }, { 0x3923, "National Instruments Corp." }, { 0x40bb, "I-O Data" }, @@ -2915,6 +3341,7 @@ static struct vendor_name usb_vendor[] = { { 0x4572, "Shuttle, Inc." }, { 0x4586, "Panram" }, { 0x4670, "EMS Production" }, + { 0x46f4, "QEMU" }, { 0x4752, "Miditech" }, { 0x4757, "GW Instek" }, { 0x4766, "Aceeca" }, @@ -2922,12 +3349,14 @@ static struct vendor_name usb_vendor[] = { { 0x4971, "SimpleTech" }, { 0x4d46, "Musical Fidelity" }, { 0x5032, "Grandtec" }, - { 0x5041, "Linksys (?)" }, { 0x50c2, "Averatec (?)" }, + { 0x5131, "MSR" }, { 0x5173, "Sweex" }, { 0x5219, "I-Tetra" }, + { 0x5332, "Clearly Superior Technologies, Inc." }, { 0x5345, "Owon" }, { 0x534c, "SatoshiLabs" }, + { 0x534d, "MacroSilicon" }, { 0x5354, "Meyer Instruments (MIS)" }, { 0x544d, "Transmeta Corp." }, { 0x5543, "UC-Logic Technology Corp." }, @@ -2936,71 +3365,95 @@ static struct vendor_name usb_vendor[] = { { 0x5654, "Gotview" }, { 0x5656, "Uni-Trend Group Limited" }, { 0x595a, "IRTOUCHSYSTEMS Co. Ltd." }, - { 0x5986, "Acer, Inc" }, + { 0x5986, "Bison Electronics Inc." }, { 0x59e3, "Nonolith Labs" }, { 0x5a57, "Zinwell" }, { 0x6000, "Beholder International Ltd." }, { 0x601a, "Ingenic Semiconductor Ltd." }, + { 0x6022, "Xektek" }, { 0x6189, "Sitecom" }, { 0x6244, "LightingSoft AG" }, { 0x6253, "TwinHan Technology Co., Ltd" }, { 0x636c, "CoreLogic, Inc." }, - { 0x6472, "Unknown (Sony?)" }, + { 0x6472, "Sony Corp." }, { 0x6547, "Arkmicro Technologies Inc." }, + { 0x6557, "Emtec" }, { 0x6615, "IRTOUCHSYSTEMS Co. Ltd." }, { 0x6666, "Prototype product Vendor ID" }, { 0x6677, "WiseGroup, Ltd." }, + { 0x675d, "Humanscale" }, { 0x6891, "3Com" }, { 0x695c, "Opera1" }, { 0x6993, "Yealink Network Technology Co., Ltd." }, { 0x6a75, "Shanghai Jujo Electronics Co., Ltd" }, { 0x7104, "CME (Central Music Co.)" }, { 0x726c, "StackFoundry LLC" }, + { 0x7302, "Solinftec" }, { 0x734c, "TBS Technologies China" }, { 0x7373, "Beijing STONE Technology Co. Ltd." }, { 0x7392, "Edimax Technology Co., Ltd" }, + { 0x73d8, "Progeny Dental Equipment Specialists" }, + { 0x7669, "Venable Instruments" }, + { 0x7825, "Other World Computing" }, + { 0x8070, "ACCES I/O Products, Inc." }, { 0x8086, "Intel Corp." }, { 0x8087, "Intel Corp." }, { 0x80ee, "VirtualBox" }, { 0x8282, "Keio" }, + { 0x8301, "Hapurs" }, { 0x8341, "EGO Systems, Inc." }, { 0x8564, "Transcend Information, Inc." }, { 0x8644, "Intenso GmbG" }, { 0x8e06, "CH Products, Inc." }, + { 0x8ea3, "Doosl" }, { 0x9016, "Sitecom" }, { 0x9022, "TeVii Technology Ltd." }, { 0x9148, "GeoLab, Ltd" }, + { 0x9516, "Studiologic" }, { 0x9710, "MosChip Semiconductor" }, { 0x9849, "Bestmedia CD Recordable GmbH & Co. KG" }, + { 0x9886, "Astro Gaming" }, { 0x9999, "Odeon" }, { 0x99fa, "Grandtec" }, { 0x9ac4, "J. Westhues" }, { 0x9e88, "Marvell Semiconductor, Inc." }, + { 0xa014, "Insignia (Best Buy)" }, + { 0xa108, "Ingenic Semiconductor Co.,Ltd" }, { 0xa128, "AnMo Electronics Corp. / Dino-Lite (?)" }, { 0xa168, "AnMo Electronics Corporation" }, - { 0xa600, "Asix" }, + { 0xa466, "Haikou Xingong Electronics Co.,Ltd" }, + { 0xa600, "ASIX s.r.o." }, { 0xa727, "3Com" }, + { 0xa88a, "Clas Ohlsson" }, { 0xaaaa, "MXT" }, - { 0xabcd, "Unknown" }, + { 0xab12, "aplic" }, + { 0xabcd, "LogiLink" }, { 0xb58e, "Blue Microphones" }, + { 0xba77, "Clockmaker" }, { 0xc216, "Card Device Expert Co., LTD" }, { 0xc251, "Keil Software, Inc." }, + { 0xc502, "AGPTek" }, { 0xcace, "CACE Technologies Inc." }, { 0xcd12, "SMART TECHNOLOGY INDUSTRIAL LTD." }, { 0xd208, "Ultimarc" }, { 0xd209, "Ultimarc" }, { 0xd904, "LogiLink" }, + { 0xe2b7, "Jie Li" }, { 0xe4e4, "Xorcom Ltd." }, { 0xeb03, "MakingThings" }, { 0xeb1a, "eMPIA Technology, Inc." }, { 0xeb2a, "KWorld" }, { 0xef18, "SMART TECHNOLOGY INDUSTRIAL LTD." }, { 0xf003, "Hewlett Packard" }, + { 0xf007, "Teslong" }, { 0xf182, "Leap Motion" }, + { 0xf3f0, "CCT, Inc" }, { 0xf4ec, "Atten Electronics / Siglent Technologies" }, { 0xf4ed, "Shenzhen Siglent Co., Ltd." }, { 0xf766, "Hama" }, + { 0xfa11, "DyingLight" }, { 0xfc08, "Conrad Electronic SE" }, + { 0xff00, "Power Delivery" }, { 0xffee, "FNK Tech" }, }; diff --git a/libwdi/winusb.inf.in b/libwdi/winusb.inf.in index 662abb33..0c0774eb 100644 --- a/libwdi/winusb.inf.in +++ b/libwdi/winusb.inf.in @@ -1,5 +1,5 @@ ; #INF_FILENAME# -; Copyright (c) 2010-2016 Pete Batard (GNU LGPL) +; Copyright (c) 2010-2023 Pete Batard (GNU LGPL) [Strings] DeviceName = "#DEVICE_DESCRIPTION#" VendorName = "#DEVICE_MANUFACTURER#" @@ -23,7 +23,7 @@ HKR,,,0,"Universal Serial Bus devices" HKR,,Icon,,-20 [Manufacturer] -%VendorName% = libusbDevice_WinUSB,NTx86,NTamd64,NTarm +%VendorName% = libusbDevice_WinUSB,NTx86,NTamd64,NTarm64 [libusbDevice_WinUSB.NTx86] %DeviceName% = USB_Install, USB\%DeviceID% @@ -31,7 +31,7 @@ HKR,,Icon,,-20 [libusbDevice_WinUSB.NTamd64] %DeviceName% = USB_Install, USB\%DeviceID% -[libusbDevice_WinUSB.NTarm] +[libusbDevice_WinUSB.NTarm64] %DeviceName% = USB_Install, USB\%DeviceID% [USB_Install] @@ -64,10 +64,17 @@ AddReg = #USE_DEVICE_INTERFACE_GUID# [AddDeviceInterfaceGUID] HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID% -[USB_Install.CoInstallers] +[USB_Install.NTx86.CoInstallers] AddReg = CoInstallers_AddReg CopyFiles = CoInstallers_CopyFiles +[USB_Install.NTamd64.CoInstallers] +AddReg = CoInstallers_AddReg +CopyFiles = CoInstallers_CopyFiles + +[USB_Install.NTarm64.CoInstallers] +; + [CoInstallers_AddReg] HKR,,CoInstallers32,0x00010000,"WdfCoInstaller#WDF_VERSION#.dll,WdfCoInstaller","WinUSBCoInstaller2.dll" @@ -89,6 +96,5 @@ WdfCoInstaller#WDF_VERSION#.dll = 1,x86 WinUSBCoInstaller2.dll = 1,amd64 WdfCoInstaller#WDF_VERSION#.dll = 1,amd64 -[SourceDisksFiles.arm] -WinUSBCoInstaller2.dll = 1,arm -WdfCoInstaller#WDF_VERSION#.dll = 1,arm +[SourceDisksFiles.arm64] +; \ No newline at end of file diff --git a/msvc/config.h b/msvc/config.h index c97d4995..c44d3779 100644 --- a/msvc/config.h +++ b/msvc/config.h @@ -16,12 +16,14 @@ #endif /* - * Embed WinUSB driver files from the following WDK location + * Embed WinUSB driver files from the following WDK location. + * If needed, you can obtain the WDK redistributable components from: + * https://go.microsoft.com/fwlink/p/?LinkID=253170 * NB: You must also make sure the WDF_VER, COINSTALLER_DIR and X64_DIR - * match your WinUSB redist directrories + * match your WinUSB redist directories. */ #ifndef WDK_DIR -#define WDK_DIR "C:/Program Files (x86)/Windows Kits/10" +#define WDK_DIR "C:/Program Files (x86)/Windows Kits/8.0" #endif /* WDK WDF coinstaller version */ @@ -54,6 +56,9 @@ /* 64 bit support */ #define OPT_M64 +/* ARM64 support */ +#define OPT_ARM + /* Debug message logging */ //#define ENABLE_DEBUG_LOGGING diff --git a/msvc/stdint.h b/msvc/stdint.h index 5d5329a9..e0c8b0c7 100644 --- a/msvc/stdint.h +++ b/msvc/stdint.h @@ -239,7 +239,7 @@ typedef unsigned long long uintmax_t; /* 7.18.4.1 Macros for minimum-width integer constants - Accoding to Douglas Gwyn : + According to Douglas Gwyn : "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC 9899:1999 as initially published, the expansion was required to be an integer constant of precisely matching type, which diff --git a/wdk_build.cmd b/wdk_build.cmd deleted file mode 100644 index 33ea4d8c..00000000 --- a/wdk_build.cmd +++ /dev/null @@ -1,185 +0,0 @@ -@echo off -rem default builds static library. -rem you can pass the following arguments (case insensitive): -rem - "DLL" to build a DLL instead of a static library -rem - "no_samples" to build the library only - -if not Test%DDK_TARGET_OS%==TestWin7 goto unsupported - -if Test%BUILD_ALT_DIR%==Test goto usage -rem /M 2 for multiple cores -set BUILD_CMD=build -bcwgZ -M2 -set PWD=%~dp0 - -rem process commandline parameters -set TARGET=LIBRARY -set BUILD_SAMPLES=YES - -:more_args -if "%1" == "" goto no_more_args -rem /I for case insensitive -if /I Test%1==TestDLL set TARGET=DYNLINK -if /I Test%1==Testno_samples set BUILD_SAMPLES=NO -rem - shift the arguments and examine %1 again -shift -goto more_args -:no_more_args - -rem Set DDK_DIR (=BASEDIR with escaped backslashes) -set DDK_DIR=%BASEDIR:\=\\% -rem Set target platform type -set ORG_BUILD_ALT_DIR=%BUILD_ALT_DIR% -set ORG_BUILDARCH=%_BUILDARCH% -set ORG_PATH=%PATH% -set ORG_BUILD_DEFAULT_TARGETS=%BUILD_DEFAULT_TARGETS% - -set ARCH_DIR=%_BUILDARCH% -if /I Test%_BUILDARCH%==Testx86 set ARCH_DIR=i386 - -if /I Test%_BUILDARCH%==Testamd64 goto x86_64 -echo #define NO_BUILD64> libwdi\build64.h -goto main_start -:x86_64 -echo #define BUILD64> libwdi\build64.h - -:main_start -cd libwdi -set srcPath=obj%BUILD_ALT_DIR%\%cpudir% - -del Makefile.hide >NUL 2>&1 -if EXIST Makefile ren Makefile Makefile.hide - -set 386=1 -set AMD64= -set BUILD_DEFAULT_TARGETS=-386 -set _AMD64bit= -set _BUILDARCH=x86 -set PATH=%BASEDIR%\bin\x86;%BASEDIR%\bin\x86\x86 - -copy .msvc\embedder_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -copy obj%BUILD_ALT_DIR%\i386\embedder.exe . >NUL 2>&1 - -copy .msvc\installer_x86_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -copy obj%BUILD_ALT_DIR%\i386\installer_x86.exe . >NUL 2>&1 - -set 386= -set AMD64=1 -set BUILD_DEFAULT_TARGETS=-amd64 -set _AMD64bit=true -set _BUILDARCH=AMD64 -set PATH=%BASEDIR%\bin\x86\amd64;%BASEDIR%\bin\x86 - -copy .msvc\installer_x64_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -copy obj%BUILD_ALT_DIR%\amd64\installer_x64.exe . >NUL 2>&1 - -if /I Test%ORG_BUILDARCH%==TestAMD64 goto restorePath -set 386=1 -set AMD64= -set BUILD_DEFAULT_TARGETS=-386 -set _AMD64bit= -set _BUILDARCH=x86 - -:restorePath -set PATH=%ORG_PATH% - -echo. -echo Embedding binary resources -embedder.exe embedded.h - -rem DLL or static lib selection (must use concatenation) -echo TARGETTYPE=%TARGET% > target -copy target+.msvc\libwdi_sources sources >NUL 2>&1 -del target -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\libwdi.lib . >NUL 2>&1 -copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\libwdi.dll . >NUL 2>&1 - -if EXIST Makefile.hide ren Makefile.hide Makefile -cd .. -if Test%BUILD_SAMPLES%==TestNO goto done -cd examples\getopt - -del Makefile.hide >NUL 2>&1 -if EXIST Makefile ren Makefile Makefile.hide -copy .msvc\getopt_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\getopt.lib . >NUL 2>&1 - -if EXIST Makefile.hide ren Makefile.hide Makefile -cd .. - -del Makefile.hide >NUL 2>&1 -if EXIST Makefile ren Makefile Makefile.hide -rem Work around MS's VC++ and WDK weird icompatibilities with regards to rc files -echo #include ^ > afxres.h -echo #ifndef IDC_STATIC >> afxres.h -echo #define IDC_STATIC -1 >> afxres.h -echo #endif >> afxres.h -copy .msvc\zadic_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\zadic.exe . >NUL 2>&1 - -copy .msvc\zadig_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -del afxres.h -copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\zadig.exe . >NUL 2>&1 - -copy .msvc\wdi-simple_sources sources >NUL 2>&1 -@echo on -%BUILD_CMD% -@echo off -if errorlevel 1 goto builderror -copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\wdi-simple.exe . >NUL 2>&1 - -if EXIST Makefile.hide ren Makefile.hide Makefile -cd .. - -goto done - -:builderror -if EXIST Makefile.hide ren Makefile.hide Makefile -if EXIST afxres.h del afxres.h -echo Build failed -goto done - -:usage -echo wdk_build must be run in a Windows Driver Kit build environment -pause -goto done - -:done -set BUILD_ALT_DIR=%ORG_BUILD_ALT_DIR% -set _BUILDARCH=%ORG_BUILDARCH% -set PATH=%ORG_PATH% -set BUILD_DEFAULT_TARGETS=%ORG_BUILD_DEFAULT_TARGETS% -cd %PWD% -goto out - -:unsupported -echo Only Windows 7 or later is supported - -:out