Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-01-30 13:18:04 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-01-30 13:28:09 +0300
commit0ea6a2c4b9f12bc9e133a74ae4deb5cc42dc7113 (patch)
treeea2f64029520054b11b4813b3cdea48b7a2dd49a /driver
parent9ddd20516fd7916cbb6f44c4b0920412cba99d64 (diff)
Added driver installer source code
Diffstat (limited to 'driver')
-rw-r--r--driver/nesmini_driver.exebin5747712 -> 5704192 bytes
-rw-r--r--driver/source/AUTHORS16
-rw-r--r--driver/source/COPYING674
-rw-r--r--driver/source/COPYING-LGPL165
-rw-r--r--driver/source/ChangeLog96
-rw-r--r--driver/source/Makefile.am7
-rw-r--r--driver/source/NEWS1
-rw-r--r--driver/source/README.md38
-rw-r--r--driver/source/_bm.sh42
-rw-r--r--driver/source/_bump.sh65
-rw-r--r--driver/source/_chlver.sh47
-rw-r--r--driver/source/_chzver.sh44
-rw-r--r--driver/source/_pre-commit.sh49
-rw-r--r--driver/source/_release.sh32
-rw-r--r--driver/source/autogen.sh28
-rw-r--r--driver/source/bootstrap.sh19
-rw-r--r--driver/source/configure.ac359
-rw-r--r--driver/source/ddk_build.cmd188
-rw-r--r--driver/source/libwdi.sln97
-rw-r--r--driver/source/libwdi/.msvc/detect_64build.vcxproj109
-rw-r--r--driver/source/libwdi/.msvc/embedder.vcxproj112
-rw-r--r--driver/source/libwdi/.msvc/embedder.vcxproj.filters28
-rw-r--r--driver/source/libwdi/.msvc/embedder_sources19
-rw-r--r--driver/source/libwdi/.msvc/installer_x64.vcxproj133
-rw-r--r--driver/source/libwdi/.msvc/installer_x64.vcxproj.filters26
-rw-r--r--driver/source/libwdi/.msvc/installer_x64_sources24
-rw-r--r--driver/source/libwdi/.msvc/installer_x86.vcxproj96
-rw-r--r--driver/source/libwdi/.msvc/installer_x86.vcxproj.filters26
-rw-r--r--driver/source/libwdi/.msvc/installer_x86_sources24
-rw-r--r--driver/source/libwdi/.msvc/libwdi_dll.vcxproj227
-rw-r--r--driver/source/libwdi/.msvc/libwdi_dll.vcxproj.filters87
-rw-r--r--driver/source/libwdi/.msvc/libwdi_sources32
-rw-r--r--driver/source/libwdi/.msvc/libwdi_static.vcxproj213
-rw-r--r--driver/source/libwdi/.msvc/libwdi_static.vcxproj.filters94
-rw-r--r--driver/source/libwdi/Makefile.am65
-rw-r--r--driver/source/libwdi/embedder.c493
-rw-r--r--driver/source/libwdi/embedder.h67
-rw-r--r--driver/source/libwdi/embedder_files.h156
-rw-r--r--driver/source/libwdi/installer.c901
-rw-r--r--driver/source/libwdi/installer.h197
-rw-r--r--driver/source/libwdi/libusb0.cat.in8
-rw-r--r--driver/source/libwdi/libusb0.inf.in148
-rw-r--r--driver/source/libwdi/libusbk.cat.in9
-rw-r--r--driver/source/libwdi/libusbk.inf.in153
-rw-r--r--driver/source/libwdi/libwdi.c1786
-rw-r--r--driver/source/libwdi/libwdi.def72
-rw-r--r--driver/source/libwdi/libwdi.h307
-rw-r--r--driver/source/libwdi/libwdi.pc.in10
-rw-r--r--driver/source/libwdi/libwdi.rc90
-rw-r--r--driver/source/libwdi/libwdi_dlg.c423
-rw-r--r--driver/source/libwdi/libwdi_i.h281
-rw-r--r--driver/source/libwdi/logging.c340
-rw-r--r--driver/source/libwdi/logging.h94
-rw-r--r--driver/source/libwdi/msapi_utf8.h669
-rw-r--r--driver/source/libwdi/mssign32.h223
-rw-r--r--driver/source/libwdi/pki.c1258
-rw-r--r--driver/source/libwdi/resource.h16
-rw-r--r--driver/source/libwdi/stdfn.h94
-rw-r--r--driver/source/libwdi/tokenizer.c256
-rw-r--r--driver/source/libwdi/tokenizer.h46
-rw-r--r--driver/source/libwdi/usbser.cat.in1
-rw-r--r--driver/source/libwdi/usbser.inf.in67
-rw-r--r--driver/source/libwdi/vid_data.c2998
-rw-r--r--driver/source/libwdi/vid_data.sh82
-rw-r--r--driver/source/libwdi/winusb.cat.in5
-rw-r--r--driver/source/libwdi/winusb.inf.in94
-rw-r--r--driver/source/msvc/config.h67
-rw-r--r--driver/source/msvc/inttypes.h299
-rw-r--r--driver/source/msvc/stdint.h273
-rw-r--r--driver/source/nesmini_driver/nesmini_driver.cpp125
-rw-r--r--driver/source/nesmini_driver/nesmini_driver.vcxproj160
-rw-r--r--driver/source/nesmini_driver/nesmini_driver.vcxproj.filters18
-rw-r--r--driver/source/nesmini_driver/nesmini_driver.vcxproj.user4
-rw-r--r--driver/usb_driver/amd64/WdfCoInstaller01011.dllbin1795952 -> 0 bytes
-rw-r--r--driver/usb_driver/amd64/winusbcoinstaller2.dllbin1002728 -> 0 bytes
-rw-r--r--driver/usb_driver/installer_x64.exebin107008 -> 0 bytes
-rw-r--r--driver/usb_driver/installer_x86.exebin92672 -> 0 bytes
-rw-r--r--driver/usb_driver/nesmini.catbin3886 -> 0 bytes
-rw-r--r--driver/usb_driver/nesmini.infbin4516 -> 0 bytes
-rw-r--r--driver/usb_driver/x86/WdfCoInstaller01011.dllbin1629040 -> 0 bytes
-rw-r--r--driver/usb_driver/x86/winusbcoinstaller2.dllbin851176 -> 0 bytes
81 files changed, 15572 insertions, 0 deletions
diff --git a/driver/nesmini_driver.exe b/driver/nesmini_driver.exe
index 402117ea..9631fe02 100644
--- a/driver/nesmini_driver.exe
+++ b/driver/nesmini_driver.exe
Binary files 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 <pete@akeo.ie>
+Copyright © 2010-2011 Travis Robinson <libusbdotnet@gmail.com>
+
+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. <http://fsf.org/>
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+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:
+
+ <program> Copyright (C) <year> <name of author>
+ 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
+<http://www.gnu.org/licenses/>.
+
+ 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
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
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. <http://fsf.org/>
+ 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 ^<windows.h^> > 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>detect_64build</ProjectName>
+ <ProjectGuid>{5FAEF8F7-C809-4A68-862F-F8BC6E775B61}</ProjectGuid>
+ <RootNamespace>detect64build</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)\..\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)\..\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)\..\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)\..\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\helper\detect_64build\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PreBuildEvent>
+ <Message>detected 32 bit build</Message>
+ <Command>echo #define NO_BUILD64&gt; $(ProjectDir)\..\build64.h</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PreBuildEvent>
+ <Message>detected 64 bit build</Message>
+ <Command>echo #define BUILD64&gt; $(ProjectDir)\..\build64.h</Command>
+ </PreBuildEvent>
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PreBuildEvent>
+ <Message>detected 32 bit build</Message>
+ <Command>echo #define NO_BUILD64&gt; $(ProjectDir)\..\build64.h</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PreBuildEvent>
+ <Message>detected 64 bit build</Message>
+ <Command>echo #define BUILD64&gt; $(ProjectDir)\..\build64.h</Command>
+ </PreBuildEvent>
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>embedder</ProjectName>
+ <ProjectGuid>{792D44D5-28A7-4EB3-B84B-8021FE3189F9}</ProjectGuid>
+ <RootNamespace>embedder</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)\..\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)\..\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <BuildLog>
+ <Path>$(IntDir)$(ProjectName).htm</Path>
+ </BuildLog>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(ProjectName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <BuildLog>
+ <Path>$(IntDir)$(ProjectName).htm</Path>
+ </BuildLog>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\embedder.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\msvc\config.h" />
+ <ClInclude Include="..\embedder.h" />
+ <ClInclude Include="..\embedder_files.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="detect_64build.vcxproj">
+ <Project>{5faef8f7-c809-4a68-862f-f8bc6e775b61}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{AF571DD9-AF6B-4F0A-9A9E-D041D12982F7}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{94a3d5a0-4579-4436-9f8f-1c7261f20c77}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\embedder.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\msvc\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\embedder.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\embedder_files.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>installer_x64</ProjectName>
+ <ProjectGuid>{E5A56EE0-182F-470F-8CDC-8C1B7B86EE26}</ProjectGuid>
+ <RootNamespace>installerx64</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\helper\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x64\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\helper\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x64\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS; _WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>newdev.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)installer_x64.exe</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS; _WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>newdev.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)installer_x64.exe</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\installer.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\installer.h" />
+ <ClInclude Include="..\msapi_utf8.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\installer.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\installer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msapi_utf8.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>installer_x86</ProjectName>
+ <ProjectGuid>{9B1C561E-F95B-4849-A7AA-A4350E227C20}</ProjectGuid>
+ <RootNamespace>installerx86</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x86\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\helper\installer_x86\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>newdev.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)installer_x86.exe</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>newdev.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)installer_x86.exe</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\installer.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\installer.h" />
+ <ClInclude Include="..\msapi_utf8.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\installer.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\installer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msapi_utf8.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>libwdi (dll)</ProjectName>
+ <ProjectGuid>{79275348-41A4-4D07-8990-4068C9594A2C}</ProjectGuid>
+ <RootNamespace>libwdi</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\dll\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\dll\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\dll\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\dll\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\dll\libwdi\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libwdi</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libwdi</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libwdi</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libwdi</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>DEBUG;_DEBUG;_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>false</ExceptionHandling>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>setupapi.lib;newdev.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)libwdi.dll</OutputFile>
+ <ModuleDefinitionFile>../libwdi.def</ModuleDefinitionFile>
+ <EmbedManagedResourceFile>../libwdi.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>DEBUG;_DEBUG;_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>false</ExceptionHandling>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>setupapi.lib;newdev.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)libwdi.dll</OutputFile>
+ <ModuleDefinitionFile>../libwdi.def</ModuleDefinitionFile>
+ <EmbedManagedResourceFile>../libwdi.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <ExceptionHandling>false</ExceptionHandling>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>setupapi.lib;newdev.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)libwdi.dll</OutputFile>
+ <ModuleDefinitionFile>../libwdi.def</ModuleDefinitionFile>
+ <EmbedManagedResourceFile>../libwdi.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <ExceptionHandling>false</ExceptionHandling>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>setupapi.lib;newdev.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)libwdi.dll</OutputFile>
+ <ModuleDefinitionFile>../libwdi.def</ModuleDefinitionFile>
+ <EmbedManagedResourceFile>../libwdi.rc;%(EmbedManagedResourceFile)</EmbedManagedResourceFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\libwdi.c" />
+ <ClCompile Include="..\libwdi_dlg.c" />
+ <ClCompile Include="..\logging.c" />
+ <ClCompile Include="..\pki.c" />
+ <ClCompile Include="..\tokenizer.c" />
+ <ClCompile Include="..\vid_data.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\msvc\config.h" />
+ <ClInclude Include="..\installer.h" />
+ <ClInclude Include="..\libwdi.h" />
+ <ClInclude Include="..\libwdi_i.h" />
+ <ClInclude Include="..\logging.h" />
+ <ClInclude Include="..\msapi_utf8.h" />
+ <ClInclude Include="..\mssign32.h" />
+ <ClInclude Include="..\resource.h" />
+ <ClInclude Include="..\tokenizer.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\libusb0.inf.in" />
+ <None Include="..\libwdi.def" />
+ <None Include="..\usbser.inf.in" />
+ <None Include="..\winusb.inf.in" />
+ <None Include="..\libusbk.inf.in" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\libwdi.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="embedder.vcxproj">
+ <Project>{792d44d5-28a7-4eb3-b84b-8021fe3189f9}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="installer_x64.vcxproj">
+ <Project>{e5a56ee0-182f-470f-8cdc-8c1b7b86ee26}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="installer_x86.vcxproj">
+ <Project>{9b1c561e-f95b-4849-a7aa-a4350e227c20}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{764477b1-9f30-48f4-b48e-dacb7fd3784f}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\libwdi.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\libwdi_dlg.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\logging.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tokenizer.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\vid_data.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\pki.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\msvc\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\installer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\libwdi.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\logging.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msapi_utf8.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\tokenizer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\mssign32.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\libwdi_i.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\libwdi.def">
+ <Filter>Source Files</Filter>
+ </None>
+ <None Include="..\libusb0.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\libusbk.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\winusb.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\usbser.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\libwdi.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>libwdi (static)</ProjectName>
+ <ProjectGuid>{9AA0E745-1A0A-4700-8ECB-6A6DE9DBF8B9}</ProjectGuid>
+ <RootNamespace>libwdi</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\lib\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\lib\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\lib\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\lib\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\lib\libwdi\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libwdi</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libwdi</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">libwdi</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">libwdi</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>DEBUG;_DEBUG;_WIN32;_CRTDBG_MAP_ALLOC;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <Optimization>Disabled</Optimization>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)libwdi.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>DEBUG;_DEBUG;_WIN32;_CRTDBG_MAP_ALLOC;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <Optimization>Disabled</Optimization>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)libwdi.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)libwdi.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PreBuildEvent>
+ <Message>Embedding binary resources</Message>
+ <Command>cd $(ProjectDir)\..
+embedder embedded.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <AdditionalIncludeDirectories>..\..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32;_WIN64;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>E:\WinDDK\7600.16385.0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)libwdi.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\libwdi.c" />
+ <ClCompile Include="..\libwdi_dlg.c" />
+ <ClCompile Include="..\logging.c" />
+ <ClCompile Include="..\pki.c" />
+ <ClCompile Include="..\tokenizer.c" />
+ <ClCompile Include="..\vid_data.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\msvc\config.h" />
+ <ClInclude Include="..\stdfn.h" />
+ <ClInclude Include="..\installer.h" />
+ <ClInclude Include="..\libwdi.h" />
+ <ClInclude Include="..\libwdi_i.h" />
+ <ClInclude Include="..\logging.h" />
+ <ClInclude Include="..\msapi_utf8.h" />
+ <ClInclude Include="..\mssign32.h" />
+ <ClInclude Include="..\resource.h" />
+ <ClInclude Include="..\tokenizer.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\libusb0.cat.in" />
+ <None Include="..\libusb0.inf.in" />
+ <None Include="..\libusbk.cat.in" />
+ <None Include="..\usbser.cat.in" />
+ <None Include="..\usbser.inf.in" />
+ <None Include="..\winusb.cat.in" />
+ <None Include="..\winusb.inf.in" />
+ <None Include="..\libusbk.inf.in" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="embedder.vcxproj">
+ <Project>{792d44d5-28a7-4eb3-b84b-8021fe3189f9}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="installer_x64.vcxproj">
+ <Project>{e5a56ee0-182f-470f-8cdc-8c1b7b86ee26}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="installer_x86.vcxproj">
+ <Project>{9b1c561e-f95b-4849-a7aa-a4350e227c20}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{7da2644f-07cc-43bb-93b9-5ddd8aec3b17}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\libwdi.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\libwdi_dlg.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\logging.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tokenizer.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\vid_data.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\pki.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\msvc\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\installer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\libwdi.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\logging.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msapi_utf8.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\tokenizer.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\mssign32.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\libwdi_i.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\stdfn.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\libusb0.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\libusbk.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\winusb.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\winusb.cat.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\libusb0.cat.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\libusbk.cat.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\usbser.cat.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="..\usbser.inf.in">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ 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 <pete@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
+ */
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(_WIN32)
+#include <windows.h>
+#else
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#endif
+
+#include <config.h>
+#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<size; i++) {
+ if (!(i%0x10))
+ fprintf(fd, "\n\t");
+ fprintf(fd, "0x%02X,", buffer[i]);
+ }
+ fprintf(fd, "\n");
+}
+
+void handle_separators(char* path)
+{
+ size_t i;
+ if (path == NULL) return;
+ for (i=0; i<strlen(path); i++) {
+ if (path[i] == NON_NATIVE_SEPARATOR) {
+ path[i] = NATIVE_SEPARATOR;
+ }
+ }
+}
+
+// These 2 functions split a path into basename and dirname
+// You must call basename_free to release the resources once done
+// Note that basename_split also normalizes the path separators
+static char* _path_copy = NULL;
+int basename_split(char* path, char** dn, char** bn)
+{
+ char* basename_pos;
+ if ((path == NULL) || (dn == NULL) || (bn == NULL)) return 1;
+ safe_free(_path_copy);
+ _path_copy = malloc(strlen(path)+1);
+ if (_path_copy == NULL) return 1;
+ memcpy(_path_copy, path, strlen(path)+1);
+ handle_separators(_path_copy);
+ basename_pos = strrchr(_path_copy, NATIVE_SEPARATOR);
+ if (basename_pos == NULL) {
+ *dn = ".";
+ *bn = _path_copy;
+ } else {
+ basename_pos[0] = 0;
+ *dn = _path_copy;
+ *bn = &basename_pos[1];
+ }
+ return 0;
+}
+
+void basename_free(char* path)
+{
+ // Ideally, we'd maintain an array associating path with the alloc'd copy
+ safe_free(_path_copy);
+}
+
+// returns 0 on success, non zero on error
+int get_full_path(char* src, char* dst, size_t dst_size)
+{
+#if defined(_WIN32)
+ DWORD r;
+ char* src_copy = NULL;
+#else
+ char *dn, *bn;
+#endif
+ if ((src == NULL) || (dst == NULL) || (dst_size == 0)) {
+ return 1;
+ }
+#if defined(_WIN32)
+ if ((src_copy = malloc(strlen(src) + 1)) == NULL) return 1;
+ memcpy(src_copy, src, strlen(src) + 1);
+ handle_separators(src_copy);
+ r = GetFullPathNameA(src_copy, (DWORD)dst_size, dst, NULL);
+ safe_free(src_copy);
+ if ((r != 0) || (r <= dst_size)) {
+ return 0;
+ }
+#else
+ if ( (basename_split(src, &dn, &bn) == 0)
+ && (realpath(dn, dst) != NULL)
+ && (strlen(dst) + strlen(bn) + 2 < dst_size) ) {
+ strcat(dst, "/");
+ strcat(dst, bn);
+ basename_free(src);
+ return 0;
+ }
+ basename_free(src);
+#endif
+ perr("Could not get full path for '%s'.\n", src);
+ return 1;
+}
+
+#if defined(USER_DIR)
+// Modified from http://www.zemris.fer.hr/predmeti/os1/misc/Unix2Win.htm
+void scan_dir(char *dirname, int countfiles)
+{
+ char dir[MAX_PATH+1];
+ char subdir[MAX_PATH+1];
+#if defined(_WIN32)
+ char entry[MAX_PATH];
+ wchar_t wdir[MAX_PATH+1];
+ HANDLE hList;
+ WIN32_FIND_DATAW FileData;
+#else
+ char* entry;
+ int r;
+ DIR *dp;
+ char cwd[MAX_PATH];
+ struct dirent* dir_entry;
+ struct stat stat_info;
+#endif
+
+ // Get the proper directory path
+ if ( (strlen(initial_dir) + strlen(dirname) + 4) > 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<nb_embeddables_fixed; i++) {
+ embeddable[i].reuse_last = 0;
+ embeddable[i].file_name = embeddable_fixed[i].file_name;
+ embeddable[i].extraction_subdir = embeddable_fixed[i].extraction_subdir;
+ }
+ nb_embeddables = nb_embeddables_fixed;
+
+ // Fill in the array
+ scan_dir("", 0);
+}
+#endif
+
+int
+#ifdef DDKBUILD
+__cdecl
+#endif
+main (int argc, char *argv[])
+{
+ int ret = 1, i, j, rebuild;
+ size_t size;
+ char* file_name = NULL;
+ char* junk;
+ size_t* file_size = NULL;
+ int64_t* file_time = NULL;
+ FILE *fd, *header_fd;
+ time_t header_time;
+ struct NATIVE_STAT stbuf;
+ struct tm* ltm;
+ char internal_name[] = "file_###";
+ unsigned char* buffer = NULL;
+ unsigned char last;
+ char fullpath[MAX_PATH];
+#if defined(_WIN32)
+ wchar_t wfullpath[MAX_PATH];
+#endif
+
+ // Disable stdout bufferring
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (argc != 2) {
+ perr("You must supply a header name.\n");
+ return 1;
+ }
+
+ nb_embeddables = nb_embeddables_fixed;
+#if defined(USER_DIR)
+ add_user_files();
+#endif
+ // Check if any of the embedded files have changed
+ rebuild = 0;
+ if (NATIVE_STAT(argv[1], &stbuf) == 0) {
+ header_time = stbuf.st_mtime; // make sure to use modification time!
+ for (i=0; i<nb_embeddables; i++) {
+ if (embeddable[i].reuse_last) continue;
+ if (get_full_path(embeddable[i].file_name, fullpath, MAX_PATH)) {
+ perr("Unable to get full path for '%s'.\n", embeddable[i].file_name);
+ goto out1;
+ }
+ if (NATIVE_STAT(fullpath, &stbuf) != 0) {
+ printf("unable to stat '%s' - assuming rebuild needed\n", fullpath);
+ rebuild = 1;
+ break;
+ }
+ if (stbuf.st_mtime > 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; i<nb_embeddables; i++) {
+ if (embeddable[i].reuse_last) {
+ continue;
+ }
+ if (get_full_path(embeddable[i].file_name, fullpath, MAX_PATH)) {
+ perr("Could not get full path for '%s'.\n", embeddable[i].file_name);
+ goto out2;
+ }
+#if defined(_WIN32)
+ MultiByteToWideChar(CP_UTF8, 0, fullpath, -1, wfullpath, MAX_PATH);
+ wprintf(L" EMBED %s ", wfullpath);
+ fd = _wfopen(wfullpath, L"rb");
+#else
+ printf(" EMBED %s ", fullpath);
+ fd = fopen(fullpath, "rb");
+#endif
+ if (fd == NULL) {
+ perr("Could not open file '%s'.\n", fullpath);
+ goto out2;
+ }
+
+ // Read the creation date
+ memset(&stbuf, 0, sizeof(stbuf));
+ if ( (NATIVE_STAT(fullpath, &stbuf) == 0) && ((ltm = localtime(&stbuf.st_ctime)) != NULL) ) {
+ printf("(%04d.%02d.%02d)\n", ltm->tm_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<nb_embeddables; i++) {
+ if (!embeddable[i].reuse_last) {
+ last = (unsigned char)i;
+ }
+ sprintf(internal_name, "file_%03X", last);
+ fprintf(header_fd, "\t{ \"");
+ // Backslashes need to be escaped
+ for (j=0; j<(int)strlen(embeddable[i].extraction_subdir); j++) {
+ if ( (embeddable[i].extraction_subdir[j] == NATIVE_SEPARATOR)
+ || (embeddable[i].extraction_subdir[j] == NON_NATIVE_SEPARATOR) ) {
+ fputc('\\', header_fd);
+ fputc('\\', header_fd);
+ } else {
+ fputc(embeddable[i].extraction_subdir[j], header_fd);
+ }
+ }
+ basename_split(embeddable[i].file_name, &junk, &file_name);
+ fprintf(header_fd, "\", \"%s\", %d, INT64_C(%"PRId64"), %s },\n",
+ file_name, (int)file_size[last], file_time[last], internal_name);
+ basename_free(embeddable[i].file_name);
+ }
+ fprintf(header_fd, "};\n");
+ fprintf(header_fd, "\nconst int nb_resources = sizeof(resource)/sizeof(resource[0]);\n");
+
+ fclose(header_fd);
+ ret = 0; goto out1;
+
+out4:
+ safe_free(buffer);
+out3:
+ fclose(fd);
+out2:
+ fclose(header_fd);
+ // Must delete a failed file so that Make can relaunch its build
+ // coverity[tainted_string]
+ NATIVE_UNLINK(argv[1]);
+out1:
+#if defined(USER_DIR)
+ for (i=nb_embeddables_fixed; i<nb_embeddables; i++) {
+ safe_free(embeddable[i].file_name);
+ safe_free(embeddable[i].extraction_subdir);
+ }
+ if (embeddable != embeddable_fixed) {
+ safe_free(embeddable);
+ }
+#endif
+ safe_free(file_size);
+ safe_free(file_time);
+ return ret;
+}
diff --git a/driver/source/libwdi/embedder.h b/driver/source/libwdi/embedder.h
new file mode 100644
index 00000000..f9c8b5e0
--- /dev/null
+++ b/driver/source/libwdi/embedder.h
@@ -0,0 +1,67 @@
+/*
+ * 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 <pete@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
+
+#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 <pete@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
+
+/*
+ * 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 <pete@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
+ */
+
+// 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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setupapi.h>
+#include <process.h>
+#include <sddl.h>
+#include <stdint.h>
+
+#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:"<root>");
+ 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:"<root>", 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,
+ &reg_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,
+ &reg_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 = "<ins>";
+ char conversion_error[] = " <Garbled data>";
+
+ if (buffer == NULL) return 0;
+
+ // CR/LF breakdown
+ for (i=0; i<size; i++) {
+ if ((buffer[i] == 0x0D) || (buffer[i] == 0x0A)) {
+ do {
+ buffer[i++] = 0;
+ } while ( ((buffer[i] == 0x0D) || (buffer[i] == 0x0A)) && (i <= size) );
+
+ // The setupapi.dev.log uses a dubious method to mark its current position
+ // If there's any "<ins>" 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<NB_SYSLOGS; i++) {
+ safe_strcpy(log_path, MAX_PATH_LENGTH, getenv("WINDIR")); // Use %WINDIR% env variable
+ safe_strcat(log_path, MAX_PATH_LENGTH, syslog_name[i]);
+ // coverity[tainted_string]
+ log_handle = CreateFileA(log_path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (log_handle != INVALID_HANDLE_VALUE) {
+ plog("using syslog '%s'", log_path);
+ break;
+ }
+ }
+ if (i == NB_SYSLOGS) {
+ plog("Could not open any syslog");
+ goto out;
+ }
+
+ // We assert that the log file is never gonna be bigger than 2 GB
+ // TODO: special case of setupapi.dev.log's last offset not being the end (v2)
+ last_offset = SetFilePointer(log_handle, 0, NULL, FILE_END);
+ if (last_offset == INVALID_SET_FILE_POINTER) {
+ plog("Could not set syslog offset");
+ goto out;
+ }
+
+ plog("syslog reader thread started");
+ SetEvent(syslog_ready_event);
+ processed_size = 0;
+
+ while(WaitForSingleObject(syslog_terminate_event, 0) != WAIT_OBJECT_0) {
+ // Find out if file size has increased since last time
+ size = GetFileSize(log_handle, NULL);
+ if (size == INVALID_FILE_SIZE) {
+ plog("could not read syslog file size");
+ goto out;
+ }
+ size -= last_offset;
+
+ if (size != 0) {
+ // Read from file and add a zero terminator
+ buffer = malloc(size+1);
+ if (buffer == NULL) {
+ plog("could not allocate buffer to read syslog");
+ goto out;
+ }
+ // Keep an extra spare byte at the beginning
+ if (!ReadFile(log_handle, buffer, size, &read_size, NULL)) {
+ plog("failed to read syslog");
+ goto out;
+ }
+ buffer[read_size] = 0;
+
+ // Send all the complete lines through the pipe
+ processed_size = process_syslog(buffer, read_size);
+ safe_free(buffer);
+ last_offset += processed_size;
+
+ // Reposition at start of last line if needed
+ if (processed_size != read_size) {
+ last_offset = SetFilePointer(log_handle, processed_size-read_size, NULL, FILE_CURRENT);
+ if (last_offset == INVALID_SET_FILE_POINTER) {
+ plog("Could not set syslog offset");
+ goto out;
+ }
+ }
+
+ // Reset adaptive sleep duration if we did send data out
+ if (processed_size !=0) {
+ duration = 0;
+ }
+ }
+
+ // Compute adaptive sleep duration
+ if (((size == 0) || (processed_size == 0)) && (duration < 500)) {
+ duration += 100; // read log more frequently on recent update
+ }
+ Sleep(duration);
+ }
+
+out:
+ plog("syslog reader thread terminating");
+ safe_free(buffer);
+ CloseHandle(log_handle);
+ _endthread();
+}
+
+static char *windows_error_str(uint32_t retval)
+{
+static char err_string[STR_BUFFER_SIZE];
+
+ DWORD size;
+ ssize_t i;
+ uint32_t error_code, format_error;
+
+ error_code = retval?retval:GetLastError();
+
+ safe_sprintf(err_string, STR_BUFFER_SIZE, "[%u] ", error_code);
+
+ // Translate codes returned by SetupAPI. The ones we are dealing with are either
+ // in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
+ // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
+ switch (error_code & 0xE0000000) {
+ case 0:
+ error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
+ break;
+ case 0xE0000000:
+ error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
+ break;
+ default:
+ break;
+ }
+
+ 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; (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, &regtype, (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<argc; i++) {
+ argv[i] = wchar_to_utf8(wargv[i]);
+ }
+ } else {
+ plog("unable to access UTF-16 args - trying ANSI");
+ }
+
+ if (argc < 2) {
+ printf("usage: %s <inf_name>\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<argc; i++) {
+ safe_free(argv[i]);
+ }
+ safe_free(argv);
+ }
+ CloseHandle(syslog_ready_event);
+ CloseHandle(syslog_terminate_event);
+ CloseHandle((HANDLE)syslog_reader_thid);
+ CloseHandle(pipe_handle);
+ return ret;
+}
diff --git a/driver/source/libwdi/installer.h b/driver/source/libwdi/installer.h
new file mode 100644
index 00000000..1a68ce41
--- /dev/null
+++ b/driver/source/libwdi/installer.h
@@ -0,0 +1,197 @@
+/*
+ * Library for WinUSB/libusb automated driver installation
+ * Copyright (c) 2010-2013 Pete Batard <pete@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 <windows.h>
+#include <objbase.h>
+
+#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)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
+#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
+#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
+#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
+#define safe_sprintf(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,<your config value>
+
+;--------------------------------------------------------------------------
+; 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 <pete@akeo.ie>
+ * 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 <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include <windows.h>
+#include <setupapi.h>
+#include <io.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <objbase.h>
+#include <shellapi.h>
+#include <config.h>
+#include <ctype.h>
+#include <sddl.h>
+#include <fcntl.h>
+#include <wincrypt.h>
+
+#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<strlen(mode); i++) {
+ if (mode[i] == 'r') {
+ access_mode |= GENERIC_READ;
+ } else if (mode[i] == 'w') {
+ access_mode |= GENERIC_WRITE;
+ }
+ }
+ if (!(access_mode & GENERIC_WRITE)) {
+ // If the file is not used for writing, might as well use fopen
+ return NULL;
+ }
+
+ // 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));
+ }
+
+ handle = CreateFileU(filename, access_mode, FILE_SHARE_READ,
+ ps, CREATE_ALWAYS, 0, NULL);
+ if (sid != NULL) LocalFree(sid);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ return NULL;
+ }
+
+ lowlevel_fd = _open_osfhandle((intptr_t)handle,
+ (access_mode&GENERIC_READ)?_O_RDWR:_O_WRONLY);
+ return _fdopen(lowlevel_fd, mode);
+}
+
+
+// Retrieve the version info from the WinUSB, libusbK or libusb0 drivers
+int get_version_info(int driver_type, VS_FIXEDFILEINFO* driver_info)
+{
+ FILE *fd;
+ int res, r;
+ char* tmpdir;
+ char filename[MAX_PATH];
+ int64_t t;
+ DWORD version_size;
+ void* version_buf;
+ UINT junk;
+ VS_FIXEDFILEINFO *file_info;
+
+ if ((driver_type < 0) || (driver_type >= 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<nb_resources; res++) {
+ // Identify the WinUSB and libusb0 files we'll pick the date & version of
+ if (safe_strcmp(resource[res].name, driver_name[driver_type]) == 0) {
+ break;
+ }
+ }
+ if (res == nb_resources) {
+ return WDI_ERROR_NOT_FOUND;
+ }
+
+ // First, we need a physical file => 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; i<nb_resources; i++) {
+ if (safe_strcmp(name, resource[i].name) == 0) {
+ if (path == NULL) {
+ return TRUE;
+ }
+ if (safe_strcmp(path, resource[i].subdir) == 0) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+ * Returns a constant string with an English short description of the given
+ * error code. The caller should never free() the returned pointer since it
+ * points to a constant string.
+ * The returned string is encoded in ASCII form and always starts with a
+ * capital letter and ends without any dot.
+ * \param error_code the error code whose description is desired
+ * \returns a short description of the error code in English
+ */
+const char* LIBWDI_API wdi_strerror(int error_code)
+{
+ static char unknown[] = "Unknown error (-9223372036854775808)"; // min 64 bit int in decimal
+ switch (error_code)
+ {
+ case WDI_SUCCESS:
+ return "Success";
+ case WDI_ERROR_IO:
+ return "Input/Output error";
+ case WDI_ERROR_INVALID_PARAM:
+ return "Invalid parameter";
+ case WDI_ERROR_ACCESS:
+ return "Access denied";
+ case WDI_ERROR_NO_DEVICE:
+ return "No such device";
+ case WDI_ERROR_NOT_FOUND:
+ return "Requested resource not found";
+ case WDI_ERROR_BUSY:
+ return "Requested resource busy or similar call already in progress";
+ case WDI_ERROR_TIMEOUT:
+ return "Operation timed out";
+ case WDI_ERROR_OVERFLOW:
+ return "Overflow";
+ case WDI_ERROR_INTERRUPTED:
+ return "System call interrupted";
+ case WDI_ERROR_RESOURCE:
+ return "Could not allocate resource";
+ case WDI_ERROR_NOT_SUPPORTED:
+ return "Operation not supported or not implemented";
+ case WDI_ERROR_EXISTS:
+ return "Resource already exists";
+ case WDI_ERROR_USER_CANCEL:
+ return "Cancelled by user";
+ // The errors below are generated during driver installation
+ case WDI_ERROR_PENDING_INSTALLATION:
+ return "Another installation is detected pending";
+ case WDI_ERROR_NEEDS_ADMIN:
+ return "Unable to run process with required administrative privileges";
+ case WDI_ERROR_WOW64:
+ return "Attempted to use a 32 bit installer on a 64 bit machine";
+ case WDI_ERROR_INF_SYNTAX:
+ return "The syntax of the inf is invalid";
+ case WDI_ERROR_CAT_MISSING:
+ return "Unable to locate cat file";
+ case WDI_ERROR_UNSIGNED:
+ return "System policy has been modified to reject unsigned drivers";
+ case WDI_ERROR_OTHER:
+ return "Other error";
+ }
+ static_sprintf(unknown, "Unknown Error: %d", error_code);
+ return (const char*)unknown;
+}
+
+// convert a GUID to an hex GUID string
+static char* guid_to_string(const GUID guid)
+{
+ static char guid_string[MAX_GUID_STRING_LENGTH];
+
+ sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ (unsigned int)guid.Data1, guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
+ guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+ return guid_string;
+}
+
+// free a device info struct
+static void free_di(struct wdi_device_info *di)
+{
+ if (di == NULL) {
+ return;
+ }
+ safe_free(di->desc);
+ 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,
+ &reg_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, &reg_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,
+ &reg_type, (BYTE*)strbuf, STR_BUFFER_SIZE, &size)) {
+ device_info->driver = NULL;
+ } else {
+ device_info->driver = safe_strdup(strbuf);
+ }
+ is_hub = FALSE;
+ for (j=0; j<ARRAYSIZE(usbhub_name); j++) {
+ if (safe_stricmp(strbuf, usbhub_name[j]) == 0) {
+ is_hub = TRUE;
+ break;
+ }
+ }
+ if (is_hub && ((options == NULL) || (!options->list_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,
+ &reg_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,
+ &reg_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,
+ &reg_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,
+ &reg_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,
+ &reg_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<nb_resources; i++) {
+ // Ignore tokenizer files
+ if (resource[i].subdir[0] == 0) {
+ continue;
+ }
+ safe_strcpy(filename, MAX_PATH, path);
+ safe_strcat(filename, MAX_PATH, "\\");
+ safe_strcat(filename, MAX_PATH, resource[i].subdir);
+
+ r = check_dir(filename, TRUE);
+ if (r != WDI_SUCCESS) {
+ return r;
+ }
+ safe_strcat(filename, MAX_PATH, "\\");
+ safe_strcat(filename, MAX_PATH, resource[i].name);
+
+ if ( (safe_strlen(path) + safe_strlen(resource[i].subdir) + safe_strlen(resource[i].name)) > (MAX_PATH - 3)) {
+ wdi_err("qualified path is too long: '%s'", filename);
+ 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; i<nb_resources; i++) {
+ // Ignore driver files
+ if (resource[i].subdir[0] != 0) {
+ continue;
+ }
+ if (strcmp(resource[i].name, resource_name) == 0) {
+ return tokenize_string(resource[i].data, (long)resource[i].size,
+ dst, token_entities, tok_prefix, tok_suffix, recursive);
+ }
+ }
+ return -ERROR_RESOURCE_DATA_NOT_FOUND;
+}
+
+#define CAT_LIST_MAX_ENTRIES 16
+// Create an inf and extract coinstallers in the directory pointed by path
+int LIBWDI_API wdi_prepare_driver(struct wdi_device_info* device_info, const char* path,
+ const char* inf_name, struct wdi_options_prepare_driver* options)
+{
+ const wchar_t bom = 0xFEFF;
+#if defined(ENABLE_DEBUG_LOGGING) || defined(INCLUDE_DEBUG_LOGGING)
+ const char* driver_display_name[WDI_NB_DRIVERS] = { "WinUSB", "libusb0.sys", "libusbK.sys", "Generic USB CDC", "user driver" };
+#endif
+ const char* inf_ext = ".inf";
+ const char* vendor_name = NULL;
+ const char* cat_list[CAT_LIST_MAX_ENTRIES+1];
+ char inf_path[MAX_PATH], cat_path[MAX_PATH], hw_id[40], cert_subject[64];
+ char *strguid, *token, *cat_name = NULL, *dst = NULL, *cat_in_copy = NULL;
+ wchar_t *wdst = NULL;
+ int i, nb_entries, driver_type = WDI_WINUSB, r = WDI_ERROR_OTHER;
+ long inf_file_size, cat_file_size;
+ BOOL is_android_device = FALSE;
+ FILE* fd;
+ GUID guid;
+ SYSTEMTIME system_time;
+ FILETIME file_time, local_time;
+
+ MUTEX_START;
+
+ if ((device_info == NULL) || (inf_name == NULL)) {
+ wdi_err("one of the required parameter is NULL");
+ MUTEX_RETURN(WDI_ERROR_INVALID_PARAM);
+ }
+
+ if (!init_dlls())
+ MUTEX_RETURN(WDI_ERROR_RESOURCE);
+
+ // Check the inf file provided and create the cat file name
+ if (strcmp(inf_name+safe_strlen(inf_name)-4, inf_ext) != 0) {
+ wdi_err("inf name provided must have a '.inf' extension");
+ MUTEX_RETURN(WDI_ERROR_INVALID_PARAM);
+ }
+
+ // Try to use the user's temp dir if no path is provided
+ if ((path == NULL) || (path[0] == 0)) {
+ path = getenv("TEMP");
+ if (path == NULL) {
+ wdi_err("no path provided and unable to use TEMP");
+ MUTEX_RETURN(WDI_ERROR_INVALID_PARAM);
+ } else {
+ wdi_info("no path provided - extracting to '%s'", path);
+ }
+ }
+
+ // Try to create directory if it doesn't exist
+ r = check_dir(path, TRUE);
+ if (r != WDI_SUCCESS) {
+ MUTEX_RETURN(r);
+ }
+
+ if (options != NULL) {
+ driver_type = options->driver_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_type<WDI_NB_DRIVERS; driver_type++) {
+ if (wdi_is_driver_supported(driver_type, NULL)) {
+ wdi_warn("unsupported or no driver type specified, will use %s",
+ driver_display_name[driver_type]);
+ break;
+ }
+ }
+ if (driver_type == WDI_NB_DRIVERS) {
+ wdi_warn("program assertion failed - no driver supported");
+ MUTEX_RETURN(WDI_ERROR_NOT_FOUND);
+ }
+ }
+
+ // If the target is libusb-win32 and we have the K DLLs, add them to the inf
+ if ((driver_type == WDI_LIBUSB0) && (wdi_is_driver_supported(WDI_LIBUSBK, NULL))) {
+ wdi_info("K driver available - adding the libusbK DLLs to the libusb-win32 inf");
+ static_strcpy(inf_entities[LK_COMMA].replace, ",");
+ static_strcpy(inf_entities[LK_DLL].replace, "libusbk.dll");
+ static_strcpy(inf_entities[LK_X86_DLL].replace, "libusbk_x86.dll");
+ static_strcpy(inf_entities[LK_EQ_X86].replace, "= 1,x86");
+ static_strcpy(inf_entities[LK_EQ_X64].replace, "= 1,amd64");
+ }
+
+ // For custom drivers, as we cannot autogenerate the inf, simply extract binaries
+ if (driver_type == WDI_USER) {
+ wdi_info("custom driver - extracting binaries only (no inf/cat creation)");
+ MUTEX_RETURN(extract_binaries(path));
+ }
+
+ if (device_info->desc == 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; i<ARRAYSIZE(android_device); i++) {
+ if ((android_device[i].vid == device_info->vid) && (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*)&params);
+ }
+ wdi_dbg("using progress bar mode");
+ return run_with_progress_bar(options->hWnd, install_driver_internal, (void*)&params);
+}
+
+// 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; i<nb_resources; i++) {
+ if (safe_strcmp(cert_name, resource[i].name) == 0) {
+ break;
+ }
+ }
+ if (i == nb_resources) {
+ wdi_err("unable to locate certificate '%s' in embedded resources", cert_name);
+ return WDI_ERROR_NOT_FOUND;
+ }
+
+ if (options != NULL) {
+ hWnd = options->hWnd;
+ 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 <pete@akeo.ie>
+ * 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 <windows.h>
+
+/*
+ * 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 <pete@akeo.ie>
+ * 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 <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include <windows.h>
+#include <windowsx.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <shlobj.h>
+#include <process.h>
+#include <stdint.h>
+#include <wingdi.h>
+#include <config.h>
+
+#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 <pete@akeo.ie>
+ * 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 <windows.h>
+#include <stdint.h>
+#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 <pete@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 <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include <windows.h>
+#include <config.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#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 <pete@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
+
+#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 <pete@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
+ */
+#include <windows.h>
+#include <stdio.h>
+#include <shlobj.h>
+#include <commdlg.h>
+#include <shellapi.h>
+#include <setupapi.h>
+#include <direct.h>
+
+#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; i<len; i++) {
+ if (wofn.lpstrFilter[i] == '\r') {
+ ((wchar_t*)wofn.lpstrFilter)[i] = 0;
+ }
+ }
+ len = strlen(lpofn->lpstrFilter);
+ for (i=0; i<len; i++) {
+ if (lpofn->lpstrFilter[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 <pete@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 <windows.h>
+#include <wincrypt.h>
+
+#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 <pete@akeo.ie>
+ * 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 <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include <windows.h>
+#include <setupapi.h>
+#include <wincrypt.h>
+#include <stdio.h>
+#include <conio.h>
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+#include "mssign32.h"
+
+#include <config.h>
+#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; i<ARRAYSIZE(szStoresToUpdate); i++)
+ {
+ hSystemStore = pfCertOpenStore(CERT_STORE_PROV_SYSTEM_A, X509_ASN_ENCODING,
+ 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, szStoresToUpdate[i]);
+ if (hSystemStore == NULL) continue;
+
+ if ( (pfCertAddEncodedCertificateToStore(hSystemStore, X509_ASN_ENCODING, pCertContext->pbCertEncoded,
+ 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 "<<<Obsolete>>>" 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<SHA1_HASH_LENGTH; i++) {
+ _snwprintf((wchar_t*)(&wszHash[2*i]), 3, L"%02X", pbFileHash[i]);
+ }
+ wszFileName = UTF8toWCHAR(szFileName);
+ if (wszFileName == NULL) {
+ goto out;
+ }
+ _wcslwr(wszFileName); // All cat filenames seem to be lowercases
+
+ // Set the PE or CAB/INF type according to the extension
+ for (szExt = &szFileName[strlen(szFileName)]; (szExt > szFileName) && (*szExt!='.'); szExt--);
+ if (szExt == szFileName) {
+ wdi_warn("unhandled file type: '%s' - ignoring", szFileName);
+ 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 "<<<Obsolete>>>" Authenticode link must be populated for each entry
+ sSPCLink.dwLinkChoice = SPC_FILE_LINK_CHOICE;
+ sSPCLink.pwszUrl = L"<<<Obsolete>>>";
+ 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<strlen(szPath); i++) {
+ if (szPath[i] == '/') {
+ szPath[i] = '\\';
+ }
+ }
+}
+
+static BOOL GetFullPath(LPCSTR szSrc, LPSTR szDst, DWORD dwDstSize)
+{
+ DWORD r;
+ LPSTR szSrcCopy = NULL;
+
+ if ((szSrc == NULL) || (szDst == NULL) || (dwDstSize == 0)) {
+ return FALSE;
+ }
+ if ((szSrcCopy = (LPSTR)malloc(strlen(szSrc) + 1)) == NULL) return 1;
+ memcpy(szSrcCopy, szSrc, strlen(szSrc) + 1);
+ HandleSeparators(szSrcCopy);
+ r = GetFullPathNameA(szSrcCopy, (DWORD)dwDstSize, szDst, NULL);
+ free(szSrcCopy);
+ if ((r != 0) && (r <= dwDstSize)) {
+ return TRUE;
+ }
+ fprintf(stderr, "Unable to get full path for '%s'.\n", szSrc);
+ return FALSE;
+}
+
+// Modified from http://www.zemris.fer.hr/predmeti/os1/misc/Unix2Win.htm
+static CHAR szInitialDir[MAX_PATH]; // We need a global variable
+static void ScanDirAndHash(HANDLE hCat, LPCSTR szDirName, LPSTR* szFileList, DWORD cFileList)
+{
+ CHAR szDir[MAX_PATH+1];
+ CHAR szSubDir[MAX_PATH+1];
+ CHAR szEntry[MAX_PATH];
+ CHAR szFilePath[MAX_PATH];
+ WCHAR wszDir[MAX_PATH+1];
+ HANDLE hList;
+ WIN32_FIND_DATAW FileData;
+ DWORD i;
+ BYTE pbHash[SHA1_HASH_LENGTH];
+
+ // Get the proper directory path
+ if ( (strlen(szInitialDir) + strlen(szDirName) + 4) > 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<cFileList; i++) {
+ _strlwr(szEntry); // must be lowercase for comparison
+ if (strcmp(szEntry, szFileList[i]) == 0) {
+ sprintf(szFilePath, "%s%s%c%s", szInitialDir, szDirName, '\\', szEntry);
+ // TODO: check return value
+ if ( (CalcHash(pbHash, szFilePath)) && AddFileHash(hCat, szEntry, pbHash) ) {
+ wdi_info("added hash for '%s'", szFilePath);
+ } else {
+ wdi_warn("could not add hash for '%s' - ignored", szFilePath);
+ }
+ break;
+ }
+ }
+ }
+ }
+ while ( FindNextFileW(hList, &FileData) || (GetLastError() != ERROR_NO_MORE_FILES) );
+ FindClose(hList);
+}
+
+/*
+ * Create a cat file for driver package signing, and add any listed matching file found in the
+ * szSearchDir directory
+ */
+BOOL CreateCat(LPCSTR szCatPath, LPCSTR szHWID, LPCSTR szSearchDir, LPCSTR* szFileList, DWORD cFileList)
+{
+ PF_DECL(CryptCATOpen);
+ PF_DECL(CryptCATClose);
+ PF_DECL(CryptCATPersistStore);
+ PF_DECL(CryptCATStoreFromHandle);
+ PF_DECL(CryptCATPutCatAttrInfo);
+
+ HCRYPTPROV hProv = 0;
+ HANDLE hCat = NULL;
+ BOOL r = FALSE;
+ DWORD i;
+ LPWSTR wszCatPath = NULL;
+ LPWSTR wszHWID = NULL;
+ // From the inf2cat /os parameter - doesn't seem to be used by the OS though...
+ LPCWSTR wszOS = L"XP_X86,XP_X64,Vista_X86,Vista_X64,7_X86,7_X64,8_X86,8_X64,8_ARM,10_X86,10_X64,10_ARM";
+ LPSTR * szLocalFileList;
+
+ PF_INIT_OR_OUT(CryptCATOpen, wintrust);
+ PF_INIT_OR_OUT(CryptCATClose, wintrust);
+ PF_INIT_OR_OUT(CryptCATPersistStore, wintrust);
+ PF_INIT_OR_OUT(CryptCATStoreFromHandle, wintrust);
+ PF_INIT_OR_OUT(CryptCATPutCatAttrInfo, wintrust);
+
+ if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ wdi_warn("unable to acquire crypt context for cat creation");
+ goto out;
+ }
+ wszCatPath = UTF8toWCHAR(szCatPath);
+ wszHWID = UTF8toWCHAR(szHWID);
+ _wcslwr(wszHWID); // Most of the cat strings are converted to lowercase
+ hCat= pfCryptCATOpen(wszCatPath, CRYPTCAT_OPEN_CREATENEW, hProv, 0, 0);
+ if (hCat == INVALID_HANDLE_VALUE) {
+ wdi_warn("unable to create file '%s': %s", szCatPath, windows_error_str(0));
+ goto out;
+ }
+
+ // Setup the general Cat attributes
+ if (pfCryptCATPutCatAttrInfo(hCat, L"HWID1", CRYPTCAT_ATTR_AUTHENTICATED|CRYPTCAT_ATTR_NAMEASCII|CRYPTCAT_ATTR_DATAASCII,
+ 2*((DWORD)wcslen(wszHWID)+1), (BYTE*)wszHWID) == NULL) {
+ wdi_warn("failed to set HWID1 cat attribute: %s", windows_error_str(0));
+ goto out;
+ }
+ if (pfCryptCATPutCatAttrInfo(hCat, L"OS", CRYPTCAT_ATTR_AUTHENTICATED|CRYPTCAT_ATTR_NAMEASCII|CRYPTCAT_ATTR_DATAASCII,
+ 2*((DWORD)wcslen(wszOS)+1), (BYTE*)wszOS) == NULL) {
+ wdi_warn("failed to set OS cat attribute: %s", windows_error_str(0));
+ goto out;
+ }
+
+ // Setup the hash file members
+ if (!GetFullPath(szSearchDir, szInitialDir, sizeof(szInitialDir))) {
+ goto out;
+ }
+ // Make sure the list entries are all lowercase
+ szLocalFileList = (LPSTR *)malloc(cFileList*sizeof(LPSTR));
+ if (szLocalFileList == NULL) {
+ wdi_warn("unable allocate local file list");
+ goto out;
+ }
+ for (i=0; i<cFileList; i++){
+ szLocalFileList[i] = _strdup(szFileList[i]);
+ if (szLocalFileList[i] == NULL)
+ wdi_warn("'%s' could not be duplicated and will be ignored", szFileList[i]);
+ else
+ _strlwr(szLocalFileList[i]);
+ }
+ ScanDirAndHash(hCat, "", szLocalFileList, cFileList);
+ for (i=0; i<cFileList; i++){
+ free(szLocalFileList[i]);
+ }
+ free(szLocalFileList);
+ // The cat needs to be sorted before being saved
+ if (!pfCryptCATPersistStore(hCat)) {
+ wdi_warn("unable to sort file: %s", windows_error_str(0));
+ goto out;
+ }
+ wdi_info("successfully created file '%s'", szCatPath);
+ r = TRUE;
+
+out:
+ if (hProv) (CryptReleaseContext(hProv, 0));
+ if (wszCatPath != NULL) free(wszCatPath);
+ if (wszHWID != NULL) free(wszHWID);
+ if ((hCat)) pfCryptCATClose(hCat);
+ return r;
+}
diff --git a/driver/source/libwdi/resource.h b/driver/source/libwdi/resource.h
new file mode 100644
index 00000000..d61727ab
--- /dev/null
+++ b/driver/source/libwdi/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by libwdi.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1003
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/driver/source/libwdi/stdfn.h b/driver/source/libwdi/stdfn.h
new file mode 100644
index 00000000..18628639
--- /dev/null
+++ b/driver/source/libwdi/stdfn.h
@@ -0,0 +1,94 @@
+/*
+* Library for USB automated driver installation
+* Copyright (c) 2010-2016 Pete Batard <pete@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
+*/
+
+#include <windows.h>
+#include <stdint.h>
+
+#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 <libusbdotnet@gmail.com>
+ *
+ * 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 <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include "config.h"
+#include "tokenizer.h"
+#include <stdlib.h>
+
+#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 <libusbdotnet@gmail.com>
+ *
+ * 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 <windows.h>
+
+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 <pete@akeo.ie> (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. <http://sensics.com/osvr>,
+; 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 <stdlib.h>
+#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<sizeof(usb_vendor)/sizeof(usb_vendor[0]); i++) {
+ if (usb_vendor[i].vid == vid) {
+ return usb_vendor[i].name;
+ }
+ }
+ return NULL;
+}
diff --git a/driver/source/libwdi/vid_data.sh b/driver/source/libwdi/vid_data.sh
new file mode 100644
index 00000000..1f9c1c76
--- /dev/null
+++ b/driver/source/libwdi/vid_data.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+echo This file recreates vid_data.c according http://www.linux-usb.org/usb.ids
+echo
+
+# check that wget and sed are available
+type -P wget &>/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 <stdlib.h>\
+#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<sizeof(usb_vendor)/sizeof(usb_vendor[0]); i++) \{\
+ if (usb_vendor[i].vid == vid) \{\
+ return usb_vendor[i].name;\
+ \}\
+ \}\
+ return NULL;\
+\}
+
+# Main Data
+/^[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F] /!d
+s/^\([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\) \(.*\)/\ { 0x\1, "\2" \},/
+s/???/?/
+s/??/?/
+_EOF
+
+# Run sed to generate the source.
+sed -f cmd.sed usb.ids > 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 <pete@akeo.ie> (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 <pbatard@gmail.com>
+ *
+ * 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 <inttypes.h> */
+
+#ifndef _INTTYPES_H_
+#define _INTTYPES_H_
+
+#include <stdint.h>
+
+#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 <stdint.h>
+ * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * Contributor: Danny Smith <danny_r_smith_2001@yahoo.co.nz>
+ * Modified for libusb/MSVC: Pete Batard <pbatard@gmail.com>
+ *
+ * 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 <gwyn@arl.mil>:
+ "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 <pete@akeo.ie>
+* Copyright (c) 2015 PhracturedBlue <6xtc2h7upj@snkmail.com>
+* Copyright (c) 2010 Joseph Marshall <jmarshall@gcdataconcepts.com>
+*
+* 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 <stdio.h>
+#include <string.h>
+#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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CEB55682-D761-4F72-9345-D0DB436048E9}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>nesmini_driver</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\libwdi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
+ <AdditionalDependencies>setupapi.lib;newdev.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\libwdi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>setupapi.lib;newdev.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="nesmini_driver.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\libwdi\.msvc\libwdi_static.vcxproj">
+ <Project>{9aa0e745-1a0a-4700-8ecb-6a6de9dbf8b9}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="nesmini_driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project> \ 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
--- a/driver/usb_driver/amd64/WdfCoInstaller01011.dll
+++ /dev/null
Binary files differ
diff --git a/driver/usb_driver/amd64/winusbcoinstaller2.dll b/driver/usb_driver/amd64/winusbcoinstaller2.dll
deleted file mode 100644
index 30e55025..00000000
--- a/driver/usb_driver/amd64/winusbcoinstaller2.dll
+++ /dev/null
Binary files differ
diff --git a/driver/usb_driver/installer_x64.exe b/driver/usb_driver/installer_x64.exe
deleted file mode 100644
index 85e65705..00000000
--- a/driver/usb_driver/installer_x64.exe
+++ /dev/null
Binary files differ
diff --git a/driver/usb_driver/installer_x86.exe b/driver/usb_driver/installer_x86.exe
deleted file mode 100644
index 1b84e95d..00000000
--- a/driver/usb_driver/installer_x86.exe
+++ /dev/null
Binary files differ
diff --git a/driver/usb_driver/nesmini.cat b/driver/usb_driver/nesmini.cat
deleted file mode 100644
index 20ad55f5..00000000
--- a/driver/usb_driver/nesmini.cat
+++ /dev/null
Binary files differ
diff --git a/driver/usb_driver/nesmini.inf b/driver/usb_driver/nesmini.inf
deleted file mode 100644
index 707d4b72..00000000
--- a/driver/usb_driver/nesmini.inf
+++ /dev/null
Binary files differ
diff --git a/driver/usb_driver/x86/WdfCoInstaller01011.dll b/driver/usb_driver/x86/WdfCoInstaller01011.dll
deleted file mode 100644
index e943ea45..00000000
--- a/driver/usb_driver/x86/WdfCoInstaller01011.dll
+++ /dev/null
Binary files differ
diff --git a/driver/usb_driver/x86/winusbcoinstaller2.dll b/driver/usb_driver/x86/winusbcoinstaller2.dll
deleted file mode 100644
index fc450d2b..00000000
--- a/driver/usb_driver/x86/winusbcoinstaller2.dll
+++ /dev/null
Binary files differ