execenv_windows.mx raw

   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  
   7  package execenv
   8  
   9  import (
  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().
  23  func 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