github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/pkg/system/syscall_windows.go (about)

     1  package system // import "github.com/docker/docker/pkg/system"
     2  
     3  import (
     4  	"fmt"
     5  	"syscall"
     6  	"unsafe"
     7  
     8  	"github.com/sirupsen/logrus"
     9  	"golang.org/x/sys/windows"
    10  )
    11  
    12  const (
    13  	OWNER_SECURITY_INFORMATION               = 0x00000001
    14  	GROUP_SECURITY_INFORMATION               = 0x00000002
    15  	DACL_SECURITY_INFORMATION                = 0x00000004
    16  	SACL_SECURITY_INFORMATION                = 0x00000008
    17  	LABEL_SECURITY_INFORMATION               = 0x00000010
    18  	ATTRIBUTE_SECURITY_INFORMATION           = 0x00000020
    19  	SCOPE_SECURITY_INFORMATION               = 0x00000040
    20  	PROCESS_TRUST_LABEL_SECURITY_INFORMATION = 0x00000080
    21  	ACCESS_FILTER_SECURITY_INFORMATION       = 0x00000100
    22  	BACKUP_SECURITY_INFORMATION              = 0x00010000
    23  	PROTECTED_DACL_SECURITY_INFORMATION      = 0x80000000
    24  	PROTECTED_SACL_SECURITY_INFORMATION      = 0x40000000
    25  	UNPROTECTED_DACL_SECURITY_INFORMATION    = 0x20000000
    26  	UNPROTECTED_SACL_SECURITY_INFORMATION    = 0x10000000
    27  )
    28  
    29  const (
    30  	SE_UNKNOWN_OBJECT_TYPE = iota
    31  	SE_FILE_OBJECT
    32  	SE_SERVICE
    33  	SE_PRINTER
    34  	SE_REGISTRY_KEY
    35  	SE_LMSHARE
    36  	SE_KERNEL_OBJECT
    37  	SE_WINDOW_OBJECT
    38  	SE_DS_OBJECT
    39  	SE_DS_OBJECT_ALL
    40  	SE_PROVIDER_DEFINED_OBJECT
    41  	SE_WMIGUID_OBJECT
    42  	SE_REGISTRY_WOW64_32KEY
    43  )
    44  
    45  const (
    46  	SeTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege"
    47  )
    48  
    49  const (
    50  	ContainerAdministratorSidString = "S-1-5-93-2-1"
    51  	ContainerUserSidString          = "S-1-5-93-2-2"
    52  )
    53  
    54  var (
    55  	ntuserApiset                  = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
    56  	modadvapi32                   = windows.NewLazySystemDLL("advapi32.dll")
    57  	procGetVersionExW             = modkernel32.NewProc("GetVersionExW")
    58  	procGetProductInfo            = modkernel32.NewProc("GetProductInfo")
    59  	procSetNamedSecurityInfo      = modadvapi32.NewProc("SetNamedSecurityInfoW")
    60  	procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl")
    61  )
    62  
    63  // OSVersion is a wrapper for Windows version information
    64  // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
    65  type OSVersion struct {
    66  	Version      uint32
    67  	MajorVersion uint8
    68  	MinorVersion uint8
    69  	Build        uint16
    70  }
    71  
    72  // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
    73  type osVersionInfoEx struct {
    74  	OSVersionInfoSize uint32
    75  	MajorVersion      uint32
    76  	MinorVersion      uint32
    77  	BuildNumber       uint32
    78  	PlatformID        uint32
    79  	CSDVersion        [128]uint16
    80  	ServicePackMajor  uint16
    81  	ServicePackMinor  uint16
    82  	SuiteMask         uint16
    83  	ProductType       byte
    84  	Reserve           byte
    85  }
    86  
    87  // GetOSVersion gets the operating system version on Windows. Note that
    88  // docker.exe must be manifested to get the correct version information.
    89  func GetOSVersion() OSVersion {
    90  	var err error
    91  	osv := OSVersion{}
    92  	osv.Version, err = windows.GetVersion()
    93  	if err != nil {
    94  		// GetVersion never fails.
    95  		panic(err)
    96  	}
    97  	osv.MajorVersion = uint8(osv.Version & 0xFF)
    98  	osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
    99  	osv.Build = uint16(osv.Version >> 16)
   100  	return osv
   101  }
   102  
   103  func (osv OSVersion) ToString() string {
   104  	return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build)
   105  }
   106  
   107  // IsWindowsClient returns true if the SKU is client
   108  // @engine maintainers - this function should not be removed or modified as it
   109  // is used to enforce licensing restrictions on Windows.
   110  func IsWindowsClient() bool {
   111  	osviex := &osVersionInfoEx{OSVersionInfoSize: 284}
   112  	r1, _, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(osviex)))
   113  	if r1 == 0 {
   114  		logrus.Warnf("GetVersionExW failed - assuming server SKU: %v", err)
   115  		return false
   116  	}
   117  	const verNTWorkstation = 0x00000001
   118  	return osviex.ProductType == verNTWorkstation
   119  }
   120  
   121  // IsIoTCore returns true if the currently running image is based off of
   122  // Windows 10 IoT Core.
   123  // @engine maintainers - this function should not be removed or modified as it
   124  // is used to enforce licensing restrictions on Windows.
   125  func IsIoTCore() bool {
   126  	var returnedProductType uint32
   127  	r1, _, err := procGetProductInfo.Call(6, 1, 0, 0, uintptr(unsafe.Pointer(&returnedProductType)))
   128  	if r1 == 0 {
   129  		logrus.Warnf("GetProductInfo failed - assuming this is not IoT: %v", err)
   130  		return false
   131  	}
   132  	const productIoTUAP = 0x0000007B
   133  	const productIoTUAPCommercial = 0x00000083
   134  	return returnedProductType == productIoTUAP || returnedProductType == productIoTUAPCommercial
   135  }
   136  
   137  // Unmount is a platform-specific helper function to call
   138  // the unmount syscall. Not supported on Windows
   139  func Unmount(dest string) error {
   140  	return nil
   141  }
   142  
   143  // CommandLineToArgv wraps the Windows syscall to turn a commandline into an argument array.
   144  func CommandLineToArgv(commandLine string) ([]string, error) {
   145  	var argc int32
   146  
   147  	argsPtr, err := windows.UTF16PtrFromString(commandLine)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	argv, err := windows.CommandLineToArgv(argsPtr, &argc)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  	defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(argv))))
   157  
   158  	newArgs := make([]string, argc)
   159  	for i, v := range (*argv)[:argc] {
   160  		newArgs[i] = string(windows.UTF16ToString((*v)[:]))
   161  	}
   162  
   163  	return newArgs, nil
   164  }
   165  
   166  // HasWin32KSupport determines whether containers that depend on win32k can
   167  // run on this machine. Win32k is the driver used to implement windowing.
   168  func HasWin32KSupport() bool {
   169  	// For now, check for ntuser API support on the host. In the future, a host
   170  	// may support win32k in containers even if the host does not support ntuser
   171  	// APIs.
   172  	return ntuserApiset.Load() == nil
   173  }
   174  
   175  func SetNamedSecurityInfo(objectName *uint16, objectType uint32, securityInformation uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *byte, sacl *byte) (result error) {
   176  	r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfo.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(sidOwner)), uintptr(unsafe.Pointer(sidGroup)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0)
   177  	if r0 != 0 {
   178  		result = syscall.Errno(r0)
   179  	}
   180  	return
   181  }
   182  
   183  func GetSecurityDescriptorDacl(securityDescriptor *byte, daclPresent *uint32, dacl **byte, daclDefaulted *uint32) (result error) {
   184  	r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(securityDescriptor)), uintptr(unsafe.Pointer(daclPresent)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclDefaulted)), 0, 0)
   185  	if r1 == 0 {
   186  		if e1 != 0 {
   187  			result = syscall.Errno(e1)
   188  		} else {
   189  			result = syscall.EINVAL
   190  		}
   191  	}
   192  	return
   193  }