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
5package windows
6
7import (
8	"syscall"
9	"unsafe"
10)
11
12const (
13	STANDARD_RIGHTS_REQUIRED = 0xf0000
14	STANDARD_RIGHTS_READ     = 0x20000
15	STANDARD_RIGHTS_WRITE    = 0x20000
16	STANDARD_RIGHTS_EXECUTE  = 0x20000
17	STANDARD_RIGHTS_ALL      = 0x1F0000
18)
19
20const (
21	NameUnknown          = 0
22	NameFullyQualifiedDN = 1
23	NameSamCompatible    = 2
24	NameDisplay          = 3
25	NameUniqueId         = 6
26	NameCanonical        = 7
27	NameUserPrincipal    = 8
28	NameCanonicalEx      = 9
29	NameServicePrincipal = 10
30	NameDnsDomain        = 12
31)
32
33// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
34// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
35//sys	TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
36//sys	GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
37
38// TranslateAccountName converts a directory service
39// object name from one format to another.
40func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
41	u, e := UTF16PtrFromString(username)
42	if e != nil {
43		return "", e
44	}
45	n := uint32(50)
46	for {
47		b := make([]uint16, n)
48		e = TranslateName(u, from, to, &b[0], &n)
49		if e == nil {
50			return UTF16ToString(b[:n]), nil
51		}
52		if e != ERROR_INSUFFICIENT_BUFFER {
53			return "", e
54		}
55		if n <= uint32(len(b)) {
56			return "", e
57		}
58	}
59}
60
61const (
62	// do not reorder
63	NetSetupUnknownStatus = iota
64	NetSetupUnjoined
65	NetSetupWorkgroupName
66	NetSetupDomainName
67)
68
69type UserInfo10 struct {
70	Name       *uint16
71	Comment    *uint16
72	UsrComment *uint16
73	FullName   *uint16
74}
75
76//sys	NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
77//sys	NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
78//sys	NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
79
80const (
81	// do not reorder
82	SidTypeUser = 1 + iota
83	SidTypeGroup
84	SidTypeDomain
85	SidTypeAlias
86	SidTypeWellKnownGroup
87	SidTypeDeletedAccount
88	SidTypeInvalid
89	SidTypeUnknown
90	SidTypeComputer
91	SidTypeLabel
92)
93
94type SidIdentifierAuthority struct {
95	Value [6]byte
96}
97
98var (
99	SECURITY_NULL_SID_AUTHORITY        = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
100	SECURITY_WORLD_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
101	SECURITY_LOCAL_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
102	SECURITY_CREATOR_SID_AUTHORITY     = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
103	SECURITY_NON_UNIQUE_AUTHORITY      = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
104	SECURITY_NT_AUTHORITY              = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
105	SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
106)
107
108const (
109	SECURITY_NULL_RID                   = 0
110	SECURITY_WORLD_RID                  = 0
111	SECURITY_LOCAL_RID                  = 0
112	SECURITY_CREATOR_OWNER_RID          = 0
113	SECURITY_CREATOR_GROUP_RID          = 1
114	SECURITY_DIALUP_RID                 = 1
115	SECURITY_NETWORK_RID                = 2
116	SECURITY_BATCH_RID                  = 3
117	SECURITY_INTERACTIVE_RID            = 4
118	SECURITY_LOGON_IDS_RID              = 5
119	SECURITY_SERVICE_RID                = 6
120	SECURITY_LOCAL_SYSTEM_RID           = 18
121	SECURITY_BUILTIN_DOMAIN_RID         = 32
122	SECURITY_PRINCIPAL_SELF_RID         = 10
123	SECURITY_CREATOR_OWNER_SERVER_RID   = 0x2
124	SECURITY_CREATOR_GROUP_SERVER_RID   = 0x3
125	SECURITY_LOGON_IDS_RID_COUNT        = 0x3
126	SECURITY_ANONYMOUS_LOGON_RID        = 0x7
127	SECURITY_PROXY_RID                  = 0x8
128	SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
129	SECURITY_SERVER_LOGON_RID           = SECURITY_ENTERPRISE_CONTROLLERS_RID
130	SECURITY_AUTHENTICATED_USER_RID     = 0xb
131	SECURITY_RESTRICTED_CODE_RID        = 0xc
132	SECURITY_NT_NON_UNIQUE_RID          = 0x15
133)
134
135// Predefined domain-relative RIDs for local groups.
136// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
137const (
138	DOMAIN_ALIAS_RID_ADMINS                         = 0x220
139	DOMAIN_ALIAS_RID_USERS                          = 0x221
140	DOMAIN_ALIAS_RID_GUESTS                         = 0x222
141	DOMAIN_ALIAS_RID_POWER_USERS                    = 0x223
142	DOMAIN_ALIAS_RID_ACCOUNT_OPS                    = 0x224
143	DOMAIN_ALIAS_RID_SYSTEM_OPS                     = 0x225
144	DOMAIN_ALIAS_RID_PRINT_OPS                      = 0x226
145	DOMAIN_ALIAS_RID_BACKUP_OPS                     = 0x227
146	DOMAIN_ALIAS_RID_REPLICATOR                     = 0x228
147	DOMAIN_ALIAS_RID_RAS_SERVERS                    = 0x229
148	DOMAIN_ALIAS_RID_PREW2KCOMPACCESS               = 0x22a
149	DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS           = 0x22b
150	DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS      = 0x22c
151	DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
152	DOMAIN_ALIAS_RID_MONITORING_USERS               = 0x22e
153	DOMAIN_ALIAS_RID_LOGGING_USERS                  = 0x22f
154	DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS            = 0x230
155	DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS             = 0x231
156	DOMAIN_ALIAS_RID_DCOM_USERS                     = 0x232
157	DOMAIN_ALIAS_RID_IUSERS                         = 0x238
158	DOMAIN_ALIAS_RID_CRYPTO_OPERATORS               = 0x239
159	DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP     = 0x23b
160	DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
161	DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP        = 0x23d
162	DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP      = 0x23e
163)
164
165//sys	LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
166//sys	LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
167//sys	ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
168//sys	ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
169//sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
170//sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
171//sys	AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
172//sys	createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid
173//sys	FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
174//sys	EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
175
176// The security identifier (SID) structure is a variable-length
177// structure used to uniquely identify users or groups.
178type SID struct{}
179
180// StringToSid converts a string-format security identifier
181// sid into a valid, functional sid.
182func StringToSid(s string) (*SID, error) {
183	var sid *SID
184	p, e := UTF16PtrFromString(s)
185	if e != nil {
186		return nil, e
187	}
188	e = ConvertStringSidToSid(p, &sid)
189	if e != nil {
190		return nil, e
191	}
192	defer LocalFree((Handle)(unsafe.Pointer(sid)))
193	return sid.Copy()
194}
195
196// LookupSID retrieves a security identifier sid for the account
197// and the name of the domain on which the account was found.
198// System specify target computer to search.
199func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
200	if len(account) == 0 {
201		return nil, "", 0, syscall.EINVAL
202	}
203	acc, e := UTF16PtrFromString(account)
204	if e != nil {
205		return nil, "", 0, e
206	}
207	var sys *uint16
208	if len(system) > 0 {
209		sys, e = UTF16PtrFromString(system)
210		if e != nil {
211			return nil, "", 0, e
212		}
213	}
214	n := uint32(50)
215	dn := uint32(50)
216	for {
217		b := make([]byte, n)
218		db := make([]uint16, dn)
219		sid = (*SID)(unsafe.Pointer(&b[0]))
220		e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
221		if e == nil {
222			return sid, UTF16ToString(db), accType, nil
223		}
224		if e != ERROR_INSUFFICIENT_BUFFER {
225			return nil, "", 0, e
226		}
227		if n <= uint32(len(b)) {
228			return nil, "", 0, e
229		}
230	}
231}
232
233// String converts sid to a string format
234// suitable for display, storage, or transmission.
235func (sid *SID) String() (string, error) {
236	var s *uint16
237	e := ConvertSidToStringSid(sid, &s)
238	if e != nil {
239		return "", e
240	}
241	defer LocalFree((Handle)(unsafe.Pointer(s)))
242	return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
243}
244
245// Len returns the length, in bytes, of a valid security identifier sid.
246func (sid *SID) Len() int {
247	return int(GetLengthSid(sid))
248}
249
250// Copy creates a duplicate of security identifier sid.
251func (sid *SID) Copy() (*SID, error) {
252	b := make([]byte, sid.Len())
253	sid2 := (*SID)(unsafe.Pointer(&b[0]))
254	e := CopySid(uint32(len(b)), sid2, sid)
255	if e != nil {
256		return nil, e
257	}
258	return sid2, nil
259}
260
261// LookupAccount retrieves the name of the account for this sid
262// and the name of the first domain on which this sid is found.
263// System specify target computer to search for.
264func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
265	var sys *uint16
266	if len(system) > 0 {
267		sys, err = UTF16PtrFromString(system)
268		if err != nil {
269			return "", "", 0, err
270		}
271	}
272	n := uint32(50)
273	dn := uint32(50)
274	for {
275		b := make([]uint16, n)
276		db := make([]uint16, dn)
277		e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
278		if e == nil {
279			return UTF16ToString(b), UTF16ToString(db), accType, nil
280		}
281		if e != ERROR_INSUFFICIENT_BUFFER {
282			return "", "", 0, e
283		}
284		if n <= uint32(len(b)) {
285			return "", "", 0, e
286		}
287	}
288}
289
290// Various types of pre-specified sids that can be synthesized at runtime.
291type WELL_KNOWN_SID_TYPE uint32
292
293const (
294	WinNullSid                                    = 0
295	WinWorldSid                                   = 1
296	WinLocalSid                                   = 2
297	WinCreatorOwnerSid                            = 3
298	WinCreatorGroupSid                            = 4
299	WinCreatorOwnerServerSid                      = 5
300	WinCreatorGroupServerSid                      = 6
301	WinNtAuthoritySid                             = 7
302	WinDialupSid                                  = 8
303	WinNetworkSid                                 = 9
304	WinBatchSid                                   = 10
305	WinInteractiveSid                             = 11
306	WinServiceSid                                 = 12
307	WinAnonymousSid                               = 13
308	WinProxySid                                   = 14
309	WinEnterpriseControllersSid                   = 15
310	WinSelfSid                                    = 16
311	WinAuthenticatedUserSid                       = 17
312	WinRestrictedCodeSid                          = 18
313	WinTerminalServerSid                          = 19
314	WinRemoteLogonIdSid                           = 20
315	WinLogonIdsSid                                = 21
316	WinLocalSystemSid                             = 22
317	WinLocalServiceSid                            = 23
318	WinNetworkServiceSid                          = 24
319	WinBuiltinDomainSid                           = 25
320	WinBuiltinAdministratorsSid                   = 26
321	WinBuiltinUsersSid                            = 27
322	WinBuiltinGuestsSid                           = 28
323	WinBuiltinPowerUsersSid                       = 29
324	WinBuiltinAccountOperatorsSid                 = 30
325	WinBuiltinSystemOperatorsSid                  = 31
326	WinBuiltinPrintOperatorsSid                   = 32
327	WinBuiltinBackupOperatorsSid                  = 33
328	WinBuiltinReplicatorSid                       = 34
329	WinBuiltinPreWindows2000CompatibleAccessSid   = 35
330	WinBuiltinRemoteDesktopUsersSid               = 36
331	WinBuiltinNetworkConfigurationOperatorsSid    = 37
332	WinAccountAdministratorSid                    = 38
333	WinAccountGuestSid                            = 39
334	WinAccountKrbtgtSid                           = 40
335	WinAccountDomainAdminsSid                     = 41
336	WinAccountDomainUsersSid                      = 42
337	WinAccountDomainGuestsSid                     = 43
338	WinAccountComputersSid                        = 44
339	WinAccountControllersSid                      = 45
340	WinAccountCertAdminsSid                       = 46
341	WinAccountSchemaAdminsSid                     = 47
342	WinAccountEnterpriseAdminsSid                 = 48
343	WinAccountPolicyAdminsSid                     = 49
344	WinAccountRasAndIasServersSid                 = 50
345	WinNTLMAuthenticationSid                      = 51
346	WinDigestAuthenticationSid                    = 52
347	WinSChannelAuthenticationSid                  = 53
348	WinThisOrganizationSid                        = 54
349	WinOtherOrganizationSid                       = 55
350	WinBuiltinIncomingForestTrustBuildersSid      = 56
351	WinBuiltinPerfMonitoringUsersSid              = 57
352	WinBuiltinPerfLoggingUsersSid                 = 58
353	WinBuiltinAuthorizationAccessSid              = 59
354	WinBuiltinTerminalServerLicenseServersSid     = 60
355	WinBuiltinDCOMUsersSid                        = 61
356	WinBuiltinIUsersSid                           = 62
357	WinIUserSid                                   = 63
358	WinBuiltinCryptoOperatorsSid                  = 64
359	WinUntrustedLabelSid                          = 65
360	WinLowLabelSid                                = 66
361	WinMediumLabelSid                             = 67
362	WinHighLabelSid                               = 68
363	WinSystemLabelSid                             = 69
364	WinWriteRestrictedCodeSid                     = 70
365	WinCreatorOwnerRightsSid                      = 71
366	WinCacheablePrincipalsGroupSid                = 72
367	WinNonCacheablePrincipalsGroupSid             = 73
368	WinEnterpriseReadonlyControllersSid           = 74
369	WinAccountReadonlyControllersSid              = 75
370	WinBuiltinEventLogReadersGroup                = 76
371	WinNewEnterpriseReadonlyControllersSid        = 77
372	WinBuiltinCertSvcDComAccessGroup              = 78
373	WinMediumPlusLabelSid                         = 79
374	WinLocalLogonSid                              = 80
375	WinConsoleLogonSid                            = 81
376	WinThisOrganizationCertificateSid             = 82
377	WinApplicationPackageAuthoritySid             = 83
378	WinBuiltinAnyPackageSid                       = 84
379	WinCapabilityInternetClientSid                = 85
380	WinCapabilityInternetClientServerSid          = 86
381	WinCapabilityPrivateNetworkClientServerSid    = 87
382	WinCapabilityPicturesLibrarySid               = 88
383	WinCapabilityVideosLibrarySid                 = 89
384	WinCapabilityMusicLibrarySid                  = 90
385	WinCapabilityDocumentsLibrarySid              = 91
386	WinCapabilitySharedUserCertificatesSid        = 92
387	WinCapabilityEnterpriseAuthenticationSid      = 93
388	WinCapabilityRemovableStorageSid              = 94
389	WinBuiltinRDSRemoteAccessServersSid           = 95
390	WinBuiltinRDSEndpointServersSid               = 96
391	WinBuiltinRDSManagementServersSid             = 97
392	WinUserModeDriversSid                         = 98
393	WinBuiltinHyperVAdminsSid                     = 99
394	WinAccountCloneableControllersSid             = 100
395	WinBuiltinAccessControlAssistanceOperatorsSid = 101
396	WinBuiltinRemoteManagementUsersSid            = 102
397	WinAuthenticationAuthorityAssertedSid         = 103
398	WinAuthenticationServiceAssertedSid           = 104
399	WinLocalAccountSid                            = 105
400	WinLocalAccountAndAdministratorSid            = 106
401	WinAccountProtectedUsersSid                   = 107
402	WinCapabilityAppointmentsSid                  = 108
403	WinCapabilityContactsSid                      = 109
404	WinAccountDefaultSystemManagedSid             = 110
405	WinBuiltinDefaultSystemManagedGroupSid        = 111
406	WinBuiltinStorageReplicaAdminsSid             = 112
407	WinAccountKeyAdminsSid                        = 113
408	WinAccountEnterpriseKeyAdminsSid              = 114
409	WinAuthenticationKeyTrustSid                  = 115
410	WinAuthenticationKeyPropertyMFASid            = 116
411	WinAuthenticationKeyPropertyAttestationSid    = 117
412	WinAuthenticationFreshKeyAuthSid              = 118
413	WinBuiltinDeviceOwnersSid                     = 119
414)
415
416// Creates a sid for a well-known predefined alias, generally using the constants of the form
417// Win*Sid, for the local machine.
418func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) {
419	return CreateWellKnownDomainSid(sidType, nil)
420}
421
422// Creates a sid for a well-known predefined alias, generally using the constants of the form
423// Win*Sid, for the domain specified by the domainSid parameter.
424func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) {
425	n := uint32(50)
426	for {
427		b := make([]byte, n)
428		sid := (*SID)(unsafe.Pointer(&b[0]))
429		err := createWellKnownSid(sidType, domainSid, sid, &n)
430		if err == nil {
431			return sid, nil
432		}
433		if err != ERROR_INSUFFICIENT_BUFFER {
434			return nil, err
435		}
436		if n <= uint32(len(b)) {
437			return nil, err
438		}
439	}
440}
441
442const (
443	// do not reorder
444	TOKEN_ASSIGN_PRIMARY = 1 << iota
445	TOKEN_DUPLICATE
446	TOKEN_IMPERSONATE
447	TOKEN_QUERY
448	TOKEN_QUERY_SOURCE
449	TOKEN_ADJUST_PRIVILEGES
450	TOKEN_ADJUST_GROUPS
451	TOKEN_ADJUST_DEFAULT
452	TOKEN_ADJUST_SESSIONID
453
454	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
455		TOKEN_ASSIGN_PRIMARY |
456		TOKEN_DUPLICATE |
457		TOKEN_IMPERSONATE |
458		TOKEN_QUERY |
459		TOKEN_QUERY_SOURCE |
460		TOKEN_ADJUST_PRIVILEGES |
461		TOKEN_ADJUST_GROUPS |
462		TOKEN_ADJUST_DEFAULT |
463		TOKEN_ADJUST_SESSIONID
464	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
465	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
466		TOKEN_ADJUST_PRIVILEGES |
467		TOKEN_ADJUST_GROUPS |
468		TOKEN_ADJUST_DEFAULT
469	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
470)
471
472const (
473	// do not reorder
474	TokenUser = 1 + iota
475	TokenGroups
476	TokenPrivileges
477	TokenOwner
478	TokenPrimaryGroup
479	TokenDefaultDacl
480	TokenSource
481	TokenType
482	TokenImpersonationLevel
483	TokenStatistics
484	TokenRestrictedSids
485	TokenSessionId
486	TokenGroupsAndPrivileges
487	TokenSessionReference
488	TokenSandBoxInert
489	TokenAuditPolicy
490	TokenOrigin
491	TokenElevationType
492	TokenLinkedToken
493	TokenElevation
494	TokenHasRestrictions
495	TokenAccessInformation
496	TokenVirtualizationAllowed
497	TokenVirtualizationEnabled
498	TokenIntegrityLevel
499	TokenUIAccess
500	TokenMandatoryPolicy
501	TokenLogonSid
502	MaxTokenInfoClass
503)
504
505type SIDAndAttributes struct {
506	Sid        *SID
507	Attributes uint32
508}
509
510type Tokenuser struct {
511	User SIDAndAttributes
512}
513
514type Tokenprimarygroup struct {
515	PrimaryGroup *SID
516}
517
518type Tokengroups struct {
519	GroupCount uint32
520	Groups     [1]SIDAndAttributes
521}
522
523// Authorization Functions
524//sys checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
525//sys	OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
526//sys	GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
527//sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
528//sys	getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
529
530// An access token contains the security information for a logon session.
531// The system creates an access token when a user logs on, and every
532// process executed on behalf of the user has a copy of the token.
533// The token identifies the user, the user's groups, and the user's
534// privileges. The system uses the token to control access to securable
535// objects and to control the ability of the user to perform various
536// system-related operations on the local computer.
537type Token Handle
538
539// OpenCurrentProcessToken opens the access token
540// associated with current process.
541func OpenCurrentProcessToken() (Token, error) {
542	p, e := GetCurrentProcess()
543	if e != nil {
544		return 0, e
545	}
546	var t Token
547	e = OpenProcessToken(p, TOKEN_QUERY, &t)
548	if e != nil {
549		return 0, e
550	}
551	return t, nil
552}
553
554// Close releases access to access token.
555func (t Token) Close() error {
556	return CloseHandle(Handle(t))
557}
558
559// getInfo retrieves a specified type of information about an access token.
560func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
561	n := uint32(initSize)
562	for {
563		b := make([]byte, n)
564		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
565		if e == nil {
566			return unsafe.Pointer(&b[0]), nil
567		}
568		if e != ERROR_INSUFFICIENT_BUFFER {
569			return nil, e
570		}
571		if n <= uint32(len(b)) {
572			return nil, e
573		}
574	}
575}
576
577// GetTokenUser retrieves access token t user account information.
578func (t Token) GetTokenUser() (*Tokenuser, error) {
579	i, e := t.getInfo(TokenUser, 50)
580	if e != nil {
581		return nil, e
582	}
583	return (*Tokenuser)(i), nil
584}
585
586// GetTokenGroups retrieves group accounts associated with access token t.
587func (t Token) GetTokenGroups() (*Tokengroups, error) {
588	i, e := t.getInfo(TokenGroups, 50)
589	if e != nil {
590		return nil, e
591	}
592	return (*Tokengroups)(i), nil
593}
594
595// GetTokenPrimaryGroup retrieves access token t primary group information.
596// A pointer to a SID structure representing a group that will become
597// the primary group of any objects created by a process using this access token.
598func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
599	i, e := t.getInfo(TokenPrimaryGroup, 50)
600	if e != nil {
601		return nil, e
602	}
603	return (*Tokenprimarygroup)(i), nil
604}
605
606// GetUserProfileDirectory retrieves path to the
607// root directory of the access token t user's profile.
608func (t Token) GetUserProfileDirectory() (string, error) {
609	n := uint32(100)
610	for {
611		b := make([]uint16, n)
612		e := GetUserProfileDirectory(t, &b[0], &n)
613		if e == nil {
614			return UTF16ToString(b), nil
615		}
616		if e != ERROR_INSUFFICIENT_BUFFER {
617			return "", e
618		}
619		if n <= uint32(len(b)) {
620			return "", e
621		}
622	}
623}
624
625// GetSystemDirectory retrieves path to current location of the system
626// directory, which is typically, though not always, C:\Windows\System32.
627func GetSystemDirectory() (string, error) {
628	n := uint32(MAX_PATH)
629	for {
630		b := make([]uint16, n)
631		l, e := getSystemDirectory(&b[0], n)
632		if e != nil {
633			return "", e
634		}
635		if l <= n {
636			return UTF16ToString(b[:l]), nil
637		}
638		n = l
639	}
640}
641
642// IsMember reports whether the access token t is a member of the provided SID.
643func (t Token) IsMember(sid *SID) (bool, error) {
644	var b int32
645	if e := checkTokenMembership(t, sid, &b); e != nil {
646		return false, e
647	}
648	return b != 0, nil
649}
650