github.com/zxy12/golang_with_comment@v0.0.0-20190701084843-0e6b2aff5ef3/os/user/lookup_windows.go (about)

     1  // Copyright 2012 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  package user
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  	"syscall"
    11  	"unsafe"
    12  )
    13  
    14  func init() {
    15  	groupImplemented = false
    16  }
    17  
    18  func isDomainJoined() (bool, error) {
    19  	var domain *uint16
    20  	var status uint32
    21  	err := syscall.NetGetJoinInformation(nil, &domain, &status)
    22  	if err != nil {
    23  		return false, err
    24  	}
    25  	syscall.NetApiBufferFree((*byte)(unsafe.Pointer(domain)))
    26  	return status == syscall.NetSetupDomainName, nil
    27  }
    28  
    29  func lookupFullNameDomain(domainAndUser string) (string, error) {
    30  	return syscall.TranslateAccountName(domainAndUser,
    31  		syscall.NameSamCompatible, syscall.NameDisplay, 50)
    32  }
    33  
    34  func lookupFullNameServer(servername, username string) (string, error) {
    35  	s, e := syscall.UTF16PtrFromString(servername)
    36  	if e != nil {
    37  		return "", e
    38  	}
    39  	u, e := syscall.UTF16PtrFromString(username)
    40  	if e != nil {
    41  		return "", e
    42  	}
    43  	var p *byte
    44  	e = syscall.NetUserGetInfo(s, u, 10, &p)
    45  	if e != nil {
    46  		return "", e
    47  	}
    48  	defer syscall.NetApiBufferFree(p)
    49  	i := (*syscall.UserInfo10)(unsafe.Pointer(p))
    50  	if i.FullName == nil {
    51  		return "", nil
    52  	}
    53  	name := syscall.UTF16ToString((*[1024]uint16)(unsafe.Pointer(i.FullName))[:])
    54  	return name, nil
    55  }
    56  
    57  func lookupFullName(domain, username, domainAndUser string) (string, error) {
    58  	joined, err := isDomainJoined()
    59  	if err == nil && joined {
    60  		name, err := lookupFullNameDomain(domainAndUser)
    61  		if err == nil {
    62  			return name, nil
    63  		}
    64  	}
    65  	name, err := lookupFullNameServer(domain, username)
    66  	if err == nil {
    67  		return name, nil
    68  	}
    69  	// domain worked neither as a domain nor as a server
    70  	// could be domain server unavailable
    71  	// pretend username is fullname
    72  	return username, nil
    73  }
    74  
    75  func newUser(usid *syscall.SID, gid, dir string) (*User, error) {
    76  	username, domain, t, e := usid.LookupAccount("")
    77  	if e != nil {
    78  		return nil, e
    79  	}
    80  	if t != syscall.SidTypeUser {
    81  		return nil, fmt.Errorf("user: should be user account type, not %d", t)
    82  	}
    83  	domainAndUser := domain + `\` + username
    84  	uid, e := usid.String()
    85  	if e != nil {
    86  		return nil, e
    87  	}
    88  	name, e := lookupFullName(domain, username, domainAndUser)
    89  	if e != nil {
    90  		return nil, e
    91  	}
    92  	u := &User{
    93  		Uid:      uid,
    94  		Gid:      gid,
    95  		Username: domainAndUser,
    96  		Name:     name,
    97  		HomeDir:  dir,
    98  	}
    99  	return u, nil
   100  }
   101  
   102  func current() (*User, error) {
   103  	t, e := syscall.OpenCurrentProcessToken()
   104  	if e != nil {
   105  		return nil, e
   106  	}
   107  	defer t.Close()
   108  	u, e := t.GetTokenUser()
   109  	if e != nil {
   110  		return nil, e
   111  	}
   112  	pg, e := t.GetTokenPrimaryGroup()
   113  	if e != nil {
   114  		return nil, e
   115  	}
   116  	gid, e := pg.PrimaryGroup.String()
   117  	if e != nil {
   118  		return nil, e
   119  	}
   120  	dir, e := t.GetUserProfileDirectory()
   121  	if e != nil {
   122  		return nil, e
   123  	}
   124  	return newUser(u.User.Sid, gid, dir)
   125  }
   126  
   127  // BUG(brainman): Lookup and LookupId functions do not set
   128  // Gid and HomeDir fields in the User struct returned on windows.
   129  
   130  func newUserFromSid(usid *syscall.SID) (*User, error) {
   131  	// TODO(brainman): do not know where to get gid and dir fields
   132  	gid := "unknown"
   133  	dir := "Unknown directory"
   134  	return newUser(usid, gid, dir)
   135  }
   136  
   137  func lookupUser(username string) (*User, error) {
   138  	sid, _, t, e := syscall.LookupSID("", username)
   139  	if e != nil {
   140  		return nil, e
   141  	}
   142  	if t != syscall.SidTypeUser {
   143  		return nil, fmt.Errorf("user: should be user account type, not %d", t)
   144  	}
   145  	return newUserFromSid(sid)
   146  }
   147  
   148  func lookupUserId(uid string) (*User, error) {
   149  	sid, e := syscall.StringToSid(uid)
   150  	if e != nil {
   151  		return nil, e
   152  	}
   153  	return newUserFromSid(sid)
   154  }
   155  
   156  func lookupGroup(groupname string) (*Group, error) {
   157  	return nil, errors.New("user: LookupGroup not implemented on windows")
   158  }
   159  
   160  func lookupGroupId(string) (*Group, error) {
   161  	return nil, errors.New("user: LookupGroupId not implemented on windows")
   162  }
   163  
   164  func listGroups(*User) ([]string, error) {
   165  	return nil, errors.New("user: GroupIds not implemented on windows")
   166  }