From 0ea6a2c4b9f12bc9e133a74ae4deb5cc42dc7113 Mon Sep 17 00:00:00 2001 From: Alexey 'Cluster' Avdyukhin Date: Mon, 30 Jan 2017 13:18:04 +0300 Subject: Added driver installer source code --- driver/nesmini_driver.exe | Bin 5747712 -> 5704192 bytes driver/source/AUTHORS | 16 + driver/source/COPYING | 674 +++++ driver/source/COPYING-LGPL | 165 ++ driver/source/ChangeLog | 96 + driver/source/Makefile.am | 7 + driver/source/NEWS | 1 + driver/source/README.md | 38 + driver/source/_bm.sh | 42 + driver/source/_bump.sh | 65 + driver/source/_chlver.sh | 47 + driver/source/_chzver.sh | 44 + driver/source/_pre-commit.sh | 49 + driver/source/_release.sh | 32 + driver/source/autogen.sh | 28 + driver/source/bootstrap.sh | 19 + driver/source/configure.ac | 359 +++ driver/source/ddk_build.cmd | 188 ++ driver/source/libwdi.sln | 97 + driver/source/libwdi/.msvc/detect_64build.vcxproj | 109 + driver/source/libwdi/.msvc/embedder.vcxproj | 112 + .../source/libwdi/.msvc/embedder.vcxproj.filters | 28 + driver/source/libwdi/.msvc/embedder_sources | 19 + driver/source/libwdi/.msvc/installer_x64.vcxproj | 133 + .../libwdi/.msvc/installer_x64.vcxproj.filters | 26 + driver/source/libwdi/.msvc/installer_x64_sources | 24 + driver/source/libwdi/.msvc/installer_x86.vcxproj | 96 + .../libwdi/.msvc/installer_x86.vcxproj.filters | 26 + driver/source/libwdi/.msvc/installer_x86_sources | 24 + driver/source/libwdi/.msvc/libwdi_dll.vcxproj | 227 ++ .../source/libwdi/.msvc/libwdi_dll.vcxproj.filters | 87 + driver/source/libwdi/.msvc/libwdi_sources | 32 + driver/source/libwdi/.msvc/libwdi_static.vcxproj | 213 ++ .../libwdi/.msvc/libwdi_static.vcxproj.filters | 94 + driver/source/libwdi/Makefile.am | 65 + driver/source/libwdi/embedder.c | 493 ++++ driver/source/libwdi/embedder.h | 67 + driver/source/libwdi/embedder_files.h | 156 + driver/source/libwdi/installer.c | 901 ++++++ driver/source/libwdi/installer.h | 197 ++ driver/source/libwdi/libusb0.cat.in | 8 + driver/source/libwdi/libusb0.inf.in | 148 + driver/source/libwdi/libusbk.cat.in | 9 + driver/source/libwdi/libusbk.inf.in | 153 + driver/source/libwdi/libwdi.c | 1786 ++++++++++++ driver/source/libwdi/libwdi.def | 72 + driver/source/libwdi/libwdi.h | 307 ++ driver/source/libwdi/libwdi.pc.in | 10 + driver/source/libwdi/libwdi.rc | 90 + driver/source/libwdi/libwdi_dlg.c | 423 +++ driver/source/libwdi/libwdi_i.h | 281 ++ driver/source/libwdi/logging.c | 340 +++ driver/source/libwdi/logging.h | 94 + driver/source/libwdi/msapi_utf8.h | 669 +++++ driver/source/libwdi/mssign32.h | 223 ++ driver/source/libwdi/pki.c | 1258 ++++++++ driver/source/libwdi/resource.h | 16 + driver/source/libwdi/stdfn.h | 94 + driver/source/libwdi/tokenizer.c | 256 ++ driver/source/libwdi/tokenizer.h | 46 + driver/source/libwdi/usbser.cat.in | 1 + driver/source/libwdi/usbser.inf.in | 67 + driver/source/libwdi/vid_data.c | 2998 ++++++++++++++++++++ driver/source/libwdi/vid_data.sh | 82 + driver/source/libwdi/winusb.cat.in | 5 + driver/source/libwdi/winusb.inf.in | 94 + driver/source/msvc/config.h | 67 + driver/source/msvc/inttypes.h | 299 ++ driver/source/msvc/stdint.h | 273 ++ driver/source/nesmini_driver/nesmini_driver.cpp | 125 + .../source/nesmini_driver/nesmini_driver.vcxproj | 160 ++ .../nesmini_driver/nesmini_driver.vcxproj.filters | 18 + .../nesmini_driver/nesmini_driver.vcxproj.user | 4 + driver/usb_driver/amd64/WdfCoInstaller01011.dll | Bin 1795952 -> 0 bytes driver/usb_driver/amd64/winusbcoinstaller2.dll | Bin 1002728 -> 0 bytes driver/usb_driver/installer_x64.exe | Bin 107008 -> 0 bytes driver/usb_driver/installer_x86.exe | Bin 92672 -> 0 bytes driver/usb_driver/nesmini.cat | Bin 3886 -> 0 bytes driver/usb_driver/nesmini.inf | Bin 4516 -> 0 bytes driver/usb_driver/x86/WdfCoInstaller01011.dll | Bin 1629040 -> 0 bytes driver/usb_driver/x86/winusbcoinstaller2.dll | Bin 851176 -> 0 bytes 81 files changed, 15572 insertions(+) create mode 100644 driver/source/AUTHORS create mode 100644 driver/source/COPYING create mode 100644 driver/source/COPYING-LGPL create mode 100644 driver/source/ChangeLog create mode 100644 driver/source/Makefile.am create mode 100644 driver/source/NEWS create mode 100644 driver/source/README.md create mode 100644 driver/source/_bm.sh create mode 100644 driver/source/_bump.sh create mode 100644 driver/source/_chlver.sh create mode 100644 driver/source/_chzver.sh create mode 100644 driver/source/_pre-commit.sh create mode 100644 driver/source/_release.sh create mode 100644 driver/source/autogen.sh create mode 100644 driver/source/bootstrap.sh create mode 100644 driver/source/configure.ac create mode 100644 driver/source/ddk_build.cmd create mode 100644 driver/source/libwdi.sln create mode 100644 driver/source/libwdi/.msvc/detect_64build.vcxproj create mode 100644 driver/source/libwdi/.msvc/embedder.vcxproj create mode 100644 driver/source/libwdi/.msvc/embedder.vcxproj.filters create mode 100644 driver/source/libwdi/.msvc/embedder_sources create mode 100644 driver/source/libwdi/.msvc/installer_x64.vcxproj create mode 100644 driver/source/libwdi/.msvc/installer_x64.vcxproj.filters create mode 100644 driver/source/libwdi/.msvc/installer_x64_sources create mode 100644 driver/source/libwdi/.msvc/installer_x86.vcxproj create mode 100644 driver/source/libwdi/.msvc/installer_x86.vcxproj.filters create mode 100644 driver/source/libwdi/.msvc/installer_x86_sources create mode 100644 driver/source/libwdi/.msvc/libwdi_dll.vcxproj create mode 100644 driver/source/libwdi/.msvc/libwdi_dll.vcxproj.filters create mode 100644 driver/source/libwdi/.msvc/libwdi_sources create mode 100644 driver/source/libwdi/.msvc/libwdi_static.vcxproj create mode 100644 driver/source/libwdi/.msvc/libwdi_static.vcxproj.filters create mode 100644 driver/source/libwdi/Makefile.am create mode 100644 driver/source/libwdi/embedder.c create mode 100644 driver/source/libwdi/embedder.h create mode 100644 driver/source/libwdi/embedder_files.h create mode 100644 driver/source/libwdi/installer.c create mode 100644 driver/source/libwdi/installer.h create mode 100644 driver/source/libwdi/libusb0.cat.in create mode 100644 driver/source/libwdi/libusb0.inf.in create mode 100644 driver/source/libwdi/libusbk.cat.in create mode 100644 driver/source/libwdi/libusbk.inf.in create mode 100644 driver/source/libwdi/libwdi.c create mode 100644 driver/source/libwdi/libwdi.def create mode 100644 driver/source/libwdi/libwdi.h create mode 100644 driver/source/libwdi/libwdi.pc.in create mode 100644 driver/source/libwdi/libwdi.rc create mode 100644 driver/source/libwdi/libwdi_dlg.c create mode 100644 driver/source/libwdi/libwdi_i.h create mode 100644 driver/source/libwdi/logging.c create mode 100644 driver/source/libwdi/logging.h create mode 100644 driver/source/libwdi/msapi_utf8.h create mode 100644 driver/source/libwdi/mssign32.h create mode 100644 driver/source/libwdi/pki.c create mode 100644 driver/source/libwdi/resource.h create mode 100644 driver/source/libwdi/stdfn.h create mode 100644 driver/source/libwdi/tokenizer.c create mode 100644 driver/source/libwdi/tokenizer.h create mode 100644 driver/source/libwdi/usbser.cat.in create mode 100644 driver/source/libwdi/usbser.inf.in create mode 100644 driver/source/libwdi/vid_data.c create mode 100644 driver/source/libwdi/vid_data.sh create mode 100644 driver/source/libwdi/winusb.cat.in create mode 100644 driver/source/libwdi/winusb.inf.in create mode 100644 driver/source/msvc/config.h create mode 100644 driver/source/msvc/inttypes.h create mode 100644 driver/source/msvc/stdint.h create mode 100644 driver/source/nesmini_driver/nesmini_driver.cpp create mode 100644 driver/source/nesmini_driver/nesmini_driver.vcxproj create mode 100644 driver/source/nesmini_driver/nesmini_driver.vcxproj.filters create mode 100644 driver/source/nesmini_driver/nesmini_driver.vcxproj.user delete mode 100644 driver/usb_driver/amd64/WdfCoInstaller01011.dll delete mode 100644 driver/usb_driver/amd64/winusbcoinstaller2.dll delete mode 100644 driver/usb_driver/installer_x64.exe delete mode 100644 driver/usb_driver/installer_x86.exe delete mode 100644 driver/usb_driver/nesmini.cat delete mode 100644 driver/usb_driver/nesmini.inf delete mode 100644 driver/usb_driver/x86/WdfCoInstaller01011.dll delete mode 100644 driver/usb_driver/x86/winusbcoinstaller2.dll (limited to 'driver') diff --git a/driver/nesmini_driver.exe b/driver/nesmini_driver.exe index 402117ea..9631fe02 100644 Binary files a/driver/nesmini_driver.exe and b/driver/nesmini_driver.exe differ diff --git a/driver/source/AUTHORS b/driver/source/AUTHORS new file mode 100644 index 00000000..d0e64ad2 --- /dev/null +++ b/driver/source/AUTHORS @@ -0,0 +1,16 @@ +Copyright © 2010-2016 Pete Batard +Copyright © 2010-2011 Travis Robinson + +Other contributors: +Alexander Sashnov +Bob Paddock +JaggedJax +Jerome-PS +Joseph Marshall +Liam Staskawicz +Louie Caulfield +PhracturedBlue +Ryan Pavlik +Uri Lublin +Vitali Lovich +Xiaofan Chen \ No newline at end of file diff --git a/driver/source/COPYING b/driver/source/COPYING new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/driver/source/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/driver/source/COPYING-LGPL b/driver/source/COPYING-LGPL new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/driver/source/COPYING-LGPL @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/driver/source/ChangeLog b/driver/source/ChangeLog new file mode 100644 index 00000000..e9ca1435 --- /dev/null +++ b/driver/source/ChangeLog @@ -0,0 +1,96 @@ +For the latest changes, please visit: + https://github.com/pbatard/libwdi/commits/master + +o v1.2.4 (2014.11.30) + Bugfixes + - fix multiple potential NULL derefs + - fix a Zadig crash when listing devices + Improvements + - upgrade solution files for Visual Studio 2013 Community Edition + - update the list of known Android devices + - add support for AMD USB 3.0 hub driver + - improve error reporting and external DLL handling + +o v1.2.3 (2014.02.05) + Bugfixes + - allow spaces and commas in paths and names used for installation + - don't redefine boolean but use BOOL, so that C++ apps can properly invoke libwdi + Improvements + - add support for additional xHCI controllers (Intel, VIA...) + - add timeout for pending installations in wdi_options_install_driver + - use Google's Device Interface GUID for Android devices + - major improvements to Zadig + +o v1.2.2 (2012.09.19) + Bugfixes: + - more Clang static-analyzer fixes + - WDK/OACR fixes + - other bugfixes + Improvements: + - Add KMDF v1.11 and Windows Kit 8.0 support + - Improved USB 3.0 support + - Improved libusb-win32 driver support with libusb + +o v1.2.1 (2011.11.02) + Bugfixes: + - Clang static-analyzer fixes + - memory leaks in libwdi_create_list() and Zadig + - MSVC project files settings + Improvements: + - updated executable/DLL file properties + +o v1.2.0 (2011.10.14) + Improvements: + - WCID device driver installation support + - libusb-win32 filter driver installation/uninstallation + - Zadig UI redesign and other improvements + - Windows 8 and USB 3.0 support improvements + - removal of cygwin's no longer available '-mno-cygwin' support + +o v1.1.1 (2011.04.13) + Bugfixes: + - autogenerated certificate no longer reports a private key available + Improvements: + - Zadig UI improvements + - wdi-simple now handles certificate related operations + - New NSIS (Nullsoft Scriptable Install System) script sample + - improved INNO Setup script sample + +o v1.1.0 (2011.03.30) + Improvements: + - libsubK support + - autogeneration and self-signing of a .cat file, to prevent further security + prompts during driver installation on Vista and later. + for more information, see http://libwdi-cps.akeo.ie + - disable restore point creation during installation + - Visual Studio 2010 support and overall MS file cleanup + - use of the Kerberos/e2fsprogs parser in Zadig instead of libconfig + +o v1.0.4 (2011.01.22) + Bugfixes: + - improper title for progress bar + - improper detection of updated files for embedder run + Improvements: + - embedding of user files with international characters should be possible + - new wdi_install_trusted_certificate API call, for promptless driver + installation of static signed driver packages + - new wdi_is_file_embedded API call + +o v1.0.3 (2010.10.07) + Bugfixes: + - progress bar text was not being erased properly + Improvements: + - libwdi can now be cross-compiled + - MinGW and MS generated DLLs are interchangeable + - updated inf-wizard libusb-win32 sample to v1.2.2.0 + +o v1.0.2 (2010.09.15) + Bugfixes: + - WinUSB inf file appends libusb0 template + - inf-wizard does not support international characters + Improvements: + - Relative path for extraction dir + - Logging (silent mode) + - New sample (wdi-simple) and setup script example + +o v1.0.1 (2010.09.01) - Initial Release \ No newline at end of file diff --git a/driver/source/Makefile.am b/driver/source/Makefile.am new file mode 100644 index 00000000..186158f9 --- /dev/null +++ b/driver/source/Makefile.am @@ -0,0 +1,7 @@ +AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip +ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = libwdi + +if BUILD_EXAMPLES +SUBDIRS += examples +endif diff --git a/driver/source/NEWS b/driver/source/NEWS new file mode 100644 index 00000000..788c1926 --- /dev/null +++ b/driver/source/NEWS @@ -0,0 +1 @@ +For the latest news, please visit http://libwdi.akeo.ie diff --git a/driver/source/README.md b/driver/source/README.md new file mode 100644 index 00000000..f4b14549 --- /dev/null +++ b/driver/source/README.md @@ -0,0 +1,38 @@ +libwdi: A Windows Driver Installation library for USB devices +============================================================= + +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 installation, including UAC elevation where necessary +* Single library embedding all the required files +* Supports all Windows platform from Windows XP to Windows 10 + +Additional features +------------------- + +* Embedding of WinUSB, libusb0.sys or libusbK.sys, USB Serial (CDC) or your own + USB drivers (eg. WHQL) +* Full locale support with UTF-8 API strings and UTF-16 autogenerated inf files +* 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 + +Installation and Compilation +---------------------------- + +See: https://github.com/pbatard/libwdi/wiki/Install + +API usage +--------- + +See: https://github.com/pbatard/libwdi/wiki/Usage + +FAQ +--- + +See: https://github.com/pbatard/libwdi/wiki/FAQ diff --git a/driver/source/_bm.sh b/driver/source/_bm.sh new file mode 100644 index 00000000..fde30169 --- /dev/null +++ b/driver/source/_bm.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# Create and upload a Zadig release +# !!!THIS SCRIPT IS FOR INTERNAL DEVELOPER USE ONLY!!! + +target_dir=/e/dailies/libwdi + +type -P git &>/dev/null || { echo "Git not found. Aborting." >&2; exit 1; } +type -P sed &>/dev/null || { echo "Set not found. Aborting." >&2; exit 1; } +type -P upx &>/dev/null || { echo "UPX executable not found. Aborting." >&2; exit 1; } + +zadig_version=`sed -n 's/^.*\"FileVersion\", \"\(.*\)\..*\"/\1/p' examples/zadig.rc` +echo Building Zadig v$zadig_version... + +# Build Zadig for XP (KMDF v1.09) +git clean -fdx +./autogen.sh --disable-shared --disable-debug --with-wdfver=1009 + +cd libwdi +make +cd ../examples +make zadig.exe +# For the app icon to show during UAC, the app needs to have SYSTEM access which MinGW may not grant by default +# (NB this only matters for local apps - an app extracted from a 7z will always have SYSTEM access) +# SetACL can be downloaded from http://helgeklein.com/ +type -P SetACL &>/dev/null && { SetACL -on ./zadig.exe -ot file -actn ace -ace "n:S-1-5-18;p:read,read_ex;s:y"; } +upx --lzma zadig.exe +cp zadig.exe $target_dir/zadig_xp_$zadig_version.exe +cd .. + +# Build Zadig for Vista and later (KMDF v1.11) +git clean -fdx +./autogen.sh --disable-shared --disable-debug --with-wdfver=1011 + +cd libwdi +make +cd ../examples +make zadig.exe +type -P SetACL &>/dev/null && { SetACL -on ./zadig.exe -ot file -actn ace -ace "n:S-1-5-18;p:read,read_ex;s:y"; } +upx --lzma zadig.exe +cp zadig.exe $target_dir/zadig_$zadig_version.exe +cmd.exe /k zadig_sign.bat "$target_dir/zadig_xp_$zadig_version.exe" "$target_dir/zadig_$zadig_version.exe" +cd .. diff --git a/driver/source/_bump.sh b/driver/source/_bump.sh new file mode 100644 index 00000000..47e498ac --- /dev/null +++ b/driver/source/_bump.sh @@ -0,0 +1,65 @@ +#!/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} = 'w' ]; then + echo Tag "$TAG" does not start with 'w' - 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 "w$TAGVER" \ No newline at end of file diff --git a/driver/source/_chlver.sh b/driver/source/_chlver.sh new file mode 100644 index 00000000..5ab95919 --- /dev/null +++ b/driver/source/_chlver.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# Changes the version number for the library and non Zadig samples +# !!!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 + echo "you must provide a version number (eg. 1.0.2)" + exit 1 +else + MAJOR=`echo $1 | sed "s/\(.*\)[.].*[.].*/\1/"` + MINOR=`echo $1 | sed "s/.*[.]\(.*\)[.].*/\1/"` + MICRO=`echo $1 | sed "s/.*[.].*[.]\(.*\)/\1/"` +fi +case $MAJOR in *[!0-9]*) + echo "$MAJOR is not a number" + exit 1 +esac +case $MINOR in *[!0-9]*) + echo "$MINOR is not a number" + exit 1 +esac +case $MICRO in *[!0-9]*) + echo "$MICRO is not a number" + exit 1 +esac +echo "changing version to $MAJOR.$MINOR.$MICRO" +sed -i -e "s/^AC_INIT(\[\([^ ]*\)\], \[[^ ]*\]\(.*\)/AC_INIT([\1], [$MAJOR.$MINOR.$MICRO]\2/" configure.ac + +cat > cmd.sed <<\_EOF +s/^[ \t]*FILEVERSION[ \t]*.*,.*,.*,\(.*\)/ FILEVERSION @@MAJOR@@,@@MINOR@@,@@MICRO@@,\1/ +s/^[ \t]*PRODUCTVERSION[ \t]*.*,.*,.*,\(.*\)/ PRODUCTVERSION @@MAJOR@@,@@MINOR@@,@@MICRO@@,\1/ +s/^\([ \t]*\)VALUE[ \t]*"FileVersion",[ \t]*".*\..*\..*\.\(.*\)"/\1VALUE "FileVersion", "@@MAJOR@@.@@MINOR@@.@@MICRO@@.\2"/ +s/^\([ \t]*\)VALUE[ \t]*"ProductVersion",[ \t]*".*\..*\..*\.\(.*\)"/\1VALUE "ProductVersion", "@@MAJOR@@.@@MINOR@@.@@MICRO@@.\2"/ +_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 +rm cmd.sed diff --git a/driver/source/_chzver.sh b/driver/source/_chzver.sh new file mode 100644 index 00000000..e0c2b745 --- /dev/null +++ b/driver/source/_chzver.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Changes the version number for Zadig +# !!!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 + echo "you must provide a version number (eg. 2.2)" + exit 1 +else + MAJOR=`echo $1 | sed "s/\(.*\)[.].*/\1/"` + MINOR=`echo $1 | sed "s/.*[.]\(.*\)/\1/"` +fi +case $MAJOR in *[!0-9]*) + echo "$MAJOR is not a number" + exit 1 +esac +case $MINOR in *[!0-9]*) + echo "$MINOR is not a number" + exit 1 +esac +echo "changing version to $MAJOR.$MINOR" + +cat > cmd.sed <<\_EOF +s/^[ \t]*FILEVERSION[ \t]*.*,.*,\(.*\),\(.*\)/ FILEVERSION @@MAJOR@@,@@MINOR@@,\1,\2/ +s/^[ \t]*PRODUCTVERSION[ \t]*.*,.*,\(.*\),\(.*\)/ PRODUCTVERSION @@MAJOR@@,@@MINOR@@,\1,\2/ +s/^\([ \t]*\)VALUE[ \t]*"FileVersion",[ \t]*".*\..*\.\(.*\)"/\1VALUE "FileVersion", "@@MAJOR@@.@@MINOR@@.\2"/ +s/^\([ \t]*\)VALUE[ \t]*"ProductVersion",[ \t]*".*\..*\.\(.*\)"/\1VALUE "ProductVersion", "@@MAJOR@@.@@MINOR@@.\2"/ +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 + +rm cmd.sed + +# Update VID data while we're at it +cd libwdi +./vid_data.sh +cd .. diff --git a/driver/source/_pre-commit.sh b/driver/source/_pre-commit.sh new file mode 100644 index 00000000..af01de12 --- /dev/null +++ b/driver/source/_pre-commit.sh @@ -0,0 +1,49 @@ +#!/bin/sh +# +# Bumps the nano version according to the number of commits on this branch +# +# To have git run this script on commit, create a "pre-commit" text file in +# .git/hooks/ with the following content: +# #!/bin/sh +# if [ -x ./_pre-commit.sh ]; then +# source ./_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` +# adjust so that we match the github commit count +TAGVER=`expr $VER + 1` +# 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` + rm ./.amend; +fi +echo "setting nano to $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/^\(.*\)"Zadig \(.*\)\..*"\(.*\)/\1"Zadig \2.@@TAGVER@@"\3/ +_EOF + +# First run sed to substitute our variable in the sed command file +sed -i -e "s/@@TAGVER@@/$TAGVER/g" cmd.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 diff --git a/driver/source/_release.sh b/driver/source/_release.sh new file mode 100644 index 00000000..2c65e298 --- /dev/null +++ b/driver/source/_release.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# Create a release archive +# !!!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; } + +VERSION=`sed -n -e "s/^AC_INIT(\[libwdi\], \[\(.*\)\], \[.*\], \[.*\], \[.*/\1/p" configure.ac` +echo "Creating libwdi-$VERSION" + +BASEDIR=/e/dailies/libwdi +TARGET_DIR=$BASEDIR/libwdi-$VERSION +mkdir $TARGET_DIR +git clean -fdx + +(glibtoolize --version) < /dev/null > /dev/null 2>&1 && LIBTOOLIZE=glibtoolize || LIBTOOLIZE=libtoolize +$LIBTOOLIZE --copy --force || exit 1 +sed -e s/\\\\\${\$lt_var+set}/set/g ltmain.sh > ltmain.sh~ +mv ltmain.sh~ ltmain.sh +aclocal || exit 1 +autoheader || exit 1 +autoconf || exit 1 +automake -a -c || exit 1 + +git archive master | tar -x -C $TARGET_DIR +cp -r m4 autom4te.cache $TARGET_DIR +rm -f $TARGET_DIR/*.sh +cp aclocal.m4 compile config.guess config.sub config.h.in configure depcomp INSTALL install-sh ltmain.sh Makefile.in missing $TARGET_DIR +cp libwdi/Makefile.in $TARGET_DIR/libwdi/Makefile.in +cp examples/Makefile.in $TARGET_DIR/examples/Makefile.in +tar -C $BASEDIR -cf $BASEDIR/libwdi-$VERSION.tar libwdi-$VERSION +gzip $BASEDIR/libwdi-$VERSION.tar diff --git a/driver/source/autogen.sh b/driver/source/autogen.sh new file mode 100644 index 00000000..b54141e0 --- /dev/null +++ b/driver/source/autogen.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# rebuilds the Windows def file by exporting all LIBDWI API calls +create_def() +{ + echo "rebuidling 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 + # We need to manually define a whole set of DLL aliases if we want the MS + # DLLs to be usable with dynamically linked MinGW executables. This is + # because it is not possible to avoid the @ decoration from import WINAPI + # calls in MinGW generated objects, and .def based MS generated DLLs don't + # have such a decoration => linking to MS DLL will fail without aliases. + # Currently, the maximum size is 16 and all sizes are multiples of 4 + for i in 4 8 12 16 + do + sed -n -e "s/.*LIBWDI_API.*\([[:blank:]]\)\(wdi.*\)(.*/ \2@$i = \2/p" libwdi/libwdi.c libwdi/vid_data.c libwdi/logging.c >> libwdi/libwdi.def + done + type -P unix2dos &>/dev/null && unix2dos -q libwdi/libwdi.def +} + +set -e + +./bootstrap.sh +./configure --enable-toggable-debug --enable-examples-build --disable-debug --with-ddkdir="C:/Program Files (x86)/Windows Kits/10" --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/driver/source/bootstrap.sh b/driver/source/bootstrap.sh new file mode 100644 index 00000000..8b2b2c00 --- /dev/null +++ b/driver/source/bootstrap.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +set -e + +# use libtoolize if available, otherwise look for glibtoolize (darwin) +if (libtoolize --version) < /dev/null > /dev/null 2>&1; then + LIBTOOLIZE=libtoolize +elif (glibtoolize --version) < /dev/null > /dev/null 2>&1; then + LIBTOOLIZE=glibtoolize +else + echo "libtoolize or glibtoolize was not found! Please install libtool." 1>&2 + exit 1 +fi + +$LIBTOOLIZE --copy --force || exit 1 +aclocal || exit 1 +autoheader || exit 1 +autoconf || exit 1 +automake -a -c || exit 1 diff --git a/driver/source/configure.ac b/driver/source/configure.ac new file mode 100644 index 00000000..6f7b42da --- /dev/null +++ b/driver/source/configure.ac @@ -0,0 +1,359 @@ +AC_INIT([libwdi], [1.2.5], [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]) +# 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_PROG_CC +AC_PROG_LIBTOOL +LT_LANG([Windows Resource]) +AC_C_INLINE +AM_PROG_CC_C_O +AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) + +AC_ARG_WITH([ddkdir], + [AS_HELP_STRING([--with-ddkdir], [embed WinUSB driver files from the following DDK location])], + [DDK_DIR=$withval], + [DDK_DIR=""]) +if test "x$DDK_DIR" != "x"; then + AC_DEFINE_UNQUOTED([DDK_DIR], ["${DDK_DIR}"], [embed WinUSB driver files from the following DDK location]) +fi + +AC_ARG_WITH([wdfver], + [AS_HELP_STRING([--with-wdfver], [WDF/KDMF version to use - either 1011 or 1009. Use 1009 if you need XP compatibility])], + [WDF_VER=$withval], + [WDF_VER=1011]) +AC_DEFINE_UNQUOTED([WDF_VER], [${WDF_VER}], [DDK WDF/KMDF coinstaller version]) + +AC_ARG_WITH([libusb0], + [AS_HELP_STRING([--with-libusb0], [embed libusb0 driver files from the following location])], + [LIBUSB0_DIR=$withval], + [LIBUSB0_DIR=""]) +if test "x$LIBUSB0_DIR" != "x"; then + AC_DEFINE_UNQUOTED([LIBUSB0_DIR], ["${LIBUSB0_DIR}"], [embed libusb0 driver files from the following location]) +fi + +AC_ARG_WITH([libusbk], + [AS_HELP_STRING([--with-libusbk], [embed libusbK driver files from the following location])], + [LIBUSBK_DIR=$withval], + [LIBUSBK_DIR=""]) +if test "x$LIBUSBK_DIR" != "x"; then + AC_DEFINE_UNQUOTED([LIBUSBK_DIR], ["${LIBUSBK_DIR}"], [embed libusbK driver files from the following location]) +fi + +AC_ARG_WITH([userdir], + [AS_HELP_STRING([--with-userdir], [embed user defined driver files from the following location])], + [USER_DIR=$withval], + [USER_DIR=""]) +if test "x$USER_DIR" != "x"; then + AC_DEFINE_UNQUOTED([USER_DIR], ["${USER_DIR}"], [embed user defined driver files from the following location]) +fi + +if test "x$USER_DIR" == "x" -a "x$DDK_DIR" == "x" -a "x$LIBUSB0_DIR" == "x" -a "x$LIBUSBK_DIR" == "x"; then + AC_MSG_ERROR([One of --with-ddkdir, --with-libusb0, --with-libusbk or --with-userdir options MUST be provided.]) +fi + +AC_MSG_CHECKING([development environment]) +case $host in +*-mingw*) + AC_MSG_RESULT([MinGW]) + create_import_lib="yes" + LIBCONFIG_LIBADD="" + LIBCONFIG_CFLAGS="" + AM_CFLAGS="-Wshadow" + AM_LDFLAGS="-Wl,--add-stdcall-alias" + ;; +*) + AC_MSG_ERROR([unsupported development environment]) +esac + +AM_CFLAGS="${AM_CFLAGS} -DWINVER=0x500 -D_WIN32_IE=0x500" +AM_LDFLAGS="${AM_LDFLAGS} -no-undefined -avoid-version" +AM_CONDITIONAL([CREATE_IMPORT_LIB], [test "x$create_import_lib" = "xyes"]) + +# cross compiling support +if test "x$CC_FOR_BUILD" == "x"; then + if test "x$cross_compiling" == "xyes"; then + AC_CHECK_PROGS([CC_FOR_BUILD], [gcc], [cc]) + else + CC_FOR_BUILD="$CC" + fi +fi +AC_SUBST([CC_FOR_BUILD]) + +# detect if the host's CC_FOR_BUILD actually produces executables that run +# (this is required for the embedder) +saved_CC="${CC}" +saved_CFLAGS="${CFLAGS}" +saved_LDFLAGS="${LDFLAGS}" +# we need to disable cross compiling detection for this test +saved_cross_compiling=$cross_compiling +cross_compiling=no +CC="${CC_FOR_BUILD}" +CFLAGS="" +LDFLAGS="" +AC_MSG_CHECKING([whether the build compiler can produce executables that run on this host]) +AC_RUN_IFELSE([AC_LANG_PROGRAM([])], + [AC_MSG_RESULT([yes]) + cc_for_build_ok="yes"], + [AC_MSG_RESULT([no]) + cc_for_build_ok="no"]) +CC="${saved_CC}" +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 + 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"]) +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]) +if test "x$compiler_has_m32" == "xyes"; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +CFLAGS="${saved_CFLAGS}" + +# 64 bit support +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]) +if test "x$compiler_has_m64" == "xyes"; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +CFLAGS="${saved_CFLAGS}" + +if test "x$compiler_has_m64" != "xyes" -a "x$compiler_has_m32" != "xyes"; then + AC_MSG_ERROR([neither -m32 nor -m64 is supported by your compiler]) +fi + +# 32 and 64 bit selection +AC_ARG_ENABLE([32bit], [AS_HELP_STRING([--enable-32bit], + [build 32 bit compatible library (default y)])], + [enable_32bit=$enableval], + [enable_32bit='yes']) +AC_ARG_ENABLE([64bit], [AS_HELP_STRING([--enable-64bit], + [build 64 bit compatible library (default y)])], + [enable_64bit='$enableval'], + [enable_64bit='yes']) +AC_ARG_ENABLE([ia64], [AS_HELP_STRING([--enable-ia64], + [embed IA64/Itanium driver files (default n)])], + [enable_ia64='$enableval'], + [enable_ia64='no']) +if test "x$enable_64bit" == "xno" -a "x$enable_32bit" == "xno"; then + AC_MSG_ERROR([you cannot disable both 32 and 64 bit support]) +fi + +# OK, let's make some sense of all this 32/64 bit mess... +if test "x$enable_64bit" != "xno" -a "x$compiler_has_m64" == "xno"; then + if test "x$enable_32bit" == "xno"; then + AC_MSG_ERROR([compiler cannot produce 64 bit binaries, and 32 bit support is disabled]) + fi + AC_MSG_WARN([compiler cannot produce 64 bit binaries - disabling 64 bit support]) + enable_64bit="no" +fi + +if test "x$enable_32bit" != "xno" -a "x$compiler_has_m32" == "xno"; then + if test "x$enable_64bit" == "xno"; then + AC_MSG_ERROR([compiler cannot produce 32 bit binaries, and 64 bit support is disabled]) + fi + AC_MSG_WARN([compiler cannot produce 32 bit binaries - disabling 32 bit support]) + enable_32bit="no" +fi + +# define the automake and config.h variables +if test "x$enable_32bit" != "xno"; then + AC_DEFINE([OPT_M32], [], [32 bit support]) + AC_SUBST([OPT_M32]) +fi +AM_CONDITIONAL([OPT_M32], [test "x$enable_32bit" != "xno"]) +if test "x$enable_64bit" != "xno"; then + AC_DEFINE([OPT_M64], [], [64 bit support]) + AC_SUBST([OPT_M64]) +fi +AM_CONDITIONAL([OPT_M64], [test "x$enable_64bit" != "xno"]) +if test "x$enable_ia64" != "xno"; then + AC_DEFINE([OPT_IA64], [], [embed IA64 driver files]) + AC_SUBST([OPT_IA64]) +fi + +if test "x$enable_64bit" != "xno"; then + # the default is to produce 32 bit, when both 64 and 32 bit support are available + if test "x$enable_32bit" != "xno"; then + AC_MSG_NOTICE([will produce 32 bit library and samples, compatible with 64 bit platforms]) + AC_MSG_NOTICE([if you want to produce 64 bit only library and samples, use --disable-32bit]) + ARCH_CFLAGS="-m32" + ARCH_RCFLAGS="--target=pe-i386" + + else + AC_MSG_WARN([will produce a 64 bit library that is INCOMPATIBLE with 32 bit platforms]) + ARCH_CFLAGS="-m64 -D_WIN64" + ARCH_RCFLAGS="" + fi +else + AC_MSG_WARN([will produce a 32 bit library that is INCOMPATIBLE with 64 bit platforms]) + ARCH_CFLAGS="" + ARCH_RCFLAGS="" + +fi +AC_SUBST([ARCH_CFLAGS]) +AC_SUBST([ARCH_RCFLAGS]) + +# AC_CHECK_FILES only works when not cross compiling +if test "$cross_compiling" != "yes" +then + if test "x$DDK_DIR" != "x"; then + # check that the required WinUSB DDK files are available + AC_CHECK_FILES([$DDK_DIR/redist/winusb/], [COINSTALLER_DIR="winusb"], [COINSTALLER_DIR="wdf"]) + AC_DEFINE_UNQUOTED([COINSTALLER_DIR], ["${COINSTALLER_DIR}"], [CoInstaller subdirectory for WinUSB redist files ("winusb" or "wdf")]) + AC_SUBST([COINSTALLER_DIR]) + if test "x$enable_64bit" != "xno"; then + AC_CHECK_FILES([$DDK_DIR/redist/wdf/x64/], [X64_DIR="x64"], [X64_DIR="amd64"]) + AC_DEFINE_UNQUOTED([X64_DIR], ["${X64_DIR}"], [64bit subdirectory for WinUSB redist files ("x64" or "amd64")]) + AC_SUBST([X64_DIR]) + AC_CHECK_FILES([$DDK_DIR/redist/wdf/${X64_DIR}/WdfCoInstaller0${WDF_VER}.dll $DDK_DIR/redist/${COINSTALLER_DIR}/${X64_DIR}/winusbcoinstaller2.dll], [], + [AC_MSG_ERROR([the WinUSB x64 driver files could not be detected (--with-ddkdir)])]) + fi + if test "x$enable_32bit" != "xno"; then + AC_CHECK_FILES([$DDK_DIR/redist/wdf/x86/WdfCoInstaller0${WDF_VER}.dll $DDK_DIR/redist/${COINSTALLER_DIR}/x86/winusbcoinstaller2.dll], [], + [AC_MSG_ERROR([the WinUSB x86 driver files could not be detected (--with-ddkdir)])]) + fi + if test "x$enable_ia64" != "xno"; then + AC_CHECK_FILES([$DDK_DIR/redist/wdf/ia64/WdfCoInstaller0${WDF_VER}.dll $DDK_DIR/redist/${COINSTALLER_DIR}/ia64/winusbcoinstaller2.dll], [], + [AC_MSG_ERROR([the WinUSB ia64 driver files could not be detected (--with-ddkdir)])]) + fi + case "$DDK_DIR" in + [[\\/]]*|?:[[\\/]]*) ;; + *) AC_DEFINE_UNQUOTED([DDK_DIR], "../$DDK_DIR");; + esac + fi + + if test "x$LIBUSB0_DIR" != "x"; then + # check that the required libusb0 driver files are available + AC_CHECK_FILES([$LIBUSB0_DIR/bin/x86/libusb0.sys $LIBUSB0_DIR/bin/x86/libusb0_x86.dll],, + [AC_MSG_ERROR([the libusb0 x86 driver files could not be detected (--with-libusb0)])]) + if test "x$enable_64bit" != "xno"; then + AC_CHECK_FILES([$LIBUSB0_DIR/bin/amd64/libusb0.sys $LIBUSB0_DIR/bin/amd64/libusb0.dll],, + [AC_MSG_ERROR([the libusb0 amd64 driver files could not be detected (--with-libusb0)])]) + fi + if test "x$enable_ia64" != "xno"; then + AC_CHECK_FILES([$LIBUSB0_DIR/bin/ia64/libusb0.sys $LIBUSB0_DIR/bin/ia64/libusb0.dll],, + [AC_MSG_ERROR([the libusb0 ia64 driver files could not be detected (--with-libusb0)])]) + fi + case "$LIBUSB0_DIR" in + [[\\/]]*|?:[[\\/]]*) ;; + *) AC_DEFINE_UNQUOTED([LIBUSB0_DIR], "../$LIBUSB0_DIR");; + esac + fi + + if test "x$LIBUSBK_DIR" != "x"; then + # check that the required libusbK driver files are available + AC_CHECK_FILES([$LIBUSBK_DIR/sys/x86/libusbK.sys $LIBUSBK_DIR/dll/x86/libusbK.dll $LIBUSBK_DIR/dll/x86/libusb0.dll],, + [AC_MSG_ERROR([the libusbK x86 driver files could not be detected (--with-libusbk)])]) + if test "x$enable_64bit" != "xno"; then + AC_CHECK_FILES([$LIBUSBK_DIR/sys/amd64/libusbK.sys $LIBUSBK_DIR/dll/amd64/libusbK.dll $LIBUSBK_DIR/dll/amd64/libusb0.dll],, + [AC_MSG_ERROR([the libusbK amd64 driver files could not be detected (--with-libusbk)])]) + fi + if test "x$enable_ia64" != "xno"; then + AC_CHECK_FILES([$LIBUSBK_DIR/sys/ia64/libusbK.sys $LIBUSBK_DIR/dll/ia64/libusbK.dll $LIBUSBK_DIR/dll/ia64/libusb0.dll],, + [AC_MSG_ERROR([the libusbK ia64 driver files could not be detected (--with-libusbk)])]) + fi + case "$LIBUSBK_DIR" in + [[\\/]]*|?:[[\\/]]*) ;; + *) AC_DEFINE_UNQUOTED([LIBUSBK_DIR], "../$LIBUSBK_DIR");; + esac + fi + + if test "x$USER_DIR" != "x"; then + AC_CHECK_FILE([$USER_DIR],,[AC_MSG_ERROR([the custom driver directory could not be detected (--with-userdir)])]) + case "$USER_DIR" in + [[\\/]]*|?:[[\\/]]*) ;; + *) AC_DEFINE_UNQUOTED([USER_DIR], "../$USER_DIR");; + esac + fi +fi + +# Message logging +AC_ARG_ENABLE([log], [AS_HELP_STRING([--enable-log], [enable logging (default y)])], + [log_enabled=$enableval], + [log_enabled='yes']) +if test "x$log_enabled" != "xno"; then + AC_DEFINE([ENABLE_LOGGING], [1], [Message logging]) +fi + +AC_ARG_ENABLE([debug-log], [AS_HELP_STRING([--enable-debug-log], + [force debug logging always (default n)])], + [debug_log_enabled=$enableval], + [debug_log_enabled='no']) + +AC_ARG_ENABLE([toggable-debug], [AS_HELP_STRING([--enable-toggable-debug], + [enable switchable debug logging (default n)])], + [toggable_debug=$enableval], + [toggable_debug='no']) + +if test "x$debug_log_enabled" != "xno"; then + AC_DEFINE([ENABLE_DEBUG_LOGGING], [1], [Debug message logging (forced)]) +else + if test "x$toggable_debug" != "xno"; then + AC_DEFINE([INCLUDE_DEBUG_LOGGING], [1], [Debug message logging (toggable)]) + fi +fi + +# --enable-debug : check whether they want to have debug symbols: +AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [include debug symbols for gdb (default y)]), + [debug_enabled=$enableval], + [debug_enabled='yes']) +if test "x$debug_enabled" = "xyes" ; then + CFLAGS="-g -O2" +else + CFLAGS="-Os" +fi + +# Examples build +AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build], + [build example applications (default n)])], + [build_examples=$enableval], + [build_examples='no']) +AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"]) + +# check for -Wno-pointer-sign compiler support (GCC >= 4) +saved_CFLAGS="${CFLAGS}" +CFLAGS="$CFLAGS -Wno-pointer-sign" +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], + [nopointersign_cflags="-Wno-pointer-sign"], [nopointersign_cflags=""]) +CFLAGS="${saved_CFLAGS}" + +AM_CFLAGS="$AM_CFLAGS -std=gnu99 -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow" + +AC_SUBST([VISIBILITY_CFLAGS]) +AC_SUBST([AM_CFLAGS]) +AC_SUBST([AM_LDFLAGS]) +AC_SUBST([LIBCONFIG_CFLAGS]) +AC_SUBST([LIBCONFIG_LIBADD]) + +AC_CONFIG_FILES([ +Makefile +libwdi/Makefile +libwdi/libwdi.pc +examples/Makefile +]) +AC_OUTPUT diff --git a/driver/source/ddk_build.cmd b/driver/source/ddk_build.cmd new file mode 100644 index 00000000..d1dff558 --- /dev/null +++ b/driver/source/ddk_build.cmd @@ -0,0 +1,188 @@ +@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 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 DDK 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 ddk_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% + +if Test%DDK_TARGET_OS%==TestWinXP goto nowarn + +echo. +echo. +echo WARNING: You do not seem to use the Windows XP DDK build environment. +echo Be mindful that using the Windows Vista or Windows 7 DDK build environments +echo will result in library and applications that do NOT run on Windows XP. +echo. + +:nowarn +cd %PWD% diff --git a/driver/source/libwdi.sln b/driver/source/libwdi.sln new file mode 100644 index 00000000..fd6e7864 --- /dev/null +++ b/driver/source/libwdi.sln @@ -0,0 +1,97 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwdi (static)", "libwdi\.msvc\libwdi_static.vcxproj", "{9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "embedder", "libwdi\.msvc\embedder.vcxproj", "{792D44D5-28A7-4EB3-B84B-8021FE3189F9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwdi (dll)", "libwdi\.msvc\libwdi_dll.vcxproj", "{79275348-41A4-4D07-8990-4068C9594A2C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "installer_x86", "libwdi\.msvc\installer_x86.vcxproj", "{9B1C561E-F95B-4849-A7AA-A4350E227C20}" +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}") = "detect_64build", "libwdi\.msvc\detect_64build.vcxproj", "{5FAEF8F7-C809-4A68-862F-F8BC6E775B61}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nesmini_driver", "nesmini_driver\nesmini_driver.vcxproj", "{CEB55682-D761-4F72-9345-D0DB436048E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|Win32.ActiveCfg = Debug|Win32 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|Win32.Build.0 = Debug|Win32 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|x64.ActiveCfg = Debug|x64 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Debug|x64.Build.0 = Debug|x64 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|Any CPU.ActiveCfg = Release|Win32 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|Win32.ActiveCfg = Release|Win32 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|Win32.Build.0 = Release|Win32 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|x64.ActiveCfg = Release|x64 + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}.Release|x64.Build.0 = Release|x64 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Debug|Win32.ActiveCfg = Debug|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Debug|Win32.Build.0 = Debug|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Debug|x64.ActiveCfg = Debug|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Debug|x64.Build.0 = Debug|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Release|Any CPU.ActiveCfg = Release|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Release|Win32.ActiveCfg = Release|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Release|Win32.Build.0 = Release|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Release|x64.ActiveCfg = Release|Win32 + {792D44D5-28A7-4EB3-B84B-8021FE3189F9}.Release|x64.Build.0 = Release|Win32 + {79275348-41A4-4D07-8990-4068C9594A2C}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {79275348-41A4-4D07-8990-4068C9594A2C}.Debug|Win32.ActiveCfg = Debug|Win32 + {79275348-41A4-4D07-8990-4068C9594A2C}.Debug|x64.ActiveCfg = Debug|x64 + {79275348-41A4-4D07-8990-4068C9594A2C}.Release|Any CPU.ActiveCfg = Release|Win32 + {79275348-41A4-4D07-8990-4068C9594A2C}.Release|Win32.ActiveCfg = Release|Win32 + {79275348-41A4-4D07-8990-4068C9594A2C}.Release|x64.ActiveCfg = Release|x64 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Debug|Win32.ActiveCfg = Debug|Win32 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Debug|Win32.Build.0 = Debug|Win32 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Debug|x64.ActiveCfg = Debug|Win32 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Release|Any CPU.ActiveCfg = Release|Win32 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Release|Win32.ActiveCfg = Release|Win32 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Release|Win32.Build.0 = Release|Win32 + {9B1C561E-F95B-4849-A7AA-A4350E227C20}.Release|x64.ActiveCfg = Release|Win32 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Debug|Win32.ActiveCfg = Debug|x64 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Debug|Win32.Build.0 = Debug|x64 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Debug|x64.ActiveCfg = Debug|x64 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Debug|x64.Build.0 = Debug|x64 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Release|Any CPU.ActiveCfg = Release|Win32 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}.Release|Win32.ActiveCfg = Release|x64 + {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 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Debug|Win32.ActiveCfg = Debug|Win32 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Debug|Win32.Build.0 = Debug|Win32 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Debug|x64.ActiveCfg = Debug|x64 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Debug|x64.Build.0 = Debug|x64 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Release|Any CPU.ActiveCfg = Release|Win32 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Release|Win32.ActiveCfg = Release|Win32 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Release|Win32.Build.0 = Release|Win32 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Release|x64.ActiveCfg = Release|x64 + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61}.Release|x64.Build.0 = Release|x64 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Debug|Win32.Build.0 = Debug|Win32 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Debug|x64.ActiveCfg = Debug|x64 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Debug|x64.Build.0 = Debug|x64 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Release|Any CPU.ActiveCfg = Release|Win32 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Release|Win32.ActiveCfg = Release|Win32 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Release|Win32.Build.0 = Release|Win32 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Release|x64.ActiveCfg = Release|x64 + {CEB55682-D761-4F72-9345-D0DB436048E9}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/driver/source/libwdi/.msvc/detect_64build.vcxproj b/driver/source/libwdi/.msvc/detect_64build.vcxproj new file mode 100644 index 00000000..407667ef --- /dev/null +++ b/driver/source/libwdi/.msvc/detect_64build.vcxproj @@ -0,0 +1,109 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + detect_64build + {5FAEF8F7-C809-4A68-862F-F8BC6E775B61} + detect64build + + + + Utility + Unicode + v140 + + + Utility + Unicode + v140 + + + Utility + Unicode + v140 + + + Utility + Unicode + v140 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(ProjectDir)\..\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\ + $(ProjectDir)\..\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\ + $(ProjectDir)\..\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\ + $(ProjectDir)\..\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\ + + + + detected 32 bit build + echo #define NO_BUILD64> $(ProjectDir)\..\build64.h + + + + + detected 64 bit build + echo #define BUILD64> $(ProjectDir)\..\build64.h + + + X64 + + + + + detected 32 bit build + echo #define NO_BUILD64> $(ProjectDir)\..\build64.h + + + + + detected 64 bit build + echo #define BUILD64> $(ProjectDir)\..\build64.h + + + X64 + + + + + + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/embedder.vcxproj b/driver/source/libwdi/.msvc/embedder.vcxproj new file mode 100644 index 00000000..82cba849 --- /dev/null +++ b/driver/source/libwdi/.msvc/embedder.vcxproj @@ -0,0 +1,112 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + embedder + {792D44D5-28A7-4EB3-B84B-8021FE3189F9} + embedder + Win32Proj + + + + Application + Unicode + true + v140 + + + Application + Unicode + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(ProjectDir)\..\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\$(ProjectName)\ + $(ProjectDir)\..\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\$(ProjectName)\ + + + + $(IntDir)$(ProjectName).htm + + + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Level3 + ProgramDatabase + CompileAsC + + + %(AdditionalLibraryDirectories) + true + $(TargetDir)$(ProjectName).pdb + Console + MachineX86 + + + + + $(IntDir)$(ProjectName).htm + + + MaxSpeed + true + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + CompileAsC + + + %(AdditionalLibraryDirectories) + false + Console + true + true + MachineX86 + + + + + + + + + + + + + {5faef8f7-c809-4a68-862f-f8bc6e775b61} + false + + + + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/embedder.vcxproj.filters b/driver/source/libwdi/.msvc/embedder.vcxproj.filters new file mode 100644 index 00000000..2a51fafd --- /dev/null +++ b/driver/source/libwdi/.msvc/embedder.vcxproj.filters @@ -0,0 +1,28 @@ + + + + + {AF571DD9-AF6B-4F0A-9A9E-D041D12982F7} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {94a3d5a0-4579-4436-9f8f-1c7261f20c77} + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/embedder_sources b/driver/source/libwdi/.msvc/embedder_sources new file mode 100644 index 00000000..d4646a52 --- /dev/null +++ b/driver/source/libwdi/.msvc/embedder_sources @@ -0,0 +1,19 @@ +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/driver/source/libwdi/.msvc/installer_x64.vcxproj b/driver/source/libwdi/.msvc/installer_x64.vcxproj new file mode 100644 index 00000000..bb609f9d --- /dev/null +++ b/driver/source/libwdi/.msvc/installer_x64.vcxproj @@ -0,0 +1,133 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + installer_x64 + {E5A56EE0-182F-470F-8CDC-8C1B7B86EE26} + installerx64 + Win32Proj + + + + Application + v140 + + + Application + v140 + + + Application + Unicode + true + v140 + + + Application + Unicode + v140 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\helper\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x64\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x64\ + + + + X64 + + + Disabled + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS; _WIN64;%(PreprocessorDefinitions) + MultiThreadedDebug + Level3 + ProgramDatabase + CompileAsC + + + newdev.lib;setupapi.lib;%(AdditionalDependencies) + $(OutDir)installer_x64.exe + true + Console + MachineX64 + + + + + X64 + + + MinSpace + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS; _WIN64;%(PreprocessorDefinitions) + MultiThreaded + Level3 + CompileAsC + + + newdev.lib;setupapi.lib;%(AdditionalDependencies) + $(OutDir)installer_x64.exe + false + Console + true + true + MachineX64 + + + + + CompileAsC + + + + + CompileAsC + + + + + + + + + + + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/installer_x64.vcxproj.filters b/driver/source/libwdi/.msvc/installer_x64.vcxproj.filters new file mode 100644 index 00000000..ed5e4e6d --- /dev/null +++ b/driver/source/libwdi/.msvc/installer_x64.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/installer_x64_sources b/driver/source/libwdi/.msvc/installer_x64_sources new file mode 100644 index 00000000..7ff972bb --- /dev/null +++ b/driver/source/libwdi/.msvc/installer_x64_sources @@ -0,0 +1,24 @@ +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/driver/source/libwdi/.msvc/installer_x86.vcxproj b/driver/source/libwdi/.msvc/installer_x86.vcxproj new file mode 100644 index 00000000..1c834044 --- /dev/null +++ b/driver/source/libwdi/.msvc/installer_x86.vcxproj @@ -0,0 +1,96 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + installer_x86 + {9B1C561E-F95B-4849-A7AA-A4350E227C20} + installerx86 + Win32Proj + + + + Application + Unicode + true + v140 + + + Application + Unicode + v140 + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\helper\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x86\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\ + $(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x86\ + + + + Disabled + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreadedDebug + Level3 + ProgramDatabase + CompileAsC + + + newdev.lib;setupapi.lib;%(AdditionalDependencies) + $(OutDir)installer_x86.exe + true + Console + MachineX86 + + + + + MinSpace + ..\..\msvc;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + Level3 + CompileAsC + + + newdev.lib;setupapi.lib;%(AdditionalDependencies) + $(OutDir)installer_x86.exe + false + Console + true + true + MachineX86 + + + + + + + + + + + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/installer_x86.vcxproj.filters b/driver/source/libwdi/.msvc/installer_x86.vcxproj.filters new file mode 100644 index 00000000..ed5e4e6d --- /dev/null +++ b/driver/source/libwdi/.msvc/installer_x86.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/installer_x86_sources b/driver/source/libwdi/.msvc/installer_x86_sources new file mode 100644 index 00000000..c9e41817 --- /dev/null +++ b/driver/source/libwdi/.msvc/installer_x86_sources @@ -0,0 +1,24 @@ +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/driver/source/libwdi/.msvc/libwdi_dll.vcxproj b/driver/source/libwdi/.msvc/libwdi_dll.vcxproj new file mode 100644 index 00000000..c0a178ec --- /dev/null +++ b/driver/source/libwdi/.msvc/libwdi_dll.vcxproj @@ -0,0 +1,227 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + libwdi (dll) + {79275348-41A4-4D07-8990-4068C9594A2C} + libwdi + + + + DynamicLibrary + Unicode + true + v140 + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + v140 + + + DynamicLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\dll\ + $(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\ + $(SolutionDir)$(Platform)\$(Configuration)\dll\ + $(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\ + $(SolutionDir)$(Platform)\$(Configuration)\dll\ + $(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\ + $(SolutionDir)$(Platform)\$(Configuration)\dll\ + $(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\ + libwdi + libwdi + libwdi + libwdi + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + Disabled + ..\..\msvc;%(AdditionalIncludeDirectories) + DEBUG;_DEBUG;_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + false + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + setupapi.lib;newdev.lib;%(AdditionalDependencies) + $(OutDir)libwdi.dll + ../libwdi.def + ../libwdi.rc;%(EmbedManagedResourceFile) + + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + Disabled + ..\..\msvc;%(AdditionalIncludeDirectories) + DEBUG;_DEBUG;_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + false + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + setupapi.lib;newdev.lib;%(AdditionalDependencies) + $(OutDir)libwdi.dll + ../libwdi.def + ../libwdi.rc;%(EmbedManagedResourceFile) + + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + MinSpace + ..\..\msvc;%(AdditionalIncludeDirectories) + _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + false + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + setupapi.lib;newdev.lib;%(AdditionalDependencies) + $(OutDir)libwdi.dll + ../libwdi.def + ../libwdi.rc;%(EmbedManagedResourceFile) + + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + MinSpace + ..\..\msvc;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + false + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + setupapi.lib;newdev.lib;%(AdditionalDependencies) + $(OutDir)libwdi.dll + ../libwdi.def + ../libwdi.rc;%(EmbedManagedResourceFile) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {792d44d5-28a7-4eb3-b84b-8021fe3189f9} + false + + + {e5a56ee0-182f-470f-8cdc-8c1b7b86ee26} + false + + + {9b1c561e-f95b-4849-a7aa-a4350e227c20} + false + + + + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/libwdi_dll.vcxproj.filters b/driver/source/libwdi/.msvc/libwdi_dll.vcxproj.filters new file mode 100644 index 00000000..00efde68 --- /dev/null +++ b/driver/source/libwdi/.msvc/libwdi_dll.vcxproj.filters @@ -0,0 +1,87 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {764477b1-9f30-48f4-b48e-dacb7fd3784f} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/libwdi_sources b/driver/source/libwdi/.msvc/libwdi_sources new file mode 100644 index 00000000..8938310e --- /dev/null +++ b/driver/source/libwdi/.msvc/libwdi_sources @@ -0,0 +1,32 @@ +#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/driver/source/libwdi/.msvc/libwdi_static.vcxproj b/driver/source/libwdi/.msvc/libwdi_static.vcxproj new file mode 100644 index 00000000..223f2e83 --- /dev/null +++ b/driver/source/libwdi/.msvc/libwdi_static.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + libwdi (static) + {9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9} + libwdi + + + + StaticLibrary + Unicode + true + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + StaticLibrary + Unicode + v140 + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Platform)\$(Configuration)\lib\ + $(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\ + $(SolutionDir)$(Platform)\$(Configuration)\lib\ + $(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\ + $(SolutionDir)$(Platform)\$(Configuration)\lib\ + $(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\ + $(SolutionDir)$(Platform)\$(Configuration)\lib\ + $(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\ + libwdi + libwdi + libwdi + libwdi + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + ..\..\msvc;%(AdditionalIncludeDirectories) + DEBUG;_DEBUG;_WIN32;_CRTDBG_MAP_ALLOC;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreadedDebug + Level3 + ProgramDatabase + Disabled + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + $(OutDir)libwdi.lib + + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + ..\..\msvc;%(AdditionalIncludeDirectories) + DEBUG;_DEBUG;_WIN32;_CRTDBG_MAP_ALLOC;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level3 + ProgramDatabase + Disabled + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + $(OutDir)libwdi.lib + + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + MinSpace + ..\..\msvc;%(AdditionalIncludeDirectories) + _WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + Level3 + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + $(OutDir)libwdi.lib + + + + + Embedding binary resources + cd $(ProjectDir)\.. +embedder embedded.h + + + MinSpace + ..\..\msvc;%(AdditionalIncludeDirectories) + _WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + Level3 + CompileAsC + + + E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories) + + + $(OutDir)libwdi.lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {792d44d5-28a7-4eb3-b84b-8021fe3189f9} + false + + + {e5a56ee0-182f-470f-8cdc-8c1b7b86ee26} + false + + + {9b1c561e-f95b-4849-a7aa-a4350e227c20} + false + + + + + + \ No newline at end of file diff --git a/driver/source/libwdi/.msvc/libwdi_static.vcxproj.filters b/driver/source/libwdi/.msvc/libwdi_static.vcxproj.filters new file mode 100644 index 00000000..d5a27566 --- /dev/null +++ b/driver/source/libwdi/.msvc/libwdi_static.vcxproj.filters @@ -0,0 +1,94 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {7da2644f-07cc-43bb-93b9-5ddd8aec3b17} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/driver/source/libwdi/Makefile.am b/driver/source/libwdi/Makefile.am new file mode 100644 index 00000000..404b01c7 --- /dev/null +++ b/driver/source/libwdi/Makefile.am @@ -0,0 +1,65 @@ +all-local: embedded.h libwdi.la +if CREATE_IMPORT_LIB +# Rebuild the import lib from the .def so that MS and MinGW DLLs can be interchanged + @echo " CCLD libwdi.dll.a" + @$(DLLTOOL) $(DLLTOOLFLAGS) --kill-at --input-def libwdi.def --dllname libwdi.dll --output-lib .libs/libwdi.dll.a +endif + +AM_CPPFLAGS = -I$(top_srcdir) + +BUILT_SOURCES = embedded.h +noinst_PROGRAMS = +noinst_EXES = +lib_LTLIBRARIES = libwdi.la +LIB_SRC = resource.h logging.h tokenizer.h installer.h libwdi_i.h mssign32.h logging.c tokenizer.c vid_data.c pki.c libwdi_dlg.c libwdi.c +LIB_HDR = libwdi.h + +if OPT_M32 +noinst_PROGRAMS += installer_x86 +noinst_EXES += installer_x86.exe +installer_x86_SOURCES = installer.h installer.c +installer_x86_CFLAGS = -m32 $(AM_CFLAGS) +installer_x86_LDFLAGS = -m32 $(AM_LDFLAGS) -static +installer_x86_LDADD = -lsetupapi -lnewdev -lole32 +endif + +if OPT_M64 +noinst_PROGRAMS += installer_x64 +noinst_EXES += installer_x64.exe +installer_x64_SOURCES = installer.h installer.c +installer_x64_CFLAGS = -m64 -D_WIN64 $(AM_CFLAGS) +installer_x64_LDFLAGS = -m64 $(AM_LDFLAGS) -static +installer_x64_LDADD = -lsetupapi -lnewdev -lole32 +endif + +pkg_v_rc = $(pkg_v_rc_$(V)) +pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY)) +pkg_v_rc_0 = @echo " RC $@"; +pkg_v_localcc = $(pkg_v_localcc_$(V)) +pkg_v_localcc_ = $(pkg_v_localcc_$(AM_DEFAULT_VERBOSITY)) +pkg_v_localcc_0 = @echo " CCLD $@"; + +# call host's CC to allow for cross compilation +embedder: embedder.h embedder_files.h embedder.c + $(pkg_v_localcc)$(CC_FOR_BUILD) -I.. embedder.c -o $@ + +EXTRA_DIST = $(LIB_SRC) + +libwdi_rc.lo: libwdi.rc + $(pkg_v_rc)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --tag=RC --mode=compile $(RC) $(ARCH_RCFLAGS) -i $< -o $@ + +libwdi_la_CFLAGS = $(ARCH_CFLAGS) $(VISIBILITY_CFLAGS) $(AM_CFLAGS) +libwdi_la_LDLAGS = $(AM_LDFLAGS) +libwdi_la_LIBADD = libwdi_rc.lo -lsetupapi -lole32 +libwdi_la_SOURCES = $(LIB_SRC) +libwdi_la_HEADERS = $(LIB_HDR) +libwdi_ladir = $(includedir) + +embedded.h: embedder $(noinst_PROGRAMS) + @./embedder embedded.h + +clean-local: + -rm -rf embedded.h embedder embedder.exe + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libwdi.pc diff --git a/driver/source/libwdi/embedder.c b/driver/source/libwdi/embedder.c new file mode 100644 index 00000000..78dfd424 --- /dev/null +++ b/driver/source/libwdi/embedder.c @@ -0,0 +1,493 @@ +/* + * 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-2013 Pete Batard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 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 + */ + +/* + * This tool is meant to be call as a pre-built event when compiling the + * installer library, to produce a .h that embeds all the necessary driver + * binary resources. + * + * This is required work around the many limitations of resource files, as + * well as the impossibility to force the MS linker to embed resources always + * with a static library (unless the library is split into .res + .lib) + */ + +#include +#include +#include +#include +#include +#include +#include +#if defined(_WIN32) +#include +#else +#include +#include +#include +#endif + +#include +#include "embedder.h" +#include "embedder_files.h" + +#define safe_free(p) do {if (p != NULL) {free(p); p = NULL;}} while(0) +#define perr(...) fprintf(stderr, "embedder : error: " __VA_ARGS__) + +const int nb_embeddables_fixed = sizeof(embeddable_fixed)/sizeof(struct emb); +int nb_embeddables; +struct emb* embeddable = embeddable_fixed; + +#ifndef MAX_PATH +#ifdef PATH_MAX +#define MAX_PATH PATH_MAX +#else +#define MAX_PATH 260 +#endif +#endif + +#if defined(USER_DIR) +char initial_dir[MAX_PATH]; +#endif + +#if defined(_WIN32) +#define NATIVE_STAT _stat +#define NATIVE_STRDUP _strdup +#define NATIVE_UNLINK _unlink +#define NATIVE_SEPARATOR '\\' +#define NON_NATIVE_SEPARATOR '/' +#else +#define NATIVE_STAT stat +#define NATIVE_STRDUP strdup +#define NATIVE_UNLINK unlink +#define NATIVE_SEPARATOR '/' +#define NON_NATIVE_SEPARATOR '\\' +#endif + +void dump_buffer_hex(FILE* fd, unsigned char *buffer, size_t size) +{ + size_t i; + + // Make sure we output something even if the original file is empty + if (size == 0) { + fprintf(fd, "0x00"); + } + + for (i=0; i sizeof(dir) ) { + perr("Path overflow.\n"); + return; + } + sprintf(dir, "%s%c%s", initial_dir, NATIVE_SEPARATOR, dirname); + + // Get the first file +#if defined(_WIN32) + strcat(dir, "\\*"); + MultiByteToWideChar(CP_UTF8, 0, dir, -1, wdir, MAX_PATH); + hList = FindFirstFileW(wdir, &FileData); + if (hList == INVALID_HANDLE_VALUE) return; +#else + dp = opendir(dir); + if (dp == NULL) return; + dir_entry = readdir(dp); + if (dir_entry == NULL) return; +#endif + + // Traverse through the directory structure + do { + // Check if the object is a directory or not +#if defined(_WIN32) + WideCharToMultiByte(CP_UTF8, 0, FileData.cFileName, -1, entry, MAX_PATH, NULL, NULL); + if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { +#else + entry = dir_entry->d_name; + getcwd(cwd, sizeof(cwd)); + chdir(dir); + r = NATIVE_STAT(entry, &stat_info); + chdir(cwd); + if (r != 0) { + continue; + } + if (S_ISDIR(stat_info.st_mode)) { +#endif + if ( (strcmp(entry, ".") != 0) + && (strcmp(entry, "..") != 0)) { + // Get the full path for sub directory + if ( (strlen(dirname) + strlen(entry) + 2) > sizeof(subdir) ) { + perr("Path overflow.\n"); + return; + } + sprintf(subdir, "%s%c%s", dirname, NATIVE_SEPARATOR, entry); + scan_dir(subdir, countfiles); + } + } else { + if (!countfiles) { + if ( (embeddable[nb_embeddables].file_name = + malloc(strlen(initial_dir) + strlen(dirname) + + strlen(entry) + 2) ) == NULL) { + return; + } + if ( (embeddable[nb_embeddables].extraction_subdir = + malloc(strlen(dirname)) ) == NULL) { + return; + } + sprintf(embeddable[nb_embeddables].file_name, + "%s%s%c%s", initial_dir, dirname, NATIVE_SEPARATOR, entry); + if (dirname[0] == NATIVE_SEPARATOR) { + sprintf(embeddable[nb_embeddables].extraction_subdir, + "%s", dirname+1); + } else { + safe_free(embeddable[nb_embeddables].extraction_subdir); + embeddable[nb_embeddables].extraction_subdir = NATIVE_STRDUP("."); + } + } + nb_embeddables++; + } + } +#if defined(_WIN32) + while ( FindNextFileW(hList, &FileData) || (GetLastError() != ERROR_NO_MORE_FILES) ); + FindClose(hList); +#else + while ((dir_entry = readdir(dp)) != NULL); + closedir(dp); +#endif +} + +void add_user_files(void) { + int i; + + get_full_path(USER_DIR, initial_dir, sizeof(initial_dir)); + // Dry run to count additional files + scan_dir("", -1); + if (nb_embeddables == nb_embeddables_fixed) { + perr("No user embeddable files found.\nNote that the USER_DIR path must be provided in Windows format\n" \ + "(eg: 'C:\\signed-driver'), if compiling from a Windows platform.\n"); + return; + } + + // Extend the array to add the user files + embeddable = calloc(nb_embeddables, sizeof(struct emb)); + if (embeddable == NULL) { + perr("Could not include user embeddable files.\n"); + return; + } + // Copy the fixed part of our table into our new array + for (i=0; i header_time) { + printf("detected change for '%s'\n", fullpath); + rebuild = 1; + break; + } + } + if (!rebuild) { + printf(" resources haven't changed - skipping step\n"); + ret = 0; goto out1; + } + } + + size = sizeof(size_t)*nb_embeddables; + file_size = malloc(size); + if (file_size == NULL) goto out1; + size = sizeof(int64_t)*nb_embeddables; + file_time = malloc(size); + if (file_time == NULL) goto out1; + + header_fd = fopen(argv[1], "w"); + if (header_fd == NULL) { + perr("Could not create file '%s'.\n", argv[1]); + goto out1; + } + fprintf(header_fd, "#pragma once\n"); + + for (i=0; itm_year+1900, ltm->tm_mon+1, ltm->tm_mday); + } else { + printf("\n"); + } + file_time[i] = (int64_t)stbuf.st_ctime; + file_size[i] = (size_t)stbuf.st_size; + + buffer = (unsigned char*) malloc(file_size[i]); + if (buffer == NULL) { + perr("Could not allocate buffer.\n"); + goto out3; + } + + if (fread(buffer, 1, file_size[i], fd) != file_size[i]) { + perr("Could not read file '%s'.\n", fullpath); + goto out4; + } + fclose(fd); + + sprintf(internal_name, "file_%03X", (unsigned char)i); + fprintf(header_fd, "const unsigned char %s[] = {", internal_name); + dump_buffer_hex(header_fd, buffer, file_size[i]); + fprintf(header_fd, "};\n\n"); + safe_free(buffer); + } + fprintf(header_fd, "struct res {\n" \ + "\tchar* subdir;\n" \ + "\tchar* name;\n" \ + "\tsize_t size;\n" \ + "\tint64_t creation_time;\n" \ + "\tconst unsigned char* data;\n" \ + "};\n\n"); + + fprintf(header_fd, "const struct res resource[] = {\n"); + for (last=0,i=0; i + * + * 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 + */ +#pragma once + +#if !defined(OPT_M32) && !defined(OPT_M64) +#error both 32 and 64 bit support have been disabled - check your config.h +#endif + +#if !defined(DDK_DIR) && !defined(LIBUSB0_DIR) && !defined(USER_DIR) && !defined(LIBUSBK_DIR) +#error at least one of DDK_DIR, LIBUSB0_DIR, LIBUSBK_DIR or USER_DIR must be defined - check your config.h +#endif + +// Some adjustment is needed for MSVC +#if defined(_MSC_VER) +#pragma warning(disable:6385) +// Because the embedder is compiled as 32 bit always, we detect +// 64 bit MS compilations through an additional include +#include "build64.h" +#define __STR2__(x) #x +#define __STR1__(x) __STR2__(x) +#if (defined(_WIN64) || defined(BUILD64)) && defined(OPT_M32) +// a 64 bit application/library CANNOT be used on 32 bit platforms +#pragma message(__FILE__ "(" __STR1__(__LINE__) ") : warning : library is compiled as 64 bit - disabling 32 bit support") +#undef OPT_M32 +#endif +#endif + +/* + * Defines where we should we pick the 32 and 64 bit installer exes to embed + */ +#if defined(_MSC_VER) && !defined(DDKBUILD) +#if !defined(SOLUTIONDIR) +#define SOLUTIONDIR ".." +#endif +#if defined(_DEBUG) +#define INSTALLER_PATH_32 SOLUTIONDIR "\\Win32\\Debug\\helper" +#define INSTALLER_PATH_64 SOLUTIONDIR "\\x64\\Debug\\helper" +#else +#define INSTALLER_PATH_32 SOLUTIONDIR "\\Win32\\Release\\helper" +#define INSTALLER_PATH_64 SOLUTIONDIR "\\x64\\Release\\helper" +#endif +#else +#if !defined(SOLUTIONDIR) +#define SOLUTIONDIR "." +#endif +// If you compile with shared libs, DON'T PICK THE EXE IN "installer", +// as it won't run from ANYWHERE ELSE! Use the one from .libs instead. +#define INSTALLER_PATH_32 SOLUTIONDIR +#define INSTALLER_PATH_64 SOLUTIONDIR +#endif diff --git a/driver/source/libwdi/embedder_files.h b/driver/source/libwdi/embedder_files.h new file mode 100644 index 00000000..e0e1b2ed --- /dev/null +++ b/driver/source/libwdi/embedder_files.h @@ -0,0 +1,156 @@ +/* + * 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-2013 Pete Batard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 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 + */ +#pragma once + +/* + * This include defines the driver files that should be embedded in the library. + * This file is meant to be used by libwdi developers only. + * If you want to add extra files from a specific directory (eg signed inf and cat) + * you should either define the macro USER_DIR in msvc/config.h (MS compilers) or + * use the --with-userdir option when running configure. + */ + +struct emb { + int reuse_last; + char* file_name; + char* extraction_subdir; +}; + +#define _STR(s) #s +#define STR(s) _STR(s) + +/* + * files to embed + */ +struct emb embeddable_fixed[] = { + +// WinUSB +#if defined(DDK_DIR) +# if defined(OPT_M32) + { 0, DDK_DIR "\\redist\\wdf\\x86\\WdfCoInstaller0" STR(WDF_VER) ".dll", "x86" }, + { 0, DDK_DIR "\\redist\\" COINSTALLER_DIR "\\x86\\winusbcoinstaller2.dll", "x86" }, +# endif // OPT_M32 +# if defined(OPT_M64) + { 0, DDK_DIR "\\redist\\wdf\\" X64_DIR "\\WdfCoInstaller0" STR(WDF_VER) ".dll", "amd64" }, + { 0, DDK_DIR "\\redist\\" COINSTALLER_DIR "\\" X64_DIR "\\winusbcoinstaller2.dll", "amd64" }, +# endif // OPT_M64 +# if defined(OPT_IA64) + { 0, DDK_DIR "\\redist\\wdf\\ia64\\WdfCoInstaller0" STR(WDF_VER) ".dll", "ia64" }, + { 0, DDK_DIR "\\redist\\" COINSTALLER_DIR "\\ia64\\winusbcoinstaller2.dll", "ia64" }, +# endif // OPT_IA64 +#endif // DDK_DIR + +// libusb0 +#if defined(LIBUSB0_DIR) + { 0, LIBUSB0_DIR "\\bin\\x86\\libusb0_x86.dll", "x86" }, + { 0, LIBUSB0_DIR "\\bin\\x86\\install-filter.exe", "x86" }, +# if defined(LIBUSBK_DIR) +# if defined(OPT_M32) + { 1, "libusb0.dll", "x86" }, // reuse +# endif // OPT_M32 +# if defined(OPT_M64) + { 1, "libusb0_x86.dll", "amd64" }, // reuse +# endif // OPT_M64 +# endif // LIBUSBK_DIR +# if defined(OPT_M32) + { 0, LIBUSB0_DIR "\\bin\\x86\\libusb0.sys", "x86" }, +# endif // OPT_M32 +# if defined(OPT_M64) + { 0, LIBUSB0_DIR "\\bin\\amd64\\libusb0.dll", "amd64" }, + { 0, LIBUSB0_DIR "\\bin\\amd64\\libusb0.sys", "amd64" }, + { 0, LIBUSB0_DIR "\\bin\\amd64\\install-filter.exe", "amd64" }, +# endif // OPT_M64 +# if defined(OPT_IA64) + { 0, LIBUSB0_DIR "\\bin\\ia64\\libusb0.dll", "ia64" }, + { 0, LIBUSB0_DIR "\\bin\\ia64\\libusb0.sys", "ia64" }, + { 0, LIBUSB0_DIR "\\bin\\ia64\\install-filter.exe", "ia64" }, +# endif // OPT_IA64 + { 0, LIBUSB0_DIR "\\installer_license.txt", "license\\libusb0" }, +#endif // LIBUSB0_DIR + +// libusbK +#if defined(LIBUSBK_DIR) + +# if defined(OPT_M32) +# if !defined(DDK_DIR) + { 0, LIBUSBK_DIR "\\sys\\x86\\WdfCoInstaller" STR(WDF_VER) ".dll", "x86" }, +# endif // DDK_DIR + { 0, LIBUSBK_DIR "\\sys\\x86\\libusbK.sys", "x86" }, + { 0, LIBUSBK_DIR "\\dll\\x86\\libusbK.dll", "x86" }, +# if defined(OPT_M64) + { 1, "libusbK_x86.dll", "amd64" }, // reuse +# endif // OPT_M64 +# if !defined(LIBUSB0_DIR) + { 0, LIBUSBK_DIR "\\dll\\x86\\libusb0.dll", "x86" }, +# if defined(OPT_M64) + { 1, "libusb0_x86.dll", "amd64" }, // reuse +# endif // OPT_M64 +# endif // LIBUSB0_DIR +# endif // OPT_M32 + +# if defined(OPT_M64) +# if !defined(DDK_DIR) + { 0, LIBUSBK_DIR "\\sys\\amd64\\WdfCoInstaller" STR(WDF_VER) ".dll", "amd64" }, +# endif // DDK_DIR + { 0, LIBUSBK_DIR "\\sys\\amd64\\libusbK.sys", "amd64" }, + { 0, LIBUSBK_DIR "\\dll\\amd64\\libusbK.dll", "amd64" }, +# if !defined(LIBUSB0_DIR) + { 0, LIBUSBK_DIR "\\dll\\amd64\\libusb0.dll", "amd64" }, +# endif // LIBUSB0_DIR +# if !defined(OPT_M32) + // The x86/ DLLs will not be used, but they are required for rename to _x86 + { 0, LIBUSBK_DIR "\\dll\\x86\\libusbK.dll", "x86" }, + { 1, "libusbK_x86.dll", "amd64" }, +# if !defined(LIBUSB0_DIR) + { 0, LIBUSBK_DIR "\\dll\\x86\\libusb0.dll", "x86" }, + { 1, "libusb0_x86.dll", "amd64" }, +# endif // LIBUSB0_DIR +# endif // OPT_M32 +# endif // OPT_M64 + +# if defined(OPT_IA64) +# if !defined(DDK_DIR) + { 0, LIBUSBK_DIR "\\sys\\ia64\\WdfCoInstaller" STR(WDF_VER) ".dll", "ia64" }, +# endif // DDK_DIR + { 0, LIBUSBK_DIR "\\sys\\ia64\\libusbK.sys", "ia64" }, + { 0, LIBUSBK_DIR "\\dll\\ia64\\libusbK.dll", "ia64" }, + { 0, LIBUSBK_DIR "\\dll\\ia64\\libusb0.dll", "ia64" }, +# endif // OPT_IA64 + +#endif // LIBUSBK_DIR + +// Common files +#if defined(OPT_M32) + { 0, INSTALLER_PATH_32 "\\installer_x86.exe", "." }, +#endif +#if defined(OPT_M64) + { 0, INSTALLER_PATH_64 "\\installer_x64.exe", "." }, +#endif +// inf templates for the tokenizer ("" directory means no extraction) + { 0, "winusb.inf.in", "" }, + { 0, "libusb0.inf.in", "" }, + { 0, "libusbk.inf.in", "" }, + { 0, "usbser.inf.in", "" }, +// cat file lists for self signing + { 0, "winusb.cat.in", "" }, + { 0, "libusb0.cat.in", "" }, + { 0, "libusbk.cat.in", "" }, + { 0, "usbser.cat.in", "" }, +}; diff --git a/driver/source/libwdi/installer.c b/driver/source/libwdi/installer.c new file mode 100644 index 00000000..7c5a935d --- /dev/null +++ b/driver/source/libwdi/installer.c @@ -0,0 +1,901 @@ +/* + * Library for WinUSB/libusb automated driver installation + * Copyright (c) 2010-2013 Pete Batard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 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 + */ + +// This standalone installer is a separate exe, as it needs +// - administrative rights, and therefore UAC elevation on platforms that use UAC +// - native 32 or 64 bit execution according to the platform + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "installer.h" +#include "libwdi.h" +#include "msapi_utf8.h" + +// DDK complains about checking a const string against NULL... +#if defined(DDKBUILD) +#pragma warning(disable:4130) +#endif +// as well as "Banned API Usage" when using OACR/Prefast. +#if defined(_PREFAST_) +#pragma warning(disable:28719) +#endif + +#define REQUEST_TIMEOUT 5000 +#define PF_ERR plog + +// UpdateDriverForPlugAndPlayDevices.InstallFlags constants +#define INSTALLFLAG_FORCE 0x00000001 +#define INSTALLFLAG_READONLY 0x00000002 +#define INSTALLFLAG_NONINTERACTIVE 0x00000004 +#define INSTALLFLAG_BITS 0x00000007 + +// MinGW32 doesn't know this one apparently +#if !defined(FACILITY_SETUPAP) +#define FACILITY_SETUPAPI 15 +#endif + +// Also MinGW doesn't have wuerror.h yet +#define WU_E_WU_DISABLED 0x8024002E +#define WU_S_ALREADY_INSTALLED 0x00240006 + +/* + * Cfgmgr32.dll interface + */ +typedef CHAR *DEVNODEID_A, *DEVINSTID_A; +typedef WCHAR *DEVNODEID_W, *DEVINSTID_W; +#ifdef UNICODE +typedef DEVNODEID_W DEVNODEID; +typedef DEVINSTID_W DEVINSTID; +#else +typedef DEVNODEID_A DEVNODEID; +typedef DEVINSTID_A DEVINSTID; +#endif + +PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Locate_DevNodeA, (PDEVINST, DEVINSTID_A, ULONG)); +PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Reenumerate_DevNode, (DEVINST, ULONG)); +PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_DevNode_Status, (PULONG, PULONG, DEVINST, ULONG)); +PF_TYPE_DECL(CDECL, int, __wgetmainargs, (int*, wchar_t***, wchar_t***, int, int*)); + +/* + * Globals + */ +HANDLE pipe_handle = INVALID_HANDLE_VALUE; +HANDLE syslog_ready_event = INVALID_HANDLE_VALUE; +HANDLE syslog_terminate_event = INVALID_HANDLE_VALUE; +PSID user_psid = NULL; + +// Log data with parent app through the pipe +void plog_v(const char *format, va_list args) +{ + char buffer[STR_BUFFER_SIZE]; + DWORD junk; + int size; + + if (pipe_handle == INVALID_HANDLE_VALUE) + return; + + buffer[0] = IC_PRINT_MESSAGE; + + size = safe_vsnprintf(buffer+1, STR_BUFFER_SIZE-1, format, args); + if (size < 0) { + buffer[STR_BUFFER_SIZE-1] = 0; + size = STR_BUFFER_SIZE-2; + } + WriteFile(pipe_handle, buffer, (DWORD)size+2, &junk, NULL); +} + +void plog(const char *format, ...) +{ + va_list args; + + va_start (args, format); + plog_v(format, args); + va_end (args); +} + +// Setup the Cfgmgr32 DLLs +static BOOL init_dlls(void) +{ + PF_INIT_OR_OUT(CM_Locate_DevNodeA, Cfgmgr32.dll); + PF_INIT_OR_OUT(CM_Reenumerate_DevNode, Cfgmgr32.dll); + PF_INIT_OR_OUT(CM_Get_DevNode_Status, Cfgmgr32.dll); + PF_INIT(__wgetmainargs, Msvcrt.dll); + return TRUE; +out: + return FALSE; +} + +// Notify the parent app +void send_status(char status) +{ + DWORD junk; + WriteFile(pipe_handle, &status, 1, &junk, NULL); +} + +// Post a WDI status code +void pstat(int status) +{ + char data[2]; + DWORD junk; + + data[0] = IC_SET_STATUS; + data[1] = (char)status; + WriteFile(pipe_handle, data, 2, &junk, NULL); +} + +// Query the parent app for data +int request_data(char req, void *buffer, int size) +{ + OVERLAPPED overlapped; + DWORD rd_count; + DWORD r, count = (DWORD)size; + + if ((buffer == NULL) || (size <= 0)) { + return -1; + } + + // Set the overlapped for messaging + memset(&overlapped, 0, sizeof(OVERLAPPED)); + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (overlapped.hEvent == NULL) { + plog("failed to create overlapped"); + return -1; + } + + if (ReadFile(pipe_handle, buffer, count, &rd_count, &overlapped)) { + // Message was read synchronously + plog("received unexpected data"); + CloseHandle(overlapped.hEvent); + return -1; + } + + if (GetLastError() != ERROR_IO_PENDING) { + plog("failure to initiate read (%d)", (int)GetLastError()); + CloseHandle(overlapped.hEvent); + return -1; + } + + // Now that we're set to receive data, let's send our request + WriteFile(pipe_handle, &req, 1, &r, NULL); + + // Wait for the response + r = WaitForSingleObject(overlapped.hEvent, REQUEST_TIMEOUT); + if ( (r == WAIT_OBJECT_0) && (GetOverlappedResult(pipe_handle, &overlapped, &rd_count, FALSE)) ) { + CloseHandle(overlapped.hEvent); + return (int)rd_count; + } + + if (r == WAIT_TIMEOUT) { + plog("message request: timed out"); + } else { + plog("read error: %d", (int)GetLastError()); + } + CloseHandle(overlapped.hEvent); + return -1; +} + +// Query parent app for device ID +char* req_id(enum installer_code id_code) +{ + int size; + char* id_text[3] = {"device_id", "hardware_id", "user_sid"}; + static char device_id[MAX_PATH_LENGTH]; + static char hardware_id[MAX_PATH_LENGTH]; + static char user_sid[MAX_PATH_LENGTH]; + char* id = NULL; + + switch(id_code) { + case IC_GET_DEVICE_ID: + id = device_id; + break; + case IC_GET_HARDWARE_ID: + id = hardware_id; + break; + case IC_GET_USER_SID: + id = user_sid; + break; + default: + plog("req_id: unknown ID requested"); + return NULL; + } + + memset(id, 0, MAX_PATH_LENGTH); + size = request_data(id_code, (void*)id, MAX_PATH_LENGTH); + if (size > 0) { + plog("got %s: '%s'", id_text[id_code-IC_GET_DEVICE_ID], id); + return (id[0] != 0)?id:NULL; + } + + plog("failed to read %s", id_text[id_code-IC_GET_DEVICE_ID]); + return NULL; +} + +/* + * Force the re-enumeration of a device and all of its children + * This causes driver installation for devices where either the driver + * is already available, or for devices where a device_id was not provided, + * yet that are plugged in. + * If device_id is NULL, this call re-enumerates all devices + */ +int enumerate_device(char* device_id) +{ + DEVINST dev_inst; + CONFIGRET status; + + plog("re-enumerating driver node %s...", device_id?device_id:""); + status = pfCM_Locate_DevNodeA(&dev_inst, device_id, 0); + if (status != CR_SUCCESS) { + plog("failed to locate device_id %s: %x\n", device_id?device_id:"", status); + return -1; + } + + status = pfCM_Reenumerate_DevNode(dev_inst, CM_REENUMERATE_RETRY_INSTALLATION); + if (status != CR_SUCCESS) { + plog("failed to re-enumerate device node: CR code %X", status); + return -1; + } + + plog("re-enumeration succeeded..."); + return 0; +} + + +/* + * Flag phantom/removed devices for reinstallation. See: + * http://msdn.microsoft.com/en-us/library/ff541091.aspx + */ +void check_removed(char* device_hardware_id) +{ + unsigned i, removed = 0; + DWORD size, reg_type, config_flags; + ULONG status, pbm_number; + HDEVINFO dev_info; + SP_DEVINFO_DATA dev_info_data; + char hardware_id[STR_BUFFER_SIZE]; + + // List all known USB devices (including non present ones) + dev_info = SetupDiGetClassDevsA(NULL, "USB", NULL, DIGCF_ALLCLASSES); + if (dev_info == INVALID_HANDLE_VALUE) { + return; + } + + // Find the ones that are driverless + for (i = 0; ; i++) + { + dev_info_data.cbSize = sizeof(dev_info_data); + if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) { + break; + } + + // Find the hardware ID + if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID, + ®_type, (BYTE*)hardware_id, STR_BUFFER_SIZE, &size)) { + continue; + } + + // Match? + if (safe_strncmp(hardware_id, device_hardware_id, STR_BUFFER_SIZE) != 0) { + continue; + } + + // Unplugged? + if (pfCM_Get_DevNode_Status(&status, &pbm_number, dev_info_data.DevInst, 0) != CR_NO_SUCH_DEVNODE) { + continue; + } + + // Flag for reinstall on next plugin + if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_CONFIGFLAGS, + ®_type, (BYTE*)&config_flags, sizeof(DWORD), &size)) { + plog("could not read SPDRP_CONFIGFLAGS for phantom device %s", hardware_id); + continue; + } + config_flags |= CONFIGFLAG_REINSTALL; + if (!SetupDiSetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_CONFIGFLAGS, + (BYTE*)&config_flags, sizeof(DWORD))) { + plog("could not write SPDRP_CONFIGFLAGS for phantom device %s", hardware_id); + continue; + } + removed++; + } + + if (removed) { + plog("flagged %d removed devices for reinstallation", removed); + } +} + +/* + * Converts a default system locate string to UTF-8 + * (allocate returned string with 1 extra leading byte) + * Returns NULL on error + */ +static __inline char* xlocale_to_utf8(const char* str) +{ + int size = 0; + wchar_t* wstr = NULL; + char* ustr = NULL; + + // locale -> unicode + size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + if (size <= 1) + return NULL; + + if ((wstr = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL) + return NULL; + + if (MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, size) != size) { + free(wstr); + return NULL; + } + + // unicode -> UTF-8 + size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); + if (size <= 1) { + free(wstr); + return NULL; + } + + // +1 for extra leading byte + if ((ustr = (char*)calloc(size+1, 1)) == NULL) { + free(wstr); + return NULL; + } + + if (wchar_to_utf8_no_alloc(wstr, ustr+1, size) != size) { + free(ustr); + free(wstr); + return NULL; + } + free(wstr); + + return ustr; +} + +/* + * Send individual lines of the syslog section pointed by buffer back to the main application + * xbuffer's payload MUST start at byte 1 to accommodate the SYSLOG_MESSAGE prefix + */ +DWORD process_syslog(char* buffer, DWORD size) +{ + DWORD i, junk, start = 0; + char* xbuffer; + char* ins_string = ""; + char conversion_error[] = " "; + + if (buffer == NULL) return 0; + + // CR/LF breakdown + for (i=0; i" line in any log file, it's game over then + if (safe_strcmp(ins_string, buffer + start) == 0) { + return start; + } + + // The logs are using the system locale. Convert to UTF8 (with extra leading byte) + xbuffer = xlocale_to_utf8(&buffer[start]); + if (xbuffer == NULL) { + xbuffer = conversion_error; + } + + // This is where we use the extra start byte + xbuffer[0] = IC_SYSLOG_MESSAGE; + WriteFile(pipe_handle, xbuffer, (DWORD)safe_strlen(&xbuffer[1])+2, &junk, NULL); + if (xbuffer != conversion_error) { + free(xbuffer); + } + start = i; + } + } + // start does not necessarily equate size, if there are truncated lines at the end + return start; +} + +/* + * Read from the driver installation syslog in real-time + */ +void __cdecl syslog_reader_thread(void* param) +{ +#define NB_SYSLOGS 3 + char* syslog_name[NB_SYSLOGS] = { "\\inf\\setupapi.dev.log", "\\setupapi.log", "\\setupact.log" }; + HANDLE log_handle; + DWORD last_offset, size, read_size, processed_size; + char *buffer = NULL; + char log_path[MAX_PATH_LENGTH]; + DWORD duration = 0; + int i; + + // Try the various driver installation logs + for (i=0; i=0) && ((err_string[i]==0x0A) || (err_string[i]==0x0D)); i--) { + err_string[i] = 0; + } + } + return err_string; +} + +/* + * Convert various installation errors to their WDI counterpart + */ +static __inline int process_error(DWORD r, char* path) { + // 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 + // r = 5 ERROR_ACCESS_DENIED if needs admin elevation + // r = 1058 ERROR_SERVICE_DISABLED => WU service is disabled + // r = 0xD ERROR_INVALID_DATA => inf is missing some data + // r = 0xE0000003 ERROR_GENERAL_SYNTAX the syntax of the inf is invalid or the inf is empty + // r = 0xE0000217 ERROR_BAD_SERVICE_INSTALLSECT happens if referencing a non present sys in svc section + // r = 0xE0000304 ERROR_INVALID_CATALOG_DATA => no cat + // r = 0xE000023F ERROR_NO_AUTHENTICODE_CATALOG => user cancelled on warnings + // r = 0xE0000235 ERROR_IN_WOW64 => trying to run a 32 bit installer on a 64 bit machine + // r = 0xE0000247 ERROR_DRIVER_STORE_ADD_FAILED if user decided not to install on warnings + // r = 0xE0000203 ERROR_NO_DRIVER_SELECTED if the driver provided is not compatible with the target platform + // 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 = 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)"); + return WDI_ERROR_EXISTS; + case ERROR_NO_SUCH_DEVINST: + plog("device 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); + return WDI_ERROR_INVALID_PARAM; + case ERROR_FILE_NOT_FOUND: + plog("the system can not find the file 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"); + return WDI_ERROR_NOT_FOUND; + case ERROR_ACCESS_DENIED: + 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"); + 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"); + return WDI_ERROR_INF_SYNTAX; + case ERROR_BAD_SERVICE_INSTALLSECT: + plog("a section of the inf has a problem"); + return WDI_ERROR_INF_SYNTAX; + case ERROR_INVALID_CATALOG_DATA: + plog("unable to locate 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"); + return WDI_ERROR_USER_CANCEL; + case ERROR_NO_DRIVER_SELECTED: + plog("the driver is not compatible with this version of Windows"); + return WDI_ERROR_NOT_SUPPORTED; + case ERROR_ALREADY_EXISTS: + plog("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("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."); + return WDI_ERROR_OTHER; + case WU_S_ALREADY_INSTALLED: + plog("the driver is already installed"); + return WDI_SUCCESS; + case ERROR_SUCCESS_REBOOT_REQUIRED: + plog("the driver was installed successfully, but a reboot is required."); + return WDI_SUCCESS; + default: + plog("unhandled error 0x%X (%d)", r, r); + plog(windows_error_str(r)); + return WDI_ERROR_OTHER; + } +} + +// Disable or restore the system restore creation point settings for driver install +BOOL disable_system_restore(BOOL enabled) +{ + OSVERSIONINFO os_version; + LONG r; + DWORD disp, regtype, val, val_size=sizeof(DWORD); + HRESULT hr; + IGroupPolicyObject* pLGPO; + 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 + const IID my_IID_IGroupPolicyObject = + { 0xea502723, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; + const IID my_CLSID_GroupPolicyObject = + { 0xea502722, 0xa23d, 0x11d1, { 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } }; + GUID ext_guid = REGISTRY_EXTENSION_GUID; + // Can be anything really + GUID snap_guid = { 0x3D271CFC, 0x2BC6, 0x4AC2, {0xB6, 0x33, 0x3B, 0xDF, 0xF5, 0xBD, 0xAB, 0x2A} }; + + // This call only makes sense on Vista or later + memset(&os_version, 0, sizeof(OSVERSIONINFO)); + os_version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if ((GetVersionEx(&os_version) != 0) && (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)) { + if (os_version.dwMajorVersion < 6) { + return TRUE; + } + } + + // We need an IGroupPolicyObject instance to set a Local Group Policy + hr = CoCreateInstance(&my_CLSID_GroupPolicyObject, NULL, CLSCTX_INPROC_SERVER, &my_IID_IGroupPolicyObject, (LPVOID*)&pLGPO); + if (FAILED(hr)) { + plog("CoCreateInstance failed; hr = %x", hr); + goto error; + } + + hr = pLGPO->lpVtbl->OpenLocalMachineGPO(pLGPO, GPO_OPEN_LOAD_REGISTRY); + if (FAILED(hr)) { + plog("OpenLocalMachineGPO failed - error %x", hr); + goto error; + } + + hr = pLGPO->lpVtbl->GetRegistryKey(pLGPO, GPO_SECTION_MACHINE, &machine_key); + if (FAILED(hr)) { + plog("GetRegistryKey failed - error %x", hr); + goto error; + } + + // The DisableSystemRestore is set in Software\Policies\Microsoft\Windows\DeviceInstall\Settings + r = RegCreateKeyExA(machine_key, "Software\\Policies\\Microsoft\\Windows\\DeviceInstall\\Settings", + 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &disable_system_restore_key, &disp); + if (r != ERROR_SUCCESS) { + plog("RegCreateKeyEx failed - error %x", hr); + goto error; + } + + if ((disp == REG_OPENED_EXISTING_KEY) && (enabled) && (original_val == -1)) { + // backup existing value for restore + regtype = REG_DWORD; + r = RegQueryValueExA(disable_system_restore_key, "DisableSystemRestore", NULL, ®type, (LPBYTE)&original_val, &val_size); + if (r == ERROR_FILE_NOT_FOUND) { + // The Key exists but not its value, which is OK + original_val = -1; + } else if (r != ERROR_SUCCESS) { + plog("failed to read original DisableSystemRestore value - error %x", r); + } + } + + if ((enabled) || (original_val != -1)) { + val = (enabled)?1:original_val; + r = RegSetValueExA(disable_system_restore_key, "DisableSystemRestore", 0, REG_DWORD, (BYTE*)&val, sizeof(val)); + } else { + r = RegDeleteValueA(disable_system_restore_key, "DisableSystemRestore"); + } + if (r != ERROR_SUCCESS) { + plog("RegSetValueEx / RegDeleteValue failed - error %x", r); + } + RegCloseKey(disable_system_restore_key); + disable_system_restore_key = NULL; + + // Apply policy + hr = pLGPO->lpVtbl->Save(pLGPO, TRUE, (enabled)?TRUE:FALSE, &ext_guid, &snap_guid); + if (r != S_OK) { + plog("unable to apply DisableSystemRestore policy - error %x", hr); + goto error; + } else { + plog("successfully %s the system restore point creation setting", (enabled)?"disabled":"restored"); + } + + RegCloseKey(machine_key); + pLGPO->lpVtbl->Release(pLGPO); + return TRUE; + +error: + if (machine_key != NULL) RegCloseKey(machine_key); + if (disable_system_restore_key != NULL) RegCloseKey(disable_system_restore_key); + if (pLGPO != NULL) pLGPO->lpVtbl->Release(pLGPO); + return FALSE; +} + +// TODO: allow commandline options (v2) +// TODO: remove existing infs for similar devices (v2) +int __cdecl main(int argc_ansi, char** argv_ansi) +{ + DWORD r; + BOOL b; + int i, ret, argc = argc_ansi, si=0; + char** argv = argv_ansi; + wchar_t **wenv, **wargv; + char* hardware_id = NULL; + char* device_id = NULL; + char* user_sid = NULL; + char* inf_name = NULL; + char path[MAX_PATH_LENGTH]; + char destname[MAX_PATH_LENGTH]; + uintptr_t syslog_reader_thid = -1L; + + // Connect to the messaging pipe + pipe_handle = CreateFileA(INSTALLER_PIPE_NAME, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL); + if (pipe_handle == INVALID_HANDLE_VALUE) { + // If we can't connect to the pipe, someone is probably trying to run us standalone + printf("This application can not be run from the command line.\n"); + printf("Please use your initial installer application if you want to install the driver.\n"); + return WDI_ERROR_NOT_SUPPORTED; + } + + if (!init_dlls()) { + plog("could not init DLLs"); + ret = WDI_ERROR_RESOURCE; + goto out; + } + + // Initialize COM for Restore Point disabling + IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); + + // libwdi provides the arguments as UTF-16 => read them and convert to UTF-8 + if (pf__wgetmainargs != NULL) { + pf__wgetmainargs(&argc, &wargv, &wenv, 1, &si); + argv = (char**)calloc(argc, sizeof(char*)); + for (i=0; i\n", argv[0]); + plog("missing inf_name parameter"); + } + + inf_name = argv[1]; + plog("got parameter %s", argv[1]); + r = GetFullPathNameU(".", MAX_PATH_LENGTH, path, NULL); + if ((r == 0) || (r > MAX_PATH_LENGTH)) { + plog("could not retrieve absolute path of working directory"); + ret = WDI_ERROR_ACCESS; + goto out; + } + safe_strcat(path, MAX_PATH_LENGTH, "\\"); + safe_strcat(path, MAX_PATH_LENGTH, inf_name); + + device_id = req_id(IC_GET_DEVICE_ID); + hardware_id = req_id(IC_GET_HARDWARE_ID); + // Will be used if we ever need to create a file, as the original user, from this app + user_sid = req_id(IC_GET_USER_SID); + ConvertStringSidToSidA(user_sid, &user_psid); + + // Setup the syslog reader thread + syslog_ready_event = CreateEvent(NULL, TRUE, FALSE, NULL); + syslog_terminate_event = CreateEvent(NULL, TRUE, FALSE, NULL); + syslog_reader_thid = _beginthread(syslog_reader_thread, 0, 0); + if ( (syslog_reader_thid == -1L) + || (WaitForSingleObject(syslog_ready_event, 2000) != WAIT_OBJECT_0) ) { + plog("Unable to create syslog reader thread"); + SetEvent(syslog_terminate_event); + // NB: if you try to close the syslog reader thread handle, you get a + // "more recent driver was found" error from UpdateForPnP. Weird... + } + + // Disable the creation of a restore point + disable_system_restore(TRUE); + + // Find if the device is plugged in + send_status(IC_SET_TIMEOUT_INFINITE); + if (hardware_id != NULL) { + plog("Installing driver for %s - please wait...", hardware_id); + b = UpdateDriverForPlugAndPlayDevicesU(NULL, hardware_id, path, INSTALLFLAG_FORCE, NULL); + send_status(IC_SET_TIMEOUT_DEFAULT); + if (b == TRUE) { + // Success + plog("driver update completed"); + enumerate_device(device_id); + ret = WDI_SUCCESS; + goto out; + } + + ret = process_error(GetLastError(), path); + if (ret != WDI_SUCCESS) { + goto out; + } + } + + // TODO: try URL for OEMSourceMediaLocation (v2) + plog("Copying inf file (for the next time device is plugged) - please wait..."); + send_status(IC_SET_TIMEOUT_INFINITE); + b = SetupCopyOEMInfU(path, NULL, SPOST_PATH, 0, destname, MAX_PATH_LENGTH, NULL, NULL); + send_status(IC_SET_TIMEOUT_DEFAULT); + if (b) { + plog("copied inf to %s", destname); + ret = WDI_SUCCESS; + enumerate_device(device_id); + goto out; + } + + ret = process_error(GetLastError(), path); + if (ret != WDI_SUCCESS) { + goto out; + } + + // If needed, flag removed devices for reinstallation. see: + // http://msdn.microsoft.com/en-us/library/aa906206.aspx + check_removed(hardware_id); + +out: + // Report any error status code and wait for target app to read it + send_status(IC_INSTALLER_COMPLETED); + pstat(ret); + // Restore the system restore point creation original settings + disable_system_restore(FALSE); + // TODO: have libwi send an ACK? + Sleep(1000); + SetEvent(syslog_terminate_event); + if (argv != argv_ansi) { + for (i=0; i + * + * 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 + */ +#pragma once + +#include +#include + +#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 + +#define MAX_DESC_LENGTH 256 +#define MAX_PATH_LENGTH 512 +#define MAX_KEY_LENGTH 256 +#define STR_BUFFER_SIZE 256 +#define MAX_GUID_STRING_LENGTH 40 + +#define INSTALLER_PIPE_NAME "\\\\.\\pipe\\libwdi-installer" + +#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0) +#define safe_min(a, b) min((size_t)(a), (size_t)(b)) +#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \ + ((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0) +#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1) +#define 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_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 static_sprintf(dest, format, ...) safe_sprintf(dest, sizeof(dest), format, __VA_ARGS__) +#define safe_swprintf _snwprintf +#define safe_strdup _strdup +#ifndef ARRAYSIZE +#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif +#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 + +/* + * For communications between installer <-> libwdi + */ +enum installer_code { + IC_PRINT_MESSAGE, + IC_SYSLOG_MESSAGE, + IC_GET_DEVICE_ID, + IC_GET_HARDWARE_ID, + IC_GET_USER_SID, + IC_SET_TIMEOUT_INFINITE, + IC_SET_TIMEOUT_DEFAULT, + IC_SET_STATUS, + IC_INSTALLER_COMPLETED, +}; + +/* Helper functions to access DLLs */ +static __inline HMODULE GetDLLHandle(char* szDLLName) +{ + HANDLE h = GetModuleHandleA(szDLLName); + if (h == NULL) { + // coverity[alloc_fn][var_assign] + h = LoadLibraryA(szDLLName); + } + 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, dllname) if (pf##proc == NULL) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc) +#define PF_INIT_OR_OUT(proc, dllname) PF_INIT(proc, dllname); if (pf##proc == NULL) { \ + PF_ERR("Unable to locate %s() in %s\n", #proc, #dllname); goto out; } + +/* + * Cfgmgr32.dll interface + */ +typedef DWORD DEVNODE, DEVINST; +typedef DEVNODE *PDEVNODE, *PDEVINST; +typedef DWORD RETURN_TYPE; +typedef RETURN_TYPE CONFIGRET; + +#define CR_SUCCESS 0x00000000 +#define CR_NO_SUCH_DEVNODE 0x0000000D +#define CONFIGFLAG_REINSTALL 0x00000020 + +#define CM_REENUMERATE_NORMAL 0x00000000 +#define CM_REENUMERATE_SYNCHRONOUS 0x00000001 +#define CM_REENUMERATE_RETRY_INSTALLATION 0x00000002 +#define CM_REENUMERATE_ASYNCHRONOUS 0x00000004 +#define CM_REENUMERATE_BITS 0x00000007 + +/* + * DifXApi.dll interface + */ +#define DRIVER_PACKAGE_REPAIR 0x00000001 +#define DRIVER_PACKAGE_FORCE 0x00000004 +#define DRIVER_PACKAGE_LEGACY_MODE 0x00000010 + +#define ERROR_INVALID_CATALOG_DATA 0xE0000304 +#ifndef ERROR_DRIVER_STORE_ADD_FAILED +#define ERROR_DRIVER_STORE_ADD_FAILED 0xE0000247 +#endif +#ifndef ERROR_NO_AUTHENTICODE_CATALOG +#define ERROR_NO_AUTHENTICODE_CATALOG 0xE000023F +#endif +#ifndef ERROR_IN_WOW64 +#define ERROR_IN_WOW64 0xE0000235 +#endif +#ifndef ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED +#define ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED 0xE0000243 +#endif +#ifndef ERROR_FILE_HASH_NOT_IN_CATALOG +#define ERROR_FILE_HASH_NOT_IN_CATALOG 0xE000024B +#endif + +typedef enum { + DIFXAPI_SUCCESS, + DIFXAPI_INFO, + DIFXAPI_WARNING, + DIFXAPI_ERROR +} DIFXAPI_LOG; +typedef void (__cdecl* DIFXAPILOGCALLBACK)(DIFXAPI_LOG EventType, DWORD Error, LPCSTR EventDescription, PVOID CallbackContext); + +typedef struct { + LPCSTR pApplicationId; + LPCSTR pDisplayName; + LPCSTR pProductName; + LPCSTR pMfgName; +} INSTALLERINFO, *PINSTALLERINFO; +typedef const PINSTALLERINFO PCINSTALLERINFO; + +/* + * GPEdit Interface (from MinGW-w64) + */ +typedef enum _GROUP_POLICY_OBJECT_TYPE { + GPOTypeLocal = 0,GPOTypeRemote,GPOTypeDS +} GROUP_POLICY_OBJECT_TYPE,*PGROUP_POLICY_OBJECT_TYPE; + +#define REGISTRY_EXTENSION_GUID { 0x35378EAC,0x683F,0x11D2, {0xA8,0x9A,0x00,0xC0,0x4F,0xBB,0xCF,0xA2} } +#define GPO_OPEN_LOAD_REGISTRY 0x00000001 +#define GPO_SECTION_MACHINE 2 + +#undef INTERFACE +#define INTERFACE IGroupPolicyObject + DECLARE_INTERFACE_(IGroupPolicyObject,IUnknown) { + STDMETHOD(QueryInterface) (THIS_ REFIID riid,LPVOID *ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + STDMETHOD(New) (THIS_ LPOLESTR pszDomainName,LPOLESTR pszDisplayName,DWORD dwFlags) PURE; + STDMETHOD(OpenDSGPO) (THIS_ LPOLESTR pszPath,DWORD dwFlags) PURE; + STDMETHOD(OpenLocalMachineGPO) (THIS_ DWORD dwFlags) PURE; + STDMETHOD(OpenRemoteMachineGPO) (THIS_ LPOLESTR pszComputerName,DWORD dwFlags) PURE; + STDMETHOD(Save) (THIS_ BOOL bMachine, BOOL bAdd,GUID *pGuidExtension,GUID *pGuid) PURE; + STDMETHOD(Delete) (THIS) PURE; + STDMETHOD(GetName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; + STDMETHOD(GetDisplayName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; + STDMETHOD(SetDisplayName) (THIS_ LPOLESTR pszName) PURE; + STDMETHOD(GetPath) (THIS_ LPOLESTR pszPath,int cchMaxPath) PURE; + STDMETHOD(GetDSPath) (THIS_ DWORD dwSection,LPOLESTR pszPath,int cchMaxPath) PURE; + STDMETHOD(GetFileSysPath) (THIS_ DWORD dwSection,LPOLESTR pszPath,int cchMaxPath) PURE; + STDMETHOD(GetRegistryKey) (THIS_ DWORD dwSection,HKEY *hKey) PURE; + STDMETHOD(GetOptions) (THIS_ DWORD *dwOptions) PURE; + STDMETHOD(SetOptions) (THIS_ DWORD dwOptions,DWORD dwMask) PURE; + STDMETHOD(GetType) (THIS_ GROUP_POLICY_OBJECT_TYPE *gpoType) PURE; + STDMETHOD(GetMachineName) (THIS_ LPOLESTR pszName,int cchMaxLength) PURE; + STDMETHOD(GetPropertySheetPages) (THIS_ HPROPSHEETPAGE **hPages,UINT *uPageCount) PURE; + }; + typedef IGroupPolicyObject *LPGROUPPOLICYOBJECT; diff --git a/driver/source/libwdi/libusb0.cat.in b/driver/source/libwdi/libusb0.cat.in new file mode 100644 index 00000000..ef0c2f2f --- /dev/null +++ b/driver/source/libwdi/libusb0.cat.in @@ -0,0 +1,8 @@ +# List of the binaries referenced by the libusb-win32 inf +# These are used to generate and self-sign a .cat file + +libusb0.sys +libusb0.dll +libusb0_x86.dll +#LK_DLL# +#LK_X86_DLL# \ No newline at end of file diff --git a/driver/source/libwdi/libusb0.inf.in b/driver/source/libwdi/libusb0.inf.in new file mode 100644 index 00000000..19f519b6 --- /dev/null +++ b/driver/source/libwdi/libusb0.inf.in @@ -0,0 +1,148 @@ +; #INF_FILENAME# +; Copyright (c) 2010 libusb-win32 (GNU LGPL) +[Strings] +DeviceName = "#DEVICE_DESCRIPTION#" +VendorName = "#DEVICE_MANUFACTURER#" +SourceName = "#DEVICE_DESCRIPTION# Install Disk" +DeviceID = "#DEVICE_HARDWARE_ID#" +DeviceGUID = "#DEVICE_INTERFACE_GUID#" + +[Version] +Signature = "$Windows NT$" +Class = "libusb-win32 devices" +ClassGuid = {EB781AAF-9C70-4523-A5DF-642A87ECA567} +Provider = "libusb-win32" +CatalogFile = #CAT_FILENAME# +DriverVer = #DRIVER_DATE#, #DRIVER_VERSION# + +[ClassInstall32] +Addreg = libusb_class_install_add_reg + +[libusb_class_install_add_reg] +HKR,,,0,"libusb-win32 devices" +HKR,,Icon,,-20 + +[Manufacturer] +%VendorName% = Devices, NT, NTAMD64, NTIA64 + +;-------------------------------------------------------------------------- +; libusb-win32 files +;-------------------------------------------------------------------------- + +[SourceDisksNames] +1 = %SourceName% + +[SourceDisksFiles.x86] +libusb0.sys = 1,x86 +libusb0_x86.dll = 1,x86 +#LK_X86_DLL# #LK_EQ_X86# + +[SourceDisksFiles.amd64] +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.ia64] +libusb0.sys = 1,ia64 +libusb0.dll = 1,ia64 + +[DestinationDirs] +libusb_files_sys = 10,system32\drivers +libusb_files_dll = 10,system32 +libusb_files_dll_wow64 = 10,syswow64 +libusb_files_dll_x86 = 10,system32 + +[libusb_files_sys] +libusb0.sys + +[libusb_files_dll] +libusb0.dll +#LK_DLL# + +[libusb_files_dll_x86] +libusb0.dll, libusb0_x86.dll #LK_COMMA# #LK_DLL# #LK_COMMA# #LK_X86_DLL# + +[libusb_files_dll_wow64] +libusb0.dll, libusb0_x86.dll #LK_COMMA# #LK_DLL# #LK_COMMA# #LK_X86_DLL# + +;-------------------------------------------------------------------------- +; libusb-win32 device driver +;-------------------------------------------------------------------------- + +[LIBUSB_WIN32_DEV.NT] +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.NTIA64] +CopyFiles = libusb_files_sys, libusb_files_dll, libusb_files_dll_wow64 + +[LIBUSB_WIN32_DEV.NT.HW] +DelReg = libusb_del_reg_hw +AddReg = libusb_add_reg_hw + +[LIBUSB_WIN32_DEV.NTAMD64.HW] +DelReg = libusb_del_reg_hw +AddReg = libusb_add_reg_hw + +[LIBUSB_WIN32_DEV.NTIA64.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.NTIA64.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] +HKR,,LowerFilters +HKR,,UpperFilters + +; libusb-win32 device properties +[libusb_add_reg_hw] +HKR,,SurpriseRemovalOK,0x00010001,1 +HKR,,DeviceInterfaceGUIDs,0x00010000,%DeviceGUID% + +; (Optional) the usb configuration value to select when this device +; is started. If this key does not exist the first config is selected. +;HKR,,InitialConfigValue,0x00010001, + +;-------------------------------------------------------------------------- +; libusb-win32 service +;-------------------------------------------------------------------------- + +[libusb_add_service] +DisplayName = "libusb-win32 - Kernel Driver #DRIVER_DATE# #DRIVER_VERSION#" +ServiceType = 1 +StartType = 3 +ErrorControl = 0 +ServiceBinary = %12%\libusb0.sys + +;-------------------------------------------------------------------------- +; libusb-win32 devices +;-------------------------------------------------------------------------- + +; Hardware IDs in a 'Devices' section can be installed by libusb-win32 +; using usb_install_driver_np(), usb_install_driver_np_rundll(), or the +; inf-wizard utility. +; +[Devices] +%DeviceName% = LIBUSB_WIN32_DEV, USB\%DeviceID% + +[Devices.NT] +%DeviceName% = LIBUSB_WIN32_DEV.NT, USB\%DeviceID% + +[Devices.NTAMD64] +%DeviceName% = LIBUSB_WIN32_DEV.NTAMD64, USB\%DeviceID% + +[Devices.NTIA64] +%DeviceName% = LIBUSB_WIN32_DEV.NTIA64, USB\%DeviceID% diff --git a/driver/source/libwdi/libusbk.cat.in b/driver/source/libwdi/libusbk.cat.in new file mode 100644 index 00000000..3daa508f --- /dev/null +++ b/driver/source/libwdi/libusbk.cat.in @@ -0,0 +1,9 @@ +# List of the binaries referenced by the libusbK inf +# These are used to generate and self-sign a .cat file + +WdfCoInstaller#WDF_VERSION#.dll +libusbk.sys +libusbk.dll +libusbk_x86.dll +libusb0.dll +libusb0_x86.dll \ No newline at end of file diff --git a/driver/source/libwdi/libusbk.inf.in b/driver/source/libwdi/libusbk.inf.in new file mode 100644 index 00000000..18ad74df --- /dev/null +++ b/driver/source/libwdi/libusbk.inf.in @@ -0,0 +1,153 @@ +; Copyright (c) 2011-2012 libusbK (GNU LGPL) +; +; Module Name: #INF_FILENAME# +; Description: Installation inf for #DEVICE_DESCRIPTION# device. +; +; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY +; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR +; PURPOSE. + +[Strings] +DeviceName = "#DEVICE_DESCRIPTION#" +VendorName = "#DEVICE_MANUFACTURER#" +SourceName = "#DEVICE_DESCRIPTION# Install Disk" +DeviceID = "#DEVICE_HARDWARE_ID#" +DeviceGUID = "#DEVICE_INTERFACE_GUID#" + +[Version] +Signature = "$Windows NT$" +Class = "libusbk devices" +ClassGuid = {ECFB0CFD-74C4-4f52-BBF7-343461CD72AC} +Provider = "libusbK" +CatalogFile = #CAT_FILENAME# +DriverVer = #DRIVER_DATE#, #DRIVER_VERSION# + +; ============== Class section ================== +[ClassInstall32] +Addreg = LUsbK_Class_AddReg + +[LUsbK_Class_AddReg] +HKR,,,0,"libusbK USB Devices" +HKR,,Icon,,-20 + +; ============== Device section ================= +[Manufacturer] +%VendorName% = LUsbK_DeviceGroup,NTX86,NTAMD64 + +; For Win2K +[LUsbK_DeviceGroup] +%DeviceName%=LUsbK_Device, USB\%DeviceID% + +; For XP and later +[LUsbK_DeviceGroup.NTX86] +%DeviceName%=LUsbK_Device, USB\%DeviceID% + +[LUsbK_DeviceGroup.NTAMD64] +%DeviceName%=LUsbK_Device, USB\%DeviceID% + +[LUsbK_Device.NT.HW] +AddReg=#USE_DEVICE_INTERFACE_GUID# + +[LUsbK_Device.NTAMD64.HW] +AddReg=#USE_DEVICE_INTERFACE_GUID# + +[NoDeviceInterfaceGUID] +; Avoids adding a DeviceInterfaceGUID for generic driver + +[AddDeviceInterfaceGUID] +HKR,,DeviceInterfaceGUIDs, 0x10000,%DeviceGUID% + +; ========== Driver/Servce section ============== +[LUsbK_Device.NT.Services] +Addservice=libusbK,2,LUsbK_AddService + +[LUsbK_Device.NTAMD64.Services] +Addservice=libusbK,2,LUsbK_AddService + +[LUsbK_AddService] +DisplayName="libusbK USB Driver #DRIVER_DATE# - #DRIVER_VERSION#" +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\libusbK.sys +AddReg=LUsbK_Driver_AddReg + +; This optional entry identifies the load order group of which this driver is a member. +; LoadOrderGroup=Base + +[LUsbK_Driver_AddReg] +HKR,"Parameters","DebugLevel",0x10001,4 + +; =========== Sources/Destinations ============== +[SourceDisksNames] +1 = %SourceName% + +[SourceDisksFiles.x86] +libusbK.sys = 1,x86 +libusbK.dll = 1,x86 +libusb0.dll = 1,x86 +;libusb-1.0.dll = 1,x86 +WdfCoInstaller#WDF_VERSION#.dll = 1,x86 + +[SourceDisksFiles.amd64] +libusbK.sys = 1,amd64 +libusbK.dll = 1,amd64 +libusbK_x86.dll = 1,amd64 +libusb0.dll = 1,amd64 +libusb0_x86.dll = 1,amd64 +;libusb-1.0.dll = 1,amd64 +;libusb-1.0_x86.dll = 1,amd64 +WdfCoInstaller#WDF_VERSION#.dll = 1,amd64 + +[DestinationDirs] +DefaultDestDir = 12 +CoInstaller_CopyFiles = 11 +libusb_files_sys = 10,system32\drivers +libusb_files_dll = 10,system32 +libusb_files_dll_syswow64 = 10,syswow64 + +; +; 0x00000040 = COPYFLG_OVERWRITE_OLDER_ONLY +; Copy the source file to the destination directory only if the file on +; the destination will be superseded by a newer version. +; + +[libusb_files_sys] +libusbK.sys + +[libusb_files_dll] +libusbK.dll +;libusb-1.0.dll,,,0x00000040 +libusb0.dll,,,0x00000040 + +[libusb_files_dll_syswow64] +libusbK.dll, libusbK_x86.dll +libusb0.dll, libusb0_x86.dll,,0x00000040 +;libusb-1.0.dll, libusb-1.0_x86.dll,,0x00000040 + +[LUsbK_Device.NT] +CopyFiles = libusb_files_sys, libusb_files_dll + +[LUsbK_Device.NTAMD64] +CopyFiles = libusb_files_sys, libusb_files_dll, libusb_files_dll_syswow64 + +; ========= WDF/CoInstaller section ============= +[LUsbK_Device.NT.CoInstallers] +AddReg=CoInstaller_AddReg +CopyFiles=CoInstaller_CopyFiles + +[CoInstaller_CopyFiles] +WdfCoInstaller#WDF_VERSION#.dll + +[CoInstaller_AddReg] +HKR,,CoInstallers32,0x00010000, "WdfCoInstaller#WDF_VERSION#.dll,WdfCoInstaller" + +[LUsbK_Device.NT.Wdf] +KmdfService = libusbK, LUsbK_wdfsect + +[LUsbK_Device.NTAMD64.Wdf] +KmdfService = libusbK, LUsbK_wdfsect + +[LUsbK_wdfsect] +KmdfLibraryVersion=#KMDF_VERSION# diff --git a/driver/source/libwdi/libwdi.c b/driver/source/libwdi/libwdi.c new file mode 100644 index 00000000..c59ada68 --- /dev/null +++ b/driver/source/libwdi/libwdi.c @@ -0,0 +1,1786 @@ +/* + * Library for USB automated driver installation + * Copyright (c) 2010-2016 Pete Batard + * Parts of the code from libusb by Daniel Drake, Johannes Erdfelt et al. + * 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 + * 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 + */ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "installer.h" +#include "libwdi.h" +#include "libwdi_i.h" +#include "logging.h" +#include "tokenizer.h" +#include "embedded.h" // auto-generated during compilation +#include "msapi_utf8.h" +#include "stdfn.h" + +// Global variables +static struct wdi_device_info *current_device = NULL; +static BOOL dlls_available = FALSE; +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* 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"}; +// for 64 bit platforms detection +static BOOL (__stdcall *pIsWow64Process)(HANDLE, PBOOL) = NULL; +int nWindowsVersion = WINDOWS_UNDEFINED; +char WindowsVersionStr[128] = "Windows "; + +// The following are only available on Vista and later +PF_TYPE_DECL(WINAPI, BOOL, IsUserAnAdmin, (void)); +PF_TYPE_DECL(WINAPI, BOOL, SetupDiGetDevicePropertyW, (HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY*, ULONG*, PBYTE, DWORD, PDWORD, DWORD)); +// Version +PF_TYPE_DECL(WINAPI, BOOL, VerQueryValueA, (LPCVOID, LPCSTR, LPVOID, PUINT)); +PF_TYPE_DECL(WINAPI, BOOL, GetFileVersionInfoA, (LPCSTR, DWORD, DWORD, LPVOID)); +PF_TYPE_DECL(WINAPI, BOOL, GetFileVersionInfoSizeA, (LPCSTR, LPDWORD)); +// Cfgmgr32 & SetupAPI interfaces +PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); +PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); +PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG)); +PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); +// This call is only available on XP and later +PF_TYPE_DECL(WINAPI, DWORD, CMP_WaitNoPendingInstallEvents, (DWORD)); + +// Detect Windows version +#define GET_WINDOWS_VERSION do{ if (nWindowsVersion == WINDOWS_UNDEFINED) GetWindowsVersion(); } while(0) + +BOOL is_x64(void) +{ + BOOL ret = FALSE; + PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process, (HANDLE, PBOOL)); + // Detect if we're running a 32 or 64 bit system + if (sizeof(uintptr_t) < 8) { + PF_INIT(IsWow64Process, Kernel32); + if (pfIsWow64Process != NULL) { + (*pfIsWow64Process)(GetCurrentProcess(), &ret); + } + } + else { + ret = TRUE; + } + return ret; +} + +// 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] = ""; + size_t vlen; + unsigned major, minor; + ULONGLONG major_equal, minor_equal; + BOOL ws; + + nWindowsVersion = WINDOWS_UNDEFINED; + safe_strcpy(WindowsVersionStr, sizeof(WindowsVersionStr), "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; + } + + 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 0x51: w = "XP"; + break; + case 0x52: w = (!GetSystemMetrics(89) ? "2003" : "2003_R2"); + break; + case 0x60: w = (ws ? "Vista" : "2008"); + break; + case 0x61: w = (ws ? "7" : "2008_R2"); + break; + case 0x62: w = (ws ? "8" : "2012"); + break; + case 0x63: w = (ws ? "8.1" : "2012_R2"); + break; + case 0x64: 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"); + break; + default: + if (nWindowsVersion < 0x51) + nWindowsVersion = WINDOWS_UNSUPPORTED; + else + w = "11 or later"; + break; + } + } + } + + if (is_x64()) + w64 = "64-bit"; + + 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); + else if (vi.wServicePackMinor) + safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); + else if (vi.wServicePackMajor) + safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64); + else + safe_sprintf(vptr, vlen, "%s %s", w, w64); + + // Add the build number for Windows 8.0 and later + 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), ")"); + } + } + +} +/* + * Converts a windows error to human readable string + * uses retval as errorcode, or, if 0, use GetLastError() + */ +char *windows_error_str(uint32_t retval) +{ +static char err_string[STR_BUFFER_SIZE]; + + DWORD size; + size_t i; + uint32_t error_code, format_error; + + error_code = retval?retval:GetLastError(); + + safe_sprintf(err_string, STR_BUFFER_SIZE, "[#%08X] ", error_code); + + 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); + 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); + else + safe_sprintf(err_string, STR_BUFFER_SIZE, "Unknown error code %u", 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; + } + } + 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) { + TOKEN_USER* tu = NULL; + DWORD len; + HANDLE token; + PSID ret = NULL; + char* psid_string = NULL; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { + wdi_err("OpenProcessToken failed: %s", 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)); + return NULL; + } + tu = (TOKEN_USER*)calloc(1, len); + } + if (tu == NULL) { + return NULL; + } + + if (GetTokenInformation(token, TokenUser, tu, len, &len)) { + /* + * now of course, the interesting thing is that if you return tu->User.Sid + * but free tu, the PSID pointer becomes invalid after a while. + * 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)); + ret = NULL; + } else { + if (!ConvertStringSidToSidA(psid_string, &ret)) { + wdi_err("unable to convert string back to SID: %s", windows_error_str(0)); + ret = NULL; + } + // MUST use LocalFree() + LocalFree(psid_string); + } + } else { + ret = NULL; + wdi_err("GetTokenInformation (real) failed: %s", windows_error_str(0)); + } + free(tu); + return ret; +} + +/* + * Check whether the path is a directory with write access + * if create is TRUE, create directory if it doesn't exist + */ +static int check_dir(const char* path, BOOL create) +{ + int r; + DWORD file_attributes; + PSID sid = NULL; + SECURITY_ATTRIBUTES s_attr, *ps = NULL; + SECURITY_DESCRIPTOR s_desc; + char* full_path; + + file_attributes = GetFileAttributesU(path); + if (file_attributes == INVALID_FILE_ATTRIBUTES) { + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + break; + default: + wdi_err("unable to read file attributes %s", windows_error_str(0)); + return WDI_ERROR_ACCESS; + } + } else { + if (file_attributes & FILE_ATTRIBUTE_DIRECTORY) { + // Directory exists + 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); + return WDI_ERROR_ACCESS; + } + } + + if (!create) { + wdi_err("%s doesn't exist", path); + return WDI_ERROR_ACCESS; + } + + // Change the owner from admin to regular user + sid = get_sid(); + if ( (sid != NULL) + && InitializeSecurityDescriptor(&s_desc, SECURITY_DESCRIPTOR_REVISION) + && SetSecurityDescriptorOwner(&s_desc, sid, FALSE) ) { + s_attr.nLength = sizeof(SECURITY_ATTRIBUTES); + s_attr.bInheritHandle = FALSE; + s_attr.lpSecurityDescriptor = &s_desc; + ps = &s_attr; + } else { + wdi_err("could not set security descriptor: %s", windows_error_str(0)); + } + + // SHCreateDirectoryEx creates subdirectories as required + r = SHCreateDirectoryExU(NULL, path, ps); + if (r == ERROR_BAD_PATHNAME) { + // 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"); + if (sid != NULL) LocalFree(sid); + return WDI_ERROR_RESOURCE; + } + GetCurrentDirectoryU(MAX_PATH, full_path); + safe_strcat(full_path, MAX_PATH, "\\"); + safe_strcat(full_path, MAX_PATH, path); + r = SHCreateDirectoryExU(NULL, full_path, ps); + free(full_path); + } + if (sid != NULL) LocalFree(sid); + + switch(r) { + case ERROR_SUCCESS: + return WDI_SUCCESS; + case ERROR_FILENAME_EXCED_RANGE: + wdi_err("directory name is too long %s", path); + return WDI_ERROR_INVALID_PARAM; + default: + wdi_err("unable to create directory %s (%s)", path, windows_error_str(0)); + return WDI_ERROR_ACCESS; + } + + return WDI_SUCCESS; +} + +/* + * fopen equivalent, that uses CreateFile with security attributes + * to create file as the user of the application + */ +static FILE *fcreate(const char *filename, const char *mode) +{ + HANDLE handle; + size_t i; + DWORD access_mode = 0; + SECURITY_ATTRIBUTES *ps = NULL; + int lowlevel_fd; + PSID sid = NULL; + SECURITY_ATTRIBUTES s_attr; + SECURITY_DESCRIPTOR s_desc; + + if ((filename == NULL) || (mode == NULL)) { + return NULL; + } + + // Simple mode handling. + for (i=0; i= WDI_USER) || (driver_info == NULL)) { + return WDI_ERROR_INVALID_PARAM; + } + + // No need to extract the version again if available + if (driver_version[driver_type].dwSignature != 0) { + memcpy(driver_info, &driver_version[driver_type], sizeof(VS_FIXEDFILEINFO)); + return WDI_SUCCESS; + } + + // Avoid the need for end user apps to link against version.lib + PF_INIT(VerQueryValueA, version.dll); + PF_INIT(GetFileVersionInfoA, version.dll); + PF_INIT(GetFileVersionInfoSizeA, version.dll); + if ((pfVerQueryValueA == NULL) || (pfGetFileVersionInfoA == NULL) || (pfGetFileVersionInfoSizeA == NULL)) { + wdi_warn("unable to access version.dll"); + return WDI_ERROR_RESOURCE; + } + + for (res=0; res extract it + tmpdir = getenv("TEMP"); + if (tmpdir == NULL) { + wdi_warn("unable to use TEMP to extract file"); + return WDI_ERROR_RESOURCE; + } + r = check_dir(tmpdir, TRUE); + if (r != WDI_SUCCESS) { + return r; + } + + safe_strcpy(filename, MAX_PATH, tmpdir); + safe_strcat(filename, MAX_PATH, "\\"); + if (resource[res].name != NULL) // Stupid Clang! + safe_strcat(filename, MAX_PATH, resource[res].name); + + fd = fcreate(filename, "w"); + if (fd == NULL) { + wdi_warn("failed to create file '%s' (%s)", filename, windows_error_str(0)); + return WDI_ERROR_RESOURCE; + } + + fwrite(resource[res].data, 1, resource[res].size, fd); + fclose(fd); + + // Read the version + version_size = pfGetFileVersionInfoSizeA(filename, NULL); + version_buf = malloc(version_size); + r = WDI_SUCCESS; + if ( (version_buf != NULL) + && (pfGetFileVersionInfoA(filename, 0, version_size, version_buf)) + && (pfVerQueryValueA(version_buf, "\\", (void*)&file_info, &junk)) ) { + // Fill the creation date of VS_FIXEDFILEINFO with the one from embedded.h + t = unixtime_to_msfiletime((time_t)resource[res].creation_time); + file_info->dwFileDateLS = (DWORD)t; + file_info->dwFileDateMS = t >> 32; + 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"); + r = WDI_ERROR_RESOURCE; + } + safe_free(version_buf); + DeleteFileU(filename); + + return r; +} + + +// Find out if the driver selected is actually embedded in this version of the library +BOOL LIBWDI_API wdi_is_driver_supported(int driver_type, VS_FIXEDFILEINFO* driver_info) +{ + if (driver_type < WDI_USER) { // github issue #40 + if (driver_type != WDI_CDC) { + // The CDC driver does not have embedded binaries + if (driver_info != NULL) { + memset(driver_info, 0, sizeof(VS_FIXEDFILEINFO)); + } + get_version_info(driver_type, driver_info); + } + } + + switch (driver_type) { + case WDI_WINUSB: +#if defined(DDK_DIR) + // WinUSB is not supported on Win2k/2k3 + GET_WINDOWS_VERSION; + if ( (nWindowsVersion < WINDOWS_XP) + || (nWindowsVersion == WINDOWS_2003) ) { + return FALSE; + } + return TRUE; +#else + return FALSE; +#endif + case WDI_LIBUSB0: +#if defined(LIBUSB0_DIR) + return TRUE; +#else + return FALSE; +#endif + case WDI_LIBUSBK: +#if defined(LIBUSBK_DIR) + return TRUE; +#else + return FALSE; +#endif + case WDI_USER: +#if defined(USER_DIR) + return TRUE; +#else + return FALSE; +#endif + case WDI_CDC: + return TRUE; + default: + wdi_err("unknown driver type"); + return FALSE; + } +} + +/* + * Find out if a file is embedded in the current libwdi resources + * path is the relative path for + */ +BOOL LIBWDI_API wdi_is_file_embedded(const char* path, const char* name) +{ + int i; + + for (i=0; idesc); + safe_free(di->driver); + safe_free(di->device_id); + safe_free(di->hardware_id); + safe_free(di->compatible_id); + safe_free(di->upper_filter); + safe_free(di); +} + +// Setup the Cfgmgr32 and SetupApi DLLs +static BOOL init_dlls(void) +{ + if (dlls_available) + return TRUE; + PF_INIT_OR_OUT(CM_Get_Parent, Cfgmgr32.dll); + PF_INIT_OR_OUT(CM_Get_Child, Cfgmgr32.dll); + PF_INIT_OR_OUT(CM_Get_Sibling, Cfgmgr32.dll); + PF_INIT_OR_OUT(CM_Get_Device_IDA, Cfgmgr32.dll); + PF_INIT_OR_OUT(CMP_WaitNoPendingInstallEvents, Setupapi.dll); + dlls_available = TRUE; + return TRUE; +out: + return FALSE; +} + +// List USB devices +int LIBWDI_API wdi_create_list(struct wdi_device_info** list, + struct wdi_options_create_list* options) +{ + unsigned i, j, tmp; + unsigned unknown_count = 1; + DWORD size, reg_type; + ULONG devprop_type; + CONFIGRET r; + HDEVINFO dev_info; + SP_DEVINFO_DATA dev_info_data; + HKEY key; + char *prefix[3] = {"VID_", "PID_", "MI_"}; + char *token, *end; + char strbuf[STR_BUFFER_SIZE], drv_version[] = "xxxxx.xxxxx.xxxxx.xxxxx"; + wchar_t desc[MAX_DESC_LENGTH]; + struct wdi_device_info *start = NULL, *cur = NULL, *device_info = NULL; + // NOTE: Don't forget to update the list of hubs in zadig.c (system_name[]) when adding new entries below + const char* usbhub_name[] = { "usbhub", "usbhub3", "usb3hub", "nusb3hub", "rusb3hub", "flxhcih", "tihub3", + "etronhub3", "viahub3", "asmthub3", "iusb3hub", "vusb3hub", "amdhub30", "vhhub" }; + const char usbccgp_name[] = "usbccgp"; + BOOL is_hub, is_composite_parent, has_vid; + + MUTEX_START; + *list = NULL; + + if (!init_dlls()) + MUTEX_RETURN(WDI_ERROR_RESOURCE); + + // List all connected USB devices + dev_info = SetupDiGetClassDevsA(NULL, "USB", NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); + if (dev_info == INVALID_HANDLE_VALUE) { + MUTEX_RETURN(WDI_ERROR_NO_DEVICE); + } + + // Find the ones that are driverless + for (i = 0; ; i++) + { + // Free any invalid previously allocated struct + free_di(device_info); + + dev_info_data.cbSize = sizeof(dev_info_data); + if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) { + break; + } + + // Allocate a driver_info struct to store our data + device_info = (struct wdi_device_info*)calloc(1, sizeof(struct wdi_device_info)); + if (device_info == NULL) { + wdi_destroy_list(start); + SetupDiDestroyDeviceInfoList(dev_info); + MUTEX_RETURN(WDI_ERROR_RESOURCE); + } + + // SPDRP_DRIVER seems to do a better job at detecting driverless devices than + // SPDRP_INSTALL_STATE + drv_version[0] = 0; + if (SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_DRIVER, + ®_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size)) { + if ((options == NULL) || (!options->list_all)) { + continue; + } + // While we have the driver key, pick up the driver version + key = SetupDiOpenDevRegKey(dev_info, &dev_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); + size = sizeof(drv_version); + if (key != INVALID_HANDLE_VALUE) { + RegQueryValueExA(key, "DriverVersion", NULL, ®_type, (BYTE*)drv_version, &size); + } + } + + // Eliminate USB hubs by checking the driver string + strbuf[0] = 0; + if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_SERVICE, + ®_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size)) { + device_info->driver = NULL; + } else { + device_info->driver = safe_strdup(strbuf); + } + is_hub = FALSE; + for (j=0; jlist_hubs))) { + continue; + } + // Also eliminate composite devices parent drivers, as replacing these drivers + // is a bad idea + is_composite_parent = FALSE; + if (safe_stricmp(strbuf, usbccgp_name) == 0) { + if ((options == NULL) || (!options->list_hubs)) { + continue; + } + is_composite_parent = TRUE; + } + + // Retrieve the first hardware ID + if (SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID, + ®_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size)) { + wdi_dbg("Hardware ID: %s", strbuf); + } else { + wdi_err("could not get hardware ID"); + strbuf[0] = 0; + } + // We assume that the first one (REG_MULTI_SZ) is the one we are interested in + device_info->hardware_id = safe_strdup(strbuf); + + // Retrieve the first Compatible ID + if (SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_COMPATIBLEIDS, + ®_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size)) { + wdi_dbg("Compatible ID: %s", strbuf); + } else { + strbuf[0] = 0; + } + // We assume that the first one (REG_MULTI_SZ) is the one we are interested in + device_info->compatible_id = safe_strdup(strbuf); + + // Lookup the upper filter + if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_UPPERFILTERS, + ®_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size)) { + device_info->upper_filter = NULL; + } else { + wdi_dbg("Upper filter: %s", strbuf); + device_info->upper_filter = safe_strdup(strbuf); + } + + // Convert driver version string to integer + device_info->driver_version = 0; + if (drv_version[0] != 0) { + wdi_dbg("Driver version: %s", drv_version); + token = strtok(drv_version, "."); + while (token != NULL) { + device_info->driver_version <<= 16; + device_info->driver_version += atoi(token); + token = strtok(NULL, "."); + } + } else if (device_info->driver != NULL) { + // Only produce a warning for non-driverless devices + wdi_warn("could not read driver version"); + } + + // Retrieve device ID. This is needed to re-enumerate our device and force + // the final driver installation + r = pfCM_Get_Device_IDA(dev_info_data.DevInst, strbuf, STR_BUFFER_SIZE, 0); + if (r != CR_SUCCESS) { + wdi_err("could not retrieve simple path for device %d: CR error %d", i, r); + continue; + } else { + wdi_dbg("%s USB device (%d): %s", + device_info->driver?device_info->driver:"Driverless", i, strbuf); + } + device_info->device_id = safe_strdup(strbuf); + + GET_WINDOWS_VERSION; + if (nWindowsVersion < WINDOWS_7) { + // On Vista and earlier, we can use SPDRP_DEVICEDESC + if (!SetupDiGetDeviceRegistryPropertyW(dev_info, &dev_info_data, SPDRP_DEVICEDESC, + ®_type, (BYTE*)desc, 2*MAX_DESC_LENGTH, &size)) { + wdi_warn("could not read device description for %d: %s", + i, windows_error_str(0)); + safe_swprintf(desc, MAX_DESC_LENGTH, L"Unknown Device #%d", unknown_count++); + } + } else { + // On Windows 7, the information we want ("Bus reported device description") is + // accessed through DEVPKEY_Device_BusReportedDeviceDesc + PF_INIT(SetupDiGetDevicePropertyW, setupapi.dll); + if (pfSetupDiGetDevicePropertyW == NULL) { + wdi_warn("failed to locate SetupDiGetDevicePropertyW() in Setupapi.dll"); + desc[0] = 0; + } else if (!pfSetupDiGetDevicePropertyW(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)); + safe_swprintf(desc, MAX_DESC_LENGTH, L"Unknown Device #%d", unknown_count++); + } + } + } + + device_info->is_composite = FALSE; // non composite by default + device_info->mi = 0; + token = strtok (strbuf, "\\#&"); + has_vid = FALSE; + while(token != NULL) { + for (j = 0; j < 3; j++) { + if (safe_strncmp(token, prefix[j], safe_strlen(prefix[j])) == 0) { + switch(j) { + case 0: + if (sscanf(token, "VID_%04X", &tmp) != 1) { + wdi_err("could not convert VID string"); + } else { + device_info->vid = (unsigned short)tmp; + } + has_vid = TRUE; + break; + case 1: + if (sscanf(token, "PID_%04X", &tmp) != 1) { + 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"); + } else { + device_info->is_composite = TRUE; + device_info->mi = (unsigned char)tmp; + if ((wcslen(desc) + sizeof(" (Interface ###)")) < MAX_DESC_LENGTH) { + _snwprintf(&desc[wcslen(desc)], sizeof(" (Interface ###)"), + L" (Interface %d)", device_info->mi); + } + } + break; + default: + wdi_err("unexpected case"); + break; + } + } + } + token = strtok (NULL, "\\#&"); + } + + // Eliminate root hubs (no VID/PID => 0 from calloc) + if ( (is_hub) && (!has_vid) ) { + continue; + } + + // Add a suffix for composite parents + if ( (is_composite_parent) + && ((wcslen(desc) + sizeof(" (Composite Parent)")) < MAX_DESC_LENGTH) ) { + _snwprintf(&desc[wcslen(desc)], sizeof(" (Composite Parent)"), + L" (Composite Parent)"); + } + + device_info->desc = wchar_to_utf8(desc); + + // Remove trailing whitespaces + if ((device_info->desc != NULL) && (options != NULL) && (options->trim_whitespaces)) { + end = device_info->desc + safe_strlen(device_info->desc); + while ((end != device_info->desc) && isspace(*(end-1))) { + --end; + } + *end = 0; + } + + wdi_dbg("Device description: '%s'", device_info->desc); + + // Only at this stage do we know we have a valid current element + if (cur == NULL) { + start = device_info; + } else { + cur->next = device_info; + } + cur = device_info; + // Ensure that we don't free a valid structure + device_info = NULL; + } + + SetupDiDestroyDeviceInfoList(dev_info); + + *list = start; + MUTEX_RETURN((*list==NULL)?WDI_ERROR_NO_DEVICE:WDI_SUCCESS); +} + +int LIBWDI_API wdi_destroy_list(struct wdi_device_info* list) +{ + struct wdi_device_info *tmp; + + MUTEX_START; + + while(list != NULL) { + tmp = list; + list = list->next; + free_di(tmp); + } + MUTEX_RETURN(WDI_SUCCESS); +} + +// extract the embedded binary resources +static int extract_binaries(const char* path) +{ + FILE *fd; + char filename[MAX_PATH]; + int i, r; + + for (i=0; i (MAX_PATH - 3)) { + wdi_err("qualified path is too long: '%s'", filename); + return WDI_ERROR_RESOURCE; + } + + fd = fcreate(filename, "w"); + if (fd == NULL) { + wdi_err("failed to create file '%s' (%s)", filename, windows_error_str(0)); + return WDI_ERROR_RESOURCE; + } + + fwrite(resource[i].data, 1, resource[i].size, fd); + fclose(fd); + } + + 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) +{ + int i; + + for (i=0; idriver_type; + } + + // Ensure driver_type is what we expect + if ( (driver_type < 0) || (driver_type > WDI_USER) ) { + wdi_err("unknown type"); + MUTEX_RETURN(WDI_ERROR_INVALID_PARAM); + } + + 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"); + MUTEX_RETURN(WDI_ERROR_INVALID_PARAM); + } + + r = extract_binaries(path); + if (r != WDI_SUCCESS) { + MUTEX_RETURN(r); + } + + // Populate the inf and cat names & paths + if ( (strlen(path) >= MAX_PATH) || (strlen(inf_name) >= MAX_PATH) || + ((strlen(path) + strlen(inf_name)) > (MAX_PATH - 2)) ) { + wdi_err("qualified path for inf file is too long: '%s\\%s", path, inf_name); + MUTEX_RETURN(WDI_ERROR_RESOURCE); + } + safe_strcpy(inf_path, sizeof(inf_path), path); + safe_strcat(inf_path, sizeof(inf_path), "\\"); + safe_strcat(inf_path, sizeof(inf_path), inf_name); + safe_strcpy(cat_path, sizeof(cat_path), inf_path); + cat_path[safe_strlen(cat_path)-3] = 'c'; + cat_path[safe_strlen(cat_path)-2] = 'a'; + cat_path[safe_strlen(cat_path)-1] = 't'; + + static_strcpy(inf_entities[INF_FILENAME].replace, inf_name); + cat_name = safe_strdup(inf_name); + if (cat_name == NULL) { + MUTEX_RETURN(WDI_ERROR_RESOURCE); + } + cat_name[safe_strlen(inf_name)-3] = 'c'; + cat_name[safe_strlen(inf_name)-2] = 'a'; + cat_name[safe_strlen(inf_name)-1] = 't'; + static_strcpy(inf_entities[CAT_FILENAME].replace, cat_name); + safe_free(cat_name); + + // Populate the Device Description and Hardware ID + if ((options != NULL) && (options->device_name != NULL)) { + static_strcpy(inf_entities[DEVICE_DESCRIPTION].replace, options->device_name); + } + else { + static_strcpy(inf_entities[DEVICE_DESCRIPTION].replace, device_info->desc); + } + if ((options != NULL) && (options->use_wcid_driver)) { + static_strcpy(inf_entities[DEVICE_HARDWARE_ID].replace, ms_compat_id[driver_type]); + static_strcpy(inf_entities[USE_DEVICE_INTERFACE_GUID].replace, "NoDeviceInterfaceGUID"); + } else { + if (device_info->is_composite) { + static_sprintf(inf_entities[DEVICE_HARDWARE_ID].replace, "VID_%04X&PID_%04X&MI_%02X", + device_info->vid, device_info->pid, device_info->mi); + } else { + static_sprintf(inf_entities[DEVICE_HARDWARE_ID].replace, "VID_%04X&PID_%04X", + device_info->vid, device_info->pid); + } + static_strcpy(inf_entities[USE_DEVICE_INTERFACE_GUID].replace, "AddDeviceInterfaceGUID"); + } + + // Find out if we have an Android device + for (i=0; ivid) && (android_device[i].pid == device_info->pid)) { + is_android_device = TRUE; + break; + } + } + + // Populate the Device Interface GUID + if ((options != NULL) && (options->use_wcid_driver)) { + strguid = "UNUSED"; + } else if ((options != NULL) && (options->device_guid != NULL)) { + strguid = options->device_guid; + } else if (is_android_device) { + wdi_info("using Android Device Interface GUID"); + strguid = (char*)android_device_guid; + } else { + IGNORE_RETVAL(CoCreateGuid(&guid)); + strguid = guid_to_string(guid); + } + static_sprintf(inf_entities[DEVICE_INTERFACE_GUID].replace, "%s", strguid); + + // Resolve the Manufacturer (Vendor Name) + if ((options != NULL) && (options->vendor_name != NULL)) { + static_strcpy(inf_entities[DEVICE_MANUFACTURER].replace, options->vendor_name); + } else { + vendor_name = wdi_get_vendor_name(device_info->vid); + if (vendor_name == NULL) { + vendor_name = "(Undefined Vendor)"; + } + static_strcpy(inf_entities[DEVICE_MANUFACTURER].replace, vendor_name); + } + + // Set the WDF and KMDF versions for WinUSB and libusbK + static_sprintf(inf_entities[WDF_VERSION].replace, "%05d", WDF_VER); + static_sprintf(inf_entities[KMDF_VERSION].replace, "%d.%d", WDF_VER/1000, WDF_VER%1000); + + // 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"); + MUTEX_RETURN(WDI_ERROR_OTHER); + } + + // Write the date and version data + file_time.dwHighDateTime = driver_version[driver_type].dwFileDateMS; + file_time.dwLowDateTime = driver_version[driver_type].dwFileDateLS; + if ( ((file_time.dwHighDateTime == 0) && (file_time.dwLowDateTime == 0)) + || (!FileTimeToLocalFileTime(&file_time, &local_time)) + || (!FileTimeToSystemTime(&local_time, &system_time)) ) { + GetLocalTime(&system_time); + } + static_sprintf(inf_entities[DRIVER_DATE].replace, + "%02d/%02d/%04d", system_time.wMonth, system_time.wDay, system_time.wYear); + static_sprintf(inf_entities[DRIVER_VERSION].replace, "%d.%d.%d.%d", + (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) { + fd = fcreate(inf_path, "w"); + if (fd == NULL) { + wdi_err("failed to create file: %s", inf_path); + MUTEX_RETURN(WDI_ERROR_ACCESS); + } + // Converting to UTF-16 is the only way to get devices using a + // 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); + safe_free(dst); + MUTEX_RETURN(WDI_ERROR_RESOURCE); + } + fwrite(&bom, 2, 1, fd); // Write the BOM + fwrite(wdst, 2, wcslen(wdst), fd); + fclose(fd); + safe_free(wdst); + safe_free(dst); + } else { + wdi_err("could not tokenize inf file (%d)", inf_file_size); + MUTEX_RETURN(WDI_ERROR_ACCESS); + } + wdi_info("successfully created '%s'", inf_path); + + GET_WINDOWS_VERSION; + PF_INIT(IsUserAnAdmin, shell32.dll); + if ( (nWindowsVersion >= WINDOWS_VISTA) && (pfIsUserAnAdmin != NULL) && (pfIsUserAnAdmin()) ) { + // On Vista and later, try to create and self-sign the cat file to remove security prompts + if ((options != NULL) && (options->disable_cat)) { + wdi_info(".cat generation disabled by user"); + MUTEX_RETURN(WDI_SUCCESS); + } + wdi_info("Vista or later detected - creating and self-signing a .cat file..."); + + // Tokenize the cat file (for WDF version) + if ((cat_file_size = tokenize_internal(cat_template[driver_type], + &dst, inf_entities, "#", "#", 0)) <= 0) { + wdi_err("could not tokenize inf file (%d)", inf_file_size); + MUTEX_RETURN(WDI_ERROR_ACCESS); + } + + // Build the filename list + nb_entries = 0; + token = strtok(dst, "\n\r"); + do { + // Eliminate leading, trailing spaces & comments (#...) + while (isspace(*token)) token++; + while (strlen(token) && isspace(token[strlen(token)-1])) + token[strlen(token)-1] = 0; + 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); + break; + } + } while ((token = strtok(NULL, "\n\r")) != NULL); + + // Add the inf name to our list + 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))? + ms_compat_id[driver_type]:inf_entities[DEVICE_HARDWARE_ID].replace); + sprintf(cert_subject, "CN=%s (libwdi autogenerated)", hw_id); + + // Failures on the following aren't fatal errors + if (!CreateCat(cat_path, hw_id, path, cat_list, nb_entries)) { + 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"); + } + safe_free(cat_in_copy); + safe_free(dst); + } else { + wdi_info("No .cat file generated (not running Vista or later, or missing elevated privileges)"); + } + MUTEX_RETURN(WDI_SUCCESS); +} + +// Handle messages received from the elevated installer through the pipe +static int process_message(char* buffer, DWORD size) +{ + DWORD tmp; + char* sid_str; + + if (size <= 0) + return WDI_ERROR_INVALID_PARAM; + + if (current_device == NULL) { + wdi_err("program assertion failed - no current device"); + return WDI_ERROR_NOT_FOUND; + } + + if (filter_driver) { + // In filter driver mode, we just do I/O redirection + if (size > 0) { + buffer[size] = 0; + wdi_log(WDI_LOG_LEVEL_INFO, "install-filter", "%s", buffer); + } + return WDI_SUCCESS; + } + + // Note: this is a message pipe, so we don't need to care about + // multiple messages coexisting in our buffer. + switch(buffer[0]) + { + case IC_GET_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"); + WriteFile(pipe_handle, "\0", 1, &tmp, NULL); + } + break; + case IC_GET_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"); + WriteFile(pipe_handle, "\0", 1, &tmp, NULL); + } + break; + case IC_PRINT_MESSAGE: + if (size < 2) { + 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"); + 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"); + return WDI_ERROR_NOT_FOUND; + } + return (int)buffer[1]; + break; + case IC_SET_TIMEOUT_INFINITE: + wdi_dbg("switching timeout to infinite"); + timeout = INFINITE; + break; + case IC_SET_TIMEOUT_DEFAULT: + wdi_dbg("switching timeout back to finite"); + timeout = DEFAULT_TIMEOUT; + break; + case IC_INSTALLER_COMPLETED: + wdi_dbg("installer process completed"); + break; + case IC_GET_USER_SID: + if (ConvertSidToStringSidA(get_sid(), &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"); + WriteFile(pipe_handle, "\0", 1, &tmp, NULL); + } + break; + default: + wdi_err("unrecognized installer message"); + return WDI_ERROR_NOT_FOUND; + } + return WDI_SUCCESS; +} + +// Run the elevated installer +static int install_driver_internal(void* arglist) +{ + struct install_driver_params* params = (struct install_driver_params*)arglist; + SHELLEXECUTEINFOA shExecInfo; + 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; + char *buffer = NULL, *new_buffer; + const char* filter_name = "libusb0"; + + MUTEX_START; + + if (!init_dlls()) + MUTEX_RETURN(WDI_ERROR_RESOURCE); + + current_device = params->device_info; + filter_driver = FALSE; + if (params->options != NULL) + filter_driver = params->options->install_filter_driver; + + // Try to use the user's temp dir if no path is provided + if ((params->path == NULL) || (params->path[0] == 0)) { + static_strcpy(path, getenv("TEMP")); + 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"); + MUTEX_RETURN(WDI_ERROR_INVALID_PARAM); + } + + // 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"); + MUTEX_RETURN(WDI_ERROR_PENDING_INSTALLATION); + } + } else { + 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 + pIsWow64Process = (BOOL (__stdcall *)(HANDLE, PBOOL)) + GetProcAddress(GetDLLHandle("kernel32.dll"), "IsWow64Process"); + if (pIsWow64Process != NULL) { + (*pIsWow64Process)(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)); + r = WDI_ERROR_RESOURCE; goto out; + } + + // Set the overlapped for messaging + memset(&overlapped, 0, sizeof(OVERLAPPED)); + handle[0] = CreateEvent(NULL, TRUE, FALSE, NULL); + if(handle[0] == NULL) { + r = WDI_ERROR_RESOURCE; goto out; + } + 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 + // 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); + } else { + // Use libusb-win32's filter driver installer + safe_sprintf(exename, sizeof(exename), "\"%s\\%s\\\\install-filter.exe\"", path, is_x64?"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="); + } else { + static_strcpy(exeargs, "install -d="); + } + static_strcat(exeargs, params->device_info->hardware_id); + // We need to get a handle to the other end of the pipe for redirection + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; // REQUIRED for STDIO redirection + sa.lpSecurityDescriptor = NULL; + 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)); + r = WDI_ERROR_RESOURCE; goto out; + } + } + // At this stage, if either the 32 or 64 bit installer version 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; + } + + GET_WINDOWS_VERSION; + PF_INIT(IsUserAnAdmin, shell32.dll); + if ( (nWindowsVersion >= WINDOWS_VISTA) && (pfIsUserAnAdmin != NULL) && (pfIsUserAnAdmin()) ) { + // On Vista and later, we must 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.lpParameters = exeargs; + shExecInfo.lpDirectory = path; + shExecInfo.lpClass = NULL; + shExecInfo.nShow = SW_HIDE; + shExecInfo.hInstApp = NULL; + + err = ERROR_SUCCESS; + if (!ShellExecuteExU(&shExecInfo)) { + err = GetLastError(); + } + + switch(err) { + case ERROR_SUCCESS: + break; + case ERROR_CANCELLED: + wdi_info("operation cancelled by the user"); + r = WDI_ERROR_USER_CANCEL; goto out; + case ERROR_FILE_NOT_FOUND: + wdi_info("could not find installer executable"); + r = WDI_ERROR_NOT_FOUND; goto out; + default: + wdi_err("ShellExecuteEx failed: %s", windows_error_str(err)); + r = WDI_ERROR_NEEDS_ADMIN; goto out; + } + + handle[1] = shExecInfo.hProcess; + } else { + // On XP and earlier, or if app is already elevated, simply use CreateProcess + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + if (filter_driver) { + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = stdout_w; + si.hStdError = stdout_w; + } + + memset(&pi, 0, sizeof(pi)); + + 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)); + r = WDI_ERROR_NEEDS_ADMIN; goto out; + } + handle[1] = pi.hProcess; + handle[2] = pi.hThread; // MSDN indicates to also close this handle when done + } + + r = WDI_SUCCESS; + offset = 0; + buffer = (char*)malloc(bufsize); + if (buffer == NULL) { + wdi_err("unable to alloc buffer: aborting"); + r = WDI_ERROR_RESOURCE; goto out; + } + + while (r == WDI_SUCCESS) { + to_read = bufsize-offset; // rd_count is useless on sync (reset to 0) + if (ReadFile(pipe_handle, &buffer[offset], to_read, &rd_count, &overlapped)) { + offset = 0; + // Message was read synchronously + r = process_message(buffer, rd_count); + } else { + switch(GetLastError()) { + case ERROR_BROKEN_PIPE: + // The pipe has been ended - wait for installer to finish + if ((WaitForSingleObject(handle[1], timeout) == WAIT_TIMEOUT)) { + TerminateProcess(handle[1], 0); + } + r = check_completion(handle[1]); goto out; + case ERROR_PIPE_LISTENING: + // Wait for installer to open the pipe + Sleep(100); + continue; + case ERROR_IO_PENDING: + switch(WaitForMultipleObjects(2, handle, FALSE, timeout)) { + case WAIT_OBJECT_0: // Pipe event + if (GetOverlappedResult(pipe_handle, &overlapped, &rd_count, FALSE)) { + // Message was read asynchronously + r = process_message(buffer, rd_count); + offset = 0; + } else { + switch(GetLastError()) { + case ERROR_BROKEN_PIPE: + // The pipe has been ended - wait for installer to finish + if ((WaitForSingleObject(handle[1], timeout) == WAIT_TIMEOUT)) { + TerminateProcess(handle[1], 0); + } + 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); + new_buffer = (char*)realloc(buffer, bufsize); + if (new_buffer == NULL) { + wdi_err("unable to realloc buffer: aborting"); + r = WDI_ERROR_RESOURCE; + } else { + buffer = new_buffer; + offset += to_read; + } + break; + default: + wdi_err("could not read from pipe (async): %s", windows_error_str(0)); + break; + } + } + break; + case WAIT_TIMEOUT: + // Lost contact + 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)); + break; + } + break; + case ERROR_MORE_DATA: + bufsize *= 2; + wdi_dbg("message overflow (sync) - increasing buffer size to %d bytes", bufsize); + new_buffer = (char*)realloc(buffer, bufsize); + if (new_buffer == NULL) { + wdi_err("unable to realloc buffer: aborting"); + r = WDI_ERROR_RESOURCE; + } else { + buffer = new_buffer; + offset += to_read; + } + break; + default: + wdi_err("could not read from pipe (sync): %s", windows_error_str(0)); + break; + } + } + } +out: + // If the security prompt is still active, attempt to destroy it + DestroyWindow(find_security_prompt()); + current_device = NULL; + safe_free(buffer); + safe_closehandle(handle[2]); + safe_closehandle(handle[1]); + safe_closehandle(handle[0]); + safe_closehandle(pipe_handle); + safe_closehandle(stdout_w); + MUTEX_RETURN(r); +} + +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) +{ + struct install_driver_params params; + params.device_info = device_info; + params.inf_name = inf_name; + params.options = options; + params.path = path; + + if ((options == NULL) || (options->hWnd == NULL)) { + wdi_dbg("using standard mode"); + return install_driver_internal((void*)¶ms); + } + wdi_dbg("using progress bar mode"); + return run_with_progress_bar(options->hWnd, install_driver_internal, (void*)¶ms); +} + +// Install a driver signing certificate to the Trusted Publisher system store +// This allows promptless installation if you also provide a signed inf/cat pair +int LIBWDI_API wdi_install_trusted_certificate(const char* cert_name, + struct wdi_options_install_cert* options) +{ + int i; + HWND hWnd = NULL; + BOOL disable_warning = FALSE; + + GET_WINDOWS_VERSION; + + if (safe_strlen(cert_name) == 0) { + return WDI_ERROR_INVALID_PARAM; + } + + PF_INIT(IsUserAnAdmin, shell32.dll); + if ( (nWindowsVersion < WINDOWS_VISTA) || ((pfIsUserAnAdmin != NULL) && (pfIsUserAnAdmin())) ) { + for (i=0; ihWnd; + disable_warning = options->disable_warning; + } + + 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); + return WDI_ERROR_RESOURCE; + } + wdi_info("certificate '%s' successfully added as Trusted Publisher", cert_name); + return WDI_SUCCESS; + } + + wdi_err("this call must be run with elevated privileges on Vista and later"); + return WDI_ERROR_NEEDS_ADMIN; +} + +// Return the WDF version used by the native drivers +int LIBWDI_API wdi_get_wdf_version(void) +{ +#if defined(WDF_VER) + return WDF_VER; +#else + return -1; +#endif +} diff --git a/driver/source/libwdi/libwdi.def b/driver/source/libwdi/libwdi.def new file mode 100644 index 00000000..ce4cf41c --- /dev/null +++ b/driver/source/libwdi/libwdi.def @@ -0,0 +1,72 @@ +LIBRARY "libwdi.dll" +EXPORTS + wdi_is_driver_supported + wdi_is_file_embedded + wdi_strerror + wdi_create_list + wdi_destroy_list + wdi_prepare_driver + wdi_install_driver + wdi_install_trusted_certificate + wdi_get_wdf_version + wdi_get_vendor_name + wdi_register_logger + wdi_unregister_logger + wdi_read_logger + wdi_set_log_level + wdi_is_driver_supported@4 = wdi_is_driver_supported + wdi_is_file_embedded@4 = wdi_is_file_embedded + wdi_strerror@4 = wdi_strerror + wdi_create_list@4 = wdi_create_list + wdi_destroy_list@4 = wdi_destroy_list + wdi_prepare_driver@4 = wdi_prepare_driver + wdi_install_driver@4 = wdi_install_driver + wdi_install_trusted_certificate@4 = wdi_install_trusted_certificate + wdi_get_wdf_version@4 = wdi_get_wdf_version + wdi_get_vendor_name@4 = wdi_get_vendor_name + wdi_register_logger@4 = wdi_register_logger + wdi_unregister_logger@4 = wdi_unregister_logger + wdi_read_logger@4 = wdi_read_logger + wdi_set_log_level@4 = wdi_set_log_level + wdi_is_driver_supported@8 = wdi_is_driver_supported + wdi_is_file_embedded@8 = wdi_is_file_embedded + wdi_strerror@8 = wdi_strerror + wdi_create_list@8 = wdi_create_list + wdi_destroy_list@8 = wdi_destroy_list + wdi_prepare_driver@8 = wdi_prepare_driver + wdi_install_driver@8 = wdi_install_driver + wdi_install_trusted_certificate@8 = wdi_install_trusted_certificate + wdi_get_wdf_version@8 = wdi_get_wdf_version + wdi_get_vendor_name@8 = wdi_get_vendor_name + wdi_register_logger@8 = wdi_register_logger + wdi_unregister_logger@8 = wdi_unregister_logger + wdi_read_logger@8 = wdi_read_logger + wdi_set_log_level@8 = wdi_set_log_level + wdi_is_driver_supported@12 = wdi_is_driver_supported + wdi_is_file_embedded@12 = wdi_is_file_embedded + wdi_strerror@12 = wdi_strerror + wdi_create_list@12 = wdi_create_list + wdi_destroy_list@12 = wdi_destroy_list + wdi_prepare_driver@12 = wdi_prepare_driver + wdi_install_driver@12 = wdi_install_driver + wdi_install_trusted_certificate@12 = wdi_install_trusted_certificate + wdi_get_wdf_version@12 = wdi_get_wdf_version + wdi_get_vendor_name@12 = wdi_get_vendor_name + wdi_register_logger@12 = wdi_register_logger + wdi_unregister_logger@12 = wdi_unregister_logger + wdi_read_logger@12 = wdi_read_logger + wdi_set_log_level@12 = wdi_set_log_level + wdi_is_driver_supported@16 = wdi_is_driver_supported + wdi_is_file_embedded@16 = wdi_is_file_embedded + wdi_strerror@16 = wdi_strerror + wdi_create_list@16 = wdi_create_list + wdi_destroy_list@16 = wdi_destroy_list + wdi_prepare_driver@16 = wdi_prepare_driver + wdi_install_driver@16 = wdi_install_driver + wdi_install_trusted_certificate@16 = wdi_install_trusted_certificate + wdi_get_wdf_version@16 = wdi_get_wdf_version + wdi_get_vendor_name@16 = wdi_get_vendor_name + wdi_register_logger@16 = wdi_register_logger + wdi_unregister_logger@16 = wdi_unregister_logger + wdi_read_logger@16 = wdi_read_logger + wdi_set_log_level@16 = wdi_set_log_level diff --git a/driver/source/libwdi/libwdi.h b/driver/source/libwdi/libwdi.h new file mode 100644 index 00000000..31393b1f --- /dev/null +++ b/driver/source/libwdi/libwdi.h @@ -0,0 +1,307 @@ +/* + * Library for USB automated driver installation + * Copyright (c) 2010-2016 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 + * 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 + */ +#pragma once +#include + +/* + * Maximum length for any string used by libwdi structures + */ +#define WDI_MAX_STRLEN 200 + +#if defined(DLL_EXPORT) +#define LIBWDI_EXP __declspec(dllexport) +#else +#define LIBWDI_EXP +#endif + +/* + * Set the default calling convention to WINAPI (__stdcall) + */ +#if !defined(LIBWDI_API) +#define LIBWDI_API WINAPI +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Type of driver to install + */ +enum wdi_driver_type { + WDI_WINUSB, + WDI_LIBUSB0, + WDI_LIBUSBK, + WDI_CDC, + WDI_USER, + WDI_NB_DRIVERS // Total number of drivers in the enum +}; + +/* + * Log level + */ +enum wdi_log_level { + WDI_LOG_LEVEL_DEBUG, + WDI_LOG_LEVEL_INFO, + WDI_LOG_LEVEL_WARNING, + WDI_LOG_LEVEL_ERROR, + WDI_LOG_LEVEL_NONE +}; + +/* + * Error codes. Most libwdi functions return 0 on success or one of these + * codes on failure. + * You can use wdi_strerror() to retrieve a short string description of + * a wdi_error enumeration value. + */ +enum wdi_error { + /** Success (no error) */ + WDI_SUCCESS = 0, + + /** Input/output error */ + WDI_ERROR_IO = -1, + + /** Invalid parameter */ + WDI_ERROR_INVALID_PARAM = -2, + + /** Access denied (insufficient permissions) */ + WDI_ERROR_ACCESS = -3, + + /** No such device (it may have been disconnected) */ + WDI_ERROR_NO_DEVICE = -4, + + /** Entity not found */ + WDI_ERROR_NOT_FOUND = -5, + + /** Resource busy, or API call already running */ + WDI_ERROR_BUSY = -6, + + /** Operation timed out */ + WDI_ERROR_TIMEOUT = -7, + + /** Overflow */ + WDI_ERROR_OVERFLOW = -8, + + /** Another installation is pending */ + WDI_ERROR_PENDING_INSTALLATION = -9, + + /** System call interrupted (perhaps due to signal) */ + WDI_ERROR_INTERRUPTED = -10, + + /** Could not acquire resource (Insufficient memory, etc) */ + WDI_ERROR_RESOURCE = -11, + + /** Operation not supported or unimplemented on this platform */ + WDI_ERROR_NOT_SUPPORTED = -12, + + /** Entity already exists */ + WDI_ERROR_EXISTS = -13, + + /** Cancelled by user */ + WDI_ERROR_USER_CANCEL = -14, + + /** Couldn't run installer with required privileges */ + WDI_ERROR_NEEDS_ADMIN = -15, + + /** Attempted to run the 32 bit installer on 64 bit */ + WDI_ERROR_WOW64 = -16, + + /** Bad inf syntax */ + WDI_ERROR_INF_SYNTAX = -17, + + /** Missing cat file */ + WDI_ERROR_CAT_MISSING = -18, + + /** System policy prevents the installation of unsigned drivers */ + WDI_ERROR_UNSIGNED = -19, + + /** Other error */ + WDI_ERROR_OTHER = -99 + + /** IMPORTANT: when adding new values to this enum, remember to + update the wdi_strerror() function implementation! */ +}; + + +/* + * Device information structure, used by libwdi functions + */ +struct wdi_device_info { + /** (Optional) Pointer to the next element in the chained list. NULL if unused */ + struct wdi_device_info *next; + /** USB VID */ + unsigned short vid; + /** USB PID */ + unsigned short pid; + /** Whether the USB device is composite */ + BOOL is_composite; + /** (Optional) Composite USB interface number */ + unsigned char mi; + /** USB Device description, usually provided by the device itself */ + char* desc; + /** Windows' driver (service) name */ + char* driver; + /** (Optional) Microsoft's device URI string. NULL if unused */ + char* device_id; + /** (Optional) Microsoft's Hardware ID string. NULL if unused */ + char* hardware_id; + /** (Optional) Microsoft's Compatible ID string. NULL if unused */ + char* compatible_id; + /** (Optional) Upper filter. NULL if unused */ + char* upper_filter; + /** (Optional) Driver version (four WORDS). 0 if unused */ + UINT64 driver_version; +}; + +/* + * Optional settings, used by libwdi functions + */ + +// wdi_create_list options +struct wdi_options_create_list { + /** list all devices, instead of just the ones that are driverless */ + BOOL list_all; + /** also list generic hubs and composite parent devices */ + BOOL list_hubs; + /** trim trailing whitespaces from the description string */ + BOOL trim_whitespaces; +}; + +// wdi_prepare_driver options: +struct wdi_options_prepare_driver { + /** Type of driver to use. Should be either WDI_WINUSB, WDI_LIBUSB, WDI_LIBUSBK or WDI_USER */ + int driver_type; + /** Device name that should be used for the DeviceName in the inf */ + char* device_name; + /** Vendor name that should be used for the Manufacturer in the inf */ + char* vendor_name; + /** Device GUID (with braces) that should be used, instead of the automatically generated one */ + char* device_guid; + /** Disable the generation of a cat file for libusbK, libusb0 or WinUSB drivers */ + BOOL disable_cat; + /** Disable the signing and installation of a self-signed certificate, for libusbK, libusb0 or WinUSB drivers */ + BOOL disable_signing; + /** Subject to use for the self-signing autogenerated certificate. + * default is "CN=USB\VID_####&PID_####[&MI_##] (libwdi autogenerated)" */ + char* cert_subject; + /** Install a generic driver, for WCID devices, to allow for automated installation */ + BOOL use_wcid_driver; +}; + +// wdi_install_driver options: +struct wdi_options_install_driver { + /** Handle to a Window application that should receive a modal progress dialog */ + HWND hWnd; + /** Install a filter driver instead of a regular driver (libusb-win32 only) */ + BOOL install_filter_driver; + /** Number of milliseconds to wait for any pending installations */ + UINT32 pending_install_timeout; +}; + +// wdi_install_trusted_certificate options: +struct wdi_options_install_cert { + /** handle to a Window application that can receive a modal progress dialog */ + HWND hWnd; + /** Should the warning about a Trusted Publisher installation be disabled? */ + BOOL disable_warning; +}; + +/* + * Convert a libwdi error to a human readable error message + */ +LIBWDI_EXP const char* LIBWDI_API wdi_strerror(int errcode); + +/* + * Check if a specific driver is supported (embedded) in the current libwdi binary + */ +LIBWDI_EXP BOOL LIBWDI_API wdi_is_driver_supported(int driver_type, VS_FIXEDFILEINFO* driver_info); + +/* + * Check if a specific file is embedded in the current libwdi binary + * path is the relative path that would be used for extraction and can be NULL, + * in which case any instance of "name" will return true, no matter the extraction path + */ +LIBWDI_EXP BOOL LIBWDI_API wdi_is_file_embedded(const char* path, const char* name); + +/* + * Retrieve the full Vendor name from a Vendor ID (VID) + */ +LIBWDI_EXP const char* LIBWDI_API wdi_get_vendor_name(unsigned short vid); + +/* + * Return a wdi_device_info list of USB devices + * parameter: driverless_only - boolean + */ +LIBWDI_EXP int LIBWDI_API wdi_create_list(struct wdi_device_info** list, + struct wdi_options_create_list* options); + +/* + * Release a wdi_device_info list allocated by the previous call + */ +LIBWDI_EXP int LIBWDI_API wdi_destroy_list(struct wdi_device_info* list); + +/* + * Create an inf file for a specific device + */ +LIBWDI_EXP 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); + +/* + * Install a driver for a specific device + */ +LIBWDI_EXP 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); + +/* + * Install a code signing certificate (from embedded resources) into + * the Trusted Publisher repository. Requires elevated privileges when + * running the application on Vista and later. + */ +LIBWDI_EXP int LIBWDI_API wdi_install_trusted_certificate(const char* cert_name, + struct wdi_options_install_cert* options); + +/* + * Set the log verbosity + */ +LIBWDI_EXP int LIBWDI_API wdi_set_log_level(int level); + +/* + * Set the Windows callback message for log notification + */ +LIBWDI_EXP int LIBWDI_API wdi_register_logger(HWND hWnd, UINT message, DWORD buffsize); + +/* + * Unset the Windows callback message for log notification + */ +LIBWDI_EXP int LIBWDI_API wdi_unregister_logger(HWND hWnd); + +/* + * Read a log message after a log notification + */ +LIBWDI_EXP int LIBWDI_API wdi_read_logger(char* buffer, DWORD buffer_size, DWORD* message_size); + +/* + * Return the WDF version used by the native drivers + */ +LIBWDI_EXP int LIBWDI_API wdi_get_wdf_version(void); + +#ifdef __cplusplus +} +#endif diff --git a/driver/source/libwdi/libwdi.pc.in b/driver/source/libwdi/libwdi.pc.in new file mode 100644 index 00000000..03da6288 --- /dev/null +++ b/driver/source/libwdi/libwdi.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libwdi +Description: Windows (USB) Driver Installation library +Version: @VERSION@ +Libs: -L${libdir} -lwdi +Cflags: -I${includedir} diff --git a/driver/source/libwdi/libwdi.rc b/driver/source/libwdi/libwdi.rc new file mode 100644 index 00000000..795a6b08 --- /dev/null +++ b/driver/source/libwdi/libwdi.rc @@ -0,0 +1,90 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winresrc.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 + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winresrc.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,2,5,689 + PRODUCTVERSION 1,2,5,689 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000904b0" + BEGIN + VALUE "CompanyName", "akeo.ie" + VALUE "FileDescription", "libwdi: Windows Driver Installer Library" + VALUE "FileVersion", "1.2.5.689" + VALUE "InternalName", "libwdi" + VALUE "LegalCopyright", "© 2010-2014 Pete Batard (LGPL v3)" + VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/lesser.html" + VALUE "OriginalFilename", "libwdi" + VALUE "ProductName", "libwdi" + VALUE "ProductVersion", "1.2.5.689" + VALUE "Comments", "http://libwdi.akeo.ie" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x9, 1200 + END +END + +#endif // English resources +///////////////////////////////////////////////////////////////////////////// + + diff --git a/driver/source/libwdi/libwdi_dlg.c b/driver/source/libwdi/libwdi_dlg.c new file mode 100644 index 00000000..f58a6142 --- /dev/null +++ b/driver/source/libwdi/libwdi_dlg.c @@ -0,0 +1,423 @@ +/* + * Library for USB automated driver installation + * Copyright (c) 2010-2013 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 + * 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 + */ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "installer.h" +#include "libwdi.h" +#include "logging.h" +#include "resource.h" + +// WM_APP is not sent on focus, unlike WM_USER +enum stdlg_user_message_type { + UM_PROGRESS_START = WM_APP, + UM_PROGRESS_STOP, +}; + +// Messages that appear in our progress bar as time passes +static const char* progress_message[] = { + "Installation can take some time...", + "The installation process can take up to 5 minutes...", + "You may also be asked to reboot for KMDF upgrades.", + "If so, please watch for additional popup windows.", // 1 min + "The reason driver installation may take time...", + "...is because a System Restore point is created.", + "Microsoft offers no means of checking progress...", + "...so we can't say how long it'll take...", // 2 mins + "Please continue to be patient...", + "There's a 5 minutes timeout enventually...", + "...so if there's a problem, the process will abort.", + "I've really seen an installation take 5 minutes...", // 3 mins + "...on a Vista 64 machine with a very large disk.", + "So how was your day...", + "...before it got ruined by this endless installation?", + "Seriously, what is taking this process so long?!", // 4 mins + "Aborting in 45 seconds...", + "Aborting in 30 seconds...", + "Aborting in 15 seconds...", +}; + +#ifndef PBS_MARQUEE +#define PBS_MARQUEE 0x08 +#endif +#ifndef PBM_SETMARQUEE +#define PBM_SETMARQUEE (WM_USER+10) +#endif + +/* + * Globals + */ +static uintptr_t progress_thid = -1L; +static HWND hProgress = INVALID_HANDLE_VALUE; +static HWND hProgressBar = INVALID_HANDLE_VALUE; +static HWND hProgressText = INVALID_HANDLE_VALUE; +static HINSTANCE app_instance = NULL; +static int (*progress_function)(void*); +static void* progress_arglist; +static HANDLE progress_mutex = INVALID_HANDLE_VALUE; + +// Work around for GDI calls on DDK (would require end user apps linking with Gdi32 othwerwise) +static HFONT (WINAPI *pCreateFontA)(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCSTR) = NULL; +static HGDIOBJ (WINAPI *pGetStockObject)(int) = NULL; +static int (WINAPI *pSetBkMode)(HDC, int) = NULL; + +#define IS_CREATEFONT_AVAILABLE (pCreateFontA != NULL) +#define IS_BACKGROUND_AVAILABLE ((pGetStockObject != NULL) && (pSetBkMode != NULL)) + +#define INIT_GDI32 do { \ + pCreateFontA = (HFONT (WINAPI *)(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCSTR)) \ + GetProcAddress(GetDLLHandle("gdi32.dll"), "CreateFontA"); \ + pGetStockObject = (HGDIOBJ (WINAPI *)(int)) \ + GetProcAddress(GetDLLHandle("gdi32.dll"), "GetStockObject"); \ + pSetBkMode = (int (WINAPI *)(HDC, int)) \ + GetProcAddress(GetDLLHandle("gdi32.dll"), "SetBkMode"); \ + } while(0) + +extern char *windows_error_str(uint32_t retval); + + +/* + * Detect if a Windows Security prompt is active, by enumerating the + * whole Windows tree and looking for a security popup + */ +static BOOL CALLBACK security_prompt_callback(HWND hWnd, LPARAM lParam) +{ + char str_buf[STR_BUFFER_SIZE]; + HWND *hFound = (HWND*)lParam; + const char* security_string = "Windows Security"; + + // The security prompt has the popup window style + if (GetWindowLong(hWnd, GWL_STYLE) & WS_POPUPWINDOW) { + str_buf[0] = 0; + GetWindowTextA(hWnd, str_buf, STR_BUFFER_SIZE); + str_buf[STR_BUFFER_SIZE-1] = 0; + if (safe_strcmp(str_buf, security_string) == 0) { + *hFound = hWnd; + } + } + return TRUE; +} + +HWND find_security_prompt(void) { + HWND hSecurityPrompt = NULL; + EnumChildWindows(GetDesktopWindow(), security_prompt_callback, (LPARAM)&hSecurityPrompt); + return hSecurityPrompt; +} + +/* + * Thread executed by the run_with_progress_bar() function + */ +static void __cdecl progress_thread(void* param) +{ + int r; + + // Call the user provided function + r = (*progress_function)(progress_arglist); + progress_thid = -1L; + PostMessage(hProgress, UM_PROGRESS_STOP, (WPARAM)r, 0); + _endthread(); +} + +/* + * Center a dialog with regards to the main application Window + */ +static void center_dialog(HWND dialog) +{ + HWND hParent; + POINT Point; + RECT DialogRect; + RECT ParentRect; + int nWidth; + int nHeight; + + hParent = GetParent(dialog); + if (hParent == NULL) return; + + // Get the size of the dialog box. + GetWindowRect(dialog, &DialogRect); + GetClientRect(hParent, &ParentRect); + + // Calculate the height and width of the current dialog + nWidth = DialogRect.right - DialogRect.left; + nHeight = DialogRect.bottom - DialogRect.top; + + // Find the center point and convert to screen coordinates. + Point.x = (ParentRect.right - ParentRect.left) / 2; + Point.y = (ParentRect.bottom - ParentRect.top) / 2; + ClientToScreen(hParent, &Point); + + // Calculate the new x, y starting point. + Point.x -= nWidth / 2; + Point.y -= nHeight / 2 + 35; + + // Move the window. + MoveWindow(dialog, Point.x, Point.y, nWidth, nHeight, FALSE); +} + +/* + * Dialog sub-elements + */ +static void init_children(HWND hDlg) { + + HFONT hFont; + // Progress Bar + hProgressBar = CreateWindowExA(WS_EX_NOPARENTNOTIFY, PROGRESS_CLASSA, + NULL, + WS_CHILDWINDOW | WS_VISIBLE | PBS_MARQUEE, + 10,35,250,12, + hDlg, + NULL, + app_instance, + NULL); + if (hProgressBar == NULL) { + wdi_err("Unable to create progress bar: %s", windows_error_str(0)); + } + + // Start progress animation + PostMessage(hProgressBar, PBM_SETMARQUEE, TRUE, 0); + + // Progress Text + hProgressText = CreateWindowExA(WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT, WC_STATICA, + "Installing Driver...", + WS_CHILDWINDOW | WS_VISIBLE | WS_GROUP, + 12,12,250,16, + hDlg, + NULL, + app_instance, + NULL); + if (hProgressBar == NULL) { + wdi_err("Unable to create progress text: %s", windows_error_str(0)); + } + + // Set the font to MS Dialog default + INIT_GDI32; + if (IS_CREATEFONT_AVAILABLE) { + hFont = pCreateFontA(-11, 0, 0, 0, FW_DONTCARE, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, DEFAULT_PITCH, "MS Shell Dlg 2"); + SendMessage(hProgressText, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE); + } +} + +/* + * Callback for the run_with_progress_bar() function + */ +static LRESULT CALLBACK progress_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT loc; + HANDLE handle; + static int installation_time = 0; // active installation time, in secs + const int msg_max = ARRAYSIZE(progress_message); + static int msg_index = 0; + int i; + // coordinates that we want to disable (=> no resize) + static LRESULT disabled[9] = { HTLEFT, HTRIGHT, HTTOP, HTBOTTOM, HTSIZE, + HTTOPLEFT, HTTOPRIGHT, HTBOTTOMLEFT, HTBOTTOMRIGHT }; + + switch (message) { + + case WM_CREATE: + // Reset static variables + installation_time = 0; + msg_index = 0; + hProgress = hDlg; + + // Start modal (disable parent Window) + EnableWindow(GetParent(hDlg), FALSE); + + init_children(hProgress); + center_dialog(hProgress); + + // Send a WM_TIMER message every second + SetTimer(hProgress, 1, 1000, NULL); + + PostMessage(hProgress, UM_PROGRESS_START, 0, 0); + + return (INT_PTR)TRUE; + + case WM_NCHITTEST: + // Check coordinates to prevent resize actions + loc = DefWindowProc(hDlg, message, wParam, lParam); + for(i = 0; i < 9; i++) { + if (loc == disabled[i]) { + return (INT_PTR)TRUE; + } + } + return (INT_PTR)FALSE; + + case UM_PROGRESS_START: + if (progress_thid != -1L) { + wdi_err("program assertion failed - another operation is in progress"); + } else { + // Using a thread prevents application freezout on security warning + progress_thid = _beginthread(progress_thread, 0, NULL); + if (progress_thid != -1L) { + return (INT_PTR)TRUE; + } + wdi_err("unable to create progress_thread"); + } + // Fall through and return an error + wParam = (WPARAM)WDI_ERROR_RESOURCE; + + case UM_PROGRESS_STOP: + // If you don't re-enable the parent Window before leaving + // all kind of bad things happen (other Windows get activated, etc.) + EnableWindow(GetParent(hDlg), TRUE); + PostQuitMessage((int)wParam); + DestroyWindow(hProgress); + return (INT_PTR)TRUE; + + case WM_TIMER: + if (find_security_prompt() == NULL) { + installation_time++; // Only increment outside of security prompts + if ( (msg_index < msg_max) && (installation_time > 15*(msg_index+1)) ) { + // Change the progress blurb + SetWindowTextA(hProgressText, progress_message[msg_index]); + // Force a full redraw fot the transparent text background + ShowWindow(hProgressText, SW_HIDE); + UpdateWindow(hProgressText); + ShowWindow(hProgressText, SW_SHOW); + UpdateWindow(hProgressText); + msg_index++; + } else if ( (installation_time > 300) && (progress_thid != -1L) ) { + // Wait 300 (loose) seconds and kill the thread + // 300 secs is the timeout for driver installation on Vista + wdi_err("progress timeout expired - KILLING THREAD!"); + handle = OpenThread(THREAD_TERMINATE, FALSE, (DWORD)progress_thid); + if (handle != NULL) { + TerminateThread(handle, -1); + CloseHandle(handle); + } + PostQuitMessage(WDI_ERROR_TIMEOUT); + DestroyWindow(hProgress); + return (INT_PTR)FALSE; + } + } + return (INT_PTR)TRUE; + + case WM_CLOSE: // prevent closure using Alt-F4 + return (INT_PTR)TRUE; + + case WM_DESTROY: // close application + hProgress = INVALID_HANDLE_VALUE; + return (INT_PTR)FALSE; + + case WM_CTLCOLORSTATIC: + pSetBkMode((HDC)wParam, TRANSPARENT); + return (INT_PTR)pGetStockObject(NULL_BRUSH); + } + return DefWindowProc(hDlg, message, wParam, lParam); +} + +/* + * Call a blocking function (returning an int) as a modal thread with a progress bar + */ +int run_with_progress_bar(HWND hWnd, int(*function)(void*), void* arglist) { + HWND hDlg; + MSG msg; + WNDCLASSEX wc; + BOOL r; + + if ( (function == NULL) || (hWnd == NULL) ) { + return WDI_ERROR_INVALID_PARAM; + } + + app_instance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); + + // protect access to the thread variables and prevent 2 progress + // dialogs from executing at the same time + progress_mutex = CreateMutex(NULL, TRUE, NULL); + if ((progress_mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) { + wdi_err("could not obtain progress dialog mutex - is another dialog active?"); + if (progress_mutex != NULL) + CloseHandle(progress_mutex); + progress_mutex = INVALID_HANDLE_VALUE; + return WDI_ERROR_BUSY; + } + progress_function = function; + progress_arglist = arglist; + + // Since our lib can be static, we can't use resources + // => create the whole dialog manually. + + // First we create Window class if it doesn't already exist + if (!GetClassInfoEx(app_instance, TEXT("wdi_progress_class"), &wc)) { + wc.cbSize = sizeof(wc); + wc.style = CS_DBLCLKS | CS_SAVEBITS; + wc.lpfnWndProc = progress_callback; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = app_instance; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = TEXT("wdi_progress_class"); + wc.lpszMenuName = NULL; + wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); + + if (!RegisterClassEx(&wc)) { + wdi_err("can't register class %s", windows_error_str(0)); + safe_closehandle(progress_mutex); + return WDI_ERROR_RESOURCE; + } + } + + // Then we create the dialog base + hDlg = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT, + TEXT("wdi_progress_class"), TEXT("Installing Driver..."), + 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)); + safe_closehandle(progress_mutex); + return WDI_ERROR_RESOURCE; + } + + // Finally we Display the dialog... + ShowWindow(hDlg, SW_SHOWNORMAL); + UpdateWindow(hDlg); + + // ...and handle the message processing loop + while( (r = GetMessage(&msg, NULL, 0, 0)) != 0) { + if (r == -1) { + wdi_err("GetMessage error"); + } else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + safe_closehandle(progress_mutex); + + return (int)msg.wParam; +} diff --git a/driver/source/libwdi/libwdi_i.h b/driver/source/libwdi/libwdi_i.h new file mode 100644 index 00000000..fb7d99d6 --- /dev/null +++ b/driver/source/libwdi/libwdi_i.h @@ -0,0 +1,281 @@ +/* + * Library for USB automated driver installation - internal header + * Copyright (c) 2010-2014 Pete Batard + * Parts of the code from libusb by Daniel Drake, Johannes Erdfelt et al. + * 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 + * 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 + */ +#pragma once + +#include +#include +#include "libwdi.h" +#include "tokenizer.h" + +// Initial timeout delay to wait for the installer to run +#define DEFAULT_TIMEOUT 10000 +#define PF_ERR wdi_err + +// These warnings are taken care of in configure for other platforms +#if defined(_MSC_VER) + +#define __STR2__(x) #x +#define __STR1__(x) __STR2__(x) +#if defined(_WIN64) && defined(OPT_M32) +// a 64 bit application/library CANNOT be used on 32 bit platforms +#pragma message(__FILE__ "(" __STR1__(__LINE__) ") : warning : library is compiled as 64 bit - disabling 32 bit support") +#undef OPT_M32 +#endif + +#if !defined(OPT_M32) && !defined(OPT_M64) +#error both 32 and 64 bit support have been disabled - check your config.h +#endif +#if defined(OPT_M64) && !defined(OPT_M32) +#pragma message(__FILE__ "(" __STR1__(__LINE__) ") : warning : this library will be INCOMPATIBLE with 32 bit platforms") +#endif +#if defined(OPT_M32) && !defined(OPT_M64) +#pragma message(__FILE__ "(" __STR1__(__LINE__) ") : warning : this library will be INCOMPATIBLE with 64 bit platforms") +#endif + +#endif + +// These functions are defined in libwdi_dlg +HWND find_security_prompt(void); +int run_with_progress_bar(HWND hWnd, int(*function)(void*), void* arglist); +// These ones are defined in pki +BOOL AddCertToTrustedPublisher(BYTE* cert_data, DWORD cert_size, BOOL disable_warning, HWND hWnd); +BOOL SelfSignFile(LPCSTR szFileName, LPCSTR szCertSubject); +BOOL CreateCat(LPCSTR szCatPath, LPCSTR szHWID, LPCSTR szSearchDir, LPCSTR* szFileList, DWORD cFileList); + +// Structure used for the threaded call to install_driver_internal() +struct install_driver_params { + struct wdi_device_info* device_info; + const char* path; + const char* inf_name; + struct wdi_options_install_driver* options; +}; + +// Tokenizer data +enum INF_TAGS +{ + INF_FILENAME, + CAT_FILENAME, + DEVICE_DESCRIPTION, + DEVICE_HARDWARE_ID, + DEVICE_INTERFACE_GUID, + DEVICE_MANUFACTURER, + DRIVER_DATE, + DRIVER_VERSION, + USE_DEVICE_INTERFACE_GUID, + WDF_VERSION, + KMDF_VERSION, + LK_COMMA, + LK_DLL, + LK_X86_DLL, + LK_EQ_X86, + LK_EQ_X64, +}; + +token_entity_t inf_entities[]= +{ + {"INF_FILENAME",""}, + {"CAT_FILENAME",""}, + {"DEVICE_DESCRIPTION",""}, + {"DEVICE_HARDWARE_ID",""}, + {"DEVICE_INTERFACE_GUID",""}, + {"DEVICE_MANUFACTURER",""}, + {"DRIVER_DATE",""}, + {"DRIVER_VERSION",""}, + {"USE_DEVICE_INTERFACE_GUID",""}, + {"WDF_VERSION",""}, + {"KMDF_VERSION",""}, + {"LK_COMMA",""}, + {"LK_DLL",""}, + {"LK_X86_DLL",""}, + {"LK_EQ_X86",""}, + {"LK_EQ_X64",""}, + {NULL, ""} // DO NOT REMOVE! +}; + +/* + * List of Android devices that need to be assigned a specific Device Interface GUID + * so that they are recognized with Google's debug tools. + * This list gets updated from https://github.com/gu1dry/android_winusb/ (Cyanogenmod) + * and http://developer.android.com/sdk/win-usb.html (Google USB driver) as well as + * http://www.linux-usb.org/usb.ids (for newer Google devices as well as Samsung's) + * NB: We don't specify an MI, as the assumption is that the MTP driver has already been + * 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[] = { + {0x0451, 0xD022}, + {0x0451, 0xD101}, + {0x0489, 0xC001}, + {0x04E8, 0x685B}, // Samsung Galaxy + {0x04E8, 0x685C}, + {0x04E8, 0x685D}, + {0x04E8, 0x685E}, + {0x04E8, 0x6860}, + {0x04E8, 0x6863}, + {0x04E8, 0x6864}, + {0x04E8, 0x6865}, + {0x04E8, 0x6866}, + {0x04E8, 0x6868}, + {0x04E8, 0x6877}, + {0x04E8, 0x689e}, + {0x05C6, 0x9018}, // Qualcomm HSUSB Device + {0x05C6, 0x9025}, + {0x0955, 0x7030}, // NVidia Tegra + {0x0955, 0x7100}, + {0x0955, 0xB400}, // NVidia Shield + {0x0955, 0xB401}, + {0x0955, 0xCF05}, + {0x0955, 0xCF06}, + {0x0955, 0xCF07}, + {0x0955, 0xCF08}, + {0x0955, 0xCF09}, + {0x0B05, 0x4D00}, // Asus Transformer + {0x0B05, 0x4D01}, + {0x0B05, 0x4D02}, + {0x0B05, 0x4D03}, + {0x0B05, 0x4E01}, + {0x0B05, 0x4E03}, + {0x0B05, 0x4E1F}, + {0x0B05, 0x4E3F}, + {0x0BB4, 0x0C01}, // HTC + {0x0BB4, 0x0C02}, + {0x0BB4, 0x0C03}, + {0x0BB4, 0x0C13}, + {0x0BB4, 0x0C1F}, // Sony Ericsson Xperia X1 + {0x0BB4, 0x0C5F}, + {0x0BB4, 0x0C86}, + {0x0BB4, 0x0C87}, + {0x0BB4, 0x0C8B}, + {0x0BB4, 0x0C8D}, + {0x0BB4, 0x0C91}, + {0x0BB4, 0x0C92}, + {0x0BB4, 0x0C93}, + {0x0BB4, 0x0C94}, + {0x0BB4, 0x0C95}, + {0x0BB4, 0x0C96}, + {0x0BB4, 0x0C97}, + {0x0BB4, 0x0C98}, + {0x0BB4, 0x0C99}, + {0x0BB4, 0x0C9E}, + {0x0BB4, 0x0CA2}, + {0x0BB4, 0x0CA3}, + {0x0BB4, 0x0CA4}, + {0x0BB4, 0x0CA5}, + {0x0BB4, 0x0CAC}, + {0x0BB4, 0x0CAD}, + {0x0BB4, 0x0CAE}, + {0x0BB4, 0x0CBA}, + {0x0BB4, 0x0CED}, + {0x0BB4, 0x0E03}, + {0x0BB4, 0x0F64}, + {0x0BB4, 0x0FF8}, + {0x0BB4, 0x0FF9}, + {0x0BB4, 0x0FFE}, + {0x0BB4, 0x0FFF}, + {0x0FCE, 0x0DDE}, // Sony Ericsson + {0x0FCE, 0x4E30}, + {0x0FCE, 0x6860}, + {0x0FCE, 0xD001}, + {0x1004, 0x618E}, // LG + {0x12D1, 0x1501}, + {0x18D1, 0x0D02}, + {0x18D1, 0x2C10}, + {0x18D1, 0x2C11}, + {0x18D1, 0x4D00}, // Project Tango + {0x18D1, 0x4D02}, + {0x18D1, 0x4D04}, + {0x18D1, 0x4D06}, + {0x18D1, 0x4D07}, + {0x18D1, 0x4E10}, // Project Tango + {0x18D1, 0x4E11}, + {0x18D1, 0x4E12}, + {0x18D1, 0x4E13}, + {0x18D1, 0x4E20}, // Nexus S + {0x18D1, 0x4E21}, + {0x18D1, 0x4E22}, + {0x18D1, 0x4E23}, + {0x18D1, 0x4E24}, + {0x18D1, 0x4E30}, // Galaxy Nexus + {0x18D1, 0x4E40}, // Nexus 7 + {0x18D1, 0x4E41}, + {0x18D1, 0x4E42}, + {0x18D1, 0x4E43}, + {0x18D1, 0x4E44}, + {0x18D1, 0x4EE0}, // Nexus 4/5 + {0x18D1, 0x4EE1}, + {0x18D1, 0x4EE2}, + {0x18D1, 0x4EE3}, + {0x18D1, 0x4EE4}, + {0x18D1, 0x4EE5}, + {0x18D1, 0x4EE6}, + {0x18D1, 0x4EE7}, + {0x18D1, 0x708C}, + {0x18D1, 0x708C}, + {0x18D1, 0x7102}, // Toshiba Thrive tablet + {0x18D1, 0x9001}, + {0x18D1, 0xB004}, + {0x18D1, 0xD001}, // Nexus 4 + {0x18D1, 0xD002}, + {0x18D1, 0xD109}, // LG G2x + {0x18D1, 0xD10A}, + {0x19D2, 0x1351}, + {0x19D2, 0x1354}, + {0x2080, 0x0001}, // Nook + {0x2080, 0x0002}, + {0x2080, 0x0003}, + {0x2080, 0x0004}, + {0x22B8, 0x2D66}, // Motorola + {0x22B8, 0x41DB}, + {0x22B8, 0x4286}, + {0x22B8, 0x42A4}, + {0x22B8, 0x42DA}, + {0x22B8, 0x4331}, + {0x22B8, 0x70A9}, +}; + + +// For the retrieval of the device description on Windows 7 +#ifndef DEVPROPKEY_DEFINED +typedef struct { + GUID fmtid; + ULONG pid; +} DEVPROPKEY; +#endif + +const DEVPROPKEY DEVPKEY_Device_BusReportedDeviceDesc = { + { 0x540b947e, 0x8b40, 0x45bc, {0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2} }, 4 }; + +// Check the status of the installer process +static int __inline check_completion(HANDLE process_handle) { + DWORD exit_code; + GetExitCodeProcess(process_handle, &exit_code); + return (exit_code==0)?WDI_SUCCESS:((exit_code==STILL_ACTIVE)?WDI_ERROR_TIMEOUT:WDI_ERROR_OTHER); +} + +// Convert a UNIX timestamp to a MS FileTime one +static int64_t __inline unixtime_to_msfiletime(time_t t) +{ + int64_t ret = (int64_t)t; + ret *= INT64_C(10000000); + ret += INT64_C(116444736000000000); + return ret; +} diff --git a/driver/source/libwdi/logging.c b/driver/source/libwdi/logging.c new file mode 100644 index 00000000..5de1a97c --- /dev/null +++ b/driver/source/libwdi/logging.c @@ -0,0 +1,340 @@ +/* + * libwdi logging functions + * Copyright (c) Johannes Erdfelt, Daniel Drake et al. + * Copyright (c) 2010-2013 Pete Batard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 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 + */ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "libwdi.h" +#include "logging.h" + +static HANDLE logger_rd_handle = INVALID_HANDLE_VALUE; +static HANDLE logger_wr_handle = INVALID_HANDLE_VALUE; +// Handle and Message for the destination Window when registered +static HWND logger_dest = NULL; +static UINT logger_msg = 0; +// Detect spurious log readouts +static unsigned log_messages_pending = 0; +// Keep track of how many bytes are in the pipe +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); + +static void write_to_pipe(const char* buffer, DWORD size, enum wdi_log_level level) +{ + DWORD written; + + // Earlier checks should ensure that this is never the case, but if it is + // drop the message + if (size > LOGGER_PIPE_SIZE) + return; + + // Do not allow the pipe to outgrow its allocated size, as this freezes the app + // See http://msdn.microsoft.com/en-us/library/aa365150.aspx + // If we are about to overflow, we deplete the pipe queue by issuing a bunch of + // SendMessage, which forces the messages to be processed (as opposed to PostMessage) + if (((log_messages_pipe_size + size) > LOGGER_PIPE_SIZE) && (log_messages_pending > 0)) { + while (log_messages_pending > 0) + SendMessage(logger_dest, logger_msg, (WPARAM)level, 0); + // Just in case + log_messages_pipe_size = 0; + } + if (WriteFile(logger_wr_handle, buffer, size, &written, NULL)) + log_messages_pipe_size += written; + log_messages_pending++; + PostMessage(logger_dest, logger_msg, (WPARAM)level, 0); +} + +static void pipe_wdi_log_v(enum wdi_log_level level, + const char *function, const char *format, va_list args) +{ + char buffer[LOGBUF_SIZE]; + int size1, size2; + BOOL truncated = FALSE; + const char* prefix; + const char* truncation_notice = "TRUNCATION detected for above line - Please " + "send this log excerpt to the libwdi developers so we can fix it."; + + if (logger_wr_handle == INVALID_HANDLE_VALUE) + return; + +#ifndef ENABLE_DEBUG_LOGGING + if (level < global_log_level) + return; +#endif + + switch (level) { + case WDI_LOG_LEVEL_DEBUG: + prefix = "debug"; + break; + case WDI_LOG_LEVEL_INFO: + prefix = "info"; + break; + case WDI_LOG_LEVEL_WARNING: + prefix = "warning"; + break; + case WDI_LOG_LEVEL_ERROR: + prefix = "error"; + break; + default: + prefix = "unknown"; + break; + } + + size1 = safe_snprintf(buffer, LOGBUF_SIZE, "libwdi:%s [%s] ", prefix, function); + size2 = 0; + if (size1 < 0) { + buffer[LOGBUF_SIZE-1] = 0; + size1 = LOGBUF_SIZE-1; + truncated = TRUE; + } else { + size2 = safe_vsnprintf(buffer+size1, LOGBUF_SIZE-size1, format, args); + if (size2 < 0) { + buffer[LOGBUF_SIZE-1] = 0; + size2 = LOGBUF_SIZE-1-size1; + truncated = TRUE; + } + } + + write_to_pipe(buffer, size1+size2+1, level); + if (truncated) + write_to_pipe(truncation_notice, strlen(truncation_notice)+1, level); +} + +static void console_wdi_log_v(enum wdi_log_level level, + const char *function, const char *format, va_list args) +{ + FILE *stream; + const char *prefix; + + stream = stdout; + +#ifndef ENABLE_DEBUG_LOGGING + if (level < global_log_level) + return; +#endif + + switch (level) { + case WDI_LOG_LEVEL_DEBUG: + stream = stderr; + prefix = "debug"; + break; + case WDI_LOG_LEVEL_INFO: + prefix = "info"; + break; + case WDI_LOG_LEVEL_WARNING: + stream = stderr; + prefix = "warning"; + break; + case WDI_LOG_LEVEL_ERROR: + stream = stderr; + prefix = "error"; + break; + default: + stream = stderr; + prefix = "unknown"; + break; + } + + fprintf(stream, "libwdi:%s [%s] ", prefix, function); + + vfprintf(stream, format, args); + + fprintf(stream, "\n"); + +} + +void wdi_log(enum wdi_log_level level, + const char *function, const char *format, ...) +{ + va_list args; + + va_start (args, format); + if (logger_dest != NULL) { + pipe_wdi_log_v(level, function, format, args); + } else { + console_wdi_log_v(level, function, format, args); + } + va_end (args); +} + +// Create a synchronous pipe for messaging +static int create_logger(DWORD buffsize) +{ + if (buffsize == 0) { + buffsize = LOGGER_PIPE_SIZE; + } + + if (logger_wr_handle != INVALID_HANDLE_VALUE) { + // We (supposedly) don't have logging, so try to reach a stderr + fprintf(stderr, "trying to recreate logger pipe\n"); + return WDI_ERROR_EXISTS; + } + + // Read end of the pipe + 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)); + return WDI_ERROR_RESOURCE; + } + + // Write end of the pipe + 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)); + CloseHandle(logger_rd_handle); + logger_rd_handle = INVALID_HANDLE_VALUE; + return WDI_ERROR_RESOURCE; + } + + log_messages_pending = 0; + + return WDI_SUCCESS; +} + +// Destroy the logging pipe +static void destroy_logger(void) +{ + if (logger_wr_handle != INVALID_HANDLE_VALUE) { + CloseHandle(logger_wr_handle); + logger_wr_handle = INVALID_HANDLE_VALUE; + } + if (logger_rd_handle != INVALID_HANDLE_VALUE) { + CloseHandle(logger_rd_handle); + logger_rd_handle = INVALID_HANDLE_VALUE; + } +} + +/* + * Register a Window as destination for logging message + * This Window will be notified with a message event and should call + * wdi_read_logger() to retrieve the message data + */ +int LIBWDI_API wdi_register_logger(HWND hWnd, UINT message, DWORD buffsize) +{ + int r; + + MUTEX_START; + + if (logger_dest != NULL) { + MUTEX_RETURN(WDI_ERROR_EXISTS); + } + + r = create_logger(buffsize); + if (r == WDI_SUCCESS) { + logger_dest = hWnd; + logger_msg = message; + } + + MUTEX_RETURN(r); +} + +/* + * Unregister a Window as destination for logging message + */ +int LIBWDI_API wdi_unregister_logger(HWND hWnd) +{ + MUTEX_START; + + if (logger_dest == NULL) { + MUTEX_RETURN(WDI_SUCCESS); + } + + if (logger_dest != hWnd) { + MUTEX_RETURN(WDI_ERROR_INVALID_PARAM); + } + + destroy_logger(); + logger_dest = NULL; + logger_msg = 0; + + MUTEX_RETURN(WDI_SUCCESS); +} + +/* + * Read a log message + */ +int LIBWDI_API wdi_read_logger(char* buffer, DWORD buffer_size, DWORD* message_size) +{ + int size; + DWORD r; + + MUTEX_START; + + if ( (logger_rd_handle == INVALID_HANDLE_VALUE) && (create_logger(0) != WDI_SUCCESS) ) { + *message_size = 0; + MUTEX_RETURN(WDI_ERROR_NOT_FOUND); + } + + if (log_messages_pending == 0) { + if (log_messages_pipe_size == 0) { + buffer[0] = 0; + *message_size = 0; + MUTEX_RETURN(WDI_SUCCESS); + } + size = safe_snprintf(buffer, buffer_size, "ERROR: log buffer is empty"); + if (size < 0) { + buffer[buffer_size-1] = 0; + MUTEX_RETURN(buffer_size); + } + *message_size = (DWORD)size; + MUTEX_RETURN(WDI_SUCCESS); + } + log_messages_pending--; + + if (ReadFile(logger_rd_handle, (void*)buffer, buffer_size, message_size, NULL)) { + log_messages_pipe_size -= *message_size; + MUTEX_RETURN(WDI_SUCCESS); + } + + log_messages_pipe_size -= *message_size; + *message_size = 0; + r = GetLastError(); + if ((r == ERROR_INSUFFICIENT_BUFFER) || (r == ERROR_MORE_DATA)) { + MUTEX_RETURN(WDI_ERROR_OVERFLOW); + } + MUTEX_RETURN(WDI_ERROR_IO); +} + +/* + * Set the global log level. Only works if ENABLE_DEBUG_LOGGING is not set + */ +int LIBWDI_API wdi_set_log_level(int level) +{ +#if defined(ENABLE_DEBUG_LOGGING) + return WDI_ERROR_NOT_SUPPORTED; +#endif + global_log_level = level; + return WDI_SUCCESS; +} diff --git a/driver/source/libwdi/logging.h b/driver/source/libwdi/logging.h new file mode 100644 index 00000000..640525ee --- /dev/null +++ b/driver/source/libwdi/logging.h @@ -0,0 +1,94 @@ +/* + * libwdi logging functions + * Copyright (c) Johannes Erdfelt, Daniel Drake et al. + * Copyright (c) 2010-2013 Pete Batard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 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 + */ +#pragma once + +#define LOGGER_PIPE_NAME "\\\\.\\pipe\\libwdi-logger" +#define LOGGER_PIPE_SIZE 8192 +#define LOGBUF_SIZE 512 + +// Prevent two exclusive libwdi calls from running at the same time +#define MUTEX_RETURN(errcode) do { CloseHandle(mutex); return errcode; } while (0) +#define MUTEX_START char mutex_name[10+sizeof(__FUNCTION__)]; HANDLE mutex; \ + safe_snprintf(mutex_name, 10+sizeof(__FUNCTION__), "Global\\%s", __FUNCTION__); \ + mutex = CreateMutexA(NULL, TRUE, mutex_name); \ + if (mutex == NULL) return WDI_ERROR_RESOURCE; \ + if (GetLastError() == ERROR_ALREADY_EXISTS) { MUTEX_RETURN(WDI_ERROR_BUSY); } + +#if defined(_MSC_VER) +#define safe_vsnprintf(buf, size, format, arg) _vsnprintf_s(buf, size, _TRUNCATE, format, arg) +#define safe_snprintf(buf, size, ...) _snprintf_s(buf, size, _TRUNCATE, __VA_ARGS__) +#else +#define safe_vsnprintf vsnprintf +#define safe_snprintf snprintf +#endif + + +#if !defined(_MSC_VER) || _MSC_VER > 1200 + +#if defined(ENABLE_DEBUG_LOGGING) || defined(INCLUDE_DEBUG_LOGGING) +#define _wdi_log(level, ...) wdi_log(level, __FUNCTION__, __VA_ARGS__) +#else +#define _wdi_log(level, ...) +#endif + +#if defined(ENABLE_DEBUG_LOGGING) || defined(INCLUDE_DEBUG_LOGGING) +#define wdi_dbg(...) _wdi_log(WDI_LOG_LEVEL_DEBUG, __VA_ARGS__) +#else +#define wdi_dbg(...) +#endif + +#define wdi_info(...) _wdi_log(WDI_LOG_LEVEL_INFO, __VA_ARGS__) +#define wdi_warn(...) _wdi_log(WDI_LOG_LEVEL_WARNING, __VA_ARGS__) +#define wdi_err(...) _wdi_log(WDI_LOG_LEVEL_ERROR, __VA_ARGS__) + +#else /* !defined(_MSC_VER) || _MSC_VER > 1200 */ + +void wdi_log_v(enum wdi_log_level level, + const char *function, const char *format, va_list args); + +#if defined(ENABLE_DEBUG_LOGGING) || defined(INCLUDE_DEBUG_LOGGING) +#define LOG_BODY(level) \ +{ \ + va_list args; \ + va_start (args, format); \ + wdi_log_v(level, "", format, args); \ + va_end(args); \ +} +#else +#define LOG_BODY(level) { } +#endif + +void inline wdi_info(const char *format, ...) + LOG_BODY(LOG_LEVEL_INFO) +void inline wdi_warn(const char *format, ...) + LOG_BODY(LOG_LEVEL_WARNING) +void inline wdi_err( const char *format, ...) + LOG_BODY(LOG_LEVEL_ERROR) + +void inline wdi_dbg(const char *format, ...) +#if defined(ENABLE_DEBUG_LOGGING) || defined(INCLUDE_DEBUG_LOGGING) + LOG_BODY(LOG_LEVEL_DEBUG) +#else +{ } +#endif + +#endif /* !defined(_MSC_VER) || _MSC_VER > 1200 */ + +extern void wdi_log(enum wdi_log_level level, const char *function, const char *format, ...); diff --git a/driver/source/libwdi/msapi_utf8.h b/driver/source/libwdi/msapi_utf8.h new file mode 100644 index 00000000..f0445bea --- /dev/null +++ b/driver/source/libwdi/msapi_utf8.h @@ -0,0 +1,669 @@ +/* + * MSAPI_UTF8: Common API calls using UTF-8 strings + * Compensating for what Microsoft should have done a long long time ago. + * + * Copyright © 2010-2014 Pete Batard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 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 + */ +#include +#include +#include +#include +#include +#include +#include + +#pragma once +#if defined(_MSC_VER) +// disable VS2012 Code Analysis warnings that are intentional +#pragma warning(disable: 6387) // Don't care about bad params +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define _LTEXT(txt) L##txt +#define LTEXT(txt) _LTEXT(txt) + +#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \ + WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL) +#define utf8_to_wchar_no_alloc(src, wdest, wdest_size) \ + MultiByteToWideChar(CP_UTF8, 0, src, -1, wdest, wdest_size) +#define Edit_ReplaceSelU(hCtrl, str) ((void)SendMessageLU(hCtrl, EM_REPLACESEL, (WPARAM)FALSE, str)) +#define ComboBox_AddStringU(hCtrl, str) ((int)(DWORD)SendMessageLU(hCtrl, CB_ADDSTRING, (WPARAM)FALSE, str)) +#define ComboBox_InsertStringU(hCtrl, index, str) ((int)(DWORD)SendMessageLU(hCtrl, CB_INSERTSTRING, (WPARAM)index, str)) +#define ComboBox_GetTextU(hCtrl, str, max_str) GetWindowTextU(hCtrl, str, max_str) +#define GetSaveFileNameU(p) GetOpenSaveFileNameU(p, TRUE) +#define GetOpenFileNameU(p) GetOpenSaveFileNameU(p, FALSE) +#define ListView_SetItemTextU(hwndLV,i,iSubItem_,pszText_) { LVITEMW _ms_wlvi; _ms_wlvi.iSubItem = iSubItem_; \ + _ms_wlvi.pszText = utf8_to_wchar(pszText_); \ + SNDMSG((hwndLV),LVM_SETITEMTEXTW,(WPARAM)(i),(LPARAM)&_ms_wlvi); sfree(_ms_wlvi.pszText);} + +#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 wfree(p) sfree(w ## p) + +/* + * Converts an UTF-16 string to UTF8 (allocate returned string) + * Returns NULL on error + */ +static __inline char* wchar_to_utf8(const wchar_t* wstr) +{ + int size = 0; + char* str = NULL; + + // 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 + return NULL; + + if ((str = (char*)calloc(size, 1)) == NULL) + return NULL; + + if (wchar_to_utf8_no_alloc(wstr, str, size) != size) { + sfree(str); + return NULL; + } + + return str; +} + +/* + * Converts an UTF8 string to UTF-16 (allocate returned string) + * Returns NULL on error + */ +static __inline wchar_t* utf8_to_wchar(const char* str) +{ + int size = 0; + wchar_t* wstr = NULL; + + // Find out the size we need to allocate for our converted string + size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + if (size <= 1) // An empty string would be size 1 + return NULL; + + if ((wstr = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL) + return NULL; + + if (utf8_to_wchar_no_alloc(str, wstr, size) != size) { + sfree(wstr); + return NULL; + } + return wstr; +} + +static __inline DWORD FormatMessageU(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, + DWORD dwLanguageId, char* lpBuffer, DWORD nSize, va_list *Arguments) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + walloc(lpBuffer, nSize); + ret = FormatMessageW(dwFlags, lpSource, dwMessageId, dwLanguageId, wlpBuffer, nSize, Arguments); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nSize)) == 0)) { + err = GetLastError(); + ret = 0; + } + wfree(lpBuffer); + SetLastError(err); + return ret; +} + +// SendMessage, with LPARAM as UTF-8 string +static __inline LRESULT SendMessageLU(HWND hWnd, UINT Msg, WPARAM wParam, const char* lParam) +{ + LRESULT ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lParam); + ret = SendMessageW(hWnd, Msg, wParam, (LPARAM)wlParam); + err = GetLastError(); + wfree(lParam); + SetLastError(err); + return ret; +} + +static __inline int DrawTextExU(HDC hDC, LPCSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat, LPDRAWTEXTPARAMS lpDTParams) +{ + int ret; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpchText); + ret = DrawTextExW(hDC, wlpchText, nCount, lpRect, uFormat, lpDTParams); + err = GetLastError(); + wfree(lpchText); + SetLastError(err); + return ret; +} + +static __inline BOOL SHGetPathFromIDListU(LPCITEMIDLIST pidl, char* pszPath) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + walloc(pszPath, MAX_PATH); + ret = SHGetPathFromIDListW(pidl, wpszPath); + err = GetLastError(); + if ((ret) && (wchar_to_utf8_no_alloc(wpszPath, pszPath, MAX_PATH) == 0)) { + err = GetLastError(); + ret = FALSE; + } + wfree(pszPath); + SetLastError(err); + return ret; +} + +static __inline HWND CreateWindowU(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 = CreateWindowW(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; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpText); + wconvert(lpCaption); + ret = MessageBoxW(hWnd, wlpText, wlpCaption, uType); + err = GetLastError(); + wfree(lpText); + wfree(lpCaption); + SetLastError(err); + return ret; +} + +static __inline int GetWindowTextU(HWND hWnd, char* lpString, int nMaxCount) +{ + int ret = 0; + DWORD err = ERROR_INVALID_DATA; + walloc(lpString, nMaxCount); + ret = GetWindowTextW(hWnd, wlpString, nMaxCount); + err = GetLastError(); + if ( (ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpString, lpString, nMaxCount)) == 0) ) { + err = GetLastError(); + } + wfree(lpString); + SetLastError(err); + return ret; +} + +static __inline BOOL SetWindowTextU(HWND hWnd, const char* lpString) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpString); + ret = SetWindowTextW(hWnd, wlpString); + err = GetLastError(); + wfree(lpString); + SetLastError(err); + return ret; +} + +static __inline int GetWindowTextLengthU(HWND hWnd) +{ + int ret = 0; + DWORD err = ERROR_INVALID_DATA; + wchar_t* wbuf = NULL; + char* buf = NULL; + + ret = GetWindowTextLengthW(hWnd); + err = GetLastError(); + if (ret == 0) goto out; + wbuf = calloc(ret, sizeof(wchar_t)); + err = GetLastError(); + if (wbuf == NULL) { + err = ERROR_OUTOFMEMORY; ret = 0; goto out; + } + ret = GetWindowTextW(hWnd, wbuf, ret); + err = GetLastError(); + if (ret == 0) goto out; + buf = wchar_to_utf8(wbuf); + err = GetLastError(); + if (buf == NULL) { + err = ERROR_OUTOFMEMORY; ret = 0; goto out; + } + ret = (int)strlen(buf) + 2; // GetDlgItemText seems to add a character + err = GetLastError(); +out: + sfree(wbuf); + sfree(buf); + SetLastError(err); + return ret; +} + +static __inline UINT GetDlgItemTextU(HWND hDlg, int nIDDlgItem, char* lpString, int nMaxCount) +{ + UINT ret = 0; + DWORD err = ERROR_INVALID_DATA; + walloc(lpString, nMaxCount); + ret = GetDlgItemTextW(hDlg, nIDDlgItem, wlpString, nMaxCount); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpString, lpString, nMaxCount)) == 0)) { + err = GetLastError(); + } + wfree(lpString); + SetLastError(err); + return ret; +} + +static __inline BOOL SetDlgItemTextU(HWND hDlg, int nIDDlgItem, const char* lpString) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpString); + ret = SetDlgItemTextW(hDlg, nIDDlgItem, wlpString); + err = GetLastError(); + wfree(lpString); + SetLastError(err); + return ret; +} + +static __inline int ComboBox_GetLBTextU(HWND hCtrl, int index, char* lpString) +{ + int size; + DWORD err = ERROR_INVALID_DATA; + wchar_t* wlpString; + if (lpString == NULL) + return CB_ERR; + size = (int)SendMessageW(hCtrl, CB_GETLBTEXTLEN, (WPARAM)index, (LPARAM)0); + if (size < 0) + return size; + wlpString = (wchar_t*)calloc(size+1, sizeof(wchar_t)); + size = (int)SendMessageW(hCtrl, CB_GETLBTEXT, (WPARAM)index, (LPARAM)wlpString); + err = GetLastError(); + if (size > 0) + wchar_to_utf8_no_alloc(wlpString, lpString, size+1); + wfree(lpString); + SetLastError(err); + return size; +} + +static __inline HANDLE CreateFileU(const char* lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) +{ + HANDLE ret = INVALID_HANDLE_VALUE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpFileName); + ret = CreateFileW(wlpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + err = GetLastError(); + wfree(lpFileName); + SetLastError(err); + return ret; +} + +static __inline BOOL DeleteFileU(const char* lpFileName) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpFileName); + ret = DeleteFileW(wlpFileName); + err = GetLastError(); + wfree(lpFileName); + SetLastError(err); + return ret; +} + +// 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) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(lpString); + if (wlpString == NULL) + return FALSE; + ret = GetTextExtentPoint32W(hdc, wlpString, (int)wcslen(wlpString), lpSize); + err = GetLastError(); + wfree(lpString); + SetLastError(err); + return ret; +} + +static __inline DWORD GetCurrentDirectoryU(DWORD nBufferLength, char* lpBuffer) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + walloc(lpBuffer, nBufferLength); + ret = GetCurrentDirectoryW(nBufferLength, wlpBuffer); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) { + err = GetLastError(); + } + wfree(lpBuffer); + SetLastError(err); + return ret; +} + +static __inline DWORD GetModuleFileNameU(HMODULE hModule, char* lpFilename, DWORD nSize) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + walloc(lpFilename, nSize); + ret = GetModuleFileNameW(hModule, wlpFilename, nSize); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpFilename, lpFilename, nSize)) == 0)) { + err = GetLastError(); + } + wfree(lpFilename); + SetLastError(err); + return ret; +} + +static __inline DWORD GetFullPathNameU(const char* lpFileName, DWORD nBufferLength, char* lpBuffer, char** lpFilePart) +{ + DWORD ret = 0, err = ERROR_INVALID_DATA; + wchar_t* wlpFilePart; + wconvert(lpFileName); + walloc(lpBuffer, nBufferLength); + + // lpFilePart is not supported + if (lpFilePart != NULL) goto out; + + ret = GetFullPathNameW(wlpFileName, nBufferLength, wlpBuffer, &wlpFilePart); + err = GetLastError(); + if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) { + err = GetLastError(); + } + +out: + wfree(lpBuffer); + wfree(lpFileName); + SetLastError(err); + return ret; +} + +static __inline DWORD GetFileAttributesU(const char* lpFileName) +{ + DWORD ret = 0xFFFFFFFF, err = ERROR_INVALID_DATA; + wconvert(lpFileName); + // Unlike Microsoft's version, ours doesn't fail if the string is quoted + if ((wlpFileName[0] == L'"') && (wlpFileName[wcslen(wlpFileName) - 1] == L'"')) { + wlpFileName[wcslen(wlpFileName) - 1] = 0; + ret = GetFileAttributesW(&wlpFileName[1]); + } else { + ret = GetFileAttributesW(wlpFileName); + } + 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; + DWORD err = ERROR_INVALID_DATA; + wconvert(pszPath); + ret = SHCreateDirectoryExW(hwnd, wpszPath, psa); + err = GetLastError(); + wfree(pszPath); + SetLastError(err); + return ret; +} + +static __inline BOOL ShellExecuteExU(SHELLEXECUTEINFOA* lpExecInfo) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + SHELLEXECUTEINFOW wExecInfo; + + // Because we're lazy, we'll assume that the A and W structs inherently have the same size + if (lpExecInfo->cbSize != sizeof(SHELLEXECUTEINFOW)) { + SetLastError(ERROR_BAD_LENGTH); return FALSE; + } + memcpy(&wExecInfo, lpExecInfo, lpExecInfo->cbSize); + wExecInfo.lpVerb = utf8_to_wchar(lpExecInfo->lpVerb); + wExecInfo.lpFile = utf8_to_wchar(lpExecInfo->lpFile); + wExecInfo.lpParameters = utf8_to_wchar(lpExecInfo->lpParameters); + wExecInfo.lpDirectory = utf8_to_wchar(lpExecInfo->lpDirectory); + if (wExecInfo.fMask & SEE_MASK_CLASSNAME) { + wExecInfo.lpClass = utf8_to_wchar(lpExecInfo->lpClass); + } else { + wExecInfo.lpClass = NULL; + } + ret = ShellExecuteExW(&wExecInfo); + err = GetLastError(); + // Copy the returned values back + lpExecInfo->hInstApp = wExecInfo.hInstApp; + lpExecInfo->hProcess = wExecInfo.hProcess; + sfree(wExecInfo.lpVerb); + sfree(wExecInfo.lpFile); + sfree(wExecInfo.lpParameters); + sfree(wExecInfo.lpDirectory); + sfree(wExecInfo.lpClass); + SetLastError(err); + return ret; +} + +// Doesn't support LPSTARTUPINFOEX struct +static __inline BOOL CreateProcessU(const char* lpApplicationName, const char* lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, + LPVOID lpEnvironment, const char* lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + STARTUPINFOW wStartupInfo; + wconvert(lpApplicationName); + wconvert(lpCommandLine); + wconvert(lpCurrentDirectory); + + // Because we're lazy, we'll assume that the A and W structs inherently have the same size + // Also prevents the use of STARTUPINFOEX + if (lpStartupInfo->cb != sizeof(STARTUPINFOW)) { + err = ERROR_BAD_LENGTH; goto out; + } + memcpy(&wStartupInfo, lpStartupInfo, lpStartupInfo->cb); + wStartupInfo.lpDesktop = utf8_to_wchar(lpStartupInfo->lpDesktop); + wStartupInfo.lpTitle = utf8_to_wchar(lpStartupInfo->lpTitle); + ret = CreateProcessW(wlpApplicationName, wlpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, + dwCreationFlags, lpEnvironment, wlpCurrentDirectory, &wStartupInfo, lpProcessInformation); + err = GetLastError(); + sfree(wStartupInfo.lpDesktop); + sfree(wStartupInfo.lpTitle); +out: + wfree(lpApplicationName); + wfree(lpCommandLine); + wfree(lpCurrentDirectory); + SetLastError(err); + return ret; +} + +// NOTE: when used, nFileOffset & nFileExtension MUST be provided +// in number of Unicode characters, NOT number of UTF-8 bytes +static __inline BOOL WINAPI GetOpenSaveFileNameU(LPOPENFILENAMEA lpofn, BOOL save) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + size_t i, len; + OPENFILENAMEW wofn; + memset(&wofn, 0, sizeof(wofn)); + wofn.lStructSize = sizeof(wofn); + wofn.hwndOwner = lpofn->hwndOwner; + wofn.hInstance = lpofn->hInstance; + + // No support for custom filters + if (lpofn->lpstrCustomFilter != NULL) goto out; + + // Count on Microsoft to use an moronic scheme for filters + // that relies on NULL separators and double NULL terminators + if (lpofn->lpstrFilter != NULL) { + // Replace the NULLs by something that can be converted + for (i=0; ; i++) { + if (lpofn->lpstrFilter[i] == 0) { + ((char*)lpofn->lpstrFilter)[i] = '\r'; + if (lpofn->lpstrFilter[i+1] == 0) { + break; + } + } + } + wofn.lpstrFilter = utf8_to_wchar(lpofn->lpstrFilter); + // And revert + len = wcslen(wofn.lpstrFilter); // don't use in the loop as it would be reevaluated + for (i=0; ilpstrFilter); + for (i=0; ilpstrFilter[i] == '\r') { + ((char*)lpofn->lpstrFilter)[i] = 0; + } + } + } else { + wofn.lpstrFilter = NULL; + } + wofn.nMaxCustFilter = lpofn->nMaxCustFilter; + wofn.nFilterIndex = lpofn->nFilterIndex; + wofn.lpstrFile = 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)); + utf8_to_wchar_no_alloc(lpofn->lpstrFileTitle, wofn.lpstrFileTitle, lpofn->nMaxFileTitle); + wofn.nMaxFileTitle = lpofn->nMaxFileTitle; + wofn.lpstrInitialDir = utf8_to_wchar(lpofn->lpstrInitialDir); + wofn.lpstrTitle = utf8_to_wchar(lpofn->lpstrTitle); + wofn.Flags = lpofn->Flags; + wofn.nFileOffset = lpofn->nFileOffset; + wofn.nFileExtension = lpofn->nFileExtension; + wofn.lpstrDefExt = utf8_to_wchar(lpofn->lpstrDefExt); + wofn.lCustData = lpofn->lCustData; + wofn.lpfnHook = lpofn->lpfnHook; + wofn.lpTemplateName = utf8_to_wchar(lpofn->lpTemplateName); + wofn.pvReserved = lpofn->pvReserved; + wofn.dwReserved = lpofn->dwReserved; + wofn.FlagsEx = lpofn->FlagsEx; + + if (save) { + ret = GetSaveFileNameW(&wofn); + } else { + ret = GetOpenFileNameW(&wofn); + } + err = GetLastError(); + if ( (ret) + && ( (wchar_to_utf8_no_alloc(wofn.lpstrFile, lpofn->lpstrFile, lpofn->nMaxFile) == 0) + || (wchar_to_utf8_no_alloc(wofn.lpstrFileTitle, lpofn->lpstrFileTitle, lpofn->nMaxFileTitle) == 0) ) ) { + err = GetLastError(); + ret = FALSE; + } +out: + sfree(wofn.lpstrDefExt); + sfree(wofn.lpstrFile); + sfree(wofn.lpstrFileTitle); + sfree(wofn.lpstrFilter); + sfree(wofn.lpstrInitialDir); + sfree(wofn.lpstrTitle); + sfree(wofn.lpTemplateName); + SetLastError(err); + return ret; +} + +extern BOOL WINAPI UpdateDriverForPlugAndPlayDevicesW(HWND hwndParent, LPCWSTR HardwareId, + LPCWSTR FullInfPath, DWORD InstallFlags, PBOOL bRebootRequired); + +static __inline BOOL UpdateDriverForPlugAndPlayDevicesU(HWND hwndParent, const char* HardwareId, const char* FullInfPath, + DWORD InstallFlags, PBOOL bRebootRequired) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(HardwareId); + wconvert(FullInfPath); + ret = UpdateDriverForPlugAndPlayDevicesW(hwndParent, wHardwareId, wFullInfPath, InstallFlags, bRebootRequired); + err = GetLastError(); + wfree(HardwareId); + wfree(FullInfPath); + SetLastError(err); + return ret; +} + +static __inline BOOL SetupCopyOEMInfU(const char* SourceInfFileName, const char* OEMSourceMediaLocation, DWORD OEMSourceMediaType, + DWORD CopyStyle, char* DestinationInfFileName, DWORD DestinationInfFileNameSize, + PDWORD RequiredSize, PTSTR DestinationInfFileNameComponent) +{ + BOOL ret = FALSE; + DWORD err = ERROR_INVALID_DATA; + wconvert(SourceInfFileName); + wconvert(OEMSourceMediaLocation); + walloc(DestinationInfFileName, DestinationInfFileNameSize); + + // DestinationInfFileNameComponent is not supported + if (DestinationInfFileNameComponent != NULL) goto out; + + ret = SetupCopyOEMInfW(wSourceInfFileName, wOEMSourceMediaLocation, OEMSourceMediaType, CopyStyle, + wDestinationInfFileName, DestinationInfFileNameSize, RequiredSize, NULL); + err = GetLastError(); + if ((ret != FALSE) && ((ret = wchar_to_utf8_no_alloc(wDestinationInfFileName, DestinationInfFileName, DestinationInfFileNameSize)) == 0)) { + err = GetLastError(); + } +out: + wfree(SourceInfFileName); + wfree(OEMSourceMediaLocation); + wfree(DestinationInfFileName); + SetLastError(err); + return ret; +} + +static __inline int _chdirU(const char *dirname) +{ + int ret; + wconvert(dirname); + ret = _wchdir(wdirname); + wfree(dirname); + return ret; +} + +static __inline FILE* fopenU(const char* filename, const char* mode) +{ + FILE* ret = NULL; + wconvert(filename); + wconvert(mode); + ret = _wfopen(wfilename, wmode); + wfree(filename); + wfree(mode); + return ret; +} + +// returned UTF-8 string must be freed +static __inline char* getenvU(const char* varname) +{ + wconvert(varname); + char* ret; + ret = wchar_to_utf8(_wgetenv(wvarname)); + wfree(varname); + return ret; +} + +static __inline int _mkdirU(const char* dirname) +{ + wconvert(dirname); + int ret; + ret = _wmkdir(wdirname); + wfree(dirname); + return ret; +} + +#ifdef __cplusplus +} +#endif diff --git a/driver/source/libwdi/mssign32.h b/driver/source/libwdi/mssign32.h new file mode 100644 index 00000000..0d479790 --- /dev/null +++ b/driver/source/libwdi/mssign32.h @@ -0,0 +1,223 @@ +/* + * mssign32.h: MSSign32 interface for code signing + * + * Copyright (c) 2011-2013 Pete Batard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 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 + */ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MSSign32 definitions + * see http://msdn.microsoft.com/en-us/library/aa380252.aspx#signer_functions + */ + +// SIGNER_SUBJECT_INFO +#define SIGNER_SUBJECT_FILE 1 +#define SIGNER_SUBJECT_BLOB 2 +// SIGNER_CERT +#define SIGNER_CERT_SPC_FILE 1 +#define SIGNER_CERT_STORE 2 +#define SIGNER_CERT_SPC_CHAIN 3 +// SIGNER_SPC_CHAIN_INFO +#define SIGNER_CERT_POLICY_STORE 1 +#define SIGNER_CERT_POLICY_CHAIN 2 +#define SIGNER_CERT_POLICY_CHAIN_NO_ROOT 8 +// SIGNER_SIGNATURE_INFO +#define SIGNER_NO_ATTR 0 +#define SIGNER_AUTHCODE_ATTR 1 +// SIGNER_PROVIDER_INFO +#define PVK_TYPE_FILE_NAME 1 +#define PVK_TYPE_KEYCONTAINER 2 +// SignerSignEx +#define SPC_EXC_PE_PAGE_HASHES_FLAG 0x10 +#define SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG 0x20 +#define SPC_INC_PE_DEBUG_INFO_FLAG 0x40 +#define SPC_INC_PE_RESOURCES_FLAG 0x80 +#define SPC_INC_PE_PAGE_HASHES_FLAG 0x100 +/* + * The following is the data Microsoft adds on the + * SPC_SP_OPUS_INFO_OBJID and SPC_STATEMENT_TYPE_OBJID OIDs + */ +#define SP_OPUS_INFO_DATA { 0x30, 0x00 } +#define STATEMENT_TYPE_DATA { 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x15} + +typedef struct _SIGNER_FILE_INFO { + DWORD cbSize; + LPCWSTR pwszFileName; + HANDLE hFile; +} SIGNER_FILE_INFO, *PSIGNER_FILE_INFO; + +typedef struct _SIGNER_BLOB_INFO { + DWORD cbSize; + GUID *pGuidSubject; + DWORD cbBlob; + BYTE *pbBlob; + LPCWSTR pwszDisplayName; +} SIGNER_BLOB_INFO, *PSIGNER_BLOB_INFO; + +typedef struct _SIGNER_SUBJECT_INFO { + DWORD cbSize; + DWORD *pdwIndex; + DWORD dwSubjectChoice; + union { + SIGNER_FILE_INFO *pSignerFileInfo; + SIGNER_BLOB_INFO *pSignerBlobInfo; + }; +} SIGNER_SUBJECT_INFO, *PSIGNER_SUBJECT_INFO; + +typedef struct _SIGNER_CERT_STORE_INFO { + DWORD cbSize; + PCCERT_CONTEXT pSigningCert; + DWORD dwCertPolicy; + HCERTSTORE hCertStore; +} SIGNER_CERT_STORE_INFO, *PSIGNER_CERT_STORE_INFO; + +typedef struct _SIGNER_SPC_CHAIN_INFO { + DWORD cbSize; + LPCWSTR pwszSpcFile; + DWORD dwCertPolicy; + HCERTSTORE hCertStore; +} SIGNER_SPC_CHAIN_INFO, *PSIGNER_SPC_CHAIN_INFO; + +typedef struct _SIGNER_CERT { + DWORD cbSize; + DWORD dwCertChoice; + union { + LPCWSTR pwszSpcFile; + SIGNER_CERT_STORE_INFO *pCertStoreInfo; + SIGNER_SPC_CHAIN_INFO *pSpcChainInfo; + }; + HWND hwnd; +} SIGNER_CERT, *PSIGNER_CERT; + +typedef struct _SIGNER_ATTR_AUTHCODE { + DWORD cbSize; + BOOL fCommercial; + BOOL fIndividual; + LPCWSTR pwszName; + LPCWSTR pwszInfo; +} SIGNER_ATTR_AUTHCODE, *PSIGNER_ATTR_AUTHCODE; + +// MinGW32 doesn't know CRYPT_ATTRIBUTES +typedef struct _CRYPT_ATTRIBUTES_ARRAY { + DWORD cAttr; + PCRYPT_ATTRIBUTE rgAttr; +} CRYPT_ATTRIBUTES_ARRAY, *PCRYPT_ATTRIBUTES_ARRAY; + +typedef struct _SIGNER_SIGNATURE_INFO { + DWORD cbSize; + ALG_ID algidHash; + DWORD dwAttrChoice; + union { + SIGNER_ATTR_AUTHCODE *pAttrAuthcode; + }; + PCRYPT_ATTRIBUTES_ARRAY psAuthenticated; + PCRYPT_ATTRIBUTES_ARRAY psUnauthenticated; +} SIGNER_SIGNATURE_INFO, *PSIGNER_SIGNATURE_INFO; + +typedef struct _SIGNER_PROVIDER_INFO { + DWORD cbSize; + LPCWSTR pwszProviderName; + DWORD dwProviderType; + DWORD dwKeySpec; + DWORD dwPvkChoice; + union { + LPWSTR pwszPvkFileName; + LPWSTR pwszKeyContainer; + } ; +} SIGNER_PROVIDER_INFO, *PSIGNER_PROVIDER_INFO; + +typedef struct _SIGNER_CONTEXT { + DWORD cbSize; + DWORD cbBlob; + BYTE *pbBlob; +} SIGNER_CONTEXT, *PSIGNER_CONTEXT; + +/* + * typedefs for the function prototypes. Use the something like: + * PF_DELC(SignerSignEx); + * which translates to: + * SignerSignEx_t pfSignerSignEx = NULL; + * in your code, to declare the entrypoint and then use: + * PF_INIT(SignerSignEx, mssign32); + * which translates to: + * pfSignerSignEx = (SignerSignEx_t) GetProcAddress(GetDLLHandle("mssign32"), "SignerSignEx"); + * to make it accessible. + */ +typedef HRESULT (WINAPI *SignerFreeSignerContext_t)( + SIGNER_CONTEXT *pSignerContext +); + +typedef HRESULT (WINAPI *SignError_t)(void); + +typedef HRESULT (WINAPI *SignerSign_t)( + SIGNER_SUBJECT_INFO *pSubjectInfo, + SIGNER_CERT *pSignerCert, + SIGNER_SIGNATURE_INFO *pSignatureInfo, + SIGNER_PROVIDER_INFO *pProviderInfo, + LPCWSTR pwszHttpTimeStamp, + PCRYPT_ATTRIBUTES_ARRAY psRequest, + LPVOID pSipData +); + +typedef HRESULT (WINAPI *SignerSignEx_t)( + DWORD dwFlags, + SIGNER_SUBJECT_INFO *pSubjectInfo, + SIGNER_CERT *pSignerCert, + SIGNER_SIGNATURE_INFO *pSignatureInfo, + SIGNER_PROVIDER_INFO *pProviderInfo, + LPCWSTR pwszHttpTimeStamp, + PCRYPT_ATTRIBUTES_ARRAY psRequest, + LPVOID pSipData, + SIGNER_CONTEXT **ppSignerContext +); + +typedef HRESULT (WINAPI *SignerTimeStamp_t)( + SIGNER_SUBJECT_INFO *pSubjectInfo, + LPCWSTR pwszHttpTimeStamp, + PCRYPT_ATTRIBUTES_ARRAY psRequest, + LPVOID pSipData +); + +typedef HRESULT (WINAPI *SignerTimeStampEx_t)( + DWORD dwFlags, + SIGNER_SUBJECT_INFO *pSubjectInfo, + LPCWSTR pwszHttpTimeStamp, + PCRYPT_ATTRIBUTES_ARRAY psRequest, + LPVOID pSipData, + SIGNER_CONTEXT **ppSignerContext +); + +typedef HRESULT (WINAPI *SignerTimeStampEx2_t)( + DWORD dwFlags, + SIGNER_SUBJECT_INFO *pSubjectInfo, + LPCWSTR pwszHttpTimeStamp, + ALG_ID dwAlgId, + PCRYPT_ATTRIBUTES_ARRAY psRequest, + LPVOID pSipData, + SIGNER_CONTEXT **ppSignerContext +); + +#ifdef __cplusplus +} +#endif diff --git a/driver/source/libwdi/pki.c b/driver/source/libwdi/pki.c new file mode 100644 index 00000000..a5ae2e3e --- /dev/null +++ b/driver/source/libwdi/pki.c @@ -0,0 +1,1258 @@ +/* + * libwdi: Library for automated Windows Driver Installation - PKI part + * Copyright (c) 2011-2016 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 + * 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 + */ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mssign32.h" + +#include +#include "installer.h" +#include "libwdi.h" +#include "logging.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_SHA256RSA +#define szOID_RSA_SHA256RSA "1.2.840.113549.1.1.11" +#endif + +/* + * Crypt32.dll + */ +typedef HCERTSTORE (WINAPI *CertOpenStore_t)( + LPCSTR lpszStoreProvider, + DWORD dwMsgAndCertEncodingType, + ULONG_PTR hCryptProv, + DWORD dwFlags, + const void *pvPara +); + +typedef PCCERT_CONTEXT (WINAPI *CertCreateCertificateContext_t)( + DWORD dwCertEncodingType, + const BYTE *pbCertEncoded, + DWORD cbCertEncoded +); + +typedef PCCERT_CONTEXT (WINAPI *CertFindCertificateInStore_t)( + HCERTSTORE hCertStore, + DWORD dwCertEncodingType, + DWORD dwFindFlags, + DWORD dwFindType, + const void *pvFindPara, + PCCERT_CONTEXT pfPrevCertContext +); + +typedef BOOL (WINAPI *CertAddCertificateContextToStore_t)( + HCERTSTORE hCertStore, + PCCERT_CONTEXT pCertContext, + DWORD dwAddDisposition, + PCCERT_CONTEXT *pStoreContext +); + +typedef BOOL (WINAPI *CertSetCertificateContextProperty_t)( + PCCERT_CONTEXT pCertContext, + DWORD dwPropId, + DWORD dwFlags, + const void *pvData +); + +typedef BOOL (WINAPI *CertDeleteCertificateFromStore_t)( + PCCERT_CONTEXT pCertContext +); + +typedef BOOL (WINAPI *CertFreeCertificateContext_t)( + PCCERT_CONTEXT pCertContext +); + +typedef BOOL (WINAPI *CertCloseStore_t)( + HCERTSTORE hCertStore, + DWORD dwFlags +); + +typedef DWORD (WINAPI *CertGetNameStringA_t)( + PCCERT_CONTEXT pCertContext, + DWORD dwType, + DWORD dwFlags, + void *pvTypePara, + LPCSTR pszNameString, + DWORD cchNameString +); + +typedef BOOL (WINAPI *CryptEncodeObject_t)( + DWORD dwCertEncodingType, + LPCSTR lpszStructType, + const void *pvStructInfo, + BYTE *pbEncoded, + DWORD *pcbEncoded +); + +typedef BOOL (WINAPI *CryptDecodeObject_t)( + DWORD dwCertEncodingType, + LPCSTR lpszStructType, + const BYTE *pbEncoded, + DWORD cbEncoded, + DWORD dwFlags, + void *pvStructInfo, + DWORD *pcbStructInfo +); + +typedef BOOL (WINAPI *CertStrToNameA_t)( + DWORD dwCertEncodingType, + LPCSTR pszX500, + DWORD dwStrType, + void *pvReserved, + BYTE *pbEncoded, + DWORD *pcbEncoded, + LPCTSTR *ppszError +); + +typedef BOOL (WINAPI *CryptAcquireCertificatePrivateKey_t)( + PCCERT_CONTEXT pCert, + DWORD dwFlags, + void *pvReserved, + ULONG_PTR *phCryptProvOrNCryptKey, + DWORD *pdwKeySpec, + BOOL *pfCallerFreeProvOrNCryptKey +); + +typedef BOOL (WINAPI *CertAddEncodedCertificateToStore_t)( + HCERTSTORE hCertStore, + DWORD dwCertEncodingType, + const BYTE *pbCertEncoded, + DWORD cbCertEncoded, + DWORD dwAddDisposition, + PCCERT_CONTEXT *ppCertContext +); + +// MiNGW32 doesn't know CERT_EXTENSIONS => redef +typedef struct _CERT_EXTENSIONS_ARRAY { + DWORD cExtension; + PCERT_EXTENSION rgExtension; +} CERT_EXTENSIONS_ARRAY, *PCERT_EXTENSIONS_ARRAY; + +typedef PCCERT_CONTEXT (WINAPI *CertCreateSelfSignCertificate_t)( + ULONG_PTR hCryptProvOrNCryptKey, + PCERT_NAME_BLOB pSubjectIssuerBlob, + DWORD dwFlags, + PCRYPT_KEY_PROV_INFO pKeyProvInfo, + PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, + LPSYSTEMTIME pStartTime, + LPSYSTEMTIME pEndTime, + PCERT_EXTENSIONS_ARRAY pExtensions +); + +// MinGW32 doesn't have these ones either +#ifndef CERT_ALT_NAME_URL +#define CERT_ALT_NAME_URL 7 +#endif +#ifndef CERT_RDN_IA5_STRING +#define CERT_RDN_IA5_STRING 7 +#endif +#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; + CRYPT_OBJID_BLOB Qualifier; +} CERT_POLICY_QUALIFIER_INFO_REDEF, *PCERT_POLICY_QUALIFIER_INFO_REDEF; + +typedef struct _CERT_POLICY_INFO_ALT { + LPSTR pszPolicyIdentifier; + DWORD cPolicyQualifier; + PCERT_POLICY_QUALIFIER_INFO_REDEF rgPolicyQualifier; +} CERT_POLICY_INFO_REDEF, *PCERT_POLICY_INFO_REDEF; + +typedef struct _CERT_POLICIES_INFO_ARRAY { + DWORD cPolicyInfo; + PCERT_POLICY_INFO_REDEF rgPolicyInfo; +} CERT_POLICIES_INFO_ARRAY, *PCERT_POLICIES_INFO_ARRAY; + +/* + * WinTrust.dll + */ +#define CRYPTCAT_OPEN_CREATENEW 0x00000001 +#define CRYPTCAT_OPEN_ALWAYS 0x00000002 + +#define CRYPTCAT_ATTR_AUTHENTICATED 0x10000000 +#define CRYPTCAT_ATTR_UNAUTHENTICATED 0x20000000 +#define CRYPTCAT_ATTR_NAMEASCII 0x00000001 +#define CRYPTCAT_ATTR_NAMEOBJID 0x00000002 +#define CRYPTCAT_ATTR_DATAASCII 0x00010000 +#define CRYPTCAT_ATTR_DATABASE64 0x00020000 +#define CRYPTCAT_ATTR_DATAREPLACE 0x00040000 + +#define SPC_UUID_LENGTH 16 +#define SPC_URL_LINK_CHOICE 1 +#define SPC_MONIKER_LINK_CHOICE 2 +#define SPC_FILE_LINK_CHOICE 3 +#define SHA1_HASH_LENGTH 20 +#define SPC_PE_IMAGE_DATA_OBJID "1.3.6.1.4.1.311.2.1.15" +#define SPC_CAB_DATA_OBJID "1.3.6.1.4.1.311.2.1.25" + +typedef BYTE SPC_UUID[SPC_UUID_LENGTH]; +typedef struct _SPC_SERIALIZED_OBJECT { + SPC_UUID ClassId; + CRYPT_DATA_BLOB SerializedData; +} SPC_SERIALIZED_OBJECT,*PSPC_SERIALIZED_OBJECT; + +typedef struct SPC_LINK_ { + DWORD dwLinkChoice; + union { + LPWSTR pwszUrl; + SPC_SERIALIZED_OBJECT Moniker; + LPWSTR pwszFile; + }; +} SPC_LINK,*PSPC_LINK; + +typedef struct _SPC_PE_IMAGE_DATA { + CRYPT_BIT_BLOB Flags; + PSPC_LINK pFile; +} SPC_PE_IMAGE_DATA,*PSPC_PE_IMAGE_DATA; + +// MinGW32 doesn't know this one either +typedef struct _CRYPT_ATTRIBUTE_TYPE_VALUE_REDEF { + LPSTR pszObjId; + CRYPT_OBJID_BLOB Value; +} CRYPT_ATTRIBUTE_TYPE_VALUE_REDEF; + +typedef struct SIP_INDIRECT_DATA_ { + CRYPT_ATTRIBUTE_TYPE_VALUE_REDEF Data; + CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm; + CRYPT_HASH_BLOB Digest; +} SIP_INDIRECT_DATA, *PSIP_INDIRECT_DATA; + +typedef struct CRYPTCATSTORE_ { + DWORD cbStruct; + DWORD dwPublicVersion; + LPWSTR pwszP7File; + HCRYPTPROV hProv; + DWORD dwEncodingType; + DWORD fdwStoreFlags; + HANDLE hReserved; + HANDLE hAttrs; + HCRYPTMSG hCryptMsg; + HANDLE hSorted; +} CRYPTCATSTORE; + +typedef struct CRYPTCATMEMBER_ { + DWORD cbStruct; + LPWSTR pwszReferenceTag; + LPWSTR pwszFileName; + GUID gSubjectType; + DWORD fdwMemberFlags; + PSIP_INDIRECT_DATA pIndirectData; + DWORD dwCertVersion; + DWORD dwReserved; + HANDLE hReserved; + CRYPT_ATTR_BLOB sEncodedIndirectData; + CRYPT_ATTR_BLOB sEncodedMemberInfo; +} CRYPTCATMEMBER; + +typedef struct CRYPTCATATTRIBUTE_ { + DWORD cbStruct; + LPWSTR pwszReferenceTag; + DWORD dwAttrTypeAndAction; + DWORD cbValue; + BYTE *pbValue; + DWORD dwReserved; +} CRYPTCATATTRIBUTE; + +typedef HANDLE (WINAPI *CryptCATOpen_t)( + LPWSTR pwszFileName, + DWORD fdwOpenFlags, + ULONG_PTR hProv, + DWORD dwPublicVersion, + DWORD dwEncodingType +); + +typedef BOOL (WINAPI *CryptCATClose_t)( + HANDLE hCatalog +); + +typedef CRYPTCATSTORE* (WINAPI *CryptCATStoreFromHandle_t)( + HANDLE hCatalog +); + +typedef CRYPTCATATTRIBUTE* (WINAPI *CryptCATEnumerateCatAttr_t)( + HANDLE hCatalog, + CRYPTCATATTRIBUTE *pPrevAttr +); + +typedef CRYPTCATATTRIBUTE* (WINAPI *CryptCATPutCatAttrInfo_t)( + HANDLE hCatalog, + LPWSTR pwszReferenceTag, + DWORD dwAttrTypeAndAction, + DWORD cbData, + BYTE *pbData +); + +typedef CRYPTCATMEMBER* (WINAPI *CryptCATEnumerateMember_t)( + HANDLE hCatalog, + CRYPTCATMEMBER *pPrevMember +); + +typedef CRYPTCATMEMBER* (WINAPI *CryptCATPutMemberInfo_t)( + HANDLE hCatalog, + LPWSTR pwszFileName, + LPWSTR pwszReferenceTag, + GUID *pgSubjectType, + DWORD dwCertVersion, + DWORD cbSIPIndirectData, + BYTE *pbSIPIndirectData +); + +typedef CRYPTCATATTRIBUTE* (WINAPI *CryptCATEnumerateAttr_t)( + HANDLE hCatalog, + CRYPTCATMEMBER *pCatMember, + CRYPTCATATTRIBUTE *pPrevAttr +); + +typedef CRYPTCATATTRIBUTE* (WINAPI *CryptCATPutAttrInfo_t)( + HANDLE hCatalog, + CRYPTCATMEMBER *pCatMember, + LPWSTR pwszReferenceTag, + DWORD dwAttrTypeAndAction, + DWORD cbData, + BYTE *pbData +); + +typedef BOOL (WINAPI *CryptCATPersistStore_t)( + HANDLE hCatalog +); + +typedef BOOL (WINAPI *CryptCATAdminCalcHashFromFileHandle_t)( + HANDLE hFile, + DWORD *pcbHash, + BYTE *pbHash, + DWORD dwFlags +); + +extern char *windows_error_str(uint32_t retval); + +/* + * Convert an UTF8 string to UTF-16 (allocate returned string) + * Return NULL on error + */ +static __inline LPWSTR UTF8toWCHAR(LPCSTR szStr) +{ + int size = 0; + LPWSTR wszStr = NULL; + + // Find out the size we need to allocate for our converted string + size = MultiByteToWideChar(CP_UTF8, 0, szStr, -1, NULL, 0); + if (size <= 1) // An empty string would be size 1 + return NULL; + + if ((wszStr = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL) + return NULL; + if (MultiByteToWideChar(CP_UTF8, 0, szStr, -1, wszStr, size) != size) { + free(wszStr); + return NULL; + } + return wszStr; +} + +/* + * Parts of the following functions are based on: + * http://blogs.msdn.com/b/alejacma/archive/2009/03/16/how-to-create-a-self-signed-certificate-with-cryptoapi-c.aspx + * http://blogs.msdn.com/b/alejacma/archive/2008/12/11/how-to-sign-exe-files-with-an-authenticode-certificate-part-2.aspx + * http://www.jensign.com/hash/index.html + */ + +/* + * Add a certificate, identified by its pCertContext, to the system store 'szStoreName' + */ +BOOL AddCertToStore(PCCERT_CONTEXT pCertContext, LPCSTR szStoreName) +{ + PF_DECL(CertOpenStore); + PF_DECL(CertSetCertificateContextProperty); + PF_DECL(CertAddCertificateContextToStore); + PF_DECL(CertCloseStore); + HCERTSTORE hSystemStore = NULL; + CRYPT_DATA_BLOB libwdiNameBlob = {14, (BYTE*)L"libwdi"}; + BOOL r = FALSE; + + PF_INIT_OR_OUT(CertOpenStore, crypt32); + PF_INIT_OR_OUT(CertSetCertificateContextProperty, crypt32); + PF_INIT_OR_OUT(CertAddCertificateContextToStore, crypt32); + PF_INIT_OR_OUT(CertCloseStore, crypt32); + + 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)); + goto out; + } + + if (!pfCertSetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, 0, &libwdiNameBlob)) { + wdi_warn("coud not set friendly name: %s", windows_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)); + goto out; + } + r = TRUE; + +out: + if (hSystemStore != NULL) pfCertCloseStore(hSystemStore, 0); + return r; +} + +/* + * Remove a certificate, identified by its subject, to the system store 'szStoreName' + */ +BOOL RemoveCertFromStore(LPCSTR szCertSubject, LPCSTR szStoreName) +{ + PF_DECL(CertOpenStore); + PF_DECL(CertFindCertificateInStore); + PF_DECL(CertDeleteCertificateFromStore); + PF_DECL(CertCloseStore); + PF_DECL(CertStrToNameA); + HCERTSTORE hSystemStore = NULL; + PCCERT_CONTEXT pCertContext; + CERT_NAME_BLOB certNameBlob = {0, NULL}; + BOOL r = FALSE; + + PF_INIT_OR_OUT(CertOpenStore, crypt32); + PF_INIT_OR_OUT(CertFindCertificateInStore, crypt32); + PF_INIT_OR_OUT(CertDeleteCertificateFromStore, crypt32); + PF_INIT_OR_OUT(CertCloseStore, crypt32); + PF_INIT_OR_OUT(CertStrToNameA, crypt32); + + 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)); + goto out; + } + + // Encode Cert Name + 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)); + 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); + } + r = TRUE; + +out: + if (certNameBlob.pbData != NULL) free (certNameBlob.pbData); + if (hSystemStore != NULL) pfCertCloseStore(hSystemStore, 0); + return r; +} + +/* + * Add certificate data to the TrustedPublisher system store + * Unless bDisableWarning is set, warn the user before install + */ +BOOL AddCertToTrustedPublisher(BYTE* pbCertData, DWORD dwCertSize, BOOL bDisableWarning, HWND hWnd) +{ + PF_DECL(CertOpenStore); + PF_DECL(CertCreateCertificateContext); + PF_DECL(CertFindCertificateInStore); + PF_DECL(CertAddCertificateContextToStore); + PF_DECL(CertFreeCertificateContext); + PF_DECL(CertGetNameStringA); + PF_DECL(CertCloseStore); + BOOL r = FALSE; + int user_input; + HCERTSTORE hSystemStore = NULL; + PCCERT_CONTEXT pCertContext = NULL, pStoreCertContext = NULL; + char org[MAX_PATH], org_unit[MAX_PATH]; + char msg_string[1024]; + + PF_INIT_OR_OUT(CertOpenStore, crypt32); + PF_INIT_OR_OUT(CertCreateCertificateContext, crypt32); + PF_INIT_OR_OUT(CertFindCertificateInStore, crypt32); + PF_INIT_OR_OUT(CertAddCertificateContextToStore, crypt32); + PF_INIT_OR_OUT(CertFreeCertificateContext, crypt32); + PF_INIT_OR_OUT(CertGetNameStringA, crypt32); + PF_INIT_OR_OUT(CertCloseStore, crypt32); + + hSystemStore = pfCertOpenStore(CERT_STORE_PROV_SYSTEM_A, X509_ASN_ENCODING, + 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher"); + + if (hSystemStore == NULL) { + wdi_warn("unable to open system store: %s", windows_error_str(0)); + goto out; + } + + /* Check whether certificate already exists + * We have to do this manually, so that we can produce a warning to the user + * before any certificate is added to the store (first time or update) + */ + pCertContext = pfCertCreateCertificateContext(X509_ASN_ENCODING, pbCertData, dwCertSize); + + if (pCertContext == NULL) { + wdi_warn("could not create context for certificate: %s", windows_error_str(0)); + pfCertCloseStore(hSystemStore, 0); + goto out; + } + + pStoreCertContext = pfCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, + CERT_FIND_EXISTING, (const void*)pCertContext, NULL); + if (pStoreCertContext == NULL) { + user_input = IDOK; + if (!bDisableWarning) { + 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" + "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" + "If this is not what you want, you can cancel this operation now.", org, + (org_unit[0] != 0)?" (":"", org_unit, (org_unit[0] != 0)?")":""); + user_input = MessageBoxA(hWnd, msg_string, + "Warning: Trusted Certificate installation", MB_OKCANCEL | MB_ICONWARNING); + } + if (user_input != IDOK) { + 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)); + } else { + r = TRUE; + } + } + } else { + r = TRUE; // Cert already exists + } + +out: + if (pCertContext != NULL) pfCertFreeCertificateContext(pCertContext); + if (pStoreCertContext != NULL) pfCertFreeCertificateContext(pStoreCertContext); + if (hSystemStore) pfCertCloseStore(hSystemStore, 0); + return r; +} + +/* + * Create a self signed certificate for code signing + */ +PCCERT_CONTEXT CreateSelfSignedCert(LPCSTR szCertSubject) +{ + PF_DECL(CryptEncodeObject); + PF_DECL(CertStrToNameA); + PF_DECL(CertCreateSelfSignCertificate); + PF_DECL(CertFreeCertificateContext); + + DWORD dwSize; + HCRYPTPROV hCSP = 0; + HCRYPTKEY hKey = 0; + PCCERT_CONTEXT pCertContext = NULL; + CERT_NAME_BLOB SubjectIssuerBlob = {0, NULL}; + CRYPT_KEY_PROV_INFO KeyProvInfo; + CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; + LPWSTR wszKeyContainer = KEY_CONTAINER; + LPBYTE pbEnhKeyUsage = NULL, pbAltNameInfo = NULL, pbCPSNotice = NULL, pbPolicyInfo = NULL; + SYSTEMTIME sExpirationDate = { 2029, 01, 01, 01, 00, 00, 00, 000 }; + CERT_EXTENSION certExtension[3]; + CERT_EXTENSIONS_ARRAY certExtensionsArray; + // 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 }; + // Certificate Policies + CERT_POLICY_QUALIFIER_INFO_REDEF certPolicyQualifier; + CERT_POLICY_INFO_REDEF certPolicyInfo = { "1.3.6.1.5.5.7.2.1", 1, &certPolicyQualifier }; + CERT_POLICIES_INFO_ARRAY certPolicyInfoArray = { 1, &certPolicyInfo }; + CHAR szCPSName[] = "http://libwdi-cps.akeo.ie"; + CERT_NAME_VALUE certCPSValue; + + PF_INIT_OR_OUT(CryptEncodeObject, crypt32); + PF_INIT_OR_OUT(CertStrToNameA, crypt32); + PF_INIT_OR_OUT(CertCreateSelfSignCertificate, crypt32); + PF_INIT_OR_OUT(CertFreeCertificateContext, crypt32); + + // Set Enhanced Key Usage extension to Code Signing only + 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)); + goto out; + } + certExtension[0].pszObjId = szOID_ENHANCED_KEY_USAGE; + certExtension[0].fCritical = TRUE; // only allow code signing + certExtension[0].Value.cbData = dwSize; + certExtension[0].Value.pbData = pbEnhKeyUsage; + + // Set URL as 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)); + goto out; + } + certExtension[1].pszObjId = szOID_SUBJECT_ALT_NAME; + certExtension[1].fCritical = FALSE; + certExtension[1].Value.cbData = dwSize; + certExtension[1].Value.pbData = pbAltNameInfo; + + // Set the CPS Certificate Policies field - this enables the "Issuer Statement" button on the cert + certCPSValue.dwValueType = CERT_RDN_IA5_STRING; + certCPSValue.Value.cbData = sizeof(szCPSName); + certCPSValue.Value.pbData = (BYTE*)szCPSName; + 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)); + goto out; + } + + certPolicyQualifier.pszPolicyQualifierId = szOID_PKIX_POLICY_QUALIFIER_CPS; + certPolicyQualifier.Qualifier.cbData = dwSize; + certPolicyQualifier.Qualifier.pbData = pbCPSNotice; + 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)); + goto out; + } + certExtension[2].pszObjId = szOID_CERT_POLICIES; + certExtension[2].fCritical = FALSE; + certExtension[2].Value.cbData = dwSize; + certExtension[2].Value.pbData = pbPolicyInfo; + + certExtensionsArray.cExtension = ARRAYSIZE(certExtension); + certExtensionsArray.rgExtension = certExtension; + 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) + && (CryptAcquireContextW(&hCSP, wszKeyContainer, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET|CRYPT_SILENT)) ) { + wdi_dbg("created new key container"); + } else { + wdi_warn("could not obtain a key container: %s", windows_error_str(0)); + 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)); + goto out; + } + 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)); + goto out; + } + + // Prepare key provider structure for self-signed certificate + memset(&KeyProvInfo, 0, sizeof(KeyProvInfo)); + KeyProvInfo.pwszContainerName = wszKeyContainer; + KeyProvInfo.pwszProvName = NULL; + KeyProvInfo.dwProvType = PROV_RSA_FULL; + KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET; + KeyProvInfo.cProvParam = 0; + KeyProvInfo.rgProvParam = NULL; + KeyProvInfo.dwKeySpec = AT_SIGNATURE; + + // Prepare algorithm structure for self-signed certificate + memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm)); + SignatureAlgorithm.pszObjId = szOID_RSA_SHA256RSA; + + // 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)); + goto out; + } + wdi_info("created new self-signed certificate '%s'", szCertSubject); + +out: + if (pbEnhKeyUsage != NULL) free(pbEnhKeyUsage); + if (pbAltNameInfo != NULL) free(pbAltNameInfo); + if (pbCPSNotice != NULL) free(pbCPSNotice); + if (pbPolicyInfo != NULL) free(pbPolicyInfo); + if (SubjectIssuerBlob.pbData != NULL) free(SubjectIssuerBlob.pbData); + if (hKey) CryptDestroyKey(hKey); + if (hCSP) CryptReleaseContext(hCSP, 0); + return pCertContext; +} + +/* + * Delete the private key associated with a specific cert + */ +BOOL DeletePrivateKey(PCCERT_CONTEXT pCertContext) +{ + PF_DECL(CryptAcquireCertificatePrivateKey); + PF_DECL(CertOpenStore); + PF_DECL(CertCloseStore); + PF_DECL(CertAddEncodedCertificateToStore); + PF_DECL(CertSetCertificateContextProperty); + PF_DECL(CertFreeCertificateContext); + + LPWSTR wszKeyContainer = KEY_CONTAINER; + HCRYPTPROV hCSP = 0; + DWORD dwKeySpec; + BOOL bFreeCSP = FALSE, r = FALSE; + HCERTSTORE hSystemStore; + LPCSTR szStoresToUpdate[2] = { "Root", "TrustedPublisher" }; + CRYPT_DATA_BLOB libwdiNameBlob = {14, (BYTE*)L"libwdi"}; + PCCERT_CONTEXT pCertContextUpdate = NULL; + int i; + + PF_INIT_OR_OUT(CryptAcquireCertificatePrivateKey, crypt32); + PF_INIT_OR_OUT(CertOpenStore, crypt32); + PF_INIT_OR_OUT(CertCloseStore, crypt32); + PF_INIT_OR_OUT(CertAddEncodedCertificateToStore, crypt32); + PF_INIT_OR_OUT(CertSetCertificateContextProperty, crypt32); + 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)); + 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)); + } + + // This is optional, but unless we reimport the cert data after having deleted the key + // end users will still see a "You have a private key that corresponds to this certificate" message. + for (i=0; ipbCertEncoded, + 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)); + } + pfCertFreeCertificateContext(pCertContextUpdate); + } else { + wdi_warn("failed to update '%s': %s", szStoresToUpdate[i], windows_error_str(0)); + } + pfCertCloseStore(hSystemStore, 0); + } + + r= TRUE; + +out: + if ((bFreeCSP) && (hCSP)) { + CryptReleaseContext(hCSP, 0); + } + return r; +} + +/* + * Digitally sign a file and make it system-trusted by: + * - creating a self signed certificate for code signing + * - adding this certificate to both the Root and TrustedPublisher system stores + * - signing the file provided + * - deleting the self signed certificate private key so that it cannot be reused + */ +BOOL SelfSignFile(LPCSTR szFileName, LPCSTR szCertSubject) +{ + PF_DECL(SignerSignEx); + PF_DECL(SignerFreeSignerContext); + PF_DECL(CertFreeCertificateContext); + PF_DECL(CertCloseStore); + + BOOL r = FALSE; + LPWSTR wszFileName = NULL; + HRESULT hResult = S_OK; + PCCERT_CONTEXT pCertContext = NULL; + DWORD dwIndex; + SIGNER_FILE_INFO signerFileInfo; + SIGNER_SUBJECT_INFO signerSubjectInfo; + SIGNER_CERT_STORE_INFO signerCertStoreInfo; + SIGNER_CERT signerCert; + SIGNER_SIGNATURE_INFO signerSignatureInfo; + PSIGNER_CONTEXT pSignerContext = NULL; + CRYPT_ATTRIBUTES_ARRAY cryptAttributesArray; + CRYPT_ATTRIBUTE cryptAttribute[2]; + CRYPT_INTEGER_BLOB oidSpOpusInfoBlob, oidStatementTypeBlob; + BYTE pbOidSpOpusInfo[] = SP_OPUS_INFO_DATA; + BYTE pbOidStatementType[] = STATEMENT_TYPE_DATA; + + PF_INIT_OR_OUT(SignerSignEx, mssign32); + PF_INIT_OR_OUT(SignerFreeSignerContext, mssign32); + PF_INIT_OR_OUT(CertFreeCertificateContext, crypt32); + PF_INIT_OR_OUT(CertCloseStore, crypt32); + + // Delete any previous certificate with the same subject + RemoveCertFromStore(szCertSubject, "Root"); + RemoveCertFromStore(szCertSubject, "TrustedPublisher"); + + pCertContext = CreateSelfSignedCert(szCertSubject); + if (pCertContext == NULL) { + goto out; + } + 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); + + // 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"); + goto out; + } + signerFileInfo.pwszFileName = wszFileName; + signerFileInfo.hFile = NULL; + + // Prepare SIGNER_SUBJECT_INFO struct + signerSubjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO); + dwIndex = 0; + signerSubjectInfo.pdwIndex = &dwIndex; + signerSubjectInfo.dwSubjectChoice = SIGNER_SUBJECT_FILE; + signerSubjectInfo.pSignerFileInfo = &signerFileInfo; + + // Prepare SIGNER_CERT_STORE_INFO struct + signerCertStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO); + signerCertStoreInfo.pSigningCert = pCertContext; + signerCertStoreInfo.dwCertPolicy = SIGNER_CERT_POLICY_CHAIN; + signerCertStoreInfo.hCertStore = NULL; + + // Prepare SIGNER_CERT struct + signerCert.cbSize = sizeof(SIGNER_CERT); + signerCert.dwCertChoice = SIGNER_CERT_STORE; + signerCert.pCertStoreInfo = &signerCertStoreInfo; + signerCert.hwnd = NULL; + + // Prepare the additional Authenticode OIDs + oidSpOpusInfoBlob.cbData = sizeof(pbOidSpOpusInfo); + oidSpOpusInfoBlob.pbData = pbOidSpOpusInfo; + oidStatementTypeBlob.cbData = sizeof(pbOidStatementType); + oidStatementTypeBlob.pbData = pbOidStatementType; + cryptAttribute[0].cValue = 1; + cryptAttribute[0].rgValue = &oidSpOpusInfoBlob; + cryptAttribute[0].pszObjId = "1.3.6.1.4.1.311.2.1.12"; // SPC_SP_OPUS_INFO_OBJID in wintrust.h + cryptAttribute[1].cValue = 1; + cryptAttribute[1].rgValue = &oidStatementTypeBlob; + cryptAttribute[1].pszObjId = "1.3.6.1.4.1.311.2.1.11"; // SPC_STATEMENT_TYPE_OBJID in wintrust.h + cryptAttributesArray.cAttr = 2; + cryptAttributesArray.rgAttr = cryptAttribute; + + // Prepare SIGNER_SIGNATURE_INFO struct + signerSignatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO); + signerSignatureInfo.algidHash = CALG_SHA_256; + signerSignatureInfo.dwAttrChoice = SIGNER_NO_ATTR; + signerSignatureInfo.pAttrAuthcode = NULL; + signerSignatureInfo.psAuthenticated = &cryptAttributesArray; + signerSignatureInfo.psUnauthenticated = NULL; + + // 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)); + goto out; + } + r = TRUE; + wdi_info("successfully signed file '%s'", szFileName); + + // Clean up +out: + /* + * Because we installed our certificate as a Root CA as well as a Trusted Publisher + * we *MUST* ensure that the private key is destroyed, so that it cannot be reused + * by an attacker to self sign a malicious applications. + */ + if ((pCertContext != NULL) && (DeletePrivateKey(pCertContext))) { + wdi_info("successfully deleted private key"); + } + if (wszFileName != NULL) free((void*)wszFileName); + if (pSignerContext != NULL) pfSignerFreeSignerContext(pSignerContext); + if (pCertContext != NULL) pfCertFreeCertificateContext(pCertContext); + + return r; +} + +/* + * Opens a file and computes the SHA1 Authenticode Hash + */ +static BOOL CalcHash(BYTE* pbHash, LPCSTR szfilePath) +{ + PF_DECL(CryptCATAdminCalcHashFromFileHandle); + BOOL r = FALSE; + HANDLE hFile = NULL; + DWORD cbHash = SHA1_HASH_LENGTH; + LPWSTR wszFilePath = NULL; + + PF_INIT_OR_OUT(CryptCATAdminCalcHashFromFileHandle, wintrust); + + // Compute the SHA1 hash + wszFilePath = UTF8toWCHAR(szfilePath); + hFile = CreateFileW(wszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) goto out; + if ( (!pfCryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, pbHash, 0)) ) goto out; + r = TRUE; + +out: + if (wszFilePath != NULL) free(wszFilePath); + if (hFile) CloseHandle(hFile); + return r; +} + +/* + * Add a new member to a cat file, containing the hash for the relevant file + */ +static BOOL AddFileHash(HANDLE hCat, LPCSTR szFileName, BYTE* pbFileHash) +{ + const GUID inf_guid = {0xDE351A42, 0x8E59, 0x11D0, {0x8C, 0x47, 0x00, 0xC0, 0x4F, 0xC2, 0x95, 0xEE}}; + const GUID pe_guid = {0xC689AAB8, 0x8E78, 0x11D0, {0x8C, 0x47, 0x00, 0xC0, 0x4F, 0xC2, 0x95, 0xEE}}; + const BYTE fImageData = 0xA0; // Flags used for the SPC_PE_IMAGE_DATA "<<>>" link + LPCWSTR wszOSAttr = L"2:5.1,2:5.2,2:6.0,2:6.1"; + + PF_DECL(CryptCATPutMemberInfo); + PF_DECL(CryptCATPutAttrInfo); + PF_DECL(CryptEncodeObject); + + BOOL bPEType = TRUE; + CRYPTCATMEMBER* pCatMember = NULL; + SIP_INDIRECT_DATA sSIPData; + SPC_LINK sSPCLink; + SPC_PE_IMAGE_DATA sSPCImageData; + WCHAR wszHash[2*SHA1_HASH_LENGTH+1]; + LPWSTR wszFileName = NULL; + LPCSTR szExt; + LPSTR szExtCopy = NULL; + BYTE pbEncoded[64]; + DWORD cbEncoded; + int i; + BOOL r= FALSE; + + PF_INIT_OR_OUT(CryptCATPutMemberInfo, wintrust); + PF_INIT_OR_OUT(CryptCATPutAttrInfo, wintrust); + PF_INIT_OR_OUT(CryptEncodeObject, crypt32); + + // Create the required UTF-16 strings + for (i=0; i szFileName) && (*szExt!='.'); szExt--); + if (szExt == szFileName) { + wdi_warn("unhandled file type: '%s' - ignoring", szFileName); + goto out; + } + szExt++; + szExtCopy = _strdup(szExt); + _strlwr((char*)szExtCopy); + if ( (strcmp(szExtCopy, "dll") == 0) || (strcmp(szExtCopy, "sys") == 0) || (strcmp(szExtCopy, "exe") == 0) ) { + wdi_dbg("'%s': PE type", szFileName); + } else if (strcmp(szExtCopy, "inf") == 0) { + wdi_dbg("'%s': INF type", szFileName); + bPEType = FALSE; + } else { + wdi_warn("unhandled file type: '%s' - ignoring", szFileName); + goto out; + } + + // An "<<>>" Authenticode link must be populated for each entry + sSPCLink.dwLinkChoice = SPC_FILE_LINK_CHOICE; + sSPCLink.pwszUrl = L"<<>>"; + cbEncoded = sizeof(pbEncoded); + // PE and INF encode the link differently + if (bPEType) { + sSPCImageData.Flags.cbData = 1; + sSPCImageData.Flags.cUnusedBits = 0; + 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)); + 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)); + goto out; + } + } + + // Populate the SHA1 Hash OID + sSIPData.Data.pszObjId = (bPEType)?SPC_PE_IMAGE_DATA_OBJID:SPC_CAB_DATA_OBJID; + sSIPData.Data.Value.cbData = cbEncoded; + sSIPData.Data.Value.pbData = pbEncoded; + sSIPData.DigestAlgorithm.pszObjId = szOID_OIWSEC_sha1; + sSIPData.DigestAlgorithm.Parameters.cbData = 0; + sSIPData.Digest.cbData = SHA1_HASH_LENGTH; + sSIPData.Digest.pbData = 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)); + goto out; + } + + // Add the "File" and "OSAttr" attributes to the newly created member + if ( (pfCryptCATPutAttrInfo(hCat, pCatMember, L"File", + CRYPTCAT_ATTR_AUTHENTICATED|CRYPTCAT_ATTR_NAMEASCII|CRYPTCAT_ATTR_DATAASCII, + 2*((DWORD)wcslen(wszFileName)+1), (BYTE*)wszFileName) == NULL) + || (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)); + goto out; + } + r = TRUE; + +out: + if (szExtCopy != NULL) free(szExtCopy); + if (wszFileName != NULL) free(wszFileName); + return r; +} + +/* + * Path and directory manipulation + */ +static void __inline HandleSeparators(LPSTR szPath) +{ + size_t i; + if (szPath == NULL) return; + for (i=0; i sizeof(szDir) ) { + wdi_warn("path overflow"); + return; + } + sprintf(szDir, "%s%c%s", szInitialDir, '\\', szDirName); + + // Get the first file + strcat(szDir, "\\*"); + MultiByteToWideChar(CP_UTF8, 0, szDir, -1, wszDir, MAX_PATH); + hList = FindFirstFileW(wszDir, &FileData); + if (hList == INVALID_HANDLE_VALUE) return; + + // Traverse through the directory structure + do { + // Check the object is a directory or not + WideCharToMultiByte(CP_UTF8, 0, FileData.cFileName, -1, szEntry, MAX_PATH, NULL, NULL); + if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if ( (strcmp(szEntry, ".") != 0) + && (strcmp(szEntry, "..") != 0)) { + // Get the full path for sub directory + if ( (strlen(szDirName) + strlen(szEntry) + 2) > sizeof(szSubDir) ) { + wdi_warn("path overflow"); + FindClose(hList); + return; + } + sprintf(szSubDir, "%s%c%s", szDirName, '\\', szEntry); + ScanDirAndHash(hCat, szSubDir, szFileList, cFileList); + } + } else { + for (i=0; i +* +* 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 +*/ + +#include +#include + +#pragma once + +#define REGKEY_HKCU HKEY_CURRENT_USER +#define REGKEY_HKLM HKEY_LOCAL_MACHINE + +#define WDI_COMPANY_NAME "Akeo Consulting" +#define WDI_APPLICATION_NAME "libwdi" + +// Windows versions +enum WindowsVersion { + WINDOWS_UNDEFINED = -1, + WINDOWS_UNSUPPORTED = 0, + WINDOWS_XP = 0x51, + WINDOWS_2003 = 0x52, // Also XP x64 + WINDOWS_VISTA = 0x60, + WINDOWS_7 = 0x61, + WINDOWS_8 = 0x62, + WINDOWS_8_1_OR_LATER = 0x63, + WINDOWS_10_PREVIEW1 = 0x64, + WINDOWS_10 = 0xA0, + 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) +{ + BOOL r = FALSE; + size_t i = 0; + LONG s; + HKEY hApp = NULL; + DWORD dwType = -1, dwSize = len; + LPBYTE dest = (LPBYTE)str; + // VS Code Analysis complains if we don't break our initialization into chars + char long_key_name[256] = { 0 }; + memset(dest, 0, len); + + if (key_name == NULL) + return FALSE; + + for (i = safe_strlen(key_name); i>0; i--) { + if (key_name[i] == '\\') + break; + } + + if (i != 0) { + strcpy(long_key_name, "SOFTWARE\\"); + safe_strcat(long_key_name, sizeof(long_key_name), key_name); + long_key_name[sizeof("SOFTWARE\\") + i - 1] = 0; + i++; + if (RegOpenKeyExA(key_root, long_key_name, 0, KEY_READ, &hApp) != ERROR_SUCCESS) { + hApp = NULL; + goto out; + } + } else { + goto out; + } + + s = RegQueryValueExA(hApp, &key_name[i], NULL, &dwType, (LPBYTE)dest, &dwSize); + // No key means default value of 0 or empty string + if ((s == ERROR_FILE_NOT_FOUND) || ((s == ERROR_SUCCESS) && (dwType == REG_SZ) && (dwSize > 0))) { + r = TRUE; + } +out: + if (hApp != NULL) + RegCloseKey(hApp); + return r; +} diff --git a/driver/source/libwdi/tokenizer.c b/driver/source/libwdi/tokenizer.c new file mode 100644 index 00000000..1442a866 --- /dev/null +++ b/driver/source/libwdi/tokenizer.c @@ -0,0 +1,256 @@ +/* LIBUSB-WIN32, Generic Windows USB Library + * Copyright (c) 2010 Travis Robinson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +/* +09/13/2010 Revisions: + o Fixed processing of non NUL terminated strings +08/05/2010 Revisions: + o Minor string macro improvements +07/23/2010 Revisions: + o Fixed positive return value if memory allocation fails + o Changed grow size from 8192 to 1024 +*/ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include "config.h" +#include "tokenizer.h" +#include + +#define safe_min(a, b) min((size_t)(a), (size_t)(b)) +#define safe_strncpy(dst, dst_max, src, count) strncpy(dst, src, safe_min(count, dst_max - 1)) + +// If the dst buffer is to small it grows to what is needed+GROW_SIZE +#define GetDestSize(RequiredSize) RequiredSize+1024 + +BOOL grow_strcpy(char** DstPtr, char** DstPtrOrig, long* DstPos, long* DstAllocSize, + const char* ReplaceString, long ReplaceLength) +{ + if (ReplaceString == NULL) + return FALSE; + if ((*DstPos)+(ReplaceLength) >= (*DstAllocSize)) + { + void *p; + *DstAllocSize = GetDestSize((*DstPos) + ReplaceLength); + p = realloc((*DstPtr),(*DstAllocSize)); + if (p == NULL) + free(*DstPtr); + *DstPtr = p; + } + if (!(*DstPtr)) + { + free((*DstPtrOrig)); + return FALSE; + } + *DstPtrOrig = (*DstPtr); + safe_strncpy(((*DstPtr)+(*DstPos)),(*DstAllocSize)-(*DstPos), ReplaceString, ReplaceLength); + *DstPos += ReplaceLength; + + return TRUE; +} + +// replaces tokens in text. +// Returns: less than 0 on error, 0 if src is empty, +// number of chars written to dst on success. +// NOTE: On success dst must be freed by the calling function. +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:")" + int recursive) // allows tokenzing tokens in tokens +{ + const token_entity_t* next_match; + long match_replace_pos; + const char* match_start; + long tok_prefix_size; + long tok_suffix_size; + int match_found; + long match_length; + long replace_length; + long dst_pos; + long dst_alloc_size; + char* pDst; + long match_count; + + if (!src || !dst || !token_entities || !src_count || !tok_prefix || !tok_suffix) + return -ERROR_BAD_ARGUMENTS; + + tok_prefix_size = (long)strlen(tok_prefix); + tok_suffix_size = (long)strlen(tok_suffix); + + // token prefix and suffix markers is required + if (!tok_prefix_size || !tok_suffix_size) + return -ERROR_BAD_ARGUMENTS; + + // if the src buffer count <= 0 assume it is null terminated + if (src_count < 0) src_count = (long)strlen(src); + + // nothing to do + if (src_count == 0) return 0; + + // Set the initial buffer size. + dst_alloc_size = GetDestSize(src_count); + *dst = pDst = malloc(dst_alloc_size); + if (!pDst) + return -ERROR_NOT_ENOUGH_MEMORY; + dst_pos=0; + + match_count=0; + + while(src_count > (tok_prefix_size + tok_suffix_size)) + { + // search for a token prefix + match_start = src; + while(match_start && strncmp(match_start, tok_prefix, tok_prefix_size) != 0) + { + match_start++; + if ((match_start + tok_prefix_size + tok_suffix_size) > (src+src_count)) + { + match_start = NULL; + break; + } + } + if (!match_start) break; + + // found a token prefix + match_replace_pos=0; + match_found=0; + match_length = (long)(match_start-src); + + // copy all the text up to the tok_prefix start from src to dst. + if (!grow_strcpy(&pDst, dst, &dst_pos, &dst_alloc_size, src, match_length)) + { + return -ERROR_NOT_ENOUGH_MEMORY; + } + + src+=match_length+tok_prefix_size; + src_count-=(match_length+tok_prefix_size); + + // iterate through the match/replace tokens + 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) + { + break; + } + match_length=(long)strlen(next_match->match); + + // if this token will be longer than what's left in src buffer, skip it. + if (src_count < (match_length+tok_suffix_size)) + continue; // not found + + // check for a match suffix + if (strncmp(src+match_length,tok_suffix,tok_suffix_size)!=0) + continue; // not found + + if (strncmp(src,next_match->match,match_length)==0) + { + // found a valid token match + replace_length=(long)strlen(next_match->replace); + + if (!grow_strcpy(&pDst, dst, &dst_pos, &dst_alloc_size, + next_match->replace, replace_length)) + { + return -ERROR_NOT_ENOUGH_MEMORY; + } + + src+=match_length+tok_suffix_size; + src_count-=(match_length+tok_suffix_size); + match_found=1; + match_count++; + break; + } + } + if (!match_found) + { + // No matches were found; leave it as-is. + if (!grow_strcpy(&pDst, dst, &dst_pos, &dst_alloc_size, + tok_prefix, tok_prefix_size)) + { + return -ERROR_NOT_ENOUGH_MEMORY; + } + } + } + + match_length=src_count; + if (match_length > 0) + { + if (!grow_strcpy(&pDst, dst, &dst_pos, &dst_alloc_size, src, match_length)) + { + return -ERROR_NOT_ENOUGH_MEMORY; + } + } + // grow_strcpy is aware an extra char is always needed for null. + pDst[dst_pos]='\0'; + + if (recursive && match_count) + { + // if recursive mode is true, keep re-tokenizing until no matches are found + *dst = NULL; + dst_pos = tokenize_string(pDst,dst_pos,dst, + token_entities,tok_prefix,tok_suffix,recursive); + + // free the old dst buffer + free(pDst); + } + // return the new size (excluding null) + return dst_pos; +} + +// tokenizes a resource stored in the current module. +long tokenize_resource(LPCSTR resource_name, + LPCSTR resource_type, + char** dst, + const token_entity_t* token_entities, + const char* tok_prefix, + const char* tok_suffix, + int recursive) +{ + const char* src; + long src_count; + HGLOBAL res_data; + + HRSRC hSrc = FindResourceA(NULL, resource_name, resource_type); + + if (!hSrc) + return -ERROR_RESOURCE_DATA_NOT_FOUND; + + src_count = SizeofResource(NULL, hSrc); + + res_data = LoadResource(NULL,hSrc); + + if (!res_data) + return -ERROR_RESOURCE_DATA_NOT_FOUND; + + src = (char*) LockResource(res_data); + + if (!src) + return -ERROR_RESOURCE_DATA_NOT_FOUND; + + return tokenize_string(src, src_count, dst, + token_entities, tok_prefix, tok_suffix, recursive); + +} diff --git a/driver/source/libwdi/tokenizer.h b/driver/source/libwdi/tokenizer.h new file mode 100644 index 00000000..f00e2a01 --- /dev/null +++ b/driver/source/libwdi/tokenizer.h @@ -0,0 +1,46 @@ +/* LIBUSB-WIN32, Generic Windows USB Library + * Copyright (c) 2010 Travis Robinson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _TOKENIZER_H +#define _TOKENIZER_H + +#include + +typedef struct _token_entity_t +{ + const char* match; + char replace[1024]; +}token_entity_t; + +long tokenize_string(const char* src, + long src_count, + char** dst, + const token_entity_t* token_entities, + const char* tok_prefix, + const char* tok_suffix, + int recursive); + +long tokenize_resource(LPCSTR resource_name, + LPCSTR resource_type, + char** dst, + const token_entity_t* token_entities, + const char* tok_prefix, + const char* tok_suffix, + int recursive); +#endif diff --git a/driver/source/libwdi/usbser.cat.in b/driver/source/libwdi/usbser.cat.in new file mode 100644 index 00000000..66ffd12c --- /dev/null +++ b/driver/source/libwdi/usbser.cat.in @@ -0,0 +1 @@ +# The USB CDC Serial driver doesn't need extra binaries diff --git a/driver/source/libwdi/usbser.inf.in b/driver/source/libwdi/usbser.inf.in new file mode 100644 index 00000000..d7a3e786 --- /dev/null +++ b/driver/source/libwdi/usbser.inf.in @@ -0,0 +1,67 @@ +; #INF_FILENAME# +; Copyright (c) 2016 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. , +; for providing an original (yet no longer used) inf file. + +[Strings] +DeviceName = "#DEVICE_DESCRIPTION#" +VendorName = "#DEVICE_MANUFACTURER#" +SourceName = "#DEVICE_DESCRIPTION# Install Disk" +DeviceID = "#DEVICE_HARDWARE_ID#" +DeviceGUID = "#DEVICE_INTERFACE_GUID#" +Service = "USB COM Port" + +[Version] +Signature = "$Windows NT$" +Class = Ports +ClassGuid = {4D36E978-E325-11CE-BFC1-08002BE10318} +Provider = "libwdi" +CatalogFile = #CAT_FILENAME# +DriverVer = #DRIVER_DATE#, 1.0.0.0 + +[Manufacturer] +%VendorName% = DeviceList,NTx86,NTamd64,NTarm + +[DeviceList.NTx86] +%DeviceName% = UsbSer_Install, USB\%DeviceID% + +[DeviceList.NTamd64] +%DeviceName% = UsbSer_Install, USB\%DeviceID% + +[DeviceList.NTarm] +%DeviceName% = UsbSer_Install, USB\%DeviceID% + +[UsbSer_Install] +; See https://support.microsoft.com/en-us/kb/837637 +include = mdmcpq.inf +CopyFiles = FakeModemCopyFileSection ; defined in mdmcpq.inf +AddReg = UsbSer_Install.AddReg +AddProperty = UsbSer_AddProperty + +[UsbSer_Install.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[UsbSer_Install.Services] +AddService = usbser,0x00000002,UsbSer_Service + +[UsbSer_Service] +DisplayName = %Service% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\usbser.sys + +[UsbSer_AddProperty] +GenericDriverInstalled,,,,1 + +[DestinationDirs] +DefaultDestDir = 12 + +[SourceDisksNames] +1 = %SourceName% + +[SourceDisksFiles] diff --git a/driver/source/libwdi/vid_data.c b/driver/source/libwdi/vid_data.c new file mode 100644 index 00000000..1240e173 --- /dev/null +++ b/driver/source/libwdi/vid_data.c @@ -0,0 +1,2998 @@ +/* + * USB vendors, by VID + * This file is autogenerated from http://www.linux-usb.org/usb.ids + * See http://www.linux-usb.org/usb-ids.html to submit new VIDs or PIDs + * + * + * 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 + */ + +#include +#include "libwdi.h" + +struct vendor_name { + unsigned short vid; + const char* name; +}; + +/* + * http://www.linux-usb.org/usb.ids + * Version: 2015.12.17 + */ +static struct vendor_name usb_vendor[] = { + { 0x0001, "Fry's Electronics" }, + { 0x0002, "Ingram" }, + { 0x0003, "Club Mac" }, + { 0x0004, "Nebraska Furniture Mart" }, + { 0x0011, "Unknown" }, + { 0x0053, "Planex" }, + { 0x0079, "DragonRise Inc." }, + { 0x0105, "Trust International B.V." }, + { 0x0127, "IBP" }, + { 0x0145, "Unknown" }, + { 0x017c, "MLK" }, + { 0x0200, "TP-Link" }, + { 0x0204, "Chipsbank Microelectronics Co., Ltd" }, + { 0x0218, "Hangzhou Worlde" }, + { 0x02ad, "HUMAX Co., Ltd." }, + { 0x0300, "MM300 eBook Reader" }, + { 0x0324, "OCZ Technology Inc" }, + { 0x0325, "OCZ Technology Inc" }, + { 0x0386, "LTS" }, + { 0x03d9, "Shenzhen Sinote Tech-Electron Co., Ltd" }, + { 0x03da, "Bernd Walter Computer Technology" }, + { 0x03e8, "EndPoints, Inc." }, + { 0x03e9, "Thesys Microelectronics" }, + { 0x03ea, "Data Broadcasting Corp." }, + { 0x03eb, "Atmel Corp." }, + { 0x03ec, "Iwatsu America, Inc." }, + { 0x03ed, "Mitel Corp." }, + { 0x03ee, "Mitsumi" }, + { 0x03f0, "Hewlett-Packard" }, + { 0x03f1, "Genoa Technology" }, + { 0x03f2, "Oak Technology, Inc." }, + { 0x03f3, "Adaptec, Inc." }, + { 0x03f4, "Diebold, Inc." }, + { 0x03f5, "Siemens Electromechanical" }, + { 0x03f8, "Epson Imaging Technology Center" }, + { 0x03f9, "KeyTronic Corp." }, + { 0x03fb, "OPTi, Inc." }, + { 0x03fc, "Elitegroup Computer Systems" }, + { 0x03fd, "Xilinx, Inc." }, + { 0x03fe, "Farallon Comunications" }, + { 0x0400, "National Semiconductor Corp." }, + { 0x0401, "National Registry, Inc." }, + { 0x0402, "ALi Corp." }, + { 0x0403, "Future Technology Devices International, Ltd" }, + { 0x0404, "NCR Corp." }, + { 0x0405, "Synopsys, Inc." }, + { 0x0406, "Fujitsu-ICL Computers" }, + { 0x0407, "Fujitsu Personal Systems, Inc." }, + { 0x0408, "Quanta Computer, Inc." }, + { 0x0409, "NEC Corp." }, + { 0x040a, "Kodak Co." }, + { 0x040b, "Weltrend Semiconductor" }, + { 0x040c, "VTech Computers, Ltd" }, + { 0x040d, "VIA Technologies, Inc." }, + { 0x040e, "MCCI" }, + { 0x040f, "Echo Speech Corp." }, + { 0x0411, "BUFFALO INC. (formerly MelCo., Inc.)" }, + { 0x0412, "Award Software International" }, + { 0x0413, "Leadtek Research, Inc." }, + { 0x0414, "Giga-Byte Technology Co., Ltd" }, + { 0x0416, "Winbond Electronics Corp." }, + { 0x0417, "Symbios Logic" }, + { 0x0418, "AST Research" }, + { 0x0419, "Samsung Info. Systems America, Inc." }, + { 0x041a, "Phoenix Technologies, Ltd" }, + { 0x041b, "d'TV" }, + { 0x041d, "S3, Inc." }, + { 0x041e, "Creative Technology, Ltd" }, + { 0x041f, "LCS Telegraphics" }, + { 0x0420, "Chips and Technologies" }, + { 0x0421, "Nokia Mobile Phones" }, + { 0x0422, "ADI Systems, Inc." }, + { 0x0423, "Computer Access Technology Corp." }, + { 0x0424, "Standard Microsystems Corp." }, + { 0x0425, "Motorola Semiconductors HK, Ltd" }, + { 0x0426, "Integrated Device Technology, Inc." }, + { 0x0427, "Motorola Electronics Taiwan, Ltd" }, + { 0x0428, "Advanced Gravis Computer Tech, Ltd" }, + { 0x0429, "Cirrus Logic" }, + { 0x042a, "Ericsson Austrian, AG" }, + { 0x042b, "Intel Corp." }, + { 0x042c, "Innovative Semiconductors, Inc." }, + { 0x042d, "Micronics" }, + { 0x042e, "Acer, Inc." }, + { 0x042f, "Molex, Inc." }, + { 0x0430, "Sun Microsystems, Inc." }, + { 0x0431, "Itac Systems, Inc." }, + { 0x0432, "Unisys Corp." }, + { 0x0433, "Alps Electric, Inc." }, + { 0x0434, "Samsung Info. Systems America, Inc." }, + { 0x0435, "Hyundai Electronics America" }, + { 0x0436, "Taugagreining HF" }, + { 0x0437, "Framatome Connectors USA" }, + { 0x0438, "Advanced Micro Devices, Inc." }, + { 0x0439, "Voice Technologies Group" }, + { 0x043d, "Lexmark International, Inc." }, + { 0x043e, "LG Electronics USA, Inc." }, + { 0x043f, "RadiSys Corp." }, + { 0x0440, "Eizo Nanao Corp." }, + { 0x0441, "Winbond Systems Lab." }, + { 0x0442, "Ericsson, Inc." }, + { 0x0443, "Gateway, Inc." }, + { 0x0445, "Lucent Technologies, Inc." }, + { 0x0446, "NMB Technologies Corp." }, + { 0x0447, "Momentum Microsystems" }, + { 0x044a, "Shamrock Tech. Co., Ltd" }, + { 0x044b, "WSI" }, + { 0x044c, "CCL/ITRI" }, + { 0x044d, "Siemens Nixdorf AG" }, + { 0x044e, "Alps Electric Co., Ltd" }, + { 0x044f, "ThrustMaster, Inc." }, + { 0x0450, "DFI, Inc." }, + { 0x0451, "Texas Instruments, Inc." }, + { 0x0452, "Mitsubishi Electronics America, Inc." }, + { 0x0453, "CMD Technology" }, + { 0x0454, "Vobis Microcomputer AG" }, + { 0x0455, "Telematics International, Inc." }, + { 0x0456, "Analog Devices, Inc." }, + { 0x0457, "Silicon Integrated Systems Corp." }, + { 0x0458, "KYE Systems Corp. (Mouse Systems)" }, + { 0x0459, "Adobe Systems, Inc." }, + { 0x045a, "SONICblue, Inc." }, + { 0x045b, "Hitachi, Ltd" }, + { 0x045d, "Nortel Networks, Ltd" }, + { 0x045e, "Microsoft Corp." }, + { 0x0460, "Ace Cad Enterprise Co., Ltd" }, + { 0x0461, "Primax Electronics, Ltd" }, + { 0x0463, "MGE UPS Systems" }, + { 0x0464, "AMP/Tycoelectronics Corp." }, + { 0x0467, "AT&T Paradyne" }, + { 0x0468, "Wieson Technologies Co., Ltd" }, + { 0x046a, "Cherry GmbH" }, + { 0x046b, "American Megatrends, Inc." }, + { 0x046c, "Toshiba Corp., Digital Media Equipment" }, + { 0x046d, "Logitech, Inc." }, + { 0x046e, "Behavior Tech. Computer Corp." }, + { 0x046f, "Crystal Semiconductor" }, + { 0x0471, "Philips (or NXP)" }, + { 0x0472, "Chicony Electronics Co., Ltd" }, + { 0x0473, "Sanyo Information Business Co., Ltd" }, + { 0x0474, "Sanyo Electric Co., Ltd" }, + { 0x0475, "Relisys/Teco Information System" }, + { 0x0476, "AESP" }, + { 0x0477, "Seagate Technology, Inc." }, + { 0x0478, "Connectix Corp." }, + { 0x0479, "Advanced Peripheral Laboratories" }, + { 0x047a, "Semtech Corp." }, + { 0x047b, "Silitek Corp." }, + { 0x047c, "Dell Computer Corp." }, + { 0x047d, "Kensington" }, + { 0x047e, "Agere Systems, Inc. (Lucent)" }, + { 0x047f, "Plantronics, Inc." }, + { 0x0480, "Toshiba America Inc" }, + { 0x0481, "Zenith Data Systems" }, + { 0x0482, "Kyocera Corp." }, + { 0x0483, "STMicroelectronics" }, + { 0x0484, "Specialix" }, + { 0x0485, "Nokia Monitors" }, + { 0x0486, "ASUS Computers, Inc." }, + { 0x0487, "Stewart Connector" }, + { 0x0488, "Cirque Corp." }, + { 0x0489, "Foxconn / Hon Hai" }, + { 0x048a, "S-MOS Systems, Inc." }, + { 0x048c, "Alps Electric Ireland, Ltd" }, + { 0x048d, "Integrated Technology Express, Inc." }, + { 0x048f, "Eicon Tech." }, + { 0x0490, "United Microelectronics Corp." }, + { 0x0491, "Capetronic" }, + { 0x0492, "Samsung SemiConductor, Inc." }, + { 0x0493, "MAG Technology Co., Ltd" }, + { 0x0495, "ESS Technology, Inc." }, + { 0x0496, "Micron Electronics" }, + { 0x0497, "Smile International" }, + { 0x0498, "Capetronic (Kaohsiung) Corp." }, + { 0x0499, "Yamaha Corp." }, + { 0x049a, "Gandalf Technologies, Ltd" }, + { 0x049b, "Curtis Computer Products" }, + { 0x049c, "Acer Advanced Labs, Inc." }, + { 0x049d, "VLSI Technology" }, + { 0x049f, "Compaq Computer Corp." }, + { 0x04a0, "Digital Equipment Corp." }, + { 0x04a1, "SystemSoft Corp." }, + { 0x04a2, "FirePower Systems" }, + { 0x04a3, "Trident Microsystems, Inc." }, + { 0x04a4, "Hitachi, Ltd" }, + { 0x04a5, "Acer Peripherals Inc. (now BenQ Corp.)" }, + { 0x04a6, "Nokia Display Products" }, + { 0x04a7, "Visioneer" }, + { 0x04a8, "Multivideo Labs, Inc." }, + { 0x04a9, "Canon, Inc." }, + { 0x04aa, "DaeWoo Telecom, Ltd" }, + { 0x04ab, "Chromatic Research" }, + { 0x04ac, "Micro Audiometrics Corp." }, + { 0x04ad, "Dooin Electronics" }, + { 0x04af, "Winnov L.P." }, + { 0x04b0, "Nikon Corp." }, + { 0x04b1, "Pan International" }, + { 0x04b3, "IBM Corp." }, + { 0x04b4, "Cypress Semiconductor Corp." }, + { 0x04b5, "ROHM LSI Systems USA, LLC" }, + { 0x04b6, "Hint Corp." }, + { 0x04b7, "Compal Electronics, Inc." }, + { 0x04b8, "Seiko Epson Corp." }, + { 0x04b9, "Rainbow Technologies, Inc." }, + { 0x04ba, "Toucan Systems, Ltd" }, + { 0x04bb, "I-O Data Device, Inc." }, + { 0x04bd, "Toshiba Electronics Taiwan Corp." }, + { 0x04be, "Telia Research AB" }, + { 0x04bf, "TDK Corp." }, + { 0x04c1, "U.S. Robotics (3Com)" }, + { 0x04c2, "Methode Electronics Far East PTE, Ltd" }, + { 0x04c3, "Maxi Switch, Inc." }, + { 0x04c4, "Lockheed Martin Energy Research" }, + { 0x04c5, "Fujitsu, Ltd" }, + { 0x04c6, "Toshiba America Electronic Components" }, + { 0x04c7, "Micro Macro Technologies" }, + { 0x04c8, "Konica Corp." }, + { 0x04ca, "Lite-On Technology Corp." }, + { 0x04cb, "Fuji Photo Film Co., Ltd" }, + { 0x04cc, "ST-Ericsson" }, + { 0x04cd, "Tatung Co. Of America" }, + { 0x04ce, "ScanLogic Corp." }, + { 0x04cf, "Myson Century, Inc." }, + { 0x04d0, "Digi International" }, + { 0x04d1, "ITT Canon" }, + { 0x04d2, "Altec Lansing Technologies" }, + { 0x04d3, "VidUS, Inc." }, + { 0x04d4, "LSI Logic, Inc." }, + { 0x04d5, "Forte Technologies, Inc." }, + { 0x04d6, "Mentor Graphics" }, + { 0x04d7, "Oki Semiconductor" }, + { 0x04d8, "Microchip Technology, Inc." }, + { 0x04d9, "Holtek Semiconductor, Inc." }, + { 0x04da, "Panasonic (Matsushita)" }, + { 0x04db, "Hypertec Pty, Ltd" }, + { 0x04dc, "Huan Hsin Holdings, Ltd" }, + { 0x04dd, "Sharp Corp." }, + { 0x04de, "MindShare, Inc." }, + { 0x04df, "Interlink Electronics" }, + { 0x04e1, "Iiyama North America, Inc." }, + { 0x04e2, "Exar Corp." }, + { 0x04e3, "Zilog, Inc." }, + { 0x04e4, "ACC Microelectronics" }, + { 0x04e5, "Promise Technology" }, + { 0x04e6, "SCM Microsystems, Inc." }, + { 0x04e7, "Elo TouchSystems" }, + { 0x04e8, "Samsung Electronics Co., Ltd" }, + { 0x04e9, "PC-Tel, Inc." }, + { 0x04ea, "Brooktree Corp." }, + { 0x04eb, "Northstar Systems, Inc." }, + { 0x04ec, "Tokyo Electron Device, Ltd" }, + { 0x04ed, "Annabooks" }, + { 0x04ef, "Pacific Electronic International, Inc." }, + { 0x04f0, "Daewoo Electronics Co., Ltd" }, + { 0x04f1, "Victor Company of Japan, Ltd" }, + { 0x04f2, "Chicony Electronics Co., Ltd" }, + { 0x04f3, "Elan Microelectronics Corp." }, + { 0x04f4, "Harting Elektronik, Inc." }, + { 0x04f5, "Fujitsu-ICL Systems, Inc." }, + { 0x04f6, "Norand Corp." }, + { 0x04f7, "Newnex Technology Corp." }, + { 0x04f8, "FuturePlus Systems" }, + { 0x04f9, "Brother Industries, Ltd" }, + { 0x04fa, "Dallas Semiconductor" }, + { 0x04fb, "Biostar Microtech International Corp." }, + { 0x04fc, "Sunplus Technology Co., Ltd" }, + { 0x04fd, "Soliton Systems, K.K." }, + { 0x04fe, "PFU, Ltd" }, + { 0x04ff, "E-CMOS Corp." }, + { 0x0500, "Siam United Hi-Tech" }, + { 0x0501, "Fujikura DDK, Ltd" }, + { 0x0502, "Acer, Inc." }, + { 0x0503, "Hitachi America, Ltd" }, + { 0x0504, "Hayes Microcomputer Products" }, + { 0x0506, "3Com Corp." }, + { 0x0507, "Hosiden Corp." }, + { 0x0508, "Clarion Co., Ltd" }, + { 0x0509, "Aztech Systems, Ltd" }, + { 0x050a, "Cinch Connectors" }, + { 0x050b, "Cable System International" }, + { 0x050c, "InnoMedia, Inc." }, + { 0x050d, "Belkin Components" }, + { 0x050e, "Neon Technology, Inc." }, + { 0x050f, "KC Technology, Inc." }, + { 0x0510, "Sejin Electron, Inc." }, + { 0x0511, "N'Able (DataBook) Technologies, Inc." }, + { 0x0512, "Hualon Microelectronics Corp." }, + { 0x0513, "digital-X, Inc." }, + { 0x0514, "FCI Electronics" }, + { 0x0515, "ACTC" }, + { 0x0516, "Longwell Electronics" }, + { 0x0517, "Butterfly Communications" }, + { 0x0518, "EzKEY Corp." }, + { 0x0519, "Star Micronics Co., Ltd" }, + { 0x051a, "WYSE Technology" }, + { 0x051b, "Silicon Graphics" }, + { 0x051c, "Shuttle, Inc." }, + { 0x051d, "American Power Conversion" }, + { 0x051e, "Scientific Atlanta, Inc." }, + { 0x051f, "IO Systems (Elite Electronics), Inc." }, + { 0x0520, "Taiwan Semiconductor Manufacturing Co." }, + { 0x0521, "Airborn Connectors" }, + { 0x0522, "Advanced Connectek, Inc." }, + { 0x0523, "ATEN GmbH" }, + { 0x0524, "Sola Electronics" }, + { 0x0525, "Netchip Technology, Inc." }, + { 0x0526, "Temic MHS S.A." }, + { 0x0527, "ALTRA" }, + { 0x0528, "ATI Technologies, Inc." }, + { 0x0529, "Aladdin Knowledge Systems" }, + { 0x052a, "Crescent Heart Software" }, + { 0x052b, "Tekom Technologies, Inc." }, + { 0x052c, "Canon Information Systems, Inc." }, + { 0x052d, "Avid Electronics Corp." }, + { 0x052e, "Standard Microsystems Corp." }, + { 0x052f, "Unicore Software, Inc." }, + { 0x0530, "American Microsystems, Inc." }, + { 0x0531, "Wacom Technology Corp." }, + { 0x0532, "Systech Corp." }, + { 0x0533, "Alcatel Mobile Phones" }, + { 0x0534, "Motorola, Inc." }, + { 0x0535, "LIH TZU Electric Co., Ltd" }, + { 0x0536, "Hand Held Products (Welch Allyn, Inc.)" }, + { 0x0537, "Inventec Corp." }, + { 0x0538, "Caldera International, Inc. (SCO)" }, + { 0x0539, "Shyh Shiun Terminals Co., Ltd" }, + { 0x053a, "PrehKeyTec GmbH" }, + { 0x053b, "Global Village Communication" }, + { 0x053c, "Institut of Microelectronic & Mechatronic Systems" }, + { 0x053d, "Silicon Architect" }, + { 0x053e, "Mobility Electronics" }, + { 0x053f, "Synopsys, Inc." }, + { 0x0540, "UniAccess AB" }, + { 0x0541, "Sirf Technology, Inc." }, + { 0x0543, "ViewSonic Corp." }, + { 0x0544, "Cristie Electronics, Ltd" }, + { 0x0545, "Xirlink, Inc." }, + { 0x0546, "Polaroid Corp." }, + { 0x0547, "Anchor Chips, Inc." }, + { 0x0548, "Tyan Computer Corp." }, + { 0x0549, "Pixera Corp." }, + { 0x054a, "Fujitsu Microelectronics, Inc." }, + { 0x054b, "New Media Corp." }, + { 0x054c, "Sony Corp." }, + { 0x054d, "Try Corp." }, + { 0x054e, "Proside Corp." }, + { 0x054f, "WYSE Technology Taiwan" }, + { 0x0550, "Fuji Xerox Co., Ltd" }, + { 0x0551, "CompuTrend Systems, Inc." }, + { 0x0552, "Philips Monitors" }, + { 0x0553, "STMicroelectronics Imaging Division (VLSI Vision)" }, + { 0x0554, "Dictaphone Corp." }, + { 0x0555, "ANAM S&T Co., Ltd" }, + { 0x0556, "Asahi Kasei Microsystems Co., Ltd" }, + { 0x0557, "ATEN International Co., Ltd" }, + { 0x0558, "Truevision, Inc." }, + { 0x0559, "Cadence Design Systems, Inc." }, + { 0x055a, "Kenwood USA" }, + { 0x055b, "KnowledgeTek, Inc." }, + { 0x055c, "Proton Electronic Ind." }, + { 0x055d, "Samsung Electro-Mechanics Co." }, + { 0x055e, "CTX Opto-Electronics Corp." }, + { 0x055f, "Mustek Systems, Inc." }, + { 0x0560, "Interface Corp." }, + { 0x0561, "Oasis Design, Inc." }, + { 0x0562, "Telex Communications, Inc." }, + { 0x0563, "Immersion Corp." }, + { 0x0564, "Kodak Digital Product Center, Japan Ltd. (formerly Chinon Industries Inc.)" }, + { 0x0565, "Peracom Networks, Inc." }, + { 0x0566, "Monterey International Corp." }, + { 0x0567, "Xyratex International, Ltd" }, + { 0x0568, "Quartz Ingenierie" }, + { 0x0569, "SegaSoft" }, + { 0x056a, "Wacom Co., Ltd" }, + { 0x056b, "Decicon, Inc." }, + { 0x056c, "eTEK Labs" }, + { 0x056d, "EIZO Corp." }, + { 0x056e, "Elecom Co., Ltd" }, + { 0x056f, "Korea Data Systems Co., Ltd" }, + { 0x0570, "Epson America" }, + { 0x0571, "Interex, Inc." }, + { 0x0572, "Conexant Systems (Rockwell), Inc." }, + { 0x0573, "Zoran Co. Personal Media Division (Nogatech)" }, + { 0x0574, "City University of Hong Kong" }, + { 0x0575, "Philips Creative Display Solutions" }, + { 0x0576, "BAFO/Quality Computer Accessories" }, + { 0x0577, "ELSA" }, + { 0x0578, "Intrinsix Corp." }, + { 0x0579, "GVC Corp." }, + { 0x057a, "Samsung Electronics America" }, + { 0x057b, "Y-E Data, Inc." }, + { 0x057c, "AVM GmbH" }, + { 0x057d, "Shark Multimedia, Inc." }, + { 0x057e, "Nintendo Co., Ltd" }, + { 0x057f, "QuickShot, Ltd" }, + { 0x0580, "Denron, Inc." }, + { 0x0581, "Racal Data Group" }, + { 0x0582, "Roland Corp." }, + { 0x0583, "Padix Co., Ltd (Rockfire)" }, + { 0x0584, "RATOC System, Inc." }, + { 0x0585, "FlashPoint Technology, Inc." }, + { 0x0586, "ZyXEL Communications Corp." }, + { 0x0587, "America Kotobuki Electronics Industries, Inc." }, + { 0x0588, "Sapien Design" }, + { 0x0589, "Victron" }, + { 0x058a, "Nohau Corp." }, + { 0x058b, "Infineon Technologies" }, + { 0x058c, "In Focus Systems" }, + { 0x058d, "Micrel Semiconductor" }, + { 0x058e, "Tripath Technology, Inc." }, + { 0x058f, "Alcor Micro Corp." }, + { 0x0590, "Omron Corp." }, + { 0x0591, "Questra Consulting" }, + { 0x0592, "Powerware Corp." }, + { 0x0593, "Incite" }, + { 0x0594, "Princeton Graphic Systems" }, + { 0x0595, "Zoran Microelectronics, Ltd" }, + { 0x0596, "MicroTouch Systems, Inc." }, + { 0x0597, "Trisignal Communications" }, + { 0x0598, "Niigata Canotec Co., Inc." }, + { 0x0599, "Brilliance Semiconductor, Inc." }, + { 0x059a, "Spectrum Signal Processing, Inc." }, + { 0x059b, "Iomega Corp." }, + { 0x059c, "A-Trend Technology Co., Ltd" }, + { 0x059d, "Advanced Input Devices" }, + { 0x059e, "Intelligent Instrumentation" }, + { 0x059f, "LaCie, Ltd" }, + { 0x05a0, "Vetronix Corp." }, + { 0x05a1, "USC Corp." }, + { 0x05a2, "Fuji Film Microdevices Co., Ltd" }, + { 0x05a3, "ARC International" }, + { 0x05a4, "Ortek Technology, Inc." }, + { 0x05a5, "Sampo Technology Corp." }, + { 0x05a6, "Cisco Systems, Inc." }, + { 0x05a7, "Bose Corp." }, + { 0x05a8, "Spacetec IMC Corp." }, + { 0x05a9, "OmniVision Technologies, Inc." }, + { 0x05aa, "Utilux South China, Ltd" }, + { 0x05ab, "In-System Design" }, + { 0x05ac, "Apple, Inc." }, + { 0x05ad, "Y.C. Cable U.S.A., Inc." }, + { 0x05ae, "Synopsys, Inc." }, + { 0x05af, "Jing-Mold Enterprise Co., Ltd" }, + { 0x05b0, "Fountain Technologies, Inc." }, + { 0x05b1, "First International Computer, Inc." }, + { 0x05b4, "LG Semicon Co., Ltd" }, + { 0x05b5, "Dialogic Corp." }, + { 0x05b6, "Proxima Corp." }, + { 0x05b7, "Medianix Semiconductor, Inc." }, + { 0x05b8, "Agiler, Inc." }, + { 0x05b9, "Philips Research Laboratories" }, + { 0x05ba, "DigitalPersona, Inc." }, + { 0x05bb, "Grey Cell Systems" }, + { 0x05bc, "3G Green Green Globe Co., Ltd" }, + { 0x05bd, "RAFI GmbH & Co. KG" }, + { 0x05be, "Tyco Electronics (Raychem)" }, + { 0x05bf, "S & S Research" }, + { 0x05c0, "Keil Software" }, + { 0x05c1, "Kawasaki Microelectronics, Inc." }, + { 0x05c2, "Media Phonics (Suisse) S.A." }, + { 0x05c5, "Digi International, Inc." }, + { 0x05c6, "Qualcomm, Inc." }, + { 0x05c7, "Qtronix Corp." }, + { 0x05c8, "Cheng Uei Precision Industry Co., Ltd (Foxlink)" }, + { 0x05c9, "Semtech Corp." }, + { 0x05ca, "Ricoh Co., Ltd" }, + { 0x05cb, "PowerVision Technologies, Inc." }, + { 0x05cc, "ELSA AG" }, + { 0x05cd, "Silicom, Ltd" }, + { 0x05ce, "sci-worx GmbH" }, + { 0x05cf, "Sung Forn Co., Ltd" }, + { 0x05d0, "GE Medical Systems Lunar" }, + { 0x05d1, "Brainboxes, Ltd" }, + { 0x05d2, "Wave Systems Corp." }, + { 0x05d3, "Tohoku Ricoh Co., Ltd" }, + { 0x05d5, "Super Gate Technology Co., Ltd" }, + { 0x05d6, "Philips Semiconductors, CICT" }, + { 0x05d7, "Thomas & Betts Corp." }, + { 0x05d8, "Ultima Electronics Corp." }, + { 0x05d9, "Axiohm Transaction Solutions" }, + { 0x05da, "Microtek International, Inc." }, + { 0x05db, "Sun Corp. (Suntac?)" }, + { 0x05dc, "Lexar Media, Inc." }, + { 0x05dd, "Delta Electronics, Inc." }, + { 0x05df, "Silicon Vision, Inc." }, + { 0x05e0, "Symbol Technologies" }, + { 0x05e1, "Syntek Semiconductor Co., Ltd" }, + { 0x05e2, "ElecVision, Inc." }, + { 0x05e3, "Genesys Logic, Inc." }, + { 0x05e4, "Red Wing Corp." }, + { 0x05e5, "Fuji Electric Co., Ltd" }, + { 0x05e6, "Keithley Instruments" }, + { 0x05e8, "ICC, Inc." }, + { 0x05e9, "Kawasaki LSI" }, + { 0x05eb, "FFC, Ltd" }, + { 0x05ec, "COM21, Inc." }, + { 0x05ee, "Cytechinfo Inc." }, + { 0x05ef, "AVB, Inc. [anko?]" }, + { 0x05f0, "Canopus Co., Ltd" }, + { 0x05f1, "Compass Communications" }, + { 0x05f2, "Dexin Corp., Ltd" }, + { 0x05f3, "PI Engineering, Inc." }, + { 0x05f5, "Unixtar Technology, Inc." }, + { 0x05f6, "AOC International" }, + { 0x05f7, "RFC Distribution(s) PTE, Ltd" }, + { 0x05f9, "PSC Scanning, Inc." }, + { 0x05fa, "Siemens Telecommunications Systems, Ltd" }, + { 0x05fc, "Harman" }, + { 0x05fd, "InterAct, Inc." }, + { 0x05fe, "Chic Technology Corp." }, + { 0x05ff, "LeCroy Corp." }, + { 0x0600, "Barco Display Systems" }, + { 0x0601, "Jazz Hipster Corp." }, + { 0x0602, "Vista Imaging, Inc." }, + { 0x0603, "Novatek Microelectronics Corp." }, + { 0x0604, "Jean Co., Ltd" }, + { 0x0605, "Anchor C&C Co., Ltd" }, + { 0x0606, "Royal Information Electronics Co., Ltd" }, + { 0x0607, "Bridge Information Co., Ltd" }, + { 0x0608, "Genrad Ads" }, + { 0x0609, "SMK Manufacturing, Inc." }, + { 0x060a, "Worthington Data Solutions, Inc." }, + { 0x060b, "Solid Year" }, + { 0x060c, "EEH Datalink GmbH" }, + { 0x060d, "Auctor Corp." }, + { 0x060e, "Transmonde Technologies, Inc." }, + { 0x060f, "Joinsoon Electronics Mfg. Co., Ltd" }, + { 0x0610, "Costar Electronics, Inc." }, + { 0x0611, "Totoku Electric Co., Ltd" }, + { 0x0613, "TransAct Technologies, Inc." }, + { 0x0614, "Bio-Rad Laboratories" }, + { 0x0615, "Quabbin Wire & Cable Co., Inc." }, + { 0x0616, "Future Techno Designs PVT, Ltd" }, + { 0x0617, "Swiss Federal Insitute of Technology" }, + { 0x0618, "MacAlly" }, + { 0x0619, "Seiko Instruments, Inc." }, + { 0x061a, "Veridicom International, Inc." }, + { 0x061b, "Promptus Communications, Inc." }, + { 0x061c, "Act Labs, Ltd" }, + { 0x061d, "Quatech, Inc." }, + { 0x061e, "Nissei Electric Co." }, + { 0x0620, "Alaris, Inc." }, + { 0x0621, "ODU-Steckverbindungssysteme GmbH & Co. KG" }, + { 0x0622, "Iotech, Inc." }, + { 0x0623, "Littelfuse, Inc." }, + { 0x0624, "Avocent Corp." }, + { 0x0625, "TiMedia Technology Co., Ltd" }, + { 0x0626, "Nippon Systems Development Co., Ltd" }, + { 0x0627, "Adomax Technology Co., Ltd" }, + { 0x0628, "Tasking Software, Inc." }, + { 0x0629, "Zida Technologies, Ltd" }, + { 0x062a, "Creative Labs" }, + { 0x062b, "Greatlink Electronics Taiwan, Ltd" }, + { 0x062c, "Institute for Information Industry" }, + { 0x062d, "Taiwan Tai-Hao Enterprises Co., Ltd" }, + { 0x062e, "Mainsuper Enterprises Co., Ltd" }, + { 0x062f, "Sin Sheng Terminal & Machine, Inc." }, + { 0x0631, "JUJO Electronics Corp." }, + { 0x0633, "Cyrix Corp." }, + { 0x0634, "Micron Technology, Inc." }, + { 0x0635, "Methode Electronics, Inc." }, + { 0x0636, "Sierra Imaging, Inc." }, + { 0x0638, "Avision, Inc." }, + { 0x0639, "Chrontel, Inc." }, + { 0x063a, "Techwin Corp." }, + { 0x063b, "Taugagreining HF" }, + { 0x063c, "Yamaichi Electronics Co., Ltd (Sakura)" }, + { 0x063d, "Fong Kai Industrial Co., Ltd" }, + { 0x063e, "RealMedia Technology, Inc." }, + { 0x063f, "New Technology Cable, Ltd" }, + { 0x0640, "Hitex Development Tools" }, + { 0x0641, "Woods Industries, Inc." }, + { 0x0642, "VIA Medical Corp." }, + { 0x0644, "TEAC Corp." }, + { 0x0645, "Who? Vision Systems, Inc." }, + { 0x0646, "UMAX" }, + { 0x0647, "Acton Research Corp." }, + { 0x0648, "Inside Out Networks" }, + { 0x0649, "Weli Science Co., Ltd" }, + { 0x064b, "Analog Devices, Inc. (White Mountain DSP)" }, + { 0x064c, "Ji-Haw Industrial Co., Ltd" }, + { 0x064d, "TriTech Microelectronics, Ltd" }, + { 0x064e, "Suyin Corp." }, + { 0x064f, "WIBU-Systems AG" }, + { 0x0650, "Dynapro Systems" }, + { 0x0651, "Likom Technology Sdn. Bhd." }, + { 0x0652, "Stargate Solutions, Inc." }, + { 0x0653, "CNF, Inc." }, + { 0x0654, "Granite Microsystems, Inc." }, + { 0x0655, "Space Shuttle Hi-Tech Co., Ltd" }, + { 0x0656, "Glory Mark Electronic, Ltd" }, + { 0x0657, "Tekcon Electronics Corp." }, + { 0x0658, "Sigma Designs, Inc." }, + { 0x0659, "Aethra" }, + { 0x065a, "Optoelectronics Co., Ltd" }, + { 0x065b, "Tracewell Systems" }, + { 0x065e, "Silicon Graphics" }, + { 0x065f, "Good Way Technology Co., Ltd & GWC technology Inc." }, + { 0x0660, "TSAY-E (BVI) International, Inc." }, + { 0x0661, "Hamamatsu Photonics K.K." }, + { 0x0662, "Kansai Electric Co., Ltd" }, + { 0x0663, "Topmax Electronic Co., Ltd" }, + { 0x0664, "ET&T Technology Co., Ltd." }, + { 0x0665, "Cypress Semiconductor" }, + { 0x0667, "Aiwa Co., Ltd" }, + { 0x0668, "WordWand" }, + { 0x0669, "Oce' Printing Systems GmbH" }, + { 0x066a, "Total Technologies, Ltd" }, + { 0x066b, "Linksys, Inc." }, + { 0x066d, "Entrega, Inc." }, + { 0x066e, "Acer Semiconductor America, Inc." }, + { 0x066f, "SigmaTel, Inc." }, + { 0x0670, "Sequel Imaging" }, + { 0x0672, "Labtec, Inc." }, + { 0x0673, "HCL" }, + { 0x0674, "Key Mouse Electronic Enterprise Co., Ltd" }, + { 0x0675, "DrayTek Corp." }, + { 0x0676, "Teles AG" }, + { 0x0677, "Aiwa Co., Ltd" }, + { 0x0678, "ACard Technology Corp." }, + { 0x067b, "Prolific Technology, Inc." }, + { 0x067c, "Efficient Networks, Inc." }, + { 0x067d, "Hohner Corp." }, + { 0x067e, "Intermec Technologies Corp." }, + { 0x067f, "Virata, Ltd" }, + { 0x0680, "Realtek Semiconductor Corp., CPP Div. (Avance Logic)" }, + { 0x0681, "Siemens Information and Communication Products" }, + { 0x0682, "Victor Company of Japan, Ltd" }, + { 0x0684, "Actiontec Electronics, Inc." }, + { 0x0685, "ZD Incorporated" }, + { 0x0686, "Minolta Co., Ltd" }, + { 0x068a, "Pertech, Inc." }, + { 0x068b, "Potrans International, Inc." }, + { 0x068e, "CH Products, Inc." }, + { 0x0690, "Golden Bridge Electech, Inc." }, + { 0x0693, "Hagiwara Sys-Com Co., Ltd" }, + { 0x0694, "Lego Group" }, + { 0x0698, "Chuntex (CTX)" }, + { 0x0699, "Tektronix, Inc." }, + { 0x069a, "Askey Computer Corp." }, + { 0x069b, "Thomson, Inc." }, + { 0x069d, "Hughes Network Systems (HNS)" }, + { 0x069e, "Welcat Inc." }, + { 0x069f, "Allied Data Technologies BV" }, + { 0x06a2, "Topro Technology, Inc." }, + { 0x06a3, "Saitek PLC" }, + { 0x06a4, "Xiamen Doowell Electron Co., Ltd" }, + { 0x06a5, "Divio" }, + { 0x06a7, "MicroStore, Inc." }, + { 0x06a8, "Topaz Systems, Inc." }, + { 0x06a9, "Westell" }, + { 0x06aa, "Sysgration, Ltd" }, + { 0x06ac, "Fujitsu Laboratories of America, Inc." }, + { 0x06ad, "Greatland Electronics Taiwan, Ltd" }, + { 0x06ae, "Professional Multimedia Testing Centre" }, + { 0x06af, "Harting, Inc. of North America" }, + { 0x06b8, "Pixela Corp." }, + { 0x06b9, "Alcatel Telecom" }, + { 0x06ba, "Smooth Cord & Connector Co., Ltd" }, + { 0x06bb, "EDA, Inc." }, + { 0x06bc, "Oki Data Corp." }, + { 0x06bd, "AGFA-Gevaert NV" }, + { 0x06be, "AME Optimedia Technology Co., Ltd" }, + { 0x06bf, "Leoco Corp." }, + { 0x06c2, "Phidgets Inc. (formerly GLAB)" }, + { 0x06c4, "Bizlink International Corp." }, + { 0x06c5, "Hagenuk, GmbH" }, + { 0x06c6, "Infowave Software, Inc." }, + { 0x06c8, "SIIG, Inc." }, + { 0x06c9, "Taxan (Europe), Ltd" }, + { 0x06ca, "Newer Technology, Inc." }, + { 0x06cb, "Synaptics, Inc." }, + { 0x06cc, "Terayon Communication Systems" }, + { 0x06cd, "Keyspan" }, + { 0x06ce, "Contec" }, + { 0x06cf, "SpheronVR AG" }, + { 0x06d0, "LapLink, Inc." }, + { 0x06d1, "Daewoo Electronics Co., Ltd" }, + { 0x06d3, "Mitsubishi Electric Corp." }, + { 0x06d4, "Cisco Systems" }, + { 0x06d5, "Toshiba" }, + { 0x06d6, "Aashima Technology B.V." }, + { 0x06d7, "Network Computing Devices (NCD)" }, + { 0x06d8, "Technical Marketing Research, Inc." }, + { 0x06da, "Phoenixtec Power Co., Ltd" }, + { 0x06db, "Paradyne" }, + { 0x06dc, "Foxlink Image Technology Co., Ltd" }, + { 0x06de, "Heisei Electronics Co., Ltd" }, + { 0x06e0, "Multi-Tech Systems, Inc." }, + { 0x06e1, "ADS Technologies, Inc." }, + { 0x06e4, "Alcatel Microelectronics" }, + { 0x06e6, "Tiger Jet Network, Inc." }, + { 0x06ea, "Sirius Technologies" }, + { 0x06eb, "PC Expert Tech. Co., Ltd" }, + { 0x06ef, "I.A.C. Geometrische Ingenieurs B.V." }, + { 0x06f0, "T.N.C Industrial Co., Ltd" }, + { 0x06f1, "Opcode Systems, Inc." }, + { 0x06f2, "Emine Technology Co." }, + { 0x06f6, "Wintrend Technology Co., Ltd" }, + { 0x06f7, "Wailly Technology Ltd" }, + { 0x06f8, "Guillemot Corp." }, + { 0x06f9, "ASYST electronic d.o.o." }, + { 0x06fa, "HSD S.r.L" }, + { 0x06fc, "Motorola Semiconductor Products Sector" }, + { 0x06fd, "Boston Acoustics" }, + { 0x06fe, "Gallant Computer, Inc." }, + { 0x0701, "Supercomal Wire & Cable SDN. BHD." }, + { 0x0703, "Bvtech Industry, Inc." }, + { 0x0705, "NKK Corp." }, + { 0x0706, "Ariel Corp." }, + { 0x0707, "Standard Microsystems Corp." }, + { 0x0708, "Putercom Co., Ltd" }, + { 0x0709, "Silicon Systems, Ltd (SSL)" }, + { 0x070a, "Oki Electric Industry Co., Ltd" }, + { 0x070d, "Comoss Electronic Co., Ltd" }, + { 0x070e, "Excel Cell Electronic Co., Ltd" }, + { 0x0710, "Connect Tech, Inc." }, + { 0x0711, "Magic Control Technology Corp." }, + { 0x0713, "Interval Research Corp." }, + { 0x0714, "NewMotion, Inc." }, + { 0x0717, "ZNK Corp." }, + { 0x0718, "Imation Corp." }, + { 0x0719, "Tremon Enterprises Co., Ltd" }, + { 0x071b, "Domain Technologies, Inc." }, + { 0x071c, "Xionics Document Technologies, Inc." }, + { 0x071d, "Eicon Networks Corp." }, + { 0x071e, "Ariston Technologies" }, + { 0x0723, "Centillium Communications Corp." }, + { 0x0726, "Vanguard International Semiconductor-America" }, + { 0x0729, "Amitm" }, + { 0x072e, "Sunix Co., Ltd" }, + { 0x072f, "Advanced Card Systems, Ltd" }, + { 0x0731, "Susteen, Inc." }, + { 0x0732, "Goldfull Electronics & Telecommunications Corp." }, + { 0x0733, "ViewQuest Technologies, Inc." }, + { 0x0734, "Lasat Communications A/S" }, + { 0x0735, "Asuscom Network" }, + { 0x0736, "Lorom Industrial Co., Ltd" }, + { 0x0738, "Mad Catz, Inc." }, + { 0x073a, "Chaplet Systems, Inc." }, + { 0x073b, "Suncom Technologies" }, + { 0x073c, "Industrial Electronic Engineers, Inc." }, + { 0x073d, "Eutron S.p.a." }, + { 0x073e, "NEC, Inc." }, + { 0x0742, "Stollmann" }, + { 0x0745, "Syntech Information Co., Ltd" }, + { 0x0746, "Onkyo Corp." }, + { 0x0747, "Labway Corp." }, + { 0x0748, "Strong Man Enterprise Co., Ltd" }, + { 0x0749, "EVer Electronics Corp." }, + { 0x074a, "Ming Fortune Industry Co., Ltd" }, + { 0x074b, "Polestar Tech. Corp." }, + { 0x074c, "C-C-C Group PLC" }, + { 0x074d, "Micronas GmbH" }, + { 0x074e, "Digital Stream Corp." }, + { 0x0755, "Aureal Semiconductor" }, + { 0x0757, "Network Technologies, Inc." }, + { 0x075b, "Sophisticated Circuits, Inc." }, + { 0x0763, "Midiman" }, + { 0x0764, "Cyber Power System, Inc." }, + { 0x0765, "X-Rite, Inc." }, + { 0x0766, "Jess-Link Products Co., Ltd" }, + { 0x0767, "Tokheim Corp." }, + { 0x0768, "Camtel Technology Corp." }, + { 0x0769, "Surecom Technology Corp." }, + { 0x076a, "Smart Technology Enablers, Inc." }, + { 0x076b, "OmniKey AG" }, + { 0x076c, "Partner Tech" }, + { 0x076d, "Denso Corp." }, + { 0x076e, "Kuan Tech Enterprise Co., Ltd" }, + { 0x076f, "Jhen Vei Electronic Co., Ltd" }, + { 0x0770, "Welch Allyn, Inc - Medical Division" }, + { 0x0771, "Observator Instruments BV" }, + { 0x0772, "Your data Our Care" }, + { 0x0774, "AmTRAN Technology Co., Ltd" }, + { 0x0775, "Longshine Electronics Corp." }, + { 0x0776, "Inalways Corp." }, + { 0x0777, "Comda Enterprise Corp." }, + { 0x0778, "Volex, Inc." }, + { 0x0779, "Fairchild Semiconductor" }, + { 0x077a, "Sankyo Seiki Mfg. Co., Ltd" }, + { 0x077b, "Linksys" }, + { 0x077c, "Forward Electronics Co., Ltd" }, + { 0x077d, "Griffin Technology" }, + { 0x077f, "Well Excellent & Most Corp." }, + { 0x0780, "Sagem Monetel GmbH" }, + { 0x0781, "SanDisk Corp." }, + { 0x0782, "Trackerball" }, + { 0x0783, "C3PO" }, + { 0x0784, "Vivitar, Inc." }, + { 0x0785, "NTT-ME" }, + { 0x0789, "Logitec Corp." }, + { 0x078b, "Happ Controls, Inc." }, + { 0x078c, "GTCO/CalComp" }, + { 0x078e, "Brincom, Inc." }, + { 0x0790, "Pro-Image Manufacturing Co., Ltd" }, + { 0x0791, "Copartner Wire and Cable Mfg. Corp." }, + { 0x0792, "Axis Communications AB" }, + { 0x0793, "Wha Yu Industrial Co., Ltd" }, + { 0x0794, "ABL Electronics Corp." }, + { 0x0795, "RealChip, Inc." }, + { 0x0796, "Certicom Corp." }, + { 0x0797, "Grandtech Semiconductor Corp." }, + { 0x0798, "Optelec" }, + { 0x0799, "Altera" }, + { 0x079b, "Sagem" }, + { 0x079d, "Alfadata Computer Corp." }, + { 0x07a1, "Digicom S.p.A." }, + { 0x07a2, "National Technical Systems" }, + { 0x07a3, "Onnto Corp." }, + { 0x07a4, "Be, Inc." }, + { 0x07a6, "ADMtek, Inc." }, + { 0x07aa, "Corega K.K." }, + { 0x07ab, "Freecom Technologies" }, + { 0x07af, "Microtech" }, + { 0x07b0, "Trust Technologies" }, + { 0x07b1, "IMP, Inc." }, + { 0x07b2, "Motorola BCS, Inc." }, + { 0x07b3, "Plustek, Inc." }, + { 0x07b4, "Olympus Optical Co., Ltd" }, + { 0x07b5, "Mega World International, Ltd" }, + { 0x07b6, "Marubun Corp." }, + { 0x07b7, "TIME Interconnect, Ltd" }, + { 0x07b8, "AboCom Systems Inc" }, + { 0x07bc, "Canon Computer Systems, Inc." }, + { 0x07bd, "Webgear, Inc." }, + { 0x07be, "Veridicom" }, + { 0x07c0, "Code Mercenaries Hard- und Software GmbH" }, + { 0x07c1, "Keisokugiken" }, + { 0x07c4, "Datafab Systems, Inc." }, + { 0x07c5, "APG Cash Drawer" }, + { 0x07c6, "ShareWave, Inc." }, + { 0x07c7, "Powertech Industrial Co., Ltd" }, + { 0x07c8, "B.U.G., Inc." }, + { 0x07c9, "Allied Telesyn International" }, + { 0x07ca, "AVerMedia Technologies, Inc." }, + { 0x07cb, "Kingmax Technology, Inc." }, + { 0x07cc, "Carry Computer Eng., Co., Ltd" }, + { 0x07cd, "Elektor" }, + { 0x07cf, "Casio Computer Co., Ltd" }, + { 0x07d0, "Dazzle" }, + { 0x07d1, "D-Link System" }, + { 0x07d2, "Aptio Products, Inc." }, + { 0x07d3, "Cyberdata Corp." }, + { 0x07d5, "Radiant Systems" }, + { 0x07d7, "GCC Technologies, Inc." }, + { 0x07da, "Arasan Chip Systems" }, + { 0x07de, "Diamond Multimedia" }, + { 0x07df, "David Electronics Co., Ltd" }, + { 0x07e1, "Ambient Technologies, Inc." }, + { 0x07e2, "Elmeg GmbH & Co., Ltd" }, + { 0x07e3, "Planex Communications, Inc." }, + { 0x07e4, "Movado Enterprise Co., Ltd" }, + { 0x07e5, "QPS, Inc." }, + { 0x07e6, "Allied Cable Corp." }, + { 0x07e7, "Mirvo Toys, Inc." }, + { 0x07e8, "Labsystems" }, + { 0x07ea, "Iwatsu Electric Co., Ltd" }, + { 0x07eb, "Double-H Technology Co., Ltd" }, + { 0x07ec, "Taiyo Electric Wire & Cable Co., Ltd" }, + { 0x07ee, "Torex Retail (formerly Logware)" }, + { 0x07ef, "STSN" }, + { 0x07f2, "Microcomputer Applications, Inc." }, + { 0x07f6, "Circuit Assembly Corp." }, + { 0x07f7, "Century Corp." }, + { 0x07f9, "Dotop Technology, Inc." }, + { 0x07fa, "DrayTek Corp." }, + { 0x07fd, "Mark of the Unicorn" }, + { 0x07ff, "Unknown" }, + { 0x0801, "MagTek" }, + { 0x0802, "Mako Technologies, LLC" }, + { 0x0803, "Zoom Telephonics, Inc." }, + { 0x0809, "Genicom Technology, Inc." }, + { 0x080a, "Evermuch Technology Co., Ltd" }, + { 0x080b, "Cross Match Technologies" }, + { 0x080c, "Datalogic S.p.A." }, + { 0x080d, "Teco Image Systems Co., Ltd" }, + { 0x0810, "Personal Communication Systems, Inc." }, + { 0x0813, "Mattel, Inc." }, + { 0x0819, "eLicenser" }, + { 0x081a, "MG Logic" }, + { 0x081b, "Indigita Corp." }, + { 0x081c, "Mipsys" }, + { 0x081e, "AlphaSmart, Inc." }, + { 0x0822, "Reudo Corp." }, + { 0x0825, "GC Protronics" }, + { 0x0826, "Data Transit" }, + { 0x0827, "BroadLogic, Inc." }, + { 0x0828, "Sato Corp." }, + { 0x0829, "DirecTV Broadband, Inc. (Telocity)" }, + { 0x082d, "Handspring" }, + { 0x0830, "Palm, Inc." }, + { 0x0832, "Kouwell Electronics Corp." }, + { 0x0833, "Sourcenext Corp." }, + { 0x0835, "Action Star Enterprise Co., Ltd" }, + { 0x0836, "TrekStor" }, + { 0x0839, "Samsung Techwin Co., Ltd" }, + { 0x083a, "Accton Technology Corp." }, + { 0x083f, "Global Village" }, + { 0x0840, "Argosy Research, Inc." }, + { 0x0841, "Rioport.com, Inc." }, + { 0x0844, "Welland Industrial Co., Ltd" }, + { 0x0846, "NetGear, Inc." }, + { 0x084d, "Minton Optic Industry Co., Inc." }, + { 0x084e, "KB Gear" }, + { 0x084f, "Empeg" }, + { 0x0850, "Fast Point Technologies, Inc." }, + { 0x0851, "Macronix International Co., Ltd" }, + { 0x0852, "CSEM" }, + { 0x0853, "Topre Corporation" }, + { 0x0854, "ActiveWire, Inc." }, + { 0x0856, "B&B Electronics" }, + { 0x0858, "Hitachi Maxell, Ltd" }, + { 0x0859, "Minolta Systems Laboratory, Inc." }, + { 0x085a, "Xircom" }, + { 0x085c, "ColorVision, Inc." }, + { 0x0862, "Teletrol Systems, Inc." }, + { 0x0863, "Filanet Corp." }, + { 0x0864, "NetGear, Inc." }, + { 0x0867, "Data Translation, Inc." }, + { 0x086a, "Emagic Soft- und Hardware GmbH" }, + { 0x086c, "DeTeWe - Deutsche Telephonwerke AG & Co." }, + { 0x086e, "System TALKS, Inc." }, + { 0x086f, "MEC IMEX, Inc." }, + { 0x0870, "Metricom" }, + { 0x0871, "SanDisk, Inc." }, + { 0x0873, "Xpeed, Inc." }, + { 0x0874, "A-Tec Subsystem, Inc." }, + { 0x0879, "Comtrol Corp." }, + { 0x087c, "Adesso/Kbtek America, Inc." }, + { 0x087d, "Jaton Corp." }, + { 0x087e, "Fujitsu Computer Products of America" }, + { 0x087f, "QualCore Logic Inc." }, + { 0x0880, "APT Technologies, Inc." }, + { 0x0883, "Recording Industry Association of America (RIAA)" }, + { 0x0885, "Boca Research, Inc." }, + { 0x0886, "XAC Automation Corp." }, + { 0x0887, "Hannstar Electronics Corp." }, + { 0x088a, "TechTools" }, + { 0x088b, "MassWorks, Inc." }, + { 0x088c, "Swecoin AB" }, + { 0x088e, "iLok" }, + { 0x0892, "DioGraphy, Inc." }, + { 0x0894, "TSI Incorporated" }, + { 0x0897, "Lauterbach" }, + { 0x089c, "United Technologies Research Cntr." }, + { 0x089d, "Icron Technologies Corp." }, + { 0x089e, "NST Co., Ltd" }, + { 0x089f, "Primex Aerospace Co." }, + { 0x08a5, "e9, Inc." }, + { 0x08a6, "Toshiba TEC" }, + { 0x08a8, "Andrea Electronics" }, + { 0x08a9, "CWAV Inc." }, + { 0x08ac, "Macraigor Systems LLC" }, + { 0x08ae, "Macally (Mace Group, Inc.)" }, + { 0x08b0, "Metrohm" }, + { 0x08b4, "Sorenson Vision, Inc." }, + { 0x08b7, "NATSU" }, + { 0x08b8, "J. Gordon Electronic Design, Inc." }, + { 0x08b9, "RadioShack Corp. (Tandy)" }, + { 0x08bb, "Texas Instruments" }, + { 0x08bd, "Citizen Watch Co., Ltd" }, + { 0x08c3, "Precise Biometrics" }, + { 0x08c4, "Proxim, Inc." }, + { 0x08c7, "Key Nice Enterprise Co., Ltd" }, + { 0x08c8, "2Wire, Inc." }, + { 0x08c9, "Nippon Telegraph and Telephone Corp." }, + { 0x08ca, "Aiptek International, Inc." }, + { 0x08cd, "Jue Hsun Ind. Corp." }, + { 0x08ce, "Long Well Electronics Corp." }, + { 0x08cf, "Productivity Enhancement Products" }, + { 0x08d1, "smartBridges, Inc." }, + { 0x08d3, "Virtual Ink" }, + { 0x08d4, "Fujitsu Siemens Computers" }, + { 0x08d8, "IXXAT Automation GmbH" }, + { 0x08d9, "Increment P Corp." }, + { 0x08dd, "Billionton Systems, Inc." }, + { 0x08de, "?" }, + { 0x08df, "Spyrus, Inc." }, + { 0x08e3, "Olitec, Inc." }, + { 0x08e4, "Pioneer Corp." }, + { 0x08e5, "Litronic" }, + { 0x08e6, "Gemalto (was Gemplus)" }, + { 0x08e7, "Pan-International Wire & Cable" }, + { 0x08e8, "Integrated Memory Logic" }, + { 0x08e9, "Extended Systems, Inc." }, + { 0x08ea, "Ericsson, Inc., Blue Ridge Labs" }, + { 0x08ec, "M-Systems Flash Disk Pioneers" }, + { 0x08ed, "MediaTek Inc." }, + { 0x08ee, "CCSI/Hesso" }, + { 0x08f0, "Corex Technologies" }, + { 0x08f1, "CTI Electronics Corp." }, + { 0x08f2, "Gotop Information Inc." }, + { 0x08f5, "SysTec Co., Ltd" }, + { 0x08f6, "Logic 3 International, Ltd" }, + { 0x08f7, "Vernier" }, + { 0x08f8, "Keen Top International Enterprise Co., Ltd" }, + { 0x08f9, "Wipro Technologies" }, + { 0x08fa, "Caere" }, + { 0x08fb, "Socket Communications" }, + { 0x08fc, "Sicon Cable Technology Co., Ltd" }, + { 0x08fd, "Digianswer A/S" }, + { 0x08ff, "AuthenTec, Inc." }, + { 0x0900, "Pinnacle Systems, Inc." }, + { 0x0901, "VST Technologies" }, + { 0x0906, "Faraday Technology Corp." }, + { 0x0908, "Siemens AG" }, + { 0x0909, "Audio-Technica Corp." }, + { 0x090a, "Trumpion Microelectronics, Inc." }, + { 0x090b, "Neurosmith" }, + { 0x090c, "Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.)" }, + { 0x090d, "Multiport Computer Vertriebs GmbH" }, + { 0x090e, "Shining Technology, Inc." }, + { 0x090f, "Fujitsu Devices, Inc." }, + { 0x0910, "Alation Systems, Inc." }, + { 0x0911, "Philips Speech Processing" }, + { 0x0912, "Voquette, Inc." }, + { 0x0915, "GlobeSpan, Inc." }, + { 0x0917, "SmartDisk Corp." }, + { 0x0919, "Tiger Electronics" }, + { 0x091e, "Garmin International" }, + { 0x0920, "Echelon Co." }, + { 0x0921, "GoHubs, Inc." }, + { 0x0922, "Dymo-CoStar Corp." }, + { 0x0923, "IC Media Corp." }, + { 0x0924, "Xerox" }, + { 0x0925, "Lakeview Research" }, + { 0x0927, "Summus, Ltd" }, + { 0x0928, "PLX Technology, Inc. (formerly Oxford Semiconductor, Ltd)" }, + { 0x0929, "American Biometric Co." }, + { 0x092a, "Toshiba Information & Industrial Sys. And Services" }, + { 0x092b, "Sena Technologies, Inc." }, + { 0x092f, "Northern Embedded Science/CAVNEX" }, + { 0x0930, "Toshiba Corp." }, + { 0x0931, "Harmonic Data Systems, Ltd" }, + { 0x0932, "Crescentec Corp." }, + { 0x0933, "Quantum Corp." }, + { 0x0934, "Spirent Communications" }, + { 0x0936, "NuTesla" }, + { 0x0939, "Lumberg, Inc." }, + { 0x093a, "Pixart Imaging, Inc." }, + { 0x093b, "Plextor Corp." }, + { 0x093c, "Intrepid Control Systems, Inc." }, + { 0x093d, "InnoSync, Inc." }, + { 0x093e, "J.S.T. Mfg. Co., Ltd" }, + { 0x093f, "Olympia Telecom Vertriebs GmbH" }, + { 0x0940, "Japan Storage Battery Co., Ltd" }, + { 0x0941, "Photobit Corp." }, + { 0x0942, "i2Go.com, LLC" }, + { 0x0943, "HCL Technologies India Private, Ltd" }, + { 0x0944, "KORG, Inc." }, + { 0x0945, "Pasco Scientific" }, + { 0x0948, "Kronauer music in digital" }, + { 0x094b, "Linkup Systems Corp." }, + { 0x094d, "Cable Television Laboratories" }, + { 0x094f, "Yano" }, + { 0x0951, "Kingston Technology" }, + { 0x0954, "RPM Systems Corp." }, + { 0x0955, "NVidia Corp." }, + { 0x0956, "BSquare Corp." }, + { 0x0957, "Agilent Technologies, Inc." }, + { 0x0958, "CompuLink Research, Inc." }, + { 0x0959, "Cologne Chip AG" }, + { 0x095a, "Portsmith" }, + { 0x095b, "Medialogic Corp." }, + { 0x095c, "K-Tec Electronics" }, + { 0x095d, "Polycom, Inc." }, + { 0x0967, "Acer NeWeb Corp." }, + { 0x0968, "Catalyst Enterprises, Inc." }, + { 0x096e, "Feitian Technologies, Inc." }, + { 0x0971, "Gretag-Macbeth AG" }, + { 0x0973, "Schlumberger" }, + { 0x0974, "Datagraphix, a business unit of Anacomp" }, + { 0x0975, "OL'E Communications, Inc." }, + { 0x0976, "Adirondack Wire & Cable" }, + { 0x0977, "Lightsurf Technologies" }, + { 0x0978, "Beckhoff GmbH" }, + { 0x0979, "Jeilin Technology Corp., Ltd" }, + { 0x097a, "Minds At Work LLC" }, + { 0x097b, "Knudsen Engineering, Ltd" }, + { 0x097c, "Marunix Co., Ltd" }, + { 0x097d, "Rosun Technologies, Inc." }, + { 0x097e, "Biopac Systems Inc." }, + { 0x097f, "Barun Electronics Co., Ltd" }, + { 0x0981, "Oak Technology, Ltd" }, + { 0x0984, "Apricorn" }, + { 0x0985, "cab Produkttechnik GmbH & Co KG" }, + { 0x0986, "Matsushita Electric Works, Ltd." }, + { 0x098c, "Vitana Corp." }, + { 0x098d, "INDesign" }, + { 0x098e, "Integrated Intellectual Property, Inc." }, + { 0x098f, "Kenwood TMI Corp." }, + { 0x0993, "Gemstar eBook Group, Ltd" }, + { 0x0996, "Integrated Telecom Express, Inc." }, + { 0x099a, "Zippy Technology Corp." }, + { 0x09a3, "PairGain Technologies" }, + { 0x09a4, "Contech Research, Inc." }, + { 0x09a5, "VCON Telecommunications" }, + { 0x09a6, "Poinchips" }, + { 0x09a7, "Data Transmission Network Corp." }, + { 0x09a8, "Lin Shiung Enterprise Co., Ltd" }, + { 0x09a9, "Smart Card Technologies Co., Ltd" }, + { 0x09aa, "Intersil Corp." }, + { 0x09ab, "Japan Cash Machine Co., Ltd." }, + { 0x09ae, "Tripp Lite" }, + { 0x09b2, "Franklin Electronic Publishers, Inc." }, + { 0x09b3, "Altius Solutions, Inc." }, + { 0x09b4, "MDS Telephone Systems" }, + { 0x09b5, "Celltrix Technology Co., Ltd" }, + { 0x09bc, "Grundig" }, + { 0x09be, "MySmart.Com" }, + { 0x09bf, "Auerswald GmbH & Co. KG" }, + { 0x09c0, "Genpix Electronics, LLC" }, + { 0x09c1, "Arris Interactive LLC" }, + { 0x09c2, "Nisca Corp." }, + { 0x09c3, "ActivCard, Inc." }, + { 0x09c4, "ACTiSYS Corp." }, + { 0x09c5, "Memory Corp." }, + { 0x09ca, "BMC Messsysteme GmbH" }, + { 0x09cc, "Workbit Corp." }, + { 0x09cd, "Psion Dacom Home Networks, Ltd" }, + { 0x09ce, "City Electronics, Ltd" }, + { 0x09cf, "Electronics Testing Center, Taiwan" }, + { 0x09d1, "NeoMagic, Inc." }, + { 0x09d2, "Vreelin Engineering, Inc." }, + { 0x09d3, "Com One" }, + { 0x09d7, "Novatel Wireless" }, + { 0x09d9, "KRF Tech, Ltd" }, + { 0x09da, "A4Tech Co., Ltd." }, + { 0x09db, "Measurement Computing Corp." }, + { 0x09dc, "Aimex Corp." }, + { 0x09dd, "Fellowes, Inc." }, + { 0x09df, "Addonics Technologies Corp." }, + { 0x09e1, "Intellon Corp." }, + { 0x09e5, "Jo-Dan International, Inc." }, + { 0x09e6, "Silutia, Inc." }, + { 0x09e7, "Real 3D, Inc." }, + { 0x09e8, "AKAI Professional M.I. Corp." }, + { 0x09e9, "Chen-Source, Inc." }, + { 0x09eb, "IM Networks, Inc." }, + { 0x09ef, "Xitel" }, + { 0x09f3, "GoFlight, Inc." }, + { 0x09f5, "AresCom" }, + { 0x09f6, "RocketChips, Inc." }, + { 0x09f7, "Edu-Science (H.K.), Ltd" }, + { 0x09f8, "SoftConnex Technologies, Inc." }, + { 0x09f9, "Bay Associates" }, + { 0x09fa, "Mtek Vision" }, + { 0x09fb, "Altera" }, + { 0x09ff, "Gain Technology Corp." }, + { 0x0a00, "Liquid Audio" }, + { 0x0a01, "ViA, Inc." }, + { 0x0a05, "Unknown Manufacturer" }, + { 0x0a07, "Ontrak Control Systems Inc." }, + { 0x0a0b, "Cybex Computer Products Co." }, + { 0x0a0d, "Servergy, Inc" }, + { 0x0a11, "Xentec, Inc." }, + { 0x0a12, "Cambridge Silicon Radio, Ltd" }, + { 0x0a13, "Telebyte, Inc." }, + { 0x0a14, "Spacelabs Medical, Inc." }, + { 0x0a15, "Scalar Corp." }, + { 0x0a16, "Trek Technology (S) PTE, Ltd" }, + { 0x0a17, "Pentax Corp." }, + { 0x0a18, "Heidelberger Druckmaschinen AG" }, + { 0x0a19, "Hua Geng Technologies, Inc." }, + { 0x0a21, "Medtronic Physio Control Corp." }, + { 0x0a22, "Century Semiconductor USA, Inc." }, + { 0x0a27, "Datacard Group" }, + { 0x0a2c, "AK-Modul-Bus Computer GmbH" }, + { 0x0a34, "TG3 Electronics, Inc." }, + { 0x0a35, "Radikal Technologies" }, + { 0x0a39, "Gilat Satellite Networks, Ltd" }, + { 0x0a3a, "PentaMedia Co., Ltd" }, + { 0x0a3c, "NTT DoCoMo, Inc." }, + { 0x0a3d, "Varo Vision" }, + { 0x0a3f, "Swissonic AG" }, + { 0x0a43, "Boca Systems, Inc." }, + { 0x0a46, "Davicom Semiconductor, Inc." }, + { 0x0a47, "Hirose Electric" }, + { 0x0a48, "I/O Interconnect" }, + { 0x0a4a, "Ploytec GmbH" }, + { 0x0a4b, "Fujitsu Media Devices, Ltd" }, + { 0x0a4c, "Computex Co., Ltd" }, + { 0x0a4d, "Evolution Electronics, Ltd" }, + { 0x0a4e, "Steinberg Soft-und Hardware GmbH" }, + { 0x0a4f, "Litton Systems, Inc." }, + { 0x0a50, "Mimaki Engineering Co., Ltd" }, + { 0x0a51, "Sony Electronics, Inc." }, + { 0x0a52, "Jebsee Electronics Co., Ltd" }, + { 0x0a53, "Portable Peripheral Co., Ltd" }, + { 0x0a5a, "Electronics For Imaging, Inc." }, + { 0x0a5b, "EAsics NV" }, + { 0x0a5c, "Broadcom Corp." }, + { 0x0a5d, "Diatrend Corp." }, + { 0x0a5f, "Zebra" }, + { 0x0a62, "MPMan" }, + { 0x0a66, "ClearCube Technology" }, + { 0x0a67, "Medeli Electronics Co., Ltd" }, + { 0x0a68, "Comaide Corp." }, + { 0x0a69, "Chroma ate, Inc." }, + { 0x0a6b, "Green House Co., Ltd" }, + { 0x0a6c, "Integrated Circuit Systems, Inc." }, + { 0x0a6d, "UPS Manufacturing" }, + { 0x0a6e, "Benwin" }, + { 0x0a6f, "Core Technology, Inc." }, + { 0x0a70, "International Game Technology" }, + { 0x0a71, "VIPColor Technologies USA, Inc." }, + { 0x0a72, "Sanwa Denshi" }, + { 0x0a73, "Mackie Designs" }, + { 0x0a7d, "NSTL, Inc." }, + { 0x0a7e, "Octagon Systems Corp." }, + { 0x0a80, "Rexon Technology Corp., Ltd" }, + { 0x0a81, "Chesen Electronics Corp." }, + { 0x0a82, "Syscan" }, + { 0x0a83, "NextComm, Inc." }, + { 0x0a84, "Maui Innovative Peripherals" }, + { 0x0a85, "Idexx Labs" }, + { 0x0a86, "NITGen Co., Ltd" }, + { 0x0a89, "Aktiv" }, + { 0x0a8d, "Picturetel" }, + { 0x0a8e, "Japan Aviation Electronics Industry, Ltd" }, + { 0x0a90, "Candy Technology Co., Ltd" }, + { 0x0a91, "Globlink Technology, Inc." }, + { 0x0a92, "EGO SYStems, Inc." }, + { 0x0a93, "C Technologies AB" }, + { 0x0a94, "Intersense" }, + { 0x0aa3, "Lava Computer Mfg., Inc." }, + { 0x0aa4, "Develco Elektronik" }, + { 0x0aa5, "First International Digital" }, + { 0x0aa6, "Perception Digital, Ltd" }, + { 0x0aa7, "Wincor Nixdorf International GmbH" }, + { 0x0aa8, "TriGem Computer, Inc." }, + { 0x0aa9, "Baromtec Co." }, + { 0x0aaa, "Japan CBM Corp." }, + { 0x0aab, "Vision Shape Europe SA" }, + { 0x0aac, "iCompression, Inc." }, + { 0x0aad, "Rohde & Schwarz GmbH & Co. KG" }, + { 0x0aae, "NEC infrontia Corp. (Nitsuko)" }, + { 0x0aaf, "Digitalway Co., Ltd" }, + { 0x0ab0, "Arrow Strong Electronics Co., Ltd" }, + { 0x0ab1, "FEIG ELECTRONIC GmbH" }, + { 0x0aba, "Ellisys" }, + { 0x0abe, "Stereo-Link" }, + { 0x0abf, "Diolan" }, + { 0x0ac3, "Sanyo Semiconductor Company Micro" }, + { 0x0ac4, "Leco Corp." }, + { 0x0ac5, "I & C Corp." }, + { 0x0ac6, "Singing Electrons, Inc." }, + { 0x0ac7, "Panwest Corp." }, + { 0x0ac8, "Z-Star Microelectronics Corp." }, + { 0x0ac9, "Micro Solutions, Inc." }, + { 0x0aca, "OPEN Networks Ltd" }, + { 0x0acc, "Koga Electronics Co." }, + { 0x0acd, "ID Tech" }, + { 0x0ace, "ZyDAS" }, + { 0x0acf, "Intoto, Inc." }, + { 0x0ad0, "Intellix Corp." }, + { 0x0ad1, "Remotec Technology, Ltd" }, + { 0x0ad2, "Service & Quality Technology Co., Ltd" }, + { 0x0ada, "Data Encryption Systems Ltd." }, + { 0x0ae3, "Allion Computer, Inc." }, + { 0x0ae4, "Taito Corp." }, + { 0x0ae7, "Neodym Systems, Inc." }, + { 0x0ae8, "System Support Co., Ltd" }, + { 0x0ae9, "North Shore Circuit Design L.L.P." }, + { 0x0aea, "SciEssence, LLC" }, + { 0x0aeb, "TTP Communications, Ltd" }, + { 0x0aec, "Neodio Technologies Corp." }, + { 0x0af0, "Option" }, + { 0x0af6, "Silver I Co., Ltd" }, + { 0x0af7, "B2C2, Inc." }, + { 0x0af9, "Hama, Inc." }, + { 0x0afa, "DMC Co., Ltd." }, + { 0x0afc, "Zaptronix Ltd" }, + { 0x0afd, "Tateno Dennou, Inc." }, + { 0x0afe, "Cummins Engine Co." }, + { 0x0aff, "Jump Zone Network Products, Inc." }, + { 0x0b00, "INGENICO" }, + { 0x0b05, "ASUSTek Computer, Inc." }, + { 0x0b0b, "Datamax-O'Neil" }, + { 0x0b0c, "Todos AB" }, + { 0x0b0d, "ProjectLab" }, + { 0x0b0e, "GN Netcom" }, + { 0x0b0f, "AVID Technology" }, + { 0x0b10, "Pcally" }, + { 0x0b11, "I Tech Solutions Co., Ltd" }, + { 0x0b1e, "Electronic Warfare Assoc., Inc. (EWA)" }, + { 0x0b1f, "Insyde Software Corp." }, + { 0x0b20, "TransDimension, Inc." }, + { 0x0b21, "Yokogawa Electric Corp." }, + { 0x0b22, "Japan System Development Co., Ltd" }, + { 0x0b23, "Pan-Asia Electronics Co., Ltd" }, + { 0x0b24, "Link Evolution Corp." }, + { 0x0b27, "Ritek Corp." }, + { 0x0b28, "Kenwood Corp." }, + { 0x0b2c, "Village Center, Inc." }, + { 0x0b30, "PNY Technologies, Inc." }, + { 0x0b33, "Contour Design, Inc." }, + { 0x0b37, "Hitachi ULSI Systems Co., Ltd" }, + { 0x0b38, "Gear Head" }, + { 0x0b39, "Omnidirectional Control Technology, Inc." }, + { 0x0b3a, "IPaxess" }, + { 0x0b3b, "Tekram Technology Co., Ltd" }, + { 0x0b3c, "Olivetti Techcenter" }, + { 0x0b3e, "Kikusui Electronics Corp." }, + { 0x0b41, "Hal Corp." }, + { 0x0b43, "Play.com, Inc." }, + { 0x0b47, "Sportbug.com, Inc." }, + { 0x0b48, "TechnoTrend AG" }, + { 0x0b49, "ASCII Corp." }, + { 0x0b4b, "Pine Corp. Ltd." }, + { 0x0b4d, "Graphtec America, Inc." }, + { 0x0b4e, "Musical Electronics, Ltd" }, + { 0x0b50, "Dumpries Co., Ltd" }, + { 0x0b51, "Comfort Keyboard Co." }, + { 0x0b52, "Colorado MicroDisplay, Inc." }, + { 0x0b54, "Sinbon Electronics Co., Ltd" }, + { 0x0b56, "TYI Systems, Ltd" }, + { 0x0b57, "Beijing HanwangTechnology Co., Ltd" }, + { 0x0b59, "Lake Communications, Ltd" }, + { 0x0b5a, "Corel Corp." }, + { 0x0b5f, "Green Electronics Co., Ltd" }, + { 0x0b60, "Nsine, Ltd" }, + { 0x0b61, "NEC Viewtechnology, Ltd" }, + { 0x0b62, "Orange Micro, Inc." }, + { 0x0b63, "ADLink Technology, Inc." }, + { 0x0b64, "Wonderful Wire Cable Co., Ltd" }, + { 0x0b65, "Expert Magnetics Corp." }, + { 0x0b66, "Cybiko Inc." }, + { 0x0b67, "Fairbanks Scales" }, + { 0x0b69, "CacheVision" }, + { 0x0b6a, "Maxim Integrated Products" }, + { 0x0b6f, "Nagano Japan Radio Co., Ltd" }, + { 0x0b70, "PortalPlayer, Inc." }, + { 0x0b71, "SHIN-EI Sangyo Co., Ltd" }, + { 0x0b72, "Embedded Wireless Technology Co., Ltd" }, + { 0x0b73, "Computone Corp." }, + { 0x0b75, "Roland DG Corp." }, + { 0x0b79, "Sunrise Telecom, Inc." }, + { 0x0b7a, "Zeevo, Inc." }, + { 0x0b7b, "Taiko Denki Co., Ltd" }, + { 0x0b7c, "ITRAN Communications, Ltd" }, + { 0x0b7d, "Astrodesign, Inc." }, + { 0x0b81, "id3 Technologies" }, + { 0x0b84, "Rextron Technology, Inc." }, + { 0x0b85, "Elkat Electronics, Sdn., Bhd." }, + { 0x0b86, "Exputer Systems, Inc." }, + { 0x0b87, "Plus-One I & T, Inc." }, + { 0x0b88, "Sigma Koki Co., Ltd, Technology Center" }, + { 0x0b89, "Advanced Digital Broadcast, Ltd" }, + { 0x0b8c, "SMART Technologies Inc." }, + { 0x0b95, "ASIX Electronics Corp." }, + { 0x0b96, "Sewon Telecom" }, + { 0x0b97, "O2 Micro, Inc." }, + { 0x0b98, "Playmates Toys, Inc." }, + { 0x0b99, "Audio International, Inc." }, + { 0x0b9b, "Dipl.-Ing. Stefan Kunde" }, + { 0x0b9d, "Softprotec Co." }, + { 0x0b9f, "Chippo Technologies" }, + { 0x0baf, "U.S. Robotics" }, + { 0x0bb0, "Concord Camera Corp." }, + { 0x0bb1, "Infinilink Corp." }, + { 0x0bb2, "Ambit Microsystems Corp." }, + { 0x0bb3, "Ofuji Technology" }, + { 0x0bb4, "HTC (High Tech Computer Corp.)" }, + { 0x0bb5, "Murata Manufacturing Co., Ltd" }, + { 0x0bb6, "Network Alchemy" }, + { 0x0bb7, "Joytech Computer Co., Ltd" }, + { 0x0bb8, "Hitachi Semiconductor and Devices Sales Co., Ltd" }, + { 0x0bb9, "Eiger M&C Co., Ltd" }, + { 0x0bba, "ZAccess Systems" }, + { 0x0bbb, "General Meters Corp." }, + { 0x0bbc, "Assistive Technology, Inc." }, + { 0x0bbd, "System Connection, Inc." }, + { 0x0bc0, "Knilink Technology, Inc." }, + { 0x0bc1, "Fuw Yng Electronics Co., Ltd" }, + { 0x0bc2, "Seagate RSS LLC" }, + { 0x0bc3, "IPWireless, Inc." }, + { 0x0bc4, "Microcube Corp." }, + { 0x0bc5, "JCN Co., Ltd" }, + { 0x0bc6, "ExWAY, Inc." }, + { 0x0bc7, "X10 Wireless Technology, Inc." }, + { 0x0bc8, "Telmax Communications" }, + { 0x0bc9, "ECI Telecom, Ltd" }, + { 0x0bca, "Startek Engineering, Inc." }, + { 0x0bcb, "Perfect Technic Enterprise Co., Ltd" }, + { 0x0bd7, "Andrew Pargeter & Associates" }, + { 0x0bda, "Realtek Semiconductor Corp." }, + { 0x0bdb, "Ericsson Business Mobile Networks BV" }, + { 0x0bdc, "Y Media Corp." }, + { 0x0bdd, "Orange PCS" }, + { 0x0be2, "Kanda Tsushin Kogyo Co., Ltd" }, + { 0x0be3, "TOYO Corp." }, + { 0x0be4, "Elka International, Ltd" }, + { 0x0be5, "DOME imaging systems, Inc." }, + { 0x0be6, "Dong Guan Humen Wonderful Wire Cable Factory" }, + { 0x0bed, "MEI" }, + { 0x0bee, "LTK Industries, Ltd" }, + { 0x0bef, "Way2Call Communications" }, + { 0x0bf0, "Pace Micro Technology PLC" }, + { 0x0bf1, "Intracom S.A." }, + { 0x0bf2, "Konexx" }, + { 0x0bf6, "Addonics Technologies, Inc." }, + { 0x0bf7, "Sunny Giken, Inc." }, + { 0x0bf8, "Fujitsu Siemens Computers" }, + { 0x0bfd, "Kvaser AB" }, + { 0x0c04, "MOTO Development Group, Inc." }, + { 0x0c05, "Appian Graphics" }, + { 0x0c06, "Hasbro Games, Inc." }, + { 0x0c07, "Infinite Data Storage, Ltd" }, + { 0x0c08, "Agate" }, + { 0x0c09, "Comjet Information System" }, + { 0x0c0a, "Highpoint Technologies, Inc." }, + { 0x0c0b, "Dura Micro, Inc. (Acomdata)" }, + { 0x0c12, "Zeroplus" }, + { 0x0c15, "Iris Graphics" }, + { 0x0c16, "Gyration, Inc." }, + { 0x0c17, "Cyberboard A/S" }, + { 0x0c18, "SynerTek Korea, Inc." }, + { 0x0c19, "cyberPIXIE, Inc." }, + { 0x0c1a, "Silicon Motion, Inc." }, + { 0x0c1b, "MIPS Technologies" }, + { 0x0c1c, "Hang Zhou Silan Electronics Co., Ltd" }, + { 0x0c22, "Tally Printer Corp." }, + { 0x0c23, "Lernout + Hauspie" }, + { 0x0c24, "Taiyo Yuden" }, + { 0x0c25, "Sampo Corp." }, + { 0x0c26, "Prolific Technology Inc." }, + { 0x0c27, "RFIDeas, Inc" }, + { 0x0c2e, "Metrologic Instruments" }, + { 0x0c35, "Eagletron, Inc." }, + { 0x0c36, "E Ink Corp." }, + { 0x0c37, "e.Digital" }, + { 0x0c38, "Der An Electric Wire & Cable Co., Ltd" }, + { 0x0c39, "IFR" }, + { 0x0c3a, "Furui Precise Component (Kunshan) Co., Ltd" }, + { 0x0c3b, "Komatsu, Ltd" }, + { 0x0c3c, "Radius Co., Ltd" }, + { 0x0c3d, "Innocom, Inc." }, + { 0x0c3e, "Nextcell, Inc." }, + { 0x0c44, "Motorola iDEN" }, + { 0x0c45, "Microdia" }, + { 0x0c46, "WaveRider Communications, Inc." }, + { 0x0c4a, "ALGE-TIMING GmbH" }, + { 0x0c4b, "Reiner SCT Kartensysteme GmbH" }, + { 0x0c4c, "Needham's Electronics" }, + { 0x0c52, "Sealevel Systems, Inc." }, + { 0x0c53, "ViewPLUS, Inc." }, + { 0x0c54, "Glory, Ltd" }, + { 0x0c55, "Spectrum Digital, Inc." }, + { 0x0c56, "Billion Bright, Ltd" }, + { 0x0c57, "Imaginative Design Operation Co., Ltd" }, + { 0x0c58, "Vidar Systems Corp." }, + { 0x0c59, "Dong Guan Shinko Wire Co., Ltd" }, + { 0x0c5a, "TRS International Mfg., Inc." }, + { 0x0c5e, "Xytronix Research & Design" }, + { 0x0c60, "Apogee Electronics Corp." }, + { 0x0c62, "Chant Sincere Co., Ltd" }, + { 0x0c63, "Toko, Inc." }, + { 0x0c64, "Signality System Engineering Co., Ltd" }, + { 0x0c65, "Eminence Enterprise Co., Ltd" }, + { 0x0c66, "Rexon Electronics Corp." }, + { 0x0c67, "Concept Telecom, Ltd" }, + { 0x0c6a, "ACS" }, + { 0x0c6c, "JETI Technische Instrumente GmbH" }, + { 0x0c70, "MCT Elektronikladen" }, + { 0x0c72, "PEAK System" }, + { 0x0c74, "Optronic Laboratories Inc." }, + { 0x0c76, "JMTek, LLC." }, + { 0x0c77, "Sipix Group, Ltd" }, + { 0x0c78, "Detto Corp." }, + { 0x0c79, "NuConnex Technologies Pte., Ltd" }, + { 0x0c7a, "Wing-Span Enterprise Co., Ltd" }, + { 0x0c86, "NDA Technologies, Inc." }, + { 0x0c88, "Kyocera Wireless Corp." }, + { 0x0c89, "Honda Tsushin Kogyo Co., Ltd" }, + { 0x0c8a, "Pathway Connectivity, Inc." }, + { 0x0c8b, "Wavefly Corp." }, + { 0x0c8c, "Coactive Networks" }, + { 0x0c8d, "Tempo" }, + { 0x0c8e, "Cesscom Co., Ltd" }, + { 0x0c8f, "Applied Microsystems" }, + { 0x0c94, "Cryptera" }, + { 0x0c98, "Berkshire Products, Inc." }, + { 0x0c99, "Innochips Co., Ltd" }, + { 0x0c9a, "Hanwool Robotics Corp." }, + { 0x0c9b, "Jobin Yvon, Inc." }, + { 0x0c9d, "SemTek" }, + { 0x0ca2, "Zyfer" }, + { 0x0ca3, "Sega Corp." }, + { 0x0ca4, "ST&T Instrument Corp." }, + { 0x0ca5, "BAE Systems Canada, Inc." }, + { 0x0ca6, "Castles Technology Co., Ltd" }, + { 0x0ca7, "Information Systems Laboratories" }, + { 0x0cad, "Motorola CGISS" }, + { 0x0cae, "Ascom Business Systems, Ltd" }, + { 0x0caf, "Buslink" }, + { 0x0cb0, "Flying Pig Systems" }, + { 0x0cb1, "Innovonics, Inc." }, + { 0x0cb6, "Celestix Networks, Pte., Ltd" }, + { 0x0cb7, "Singatron Enterprise Co., Ltd" }, + { 0x0cb8, "Opticis Co., Ltd" }, + { 0x0cba, "Trust Electronic (Shanghai) Co., Ltd" }, + { 0x0cbb, "Shanghai Darong Electronics Co., Ltd" }, + { 0x0cbc, "Palmax Technology Co., Ltd" }, + { 0x0cbd, "Pentel Co., Ltd (Electronics Equipment Div.)" }, + { 0x0cbe, "Keryx Technologies, Inc." }, + { 0x0cbf, "Union Genius Computer Co., Ltd" }, + { 0x0cc0, "Kuon Yi Industrial Corp." }, + { 0x0cc1, "Given Imaging, Ltd" }, + { 0x0cc2, "Timex Corp." }, + { 0x0cc3, "Rimage Corp." }, + { 0x0cc4, "emsys GmbH" }, + { 0x0cc5, "Sendo" }, + { 0x0cc6, "Intermagic Corp." }, + { 0x0cc7, "Kontron Medical AG" }, + { 0x0cc8, "Technotools Corp." }, + { 0x0cc9, "BroadMAX Technologies, Inc." }, + { 0x0cca, "Amphenol" }, + { 0x0ccb, "SKNet Co., Ltd" }, + { 0x0ccc, "Domex Technology Corp." }, + { 0x0ccd, "TerraTec Electronic GmbH" }, + { 0x0cd4, "Bang Olufsen" }, + { 0x0cd5, "LabJack Corporation" }, + { 0x0cd7, "NewChip S.r.l." }, + { 0x0cd8, "JS Digitech, Inc." }, + { 0x0cd9, "Hitachi Shin Din Cable, Ltd" }, + { 0x0cde, "Z-Com" }, + { 0x0ce5, "Validation Technologies International" }, + { 0x0ce9, "Pico Technology" }, + { 0x0cf1, "e-Conn Electronic Co., Ltd" }, + { 0x0cf2, "ENE Technology, Inc." }, + { 0x0cf3, "Atheros Communications, Inc." }, + { 0x0cf4, "Fomtex Corp." }, + { 0x0cf5, "Cellink Co., Ltd" }, + { 0x0cf6, "Compucable Corp." }, + { 0x0cf7, "ishoni Networks" }, + { 0x0cf8, "Clarisys, Inc." }, + { 0x0cf9, "Central System Research Co., Ltd" }, + { 0x0cfa, "Inviso, Inc." }, + { 0x0cfc, "Minolta-QMS, Inc." }, + { 0x0cff, "SAFA MEDIA Co., Ltd." }, + { 0x0d06, "telos EDV Systementwicklung GmbH" }, + { 0x0d08, "UTStarcom" }, + { 0x0d0b, "Contemporary Controls" }, + { 0x0d0c, "Astron Electronics Co., Ltd" }, + { 0x0d0d, "MKNet Corp." }, + { 0x0d0e, "Hybrid Networks, Inc." }, + { 0x0d0f, "Feng Shin Cable Co., Ltd" }, + { 0x0d10, "Elastic Networks" }, + { 0x0d11, "Maspro Denkoh Corp." }, + { 0x0d12, "Hansol Electronics, Inc." }, + { 0x0d13, "BMF Corp." }, + { 0x0d14, "Array Comm, Inc." }, + { 0x0d15, "OnStream b.v." }, + { 0x0d16, "Hi-Touch Imaging Technologies Co., Ltd" }, + { 0x0d17, "NALTEC, Inc." }, + { 0x0d18, "coaXmedia" }, + { 0x0d19, "Hank Connection Industrial Co., Ltd" }, + { 0x0d28, "NXP" }, + { 0x0d32, "Leo Hui Electric Wire & Cable Co., Ltd" }, + { 0x0d33, "AirSpeak, Inc." }, + { 0x0d34, "Rearden Steel Technologies" }, + { 0x0d35, "Dah Kun Co., Ltd" }, + { 0x0d3a, "Posiflex Technologies, Inc." }, + { 0x0d3c, "Sri Cable Technology, Ltd" }, + { 0x0d3d, "Tangtop Technology Co., Ltd" }, + { 0x0d3e, "Fitcom, inc." }, + { 0x0d3f, "MTS Systems Corp." }, + { 0x0d40, "Ascor, Inc." }, + { 0x0d41, "Ta Yun Terminals Industrial Co., Ltd" }, + { 0x0d42, "Full Der Co., Ltd" }, + { 0x0d46, "Kobil Systems GmbH" }, + { 0x0d48, "Promethean Limited" }, + { 0x0d49, "Maxtor" }, + { 0x0d4a, "NF Corp." }, + { 0x0d4b, "Grape Systems, Inc." }, + { 0x0d4c, "Tedas AG" }, + { 0x0d4d, "Coherent, Inc." }, + { 0x0d4e, "Agere Systems Netherland BV" }, + { 0x0d4f, "EADS Airbus France" }, + { 0x0d50, "Cleware GmbH" }, + { 0x0d51, "Volex (Asia) Pte., Ltd" }, + { 0x0d53, "HMI Co., Ltd" }, + { 0x0d54, "Holon Corp." }, + { 0x0d55, "ASKA Technologies, Inc." }, + { 0x0d56, "AVLAB Technology, Inc." }, + { 0x0d57, "Solomon Microtech, Ltd" }, + { 0x0d5c, "SMC Networks, Inc." }, + { 0x0d5e, "Myacom, Ltd" }, + { 0x0d5f, "CSI, Inc." }, + { 0x0d60, "IVL Technologies, Ltd" }, + { 0x0d61, "Meilu Electronics (Shenzhen) Co., Ltd" }, + { 0x0d62, "Darfon Electronics Corp." }, + { 0x0d63, "Fritz Gegauf AG" }, + { 0x0d64, "DXG Technology Corp." }, + { 0x0d65, "KMJP Co., Ltd" }, + { 0x0d66, "TMT" }, + { 0x0d67, "Advanet, Inc." }, + { 0x0d68, "Super Link Electronics Co., Ltd" }, + { 0x0d69, "NSI" }, + { 0x0d6a, "Megapower International Corp." }, + { 0x0d6b, "And-Or Logic" }, + { 0x0d70, "Try Computer Co., Ltd" }, + { 0x0d71, "Hirakawa Hewtech Corp." }, + { 0x0d72, "Winmate Communication, Inc." }, + { 0x0d73, "Hit's Communications, Inc." }, + { 0x0d76, "MFP Korea, Inc." }, + { 0x0d77, "Power Sentry/Newpoint" }, + { 0x0d78, "Japan Distributor Corp." }, + { 0x0d7a, "MARX Datentechnik GmbH" }, + { 0x0d7b, "Wellco Technology Co., Ltd" }, + { 0x0d7c, "Taiwan Line Tek Electronic Co., Ltd" }, + { 0x0d7d, "Phison Electronics Corp." }, + { 0x0d7e, "American Computer & Digital Components" }, + { 0x0d7f, "Essential Reality LLC" }, + { 0x0d80, "H.R. Silvine Electronics, Inc." }, + { 0x0d81, "TechnoVision" }, + { 0x0d83, "Think Outside, Inc." }, + { 0x0d87, "Dolby Laboratories Inc." }, + { 0x0d89, "Oz Software" }, + { 0x0d8a, "King Jim Co., Ltd" }, + { 0x0d8b, "Ascom Telecommunications, Ltd" }, + { 0x0d8c, "C-Media Electronics, Inc." }, + { 0x0d8d, "Promotion & Display Technology, Ltd" }, + { 0x0d8e, "Global Sun Technology, Inc." }, + { 0x0d8f, "Pitney Bowes" }, + { 0x0d90, "Sure-Fire Electrical Corp." }, + { 0x0d96, "Skanhex Technology, Inc." }, + { 0x0d97, "Santa Barbara Instrument Group" }, + { 0x0d98, "Mars Semiconductor Corp." }, + { 0x0d99, "Trazer Technologies, Inc." }, + { 0x0d9a, "RTX Telecom AS" }, + { 0x0d9b, "Tat Shing Electrical Co." }, + { 0x0d9c, "Chee Chen Hi-Technology Co., Ltd" }, + { 0x0d9d, "Sanwa Supply, Inc." }, + { 0x0d9e, "Avaya" }, + { 0x0d9f, "Powercom Co., Ltd" }, + { 0x0da0, "Danger Research" }, + { 0x0da1, "Suzhou Peter's Precise Industrial Co., Ltd" }, + { 0x0da2, "Land Instruments International, Ltd" }, + { 0x0da3, "Nippon Electro-Sensory Devices Corp." }, + { 0x0da4, "Polar Electro Oy" }, + { 0x0da7, "IOGear, Inc." }, + { 0x0da8, "softDSP Co., Ltd" }, + { 0x0dab, "Cubig Group" }, + { 0x0dad, "Westover Scientific" }, + { 0x0db0, "Micro Star International" }, + { 0x0db1, "Wen Te Electronics Co., Ltd" }, + { 0x0db2, "Shian Hwi Plug Parts, Plastic Factory" }, + { 0x0db3, "Tekram Technology Co., Ltd" }, + { 0x0db4, "Chung Fu Chen Yeh Enterprise Corp." }, + { 0x0db5, "Access IS" }, + { 0x0db7, "ELCON Systemtechnik" }, + { 0x0dba, "Digidesign" }, + { 0x0dbc, "A&D Medical" }, + { 0x0dbe, "Jiuh Shiuh Precision Industry Co., Ltd" }, + { 0x0dbf, "Jess-Link International" }, + { 0x0dc0, "G7 Solutions (formerly Great Notions)" }, + { 0x0dc1, "Tamagawa Seiki Co., Ltd" }, + { 0x0dc3, "Athena Smartcard Solutions, Inc." }, + { 0x0dc4, "Macpower Peripherals, Ltd" }, + { 0x0dc5, "SDK Co., Ltd" }, + { 0x0dc6, "Precision Squared Technology Corp." }, + { 0x0dc7, "First Cable Line, Inc." }, + { 0x0dcd, "NetworkFab Corp." }, + { 0x0dd0, "Access Solutions" }, + { 0x0dd1, "Contek Electronics Co., Ltd" }, + { 0x0dd2, "Power Quotient International Co., Ltd" }, + { 0x0dd3, "MediaQ" }, + { 0x0dd4, "Custom Engineering SPA" }, + { 0x0dd5, "California Micro Devices" }, + { 0x0dd7, "Kocom Co., Ltd" }, + { 0x0dd8, "Netac Technology Co., Ltd" }, + { 0x0dd9, "HighSpeed Surfing" }, + { 0x0dda, "Integrated Circuit Solution, Inc." }, + { 0x0ddb, "Tamarack, Inc." }, + { 0x0ddd, "Datelink Technology Co., Ltd" }, + { 0x0dde, "Ubicom, Inc." }, + { 0x0de0, "BD Consumer Healthcare" }, + { 0x0de7, "USBmicro" }, + { 0x0dea, "UTECH Electronic (D.G.) Co., Ltd." }, + { 0x0ded, "Novasonics" }, + { 0x0dee, "Lifetime Memory Products" }, + { 0x0def, "Full Rise Electronic Co., Ltd" }, + { 0x0df4, "NET&SYS" }, + { 0x0df6, "Sitecom Europe B.V." }, + { 0x0df7, "Mobile Action Technology, Inc." }, + { 0x0dfa, "Toyo Communication Equipment Co., Ltd" }, + { 0x0dfc, "GeneralTouch Technology Co., Ltd" }, + { 0x0e03, "Nippon Systemware Co., Ltd" }, + { 0x0e08, "Winbest Technology Co., Ltd" }, + { 0x0e0b, "Amigo Technology Inc." }, + { 0x0e0c, "Gesytec" }, + { 0x0e0d, "PicoQuant GmbH" }, + { 0x0e0f, "VMware, Inc." }, + { 0x0e16, "JMTek, LLC" }, + { 0x0e17, "Walex Electronic, Ltd" }, + { 0x0e1a, "Unisys" }, + { 0x0e1b, "Crewave" }, + { 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" }, + { 0x0e30, "HeartMath LLC" }, + { 0x0e34, "Micro Computer Control Corp." }, + { 0x0e35, "3Pea Technologies, Inc." }, + { 0x0e36, "TiePie engineering" }, + { 0x0e38, "Stratitec, Inc." }, + { 0x0e39, "Smart Modular Technologies, Inc." }, + { 0x0e3a, "Neostar Technology Co., Ltd" }, + { 0x0e3b, "Mansella, Ltd" }, + { 0x0e41, "Line6, Inc." }, + { 0x0e44, "Sun-Riseful Technology Co., Ltd." }, + { 0x0e48, "Julia Corp., Ltd" }, + { 0x0e4a, "Shenzhen Bao Hing Electric Wire & Cable Mfr. Co." }, + { 0x0e4c, "Radica Games, Ltd" }, + { 0x0e50, "TechnoData Interware" }, + { 0x0e55, "Speed Dragon Multimedia, Ltd" }, + { 0x0e56, "Kingston Technology Company, Inc." }, + { 0x0e5a, "Active Co., Ltd" }, + { 0x0e5b, "Union Power Information Industrial Co., Ltd" }, + { 0x0e5c, "Bitland Information Technology Co., Ltd" }, + { 0x0e5d, "Neltron Industrial Co., Ltd" }, + { 0x0e5e, "Conwise Technology Co., Ltd." }, + { 0x0e66, "Hawking Technologies" }, + { 0x0e67, "Fossil, Inc." }, + { 0x0e6a, "Megawin Technology Co., Ltd" }, + { 0x0e6f, "Logic3" }, + { 0x0e70, "Tokyo Electronic Industry Co., Ltd" }, + { 0x0e72, "Hsi-Chin Electronics Co., Ltd" }, + { 0x0e75, "TVS Electronics, Ltd" }, + { 0x0e79, "Archos, Inc." }, + { 0x0e7b, "On-Tech Industry Co., Ltd" }, + { 0x0e7e, "Gmate, Inc." }, + { 0x0e82, "Ching Tai Electric Wire & Cable Co., Ltd" }, + { 0x0e83, "Shin An Wire & Cable Co." }, + { 0x0e8c, "Well Force Electronic Co., Ltd" }, + { 0x0e8d, "MediaTek Inc." }, + { 0x0e8f, "GreenAsia Inc." }, + { 0x0e90, "WiebeTech, LLC" }, + { 0x0e91, "VTech Engineering Canada, Ltd" }, + { 0x0e92, "C's Glory Enterprise Co., Ltd" }, + { 0x0e93, "eM Technics Co., Ltd" }, + { 0x0e95, "Future Technology Co., Ltd" }, + { 0x0e96, "Aplux Communications, Ltd" }, + { 0x0e97, "Fingerworks, Inc." }, + { 0x0e98, "Advanced Analogic Technologies, Inc." }, + { 0x0e99, "Parallel Dice Co., Ltd" }, + { 0x0e9a, "TA HSING Industries, Ltd" }, + { 0x0e9b, "ADTEC Corp." }, + { 0x0e9c, "Streamzap, Inc." }, + { 0x0e9f, "Tamura Corp." }, + { 0x0ea0, "Ours Technology, Inc." }, + { 0x0ea6, "Nihon Computer Co., Ltd" }, + { 0x0ea7, "MSL Enterprises Corp." }, + { 0x0ea8, "CenDyne, Inc." }, + { 0x0ead, "Humax Co., Ltd" }, + { 0x0eb0, "NovaTech" }, + { 0x0eb1, "WIS Technologies, Inc." }, + { 0x0eb2, "Y-S Electronic Co., Ltd" }, + { 0x0eb3, "Saint Technology Corp." }, + { 0x0eb7, "Endor AG" }, + { 0x0eb8, "Mettler Toledo" }, + { 0x0ebb, "Thermo Fisher Scientific" }, + { 0x0ebe, "VWeb Corp." }, + { 0x0ebf, "Omega Technology of Taiwan, Inc." }, + { 0x0ec0, "LHI Technology (China) Co., Ltd" }, + { 0x0ec1, "Abit Computer Corp." }, + { 0x0ec2, "Sweetray Industrial, Ltd" }, + { 0x0ec3, "Axell Co., Ltd" }, + { 0x0ec4, "Ballracing Developments, Ltd" }, + { 0x0ec5, "GT Information System Co., Ltd" }, + { 0x0ec6, "InnoVISION Multimedia, Ltd" }, + { 0x0ec7, "Theta Link Corp." }, + { 0x0ecd, "Lite-On IT Corp." }, + { 0x0ece, "TaiSol Electronics Co., Ltd" }, + { 0x0ecf, "Phogenix Imaging, LLC" }, + { 0x0ed1, "WinMaxGroup" }, + { 0x0ed2, "Kyoto Micro Computer Co., Ltd" }, + { 0x0ed3, "Wing-Tech Enterprise Co., Ltd" }, + { 0x0ed5, "Fiberbyte" }, + { 0x0eda, "Noriake Itron Corp." }, + { 0x0edf, "e-MDT Co., Ltd" }, + { 0x0ee0, "Shima Seiki Mfg., Ltd" }, + { 0x0ee1, "Sarotech Co., Ltd" }, + { 0x0ee2, "AMI Semiconductor, Inc." }, + { 0x0ee3, "ComTrue Technology Corp." }, + { 0x0ee4, "Sunrich Technology, Ltd" }, + { 0x0eee, "Digital Stream Technology, Inc." }, + { 0x0eef, "D-WAV Scientific Co., Ltd" }, + { 0x0ef0, "Hitachi Cable, Ltd" }, + { 0x0ef1, "Aichi Micro Intelligent Corp." }, + { 0x0ef2, "I/O Magic Corp." }, + { 0x0ef3, "Lynn Products, Inc." }, + { 0x0ef4, "DSI Datotech" }, + { 0x0ef5, "PointChips" }, + { 0x0ef6, "Yield Microelectronics Corp." }, + { 0x0ef7, "SM Tech Co., Ltd (Tulip)" }, + { 0x0efd, "Oasis Semiconductor" }, + { 0x0efe, "Wem Technology, Inc." }, + { 0x0f03, "Unitek UPS Systems" }, + { 0x0f06, "Visual Frontier Enterprise Co., Ltd" }, + { 0x0f08, "CSL Wire & Plug (Shen Zhen) Co." }, + { 0x0f0c, "CAS Corp." }, + { 0x0f0d, "Hori Co., Ltd" }, + { 0x0f0e, "Energy Full Corp." }, + { 0x0f11, "LD Didactic GmbH" }, + { 0x0f12, "Mars Engineering Corp." }, + { 0x0f13, "Acetek Technology Co., Ltd" }, + { 0x0f14, "Ingenico" }, + { 0x0f18, "Finger Lakes Instrumentation" }, + { 0x0f19, "Oracom Co., Ltd" }, + { 0x0f1b, "Onset Computer Corp." }, + { 0x0f1c, "Funai Electric Co., Ltd" }, + { 0x0f1d, "Iwill Corp." }, + { 0x0f21, "IOI Technology Corp." }, + { 0x0f22, "Senior Industries, Inc." }, + { 0x0f23, "Leader Tech Manufacturer Co., Ltd" }, + { 0x0f24, "Flex-P Industries, Snd., Bhd." }, + { 0x0f2d, "ViPower, Inc." }, + { 0x0f2e, "Geniality Maple Technology Co., Ltd" }, + { 0x0f2f, "Priva Design Services" }, + { 0x0f30, "Jess Technology Co., Ltd" }, + { 0x0f31, "Chrysalis Development" }, + { 0x0f32, "YFC-BonEagle Electric Co., Ltd" }, + { 0x0f37, "Kokuyo Co., Ltd" }, + { 0x0f38, "Nien-Yi Industrial Corp." }, + { 0x0f39, "TG3 Electronics" }, + { 0x0f3d, "Airprime, Incorporated" }, + { 0x0f41, "RDC Semiconductor Co., Ltd" }, + { 0x0f42, "Nital Consulting Services, Inc." }, + { 0x0f44, "Polhemus" }, + { 0x0f4b, "St. John Technology Co., Ltd" }, + { 0x0f4c, "WorldWide Cable Opto Corp." }, + { 0x0f4d, "Microtune, Inc." }, + { 0x0f4e, "Freedom Scientific" }, + { 0x0f52, "Wing Key Electrical Co., Ltd" }, + { 0x0f53, "Dongguan White Horse Cable Factory, Ltd" }, + { 0x0f54, "Kawai Musical Instruments Mfg. Co., Ltd" }, + { 0x0f55, "AmbiCom, Inc." }, + { 0x0f5c, "Prairiecomm, Inc." }, + { 0x0f5d, "NewAge International, LLC" }, + { 0x0f5f, "Key Technology Corp." }, + { 0x0f60, "NTK, Ltd" }, + { 0x0f61, "Varian, Inc." }, + { 0x0f62, "Acrox Technologies Co., Ltd" }, + { 0x0f63, "LeapFrog Enterprises" }, + { 0x0f68, "Kobe Steel, Ltd" }, + { 0x0f69, "Dionex Corp." }, + { 0x0f6a, "Vibren Technologies, Inc." }, + { 0x0f6e, "INTELLIGENT SYSTEMS" }, + { 0x0f73, "DFI" }, + { 0x0f78, "Guntermann & Drunck GmbH" }, + { 0x0f7c, "DQ Technology, Inc." }, + { 0x0f7d, "NetBotz, Inc." }, + { 0x0f7e, "Fluke Corp." }, + { 0x0f88, "VTech Holdings, Ltd" }, + { 0x0f8b, "Yazaki Corp." }, + { 0x0f8c, "Young Generation International Corp." }, + { 0x0f8d, "Uniwill Computer Corp." }, + { 0x0f8e, "Kingnet Technology Co., Ltd" }, + { 0x0f8f, "Soma Networks" }, + { 0x0f97, "CviLux Corp." }, + { 0x0f98, "CyberBank Corp." }, + { 0x0f9c, "Hyun Won, Inc." }, + { 0x0f9e, "Lucent Technologies" }, + { 0x0fa3, "Starconn Electronic Co., Ltd" }, + { 0x0fa4, "ATL Technology" }, + { 0x0fa5, "Sotec Co., Ltd" }, + { 0x0fa7, "Epox Computer Co., Ltd" }, + { 0x0fa8, "Logic Controls, Inc." }, + { 0x0faf, "Winpoint Electronic Corp." }, + { 0x0fb0, "Haurtian Wire & Cable Co., Ltd" }, + { 0x0fb1, "Inclose Design, Inc." }, + { 0x0fb2, "Juan-Chern Industrial Co., Ltd" }, + { 0x0fb6, "Heber Ltd" }, + { 0x0fb8, "Wistron Corp." }, + { 0x0fb9, "AACom Corp." }, + { 0x0fba, "San Shing Electronics Co., Ltd" }, + { 0x0fbb, "Bitwise Systems, Inc." }, + { 0x0fc1, "Mitac Internatinal Corp." }, + { 0x0fc2, "Plug and Jack Industrial, Inc." }, + { 0x0fc5, "Delcom Engineering" }, + { 0x0fc6, "Dataplus Supplies, Inc." }, + { 0x0fca, "Research In Motion, Ltd." }, + { 0x0fce, "Sony Ericsson Mobile Communications AB" }, + { 0x0fcf, "Dynastream Innovations, Inc." }, + { 0x0fd0, "Tulip Computers B.V." }, + { 0x0fd1, "Giant Electronics Ltd." }, + { 0x0fd2, "Seac Banche" }, + { 0x0fd4, "Tenovis GmbH & Co., KG" }, + { 0x0fd5, "Direct Access Technology, Inc." }, + { 0x0fd9, "Elgato Systems GmbH" }, + { 0x0fda, "Quantec Networks GmbH" }, + { 0x0fdc, "Micro Plus" }, + { 0x0fde, "Oregon Scientific" }, + { 0x0fe0, "Osterhout Design Group" }, + { 0x0fe4, "IN-Tech Electronics, Ltd" }, + { 0x0fe5, "Greenconn (U.S.A.), Inc." }, + { 0x0fe6, "Kontron (Industrial Computer Source / ICS Advent)" }, + { 0x0fe9, "DVICO" }, + { 0x0fea, "United Computer Accessories" }, + { 0x0feb, "CRS Electronic Co., Ltd" }, + { 0x0fec, "UMC Electronics Co., Ltd" }, + { 0x0fed, "Access Co., Ltd" }, + { 0x0fee, "Xsido Corp." }, + { 0x0fef, "MJ Research, Inc." }, + { 0x0ff6, "Core Valley Co., Ltd" }, + { 0x0ff7, "CHI SHING Computer Accessories Co., Ltd" }, + { 0x0ffc, "Clavia DMI AB" }, + { 0x0ffd, "EarlySense" }, + { 0x0fff, "Aopen, Inc." }, + { 0x1000, "Speed Tech Corp." }, + { 0x1001, "Ritronics Components (S) Pte., Ltd" }, + { 0x1003, "Sigma Corp." }, + { 0x1004, "LG Electronics, Inc." }, + { 0x1005, "Apacer Technology, Inc." }, + { 0x1006, "iRiver, Ltd." }, + { 0x1009, "Emuzed, Inc." }, + { 0x100a, "AV Chaseway, Ltd" }, + { 0x100b, "Chou Chin Industrial Co., Ltd" }, + { 0x100d, "Netopia, Inc." }, + { 0x1010, "Fukuda Denshi Co., Ltd" }, + { 0x1011, "Mobile Media Tech." }, + { 0x1012, "SDKM Fibres, Wires & Cables Berhad" }, + { 0x1013, "TST-Touchless Sensor Technology AG" }, + { 0x1014, "Densitron Technologies PLC" }, + { 0x1015, "Softronics Pty., Ltd" }, + { 0x1016, "Xiamen Hung's Enterprise Co., Ltd" }, + { 0x1017, "Speedy Industrial Supplies, Pte., Ltd" }, + { 0x1019, "Elitegroup Computer Systems (ECS)" }, + { 0x1020, "Labtec" }, + { 0x1022, "Shinko Shoji Co., Ltd" }, + { 0x1025, "Hyper-Paltek" }, + { 0x1026, "Newly Corp." }, + { 0x1027, "Time Domain" }, + { 0x1028, "Inovys Corp." }, + { 0x1029, "Atlantic Coast Telesys" }, + { 0x102a, "Ramos Technology Co., Ltd" }, + { 0x102b, "Infotronic America, Inc." }, + { 0x102c, "Etoms Electronics Corp." }, + { 0x102d, "Winic Corp." }, + { 0x1031, "Comax Technology, Inc." }, + { 0x1032, "C-One Technology Corp." }, + { 0x1033, "Nucam Corp." }, + { 0x1038, "SteelSeries ApS" }, + { 0x1039, "devolo AG" }, + { 0x103a, "PSA" }, + { 0x103d, "Stanton" }, + { 0x1043, "iCreate Technologies Corp." }, + { 0x1044, "Chu Yuen Enterprise Co., Ltd" }, + { 0x1046, "Winbond Electronics Corp. [hex]" }, + { 0x1048, "Targus Group International" }, + { 0x104b, "Mylex / Buslogic" }, + { 0x104c, "AMCO TEC International, Inc." }, + { 0x104d, "Newport Corporation" }, + { 0x104f, "WB Electronics" }, + { 0x1050, "Yubico.com" }, + { 0x1053, "Immanuel Electronics Co., Ltd" }, + { 0x1054, "BMS International Beheer N.V." }, + { 0x1055, "Complex Micro Interconnection Co., Ltd" }, + { 0x1056, "Hsin Chen Ent Co., Ltd" }, + { 0x1057, "ON Semiconductor" }, + { 0x1058, "Western Digital Technologies, Inc." }, + { 0x1059, "Giesecke & Devrient GmbH" }, + { 0x105b, "Foxconn International, Inc." }, + { 0x105c, "Hong Ji Electric Wire & Cable (Dongguan) Co., Ltd" }, + { 0x105d, "Delkin Devices, Inc." }, + { 0x105e, "Valence Semiconductor Design, Ltd" }, + { 0x105f, "Chin Shong Enterprise Co., Ltd" }, + { 0x1060, "Easthome Industrial Co., Ltd" }, + { 0x1063, "Motorola Electronics Taiwan, Ltd [hex]" }, + { 0x1065, "CCYU Technology" }, + { 0x106a, "Loyal Legend, Ltd" }, + { 0x106c, "Curitel Communications, Inc." }, + { 0x106d, "San Chieh Manufacturing, Ltd" }, + { 0x106e, "ConectL" }, + { 0x106f, "Money Controls" }, + { 0x1076, "GCT Semiconductor, Inc." }, + { 0x107b, "Gateway, Inc." }, + { 0x107d, "Arlec Australia, Ltd" }, + { 0x107e, "Midoriya Electric Co., Ltd" }, + { 0x107f, "KidzMouse, Inc." }, + { 0x1082, "Shin-Etsukaken Co., Ltd" }, + { 0x1083, "Canon Electronics, Inc." }, + { 0x1084, "Pantech Co., Ltd" }, + { 0x108a, "Chloride Power Protection" }, + { 0x108b, "Grand-tek Technology Co., Ltd" }, + { 0x108c, "Robert Bosch GmbH" }, + { 0x108e, "Lotes Co., Ltd." }, + { 0x1099, "Surface Optics Corp." }, + { 0x109a, "DATASOFT Systems GmbH" }, + { 0x109b, "Hisense" }, + { 0x109f, "eSOL Co., Ltd" }, + { 0x10a0, "Hirotech, Inc." }, + { 0x10a3, "Mitsubishi Materials Corp." }, + { 0x10a9, "SK Teletech Co., Ltd" }, + { 0x10aa, "Cables To Go" }, + { 0x10ab, "USI Co., Ltd" }, + { 0x10ac, "Honeywell, Inc." }, + { 0x10ae, "Princeton Technology Corp." }, + { 0x10af, "Liebert Corp." }, + { 0x10b5, "Comodo (PLX?)" }, + { 0x10b8, "DiBcom" }, + { 0x10bb, "TM Technology, Inc." }, + { 0x10bc, "Dinging Technology Co., Ltd" }, + { 0x10bd, "TMT Technology, Inc." }, + { 0x10bf, "SmartHome" }, + { 0x10c3, "Universal Laser Systems, Inc." }, + { 0x10c4, "Cygnal Integrated Products, Inc." }, + { 0x10c5, "Sanei Electric, Inc." }, + { 0x10c6, "Intec, Inc." }, + { 0x10cb, "Eratech" }, + { 0x10cc, "GBM Connector Co., Ltd" }, + { 0x10cd, "Kycon, Inc." }, + { 0x10ce, "Silicon Labs" }, + { 0x10cf, "Velleman Components, Inc." }, + { 0x10d1, "Hottinger Baldwin Measurement" }, + { 0x10d2, "RayComposer - R. Adams" }, + { 0x10d4, "Man Boon Manufactory, Ltd" }, + { 0x10d5, "Uni Class Technology Co., Ltd" }, + { 0x10d6, "Actions Semiconductor Co., Ltd" }, + { 0x10de, "Authenex, Inc." }, + { 0x10df, "In-Win Development, Inc." }, + { 0x10e0, "Post-Op Video, Inc." }, + { 0x10e1, "CablePlus, Ltd" }, + { 0x10e2, "Nada Electronics, Ltd" }, + { 0x10ec, "Vast Technologies, Inc." }, + { 0x10f0, "Nexio Co., Ltd" }, + { 0x10f1, "Importek" }, + { 0x10f5, "Turtle Beach" }, + { 0x10fb, "Pictos Technologies, Inc." }, + { 0x10fd, "Anubis Electronics, Ltd" }, + { 0x10fe, "Thrane & Thrane" }, + { 0x1100, "VirTouch, Ltd" }, + { 0x1101, "EasyPass Industrial Co., Ltd" }, + { 0x1108, "Brightcom Technologies, Ltd" }, + { 0x110a, "Moxa Technologies Co., Ltd." }, + { 0x1110, "Analog Devices Canada, Ltd (Allied Telesyn)" }, + { 0x1111, "Pandora International Ltd." }, + { 0x1112, "YM ELECTRIC CO., Ltd" }, + { 0x1113, "Medion AG" }, + { 0x111e, "VSO Electric Co., Ltd" }, + { 0x112a, "RedRat" }, + { 0x112e, "Master Hill Electric Wire and Cable Co., Ltd" }, + { 0x112f, "Cellon International, Inc." }, + { 0x1130, "Tenx Technology, Inc." }, + { 0x1131, "Integrated System Solution Corp." }, + { 0x1132, "Toshiba Corp., Digital Media Equipment [hex]" }, + { 0x1136, "CTS Electronincs" }, + { 0x113c, "Arin Tech Co., Ltd" }, + { 0x113d, "Mapower Electronics Co., Ltd" }, + { 0x1141, "V One Multimedia, Pte., Ltd" }, + { 0x1142, "CyberScan Technologies, Inc." }, + { 0x1145, "Japan Radio Company" }, + { 0x1146, "Shimane SANYO Electric Co., Ltd." }, + { 0x1147, "Ever Great Electric Wire and Cable Co., Ltd" }, + { 0x114b, "Sphairon Access Systems GmbH" }, + { 0x114c, "Tinius Olsen Testing Machine Co., Inc." }, + { 0x114d, "Alpha Imaging Technology Corp." }, + { 0x114f, "Wavecom" }, + { 0x115b, "Salix Technology Co., Ltd." }, + { 0x1162, "Secugen Corp." }, + { 0x1163, "DeLorme Publishing, Inc." }, + { 0x1164, "YUAN High-Tech Development Co., Ltd" }, + { 0x1165, "Telson Electronics Co., Ltd" }, + { 0x1166, "Bantam Interactive Technologies" }, + { 0x1167, "Salient Systems Corp." }, + { 0x1168, "BizConn International Corp." }, + { 0x116e, "Gigastorage Corp." }, + { 0x116f, "Silicon 10 Technology Corp." }, + { 0x1175, "Shengyih Steel Mold Co., Ltd" }, + { 0x117d, "Santa Electronic, Inc." }, + { 0x117e, "JNC, Inc." }, + { 0x1182, "Venture Corp., Ltd" }, + { 0x1183, "Compaq Computer Corp. [hex] (Digital Dream ?)" }, + { 0x1184, "Kyocera Elco Corp." }, + { 0x1188, "Bloomberg L.P." }, + { 0x1189, "Acer Communications & Multimedia" }, + { 0x118f, "You Yang Technology Co., Ltd" }, + { 0x1190, "Tripace" }, + { 0x1191, "Loyalty Founder Enterprise Co., Ltd" }, + { 0x1196, "Yankee Robotics, LLC" }, + { 0x1197, "Technoimagia Co., Ltd" }, + { 0x1198, "StarShine Technology Corp." }, + { 0x1199, "Sierra Wireless, Inc." }, + { 0x119a, "ZHAN QI Technology Co., Ltd" }, + { 0x119b, "ruwido austria GmbH" }, + { 0x11a0, "Chipcon AS" }, + { 0x11a3, "Technovas Co., Ltd" }, + { 0x11aa, "GlobalMedia Group, LLC" }, + { 0x11ab, "Exito Electronics Co., Ltd" }, + { 0x11ac, "Nike" }, + { 0x11b0, "ATECH FLASH TECHNOLOGY" }, + { 0x11be, "R&D International NV" }, + { 0x11c5, "Inmax" }, + { 0x11ca, "VeriFone Inc" }, + { 0x11db, "Topfield Co., Ltd." }, + { 0x11e6, "K.I. Technology Co. Ltd." }, + { 0x11f5, "Siemens AG" }, + { 0x11f6, "Prolific" }, + { 0x11f7, "Alcatel (?)" }, + { 0x1203, "TSC Auto ID Technology Co., Ltd" }, + { 0x1209, "InterBiometrics" }, + { 0x120e, "Hudson Soft Co., Ltd" }, + { 0x120f, "Magellan" }, + { 0x1210, "DigiTech" }, + { 0x121e, "Jungsoft Co., Ltd" }, + { 0x1221, "Unknown manufacturer" }, + { 0x1223, "SKYCABLE ENTERPRISE. CO., LTD." }, + { 0x1228, "Datapaq Limited" }, + { 0x1230, "Chipidea-Microelectronica, S.A." }, + { 0x1233, "Denver Electronics" }, + { 0x1234, "Brain Actuated Technologies" }, + { 0x1235, "Focusrite-Novation" }, + { 0x1241, "Belkin" }, + { 0x124a, "AirVast" }, + { 0x124b, "Nyko (Honey Bee)" }, + { 0x124c, "MXI - Memory Experts International, Inc." }, + { 0x125c, "Apogee Inc." }, + { 0x125f, "A-DATA Technology Co., Ltd." }, + { 0x1260, "Standard Microsystems Corp." }, + { 0x1264, "Covidien Energy-based Devices" }, + { 0x1266, "Pirelli Broadband Solutions" }, + { 0x1267, "Logic3 / SpectraVideo plc" }, + { 0x126c, "Aristocrat Technologies" }, + { 0x126d, "Bel Stewart" }, + { 0x126e, "Strobe Data, Inc." }, + { 0x126f, "TwinMOS" }, + { 0x1274, "Ensoniq" }, + { 0x1275, "Xaxero Marine Software Engineering, Ltd." }, + { 0x1278, "Starlight Xpress" }, + { 0x1283, "zebris Medical GmbH" }, + { 0x1286, "Marvell Semiconductor, Inc." }, + { 0x1291, "Qualcomm Flarion Technologies, Inc. / Leadtek Research, Inc." }, + { 0x1292, "Innomedia" }, + { 0x1293, "Belkin Components [hex]" }, + { 0x1294, "RISO KAGAKU CORP." }, + { 0x129b, "CyberTAN Technology" }, + { 0x12a7, "Trendchip Technologies Corp." }, + { 0x12ab, "Honey Bee Electronic International Ltd." }, + { 0x12b8, "Zhejiang Xinya Electronic Technology Co., Ltd." }, + { 0x12b9, "E28" }, + { 0x12ba, "Licensed by Sony Computer Entertainment America" }, + { 0x12bd, "Gembird" }, + { 0x12c4, "Autocue Group Ltd" }, + { 0x12cf, "DEXIN" }, + { 0x12d1, "Huawei Technologies Co., Ltd." }, + { 0x12d2, "LINE TECH INDUSTRIAL CO., LTD." }, + { 0x12d6, "EMS Dr. Thomas Wuensche" }, + { 0x12d7, "BETTER WIRE FACTORY CO., LTD." }, + { 0x12d8, "Araneus Information Systems Oy" }, + { 0x12e6, "Waldorf Music GmbH" }, + { 0x12ef, "Tapwave, Inc." }, + { 0x12f5, "Dynamic System Electronics Corp." }, + { 0x12f7, "Memorex Products, Inc." }, + { 0x12fd, "AIN Comm. Technology Co., Ltd" }, + { 0x12ff, "Fascinating Electronics, Inc." }, + { 0x1307, "Transcend Information, Inc." }, + { 0x1308, "Shuttle, Inc." }, + { 0x1310, "Roper" }, + { 0x1312, "ICS Electronics" }, + { 0x1313, "ThorLabs" }, + { 0x131d, "Natural Point" }, + { 0x132a, "Envara Inc." }, + { 0x132b, "Konica Minolta" }, + { 0x133e, "Kemper Digital GmbH" }, + { 0x1342, "Mobility" }, + { 0x1343, "Citizen Systems" }, + { 0x1345, "Sino Lite Technology Corp." }, + { 0x1347, "Moravian Instruments" }, + { 0x1348, "Katsuragawa Electric Co., Ltd." }, + { 0x134c, "PanJit International Inc." }, + { 0x134e, "Digby's Bitpile, Inc. DBA D Bit" }, + { 0x1357, "P&E Microcomputer Systems" }, + { 0x135f, "Control Development Inc." }, + { 0x1366, "SEGGER" }, + { 0x136b, "STEC" }, + { 0x136e, "Andor Technology Ltd." }, + { 0x1370, "Swissbit" }, + { 0x1371, "CNet Technology Inc." }, + { 0x1376, "Vimtron Electronics Co., Ltd." }, + { 0x137b, "SCAPS GmbH" }, + { 0x1385, "Netgear, Inc" }, + { 0x138a, "Validity Sensors, Inc." }, + { 0x138e, "Jungo LTD" }, + { 0x1390, "TOMTOM B.V." }, + { 0x1391, "IdealTEK, Inc." }, + { 0x1395, "Sennheiser Communications" }, + { 0x1397, "BEHRINGER International GmbH" }, + { 0x1398, "Q-tec" }, + { 0x13ad, "Baltech" }, + { 0x13b0, "PerkinElmer Optoelectronics" }, + { 0x13b1, "Linksys" }, + { 0x13b2, "Alesis" }, + { 0x13b3, "Nippon Dics Co., Ltd." }, + { 0x13ba, "PCPlay" }, + { 0x13be, "Ricoh Printing Systems, Ltd." }, + { 0x13ca, "JyeTai Precision Industrial Co., Ltd." }, + { 0x13cf, "Wisair Ltd." }, + { 0x13d0, "Techsan Electronics Co., Ltd." }, + { 0x13d1, "A-Max Technology Macao Commercial Offshore Co. Ltd." }, + { 0x13d2, "Shark Multimedia" }, + { 0x13d3, "IMC Networks" }, + { 0x13d7, "Guidance Software, Inc." }, + { 0x13dc, "ALEREON, INC." }, + { 0x13dd, "i.Tech Dynamic Limited" }, + { 0x13e1, "Kaibo Wire & Cable (Shenzhen) Co., Ltd." }, + { 0x13e5, "Rane" }, + { 0x13e6, "TechnoScope Co., Ltd." }, + { 0x13ea, "Hengstler" }, + { 0x13ec, "Zydacron" }, + { 0x13ee, "MosArt" }, + { 0x13fd, "Initio Corporation" }, + { 0x13fe, "Kingston Technology Company Inc." }, + { 0x1400, "Axxion Group Corp." }, + { 0x1402, "Bowe Bell & Howell" }, + { 0x1403, "Sitronix" }, + { 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" }, + { 0x1429, "Vega Technologies Industrial (Austria) Co." }, + { 0x142a, "Thales E-Transactions" }, + { 0x142b, "Arbiter Systems, Inc." }, + { 0x1430, "RedOctane" }, + { 0x1431, "Pertech Resources, Inc." }, + { 0x1435, "Wistron NeWeb" }, + { 0x1436, "Denali Software, Inc." }, + { 0x143c, "Altek Corporation" }, + { 0x1443, "Digilent" }, + { 0x1446, "X.J.GROUP" }, + { 0x1453, "Radio Shack" }, + { 0x1456, "Extending Wire & Cable Co., Ltd." }, + { 0x1457, "First International Computer, Inc." }, + { 0x145f, "Trust" }, + { 0x1460, "Tatung Co." }, + { 0x1461, "Staccato Communications" }, + { 0x1462, "Micro Star International" }, + { 0x1472, "Huawei-3Com" }, + { 0x147a, "Formosa Industrial Computing, Inc." }, + { 0x147e, "Upek" }, + { 0x147f, "Hama GmbH & Co., KG" }, + { 0x1482, "Vaillant" }, + { 0x1484, "Elsa AG [hex]" }, + { 0x1485, "Silicom" }, + { 0x1487, "DSP Group, Ltd." }, + { 0x148e, "EVATRONIX SA" }, + { 0x148f, "Ralink Technology, Corp." }, + { 0x1491, "Futronic Technology Co. Ltd." }, + { 0x1493, "Suunto" }, + { 0x1497, "Panstrong Company Ltd." }, + { 0x1498, "Microtek International Inc." }, + { 0x149a, "Imagination Technologies" }, + { 0x14aa, "WideView Technology Inc." }, + { 0x14ad, "CTK Corporation" }, + { 0x14ae, "Printronix Inc." }, + { 0x14af, "ATP Electronics Inc." }, + { 0x14b0, "StarTech.com Ltd." }, + { 0x14b2, "Ralink Technology, Corp." }, + { 0x14c0, "Rockwell Automation, Inc." }, + { 0x14c2, "Gemlight Computer, Ltd" }, + { 0x14c8, "Zytronic" }, + { 0x14cd, "Super Top" }, + { 0x14d8, "JAMER INDUSTRIES CO., LTD." }, + { 0x14dd, "Raritan Computer, Inc." }, + { 0x14e0, "WiNRADiO Communications" }, + { 0x14e1, "Dialogue Technology Corp." }, + { 0x14e5, "SAIN Information & Communications Co., Ltd." }, + { 0x14ea, "Planex Communications" }, + { 0x14ed, "Shure Inc." }, + { 0x14f7, "TechniSat Digital GmbH" }, + { 0x1500, "Ellisys" }, + { 0x1501, "Pine-Tum Enterprise Co., Ltd." }, + { 0x1509, "First International Computer, Inc." }, + { 0x1513, "medMobile" }, + { 0x1514, "Actel" }, + { 0x1516, "CompUSA" }, + { 0x1518, "Cheshire Engineering Corp." }, + { 0x1519, "Comneon" }, + { 0x1520, "Bitwire Corp." }, + { 0x1524, "ENE Technology Inc" }, + { 0x1527, "Silicon Portals" }, + { 0x1529, "UBIQUAM Co., Ltd." }, + { 0x152a, "Thesycon Systemsoftware & Consulting GmbH" }, + { 0x152b, "MIR Srl" }, + { 0x152d, "JMicron Technology Corp. / JMicron USA Technology Corp." }, + { 0x152e, "LG (HLDS)" }, + { 0x1532, "Razer USA, Ltd" }, + { 0x153b, "TerraTec Electronic GmbH" }, + { 0x1546, "U-Blox AG" }, + { 0x1547, "SG Intec Ltd & Co KG" }, + { 0x154a, "Celectronic GmbH" }, + { 0x154b, "PNY" }, + { 0x154d, "ConnectCounty Holdings Berhad" }, + { 0x154e, "D&M Holdings, Inc. (Denon/Marantz)" }, + { 0x154f, "SNBC CO., Ltd" }, + { 0x1554, "Prolink Microsystems Corp." }, + { 0x1557, "OQO" }, + { 0x1568, "Sunf Pu Technology Co., Ltd" }, + { 0x156f, "Quantum Corporation" }, + { 0x1570, "ALLTOP TECHNOLOGY CO., LTD." }, + { 0x157b, "Ketron SRL" }, + { 0x157e, "TRENDnet" }, + { 0x1582, "Fiberline" }, + { 0x1587, "SMA Technologie AG" }, + { 0x158d, "Oakley Inc." }, + { 0x158e, "JDS Uniphase Corporation (JDSU)" }, + { 0x1598, "Kunshan Guoji Electronics Co., Ltd." }, + { 0x15a2, "Freescale Semiconductor, Inc." }, + { 0x15a4, "Afatech Technologies, Inc." }, + { 0x15a8, "Teams Power Limited" }, + { 0x15a9, "Gemtek" }, + { 0x15aa, "Gearway Electronics (Dong Guan) Co., Ltd." }, + { 0x15ad, "VMware Inc." }, + { 0x15ba, "Olimex Ltd." }, + { 0x15c0, "XL Imaging" }, + { 0x15c2, "SoundGraph Inc." }, + { 0x15c5, "Advance Multimedia Internet Technology Inc. (AMIT)" }, + { 0x15c6, "Laboratoires MXM" }, + { 0x15c8, "KTF Technologies" }, + { 0x15c9, "D-Box Technologies" }, + { 0x15ca, "Textech International Ltd." }, + { 0x15d5, "Coulomb Electronics Ltd." }, + { 0x15d9, "Trust International B.V." }, + { 0x15dc, "Hynix Semiconductor Inc." }, + { 0x15e0, "Seong Ji Industrial Co., Ltd." }, + { 0x15e1, "RSA" }, + { 0x15e4, "Numark" }, + { 0x15e8, "SohoWare" }, + { 0x15e9, "Pacific Digital Corp." }, + { 0x15ec, "Belcarra Technologies Corp." }, + { 0x15f4, "HanfTek" }, + { 0x1604, "Tascam" }, + { 0x1606, "Umax" }, + { 0x1608, "Inside Out Networks [hex]" }, + { 0x160a, "VIA Technologies, Inc." }, + { 0x160e, "INRO" }, + { 0x1614, "Amoi Electronics" }, + { 0x1617, "Sony Corp." }, + { 0x1619, "L & K Precision Technology Co., Ltd." }, + { 0x1621, "Wionics Research" }, + { 0x1628, "Stonestreet One, Inc." }, + { 0x162a, "Airgo Networks Inc." }, + { 0x162f, "WiQuest Communications, Inc." }, + { 0x1630, "2Wire, Inc." }, + { 0x1631, "Good Way Technology" }, + { 0x1645, "Entrega [hex]" }, + { 0x1649, "SofTec Microsystems" }, + { 0x164a, "ChipX" }, + { 0x164c, "Matrix Vision GmbH" }, + { 0x1657, "Struck Innovative Systeme GmbH" }, + { 0x165b, "Frontier Design Group" }, + { 0x165c, "Kondo Kagaku" }, + { 0x1660, "Creatix Polymedia GmbH" }, + { 0x1667, "GIGA-TMS INC." }, + { 0x1668, "Actiontec Electronics, Inc. [hex]" }, + { 0x1669, "PiKRON Ltd. [hex]" }, + { 0x166a, "Clipsal" }, + { 0x1677, "China Huada Integrated Circuit Design (Group) Co., Ltd. (CIDC Group)" }, + { 0x1679, "Total Phase" }, + { 0x1680, "Golden Bridge Electech Inc." }, + { 0x1681, "Prevo Technologies, Inc." }, + { 0x1682, "Maxwise Production Enterprise Ltd." }, + { 0x1684, "Godspeed Computer Corp." }, + { 0x1685, "Delock" }, + { 0x1686, "ZOOM Corporation" }, + { 0x1687, "Kingmax Digital Inc." }, + { 0x1688, "Saab AB" }, + { 0x1689, "Razer USA, Ltd" }, + { 0x168c, "Atheros Communications" }, + { 0x1690, "Askey Computer Corp. [hex]" }, + { 0x1696, "Hitachi Video and Information System, Inc." }, + { 0x1697, "VTec Test, Inc." }, + { 0x16a5, "Shenzhen Zhengerya Cable Co., Ltd." }, + { 0x16a6, "Unigraf" }, + { 0x16ab, "Global Sun Technology" }, + { 0x16ac, "Dongguan ChingLung Wire & Cable Co., Ltd." }, + { 0x16b4, "iStation" }, + { 0x16b5, "Persentec, Inc." }, + { 0x16c0, "Van Ooijen Technische Informatica" }, + { 0x16ca, "Wireless Cables, Inc." }, + { 0x16cc, "silex technology, Inc." }, + { 0x16d0, "MCS" }, + { 0x16d1, "Suprema Inc." }, + { 0x16d3, "Frontline Test Equipment, Inc." }, + { 0x16d5, "AnyDATA Corporation" }, + { 0x16d6, "JABLOCOM s.r.o." }, + { 0x16d8, "CMOTECH Co., Ltd." }, + { 0x16dc, "Wiener, Plein & Baus" }, + { 0x16df, "King Billion Electronics Co., Ltd." }, + { 0x16f0, "GN ReSound A/S" }, + { 0x16f5, "Futurelogic Inc." }, + { 0x1706, "BlueView Technologies, Inc." }, + { 0x1707, "ARTIMI" }, + { 0x170b, "Swissonic" }, + { 0x170d, "Avnera" }, + { 0x1711, "Leica Microsystems" }, + { 0x1724, "Meyer Instruments (MIS)" }, + { 0x1725, "Vitesse Semiconductor" }, + { 0x1726, "Axesstel, Inc." }, + { 0x172f, "Waltop International Corp." }, + { 0x1733, "Cellink Technology Co., Ltd" }, + { 0x1736, "CANON IMAGING SYSTEM TECHNOLOGIES INC." }, + { 0x1737, "Linksys" }, + { 0x173d, "QSENN" }, + { 0x1740, "Senao" }, + { 0x1743, "General Atomics" }, + { 0x1748, "MQP Electronics" }, + { 0x174c, "ASMedia Technology Inc." }, + { 0x174f, "Syntek" }, + { 0x1753, "GERTEC Telecomunicacoes Ltda." }, + { 0x1756, "ENENSYS Technologies" }, + { 0x1759, "LucidPort Technology, Inc." }, + { 0x1761, "ASUSTek Computer, Inc. (wrong ID)" }, + { 0x1772, "System Level Solutions, Inc." }, + { 0x1776, "Arowana" }, + { 0x177f, "Sweex" }, + { 0x1781, "Multiple Vendors" }, + { 0x1782, "Spreadtrum Communications Inc." }, + { 0x1784, "TopSeed Technology Corp." }, + { 0x1787, "ATI AIB" }, + { 0x1788, "ShenZhen Litkconn Technology Co., Ltd." }, + { 0x1796, "Printrex, Inc." }, + { 0x1797, "JALCO CO., LTD." }, + { 0x1799, "Thales Norway A/S" }, + { 0x179d, "Ricavision International, Inc." }, + { 0x17a0, "Samson Technologies Corp." }, + { 0x17a4, "Concept2" }, + { 0x17a5, "Advanced Connection Technology Inc." }, + { 0x17a7, "MICOMSOFT CO., LTD." }, + { 0x17a8, "Kamstrup A/S" }, + { 0x17b3, "Grey Innovation" }, + { 0x17b5, "Lunatone" }, + { 0x17ba, "SAURIS GmbH" }, + { 0x17c3, "Singim International Corp." }, + { 0x17cc, "Native Instruments" }, + { 0x17cf, "Hip Hing Cable & Plug Mfy. Ltd." }, + { 0x17d0, "Sanford L.P." }, + { 0x17d3, "Korea Techtron Co., Ltd." }, + { 0x17e9, "DisplayLink" }, + { 0x17eb, "Cornice, Inc." }, + { 0x17ef, "Lenovo" }, + { 0x17f4, "WaveSense" }, + { 0x17f5, "K.K. Rocky" }, + { 0x17f6, "Unicomp, Inc" }, + { 0x1809, "Advantech" }, + { 0x1822, "Twinhan" }, + { 0x1831, "Gwo Jinn Industries Co., Ltd." }, + { 0x1832, "Huizhou Shenghua Industrial Co., Ltd." }, + { 0x183d, "VIVOphone" }, + { 0x1843, "Vaisala" }, + { 0x1849, "ASRock Incorporation" }, + { 0x1852, "GYROCOM C&C Co., LTD" }, + { 0x1854, "Memory Devices Ltd." }, + { 0x185b, "Compro" }, + { 0x1861, "Tech Technology Industrial Company" }, + { 0x1862, "Teridian Semiconductor Corp." }, + { 0x1870, "Nexio Co., Ltd" }, + { 0x1871, "Aveo Technology Corp." }, + { 0x1873, "Navilock" }, + { 0x187c, "Alienware Corporation" }, + { 0x187f, "Siano Mobile Silicon" }, + { 0x1892, "Vast Technologies, Inc." }, + { 0x1894, "Topseed" }, + { 0x1897, "Evertop Wire Cable Co." }, + { 0x189f, "3Shape A/S" }, + { 0x18a4, "CSSN" }, + { 0x18a5, "Verbatim, Ltd" }, + { 0x18b1, "Petalynx" }, + { 0x18b4, "e3C Technologies" }, + { 0x18b6, "Mikkon Technology Limited" }, + { 0x18b7, "Zotek Electronic Co., Ltd." }, + { 0x18c5, "AMIT Technology, Inc." }, + { 0x18cd, "Ecamm" }, + { 0x18d1, "Google Inc." }, + { 0x18d5, "Starline International Group Limited" }, + { 0x18d9, "Kaba" }, + { 0x18dc, "LKC Technologies, Inc." }, + { 0x18dd, "Planon System Solutions Inc." }, + { 0x18e3, "Fitipower Integrated Technology Inc" }, + { 0x18e8, "Qcom" }, + { 0x18ea, "Matrox Graphics, Inc." }, + { 0x18ec, "Arkmicro Technologies Inc." }, + { 0x18fd, "FineArch Inc." }, + { 0x1908, "GEMBIRD" }, + { 0x190d, "Motorola GSG" }, + { 0x1914, "Alco Digital Devices Limited" }, + { 0x1915, "Nordic Semiconductor ASA" }, + { 0x1923, "FitLinxx" }, + { 0x1926, "NextWindow" }, + { 0x192f, "Avago Technologies, Pte." }, + { 0x1930, "Shenzhen Xianhe Technology Co., Ltd." }, + { 0x1931, "Ningbo Broad Telecommunication Co., Ltd." }, + { 0x1934, "Feature Integration Technology Inc. (Fintek)" }, + { 0x1941, "Dream Link" }, + { 0x1943, "Sensoray Co., Inc." }, + { 0x1949, "Lab126, Inc." }, + { 0x194f, "PreSonus Audio Electronics, Inc." }, + { 0x1951, "Hyperstone AG" }, + { 0x1953, "Ironkey Inc." }, + { 0x1954, "Radiient Technologies" }, + { 0x195d, "Itron Technology iONE" }, + { 0x1965, "Uniden Corporation" }, + { 0x1967, "CASIO HITACHI Mobile Communications Co., Ltd." }, + { 0x196b, "Wispro Technology Inc." }, + { 0x1970, "Dane-Elec Corp. USA" }, + { 0x1975, "Dongguan Guneetal Wire & Cable Co., Ltd." }, + { 0x1976, "Chipsbrand Microelectronics (HK) Co., Ltd." }, + { 0x1977, "T-Logic" }, + { 0x197d, "Leuze electronic" }, + { 0x1989, "Nuconn Technology Corp." }, + { 0x198f, "Beceem Communications Inc." }, + { 0x1990, "Acron Precision Industrial Co., Ltd." }, + { 0x1995, "Trillium Technology Pty. Ltd." }, + { 0x1996, "PixeLINK" }, + { 0x199b, "MicroStrain, Inc." }, + { 0x199e, "The Imaging Source Europe GmbH" }, + { 0x199f, "Benica Corporation" }, + { 0x19a8, "Biforst Technology Inc." }, + { 0x19ab, "Bodelin" }, + { 0x19af, "S Life" }, + { 0x19b2, "Batronix" }, + { 0x19b4, "Celestron" }, + { 0x19b5, "B & W Group" }, + { 0x19b6, "Infotech Logistic, LLC" }, + { 0x19b9, "Data Robotics" }, + { 0x19c2, "Futuba" }, + { 0x19ca, "Mindtribe" }, + { 0x19cf, "Parrot SA" }, + { 0x19d2, "ZTE WCDMA Technologies MSM" }, + { 0x19db, "KFI Printers" }, + { 0x19e1, "WeiDuan Electronic Accessory (S.Z.) Co., Ltd." }, + { 0x19e8, "Industrial Technology Research Institute" }, + { 0x19ef, "Pak Heng Technology (Shenzhen) Co., Ltd." }, + { 0x19f7, "RODE Microphones" }, + { 0x19fa, "Gampaq Co.Ltd" }, + { 0x19ff, "Dynex" }, + { 0x1a08, "Bellwood International, Inc." }, + { 0x1a0a, "USB-IF non-workshop" }, + { 0x1a12, "KES Co., Ltd." }, + { 0x1a1d, "Veho" }, + { 0x1a25, "Amphenol East Asia Ltd." }, + { 0x1a2a, "Seagate Branded Solutions" }, + { 0x1a2c, "China Resource Semico Co., Ltd" }, + { 0x1a32, "Quanta Microsystems, Inc." }, + { 0x1a34, "ACRUX" }, + { 0x1a36, "Biwin Technology Ltd." }, + { 0x1a40, "Terminus Technology Inc." }, + { 0x1a41, "Action Electronics Co., Ltd." }, + { 0x1a44, "VASCO Data Security International" }, + { 0x1a4a, "Silicon Image" }, + { 0x1a4b, "SafeBoot International B.V." }, + { 0x1a5a, "Tandberg Data" }, + { 0x1a61, "Abbott Diabetes Care" }, + { 0x1a6a, "Spansion Inc." }, + { 0x1a6d, "SamYoung Electronics Co., Ltd" }, + { 0x1a6e, "Global Unichip Corp." }, + { 0x1a6f, "Sagem Orga GmbH" }, + { 0x1a72, "Physik Instrumente" }, + { 0x1a79, "Bayer Health Care LLC" }, + { 0x1a7b, "Lumberg Connect GmbH & Co. KG" }, + { 0x1a7c, "Evoluent" }, + { 0x1a81, "Holtek Semiconductor, Inc." }, + { 0x1a86, "QinHeng Electronics" }, + { 0x1a89, "Dynalith Systems Co., Ltd." }, + { 0x1a8b, "SGS Taiwan Ltd." }, + { 0x1a8d, "BandRich, Inc." }, + { 0x1a98, "Leica Camera AG" }, + { 0x1aa4, "Data Drive Thru, Inc." }, + { 0x1aa5, "UBeacon Technologies, Inc." }, + { 0x1aa6, "eFortune Technology Corp." }, + { 0x1aad, "KeeTouch" }, + { 0x1ab1, "Rigol Technologies" }, + { 0x1acb, "Salcomp Plc" }, + { 0x1acc, "Midiplus Co, Ltd." }, + { 0x1ad1, "Desay Wire Co., Ltd." }, + { 0x1ad4, "APS" }, + { 0x1adb, "SEL C662 Serial Cable" }, + { 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." }, + { 0x1afe, "A. Eberle GmbH & Co. KG" }, + { 0x1b04, "Meilhaus Electronic GmbH" }, + { 0x1b0e, "BLUTRONICS S.r.l." }, + { 0x1b1c, "Corsair" }, + { 0x1b20, "MStar Semiconductor, Inc." }, + { 0x1b22, "WiLinx Corp." }, + { 0x1b26, "Cellex Power Products, Inc." }, + { 0x1b27, "Current Electronics Inc." }, + { 0x1b28, "NAVIsis Inc." }, + { 0x1b32, "Ugobe Life Forms, Inc." }, + { 0x1b36, "ViXS Systems, Inc." }, + { 0x1b3b, "iPassion Technology Inc." }, + { 0x1b3f, "Generalplus Technology Inc." }, + { 0x1b47, "Energizer Holdings, Inc." }, + { 0x1b48, "Plastron Precision Co., Ltd." }, + { 0x1b52, "ARH Inc." }, + { 0x1b59, "K.S. Terminals Inc." }, + { 0x1b5a, "Chao Zhou Kai Yuan Electric Co., Ltd." }, + { 0x1b65, "The Hong Kong Standards and Testing Centre Ltd." }, + { 0x1b71, "Fushicai" }, + { 0x1b72, "ATERGI TECHNOLOGY CO., LTD." }, + { 0x1b73, "Fresco Logic" }, + { 0x1b75, "Ovislink Corp." }, + { 0x1b76, "Legend Silicon Corp." }, + { 0x1b80, "Afatech" }, + { 0x1b86, "Dongguan Guanshang Electronics Co., Ltd." }, + { 0x1b88, "ShenMing Electron (Dong Guan) Co., Ltd." }, + { 0x1b8c, "Altium Limited" }, + { 0x1b8d, "e-MOVE Technology Co., Ltd." }, + { 0x1b8e, "Amlogic, Inc." }, + { 0x1b8f, "MA LABS, Inc." }, + { 0x1b96, "N-Trig" }, + { 0x1b98, "YMax Communications Corp." }, + { 0x1b99, "Shenzhen Yuanchuan Electronic" }, + { 0x1ba1, "JINQ CHERN ENTERPRISE CO., LTD." }, + { 0x1ba2, "Lite Metals & Plastic (Shenzhen) Co., Ltd." }, + { 0x1ba4, "Ember Corporation" }, + { 0x1ba6, "Abilis Systems" }, + { 0x1ba8, "China Telecommunication Technology Labs" }, + { 0x1bad, "Harmonix Music" }, + { 0x1bae, "Vuzix Corporation" }, + { 0x1bbb, "T & A Mobile Phones" }, + { 0x1bc4, "Ford Motor Co." }, + { 0x1bc5, "AVIXE Technology (China) Ltd." }, + { 0x1bc7, "Telit Wireless Solutions" }, + { 0x1bce, "Contac Cable Industrial Limited" }, + { 0x1bcf, "Sunplus Innovation Technology Inc." }, + { 0x1bd0, "Hangzhou Riyue Electronic Co., Ltd." }, + { 0x1bd5, "BG Systems, Inc." }, + { 0x1bde, "P-TWO INDUSTRIES, INC." }, + { 0x1bef, "Shenzhen Tongyuan Network-Communication Cables Co., Ltd" }, + { 0x1bf0, "RealVision Inc." }, + { 0x1bf5, "Extranet Systems Inc." }, + { 0x1bf6, "Orient Semiconductor Electronics, Ltd." }, + { 0x1bfd, "TouchPack" }, + { 0x1c02, "Kreton Corporation" }, + { 0x1c04, "QNAP System Inc." }, + { 0x1c0c, "Ionics EMS, Inc." }, + { 0x1c0d, "Relm Wireless" }, + { 0x1c10, "Lanterra Industrial Co., Ltd." }, + { 0x1c13, "ALECTRONIC LIMITED" }, + { 0x1c1a, "Datel Electronics Ltd." }, + { 0x1c1b, "Volkswagen of America, Inc." }, + { 0x1c1f, "Goldvish S.A." }, + { 0x1c20, "Fuji Electric Device Technology Co., Ltd." }, + { 0x1c21, "ADDMM LLC" }, + { 0x1c22, "ZHONGSHAN CHIANG YU ELECTRIC CO., LTD." }, + { 0x1c26, "Shanghai Haiying Electronics Co., Ltd." }, + { 0x1c27, "HuiYang D & S Cable Co., Ltd." }, + { 0x1c29, "Elster GmbH" }, + { 0x1c31, "LS Cable Ltd." }, + { 0x1c34, "SpringCard" }, + { 0x1c37, "Authorizer Technologies, Inc." }, + { 0x1c3d, "NONIN MEDICAL INC." }, + { 0x1c3e, "Wep Peripherals" }, + { 0x1c40, "EZPrototypes" }, + { 0x1c49, "Cherng Weei Technology Corp." }, + { 0x1c4f, "SiGma Micro" }, + { 0x1c6b, "Philips & Lite-ON Digital Solutions Corporation" }, + { 0x1c6c, "Skydigital Inc." }, + { 0x1c73, "AMT" }, + { 0x1c77, "Kaetat Industrial Co., Ltd." }, + { 0x1c78, "Datascope Corp." }, + { 0x1c79, "Unigen Corporation" }, + { 0x1c7a, "LighTuning Technology Inc." }, + { 0x1c7b, "LUXSHARE PRECISION INDUSTRY (SHENZHEN) CO., LTD." }, + { 0x1c83, "Schomaecker GmbH" }, + { 0x1c87, "2N TELEKOMUNIKACE a.s." }, + { 0x1c88, "Somagic, Inc." }, + { 0x1c89, "HONGKONG WEIDIDA ELECTRON LIMITED" }, + { 0x1c8e, "ASTRON INTERNATIONAL CORP." }, + { 0x1c98, "ALPINE ELECTRONICS, INC." }, + { 0x1c9e, "OMEGA TECHNOLOGY" }, + { 0x1ca0, "ACCARIO Inc." }, + { 0x1ca1, "Symwave" }, + { 0x1cac, "Kinstone" }, + { 0x1cb3, "Aces Electronic Co., Ltd." }, + { 0x1cb4, "OPEX CORPORATION" }, + { 0x1cb6, "IdeaCom Technology Inc." }, + { 0x1cbe, "Luminary Micro Inc." }, + { 0x1cbf, "FORTAT SKYMARK INDUSTRIAL COMPANY" }, + { 0x1cc0, "PlantSense" }, + { 0x1cca, "NextWave Broadband Inc." }, + { 0x1ccd, "Bodatong Technology (Shenzhen) Co., Ltd." }, + { 0x1cd4, "adp corporation" }, + { 0x1cd5, "Firecomms Ltd." }, + { 0x1cd6, "Antonio Precise Products Manufactory Ltd." }, + { 0x1cde, "Telecommunications Technology Association (TTA)" }, + { 0x1cdf, "WonTen Technology Co., Ltd." }, + { 0x1ce0, "EDIMAX TECHNOLOGY CO., LTD." }, + { 0x1ce1, "Amphenol KAE" }, + { 0x1cf1, "Dresden Elektronik" }, + { 0x1cfc, "ANDES TECHNOLOGY CORPORATION" }, + { 0x1cfd, "Flextronics Digital Design Japan, LTD." }, + { 0x1d03, "iCON" }, + { 0x1d07, "Solid-Motion" }, + { 0x1d08, "NINGBO HENTEK DRAGON ELECTRONICS CO., LTD." }, + { 0x1d09, "TechFaith Wireless Technology Limited" }, + { 0x1d0a, "Johnson Controls, Inc. The Automotive Business Unit" }, + { 0x1d0b, "HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD." }, + { 0x1d0f, "Sonix Technology Co., Ltd." }, + { 0x1d14, "ALPHA-SAT TECHNOLOGY LIMITED" }, + { 0x1d17, "C-Thru Music Ltd." }, + { 0x1d19, "Dexatek Technology Ltd." }, + { 0x1d1f, "Diostech Co., Ltd." }, + { 0x1d20, "SAMTACK INC." }, + { 0x1d27, "ASUS" }, + { 0x1d34, "Dream Cheeky" }, + { 0x1d45, "Touch" }, + { 0x1d4d, "PEGATRON CORPORATION" }, + { 0x1d50, "OpenMoko, Inc." }, + { 0x1d57, "Xenta" }, + { 0x1d5b, "Smartronix, Inc." }, + { 0x1d6b, "Linux Foundation" }, + { 0x1d90, "Citizen" }, + { 0x1de1, "Actions Microelectronics Co." }, + { 0x1e0e, "Qualcomm / Option" }, + { 0x1e10, "Point Grey Research, Inc." }, + { 0x1e17, "Mirion Technologies Dosimetry Services Division" }, + { 0x1e1d, "Lumension Security" }, + { 0x1e1f, "INVIA" }, + { 0x1e29, "Festo AG & Co. KG" }, + { 0x1e3d, "Chipsbank Microelectronics Co., Ltd" }, + { 0x1e41, "Cleverscope" }, + { 0x1e4e, "Cubeternet" }, + { 0x1e54, "TypeMatrix" }, + { 0x1e68, "TrekStor GmbH & Co. KG" }, + { 0x1e71, "NZXT" }, + { 0x1e74, "Coby Electronics Corporation" }, + { 0x1e7d, "ROCCAT" }, + { 0x1ebb, "NuCORE Technology, Inc." }, + { 0x1eda, "AirTies Wireless Networks" }, + { 0x1edb, "Blackmagic design" }, + { 0x1ee8, "ONDA COMMUNICATION S.p.a." }, + { 0x1ef6, "EADS Deutschland GmbH" }, + { 0x1f28, "Cal-Comp" }, + { 0x1f3a, "Onda (unverified)" }, + { 0x1f44, "The Neat Company" }, + { 0x1f48, "H-TRONIC GmbH" }, + { 0x1f4d, "G-Tek Electronics Group" }, + { 0x1f6f, "Aliph" }, + { 0x1f75, "Innostor Technology Corporation" }, + { 0x1f82, "TANDBERG" }, + { 0x1f84, "Alere, Inc." }, + { 0x1f87, "Stantum" }, + { 0x1f9b, "Ubiquiti Networks, Inc." }, + { 0x1fab, "Samsung Opto-Electroncs Co., Ltd." }, + { 0x1fbd, "Delphin Technology AG" }, + { 0x1fc9, "NXP Semiconductors" }, + { 0x1fde, "ILX Lightwave Corporation" }, + { 0x1fe7, "Vertex Wireless Co., Ltd." }, + { 0x1ff7, "CVT Electronics.Co.,Ltd" }, + { 0x1fff, "Ideofy Inc." }, + { 0x2001, "D-Link Corp." }, + { 0x2002, "DAP Technologies" }, + { 0x2003, "detectomat" }, + { 0x200c, "Reloop" }, + { 0x2013, "PCTV Systems" }, + { 0x2019, "PLANEX" }, + { 0x203d, "Encore Electronics Inc." }, + { 0x2040, "Hauppauge" }, + { 0x2047, "Texas Instruments" }, + { 0x2058, "Nano River Technology" }, + { 0x2077, "Taicang T&W Electronics Co. Ltd" }, + { 0x2080, "Barnes & Noble" }, + { 0x2086, "SIMPASS" }, + { 0x2087, "Cando" }, + { 0x20a0, "Clay Logic" }, + { 0x20b1, "XMOS Ltd" }, + { 0x20b3, "Hanvon" }, + { 0x20b7, "Qi Hardware" }, + { 0x20ce, "Minicircuits" }, + { 0x20df, "Simtec Electronics" }, + { 0x20f1, "NET New Electronic Technology GmbH" }, + { 0x20f4, "TRENDnet" }, + { 0x20f7, "XIMEA" }, + { 0x2100, "RT Systems" }, + { 0x2101, "ActionStar" }, + { 0x2109, "VIA Labs, Inc." }, + { 0x2113, "Softkinetic" }, + { 0x2149, "Advanced Silicon S.A." }, + { 0x2162, "Creative (?)" }, + { 0x2184, "GW Instek" }, + { 0x21a1, "Emotiv Systems Pty. Ltd." }, + { 0x21d6, "Agecodagis SARL" }, + { 0x2222, "MacAlly" }, + { 0x2227, "SAMWOO Enterprise" }, + { 0x2232, "Silicon Motion" }, + { 0x2233, "RadioShack Corporation" }, + { 0x2237, "Kobo Inc." }, + { 0x225d, "Morpho" }, + { 0x228d, "8D Technologies inc." }, + { 0x22a6, "Pie Digital, Inc." }, + { 0x22b8, "Motorola PCS" }, + { 0x22b9, "eTurboTouch Technology, Inc." }, + { 0x22ba, "Technology Innovation Holdings, Ltd" }, + { 0x2304, "Pinnacle Systems, Inc." }, + { 0x2318, "Shining Technologies, Inc. [hex]" }, + { 0x2341, "Arduino SA" }, + { 0x2373, "Pumatronix Ltda" }, + { 0x2375, "Digit@lway, Inc." }, + { 0x2406, "SANHO Digital Electronics Co., Ltd." }, + { 0x2443, "Aessent Technology Ltd" }, + { 0x2478, "Tripp-Lite" }, + { 0x248a, "Maxxter" }, + { 0x249c, "M2Tech s.r.l." }, + { 0x24e1, "Paratronic" }, + { 0x2632, "TwinMOS" }, + { 0x2639, "Xsens" }, + { 0x2650, "Electronics For Imaging, Inc. [hex]" }, + { 0x2659, "Sundtek" }, + { 0x2676, "Basler AG" }, + { 0x2730, "Citizen" }, + { 0x2735, "DigitalWay" }, + { 0x2770, "NHJ, Ltd" }, + { 0x27b8, "ThingM" }, + { 0x2821, "ASUSTek Computer Inc." }, + { 0x2899, "Toptronic Industrial Co., Ltd" }, + { 0x289b, "Dracal/Raphnet technologies" }, + { 0x2931, "Jolla Oy" }, + { 0x2a03, "dog hunter AG" }, + { 0x2a37, "RTD Embedded Technologies, Inc." }, + { 0x2a45, "Meizu Corp." }, + { 0x2c02, "Planex Communications" }, + { 0x2c1a, "Dolphin Peripherals" }, + { 0x2fb2, "Fujitsu, Ltd" }, + { 0x3125, "Eagletron" }, + { 0x3136, "Navini Networks" }, + { 0x3176, "Whanam Electronics Co., Ltd" }, + { 0x3195, "Link Instruments" }, + { 0x3275, "VidzMedia Pte Ltd" }, + { 0x3333, "InLine" }, + { 0x3334, "AEI" }, + { 0x3340, "Yakumo" }, + { 0x3344, "Leaguer Microelectronics (LME)" }, + { 0x3504, "Micro Star" }, + { 0x3538, "Power Quotient International Co., Ltd" }, + { 0x3579, "DIVA" }, + { 0x357d, "Sharkoon" }, + { 0x3636, "InVibro" }, + { 0x3838, "WEM" }, + { 0x3923, "National Instruments Corp." }, + { 0x40bb, "I-O Data" }, + { 0x4101, "i-rocks" }, + { 0x4102, "iRiver, Ltd." }, + { 0x413c, "Dell Computer Corp." }, + { 0x4146, "USBest Technology" }, + { 0x4168, "Targus" }, + { 0x4242, "USB Design by Example" }, + { 0x4255, "GoPro" }, + { 0x4317, "Broadcom Corp." }, + { 0x4348, "WinChipHead" }, + { 0x4572, "Shuttle, Inc." }, + { 0x4586, "Panram" }, + { 0x4670, "EMS Production" }, + { 0x4752, "Miditech" }, + { 0x4757, "GW Instek" }, + { 0x4766, "Aceeca" }, + { 0x4855, "Memorex" }, + { 0x4971, "SimpleTech" }, + { 0x4d46, "Musical Fidelity" }, + { 0x5032, "Grandtec" }, + { 0x5041, "Linksys (?)" }, + { 0x50c2, "Averatec (?)" }, + { 0x5173, "Sweex" }, + { 0x5219, "I-Tetra" }, + { 0x5345, "Owon" }, + { 0x534c, "SatoshiLabs" }, + { 0x5354, "Meyer Instruments (MIS)" }, + { 0x544d, "Transmeta Corp." }, + { 0x5543, "UC-Logic Technology Corp." }, + { 0x5555, "Epiphan Systems Inc." }, + { 0x55aa, "OnSpec Electronic, Inc." }, + { 0x5654, "Gotview" }, + { 0x5656, "Uni-Trend Group Limited" }, + { 0x595a, "IRTOUCHSYSTEMS Co. Ltd." }, + { 0x5986, "Acer, Inc" }, + { 0x59e3, "Nonolith Labs" }, + { 0x5a57, "Zinwell" }, + { 0x6000, "Beholder International Ltd." }, + { 0x601a, "Ingenic Semiconductor Ltd." }, + { 0x6189, "Sitecom" }, + { 0x6244, "LightingSoft AG" }, + { 0x6253, "TwinHan Technology Co., Ltd" }, + { 0x636c, "CoreLogic, Inc." }, + { 0x6472, "Unknown (Sony?)" }, + { 0x6547, "Arkmicro Technologies Inc." }, + { 0x6615, "IRTOUCHSYSTEMS Co. Ltd." }, + { 0x6666, "Prototype product Vendor ID" }, + { 0x6677, "WiseGroup, Ltd." }, + { 0x6891, "3Com" }, + { 0x695c, "Opera1" }, + { 0x6993, "Yealink Network Technology Co., Ltd." }, + { 0x6a75, "Shanghai Jujo Electronics Co., Ltd" }, + { 0x7104, "CME (Central Music Co.)" }, + { 0x726c, "StackFoundry LLC" }, + { 0x734c, "TBS Technologies China" }, + { 0x7373, "Beijing STONE Technology Co. Ltd." }, + { 0x7392, "Edimax Technology Co., Ltd" }, + { 0x8086, "Intel Corp." }, + { 0x8087, "Intel Corp." }, + { 0x80ee, "VirtualBox" }, + { 0x8282, "Keio" }, + { 0x8341, "EGO Systems, Inc." }, + { 0x8564, "Transcend Information, Inc." }, + { 0x8644, "Intenso GmbG" }, + { 0x8e06, "CH Products, Inc." }, + { 0x9016, "Sitecom" }, + { 0x9022, "TeVii Technology Ltd." }, + { 0x9148, "GeoLab, Ltd" }, + { 0x9710, "MosChip Semiconductor" }, + { 0x9849, "Bestmedia CD Recordable GmbH & Co. KG" }, + { 0x9999, "Odeon" }, + { 0x99fa, "Grandtec" }, + { 0x9ac4, "J. Westhues" }, + { 0x9e88, "Marvell Semiconductor, Inc." }, + { 0xa128, "AnMo Electronics Corp. / Dino-Lite (?)" }, + { 0xa168, "AnMo Electronics Corporation" }, + { 0xa600, "Asix" }, + { 0xa727, "3Com" }, + { 0xaaaa, "MXT" }, + { 0xabcd, "Unknown" }, + { 0xb58e, "Blue Microphones" }, + { 0xc216, "Card Device Expert Co., LTD" }, + { 0xc251, "Keil Software, Inc." }, + { 0xcace, "CACE Technologies Inc." }, + { 0xcd12, "SMART TECHNOLOGY INDUSTRIAL LTD." }, + { 0xd208, "Ultimarc" }, + { 0xd209, "Ultimarc" }, + { 0xd904, "LogiLink" }, + { 0xe4e4, "Xorcom Ltd." }, + { 0xeb03, "MakingThings" }, + { 0xeb1a, "eMPIA Technology, Inc." }, + { 0xeb2a, "KWorld" }, + { 0xef18, "SMART TECHNOLOGY INDUSTRIAL LTD." }, + { 0xf003, "Hewlett Packard" }, + { 0xf182, "Leap Motion" }, + { 0xf4ec, "Atten Electronics / Siglent Technologies" }, + { 0xf4ed, "Shenzhen Siglent Co., Ltd." }, + { 0xf766, "Hama" }, + { 0xfc08, "Conrad Electronic SE" }, + { 0xffee, "FNK Tech" }, +}; + +const char* LIBWDI_API wdi_get_vendor_name(unsigned short vid) +{ + int i; + + for(i=0; i/dev/null || { echo "wget command not found. Aborting." >&2; exit 1; } +type -P sed &>/dev/null || { echo "sed command not found. Aborting." >&2; exit 1; } + +# Download the latest version (overwrite previous if newer) +wget -m -nd http://www.linux-usb.org/usb.ids + +# Create the sed command file +cat > cmd.sed <<\_EOF +# Header, part 1 +s¦^#.*List of USB.*¦/*\ + * USB vendors, by VID\ + * This file is autogenerated from http://www.linux-usb.org/usb.ids\ + * See http://www.linux-usb.org/usb-ids.html to submit new VIDs or PIDs\ + *\ + *\ + * 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\ + */\ +\ +#include \ +#include "libwdi.h"\ +\ +struct vendor_name \{\ + unsigned short vid;\ + const char* name;\ +\};\ +\ +/*\ + * http://www.linux-usb.org/usb.ids¦p + +# Header part 2, version +s|# Version:| * Version:| +/ \* Version:/p + +# Header Part 3 +s|^#.*Date:.*| \*/\ +static struct vendor_name usb_vendor[] = \{|p + +# Footer +$a\ +\};\ +\ +const char* LIBWDI_API wdi_get_vendor_name(unsigned short vid)\ +\{\ + int i;\ +\ + for(i=0; i vid_data.c +rm cmd.sed +echo Done. \ No newline at end of file diff --git a/driver/source/libwdi/winusb.cat.in b/driver/source/libwdi/winusb.cat.in new file mode 100644 index 00000000..9604596a --- /dev/null +++ b/driver/source/libwdi/winusb.cat.in @@ -0,0 +1,5 @@ +# List of the binaries referenced by the WinUSB inf +# These are used to generate and self-sign a .cat file + +WdfCoInstaller#WDF_VERSION#.dll +winusbcoinstaller2.dll \ No newline at end of file diff --git a/driver/source/libwdi/winusb.inf.in b/driver/source/libwdi/winusb.inf.in new file mode 100644 index 00000000..f90c5129 --- /dev/null +++ b/driver/source/libwdi/winusb.inf.in @@ -0,0 +1,94 @@ +; #INF_FILENAME# +; Copyright (c) 2010-2016 Pete Batard (GNU LGPL) +[Strings] +DeviceName = "#DEVICE_DESCRIPTION#" +VendorName = "#DEVICE_MANUFACTURER#" +SourceName = "#DEVICE_DESCRIPTION# Install Disk" +DeviceID = "#DEVICE_HARDWARE_ID#" +DeviceGUID = "#DEVICE_INTERFACE_GUID#" + +[Version] +Signature = "$Windows NT$" +Class = "USBDevice" +ClassGuid = {88bae032-5a81-49f0-bc3d-a4ff138216d6} +Provider = "libwdi" +CatalogFile = #CAT_FILENAME# +DriverVer = #DRIVER_DATE#, #DRIVER_VERSION# + +[ClassInstall32] +Addreg = WinUSBDeviceClassReg + +[WinUSBDeviceClassReg] +HKR,,,0,"Universal Serial Bus devices" +HKR,,Icon,,-20 + +[Manufacturer] +%VendorName% = libusbDevice_WinUSB,NTx86,NTamd64,NTarm + +[libusbDevice_WinUSB.NTx86] +%DeviceName% = USB_Install, USB\%DeviceID% + +[libusbDevice_WinUSB.NTamd64] +%DeviceName% = USB_Install, USB\%DeviceID% + +[libusbDevice_WinUSB.NTarm] +%DeviceName% = USB_Install, USB\%DeviceID% + +[USB_Install] +Include = winusb.inf +Needs = WINUSB.NT + +[USB_Install.Services] +Include = winusb.inf +AddService = WinUSB,0x00000002,WinUSB_ServiceInstall + +[WinUSB_ServiceInstall] +DisplayName = "WinUSB - Kernel Driver #DRIVER_DATE# #DRIVER_VERSION#" +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\WinUSB.sys + +[USB_Install.Wdf] +KmdfService = WINUSB, WinUsb_Install + +[WinUSB_Install] +KmdfLibraryVersion = #KMDF_VERSION# + +[USB_Install.HW] +AddReg = #USE_DEVICE_INTERFACE_GUID# + +[NoDeviceInterfaceGUID] +; Avoids adding a DeviceInterfaceGUID for generic driver + +[AddDeviceInterfaceGUID] +HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID% + +[USB_Install.CoInstallers] +AddReg = CoInstallers_AddReg +CopyFiles = CoInstallers_CopyFiles + +[CoInstallers_AddReg] +HKR,,CoInstallers32,0x00010000,"WdfCoInstaller#WDF_VERSION#.dll,WdfCoInstaller","WinUSBCoInstaller2.dll" + +[CoInstallers_CopyFiles] +WinUSBCoInstaller2.dll +WdfCoInstaller#WDF_VERSION#.dll + +[DestinationDirs] +CoInstallers_CopyFiles = 11 + +[SourceDisksNames] +1 = %SourceName% + +[SourceDisksFiles.x86] +WinUSBCoInstaller2.dll = 1,x86 +WdfCoInstaller#WDF_VERSION#.dll = 1,x86 + +[SourceDisksFiles.amd64] +WinUSBCoInstaller2.dll = 1,amd64 +WdfCoInstaller#WDF_VERSION#.dll = 1,amd64 + +[SourceDisksFiles.arm] +WinUSBCoInstaller2.dll = 1,arm +WdfCoInstaller#WDF_VERSION#.dll = 1,arm diff --git a/driver/source/msvc/config.h b/driver/source/msvc/config.h new file mode 100644 index 00000000..148b3d92 --- /dev/null +++ b/driver/source/msvc/config.h @@ -0,0 +1,67 @@ +/* config.h. Manual config for MSVC. */ + +#ifndef _MSC_VER +#warn "msvc/config.h shouldn't be included for your development environment." +#error "Please make sure the msvc/ directory is removed from your build path." +#endif + +#if defined(_PREFAST_) +/* Disable "Banned API Usage:" errors when using WDK's OACR/Prefast */ +#pragma warning(disable:28719) +#endif +#if defined(_MSC_VER) +// Disable some VS2012 Code Analysis warnings +#pragma warning(disable:6258) // We'll use TerminateThread() regardless +#pragma warning(disable:6387) +#endif + +/* + * Embed WinUSB driver files from the following DDK location + * NB: You must also make sure the WDF_VER, COINSTALLER_DIR and X64_DIR + * match your WinUSB redist directrories + */ +#ifndef DDK_DIR +#define DDK_DIR "C:/Program Files (x86)/Windows Kits/10" +#endif + +/* DDK WDF coinstaller version */ +#define WDF_VER 1011 + +/* CoInstaller subdirectory for WinUSB redist files ("winusb" or "wdf") */ +#define COINSTALLER_DIR "wdf" + +/* 64bit subdirectory for WinUSB redist files ("x64" or "amd64") */ +#define X64_DIR "x64" + +/* embed libusb0 driver files from the following location */ +//#ifndef LIBUSB0_DIR +//#define LIBUSB0_DIR "D:/libusb-win32" +//#endif + +/* embed libusbK driver files from the following location */ +//#ifndef LIBUSBK_DIR +//#define LIBUSBK_DIR "D:/libusbK/bin" +//#endif + +/* embed user defined driver files from the following location */ +#ifndef USER_DIR +// #define USER_DIR "C:/signed-driver" +#endif + +/* 32 bit support */ +#define OPT_M32 + +/* 64 bit support */ +#define OPT_M64 + +/* embed IA64 driver files */ +//#define OPT_IA64 + +/* Debug message logging */ +//#define ENABLE_DEBUG_LOGGING + +/* Debug message logging (toggable) */ +#define INCLUDE_DEBUG_LOGGING + +/* Message logging */ +#define ENABLE_LOGGING 1 diff --git a/driver/source/msvc/inttypes.h b/driver/source/msvc/inttypes.h new file mode 100644 index 00000000..0282d2b4 --- /dev/null +++ b/driver/source/msvc/inttypes.h @@ -0,0 +1,299 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file was original part of the w64 mingw-runtime package. + */ + +/* + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * Modified for libusb/MSVC: Pete Batard + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2010-04-02 + */ + +#ifndef _MSC_VER +#error This header should only be used with Microsoft compilers +#endif + +/* 7.8 Format conversion of integer types */ + +#ifndef _INTTYPES_H_ +#define _INTTYPES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + intmax_t quot; + intmax_t rem; + } imaxdiv_t; + + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) + +/* 7.8.1 Macros for format specifiers + * + * MS runtime does not yet understand C9x standard "ll" + * length specifier. It appears to treat "ll" as "l". + * The non-standard I64 length specifier causes warning in GCC, + * but understood by MS runtime functions. + */ + +/* fprintf macros for signed types */ +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 "I64d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 "I64d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 "d" +#define PRIdFAST32 "d" +#define PRIdFAST64 "I64d" + +#define PRIdMAX "I64d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "I64i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 "I64i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 "i" +#define PRIiFAST32 "i" +#define PRIiFAST64 "I64i" + +#define PRIiMAX "I64i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 "I64o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 "I64o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 "o" +#define PRIoFAST32 "o" +#define PRIoFAST64 "I64o" + +#define PRIoMAX "I64o" + +/* fprintf macros for unsigned types */ +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "I64u" + + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 "I64u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 "u" +#define PRIuFAST32 "u" +#define PRIuFAST64 "I64u" + +#define PRIuMAX "I64u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 "I64x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 "I64x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 "x" +#define PRIxFAST32 "x" +#define PRIxFAST64 "I64x" + +#define PRIxMAX "I64x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 "I64X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 "I64X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 "X" +#define PRIXFAST32 "X" +#define PRIXFAST64 "I64X" + +#define PRIXMAX "I64X" + +/* + * fscanf macros for signed int types + * NOTE: if 32-bit int is used for int_fast8_t and int_fast16_t + * (see stdint.h, 7.18.1.3), FAST8 and FAST16 should have + * no length identifiers + */ + +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 "I64d" + +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 "I64d" + +#define SCNdFAST16 "hd" +#define SCNdFAST32 "d" +#define SCNdFAST64 "I64d" + +#define SCNdMAX "I64d" + +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 "I64i" + +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 "I64i" + +#define SCNiFAST16 "hi" +#define SCNiFAST32 "i" +#define SCNiFAST64 "I64i" + +#define SCNiMAX "I64i" + +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 "I64o" + +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 "I64o" + +#define SCNoFAST16 "ho" +#define SCNoFAST32 "o" +#define SCNoFAST64 "I64o" + +#define SCNoMAX "I64o" + +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 "I64x" + +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 "I64x" + +#define SCNxFAST16 "hx" +#define SCNxFAST32 "x" +#define SCNxFAST64 "I64x" + +#define SCNxMAX "I64x" + +/* fscanf macros for unsigned int types */ + +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 "I64u" + +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 "I64u" + +#define SCNuFAST16 "hu" +#define SCNuFAST32 "u" +#define SCNuFAST64 "I64u" + +#define SCNuMAX "I64u" + +#ifdef _WIN64 +#define PRIdPTR "I64d" +#define PRIiPTR "I64i" +#define PRIoPTR "I64o" +#define PRIuPTR "I64u" +#define PRIxPTR "I64x" +#define PRIXPTR "I64X" +#define SCNdPTR "I64d" +#define SCNiPTR "I64i" +#define SCNoPTR "I64o" +#define SCNxPTR "I64x" +#define SCNuPTR "I64u" +#else +#define PRIdPTR "d" +#define PRIiPTR "i" +#define PRIoPTR "o" +#define PRIuPTR "u" +#define PRIxPTR "x" +#define PRIXPTR "X" +#define SCNdPTR "d" +#define SCNiPTR "i" +#define SCNoPTR "o" +#define SCNxPTR "x" + #define SCNuPTR "u" +#endif + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +/* + * no length modifier for char types prior to C9x + * MS runtime scanf appears to treat "hh" as "h" + */ + +/* signed char */ +#define SCNd8 "hhd" +#define SCNdLEAST8 "hhd" +#define SCNdFAST8 "hhd" + +#define SCNi8 "hhi" +#define SCNiLEAST8 "hhi" +#define SCNiFAST8 "hhi" + +#define SCNo8 "hho" +#define SCNoLEAST8 "hho" +#define SCNoFAST8 "hho" + +#define SCNx8 "hhx" +#define SCNxLEAST8 "hhx" +#define SCNxFAST8 "hhx" + +/* unsigned char */ +#define SCNu8 "hhu" +#define SCNuLEAST8 "hhu" +#define SCNuFAST8 "hhu" +#endif /* __STDC_VERSION__ >= 199901 */ + +#endif /* !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) */ + + +#ifdef __cplusplus +} +#endif + +#endif /* ndef _INTTYPES_H */ diff --git a/driver/source/msvc/stdint.h b/driver/source/msvc/stdint.h new file mode 100644 index 00000000..5d5329a9 --- /dev/null +++ b/driver/source/msvc/stdint.h @@ -0,0 +1,273 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file was originally part of the w64 mingw-runtime package. + */ + +/* ISO C9x 7.18 Integer types + * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * Contributor: Danny Smith + * Modified for libusb/MSVC: Pete Batard + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2010-04-02 + */ + +#ifndef _MSC_VER +#error This header should only be used with Microsoft compilers +#endif + +#ifndef _STDINT_H +#define _STDINT_H + +/* from stddef.h and _mingw.h */ +#ifndef _SSIZE_T_DEFINED +#define _SSIZE_T_DEFINED +#undef ssize_t +#ifdef _WIN64 + typedef __int64 ssize_t; +#else + typedef int ssize_t; +#endif /* _WIN64 */ +#endif /* _SSIZE_T_DEFINED */ + +#ifndef _INTPTR_T_DEFINED +#define _INTPTR_T_DEFINED +#ifndef __intptr_t_defined +#define __intptr_t_defined +#undef intptr_t +#ifdef _WIN64 + typedef __int64 intptr_t; +#else + typedef int intptr_t; +#endif /* _WIN64 */ +#endif /* __intptr_t_defined */ +#endif /* _INTPTR_T_DEFINED */ + +#ifndef _UINTPTR_T_DEFINED +#define _UINTPTR_T_DEFINED +#ifndef __uintptr_t_defined +#define __uintptr_t_defined +#undef uintptr_t +#ifdef _WIN64 + typedef unsigned __int64 uintptr_t; +#else + typedef unsigned int uintptr_t; +#endif /* _WIN64 */ +#endif /* __uintptr_t_defined */ +#endif /* _UINTPTR_T_DEFINED */ + +#ifndef _PTRDIFF_T_DEFINED +#define _PTRDIFF_T_DEFINED +#ifndef _PTRDIFF_T_ +#define _PTRDIFF_T_ +#undef ptrdiff_t +#ifdef _WIN64 + typedef __int64 ptrdiff_t; +#else + typedef int ptrdiff_t; +#endif /* _WIN64 */ +#endif /* _PTRDIFF_T_ */ +#endif /* _PTRDIFF_T_DEFINED */ + +#ifndef _WCHAR_T_DEFINED +#define _WCHAR_T_DEFINED +#ifndef __cplusplus + typedef unsigned short wchar_t; +#endif /* C++ */ +#endif /* _WCHAR_T_DEFINED */ + +#ifndef _WCTYPE_T_DEFINED +#define _WCTYPE_T_DEFINED +#ifndef _WINT_T +#define _WINT_T + typedef unsigned short wint_t; + typedef unsigned short wctype_t; +#endif /* _WINT_T */ +#endif /* _WCTYPE_T_DEFINED */ + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef signed char int_least8_t; +typedef unsigned char uint_least8_t; +typedef short int_least16_t; +typedef unsigned short uint_least16_t; +typedef int int_least32_t; +typedef unsigned uint_least32_t; +typedef long long int_least64_t; +typedef unsigned long long uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types + * Not actually guaranteed to be fastest for all purposes + * Here we use the exact-width types for 8 and 16-bit ints. + */ +typedef signed char int_fast8_t; +typedef unsigned char uint_fast8_t; +typedef short int_fast16_t; +typedef unsigned short uint_fast16_t; +typedef int int_fast32_t; +typedef unsigned int uint_fast32_t; +typedef long long int_fast64_t; +typedef unsigned long long uint_fast64_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef long long intmax_t; +typedef unsigned long long uintmax_t; + +/* 7.18.2 Limits of specified-width integer types */ +#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS) + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647 - 1) +#define INT64_MIN (-9223372036854775807LL - 1) + +#define INT8_MAX 127 +#define INT16_MAX 32767 +#define INT32_MAX 2147483647 +#define INT64_MAX 9223372036854775807LL + +#define UINT8_MAX 255 +#define UINT16_MAX 65535 +#define UINT32_MAX 0xffffffffU /* 4294967295U */ +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding + object pointers */ +#ifdef _WIN64 +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* 7.18.3 Limits of other integer types */ +#ifdef _WIN64 +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX +#else +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX +#endif + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#ifndef SIZE_MAX +#ifdef _WIN64 +#define SIZE_MAX UINT64_MAX +#else +#define SIZE_MAX UINT32_MAX +#endif +#endif + +#ifndef WCHAR_MIN /* also in wchar.h */ +#define WCHAR_MIN 0U +#define WCHAR_MAX 0xffffU +#endif + +/* + * wint_t is unsigned short for compatibility with MS runtime + */ +#define WINT_MIN 0U +#define WINT_MAX 0xffffU + +#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */ + + +/* 7.18.4 Macros for integer constants */ +#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS) + +/* 7.18.4.1 Macros for minimum-width integer constants + + Accoding 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 + is impossible to accomplish for the shorter types on most + platforms, because C99 provides no standard way to designate + an integer constant with width less than that of type int. + TC1 changed this to require just an integer constant + *expression* with *promoted* type." + + The trick used here is from Clive D W Feather. +*/ + +#define INT8_C(val) (INT_LEAST8_MAX-INT_LEAST8_MAX+(val)) +#define INT16_C(val) (INT_LEAST16_MAX-INT_LEAST16_MAX+(val)) +#define INT32_C(val) (INT_LEAST32_MAX-INT_LEAST32_MAX+(val)) +/* The 'trick' doesn't work in C89 for long long because, without + suffix, (val) will be evaluated as int, not intmax_t */ +#define INT64_C(val) val##LL + +#define UINT8_C(val) (val) +#define UINT16_C(val) (val) +#define UINT32_C(val) (val##U) +#define UINT64_C(val) val##ULL + +/* 7.18.4.2 Macros for greatest-width integer constants */ +#define INTMAX_C(val) val##LL +#define UINTMAX_C(val) val##ULL + +#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */ + +#endif diff --git a/driver/source/nesmini_driver/nesmini_driver.cpp b/driver/source/nesmini_driver/nesmini_driver.cpp new file mode 100644 index 00000000..31a34526 --- /dev/null +++ b/driver/source/nesmini_driver/nesmini_driver.cpp @@ -0,0 +1,125 @@ + +/* +* 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 +*/ +/* +* NES Mini driver mod by Alexey 'Cluser' Avdyukhin +* clusterrr@clusterrr.com +*/ +/* +* 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 "libwdi.h" + +#define FLUSHER while(getchar() != 0x0A) +#define INF_NAME "nesmini.inf" + +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 int vid = 0x1F3A; + static unsigned short pid = 0xEFE8; + 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; + cl_options.list_all = 1; + pd_options.driver_type = WDI_WINUSB; + pd_options.device_name = "NES Mini"; + pd_options.vendor_name = "Nintendo"; + pd_options.device_guid = "{FF176DC4-7BEE-43BE-9BF2-F9299CB990BD}"; + + 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; + } + + boolean found = FALSE; + for (device = list; device != NULL; device = device->next) { + if (vid == 0 || pid == 0) 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; + } + else { + printf("Found USB device: \"%s\" (%04X:%04X)\n", device->desc, device->vid, device->pid); + found = TRUE; + } + } + // 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); + if (vid != 0 && pid != 0 && !found) + printf("%s not found, sorry\n", pd_options.device_name); + + // This is needed when ran in UAC mode + if (prompt_flag) { + printf("\nPress Enter to exit this driver installer\n"); + FLUSHER; + } + return 0; +} diff --git a/driver/source/nesmini_driver/nesmini_driver.vcxproj b/driver/source/nesmini_driver/nesmini_driver.vcxproj new file mode 100644 index 00000000..787723a4 --- /dev/null +++ b/driver/source/nesmini_driver/nesmini_driver.vcxproj @@ -0,0 +1,160 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {CEB55682-D761-4F72-9345-D0DB436048E9} + Win32Proj + nesmini_driver + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + ..\..\ + + + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\libwdi;%(AdditionalIncludeDirectories) + + + Console + true + RequireAdministrator + setupapi.lib;newdev.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\libwdi;%(AdditionalIncludeDirectories) + + + Console + true + true + true + %(AdditionalLibraryDirectories) + setupapi.lib;newdev.lib;%(AdditionalDependencies) + RequireAdministrator + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + {9aa0e745-1a0a-4700-8ecb-6a6de9dbf8b9} + + + + + + \ No newline at end of file diff --git a/driver/source/nesmini_driver/nesmini_driver.vcxproj.filters b/driver/source/nesmini_driver/nesmini_driver.vcxproj.filters new file mode 100644 index 00000000..86f38339 --- /dev/null +++ b/driver/source/nesmini_driver/nesmini_driver.vcxproj.filters @@ -0,0 +1,18 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/driver/source/nesmini_driver/nesmini_driver.vcxproj.user b/driver/source/nesmini_driver/nesmini_driver.vcxproj.user new file mode 100644 index 00000000..6fb136bf --- /dev/null +++ b/driver/source/nesmini_driver/nesmini_driver.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/driver/usb_driver/amd64/WdfCoInstaller01011.dll b/driver/usb_driver/amd64/WdfCoInstaller01011.dll deleted file mode 100644 index d49d2913..00000000 Binary files a/driver/usb_driver/amd64/WdfCoInstaller01011.dll and /dev/null differ diff --git a/driver/usb_driver/amd64/winusbcoinstaller2.dll b/driver/usb_driver/amd64/winusbcoinstaller2.dll deleted file mode 100644 index 30e55025..00000000 Binary files a/driver/usb_driver/amd64/winusbcoinstaller2.dll and /dev/null differ diff --git a/driver/usb_driver/installer_x64.exe b/driver/usb_driver/installer_x64.exe deleted file mode 100644 index 85e65705..00000000 Binary files a/driver/usb_driver/installer_x64.exe and /dev/null differ diff --git a/driver/usb_driver/installer_x86.exe b/driver/usb_driver/installer_x86.exe deleted file mode 100644 index 1b84e95d..00000000 Binary files a/driver/usb_driver/installer_x86.exe and /dev/null differ diff --git a/driver/usb_driver/nesmini.cat b/driver/usb_driver/nesmini.cat deleted file mode 100644 index 20ad55f5..00000000 Binary files a/driver/usb_driver/nesmini.cat and /dev/null differ diff --git a/driver/usb_driver/nesmini.inf b/driver/usb_driver/nesmini.inf deleted file mode 100644 index 707d4b72..00000000 Binary files a/driver/usb_driver/nesmini.inf and /dev/null differ diff --git a/driver/usb_driver/x86/WdfCoInstaller01011.dll b/driver/usb_driver/x86/WdfCoInstaller01011.dll deleted file mode 100644 index e943ea45..00000000 Binary files a/driver/usb_driver/x86/WdfCoInstaller01011.dll and /dev/null differ diff --git a/driver/usb_driver/x86/winusbcoinstaller2.dll b/driver/usb_driver/x86/winusbcoinstaller2.dll deleted file mode 100644 index fc450d2b..00000000 Binary files a/driver/usb_driver/x86/winusbcoinstaller2.dll and /dev/null differ -- cgit v1.2.3