windows: fix slicing of NTUnicodeString values

We were slicing using a count of bytes, not a count of uint16s.

Fixes golang/go#73460

Change-Id: If0fd19e795078c01fda5b976e3c34af115b25dcc
Reviewed-on: https://go-review.googlesource.com/c/sys/+/667235
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Auto-Submit: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@google.com>
diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go
index 4a32543..044fac4 100644
--- a/windows/syscall_windows.go
+++ b/windows/syscall_windows.go
@@ -1698,8 +1698,9 @@
 
 // Slice returns a uint16 slice that aliases the data in the NTUnicodeString.
 func (s *NTUnicodeString) Slice() []uint16 {
-	slice := unsafe.Slice(s.Buffer, s.MaximumLength)
-	return slice[:s.Length]
+	// Note: this rounds the length down, if it happens
+	// to (incorrectly) be odd. Probably safer than rounding up.
+	return unsafe.Slice(s.Buffer, s.MaximumLength/2)[:s.Length/2]
 }
 
 func (s *NTUnicodeString) String() string {
diff --git a/windows/syscall_windows_test.go b/windows/syscall_windows_test.go
index 1e686a4..f81fea0 100644
--- a/windows/syscall_windows_test.go
+++ b/windows/syscall_windows_test.go
@@ -1473,3 +1473,23 @@
 		t.Errorf("UnloadKeyboardLayout failed: %v", err)
 	}
 }
+
+func TestRoundtripNTUnicodeString(t *testing.T) {
+	for _, s := range []string{
+		"",
+		"hello",
+		"Ƀ",
+		strings.Repeat("*", 32000), // NTUnicodeString works up to 2^16 byte lengths == 32768 uint16s.
+		// TODO: various encoding errors?
+	} {
+		ntus, err := windows.NewNTUnicodeString(s)
+		if err != nil {
+			t.Errorf("encoding %q failed: %v", s, err)
+			continue
+		}
+		s2 := ntus.String()
+		if s != s2 {
+			t.Errorf("round trip of %q = %q, wanted original", s, s2)
+		}
+	}
+}
diff --git a/windows/types_windows.go b/windows/types_windows.go
index ad67df2..ce741c9 100644
--- a/windows/types_windows.go
+++ b/windows/types_windows.go
@@ -2700,6 +2700,8 @@
 
 // NTUnicodeString is a UTF-16 string for NT native APIs, corresponding to UNICODE_STRING.
 type NTUnicodeString struct {
+	// Note: Length and MaximumLength are in *bytes*, not uint16s.
+	// They should always be even.
 	Length        uint16
 	MaximumLength uint16
 	Buffer        *uint16