windows: manually initialize NewNTUnicodeString

The `RtlInitUnicodeString` syscall can be avoided by manually
initializing the `NTUnicodeString`.

The process is described in [WdmlibRtlInitUnicodeStringEx](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdmsec/nf-wdmsec-wdmlibrtlinitunicodestringex).

The less syscalls, the better. It also makes the function faster:

```
goos: windows
goarch: amd64
pkg: golang.org/x/sys/windows
cpu: Intel(R) Core(TM) i7-10850H CPU @ 2.70GHz
                      │    old.txt    │               new.txt                │
                      │    sec/op     │    sec/op     vs base                │
NewNTUnicodeString-12   181.05n ± 15%   96.32n ± 11%  -46.80% (p=0.000 n=10)
```

Change-Id: Iaf079acdcc2024cdca6b6b649a711f6be99c5b87
Reviewed-on: https://go-review.googlesource.com/c/sys/+/618175
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
qmuntal
2024-10-07 12:34:12 +02:00
committed by Quim Muntal
parent 23b0dabe63
commit 7143f4a4e1

View File

@@ -1685,13 +1685,16 @@ func (s NTStatus) Error() string {
// do not use NTUnicodeString, and instead UTF16PtrFromString should be used for
// the more common *uint16 string type.
func NewNTUnicodeString(s string) (*NTUnicodeString, error) {
var u NTUnicodeString
s16, err := UTF16PtrFromString(s)
s16, err := UTF16FromString(s)
if err != nil {
return nil, err
}
RtlInitUnicodeString(&u, s16)
return &u, nil
n := uint16(len(s16) * 2)
return &NTUnicodeString{
Length: n - 2, // subtract 2 bytes for the NULL terminator
MaximumLength: n,
Buffer: &s16[0],
}, nil
}
// Slice returns a uint16 slice that aliases the data in the NTUnicodeString.