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