Squashed 'third_party/allwpilib/' changes from f1a82828fe..ce550705d7

ce550705d7 [ntcore] Fix client "received unknown id -1" (#6186)
3989617bde [ntcore] NetworkTable::GetStruct: Add I template param (#6183)
f1836e1321 [fieldImages] Fix 2024 field json (#6179)
d05f179a9a [build] Fix running apriltagsvision Java example (#6173)
b1b03bed85 [wpilib] Update MotorControllerGroup deprecation message (#6171)
fa63fbf446 LICENSE.md: Bump year to 2024 (#6169)
4809f3d0fc [apriltag] Add 2024 AprilTag locations (#6168)
dd90965362 [wpiutil] Fix RawFrame.setInfo() NPE (#6167)
8659372d08 [fieldImages] Add 2024 field image (#6166)
a2e4d0b15d [docs] Fix docs for SysID routine (#6164)
0a46a3a618 [wpilib] Make ADXL345 default I2C address public (#6163)
7c26bc70ab [sysid] Load DataLog files directly for analysis (#6103)
f94e3d81b9 [docs] Fix SysId routine JavaDoc warnings (#6159)
6bed82a18e [wpilibc] Clean up C++ SysId routine (#6160)
4595f84719 [wpilib] Report LiveWindow-enabled-in-test (#6158)
707cb06105 [wpilib] Add SysIdRoutine logging utility and command factory (#6033)
3e40b9e5da [wpilib] Correct SmartDashboard usage reporting (#6157)
106518c3f8 [docs] Fix wpilibj JavaDoc warnings (#6154)
19cb2a8eb4 [wpilibj] Make class variables private to match C++ (#6153)
13f4460e00 [docs] Add missing docs to enum fields (NFC) (#6150)
4210f5635d [docs] Fix warnings about undocumented default constructors (#6151)
0f060afb55 [ntcore] Disable WebSocket fragmentation (#6149)
f29a7d2e50 [docs] Add missing JavaDocs (#6146)
6e58db398d [commands] Make Java fields private (#6148)
4ac0720385 [build] Clean up CMake files (#6141)
44db3e0ac0 [sysid] Make constexpr variables outside class scope inline (#6145)
73c7d87db7 [glass] NTStringChooser: Properly set retained (#6144)
25636b712f [build] Remove unnecessary native dependencies in wpilibjExamples (#6143)
01fb98baaa [docs] Add Missing JNI docs from C++ (NFC) (#6139)
5c424248c4 [wpilibj] Remove unused AnalogTriggerException (#6142)
c486972c55 [wpimath] Make ExponentialProfile.State mutable (#6138)
783acb9b72 [wpilibj] Store long preferences as integers (#6136)
99ab836894 [wpiutil] Add missing JavaDocs (NFC) (#6132)
ad0859a8c9 [docs] Add missing JavaDocs (#6125)
5579219716 [docs] Exclude quickbuf files and proto/struct packages from doclint (#6128)
98f06911c7 [sysid] Use eigenvector component instead of eigenvalue for fit quality check (#6131)
e1d49b975c [wpimath] Add LinearFilter reset() overload to initialize input and output buffers (#6133)
8a0bf2b7a4 [hal] Add CANAPITypes to java (#6121)
91d8837c11 [wpilib] Make protected fields in accelerometers/gyros private (#6134)
e7c9f27683 [wpilib] Add functional interface equivalents to MotorController (#6053)
8aca706217 [glass] Add type information to SmartDashboard menu (#6117)
7d3e4ddba9 [docs] Add warning about using user button to docs (NFC) (#6129)
ec3cb3dcba [build] Disable clang-tidy warning about test case names (#6127)
495585b25d [examples] Update april tag family to 36h11 (#6126)
f9aabc5ab2 [wpilib] Throw early when EventLoop is modified while running (#6115)
c16946c0ec [hal] Add CANJNI docs (NFC) (#6120)
b7f4eb2811 [doc] Update maven artifacts for units and apriltags (NFC) (#6123)
f419a62b38 [doc] Update maintainers.md (NFC) (#6124)
938bf45fd9 [wpiutil] Remove type param from ProtobufSerializable and StructSerializable (#6122)
c34debe012 [docs] Link to external OpenCV docs (#6119)
07183765de [hal] Fix formatting of HAL_ENUM enums (NFC) (#6114)
af46034b7f [wpilib] Document only first party controllers are guaranteed to have correct mapping (#6112)
636ef58d94 [hal] Properly error check readCANStreamSession (#6108)
cc631d2a69 [build] Fix generated source set location in the HAL (#6113)
09f76b32c2 [wpimath] Compile with UTF-8 encoding (#6111)
47c5fd8620 [sysid] Check data quality before OLS (#6110)
24a76be694 [hal] Add method to detect if the CAN Stream has overflowed (#6105)
9333951736 [hal] Allocate CANStreamMessage in JNI if null (#6107)
6a2d3c30a6 [wpiutil] Struct: Add info template parameter pack (#6086)
e07de37e64 [commands] Mark ParallelDeadlineGroup.setDeadline() final (#6102)
141241d2d6 [wpilib] Fix usage reporting for static classes (#6090)
f2c2bab7dc [sysid] Fix adjusted R² calculation (#6101)
5659038443 [wpiutil,cscore,apriltag] Fix RawFrame (#6098)
8aeee03626 [commands] Improve error message when composing commands twice in same composition (#6091)
55508706ff [wpiutil,cscore] Move VideoMode.PixelFormat to wpiutil (#6097)
ab78b930e9 [wpilib] ADIS16470: Add access to all 3 axes (#6074)
795d4be9fd [wpilib] Fix precision issue in Color round-and-clamp (#6100)
7aa9ad44b8 [commands] Deprecate C++ TransferOwnership() (#6095)
92c81d0791 [ci] Update pregenerate workflow to actions/checkout@v4 (#6094)
1ce617be07 [ci] Update artifact actions to v4 (#6092)
2441b57156 [wpilib] Add PWMSparkFlex MotorController (#6089)
21d1972d7a [wpiutil] DataLog: Ensure file is written on shutdown (#6087)
c29e8c66cf [wpiutil] DataLog: Fix UB in AppendImpl (#6088)
ab309e34ef [glass] Fix order of loading window settings (#6056)
22a322c9f3 [wpimath] Report error on negative PID gains (#6055)
1dba26c937 [wpilib] Add method to get breaker fault at a specific channel in PowerDistribution[Sticky]Faults (#5521)
ef1cb3f41e [commands] Fix compose-while-scheduled issue and test all compositions (#5581)
aeb1a4aa33 [wpiutil] Add serializable marker interfaces (#6060)
c1178d5add [wpilib] Add StadiaController and command wrapper (#6083)
4e4a468d4d [wpimath] Make feedforward classes throw exceptions for negative Kv or Ka (#6084)
d1793f077d [build] cmake: Add NO_WERROR option to disable -Werror (#6071)
43fb6e9f87 [glass] Add Profiled PID controller support & IZone Support (#5959)
bcef6c5398 [apriltag] Fix Java generation functions (#6063)
4059e0cd9f [hal,wpilib] Add function to control "Radio" LED (#6073)
0b2cfb3abc [dlt] Change datalogtool default folder to logs folder (#6079)
df5e439b0c [wpilib] PS4Controller: enable usage reporting (#6081)
0ff7478968 [cscore] Fix RawFrame class not being loaded in JNI (#6077)
6f23d32fe1 [wpilib] AddressableLED: Update warning about single driver (NFC) (#6069)
35a1c52788 [build] Upgrade quickbuf to 1.3.3 (#6072)
e4e2bafdb1 [sysid] Document timestamp units (#6065)
3d201c71f7 [ntcore] Fix overlapping subscriber handling (#6067)
f02984159f [glass] Check for null entries when updating struct/proto (#6059)
a004c9e05f [commands] SubsystemBase: allow setting name in constructor (#6052)
0b4c6a1546 [wpimath] Add more docs to SimulatedAnnealing (NFC) (#6054)
ab15dae887 [wpilib] ArcadeDrive: Fix max output handling (#6051)
9599c1f56f [hal] Add usage reporting ids from 2024v2 image (#6041)
f87c64af8a [wpimath] MecanumDriveWheelSpeeds: Fix desaturate() (#6040)
8798700cec [wpilibcExamples] Add inline specifier to constexpr constants (#6049)
85c9ae6eff [wpilib] Fix PS5 Controller mappings (#6050)
7c8b7a97ad [wpiutil] Zero out roborio system timestamp (#6042)
d9b504bc84 [wpilib] DataLogManager: Change sim location to logs subdir (#6039)
906b810136 [build] cmake: Fix ntcore generated header install (#6038)
56e5b404d1 Update to final 2024 V2 image (#6034)
8723ee5c39 [ntcore] Add cached topic property (#5494)
192a28af47 Fix JDK 21 warnings (#6028)
d40bdd70ba [build] Upgrade to spotbugs Gradle plugin 6.0.2 (#6027)
7bfadf32e5 [wpilibj] Joystick: make remainder of get axis methods final (#6024)
a770110438 [commands] CommandCompositionError: Include stacktrace of original composition (#5984)
54a55b8b53 [wpiutil,hal] Update image; init Rio Now() HMB with a FPGA session (#6016)
7d4e515a6b [wpimath] Simplify calculation of C for DARE precondition (#6022)
5200316c14 [ntcore] Update transmit period on topic add/remove (#6021)
ddf79a25d4 [wpiunits] Overload Measure.per(Time) to return Measure<Velocity> (#6018)
a71adef316 [wpiutil] Clean up circular_buffer iterator syntax (#6020)
39a0bf4b98 [examples] Call resetOdometry() when controller command is executed (#5905)
f5fc101fda [build] cmake: Export jars and clean up jar installs (#6014)
38bf024c96 [build] Update to Gradle 8.5 (#6007)
9d11544c18 [wpimath] Rotate traveling salesman solution so input and solution have same initial pose (#6015)
28deba20f5 [wpimath] Commit generated quickbuf Java files (#5994)
c2971c0bb3 [build] cmake: Export apriltag and wpimath (#6012)
41cfc961e4 gitattributes: Add linguist-generated locations (#6004)
14c3ade155 [wpimath] Struct cleanup (#6011)
90757b9e90 [wpilib] Make Color::HexString() constexpr (#5985)
2676b77873 Fix compilation issues that occur when building with bazel (#6008)
d32c10487c [examples] Update C++ examples to use CommandPtr (#5988)
9bc5fcf886 [build] cmake: Default WITH_JAVA_SOURCE to WITH_JAVA (#6005)
d431abba3b [upstream_utils] Fix GCEM namespace usage and add hypot(x, y, z) (#6002)
2bb1409b82 Clean up Java style (#5990)
66172ab288 Remove submodule (#6003)
e8f8c0ceb0 [upstream_utils] Update to latest Eigen HEAD (#5996)
890992a849 [hal] Commit generated usage reporting files (#5993)
a583ca01e1 [wpiutil] Change Struct to allow non-constexpr implementation (#5992)
ca272de400 [build] Fix Gradle compile_commands.json and clang-tidy warnings (#5977)
76ae090570 [wpiutil] type_traits: Add is_constexpr() (#5997)
5172ab8fd0 [commands] C++ CommandPtr: Prevent null initialization (#5991)
96914143ba [build] Bump native-utils to fix compile_commands.json (#5989)
464e6121ef [ci] Report failed status to Azure on failed tests (#2654)
5dad46cd45 [wpimath] Commit generated files (#5986)
54ab65a63a [ntcore] Commit generated files (#5962)
7ed900ae3a [wpilib] Add hex string constructor to Color and Color8Bit (#5063)
74b85b76a9 [wpimath] Make gcem call std functions if not constant-evaluated (#5983)
30816111db [wpimath] Fix TimeInterpolatableBuffer crash (#5972)
5cc923de33 [wpilib] DataLogManager: Use logs subdirectory on USB drives (#5975)
1144115da0 [commands] Add GetName to Subsystem, use in Scheduler tracer epochs (#5836)
ac7d726ac3 [wpimath] Add simulated annealing (#5961)
e09be72ee0 [wpimath] Remove unused SimpleMatrixUtils class (#5979)
0f9ebe92d9 [wpimath] Add generic circular buffer class to Java (#5969)
9fa28eb07a [ci] Bump actions/checkout to v4 (#5736)
ca684ac207 [hal] Add capability to read power distribution data as a stream (#4983)
51eecef2bd [wpimath] Optimize 2nd derivative of quintic splines (#3292)
4fcf0b25a1 [build] Apply a formatter for CMake files (#5973)
9b8011aa67 [build] Pin wpiformat version (#5982)
e00a0e84c1 [build] cmake: fix protobuf dependency finding for certain distributions (#5981)
23dd591394 [upstream_utils] Remove libuv patch that adjusts whitespace (#5976)
b0719942f0 [wpiutil] Timestamp: Report errors on Rio HMB init failure (#5974)
7bc89c4322 [wpilib] Update getAlliance() docs (NFC) (#5971)
841ea682d1 [upstream_utils] Upgrade to LLVM 17.0.5 (#5970)
a74db52dae [cameraserver] Add getVideo() pixelFormat overload (#5966)
a7eb422662 [build] Update native utils for new compile commands files (#5968)
544b231d4d [sysid] Add missing cassert include (#5967)
31cd015970 [wpimath] Add SysId doc links to LinearSystemId in C++ (NFC) (#5960)
9280054eab Revert "[build] Export wpimath protobuf symbols (#5952)"
2aba97c610 Export pb files from wpimath
c80b2d2017 [build] Export wpimath protobuf symbols (#5952)
3c0652c18a [cscore] Replace CS_PixelFormat with WPI_PixelFormat (#5954)
95716eb0cb [wpiunits] Documentation improvements (#5932)
423fd75fa8 [wpilib] Default LiveWindowEnabledInTest to false (#5950)
dfdea9c992 [wpimath] Make KalmanFilter variant for asymmetric updates (#5951)
ca81ced409 [wpiutil] Move RawFrame to wpiutil; add generation of RawFrame for AprilTags (#5923)
437cc91af5 [cscore] CvSink: Allow specifying output PixelFormat (#5943)
25b7dca46b [build] Remove CMake flat install option (#5944)
bb05e20247 [wpimath] Add protobuf/struct for trivial types (#5935)
35744a036e [wpimath] Move struct/proto classes to separate files (#5918)
80d7ad58ea [build] Declare platform launcher dependency explicitly (#5909)
f8d983b154 [ntcore] Protobuf/Struct: Use atomic_bool instead of atomic_flag (#5946)
4a44210ee3 [ntcore] NetworkTableInstance: Suppress unused lambda capture warning (#5947)
bdc8620d55 [upstream_utils] Fix fmt compilation errors on Windows (#5948)
0ca1e9b5f9 [wpimath] Add basic wpiunits support (#5821)
cc30824409 [ntcore] Increase client meta-topic decoding limit (#5934)
b1fad062f7 [wpilib] Use RKDP in DifferentialDrivetrainSim (#5931)
ead9ae5a69 [build] Add generateProto dependency to test and dev (#5933)
cfbff32185 [wpiutil] timestamp: Fix startup race on Rio (#5930)
7d90d0bcc3 [wpimath] Clean up StateSpaceUtil (#5891)
7755e45aac [build] Add generated protobuf headers to C++ test include path (#5926)
3985c031da [ntcore] ProtobufSubscriber: Fix typos (#5928)
7a87fe4b60 [ntcore] ProtobufSubscriber: Make mutex and msg mutable (#5927)
09f3ed6a5f [commands] Add static Trigger factories for robot mode changes (#5902)
79dd795bc0 [wpimath] Clean up VecBuilder and MatBuilder (#5906)
e117274a67 [wpilib] Change default Rio log dir from /home/lvuser to /home/lvuser/logs (#5899)
a8b80ca256 [upstream_utils] Update to libuv 1.47.0 (#5889)
b3a9c3e96b [build] Bump macOS deployment target to 12 (#5890)
0f8129677b [build] Distribute wpimath protobuf headers (#5925)
d105f9e3e9 [wpiutil] ProtobufBuffer: Fix buffer reallocation (#5924)
c5f2f6a0fb [fieldImages] Fix typo in field images artifact name (#5922)
c1a57e422a [commands] Clean up make_vector.h (#5917)
78ebc6e9ec [wpimath] change G to gearing in LinearSystemId factories (#5834)
9ada181866 [hal] DriverStation.h: Add stddef.h include (#5897)
95fa5ec72f [wpilibc,ntcoreffi] DataLogManager: join on Stop() call (#5910)
b6f2d3cc14 [build] Remove usage of Version.parse (#5911)
cc2cbeb04c [examples] Replace gyro rotation with poseEstimator rotation (#5900)
fa6b171e1c [wpiutil] Suppress protobuf warning false positives on GCC 13 (#5907)
d504639bbe [apriltag] Improve AprilTag docs (#5895)
3a1194be40 Replace static_cast<void>() with [[maybe_unused]] attribute (#5892)
70392cbbcb [build] cmake: Add protobuf dependency to wpiutil-config (#5886)
17c1bd5a83 [ntcore] Use json_fwd (#5881)
e69a9efeba [wpilibcExamples] Match array parameter bounds (#5880)
14dcd0d26f Use char instead of uint8_t for json::parse (#5877)
ec1d261984 [hal] Fix garbage data for match info before DS connection (#5879)
63dbf5c614 [wpiutil] MemoryBuffer: Fix normal read and file type check (#5875)
b2e7be9250 [ntcore] Only datalog meta-topics if specifically requested (#5873)
201a42a3cd [wpimath] Reorder TrapezoidProfile.calculate() arguments (#5874)
04a781b4d7 [apriltag] Add GetTags to C++ version of AprilTagFieldLayout (#5872)
87a8a1ced4 [docs] Exclude eigen and protobuf from doxygen (#5871)

git-subtree-dir: third_party/allwpilib
git-subtree-split: ce550705d7cdab117c0153a202973fc026a81274
Signed-off-by: Maxwell Henderson <mxwhenderson@gmail.com>
Change-Id: Ic8645d0551d62b411b0a816c493f0f33291896a1
diff --git a/wpinet/CMakeLists.txt b/wpinet/CMakeLists.txt
index f1eda76..b2c7e04 100644
--- a/wpinet/CMakeLists.txt
+++ b/wpinet/CMakeLists.txt
@@ -8,63 +8,73 @@
 file(GLOB wpinet_jni_src src/main/native/cpp/jni/WPINetJNI.cpp)
 
 # Java bindings
-if (WITH_JAVA)
-  find_package(Java REQUIRED)
-  find_package(JNI REQUIRED)
-  include(UseJava)
-  set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
+if(WITH_JAVA)
+    find_package(Java REQUIRED)
+    find_package(JNI REQUIRED)
+    include(UseJava)
+    set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
 
-  set(CMAKE_JNI_TARGET true)
+    set(CMAKE_JNI_TARGET true)
 
-  file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
+    file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
 
-  add_jar(wpinet_jar ${JAVA_SOURCES} INCLUDE_JARS wpiutil_jar OUTPUT_NAME wpinet GENERATE_NATIVE_HEADERS wpinet_jni_headers)
+    add_jar(
+        wpinet_jar
+        ${JAVA_SOURCES}
+        INCLUDE_JARS wpiutil_jar
+        OUTPUT_NAME wpinet
+        GENERATE_NATIVE_HEADERS wpinet_jni_headers
+    )
 
-  get_property(WPINET_JAR_FILE TARGET wpinet_jar PROPERTY JAR_FILE)
-  install(FILES ${WPINET_JAR_FILE} DESTINATION "${java_lib_dest}")
+    install_jar(wpinet_jar DESTINATION ${java_lib_dest})
+    install_jar_exports(TARGETS wpinet_jar FILE wpinet_jar.cmake DESTINATION share/wpinet)
 
-  set_property(TARGET wpinet_jar PROPERTY FOLDER "java")
+    add_library(wpinetjni ${wpinet_jni_src})
+    wpilib_target_warnings(wpinetjni)
+    target_link_libraries(wpinetjni PUBLIC wpinet)
 
-  add_library(wpinetjni ${wpinet_jni_src})
-  wpilib_target_warnings(wpinetjni)
-  target_link_libraries(wpinetjni PUBLIC wpinet)
+    set_property(TARGET wpinetjni PROPERTY FOLDER "libraries")
 
-  set_property(TARGET wpinetjni PROPERTY FOLDER "libraries")
+    target_link_libraries(wpinetjni PRIVATE wpinet_jni_headers)
+    add_dependencies(wpinetjni wpinet_jar)
 
-  target_link_libraries(wpinetjni PRIVATE wpinet_jni_headers)
-  add_dependencies(wpinetjni wpinet_jar)
-
-  install(TARGETS wpinetjni EXPORT wpinetjni)
-
+    install(TARGETS wpinetjni EXPORT wpinetjni)
 endif()
 
-if (WITH_JAVA_SOURCE)
-  find_package(Java REQUIRED)
-  include(UseJava)
-  file(GLOB WPINET_SOURCES src/main/java/edu/wpi/first/net/*.java)
-  add_jar(wpinet_src_jar
-  RESOURCES NAMESPACE "edu/wpi/first/net" ${WPINET_SOURCES}
-  OUTPUT_NAME wpinet-sources)
+if(WITH_JAVA_SOURCE)
+    find_package(Java REQUIRED)
+    include(UseJava)
+    file(GLOB WPINET_SOURCES src/main/java/edu/wpi/first/net/*.java)
+    add_jar(
+        wpinet_src_jar
+        RESOURCES
+        NAMESPACE "edu/wpi/first/net" ${WPINET_SOURCES}
+        OUTPUT_NAME wpinet-sources
+    )
 
-  get_property(WPINET_SRC_JAR_FILE TARGET wpinet_src_jar PROPERTY JAR_FILE)
-  install(FILES ${WPINET_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
+    get_property(WPINET_SRC_JAR_FILE TARGET wpinet_src_jar PROPERTY JAR_FILE)
+    install(FILES ${WPINET_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
 
-  set_property(TARGET wpinet_src_jar PROPERTY FOLDER "java")
+    set_property(TARGET wpinet_src_jar PROPERTY FOLDER "java")
 endif()
 
 set(THREADS_PREFER_PTHREAD_FLAG ON)
 find_package(Threads REQUIRED)
 
-if (NOT MSVC AND NOT APPLE)
+if(NOT MSVC AND NOT APPLE)
     find_library(ATOMIC NAMES atomic libatomic.so.1)
-    if (ATOMIC)
+    if(ATOMIC)
         message(STATUS "Found libatomic: ${ATOMIC}")
     endif()
 endif()
 
 generate_resources(src/main/native/resources generated/main/cpp WPI wpi wpinet_resources_src)
 
-file(GLOB_RECURSE wpinet_native_src src/main/native/cpp/*.cpp src/main/native/thirdparty/tcpsockets/cpp/*.cpp)
+file(
+    GLOB_RECURSE wpinet_native_src
+    src/main/native/cpp/*.cpp
+    src/main/native/thirdparty/tcpsockets/cpp/*.cpp
+)
 list(REMOVE_ITEM wpinet_native_src ${wpinet_jni_src})
 file(GLOB_RECURSE wpinet_unix_src src/main/native/unix/*.cpp)
 file(GLOB_RECURSE wpinet_linux_src src/main/native/linux/*.cpp)
@@ -123,17 +133,22 @@
 wpilib_target_warnings(wpinet)
 target_link_libraries(wpinet PUBLIC wpiutil)
 
-if (NOT USE_SYSTEM_LIBUV)
+if(NOT USE_SYSTEM_LIBUV)
     target_sources(wpinet PRIVATE ${uv_native_src})
-    install(DIRECTORY src/main/native/thirdparty/libuv/include/ DESTINATION "${include_dest}/wpinet")
-    target_include_directories(wpinet PRIVATE
-        src/main/native/thirdparty/libuv/src)
-    target_include_directories(wpinet PUBLIC
-                            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/libuv/include>
-                            $<INSTALL_INTERFACE:${include_dest}/wpinet>)
+    install(
+        DIRECTORY src/main/native/thirdparty/libuv/include/
+        DESTINATION "${include_dest}/wpinet"
+    )
+    target_include_directories(wpinet PRIVATE src/main/native/thirdparty/libuv/src)
+    target_include_directories(
+        wpinet
+        PUBLIC
+            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/libuv/include>
+            $<INSTALL_INTERFACE:${include_dest}/wpinet>
+    )
     if(NOT MSVC)
         target_sources(wpinet PRIVATE ${uv_unix_src})
-        if (APPLE)
+        if(APPLE)
             target_sources(wpinet PRIVATE ${uv_darwin_src})
         else()
             target_sources(wpinet PRIVATE ${uv_linux_src})
@@ -150,38 +165,41 @@
     target_link_libraries(wpinet PUBLIC $<IF:$<TARGET_EXISTS:libuv::uv_a>,libuv::uv_a,libuv::uv>)
 endif()
 
-if (MSVC)
+if(MSVC)
     target_sources(wpinet PRIVATE ${wpinet_windows_src})
-else ()
+else()
     target_sources(wpinet PRIVATE ${wpinet_unix_src})
-    if (APPLE)
+    if(APPLE)
         target_sources(wpinet PRIVATE ${wpinet_macos_src})
     else()
         target_sources(wpinet PRIVATE ${wpinet_linux_src})
     endif()
 endif()
 
-install(DIRECTORY src/main/native/thirdparty/tcpsockets/include/ DESTINATION "${include_dest}/wpinet")
-target_include_directories(wpinet PUBLIC
-                            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/tcpsockets/include>
-                            $<INSTALL_INTERFACE:${include_dest}/wpinet>)
+install(
+    DIRECTORY src/main/native/thirdparty/tcpsockets/include/
+    DESTINATION "${include_dest}/wpinet"
+)
+target_include_directories(
+    wpinet
+    PUBLIC
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/thirdparty/tcpsockets/include>
+        $<INSTALL_INTERFACE:${include_dest}/wpinet>
+)
 
 install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/wpinet")
-target_include_directories(wpinet PUBLIC
-                            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
-                            $<INSTALL_INTERFACE:${include_dest}/wpinet>)
+target_include_directories(
+    wpinet
+    PUBLIC
+        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
+        $<INSTALL_INTERFACE:${include_dest}/wpinet>
+)
 
 install(TARGETS wpinet EXPORT wpinet)
 
-if (WITH_FLAT_INSTALL)
-    set (wpinet_config_dir ${wpilib_dest})
-else()
-    set (wpinet_config_dir share/wpinet)
-endif()
-
-configure_file(wpinet-config.cmake.in ${WPILIB_BINARY_DIR}/wpinet-config.cmake )
-install(FILES ${WPILIB_BINARY_DIR}/wpinet-config.cmake DESTINATION ${wpinet_config_dir})
-install(EXPORT wpinet DESTINATION ${wpinet_config_dir})
+configure_file(wpinet-config.cmake.in ${WPILIB_BINARY_DIR}/wpinet-config.cmake)
+install(FILES ${WPILIB_BINARY_DIR}/wpinet-config.cmake DESTINATION share/wpinet)
+install(EXPORT wpinet DESTINATION share/wpinet)
 
 subdir_list(wpinet_examples "${CMAKE_CURRENT_SOURCE_DIR}/examples")
 foreach(example ${wpinet_examples})
@@ -194,10 +212,10 @@
     endif()
 endforeach()
 
-if (UNIX AND NOT APPLE)
-    set (LIBUTIL -lutil)
+if(UNIX AND NOT APPLE)
+    set(LIBUTIL -lutil)
 else()
-    set (LIBUTIL)
+    set(LIBUTIL)
 endif()
 
 file(GLOB netconsoleServer_src src/netconsoleServer/native/cpp/*.cpp)
@@ -213,7 +231,7 @@
 set_property(TARGET netconsoleServer PROPERTY FOLDER "examples")
 set_property(TARGET netconsoleTee PROPERTY FOLDER "examples")
 
-if (WITH_TESTS)
+if(WITH_TESTS)
     wpilib_add_test(wpinet src/test/native/cpp)
     target_include_directories(wpinet_test PRIVATE src/test/native/include src/main/native/cpp)
     target_link_libraries(wpinet_test wpinet ${LIBUTIL} gmock_main wpiutil_testlib)
diff --git a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java
index 9ccb322..39989e1 100644
--- a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java
+++ b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java
@@ -25,6 +25,7 @@
    * @param port port
    * @param txt txt
    */
+  @SuppressWarnings("this-escape")
   public MulticastServiceAnnouncer(
       String serviceName, String serviceType, int port, Map<String, String> txt) {
     String[] keys = txt.keySet().toArray(String[]::new);
@@ -41,6 +42,7 @@
    * @param serviceType service type
    * @param port port
    */
+  @SuppressWarnings("this-escape")
   public MulticastServiceAnnouncer(String serviceName, String serviceType, int port) {
     m_handle =
         WPINetJNI.createMulticastServiceAnnouncer(serviceName, serviceType, port, null, null);
diff --git a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java
index b676f4c..8d70fd7 100644
--- a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java
+++ b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java
@@ -21,6 +21,7 @@
    *
    * @param serviceType service type to look for
    */
+  @SuppressWarnings("this-escape")
   public MulticastServiceResolver(String serviceType) {
     m_handle = WPINetJNI.createMulticastServiceResolver(serviceType);
     m_cleanable = WPICleaner.register(this, cleanupAction(m_handle));
diff --git a/wpinet/src/main/java/edu/wpi/first/net/WPINetJNI.java b/wpinet/src/main/java/edu/wpi/first/net/WPINetJNI.java
index d0bcf7d..4f0e189 100644
--- a/wpinet/src/main/java/edu/wpi/first/net/WPINetJNI.java
+++ b/wpinet/src/main/java/edu/wpi/first/net/WPINetJNI.java
@@ -8,20 +8,35 @@
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+/** WPINet JNI. */
 public class WPINetJNI {
   static boolean libraryLoaded = false;
   static RuntimeLoader<WPINetJNI> loader = null;
 
+  /** Sets whether JNI should be loaded in the static block. */
   public static class Helper {
     private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
 
+    /**
+     * Returns true if the JNI should be loaded in the static block.
+     *
+     * @return True if the JNI should be loaded in the static block.
+     */
     public static boolean getExtractOnStaticLoad() {
       return extractOnStaticLoad.get();
     }
 
+    /**
+     * Sets whether the JNI should be loaded in the static block.
+     *
+     * @param load Whether the JNI should be loaded in the static block.
+     */
     public static void setExtractOnStaticLoad(boolean load) {
       extractOnStaticLoad.set(load);
     }
+
+    /** Utility class. */
+    private Helper() {}
   }
 
   static {
@@ -54,8 +69,21 @@
     libraryLoaded = true;
   }
 
+  /**
+   * Forward a local TCP port to a remote host and port. Note that local ports less than 1024 won't
+   * work as a normal user.
+   *
+   * @param port local port number
+   * @param remoteHost remote IP address / DNS name
+   * @param remotePort remote port number
+   */
   public static native void addPortForwarder(int port, String remoteHost, int remotePort);
 
+  /**
+   * Stop TCP forwarding on a port.
+   *
+   * @param port local port number
+   */
   public static native void removePortForwarder(int port);
 
   public static native int createMulticastServiceAnnouncer(
@@ -82,4 +110,7 @@
   public static native int getMulticastServiceResolverEventHandle(int handle);
 
   public static native ServiceData[] getMulticastServiceResolverData(int handle);
+
+  /** Utility class. */
+  private WPINetJNI() {}
 }
diff --git a/wpinet/src/main/native/cpp/UDPClient.cpp b/wpinet/src/main/native/cpp/UDPClient.cpp
index 5963d60..1596b59 100644
--- a/wpinet/src/main/native/cpp/UDPClient.cpp
+++ b/wpinet/src/main/native/cpp/UDPClient.cpp
@@ -110,6 +110,7 @@
 #endif
   }
 
+  // NOLINTNEXTLINE(modernize-avoid-bind)
   int result = bind(m_lsd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
   if (result != 0) {
     WPI_ERROR(m_logger, "bind() failed: {}", SocketStrerror());
diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv.h b/wpinet/src/main/native/thirdparty/libuv/include/uv.h
index d5342b0..aff06cb 100644
--- a/wpinet/src/main/native/thirdparty/libuv/include/uv.h
+++ b/wpinet/src/main/native/thirdparty/libuv/include/uv.h
@@ -1876,6 +1876,18 @@
 UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
 UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
 
+/* String utilities needed internally for dealing with Windows. */
+size_t uv_utf16_length_as_wtf8(const uint16_t* utf16,
+                               ssize_t utf16_len);
+int uv_utf16_to_wtf8(const uint16_t* utf16,
+                     ssize_t utf16_len,
+                     char** wtf8_ptr,
+                     size_t* wtf8_len_ptr);
+ssize_t uv_wtf8_length_as_utf16(const char* wtf8);
+void uv_wtf8_to_utf16(const char* wtf8,
+                      uint16_t* utf16,
+                      size_t utf16_len);
+
 /* Don't export the private CPP symbols. */
 #undef UV_HANDLE_TYPE_PRIVATE
 #undef UV_REQ_TYPE_PRIVATE
diff --git a/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h b/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h
index 24fac8d..b17220f 100644
--- a/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h
+++ b/wpinet/src/main/native/thirdparty/libuv/include/uv/version.h
@@ -31,7 +31,7 @@
  */
 
 #define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 46
+#define UV_VERSION_MINOR 47
 #define UV_VERSION_PATCH 0
 #define UV_VERSION_IS_RELEASE 1
 #define UV_VERSION_SUFFIX ""
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/fs-poll.cpp b/wpinet/src/main/native/thirdparty/libuv/src/fs-poll.cpp
index 1a7ca70..5a39dae 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/fs-poll.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/fs-poll.cpp
@@ -34,7 +34,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-
 struct poll_ctx {
   uv_fs_poll_t* parent_handle;
   int busy_polling;
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/idna.cpp b/wpinet/src/main/native/thirdparty/libuv/src/idna.cpp
index 36a39a0..fe60fb5 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/idna.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/idna.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
+/* Copyright libuv contributors. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -18,11 +18,56 @@
  */
 
 #include "uv.h"
+#include "uv-common.h"
 #include "idna.h"
 #include <assert.h>
 #include <string.h>
 #include <limits.h> /* UINT_MAX */
 
+
+static int32_t uv__wtf8_decode1(const char** input) {
+  uint32_t code_point;
+  uint8_t b1;
+  uint8_t b2;
+  uint8_t b3;
+  uint8_t b4;
+
+  b1 = **input;
+  if (b1 <= 0x7F)
+    return b1; /* ASCII code point */
+  if (b1 < 0xC2)
+    return -1; /* invalid: continuation byte */
+  code_point = b1;
+
+  b2 = *++*input;
+  if ((b2 & 0xC0) != 0x80)
+    return -1; /* invalid: not a continuation byte */
+  code_point = (code_point << 6) | (b2 & 0x3F);
+  if (b1 <= 0xDF)
+    return 0x7FF & code_point; /* two-byte character */
+
+  b3 = *++*input;
+  if ((b3 & 0xC0) != 0x80)
+    return -1; /* invalid: not a continuation byte */
+  code_point = (code_point << 6) | (b3 & 0x3F);
+  if (b1 <= 0xEF)
+    return 0xFFFF & code_point; /* three-byte character */
+
+  b4 = *++*input;
+  if ((b4 & 0xC0) != 0x80)
+    return -1; /* invalid: not a continuation byte */
+  code_point = (code_point << 6) | (b4 & 0x3F);
+  if (b1 <= 0xF4) {
+    code_point &= 0x1FFFFF;
+    if (code_point <= 0x10FFFF)
+      return code_point; /* four-byte character */
+  }
+
+  /* code point too large */
+  return -1;
+}
+
+
 static unsigned uv__utf8_decode1_slow(const char** p,
                                       const char* pe,
                                       unsigned a) {
@@ -89,6 +134,7 @@
   return a;
 }
 
+
 unsigned uv__utf8_decode1(const char** p, const char* pe) {
   unsigned a;
 
@@ -102,6 +148,7 @@
   return uv__utf8_decode1_slow(p, pe, a);
 }
 
+
 static int uv__idna_toascii_label(const char* s, const char* se,
                                   char** d, char* de) {
   static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
@@ -267,7 +314,8 @@
   return 0;
 }
 
-long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
+
+ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
   const char* si;
   const char* st;
   unsigned c;
@@ -313,3 +361,195 @@
 
   return d - ds;  /* Number of bytes written. */
 }
+
+
+ssize_t uv_wtf8_length_as_utf16(const char* source_ptr) {
+  size_t w_target_len = 0;
+  int32_t code_point;
+
+  do {
+    code_point = uv__wtf8_decode1(&source_ptr);
+    if (code_point < 0)
+      return -1;
+    if (code_point > 0xFFFF)
+      w_target_len++;
+    w_target_len++;
+  } while (*source_ptr++);
+
+  return w_target_len;
+}
+
+
+void uv_wtf8_to_utf16(const char* source_ptr,
+                      uint16_t* w_target,
+                      [[maybe_unused]] size_t w_target_len) {
+  int32_t code_point;
+
+  do {
+    code_point = uv__wtf8_decode1(&source_ptr);
+    /* uv_wtf8_length_as_utf16 should have been called and checked first. */
+    assert(code_point >= 0);
+    if (code_point > 0x10000) {
+      assert(code_point < 0x10FFFF);
+      *w_target++ = (((code_point - 0x10000) >> 10) + 0xD800);
+      *w_target++ = ((code_point - 0x10000) & 0x3FF) + 0xDC00;
+      w_target_len -= 2;
+    } else {
+      *w_target++ = code_point;
+      w_target_len -= 1;
+    }
+  } while (*source_ptr++);
+
+  assert(w_target_len == 0);
+}
+
+
+static int32_t uv__get_surrogate_value(const uint16_t* w_source_ptr,
+                                       ssize_t w_source_len) {
+  uint16_t u;
+  uint16_t next;
+
+  u = w_source_ptr[0];
+  if (u >= 0xD800 && u <= 0xDBFF && w_source_len != 1) {
+    next = w_source_ptr[1];
+    if (next >= 0xDC00 && next <= 0xDFFF)
+      return 0x10000 + ((u - 0xD800) << 10) + (next - 0xDC00);
+  }
+  return u;
+}
+
+
+size_t uv_utf16_length_as_wtf8(const uint16_t* w_source_ptr,
+                               ssize_t w_source_len) {
+  size_t target_len;
+  int32_t code_point;
+
+  target_len = 0;
+  while (w_source_len) {
+    code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
+    /* Can be invalid UTF-8 but must be valid WTF-8. */
+    assert(code_point >= 0);
+    if (w_source_len < 0 && code_point == 0)
+      break;
+    if (code_point < 0x80)
+      target_len += 1;
+    else if (code_point < 0x800)
+      target_len += 2;
+    else if (code_point < 0x10000)
+      target_len += 3;
+    else {
+      target_len += 4;
+      w_source_ptr++;
+      if (w_source_len > 0)
+        w_source_len--;
+    }
+    w_source_ptr++;
+    if (w_source_len > 0)
+      w_source_len--;
+  }
+
+  return target_len;
+}
+
+
+int uv_utf16_to_wtf8(const uint16_t* w_source_ptr,
+                     ssize_t w_source_len,
+                     char** target_ptr,
+                     size_t* target_len_ptr) {
+  size_t target_len;
+  char* target;
+  char* target_end;
+  int32_t code_point;
+
+  /* If *target_ptr is provided, then *target_len_ptr must be its length
+   * (excluding space for NUL), otherwise we will compute the target_len_ptr
+   * length and may return a new allocation in *target_ptr if target_ptr is
+   * provided. */
+  if (target_ptr == NULL || *target_ptr == NULL) {
+    target_len = uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
+    if (target_len_ptr != NULL)
+      *target_len_ptr = target_len;
+  } else {
+    target_len = *target_len_ptr;
+  }
+
+  if (target_ptr == NULL)
+    return 0;
+
+  if (*target_ptr == NULL) {
+    target = (char*)uv__malloc(target_len + 1);
+    if (target == NULL) {
+      return UV_ENOMEM;
+    }
+    *target_ptr = target;
+  } else {
+    target = *target_ptr;
+  }
+
+  target_end = target + target_len;
+
+  while (target != target_end && w_source_len) {
+    code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
+    /* Can be invalid UTF-8 but must be valid WTF-8. */
+    assert(code_point >= 0);
+    if (w_source_len < 0 && code_point == 0) {
+      w_source_len = 0;
+      break;
+    }
+    if (code_point < 0x80) {
+      *target++ = code_point;
+    } else if (code_point < 0x800) {
+      *target++ = 0xC0 | (code_point >> 6);
+      if (target == target_end)
+        break;
+      *target++ = 0x80 | (code_point & 0x3F);
+    } else if (code_point < 0x10000) {
+      *target++ = 0xE0 | (code_point >> 12);
+      if (target == target_end)
+        break;
+      *target++ = 0x80 | ((code_point >> 6) & 0x3F);
+      if (target == target_end)
+        break;
+      *target++ = 0x80 | (code_point & 0x3F);
+    } else {
+      *target++ = 0xF0 | (code_point >> 18);
+      if (target == target_end)
+        break;
+      *target++ = 0x80 | ((code_point >> 12) & 0x3F);
+      if (target == target_end)
+        break;
+      *target++ = 0x80 | ((code_point >> 6) & 0x3F);
+      if (target == target_end)
+        break;
+      *target++ = 0x80 | (code_point & 0x3F);
+      /* uv__get_surrogate_value consumed 2 input characters */
+      w_source_ptr++;
+      if (w_source_len > 0)
+        w_source_len--;
+    }
+    target_len = target - *target_ptr;
+    w_source_ptr++;
+    if (w_source_len > 0)
+      w_source_len--;
+  }
+
+  if (target != target_end && target_len_ptr != NULL)
+    /* Did not fill all of the provided buffer, so update the target_len_ptr
+     * output with the space used. */
+    *target_len_ptr = target - *target_ptr;
+
+  /* Check if input fit into target exactly. */
+  if (w_source_len < 0 && target == target_end && w_source_ptr[0] == 0)
+    w_source_len = 0;
+
+  *target++ = '\0';
+
+  /* Characters remained after filling the buffer, compute the remaining length now. */
+  if (w_source_len) {
+    if (target_len_ptr != NULL)
+      *target_len_ptr = target_len + uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
+    return UV_ENOBUFS;
+  }
+
+  return 0;
+}
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/idna.h b/wpinet/src/main/native/thirdparty/libuv/src/idna.h
index 8e0c592..ea6b4df 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/idna.h
+++ b/wpinet/src/main/native/thirdparty/libuv/src/idna.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
+/* Copyright libuv contributors. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +26,6 @@
  * is the number of bytes written to |d|, including the trailing nul byte.
  * A return value < 0 is a libuv error code. |s| and |d| can not overlap.
  */
-long uv__idna_toascii(const char* s, const char* se, char* d, char* de);
+ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de);
 
 #endif  /* UV_SRC_IDNA_H_ */
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp
index ce7fd2c..1a52716 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/core.cpp
@@ -576,7 +576,6 @@
   return peerfd;
 }
 
-
 #if defined(__APPLE__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp
index 9ee5cd8..dc93d23 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/darwin.cpp
@@ -209,7 +209,7 @@
   if (cpuspeed == 0)
     /* If sysctl hw.cputype == CPU_TYPE_ARM64, the correct value is unavailable
      * from Apple, but we can hard-code it here to a plausible value. */
-    cpuspeed = 2400000000;
+    cpuspeed = 2400000000U;
 
   if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
                           (processor_info_array_t*)&info,
@@ -235,7 +235,7 @@
     cpu_info->cpu_times.irq = 0;
 
     cpu_info->model = uv__strdup(model);
-    cpu_info->speed = cpuspeed/1000000;
+    cpu_info->speed = (int)(cpuspeed / 1000000);
   }
   vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp
index aba190a..afdf0c6 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/fs.cpp
@@ -41,27 +41,12 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/uio.h>
-#include <pthread.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <poll.h>
 
 #include <atomic>
 
-#if defined(__DragonFly__)        ||                                      \
-    defined(__FreeBSD__)          ||                                      \
-    defined(__OpenBSD__)          ||                                      \
-    defined(__NetBSD__)
-# define HAVE_PREADV 1
-#else
-# define HAVE_PREADV 0
-#endif
-
-/* preadv() and pwritev() were added in Android N (level 24) */
-#if defined(__linux__) && !(defined(__ANDROID__) && __ANDROID_API__ < 24)
-# define TRY_PREADV 1
-#endif
-
 #if defined(__linux__)
 # include <sys/sendfile.h>
 #endif
@@ -99,6 +84,15 @@
 # include <sys/statfs.h>
 #endif
 
+#if defined(__CYGWIN__) ||                                                    \
+    (defined(__HAIKU__) && B_HAIKU_VERSION < B_HAIKU_VERSION_1_PRE_BETA_5) || \
+    (defined(__sun) && !defined(__illumos__))
+#define preadv(fd, bufs, nbufs, off)                                          \
+  pread(fd, (bufs)->iov_base, (bufs)->iov_len, off)
+#define pwritev(fd, bufs, nbufs, off)                                         \
+  pwrite(fd, (bufs)->iov_base, (bufs)->iov_len, off)
+#endif
+
 #if defined(_AIX) && _XOPEN_SOURCE <= 600
 extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
 #endif
@@ -412,123 +406,57 @@
 }
 
 
-#if !HAVE_PREADV
-static ssize_t uv__fs_preadv(uv_file fd,
-                             uv_buf_t* bufs,
-                             unsigned int nbufs,
-                             off_t off) {
-  uv_buf_t* buf;
-  uv_buf_t* end;
-  ssize_t result;
-  ssize_t rc;
-  size_t pos;
-
-  assert(nbufs > 0);
-
-  result = 0;
-  pos = 0;
-  buf = bufs + 0;
-  end = bufs + nbufs;
-
-  for (;;) {
-    do
-      rc = pread(fd, buf->base + pos, buf->len - pos, off + result);
-    while (rc == -1 && errno == EINTR);
-
-    if (rc == 0)
-      break;
-
-    if (rc == -1 && result == 0)
-      return UV__ERR(errno);
-
-    if (rc == -1)
-      break;  /* We read some data so return that, ignore the error. */
-
-    pos += rc;
-    result += rc;
-
-    if (pos < buf->len)
-      continue;
-
-    pos = 0;
-    buf += 1;
-
-    if (buf == end)
-      break;
-  }
-
-  return result;
-}
-#endif
-
-
 static ssize_t uv__fs_read(uv_fs_t* req) {
-#if TRY_PREADV
-  static std::atomic<int> no_preadv;
-#endif
+  const struct iovec* bufs;
   unsigned int iovmax;
-  ssize_t result;
+  size_t nbufs;
+  ssize_t r;
+  off_t off;
+  int fd;
+
+  fd = req->file;
+  off = req->off;
+  bufs = (const struct iovec*) req->bufs;
+  nbufs = req->nbufs;
 
   iovmax = uv__getiovmax();
-  if (req->nbufs > iovmax)
-    req->nbufs = iovmax;
+  if (nbufs > iovmax)
+    nbufs = iovmax;
 
-  if (req->off < 0) {
-    if (req->nbufs == 1)
-      result = read(req->file, req->bufs[0].base, req->bufs[0].len);
-    else
-      result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
+  r = 0;
+  if (off < 0) {
+    if (nbufs == 1)
+      r = read(fd, bufs->iov_base, bufs->iov_len);
+    else if (nbufs > 1)
+      r = readv(fd, bufs, nbufs);
   } else {
-    if (req->nbufs == 1) {
-      result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
-      goto done;
-    }
-
-#if HAVE_PREADV
-    result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
-#else
-# if TRY_PREADV
-    if (atomic_load_explicit(&no_preadv, std::memory_order_relaxed)) retry:
-# endif
-    {
-      result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
-    }
-# if TRY_PREADV
-    else {
-      result = preadv(req->file,
-                      (struct iovec*) req->bufs,
-                      req->nbufs,
-                      req->off);
-      if (result == -1 && errno == ENOSYS) {
-        atomic_store_explicit(&no_preadv, 1, std::memory_order_relaxed);
-        goto retry;
-      }
-    }
-# endif
-#endif
+    if (nbufs == 1)
+      r = pread(fd, bufs->iov_base, bufs->iov_len, off);
+    else if (nbufs > 1)
+      r = preadv(fd, bufs, nbufs, off);
   }
 
-done:
-  /* Early cleanup of bufs allocation, since we're done with it. */
-  if (req->bufs != req->bufsml)
-    uv__free(req->bufs);
-
-  req->bufs = NULL;
-  req->nbufs = 0;
-
 #ifdef __PASE__
   /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
-  if (result == -1 && errno == EOPNOTSUPP) {
+  if (r == -1 && errno == EOPNOTSUPP) {
     struct stat buf;
     ssize_t rc;
-    rc = uv__fstat(req->file, &buf);
+    rc = uv__fstat(fd, &buf);
     if (rc == 0 && S_ISDIR(buf.st_mode)) {
       errno = EISDIR;
     }
   }
 #endif
 
-  return result;
+  /* We don't own the buffer list in the synchronous case. */
+  if (req->cb != NULL)
+    if (req->bufs != req->bufsml)
+      uv__free(req->bufs);
+
+  req->bufs = NULL;
+  req->nbufs = 0;
+
+  return r;
 }
 
 
@@ -1163,65 +1091,34 @@
 
 
 static ssize_t uv__fs_write(uv_fs_t* req) {
-#if TRY_PREADV
-  static std::atomic<int> no_pwritev;
-#endif
+  const struct iovec* bufs;
+  size_t nbufs;
   ssize_t r;
+  off_t off;
+  int fd;
 
-  /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
-   * data loss. We can't use a per-file descriptor lock, the descriptor may be
-   * a dup().
-   */
-#if defined(__APPLE__)
-  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+  fd = req->file;
+  off = req->off;
+  bufs = (const struct iovec*) req->bufs;
+  nbufs = req->nbufs;
 
-  if (pthread_mutex_lock(&lock))
-    abort();
-#endif
-
-  if (req->off < 0) {
-    if (req->nbufs == 1)
-      r = write(req->file, req->bufs[0].base, req->bufs[0].len);
-    else
-      r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
+  r = 0;
+  if (off < 0) {
+    if (nbufs == 1)
+      r = write(fd, bufs->iov_base, bufs->iov_len);
+    else if (nbufs > 1)
+      r = writev(fd, bufs, nbufs);
   } else {
-    if (req->nbufs == 1) {
-      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
-      goto done;
-    }
-#if HAVE_PREADV
-    r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
-#else
-# if TRY_PREADV
-    if (atomic_load_explicit(&no_pwritev, std::memory_order_relaxed)) retry:
-# endif
-    {
-      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
-    }
-# if TRY_PREADV
-    else {
-      r = pwritev(req->file,
-                  (struct iovec*) req->bufs,
-                  req->nbufs,
-                  req->off);
-      if (r == -1 && errno == ENOSYS) {
-        atomic_store_explicit(&no_pwritev, 1, std::memory_order_relaxed);
-        goto retry;
-      }
-    }
-# endif
-#endif
+    if (nbufs == 1)
+      r = pwrite(fd, bufs->iov_base, bufs->iov_len, off);
+    else if (nbufs > 1)
+      r = pwritev(fd, bufs, nbufs, off);
   }
 
-done:
-#if defined(__APPLE__)
-  if (pthread_mutex_unlock(&lock))
-    abort();
-#endif
-
   return r;
 }
 
+
 static ssize_t uv__fs_copyfile(uv_fs_t* req) {
   uv_fs_t fs_req;
   uv_file srcfd;
@@ -1981,9 +1878,14 @@
   if (bufs == NULL || nbufs == 0)
     return UV_EINVAL;
 
+  req->off = off;
   req->file = file;
-
+  req->bufs = (uv_buf_t*) bufs;  /* Safe, doesn't mutate |bufs| */
   req->nbufs = nbufs;
+
+  if (cb == NULL)
+    goto post;
+
   req->bufs = req->bufsml;
   if (nbufs > ARRAY_SIZE(req->bufsml))
     req->bufs = (uv_buf_t*)uv__malloc(nbufs * sizeof(*bufs));
@@ -1993,12 +1895,10 @@
 
   memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
 
-  req->off = off;
+  if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
+    return 0;
 
-  if (cb != NULL)
-    if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
-      return 0;
-
+post:
   POST;
 }
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp
index ffe0f91..939a426 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/kqueue.cpp
@@ -30,6 +30,9 @@
 #include <sys/types.h>
 #include <sys/event.h>
 #include <sys/time.h>
+#if defined(__FreeBSD__)
+#include <sys/user.h>
+#endif
 #include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
@@ -264,6 +267,9 @@
 
     if (nfds == -1)
       assert(errno == EINTR);
+    else if (nfds == 0)
+      /* Unlimited timeout should only return with events or signal. */
+      assert(timeout != -1);
 
     if (pset != NULL)
       pthread_sigmask(SIG_UNBLOCK, pset, NULL);
@@ -288,8 +294,6 @@
         timeout = user_timeout;
         reset_timeout = 0;
       } else if (nfds == 0) {
-        /* Reached the user timeout value. */
-        assert(timeout != -1);
         return;
       }
 
@@ -481,6 +485,16 @@
    */
   if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0)
     path = uv__basename_r(pathbuf);
+#elif defined(F_KINFO)
+  /* We try to get the file info reference from the file descriptor.
+   * the struct's kf_structsize must be initialised beforehand
+   * whether with the KINFO_FILE_SIZE constant or this way.
+   */
+  struct kinfo_file kf;
+  kf.kf_structsize = sizeof(kf);
+
+  if (fcntl(handle->event_watcher.fd, F_KINFO, &kf) == 0)
+    path = uv__basename_r(kf.kf_path);
 #endif
   handle->cb(handle, path, events, 0);
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux.cpp
index d365b62..95a2fe2 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/linux.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/linux.cpp
@@ -78,6 +78,8 @@
 #  define __NR_copy_file_range 379
 # elif defined(__arc__)
 #  define __NR_copy_file_range 285
+# elif defined(__riscv)
+#  define __NR_copy_file_range 285
 # endif
 #endif /* __NR_copy_file_range */
 
@@ -94,6 +96,8 @@
 #  define __NR_statx 383
 # elif defined(__s390__)
 #  define __NR_statx 379
+# elif defined(__riscv)
+#  define __NR_statx 291
 # endif
 #endif /* __NR_statx */
 
@@ -110,6 +114,8 @@
 #  define __NR_getrandom 359
 # elif defined(__s390__)
 #  define __NR_getrandom 349
+# elif defined(__riscv)
+#  define __NR_getrandom 278
 # endif
 #endif /* __NR_getrandom */
 
@@ -318,17 +324,64 @@
   unsigned major;
   unsigned minor;
   unsigned patch;
+  char v_sig[256];
+  char* needle;
 
   version = std::atomic_load_explicit(&cached_version, std::memory_order_relaxed);
   if (version != 0)
     return version;
 
+  /* Check /proc/version_signature first as it's the way to get the mainline
+   * kernel version in Ubuntu. The format is:
+   *   Ubuntu ubuntu_kernel_version mainline_kernel_version
+   * For example:
+   *   Ubuntu 5.15.0-79.86-generic 5.15.111
+   */
+  if (0 == uv__slurp("/proc/version_signature", v_sig, sizeof(v_sig)))
+    if (3 == sscanf(v_sig, "Ubuntu %*s %u.%u.%u", &major, &minor, &patch))
+      goto calculate_version;
+
   if (-1 == uname(&u))
     return 0;
 
+  /* In Debian we need to check `version` instead of `release` to extract the
+   * mainline kernel version. This is an example of how it looks like:
+   *  #1 SMP Debian 5.10.46-4 (2021-08-03)
+   */
+  needle = strstr(u.version, "Debian ");
+  if (needle != NULL)
+    if (3 == sscanf(needle, "Debian %u.%u.%u", &major, &minor, &patch))
+      goto calculate_version;
+
   if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))
     return 0;
 
+  /* Handle it when the process runs under the UNAME26 personality:
+   *
+   * - kernels >= 3.x identify as 2.6.40+x
+   * - kernels >= 4.x identify as 2.6.60+x
+   *
+   * UNAME26 is a poorly conceived hack that doesn't let us distinguish
+   * between 4.x kernels and 5.x/6.x kernels so we conservatively assume
+   * that 2.6.60+x means 4.x.
+   *
+   * Fun fact of the day: it's technically possible to observe the actual
+   * kernel version for a brief moment because uname() first copies out the
+   * real release string before overwriting it with the backcompat string.
+   */
+  if (major == 2 && minor == 6) {
+    if (patch >= 60) {
+      major = 4;
+      minor = patch - 60;
+      patch = 0;
+    } else if (patch >= 40) {
+      major = 3;
+      minor = patch - 40;
+      patch = 0;
+    }
+  }
+
+calculate_version:
   version = major * 65536 + minor * 256 + patch;
   std::atomic_store_explicit(&cached_version, version, std::memory_order_relaxed);
 
@@ -423,6 +476,9 @@
 static int uv__use_io_uring(void) {
 #if defined(__ANDROID_API__)
   return 0;  /* Possibly available but blocked by seccomp. */
+#elif defined(__arm__) && __SIZEOF_POINTER__ == 4
+  /* See https://github.com/libuv/libuv/issues/4158. */
+  return 0;  /* All 32 bits kernels appear buggy. */
 #else
   /* Ternary: unknown=0, yes=1, no=-1 */
   static std::atomic<int> use_io_uring;
@@ -432,8 +488,14 @@
   use = std::atomic_load_explicit(&use_io_uring, std::memory_order_relaxed);
 
   if (use == 0) {
+    /* Older kernels have a bug where the sqpoll thread uses 100% CPU. */
+    use = uv__kernel_version() >= /* 5.10.186 */ 0x050ABA ? 1 : -1;
+
+    /* But users can still enable it if they so desire. */
     val = getenv("UV_USE_IO_URING");
-    use = val == NULL || atoi(val) ? 1 : -1;
+    if (val != NULL)
+      use = atoi(val) ? 1 : -1;
+
     std::atomic_store_explicit(&use_io_uring, use, std::memory_order_relaxed);
   }
 
@@ -757,7 +819,9 @@
 int uv__iou_fs_close(uv_loop_t* loop, uv_fs_t* req) {
   struct uv__io_uring_sqe* sqe;
   struct uv__iou* iou;
+  int kv;
 
+  kv = uv__kernel_version();
   /* Work around a poorly understood bug in older kernels where closing a file
    * descriptor pointing to /foo/bar results in ETXTBSY errors when trying to
    * execve("/foo/bar") later on. The bug seems to have been fixed somewhere
@@ -765,10 +829,17 @@
    * but good candidates are the several data race fixes. Interestingly, it
    * seems to manifest only when running under Docker so the possibility of
    * a Docker bug can't be completely ruled out either. Yay, computers.
+   * Also, disable on non-longterm versions between 5.16.0 (non-longterm) and
+   * 6.1.0 (longterm). Starting with longterm 6.1.x, the issue seems to be
+   * solved.
    */
-  if (uv__kernel_version() < /* 5.15.90 */ 0x050F5A)
+  if (kv < /* 5.15.90 */ 0x050F5A)
     return 0;
 
+  if (kv >= /* 5.16.0 */ 0x050A00 && kv < /* 6.1.0 */ 0x060100)
+    return 0;
+
+
   iou = &uv__get_internal_fields(loop)->iou;
 
   sqe = uv__iou_get_sqe(iou, loop, req);
@@ -1365,41 +1436,20 @@
      */
     SAVE_ERRNO(uv__update_time(loop));
 
-    if (nfds == 0) {
+    if (nfds == -1)
+      assert(errno == EINTR);
+    else if (nfds == 0)
+      /* Unlimited timeout should only return with events or signal. */
       assert(timeout != -1);
 
+    if (nfds == 0 || nfds == -1) {
       if (reset_timeout != 0) {
         timeout = user_timeout;
         reset_timeout = 0;
+      } else if (nfds == 0) {
+        return;
       }
 
-      if (timeout == -1)
-        continue;
-
-      if (timeout == 0)
-        break;
-
-      /* We may have been inside the system call for longer than |timeout|
-       * milliseconds so we need to update the timestamp to avoid drift.
-       */
-      goto update_timeout;
-    }
-
-    if (nfds == -1) {
-      if (errno != EINTR)
-        abort();
-
-      if (reset_timeout != 0) {
-        timeout = user_timeout;
-        reset_timeout = 0;
-      }
-
-      if (timeout == -1)
-        continue;
-
-      if (timeout == 0)
-        break;
-
       /* Interrupted by a signal. Update timeout and poll again. */
       goto update_timeout;
     }
@@ -1510,13 +1560,13 @@
       break;
     }
 
+update_timeout:
     if (timeout == 0)
       break;
 
     if (timeout == -1)
       continue;
 
-update_timeout:
     assert(timeout > 0);
 
     real_timeout -= (loop->time - base);
@@ -1719,11 +1769,8 @@
     return UV__ERR(errno);
   }
 
-  /* Skip first line. */
-  if (!fgets(buf, sizeof(buf), fp)) {
-    uv__free(cpus);
-    return UV__ERR(errno);
-  }
+  if (NULL == fgets(buf, sizeof(buf), fp))
+    abort();
 
   for (;;) {
     memset(&t, 0, sizeof(t));
@@ -1734,10 +1781,8 @@
     if (n != 7)
       break;
 
-    /* Skip rest of line. */
-    if (!fgets(buf, sizeof(buf), fp)) {
-      break;
-    }
+    if (NULL == fgets(buf, sizeof(buf), fp))
+      abort();
 
     if (cpu >= ARRAY_SIZE(*cpus))
       continue;
@@ -1817,9 +1862,8 @@
     if (fp == NULL)
       continue;
 
-    if (0 > fscanf(fp, "%llu", &(*cpus)[cpu].freq)) {
-      (*cpus)[cpu].freq = 0llu;
-    }
+    if (1 != fscanf(fp, "%llu", &(*cpus)[cpu].freq))
+      abort();
     fclose(fp);
     fp = NULL;
   }
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp
index 63aba5a..bc4206e 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/signal.cpp
@@ -279,6 +279,8 @@
 
 
 int uv__signal_loop_fork(uv_loop_t* loop) {
+  struct uv__queue* q;
+
   if (loop->signal_pipefd[0] == -1)
     return 0;
   uv__io_stop(loop, &loop->signal_io_watcher, POLLIN);
@@ -286,6 +288,19 @@
   uv__close(loop->signal_pipefd[1]);
   loop->signal_pipefd[0] = -1;
   loop->signal_pipefd[1] = -1;
+
+  uv__queue_foreach(q, &loop->handle_queue) {
+    uv_handle_t* handle = uv__queue_data(q, uv_handle_t, handle_queue);
+    uv_signal_t* sh;
+
+    if (handle->type != UV_SIGNAL)
+      continue;
+
+    sh = (uv_signal_t*) handle;
+    sh->caught_signals = 0;
+    sh->dispatched_signals = 0;
+  }
+
   return uv__signal_loop_once_init(loop);
 }
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp
index d6c848f..4c4213a 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/tcp.cpp
@@ -27,6 +27,17 @@
 #include <assert.h>
 #include <errno.h>
 
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#if defined(__PASE__)
+#include <as400_protos.h>
+#define ifaddrs ifaddrs_pase
+#define getifaddrs Qp2getifaddrs
+#define freeifaddrs Qp2freeifaddrs
+#else
+#include <ifaddrs.h>
+#endif
 
 static int maybe_bind_socket(int fd) {
   union uv__sockaddr s;
@@ -198,11 +209,50 @@
 }
 
 
+static int uv__is_ipv6_link_local(const struct sockaddr* addr) {
+  const struct sockaddr_in6* a6;
+  uint8_t b[2];
+
+  if (addr->sa_family != AF_INET6)
+    return 0;
+
+  a6 = (const struct sockaddr_in6*) addr;
+  memcpy(b, &a6->sin6_addr, sizeof(b));
+
+  return b[0] == 0xFE && b[1] == 0x80;
+}
+
+
+static int uv__ipv6_link_local_scope_id(void) {
+  struct sockaddr_in6* a6;
+  struct ifaddrs* ifa;
+  struct ifaddrs* p;
+  int rv;
+
+  if (getifaddrs(&ifa))
+    return 0;
+
+  for (p = ifa; p != NULL; p = p->ifa_next)
+    if (uv__is_ipv6_link_local(p->ifa_addr))
+      break;
+
+  rv = 0;
+  if (p != NULL) {
+    a6 = (struct sockaddr_in6*) p->ifa_addr;
+    rv = a6->sin6_scope_id;
+  }
+
+  freeifaddrs(ifa);
+  return rv;
+}
+
+
 int uv__tcp_connect(uv_connect_t* req,
                     uv_tcp_t* handle,
                     const struct sockaddr* addr,
                     unsigned int addrlen,
                     uv_connect_cb cb) {
+  struct sockaddr_in6 tmp6;
   int err;
   int r;
 
@@ -220,6 +270,14 @@
   if (err)
     return err;
 
+  if (uv__is_ipv6_link_local(addr)) {
+    memcpy(&tmp6, addr, sizeof(tmp6));
+    if (tmp6.sin6_scope_id == 0) {
+      tmp6.sin6_scope_id = uv__ipv6_link_local_scope_id();
+      addr = (const struct sockaddr*) &tmp6;
+    }
+  }
+
   do {
     errno = 0;
     r = connect(uv__stream_fd(handle), addr, addrlen);
@@ -374,28 +432,39 @@
 
 
 int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
+  int intvl;
+  int cnt;
+
+  (void) &intvl;
+  (void) &cnt;
+    
   if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
     return UV__ERR(errno);
 
+  if (!on)
+    return 0;
+
 #ifdef TCP_KEEPIDLE
-  if (on) {
-    int intvl = 1;  /*  1 second; same as default on Win32 */
-    int cnt = 10;  /* 10 retries; same as hardcoded on Win32 */
-    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
-      return UV__ERR(errno);
-    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
-      return UV__ERR(errno);
-    if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
-      return UV__ERR(errno);
-  }
+  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
+    return UV__ERR(errno);
+/* Solaris/SmartOS, if you don't support keep-alive,
+ * then don't advertise it in your system headers...
+ */
+/* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
+#elif defined(TCP_KEEPALIVE) && !defined(__sun)
+  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
+    return UV__ERR(errno);
 #endif
 
-  /* Solaris/SmartOS, if you don't support keep-alive,
-   * then don't advertise it in your system headers...
-   */
-  /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
-#if defined(TCP_KEEPALIVE) && !defined(__sun)
-  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
+#ifdef TCP_KEEPINTVL
+  intvl = 1;  /*  1 second; same as default on Win32 */
+  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
+    return UV__ERR(errno);
+#endif
+
+#ifdef TCP_KEEPCNT
+  cnt = 10;  /* 10 retries; same as hardcoded on Win32 */
+  if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
     return UV__ERR(errno);
 #endif
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp b/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp
index f860094..688c042 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/unix/thread.cpp
@@ -782,11 +782,33 @@
     abort();
 }
 
+#if defined(__APPLE__) && defined(__MACH__)
+
+void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
+  int r;
+
+  errno = 0;
+  r = pthread_cond_wait(cond, mutex);
+
+  /* Workaround for a bug in OS X at least up to 13.6
+   * See https://github.com/libuv/libuv/issues/4165
+   */
+  if (r == EINVAL)
+    if (errno == EBUSY)
+      return;
+
+  if (r)
+    abort();
+}
+
+#else /* !(defined(__APPLE__) && defined(__MACH__)) */
+
 void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
   if (pthread_cond_wait(cond, mutex))
     abort();
 }
 
+#endif
 
 int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
   int r;
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp b/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp
index 5c6d841..1ce25c2 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/uv-common.cpp
@@ -559,6 +559,9 @@
   if (loop == NULL)
     loop = uv_default_loop();
 
+  if (stream == NULL)
+    stream = stderr;
+
   uv__queue_foreach(q, &loop->handle_queue) {
     h = uv__queue_data(q, uv_handle_t, handle_queue);
 
@@ -799,7 +802,6 @@
   }
 }
 
-
 #ifdef __clang__
 # pragma clang diagnostic push
 # pragma clang diagnostic ignored "-Wvarargs"
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/dl.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/dl.cpp
index 676be4d..d88400f 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/dl.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/dl.cpp
@@ -27,18 +27,17 @@
 
 int uv_dlopen(const char* filename, uv_lib_t* lib) {
   WCHAR filename_w[32768];
+  ssize_t r;
 
   lib->handle = NULL;
   lib->errmsg = NULL;
 
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           filename,
-                           -1,
-                           filename_w,
-                           ARRAY_SIZE(filename_w))) {
-    return uv__dlerror(lib, filename, GetLastError());
-  }
+  r = uv_wtf8_length_as_utf16(filename);
+  if (r < 0)
+    return uv__dlerror(lib, filename, ERROR_NO_UNICODE_TRANSLATION);
+  if ((size_t) r > ARRAY_SIZE(filename_w))
+    return uv__dlerror(lib, filename, ERROR_INSUFFICIENT_BUFFER);
+  uv_wtf8_to_utf16(filename, (uint16_t*)filename_w, r);
 
   lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
   if (lib->handle == NULL) {
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/fs-event.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/fs-event.cpp
index 3244a4e..381220b 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/fs-event.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/fs-event.cpp
@@ -159,7 +159,8 @@
                       uv_fs_event_cb cb,
                       const char* path,
                       unsigned int flags) {
-  int name_size, is_path_dir, size;
+  int is_path_dir;
+  size_t size;
   DWORD attr, last_error;
   WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
   DWORD short_path_buffer_len;
@@ -178,23 +179,9 @@
 
   uv__handle_start(handle);
 
-  /* Convert name to UTF16. */
-
-  name_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) *
-              sizeof(WCHAR);
-  pathw = (WCHAR*)uv__malloc(name_size);
-  if (!pathw) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           path,
-                           -1,
-                           pathw,
-                           name_size / sizeof(WCHAR))) {
-    return uv_translate_sys_error(GetLastError());
-  }
+  last_error = uv__convert_utf8_to_utf16(path, &pathw);
+  if (last_error)
+    goto error_uv;
 
   /* Determine whether path is a file or a directory. */
   attr = GetFileAttributesW(pathw);
@@ -335,6 +322,9 @@
   return 0;
 
 error:
+  last_error = uv_translate_sys_error(last_error);
+
+error_uv:
   if (handle->path) {
     uv__free(handle->path);
     handle->path = NULL;
@@ -367,7 +357,7 @@
 
   uv__free(short_path);
 
-  return uv_translate_sys_error(last_error);
+  return last_error;
 }
 
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp
index f415ddc..26ba539 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/fs.cpp
@@ -33,13 +33,16 @@
 #include <stdio.h>
 
 #include "uv.h"
+
+/* <winioctl.h> requires <windows.h>, included via "uv.h" above, but needs to
+   be included before our "winapi.h", included via "internal.h" below. */
+#include <winioctl.h>
+
 #include "internal.h"
 #include "req-inl.h"
 #include "handle-inl.h"
 #include "fs-fd-hash-inl.h"
 
-#include <winioctl.h>
-
 #pragma comment(lib, "Advapi32.lib")
 
 #define UV_FS_FREE_PATHS         0x0002
@@ -147,279 +150,6 @@
 }
 
 
-static int32_t fs__decode_wtf8_char(const char** input) {
-  uint32_t code_point;
-  uint8_t b1;
-  uint8_t b2;
-  uint8_t b3;
-  uint8_t b4;
-
-  b1 = **input;
-  if (b1 <= 0x7F)
-    return b1; /* ASCII code point */
-  if (b1 < 0xC2)
-    return -1; /* invalid: continuation byte */
-  code_point = b1;
-
-  b2 = *++*input;
-  if ((b2 & 0xC0) != 0x80)
-    return -1; /* invalid: not a continuation byte */
-  code_point = (code_point << 6) | (b2 & 0x3F);
-  if (b1 <= 0xDF)
-    return 0x7FF & code_point; /* two-byte character */
-
-  b3 = *++*input;
-  if ((b3 & 0xC0) != 0x80)
-    return -1; /* invalid: not a continuation byte */
-  code_point = (code_point << 6) | (b3 & 0x3F);
-  if (b1 <= 0xEF)
-    return 0xFFFF & code_point; /* three-byte character */
-
-  b4 = *++*input;
-  if ((b4 & 0xC0) != 0x80)
-    return -1; /* invalid: not a continuation byte */
-  code_point = (code_point << 6) | (b4 & 0x3F);
-  if (b1 <= 0xF4)
-    if (code_point <= 0x10FFFF)
-      return code_point; /* four-byte character */
-
-  /* code point too large */
-  return -1;
-}
-
-
-static ssize_t fs__get_length_wtf8(const char* source_ptr) {
-  size_t w_target_len = 0;
-  int32_t code_point;
-
-  do {
-    code_point = fs__decode_wtf8_char(&source_ptr);
-    if (code_point < 0)
-      return -1;
-    if (code_point > 0xFFFF)
-      w_target_len++;
-    w_target_len++;
-  } while (*source_ptr++);
-  return w_target_len;
-}
-
-
-static void fs__wtf8_to_wide(const char* source_ptr, WCHAR* w_target) {
-  int32_t code_point;
-
-  do {
-    code_point = fs__decode_wtf8_char(&source_ptr);
-    /* fs__get_length_wtf8 should have been called and checked first. */
-    assert(code_point >= 0);
-    if (code_point > 0x10000) {
-      assert(code_point < 0x10FFFF);
-      *w_target++ = (((code_point - 0x10000) >> 10) + 0xD800);
-      *w_target++ = ((code_point - 0x10000) & 0x3FF) + 0xDC00;
-    } else {
-      *w_target++ = code_point;
-    }
-  } while (*source_ptr++);
-}
-
-
-INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
-    const char* new_path, const int copy_path) {
-  WCHAR* buf;
-  WCHAR* pos;
-  size_t buf_sz = 0;
-  size_t path_len = 0;
-  ssize_t pathw_len = 0;
-  ssize_t new_pathw_len = 0;
-
-  /* new_path can only be set if path is also set. */
-  assert(new_path == NULL || path != NULL);
-
-  if (path != NULL) {
-    pathw_len = fs__get_length_wtf8(path);
-    if (pathw_len < 0)
-      return ERROR_INVALID_NAME;
-    buf_sz += pathw_len * sizeof(WCHAR);
-  }
-
-  if (path != NULL && copy_path) {
-    path_len = 1 + strlen(path);
-    buf_sz += path_len;
-  }
-
-  if (new_path != NULL) {
-    new_pathw_len = fs__get_length_wtf8(new_path);
-    if (new_pathw_len < 0)
-      return ERROR_INVALID_NAME;
-    buf_sz += new_pathw_len * sizeof(WCHAR);
-  }
-
-
-  if (buf_sz == 0) {
-    req->file.pathw = NULL;
-    req->fs.info.new_pathw = NULL;
-    req->path = NULL;
-    return 0;
-  }
-
-  buf = (WCHAR *)uv__malloc(buf_sz);
-  if (buf == NULL) {
-    return ERROR_OUTOFMEMORY;
-  }
-
-  pos = buf;
-
-  if (path != NULL) {
-    fs__wtf8_to_wide(path, pos);
-    req->file.pathw = pos;
-    pos += pathw_len;
-  } else {
-    req->file.pathw = NULL;
-  }
-
-  if (new_path != NULL) {
-    fs__wtf8_to_wide(new_path, pos);
-    req->fs.info.new_pathw = pos;
-    pos += new_pathw_len;
-  } else {
-    req->fs.info.new_pathw = NULL;
-  }
-
-  req->path = path;
-  if (path != NULL && copy_path) {
-    memcpy(pos, path, path_len);
-    assert(path_len == buf_sz - (pos - buf) * sizeof(WCHAR));
-    req->path = (char*) pos;
-  }
-
-  req->flags |= UV_FS_FREE_PATHS;
-
-  return 0;
-}
-
-
-
-INLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req,
-    uv_fs_type fs_type, const uv_fs_cb cb) {
-  uv__once_init();
-  UV_REQ_INIT(req, UV_FS);
-  req->loop = loop;
-  req->flags = 0;
-  req->fs_type = fs_type;
-  req->sys_errno_ = 0;
-  req->result = 0;
-  req->ptr = NULL;
-  req->path = NULL;
-  req->cb = cb;
-  memset(&req->fs, 0, sizeof(req->fs));
-}
-
-
-static int32_t fs__get_surrogate_value(const WCHAR* w_source_ptr,
-                                       size_t w_source_len) {
-  WCHAR u;
-  WCHAR next;
-
-  u = w_source_ptr[0];
-  if (u >= 0xD800 && u <= 0xDBFF && w_source_len > 1) {
-    next = w_source_ptr[1];
-    if (next >= 0xDC00 && next <= 0xDFFF)
-      return 0x10000 + ((u - 0xD800) << 10) + (next - 0xDC00);
-  }
-  return u;
-}
-
-
-static size_t fs__get_length_wide(const WCHAR* w_source_ptr,
-                                  size_t w_source_len) {
-  size_t target_len;
-  int32_t code_point;
-
-  target_len = 0;
-  for (; w_source_len; w_source_len--, w_source_ptr++) {
-    code_point = fs__get_surrogate_value(w_source_ptr, w_source_len);
-    /* Can be invalid UTF-8 but must be valid WTF-8. */
-    assert(code_point >= 0);
-    if (code_point < 0x80)
-      target_len += 1;
-    else if (code_point < 0x800)
-      target_len += 2;
-    else if (code_point < 0x10000)
-      target_len += 3;
-    else {
-      target_len += 4;
-      w_source_ptr++;
-      w_source_len--;
-    }
-  }
-  return target_len;
-}
-
-
-static int fs__wide_to_wtf8(WCHAR* w_source_ptr,
-                            size_t w_source_len,
-                            char** target_ptr,
-                            size_t* target_len_ptr) {
-  size_t target_len;
-  char* target;
-  int32_t code_point;
-
-  /* If *target_ptr is provided, then *target_len_ptr must be its length
-   * (excluding space for null), otherwise we will compute the target_len_ptr
-   * length and may return a new allocation in *target_ptr if target_ptr is
-   * provided. */
-  if (target_ptr == NULL || *target_ptr == NULL) {
-    target_len = fs__get_length_wide(w_source_ptr, w_source_len);
-    if (target_len_ptr != NULL)
-      *target_len_ptr = target_len;
-  } else {
-    target_len = *target_len_ptr;
-  }
-
-  if (target_ptr == NULL)
-    return 0;
-
-  if (*target_ptr == NULL) {
-    target = (char *)uv__malloc(target_len + 1);
-    if (target == NULL) {
-      SetLastError(ERROR_OUTOFMEMORY);
-      return -1;
-    }
-    *target_ptr = target;
-  } else {
-    target = *target_ptr;
-  }
-
-  for (; w_source_len; w_source_len--, w_source_ptr++) {
-    code_point = fs__get_surrogate_value(w_source_ptr, w_source_len);
-    /* Can be invalid UTF-8 but must be valid WTF-8. */
-    assert(code_point >= 0);
-
-    if (code_point < 0x80) {
-      *target++ = code_point;
-    } else if (code_point < 0x800) {
-      *target++ = 0xC0 | (code_point >> 6);
-      *target++ = 0x80 | (code_point & 0x3F);
-    } else if (code_point < 0x10000) {
-      *target++ = 0xE0 | (code_point >> 12);
-      *target++ = 0x80 | ((code_point >> 6) & 0x3F);
-      *target++ = 0x80 | (code_point & 0x3F);
-    } else {
-      *target++ = 0xF0 | (code_point >> 18);
-      *target++ = 0x80 | ((code_point >> 12) & 0x3F);
-      *target++ = 0x80 | ((code_point >> 6) & 0x3F);
-      *target++ = 0x80 | (code_point & 0x3F);
-      w_source_ptr++;
-      w_source_len--;
-    }
-  }
-  assert((size_t) (target - *target_ptr) == target_len);
-
-  *target++ = '\0';
-
-  return 0;
-}
-
-
 INLINE static int fs__readlink_handle(HANDLE handle,
                                       char** target_ptr,
                                       size_t* target_len_ptr) {
@@ -553,7 +283,98 @@
   }
 
   assert(target_ptr == NULL || *target_ptr == NULL);
-  return fs__wide_to_wtf8(w_target, w_target_len, target_ptr, target_len_ptr);
+  return uv_utf16_to_wtf8((const uint16_t*)w_target, w_target_len, target_ptr, target_len_ptr);
+}
+
+
+INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
+    const char* new_path, const int copy_path) {
+  WCHAR* buf;
+  WCHAR* pos;
+  size_t buf_sz = 0;
+  size_t path_len = 0;
+  ssize_t pathw_len = 0;
+  ssize_t new_pathw_len = 0;
+
+  /* new_path can only be set if path is also set. */
+  assert(new_path == NULL || path != NULL);
+
+  if (path != NULL) {
+    pathw_len = uv_wtf8_length_as_utf16(path);
+    if (pathw_len < 0)
+      return ERROR_INVALID_NAME;
+    buf_sz += pathw_len * sizeof(WCHAR);
+  }
+
+  if (path != NULL && copy_path) {
+    path_len = 1 + strlen(path);
+    buf_sz += path_len;
+  }
+
+  if (new_path != NULL) {
+    new_pathw_len = uv_wtf8_length_as_utf16(new_path);
+    if (new_pathw_len < 0)
+      return ERROR_INVALID_NAME;
+    buf_sz += new_pathw_len * sizeof(WCHAR);
+  }
+
+
+  if (buf_sz == 0) {
+    req->file.pathw = NULL;
+    req->fs.info.new_pathw = NULL;
+    req->path = NULL;
+    return 0;
+  }
+
+  buf = (WCHAR*)uv__malloc(buf_sz);
+  if (buf == NULL) {
+    return ERROR_OUTOFMEMORY;
+  }
+
+  pos = buf;
+
+  if (path != NULL) {
+    uv_wtf8_to_utf16(path, (uint16_t*)pos, pathw_len);
+    req->file.pathw = pos;
+    pos += pathw_len;
+  } else {
+    req->file.pathw = NULL;
+  }
+
+  if (new_path != NULL) {
+    uv_wtf8_to_utf16(new_path, (uint16_t*)pos, new_pathw_len);
+    req->fs.info.new_pathw = pos;
+    pos += new_pathw_len;
+  } else {
+    req->fs.info.new_pathw = NULL;
+  }
+
+  req->path = path;
+  if (path != NULL && copy_path) {
+    memcpy(pos, path, path_len);
+    assert(path_len == buf_sz - (pos - buf) * sizeof(WCHAR));
+    req->path = (char*) pos;
+  }
+
+  req->flags |= UV_FS_FREE_PATHS;
+
+  return 0;
+}
+
+
+INLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req,
+    uv_fs_type fs_type, const uv_fs_cb cb) {
+  uv__once_init();
+  UV_REQ_INIT(req, UV_FS);
+  req->loop = loop;
+  req->flags = 0;
+  req->fs_type = fs_type;
+  req->sys_errno_ = 0;
+  req->result = 0;
+  req->ptr = NULL;
+  req->path = NULL;
+  req->cb = cb;
+  memset(&req->fs, 0, sizeof(req->fs));
 }
 
 
@@ -1572,7 +1393,7 @@
         continue;
 
       /* Compute the space required to store the filename as WTF-8. */
-      wtf8_len = fs__get_length_wide(&info->FileName[0], wchar_len);
+      wtf8_len = uv_utf16_length_as_wtf8((const uint16_t*)&info->FileName[0], wchar_len);
 
       /* Resize the dirent array if needed. */
       if (dirents_used >= dirents_size) {
@@ -1600,8 +1421,8 @@
 
       /* Convert file name to UTF-8. */
       wtf8 = &dirent->d_name[0];
-      if (fs__wide_to_wtf8(&info->FileName[0], wchar_len, &wtf8, &wtf8_len) == -1)
-        goto win32_error;
+      if (uv_utf16_to_wtf8((const uint16_t*)&info->FileName[0], wchar_len, &wtf8, &wtf8_len) != 0)
+        goto out_of_memory_error;
 
       /* Fill out the type field. */
       if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)
@@ -2827,7 +2648,7 @@
   }
 
   assert(*realpath_ptr == NULL);
-  r = fs__wide_to_wtf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
+  r = uv_utf16_to_wtf8((const uint16_t*)w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
   uv__free(w_realpath_buf);
   return r;
 }
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/getaddrinfo.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/getaddrinfo.cpp
index dfab860..5bc63d8 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/getaddrinfo.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/getaddrinfo.cpp
@@ -104,13 +104,14 @@
  */
 static void uv__getaddrinfo_done(struct uv__work* w, int status) {
   uv_getaddrinfo_t* req;
-  int addrinfo_len = 0;
-  int name_len = 0;
+  size_t addrinfo_len = 0;
+  ssize_t name_len = 0;
   size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
   struct addrinfoW* addrinfow_ptr;
   struct addrinfo* addrinfo_ptr;
   char* alloc_ptr = NULL;
   char* cur_ptr = NULL;
+  int r;
 
   req = container_of(w, uv_getaddrinfo_t, work_req);
 
@@ -131,19 +132,12 @@
       addrinfo_len += addrinfo_struct_len +
           ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
       if (addrinfow_ptr->ai_canonname != NULL) {
-        name_len = WideCharToMultiByte(CP_UTF8,
-                                       0,
-                                       addrinfow_ptr->ai_canonname,
-                                       -1,
-                                       NULL,
-                                       0,
-                                       NULL,
-                                       NULL);
-        if (name_len == 0) {
-          req->retcode = uv_translate_sys_error(GetLastError());
+        name_len = uv_utf16_length_as_wtf8((const uint16_t*)addrinfow_ptr->ai_canonname, -1);
+        if (name_len < 0) {
+          req->retcode = name_len;
           goto complete;
         }
-        addrinfo_len += ALIGNED_SIZE(name_len);
+        addrinfo_len += ALIGNED_SIZE(name_len + 1);
       }
       addrinfow_ptr = addrinfow_ptr->ai_next;
     }
@@ -182,27 +176,14 @@
 
         /* convert canonical name to UTF-8 */
         if (addrinfow_ptr->ai_canonname != NULL) {
-          name_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         addrinfow_ptr->ai_canonname,
-                                         -1,
-                                         NULL,
-                                         0,
-                                         NULL,
-                                         NULL);
-          assert(name_len > 0);
-          assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
-          name_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         addrinfow_ptr->ai_canonname,
-                                         -1,
-                                         cur_ptr,
-                                         name_len,
-                                         NULL,
-                                         NULL);
-          assert(name_len > 0);
+          name_len = alloc_ptr + addrinfo_len - cur_ptr;
+          r = uv__copy_utf16_to_utf8(addrinfow_ptr->ai_canonname,
+                                     -1,
+                                     cur_ptr,
+                                     (size_t*)&name_len);
+          assert(r == 0);
           addrinfo_ptr->ai_canonname = cur_ptr;
-          cur_ptr += ALIGNED_SIZE(name_len);
+          cur_ptr += ALIGNED_SIZE(name_len + 1);
         }
         assert(cur_ptr <= alloc_ptr + addrinfo_len);
 
@@ -261,12 +242,11 @@
                    const char* service,
                    const struct addrinfo* hints) {
   char hostname_ascii[256];
-  int nodesize = 0;
-  int servicesize = 0;
-  int hintssize = 0;
+  size_t nodesize = 0;
+  size_t servicesize = 0;
+  size_t hintssize = 0;
   char* alloc_ptr = NULL;
-  int err;
-  long rc;
+  ssize_t rc;
 
   if (req == NULL || (node == NULL && service == NULL)) {
     return UV_EINVAL;
@@ -286,56 +266,36 @@
                           hostname_ascii + sizeof(hostname_ascii));
     if (rc < 0)
       return rc;
-    nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
-                                                -1, NULL, 0) * sizeof(WCHAR));
-    if (nodesize == 0) {
-      err = GetLastError();
-      goto error;
-    }
+    nodesize = strlen(hostname_ascii) + 1;
     node = hostname_ascii;
   }
 
   if (service != NULL) {
-    servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,
-                                                   0,
-                                                   service,
-                                                   -1,
-                                                   NULL,
-                                                   0) *
-                               sizeof(WCHAR));
-    if (servicesize == 0) {
-      err = GetLastError();
-      goto error;
-    }
+    rc = uv_wtf8_length_as_utf16(service);
+    if (rc < 0)
+       return rc;
+    servicesize = rc;
   }
   if (hints != NULL) {
     hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
   }
 
   /* allocate memory for inputs, and partition it as needed */
-  alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
-  if (!alloc_ptr) {
-    err = WSAENOBUFS;
-    goto error;
-  }
+  alloc_ptr = (char*)uv__malloc(ALIGNED_SIZE(nodesize * sizeof(WCHAR)) +
+                                ALIGNED_SIZE(servicesize * sizeof(WCHAR)) +
+                                hintssize);
+  if (!alloc_ptr)
+    return UV_ENOMEM;
 
   /* save alloc_ptr now so we can free if error */
-  req->alloc = (void*)alloc_ptr;
+  req->alloc = (void*) alloc_ptr;
 
   /* Convert node string to UTF16 into allocated memory and save pointer in the
-   * request. */
+   * request. The node here has been converted to ascii. */
   if (node != NULL) {
-    req->node = (WCHAR*)alloc_ptr;
-    if (MultiByteToWideChar(CP_UTF8,
-                            0,
-                            node,
-                            -1,
-                            (WCHAR*) alloc_ptr,
-                            nodesize / sizeof(WCHAR)) == 0) {
-      err = GetLastError();
-      goto error;
-    }
-    alloc_ptr += nodesize;
+    req->node = (WCHAR*) alloc_ptr;
+    uv_wtf8_to_utf16(node, (uint16_t*) alloc_ptr, nodesize);
+    alloc_ptr += ALIGNED_SIZE(nodesize * sizeof(WCHAR));
   } else {
     req->node = NULL;
   }
@@ -343,24 +303,16 @@
   /* Convert service string to UTF16 into allocated memory and save pointer in
    * the req. */
   if (service != NULL) {
-    req->service = (WCHAR*)alloc_ptr;
-    if (MultiByteToWideChar(CP_UTF8,
-                            0,
-                            service,
-                            -1,
-                            (WCHAR*) alloc_ptr,
-                            servicesize / sizeof(WCHAR)) == 0) {
-      err = GetLastError();
-      goto error;
-    }
-    alloc_ptr += servicesize;
+    req->service = (WCHAR*) alloc_ptr;
+    uv_wtf8_to_utf16(service, (uint16_t*) alloc_ptr, servicesize);
+    alloc_ptr += ALIGNED_SIZE(servicesize * sizeof(WCHAR));
   } else {
     req->service = NULL;
   }
 
   /* copy hints to allocated memory and save pointer in req */
   if (hints != NULL) {
-    req->addrinfow = (struct addrinfoW*)alloc_ptr;
+    req->addrinfow = (struct addrinfoW*) alloc_ptr;
     req->addrinfow->ai_family = hints->ai_family;
     req->addrinfow->ai_socktype = hints->ai_socktype;
     req->addrinfow->ai_protocol = hints->ai_protocol;
@@ -387,19 +339,11 @@
     uv__getaddrinfo_done(&req->work_req, 0);
     return req->retcode;
   }
-
-error:
-  if (req != NULL) {
-    uv__free(req->alloc);
-    req->alloc = NULL;
-  }
-  return uv_translate_sys_error(err);
 }
 
 int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
   NET_LUID luid;
   wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
-  DWORD bufsize;
   int r;
 
   if (buffer == NULL || size == NULL || *size == 0)
@@ -415,31 +359,7 @@
   if (r != 0)
     return uv_translate_sys_error(r);
 
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
-
-  if (bufsize == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (bufsize > *size) {
-    *size = bufsize;
-    return UV_ENOBUFS;
-  }
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                wname,
-                                -1,
-                                buffer,
-                                *size,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  *size = bufsize - 1;
-  return 0;
+  return uv__copy_utf16_to_utf8(wname, -1, buffer, size);
 }
 
 int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/getnameinfo.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/getnameinfo.cpp
index b377338..3286317 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/getnameinfo.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/getnameinfo.cpp
@@ -42,6 +42,7 @@
   uv_getnameinfo_t* req;
   WCHAR host[NI_MAXHOST];
   WCHAR service[NI_MAXSERV];
+  size_t size;
   int ret;
 
   req = container_of(w, uv_getnameinfo_t, work_req);
@@ -57,29 +58,17 @@
     return;
   }
 
-  ret = WideCharToMultiByte(CP_UTF8,
-                            0,
-                            host,
-                            -1,
-                            req->host,
-                            sizeof(req->host),
-                            NULL,
-                            NULL);
-  if (ret == 0) {
-    req->retcode = uv_translate_sys_error(GetLastError());
+  size = sizeof(req->host);
+  ret = uv__copy_utf16_to_utf8(host, -1, req->host, &size);
+  if (ret < 0) {
+    req->retcode = ret;
     return;
   }
 
-  ret = WideCharToMultiByte(CP_UTF8,
-                            0,
-                            service,
-                            -1,
-                            req->service,
-                            sizeof(req->service),
-                            NULL,
-                            NULL);
-  if (ret == 0) {
-    req->retcode = uv_translate_sys_error(GetLastError());
+  size = sizeof(req->service);
+  ret = uv__copy_utf16_to_utf8(service, -1, req->service, &size);
+  if (ret < 0) {
+    req->retcode = ret;
   }
 }
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h b/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h
index 9672fbc..867dea5 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/internal.h
@@ -257,8 +257,9 @@
 
 uint64_t uv__hrtime(unsigned int scale);
 __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
-int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
-int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
+int uv__convert_utf16_to_utf8(const WCHAR* utf16, size_t utf16len, char** utf8);
+int uv__copy_utf16_to_utf8(const WCHAR* utf16, size_t utf16len, char* utf8, size_t *size);
+int uv__convert_utf8_to_utf16(const char* utf8, WCHAR** utf16);
 
 typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp
index 258d6a6..b2348bd 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/pipe.cpp
@@ -51,7 +51,7 @@
 
 /* Pipe prefix */
 static char pipe_prefix[] = "\\\\?\\pipe";
-static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
+static const size_t pipe_prefix_len = sizeof(pipe_prefix) - 1;
 
 /* IPC incoming xfer queue item. */
 typedef struct {
@@ -705,7 +705,7 @@
                   size_t namelen,
                   unsigned int flags) {
   uv_loop_t* loop = handle->loop;
-  int i, err, nameSize;
+  int i, err;
   uv_pipe_accept_t* req;
 
   if (flags & ~UV_PIPE_NO_TRUNCATE) {
@@ -744,9 +744,8 @@
 
   handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*)
     uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);
-  if (!handle->pipe.serv.accept_reqs) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
+  if (!handle->pipe.serv.accept_reqs)
+    return UV_ENOMEM;
 
   for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
     req = &handle->pipe.serv.accept_reqs[i];
@@ -756,22 +755,9 @@
     req->next_pending = NULL;
   }
 
-  /* Convert name to UTF16. */
-  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
-  handle->name = (WCHAR*)uv__malloc(nameSize);
-  if (!handle->name) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           name,
-                           -1,
-                           handle->name,
-                           nameSize / sizeof(WCHAR))) {
-    err = GetLastError();
-    goto error;
-  }
+  err = uv__convert_utf8_to_utf16(name, &handle->name);
+  if (err)
+    return err;
 
   /*
    * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
@@ -797,10 +783,8 @@
   return 0;
 
 error:
-  if (handle->name) {
-    uv__free(handle->name);
-    handle->name = NULL;
-  }
+  uv__free(handle->name);
+  handle->name = NULL;
 
   return uv_translate_sys_error(err);
 }
@@ -863,7 +847,8 @@
                      unsigned int flags,
                      uv_connect_cb cb) {
   uv_loop_t* loop = handle->loop;
-  int err, nameSize;
+  int err;
+  size_t nameSize;
   HANDLE pipeHandle = INVALID_HANDLE_VALUE;
   DWORD duplex_flags;
 
@@ -906,26 +891,16 @@
   }
   uv__pipe_connection_init(handle);
 
-  /* Convert name to UTF16. */
-  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
-  handle->name = (WCHAR*)uv__malloc(nameSize);
-  if (!handle->name) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           name,
-                           -1,
-                           handle->name,
-                           nameSize / sizeof(WCHAR))) {
-    err = GetLastError();
+  err = uv__convert_utf8_to_utf16(name, &handle->name);
+  if (err) {
+    err = ERROR_NO_UNICODE_TRANSLATION;
     goto error;
   }
 
   pipeHandle = open_named_pipe(handle->name, &duplex_flags);
   if (pipeHandle == INVALID_HANDLE_VALUE) {
     if (GetLastError() == ERROR_PIPE_BUSY) {
+      nameSize = (wcslen(handle->name) + 1) * sizeof(WCHAR);
       req->u.connect.name = (WCHAR *)uv__malloc(nameSize);
       if (!req->u.connect.name) {
         uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
@@ -2441,7 +2416,6 @@
   FILE_NAME_INFORMATION tmp_name_info;
   FILE_NAME_INFORMATION* name_info;
   WCHAR* name_buf;
-  unsigned int addrlen;
   unsigned int name_size;
   unsigned int name_len;
   int err;
@@ -2452,46 +2426,7 @@
   if (handle->name != NULL) {
     /* The user might try to query the name before we are connected,
      * and this is just easier to return the cached value if we have it. */
-    name_buf = handle->name;
-    name_len = wcslen(name_buf);
-
-    /* check how much space we need */
-    addrlen = WideCharToMultiByte(CP_UTF8,
-                                  0,
-                                  name_buf,
-                                  name_len,
-                                  NULL,
-                                  0,
-                                  NULL,
-                                  NULL);
-    if (!addrlen) {
-      *size = 0;
-      err = uv_translate_sys_error(GetLastError());
-      return err;
-    } else if (addrlen >= *size) {
-      *size = addrlen + 1;
-      err = UV_ENOBUFS;
-      goto error;
-    }
-
-    addrlen = WideCharToMultiByte(CP_UTF8,
-                                  0,
-                                  name_buf,
-                                  name_len,
-                                  buffer,
-                                  addrlen,
-                                  NULL,
-                                  NULL);
-    if (!addrlen) {
-      *size = 0;
-      err = uv_translate_sys_error(GetLastError());
-      return err;
-    }
-
-    *size = addrlen;
-    buffer[addrlen] = '\0';
-
-    return 0;
+    return uv__copy_utf16_to_utf8(handle->name, -1, buffer, size);
   }
 
   if (handle->handle == INVALID_HANDLE_VALUE) {
@@ -2519,8 +2454,7 @@
     name_info = (FILE_NAME_INFORMATION*)uv__malloc(name_size);
     if (!name_info) {
       *size = 0;
-      err = UV_ENOMEM;
-      goto cleanup;
+      return UV_ENOMEM;
     }
 
     nt_status = pNtQueryInformationFile(handle->handle,
@@ -2553,51 +2487,19 @@
 
   name_len /= sizeof(WCHAR);
 
-  /* check how much space we need */
-  addrlen = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                name_buf,
-                                name_len,
-                                NULL,
-                                0,
-                                NULL,
-                                NULL);
-  if (!addrlen) {
+  /* "\\\\.\\pipe" + name */
+  if (*size < pipe_prefix_len) {
     *size = 0;
-    err = uv_translate_sys_error(GetLastError());
-    goto error;
-  } else if (pipe_prefix_len + addrlen >= *size) {
-    /* "\\\\.\\pipe" + name */
-    *size = pipe_prefix_len + addrlen + 1;
-    err = UV_ENOBUFS;
-    goto error;
   }
-
-  memcpy(buffer, pipe_prefix, pipe_prefix_len);
-  addrlen = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                name_buf,
-                                name_len,
-                                buffer+pipe_prefix_len,
-                                *size-pipe_prefix_len,
-                                NULL,
-                                NULL);
-  if (!addrlen) {
-    *size = 0;
-    err = uv_translate_sys_error(GetLastError());
-    goto error;
+  else {
+    memcpy(buffer, pipe_prefix, pipe_prefix_len);
+    *size -= pipe_prefix_len;
   }
-
-  addrlen += pipe_prefix_len;
-  *size = addrlen;
-  buffer[addrlen] = '\0';
-
-  err = 0;
+  err = uv__copy_utf16_to_utf8(name_buf, name_len, buffer+pipe_prefix_len, size);
+  *size += pipe_prefix_len;
 
 error:
   uv__free(name_info);
-
-cleanup:
   return err;
 }
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp
index 18816d3..eeb0f6a 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/process.cpp
@@ -35,6 +35,7 @@
 #include "handle-inl.h"
 #include "req-inl.h"
 
+
 #define SIGKILL         9
 
 
@@ -103,38 +104,26 @@
                                &info,
                                sizeof info))
     uv_fatal_error(GetLastError(), "SetInformationJobObject");
+
+
+  if (!AssignProcessToJobObject(uv_global_job_handle_, GetCurrentProcess())) {
+    /* Make sure this handle is functional. The Windows kernel has a bug that
+     * if the first use of AssignProcessToJobObject is for a Windows Store
+     * program, subsequent attempts to use the handle with fail with
+     * INVALID_PARAMETER (87). This is possibly because all uses of the handle
+     * must be for the same Terminal Services session. We can ensure it is tied
+     * to our current session now by adding ourself to it. We could remove
+     * ourself afterwards, but there doesn't seem to be a reason to.
+     */
+    DWORD err = GetLastError();
+    if (err != ERROR_ACCESS_DENIED)
+      uv_fatal_error(err, "AssignProcessToJobObject");
+  }
 }
 
 
 static int uv__utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
-  int ws_len, r;
-  WCHAR* ws;
-
-  ws_len = MultiByteToWideChar(CP_UTF8,
-                               0,
-                               s,
-                               -1,
-                               NULL,
-                               0);
-  if (ws_len <= 0) {
-    return GetLastError();
-  }
-
-  ws = (WCHAR*) uv__malloc(ws_len * sizeof(WCHAR));
-  if (ws == NULL) {
-    return ERROR_OUTOFMEMORY;
-  }
-
-  r = MultiByteToWideChar(CP_UTF8,
-                          0,
-                          s,
-                          -1,
-                          ws,
-                          ws_len);
-  assert(r == ws_len);
-
-  *ws_ptr = ws;
-  return 0;
+  return uv__convert_utf8_to_utf16(s, ws_ptr);
 }
 
 
@@ -394,7 +383,7 @@
                                   name_has_ext);
 
     while (result == NULL) {
-      if (*dir_end == L'\0') {
+      if (dir_end == NULL || *dir_end == L'\0') {
         break;
       }
 
@@ -537,21 +526,15 @@
 
   /* Count the required size. */
   for (arg = args; *arg; arg++) {
-    DWORD arg_len;
+    ssize_t arg_len;
 
-    arg_len = MultiByteToWideChar(CP_UTF8,
-                                  0,
-                                  *arg,
-                                  -1,
-                                  NULL,
-                                  0);
-    if (arg_len == 0) {
-      return GetLastError();
-    }
+    arg_len = uv_wtf8_length_as_utf16(*arg);
+    if (arg_len < 0)
+      return arg_len;
 
     dst_len += arg_len;
 
-    if (arg_len > temp_buffer_len)
+    if ((size_t) arg_len > temp_buffer_len)
       temp_buffer_len = arg_len;
 
     arg_count++;
@@ -562,34 +545,28 @@
   dst_len = dst_len * 2 + arg_count * 2;
 
   /* Allocate buffer for the final command line. */
-  dst = (WCHAR*) uv__malloc(dst_len * sizeof(WCHAR));
+  dst = (WCHAR*)uv__malloc(dst_len * sizeof(WCHAR));
   if (dst == NULL) {
-    err = ERROR_OUTOFMEMORY;
+    err = UV_ENOMEM;
     goto error;
   }
 
   /* Allocate temporary working buffer. */
-  temp_buffer = (WCHAR*) uv__malloc(temp_buffer_len * sizeof(WCHAR));
+  temp_buffer = (WCHAR*)uv__malloc(temp_buffer_len * sizeof(WCHAR));
   if (temp_buffer == NULL) {
-    err = ERROR_OUTOFMEMORY;
+    err = UV_ENOMEM;
     goto error;
   }
 
   pos = dst;
   for (arg = args; *arg; arg++) {
-    DWORD arg_len;
+    ssize_t arg_len;
 
     /* Convert argument to wide char. */
-    arg_len = MultiByteToWideChar(CP_UTF8,
-                                  0,
-                                  *arg,
-                                  -1,
-                                  temp_buffer,
-                                  (int) (dst + dst_len - pos));
-    if (arg_len == 0) {
-      err = GetLastError();
-      goto error;
-    }
+    arg_len = uv_wtf8_length_as_utf16(*arg);
+    assert(arg_len > 0);
+    assert(temp_buffer_len >= (size_t) arg_len);
+    uv_wtf8_to_utf16(*arg, (uint16_t*)temp_buffer, arg_len);
 
     if (verbatim_arguments) {
       /* Copy verbatim. */
@@ -601,6 +578,7 @@
     }
 
     *pos++ = *(arg + 1) ? L' ' : L'\0';
+    assert(pos <= dst + dst_len);
   }
 
   uv__free(temp_buffer);
@@ -686,28 +664,22 @@
   WCHAR* ptr;
   char** env;
   size_t env_len = 0;
-  int len;
+  size_t len;
   size_t i;
-  DWORD var_size;
+  size_t var_size;
   size_t env_block_count = 1; /* 1 for null-terminator */
   WCHAR* dst_copy;
   WCHAR** ptr_copy;
   WCHAR** env_copy;
-  DWORD required_vars_value_len[ARRAY_SIZE(required_vars)];
+  size_t required_vars_value_len[ARRAY_SIZE(required_vars)];
 
   /* first pass: determine size in UTF-16 */
   for (env = env_block; *env; env++) {
-    int len;
+    ssize_t len;
     if (strchr(*env, '=')) {
-      len = MultiByteToWideChar(CP_UTF8,
-                                0,
-                                *env,
-                                -1,
-                                NULL,
-                                0);
-      if (len <= 0) {
-        return GetLastError();
-      }
+      len = uv_wtf8_length_as_utf16(*env);
+      if (len < 0)
+        return len;
       env_len += len;
       env_block_count++;
     }
@@ -716,25 +688,19 @@
   /* second pass: copy to UTF-16 environment block */
   dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR));
   if (dst_copy == NULL && env_len > 0) {
-    return ERROR_OUTOFMEMORY;
+    return UV_ENOMEM;
   }
   env_copy = (WCHAR**)alloca(env_block_count * sizeof(WCHAR*));
 
   ptr = dst_copy;
   ptr_copy = env_copy;
   for (env = env_block; *env; env++) {
+    ssize_t len;
     if (strchr(*env, '=')) {
-      len = MultiByteToWideChar(CP_UTF8,
-                                0,
-                                *env,
-                                -1,
-                                ptr,
-                                (int) (env_len - (ptr - dst_copy)));
-      if (len <= 0) {
-        DWORD err = GetLastError();
-        uv__free(dst_copy);
-        return err;
-      }
+      len = uv_wtf8_length_as_utf16(*env);
+      assert(len > 0);
+      assert((size_t) len <= env_len - (ptr - dst_copy));
+      uv_wtf8_to_utf16(*env, (uint16_t*)ptr, len);
       *ptr_copy++ = ptr;
       ptr += len;
     }
@@ -752,7 +718,7 @@
       cmp = -1;
     } else {
       cmp = env_strncmp(required_vars[i].wide_eq,
-                       required_vars[i].len,
+                        required_vars[i].len,
                         *ptr_copy);
     }
     if (cmp < 0) {
@@ -775,7 +741,7 @@
   dst = (WCHAR*)uv__malloc((1+env_len) * sizeof(WCHAR));
   if (!dst) {
     uv__free(dst_copy);
-    return ERROR_OUTOFMEMORY;
+    return UV_ENOMEM;
   }
 
   for (ptr = dst, ptr_copy = env_copy, i = 0;
@@ -973,26 +939,26 @@
 
   err = uv__utf8_to_utf16_alloc(options->file, &application);
   if (err)
-    goto done;
+    goto done_uv;
 
   err = make_program_args(
       options->args,
       options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
       &arguments);
   if (err)
-    goto done;
+    goto done_uv;
 
   if (options->env) {
      err = make_program_env(options->env, &env);
      if (err)
-       goto done;
+       goto done_uv;
   }
 
   if (options->cwd) {
     /* Explicit cwd */
     err = uv__utf8_to_utf16_alloc(options->cwd, &cwd);
     if (err)
-      goto done;
+      goto done_uv;
 
   } else {
     /* Inherit cwd */
@@ -1023,22 +989,19 @@
     DWORD path_len, r;
 
     path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
-    if (path_len == 0) {
-      err = GetLastError();
-      goto done;
-    }
+    if (path_len != 0) {
+      alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
+      if (alloc_path == NULL) {
+        err = ERROR_OUTOFMEMORY;
+        goto done;
+      }
+      path = alloc_path;
 
-    alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
-    if (alloc_path == NULL) {
-      err = ERROR_OUTOFMEMORY;
-      goto done;
-    }
-    path = alloc_path;
-
-    r = GetEnvironmentVariableW(L"PATH", path, path_len);
-    if (r == 0 || r >= path_len) {
-      err = GetLastError();
-      goto done;
+      r = GetEnvironmentVariableW(L"PATH", path, path_len);
+      if (r == 0 || r >= path_len) {
+        err = GetLastError();
+        goto done;
+      }
     }
   }
 
@@ -1100,6 +1063,7 @@
      * breakaway.
      */
     process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
+    process_flags |= CREATE_SUSPENDED;
   }
 
   if (!CreateProcessW(application_path,
@@ -1117,11 +1081,6 @@
     goto done;
   }
 
-  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
-
-  process->process_handle = info.hProcess;
-  process->pid = info.dwProcessId;
-
   /* If the process isn't spawned as detached, assign to the global job object
    * so windows will kill it when the parent process dies. */
   if (!(options->flags & UV_PROCESS_DETACHED)) {
@@ -1144,6 +1103,19 @@
     }
   }
 
+  if (process_flags & CREATE_SUSPENDED) {
+    if (ResumeThread(info.hThread) == ((DWORD)-1)) {
+      err = GetLastError();
+      TerminateProcess(info.hProcess, 1);
+      goto done;
+    }
+  }
+
+  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
+
+  process->process_handle = info.hProcess;
+  process->pid = info.dwProcessId;
+
   /* Set IPC pid to all IPC pipes. */
   for (i = 0; i < options->stdio_count; i++) {
     const uv_stdio_container_t* fdopt = &options->stdio[i];
@@ -1171,8 +1143,13 @@
    * made or the handle is closed, whichever happens first. */
   uv__handle_start(process);
 
+  goto done_uv;
+
   /* Cleanup, whether we succeeded or failed. */
  done:
+  err = uv_translate_sys_error(err);
+
+ done_uv:
   uv__free(application);
   uv__free(application_path);
   uv__free(arguments);
@@ -1186,7 +1163,7 @@
     child_stdio_buffer = NULL;
   }
 
-  return uv_translate_sys_error(err);
+  return err;
 }
 
 
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp
index 9bb3d9e..7adf3cd 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/tty.cpp
@@ -486,9 +486,11 @@
   uv_loop_t* loop;
   uv_tty_t* handle;
   uv_req_t* req;
-  DWORD bytes, read_bytes;
+  DWORD bytes;
+  size_t read_bytes;
   WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3];
-  DWORD chars, read_chars;
+  DWORD chars;
+  DWORD read_chars;
   LONG status;
   COORD pos;
   BOOL read_console_success;
@@ -529,16 +531,13 @@
                                       NULL);
 
   if (read_console_success) {
-    read_bytes = WideCharToMultiByte(CP_UTF8,
-                                     0,
-                                     utf16,
-                                     read_chars,
-                                     handle->tty.rd.read_line_buffer.base,
-                                     bytes,
-                                     NULL,
-                                     NULL);
+    read_bytes = bytes;
+    uv_utf16_to_wtf8((const uint16_t*)utf16,
+                     read_chars,
+                     &handle->tty.rd.read_line_buffer.base,
+                     &read_bytes);
     SET_REQ_SUCCESS(req);
-    req->u.io.overlapped.InternalHigh = read_bytes;
+    req->u.io.overlapped.InternalHigh = (DWORD) read_bytes;
   } else {
     SET_REQ_ERROR(req, GetLastError());
   }
@@ -802,7 +801,9 @@
       }
 
       if (KEV.uChar.UnicodeChar != 0) {
-        int prefix_len, char_len;
+        int prefix_len;
+        size_t char_len;
+        char* last_key_buf;
 
         /* Character key pressed */
         if (KEV.uChar.UnicodeChar >= 0xD800 &&
@@ -823,38 +824,31 @@
           prefix_len = 0;
         }
 
-        if (KEV.uChar.UnicodeChar >= 0xDC00 &&
-            KEV.uChar.UnicodeChar < 0xE000) {
+        char_len = sizeof handle->tty.rd.last_key;
+        last_key_buf = &handle->tty.rd.last_key[prefix_len];
+        if (handle->tty.rd.last_utf16_high_surrogate) {
           /* UTF-16 surrogate pair */
           WCHAR utf16_buffer[2];
           utf16_buffer[0] = handle->tty.rd.last_utf16_high_surrogate;
           utf16_buffer[1] = KEV.uChar.UnicodeChar;
-          char_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         utf16_buffer,
-                                         2,
-                                         &handle->tty.rd.last_key[prefix_len],
-                                         sizeof handle->tty.rd.last_key,
-                                         NULL,
-                                         NULL);
+          if (uv_utf16_to_wtf8((const uint16_t*)utf16_buffer,
+                               2,
+                               &last_key_buf,
+                               &char_len))
+            char_len = 0;
+          handle->tty.rd.last_utf16_high_surrogate = 0;
         } else {
           /* Single UTF-16 character */
-          char_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         &KEV.uChar.UnicodeChar,
-                                         1,
-                                         &handle->tty.rd.last_key[prefix_len],
-                                         sizeof handle->tty.rd.last_key,
-                                         NULL,
-                                         NULL);
+          if (uv_utf16_to_wtf8((const uint16_t*)&KEV.uChar.UnicodeChar,
+                               1,
+                               &last_key_buf,
+                               &char_len))
+            char_len = 0;
         }
 
-        /* Whatever happened, the last character wasn't a high surrogate. */
-        handle->tty.rd.last_utf16_high_surrogate = 0;
-
         /* If the utf16 character(s) couldn't be converted something must be
          * wrong. */
-        if (!char_len) {
+        if (char_len == 0) {
           handle->flags &= ~UV_HANDLE_READING;
           DECREASE_ACTIVE_COUNT(loop, handle);
           handle->read_cb((uv_stream_t*) handle,
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp
index 4b76417..14295c4 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/util.cpp
@@ -105,7 +105,7 @@
 
 
 int uv_exepath(char* buffer, size_t* size_ptr) {
-  int utf8_len, utf16_buffer_len, utf16_len;
+  size_t utf8_len, utf16_buffer_len, utf16_len;
   WCHAR* utf16_buffer;
   int err;
 
@@ -133,25 +133,17 @@
   }
 
   /* Convert to UTF-8 */
-  utf8_len = WideCharToMultiByte(CP_UTF8,
-                                 0,
-                                 utf16_buffer,
-                                 -1,
-                                 buffer,
-                                 (int) *size_ptr,
-                                 NULL,
-                                 NULL);
-  if (utf8_len == 0) {
-    err = GetLastError();
-    goto error;
+  utf8_len = *size_ptr - 1; /* Reserve space for NUL */
+  err = uv_utf16_to_wtf8((const uint16_t*)utf16_buffer, utf16_len, &buffer, &utf8_len);
+  if (err == UV_ENOBUFS) {
+    utf8_len = *size_ptr - 1;
+    err = 0;
   }
+  *size_ptr = utf8_len;
 
   uv__free(utf16_buffer);
 
-  /* utf8_len *does* include the terminating null at this point, but the
-   * returned size shouldn't. */
-  *size_ptr = utf8_len - 1;
-  return 0;
+  return err;
 
  error:
   uv__free(utf16_buffer);
@@ -214,45 +206,14 @@
   }
 
   r = uv__cwd(&utf16_buffer, &utf16_len);
-  if (r < 0) {
+  if (r < 0)
     return r;
-  }
 
-  /* Check how much space we need */
-  r = WideCharToMultiByte(CP_UTF8,
-                          0,
-                          utf16_buffer,
-                          -1,
-                          NULL,
-                          0,
-                          NULL,
-                          NULL);
-  if (r == 0) {
-    uv__free(utf16_buffer);
-    return uv_translate_sys_error(GetLastError());
-  } else if (r > (int) *size) {
-    uv__free(utf16_buffer);
-    *size = r;
-    return UV_ENOBUFS;
-  }
+  r = uv__copy_utf16_to_utf8(utf16_buffer, utf16_len, buffer, size);
 
-  /* Convert to UTF-8 */
-  r = WideCharToMultiByte(CP_UTF8,
-                          0,
-                          utf16_buffer,
-                          -1,
-                          buffer,
-                          *size > INT_MAX ? INT_MAX : (int) *size,
-                          NULL,
-                          NULL);
   uv__free(utf16_buffer);
 
-  if (r == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  *size = r - 1;
-  return 0;
+  return r;
 }
 
 
@@ -262,33 +223,10 @@
   WCHAR drive_letter, env_var[4];
   int r;
 
-  if (dir == NULL) {
-    return UV_EINVAL;
-  }
-
-  utf16_len = MultiByteToWideChar(CP_UTF8,
-                                  0,
-                                  dir,
-                                  -1,
-                                  NULL,
-                                  0);
-  if (utf16_len == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-  utf16_buffer = (WCHAR*)uv__malloc(utf16_len * sizeof(WCHAR));
-  if (utf16_buffer == NULL) {
-    return UV_ENOMEM;
-  }
-
-  if (MultiByteToWideChar(CP_UTF8,
-                          0,
-                          dir,
-                          -1,
-                          utf16_buffer,
-                          utf16_len) == 0) {
-    uv__free(utf16_buffer);
-    return uv_translate_sys_error(GetLastError());
-  }
+  /* Convert to UTF-16 */
+  r = uv__convert_utf8_to_utf16(dir, &utf16_buffer);
+  if (r)
+    return r;
 
   if (!SetCurrentDirectoryW(utf16_buffer)) {
     uv__free(utf16_buffer);
@@ -426,29 +364,14 @@
 
   uv__once_init();
 
-  /* Find out how big the buffer for the wide-char title must be */
-  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
-  if (!length) {
-    err = GetLastError();
-    goto done;
-  }
-
-  /* Convert to wide-char string */
-  title_w = (WCHAR*)uv__malloc(sizeof(WCHAR) * length);
-  if (!title_w) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length);
-  if (!length) {
-    err = GetLastError();
-    goto done;
-  }
+  err = uv__convert_utf8_to_utf16(title, &title_w);
+  if (err)
+    return err;
 
   /* If the title must be truncated insert a \0 terminator there */
-  if (length > MAX_TITLE_LENGTH) {
+  length = wcslen(title_w);
+  if (length >= MAX_TITLE_LENGTH)
     title_w[MAX_TITLE_LENGTH - 1] = L'\0';
-  }
 
   if (!SetConsoleTitleW(title_w)) {
     err = GetLastError();
@@ -470,20 +393,19 @@
 
 static int uv__get_process_title(void) {
   WCHAR title_w[MAX_TITLE_LENGTH];
+  DWORD wlen;
 
-  if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
-    return -1;
-  }
+  wlen = GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR));
+  if (wlen == 0)
+    return uv_translate_sys_error(GetLastError());
 
-  if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0)
-    return -1;
-
-  return 0;
+  return uv__convert_utf16_to_utf8(title_w, wlen, &process_title);
 }
 
 
 int uv_get_process_title(char* buffer, size_t size) {
   size_t len;
+  int r;
 
   if (buffer == NULL || size == 0)
     return UV_EINVAL;
@@ -495,9 +417,12 @@
    * If the process_title was never read before nor explicitly set,
    * we must query it with getConsoleTitleW
    */
-  if (!process_title && uv__get_process_title() == -1) {
-    LeaveCriticalSection(&process_title_lock);
-    return uv_translate_sys_error(GetLastError());
+  if (process_title == NULL) {
+    r = uv__get_process_title();
+    if (r) {
+      LeaveCriticalSection(&process_title_lock);
+      return r;
+    }
   }
 
   assert(process_title);
@@ -844,19 +769,8 @@
       continue;
 
     /* Compute the size of the interface name. */
-    name_size = WideCharToMultiByte(CP_UTF8,
-                                    0,
-                                    adapter->FriendlyName,
-                                    -1,
-                                    NULL,
-                                    0,
-                                    NULL,
-                                    FALSE);
-    if (name_size <= 0) {
-      uv__free(win_address_buf);
-      return uv_translate_sys_error(GetLastError());
-    }
-    uv_address_buf_size += name_size;
+    name_size = uv_utf16_length_as_wtf8((const uint16_t*)adapter->FriendlyName, -1);
+    uv_address_buf_size += name_size + 1;
 
     /* Count the number of addresses associated with this interface, and
      * compute the size. */
@@ -886,30 +800,25 @@
        adapter != NULL;
        adapter = adapter->Next) {
     IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
-    int name_size;
-    size_t max_name_size;
+    size_t name_size;
+    int r;
 
     if (adapter->OperStatus != IfOperStatusUp ||
         adapter->FirstUnicastAddress == NULL)
       continue;
 
     /* Convert the interface name to UTF8. */
-    max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
-    if (max_name_size > (size_t) INT_MAX)
-      max_name_size = INT_MAX;
-    name_size = WideCharToMultiByte(CP_UTF8,
-                                    0,
-                                    adapter->FriendlyName,
-                                    -1,
-                                    name_buf,
-                                    (int) max_name_size,
-                                    NULL,
-                                    FALSE);
-    if (name_size <= 0) {
+    name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
+    r = uv__copy_utf16_to_utf8(adapter->FriendlyName,
+                               -1,
+                               name_buf,
+                               &name_size);
+    if (r) {
       uv__free(win_address_buf);
       uv__free(uv_address_buf);
-      return uv_translate_sys_error(GetLastError());
+      return r;
     }
+    name_size += 1; /* Add NUL byte. */
 
     /* Add an uv_interface_address_t element for every unicast address. */
     for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
@@ -1072,7 +981,6 @@
 
 int uv_os_tmpdir(char* buffer, size_t* size) {
   wchar_t *path;
-  DWORD bufsize;
   size_t len;
 
   if (buffer == NULL || size == NULL || *size == 0)
@@ -1089,7 +997,7 @@
   if (path == NULL) {
     return UV_ENOMEM;
   }
-  len  = GetTempPathW(len, path);
+  len = GetTempPathW(len, path);
 
   if (len == 0) {
     uv__free(path);
@@ -1104,34 +1012,7 @@
     path[len] = L'\0';
   }
 
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
-
-  if (bufsize == 0) {
-    uv__free(path);
-    return uv_translate_sys_error(GetLastError());
-  } else if (bufsize > *size) {
-    uv__free(path);
-    *size = bufsize;
-    return UV_ENOBUFS;
-  }
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                path,
-                                -1,
-                                buffer,
-                                *size,
-                                NULL,
-                                NULL);
-  uv__free(path);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  *size = bufsize - 1;
-  return 0;
+  return uv__copy_utf16_to_utf8(path, len, buffer, size);
 }
 
 
@@ -1142,95 +1023,71 @@
  * If utf16 is null terminated, utf16len can be set to -1, otherwise it must
  * be specified.
  */
-int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
-  DWORD bufsize;
+int uv__convert_utf16_to_utf8(const WCHAR* utf16, size_t utf16len, char** utf8) {
+  size_t utf8_len = 0;
 
   if (utf16 == NULL)
     return UV_EINVAL;
 
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                utf16,
-                                utf16len,
-                                NULL,
-                                0,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  /* Allocate the destination buffer adding an extra byte for the terminating
-   * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so
-   * we do it ourselves always, just in case. */
-  *utf8 = (char*)uv__malloc(bufsize + 1);
-
-  if (*utf8 == NULL)
-    return UV_ENOMEM;
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                utf16,
-                                utf16len,
-                                *utf8,
-                                bufsize,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0) {
-    uv__free(*utf8);
-    *utf8 = NULL;
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  (*utf8)[bufsize] = '\0';
-  return 0;
+   *utf8 = NULL;
+   return uv_utf16_to_wtf8((const uint16_t*)utf16, utf16len, utf8, &utf8_len);
 }
 
 
 /*
  * Converts a UTF-8 string into a UTF-16 one. The resulting string is
  * null-terminated.
- *
- * If utf8 is null terminated, utf8len can be set to -1, otherwise it must
- * be specified.
  */
-int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
+int uv__convert_utf8_to_utf16(const char* utf8, WCHAR** utf16) {
   int bufsize;
 
   if (utf8 == NULL)
     return UV_EINVAL;
 
-  /* Check how much space we need */
-  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);
+  /* Check how much space we need (including NUL). */
+  bufsize = uv_wtf8_length_as_utf16(utf8);
+  if (bufsize < 0)
+    return UV__EINVAL;
 
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  /* Allocate the destination buffer adding an extra byte for the terminating
-   * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so
-   * we do it ourselves always, just in case. */
-  *utf16 = (WCHAR*)uv__malloc(sizeof(WCHAR) * (bufsize + 1));
+  /* Allocate the destination buffer. */
+  *utf16 = (WCHAR*)uv__malloc(sizeof(WCHAR) * bufsize);
 
   if (*utf16 == NULL)
     return UV_ENOMEM;
 
   /* Convert to UTF-16 */
-  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
+  uv_wtf8_to_utf16(utf8, (uint16_t*)*utf16, bufsize);
 
-  if (bufsize == 0) {
-    uv__free(*utf16);
-    *utf16 = NULL;
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  (*utf16)[bufsize] = L'\0';
   return 0;
 }
 
 
+/*
+ * Converts a UTF-16 string into a UTF-8 one in an existing buffer. The
+ * resulting string is null-terminated.
+ *
+ * If utf16 is null terminated, utf16len can be set to -1, otherwise it must
+ * be specified.
+ */
+int uv__copy_utf16_to_utf8(const WCHAR* utf16buffer, size_t utf16len, char* utf8, size_t *size) {
+  int r;
+
+  if (utf8 == NULL || size == NULL)
+    return UV_EINVAL;
+
+  if (*size == 0) {
+    *size = uv_utf16_length_as_wtf8((const uint16_t*)utf16buffer, utf16len);
+    r = UV_ENOBUFS;
+  } else {
+    *size -= 1; /* Reserve space for NUL. */
+    r = uv_utf16_to_wtf8((const uint16_t*)utf16buffer, utf16len, &utf8, size);
+  }
+  if (r == UV_ENOBUFS)
+    *size += 1; /* Add space for NUL. */
+  return r;
+}
+
+
 static int uv__getpwuid_r(uv_passwd_t* pwd) {
   HANDLE token;
   wchar_t username[UNLEN + 1];
@@ -1395,14 +1252,13 @@
   wchar_t* var;
   DWORD varlen;
   wchar_t* name_w;
-  DWORD bufsize;
   size_t len;
   int r;
 
   if (name == NULL || buffer == NULL || size == NULL || *size == 0)
     return UV_EINVAL;
 
-  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+  r = uv__convert_utf8_to_utf16(name, &name_w);
 
   if (r != 0)
     return r;
@@ -1443,35 +1299,7 @@
     }
   }
 
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
-
-  if (bufsize == 0) {
-    r = uv_translate_sys_error(GetLastError());
-    goto fail;
-  } else if (bufsize > *size) {
-    *size = bufsize;
-    r = UV_ENOBUFS;
-    goto fail;
-  }
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                var,
-                                -1,
-                                buffer,
-                                *size,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0) {
-    r = uv_translate_sys_error(GetLastError());
-    goto fail;
-  }
-
-  *size = bufsize - 1;
-  r = 0;
+  r = uv__copy_utf16_to_utf8(var, len, buffer, size);
 
 fail:
 
@@ -1493,12 +1321,12 @@
   if (name == NULL || value == NULL)
     return UV_EINVAL;
 
-  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+  r = uv__convert_utf8_to_utf16(name, &name_w);
 
   if (r != 0)
     return r;
 
-  r = uv__convert_utf8_to_utf16(value, -1, &value_w);
+  r = uv__convert_utf8_to_utf16(value, &value_w);
 
   if (r != 0) {
     uv__free(name_w);
@@ -1523,7 +1351,7 @@
   if (name == NULL)
     return UV_EINVAL;
 
-  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
+  r = uv__convert_utf8_to_utf16(name, &name_w);
 
   if (r != 0)
     return r;
@@ -1540,9 +1368,6 @@
 
 int uv_os_gethostname(char* buffer, size_t* size) {
   WCHAR buf[UV_MAXHOSTNAMESIZE];
-  size_t len;
-  char* utf8_str;
-  int convert_result;
 
   if (buffer == NULL || size == NULL || *size == 0)
     return UV_EINVAL;
@@ -1555,22 +1380,7 @@
   if (pGetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
     return uv_translate_sys_error(WSAGetLastError());
 
-  convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str);
-
-  if (convert_result != 0)
-    return convert_result;
-
-  len = strlen(utf8_str);
-  if (len >= *size) {
-    *size = len + 1;
-    uv__free(utf8_str);
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, utf8_str, len + 1);
-  uv__free(utf8_str);
-  *size = len;
-  return 0;
+  return uv__copy_utf16_to_utf8(buf, -1, buffer, size);
 }
 
 
@@ -1676,7 +1486,7 @@
   HKEY registry_key;
   WCHAR product_name_w[256];
   DWORD product_name_w_size;
-  int version_size;
+  size_t version_size;
   int processor_level;
   int r;
 
@@ -1707,7 +1517,7 @@
   r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                     L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
                     0,
-                    KEY_QUERY_VALUE,
+                    KEY_QUERY_VALUE | KEY_WOW64_64KEY,
                     &registry_key);
 
   if (r == ERROR_SUCCESS) {
@@ -1738,37 +1548,29 @@
         }
       }
 
-      version_size = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         product_name_w,
-                                         -1,
-                                         buffer->version,
-                                         sizeof(buffer->version),
-                                         NULL,
-                                         NULL);
-      if (version_size == 0) {
-        r = uv_translate_sys_error(GetLastError());
+      version_size = sizeof(buffer->version);
+      r = uv__copy_utf16_to_utf8(product_name_w,
+                                 -1,
+                                 buffer->version,
+                                 &version_size);
+      if (r)
         goto error;
-      }
     }
   }
 
   /* Append service pack information to the version if present. */
   if (os_info.szCSDVersion[0] != L'\0') {
     if (version_size > 0)
-      buffer->version[version_size - 1] = ' ';
+      buffer->version[version_size++] = ' ';
 
-    if (WideCharToMultiByte(CP_UTF8,
-                            0,
-                            os_info.szCSDVersion,
-                            -1,
-                            buffer->version + version_size,
-                            sizeof(buffer->version) - version_size,
-                            NULL,
-                            NULL) == 0) {
-      r = uv_translate_sys_error(GetLastError());
+    version_size = sizeof(buffer->version) - version_size;
+    r = uv__copy_utf16_to_utf8(os_info.szCSDVersion,
+                               -1,
+                               buffer->version + 
+                                 sizeof(buffer->version) - version_size,
+                               &version_size);
+    if (r)
       goto error;
-    }
   }
 
   /* Populate the sysname field. */
diff --git a/wpinet/src/main/native/thirdparty/libuv/src/win/winsock.cpp b/wpinet/src/main/native/thirdparty/libuv/src/win/winsock.cpp
index cda82bc..7843e9f 100644
--- a/wpinet/src/main/native/thirdparty/libuv/src/win/winsock.cpp
+++ b/wpinet/src/main/native/thirdparty/libuv/src/win/winsock.cpp
@@ -25,7 +25,6 @@
 #include "uv.h"
 #include "internal.h"
 
-
 #pragma comment(lib, "Ws2_32.lib")
 
 /* Whether there are any non-IFS LSPs stacked on TCP */
diff --git a/wpinet/wpinet-config.cmake.in b/wpinet/wpinet-config.cmake.in
index f54fe45..e62719b 100644
--- a/wpinet/wpinet-config.cmake.in
+++ b/wpinet/wpinet-config.cmake.in
@@ -5,3 +5,6 @@
 
 @FILENAME_DEP_REPLACE@
 include(${SELF_DIR}/wpinet.cmake)
+if(@WITH_JAVA@)
+    include(${SELF_DIR}/wpinet_jar.cmake)
+endif()