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
+13 -7
View File
@@ -132,10 +132,10 @@ type ctlEvent struct {
// service provides access to windows service api.
type service struct {
name string
h windows.Handle
c chan ctlEvent
handler Handler
namePointer *uint16
h windows.Handle
c chan ctlEvent
handler Handler
}
type exitCode struct {
@@ -209,7 +209,7 @@ var theService service // This is, unfortunately, a global, which means only one
// serviceMain is the entry point called by the service manager, registered earlier by
// the call to StartServiceCtrlDispatcher.
func serviceMain(argc uint32, argv **uint16) uintptr {
handle, err := windows.RegisterServiceCtrlHandlerEx(windows.StringToUTF16Ptr(theService.name), ctlHandlerCallback, 0)
handle, err := windows.RegisterServiceCtrlHandlerEx(theService.namePointer, ctlHandlerCallback, 0)
if sysErr, ok := err.(windows.Errno); ok {
return uintptr(sysErr)
} else if err != nil {
@@ -280,15 +280,21 @@ loop:
// Run executes service name by calling appropriate handler function.
func Run(name string, handler Handler) error {
// Check to make sure that the service name is valid.
namePointer, err := windows.UTF16PtrFromString(name)
if err != nil {
return err
}
initCallbacks.Do(func() {
ctlHandlerCallback = windows.NewCallback(ctlHandler)
serviceMainCallback = windows.NewCallback(serviceMain)
})
theService.name = name
theService.namePointer = namePointer
theService.handler = handler
theService.c = make(chan ctlEvent)
t := []windows.SERVICE_TABLE_ENTRY{
{ServiceName: windows.StringToUTF16Ptr(theService.name), ServiceProc: serviceMainCallback},
{ServiceName: namePointer, ServiceProc: serviceMainCallback},
{ServiceName: nil, ServiceProc: 0},
}
return windows.StartServiceCtrlDispatcher(&t[0])