1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build windows
6
7package execenv
8
9import (
10	"internal/syscall/windows"
11	"syscall"
12	"unsafe"
13)
14
15// Default will return the default environment
16// variables based on the process attributes
17// provided.
18//
19// If the process attributes contain a token, then
20// the environment variables will be sourced from
21// the defaults for that user token, otherwise they
22// will be sourced from syscall.Environ().
23func Default(sys *syscall.SysProcAttr) (env []string, err error) {
24	if sys == nil || sys.Token == 0 {
25		return syscall.Environ(), nil
26	}
27	var blockp *uint16
28	err = windows.CreateEnvironmentBlock(&blockp, sys.Token, false)
29	if err != nil {
30		return nil, err
31	}
32	defer windows.DestroyEnvironmentBlock(blockp)
33
34	const size = unsafe.Sizeof(*blockp)
35	for *blockp != 0 { // environment block ends with empty string
36		// find NUL terminator
37		end := unsafe.Add(unsafe.Pointer(blockp), size)
38		for *(*uint16)(end) != 0 {
39			end = unsafe.Add(end, size)
40		}
41
42		entry := unsafe.Slice(blockp, (uintptr(end)-uintptr(unsafe.Pointer(blockp)))/2)
43		env = append(env, syscall.UTF16ToString(entry))
44		blockp = (*uint16)(unsafe.Add(end, size))
45	}
46	return
47}
48