github.com/sandwichdev/go-internals@v0.0.0-20210605002614-12311ac6b2c5/syscall/execenv/execenv_windows.go (about)

     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  // +build windows
     6  
     7  package execenv
     8  
     9  import (
    10  	"syscall"
    11  	"unicode/utf16"
    12  	"unsafe"
    13  
    14  	"github.com/SandwichDev/go-internals/syscall/windows"
    15  )
    16  
    17  // Default will return the default environment
    18  // variables based on the process attributes
    19  // provided.
    20  //
    21  // If the process attributes contain a token, then
    22  // the environment variables will be sourced from
    23  // the defaults for that user token, otherwise they
    24  // will be sourced from syscall.Environ().
    25  func Default(sys *syscall.SysProcAttr) (env []string, err error) {
    26  	if sys == nil || sys.Token == 0 {
    27  		return syscall.Environ(), nil
    28  	}
    29  	var block *uint16
    30  	err = windows.CreateEnvironmentBlock(&block, sys.Token, false)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	defer windows.DestroyEnvironmentBlock(block)
    35  	blockp := uintptr(unsafe.Pointer(block))
    36  	for {
    37  
    38  		// find NUL terminator
    39  		end := unsafe.Pointer(blockp)
    40  		for *(*uint16)(end) != 0 {
    41  			end = unsafe.Pointer(uintptr(end) + 2)
    42  		}
    43  
    44  		n := (uintptr(end) - uintptr(unsafe.Pointer(blockp))) / 2
    45  		if n == 0 {
    46  			// environment block ends with empty string
    47  			break
    48  		}
    49  
    50  		entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:n:n]
    51  		env = append(env, string(utf16.Decode(entry)))
    52  		blockp += 2 * (uintptr(len(entry)) + 1)
    53  	}
    54  	return
    55  }