Skip to content

Commit d9bb5f6

Browse files
committed
syscall: fix and document uses of RegEnumKeyEx
RegEnumKeyEx has an undocumented requirement that subsequent calls need to be made from the same thread. This change documents that requirement and fixes uses of it in std. Fixes #49320. Change-Id: I6d182227e22dd437996a878b3a978943f01b2d61 Reviewed-on: https://go-review.googlesource.com/c/go/+/361154 Trust: Michael Knyszek <[email protected]> Run-TryBot: Michael Knyszek <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 240df18 commit d9bb5f6

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

src/internal/syscall/windows/registry/key.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
//
2626
package registry
2727

28-
import "syscall"
28+
import (
29+
"runtime"
30+
"syscall"
31+
)
2932

3033
const (
3134
// Registry key security and access rights.
@@ -88,6 +91,12 @@ func OpenKey(k Key, path string, access uint32) (Key, error) {
8891

8992
// ReadSubKeyNames returns the names of subkeys of key k.
9093
func (k Key) ReadSubKeyNames() ([]string, error) {
94+
// RegEnumKeyEx must be called repeatedly and to completion.
95+
// During this time, this goroutine cannot migrate away from
96+
// its current thread. See #49320.
97+
runtime.LockOSThread()
98+
defer runtime.UnlockOSThread()
99+
91100
names := make([]string, 0)
92101
// Registry key size limit is 255 bytes and described there:
93102
// https://msdn.microsoft.com/library/windows/desktop/ms724872.aspx

src/syscall/syscall_windows.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
279279
//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
280280
//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
281281
//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW
282-
//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
282+
//sys regEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
283283
//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
284284
//sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
285285
//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
@@ -1301,3 +1301,31 @@ func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LI
13011301
}
13021302
return al, nil
13031303
}
1304+
1305+
// RegEnumKeyEx enumerates the subkeys of an open registry key.
1306+
// Each call retrieves information about one subkey. name is
1307+
// a buffer that should be large enough to hold the name of the
1308+
// subkey plus a null terminating character. nameLen is its
1309+
// length. On return, nameLen will contain the actual length of the
1310+
// subkey.
1311+
//
1312+
// Should name not be large enough to hold the subkey, this function
1313+
// will return ERROR_MORE_DATA, and must be called again with an
1314+
// appropriately sized buffer.
1315+
//
1316+
// reserved must be nil. class and classLen behave like name and nameLen
1317+
// but for the class of the subkey, except that they are optional.
1318+
// lastWriteTime, if not nil, will be populated with the time the subkey
1319+
// was last written.
1320+
//
1321+
// The caller must enumerate all subkeys in order. That is
1322+
// RegEnumKeyEx must be called with index starting at 0, incrementing
1323+
// the index until the function returns ERROR_NO_MORE_ITEMS, or with
1324+
// the index of the last subkey (obtainable from RegQueryInfoKey),
1325+
// decrementing until index 0 is enumerated.
1326+
//
1327+
// Successive calls to this API must happen on the same OS thread,
1328+
// so call runtime.LockOSThread before calling this function.
1329+
func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
1330+
return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime)
1331+
}

src/syscall/zsyscall_windows.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)