windows: replace all StringToUTF16 calls with UTF16FromString

`StringToUTF16` is deprecated and will panic if given an "invalid"
string (in particular, one that has a null byte in it).  The replacement
function is `UTF16FromString`, and it returns an error if there was
a problem.

This change replaces all uses of `StringToUTF16` with `UTF16FromString`.
The `service` struct now no longer stores a `string` name but rather
a `*uint16` pointer to the name.

It should not be possible to panic due to UTF16 string conversion
at this point.

Fixes golang/go#73006

Change-Id: Idce9cdbb4651fef8481f0cad19b5df0314fd4277
Reviewed-on: https://go-review.googlesource.com/c/sys/+/659936
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
Douglas Danger Manley
2025-04-02 11:32:38 -07:00
committed by Gopher Robot
parent 1c3b72f1c1
commit 1b2bd6bb49
8 changed files with 132 additions and 30 deletions
+41 -8
View File
@@ -34,7 +34,11 @@ func Connect() (*Mgr, error) {
func ConnectRemote(host string) (*Mgr, error) {
var s *uint16
if host != "" {
s = syscall.StringToUTF16Ptr(host)
var err error
s, err = syscall.UTF16PtrFromString(host)
if err != nil {
return nil, err
}
}
h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS)
if err != nil {
@@ -78,11 +82,11 @@ func (m *Mgr) LockStatus() (*LockStatus, error) {
}
}
func toPtr(s string) *uint16 {
func toPtr(s string) (*uint16, error) {
if len(s) == 0 {
return nil
return nil, nil
}
return syscall.StringToUTF16Ptr(s)
return syscall.UTF16PtrFromString(s)
}
// toStringBlock terminates strings in ss with 0, and then
@@ -122,10 +126,34 @@ func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Se
for _, v := range args {
s += " " + syscall.EscapeArg(v)
}
h, err := windows.CreateService(m.Handle, toPtr(name), toPtr(c.DisplayName),
namePointer, err := toPtr(name)
if err != nil {
return nil, err
}
displayNamePointer, err := toPtr(c.DisplayName)
if err != nil {
return nil, err
}
sPointer, err := toPtr(s)
if err != nil {
return nil, err
}
loadOrderGroupPointer, err := toPtr(c.LoadOrderGroup)
if err != nil {
return nil, err
}
serviceStartNamePointer, err := toPtr(c.ServiceStartName)
if err != nil {
return nil, err
}
passwordPointer, err := toPtr(c.Password)
if err != nil {
return nil, err
}
h, err := windows.CreateService(m.Handle, namePointer, displayNamePointer,
windows.SERVICE_ALL_ACCESS, c.ServiceType,
c.StartType, c.ErrorControl, toPtr(s), toPtr(c.LoadOrderGroup),
nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), toPtr(c.Password))
c.StartType, c.ErrorControl, sPointer, loadOrderGroupPointer,
nil, toStringBlock(c.Dependencies), serviceStartNamePointer, passwordPointer)
if err != nil {
return nil, err
}
@@ -159,7 +187,12 @@ func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Se
// OpenService retrieves access to service name, so it can
// be interrogated and controlled.
func (m *Mgr) OpenService(name string) (*Service, error) {
h, err := windows.OpenService(m.Handle, syscall.StringToUTF16Ptr(name), windows.SERVICE_ALL_ACCESS)
namePointer, err := syscall.UTF16PtrFromString(name)
if err != nil {
return nil, err
}
h, err := windows.OpenService(m.Handle, namePointer, windows.SERVICE_ALL_ACCESS)
if err != nil {
return nil, err
}