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	NameUnknown          = 0
14	NameFullyQualifiedDN = 1
15	NameSamCompatible    = 2
16	NameDisplay          = 3
17	NameUniqueId         = 6
18	NameCanonical        = 7
19	NameUserPrincipal    = 8
20	NameCanonicalEx      = 9
21	NameServicePrincipal = 10
22	NameDnsDomain        = 12
23)
24
25// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
26// http://blogs.msdn.com/b/drnick/archive/2007/12/19/windows-and-upn-format-credentials.aspx
27//sys	TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.TranslateNameW
28//sys	GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) [failretval&0xff==0] = secur32.GetUserNameExW
29
30// TranslateAccountName converts a directory service
31// object name from one format to another.
32func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
33	u, e := UTF16PtrFromString(username)
34	if e != nil {
35		return "", e
36	}
37	n := uint32(50)
38	for {
39		b := make([]uint16, n)
40		e = TranslateName(u, from, to, &b[0], &n)
41		if e == nil {
42			return UTF16ToString(b[:n]), nil
43		}
44		if e != ERROR_INSUFFICIENT_BUFFER {
45			return "", e
46		}
47		if n <= uint32(len(b)) {
48			return "", e
49		}
50	}
51}
52
53const (
54	// do not reorder
55	NetSetupUnknownStatus = iota
56	NetSetupUnjoined
57	NetSetupWorkgroupName
58	NetSetupDomainName
59)
60
61type UserInfo10 struct {
62	Name       *uint16
63	Comment    *uint16
64	UsrComment *uint16
65	FullName   *uint16
66}
67
68//sys	NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo
69//sys	NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation
70//sys	NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree
71
72const (
73	// do not reorder
74	SidTypeUser = 1 + iota
75	SidTypeGroup
76	SidTypeDomain
77	SidTypeAlias
78	SidTypeWellKnownGroup
79	SidTypeDeletedAccount
80	SidTypeInvalid
81	SidTypeUnknown
82	SidTypeComputer
83	SidTypeLabel
84)
85
86type SidIdentifierAuthority struct {
87	Value [6]byte
88}
89
90var (
91	SECURITY_NULL_SID_AUTHORITY        = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 0}}
92	SECURITY_WORLD_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 1}}
93	SECURITY_LOCAL_SID_AUTHORITY       = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 2}}
94	SECURITY_CREATOR_SID_AUTHORITY     = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 3}}
95	SECURITY_NON_UNIQUE_AUTHORITY      = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 4}}
96	SECURITY_NT_AUTHORITY              = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 5}}
97	SECURITY_MANDATORY_LABEL_AUTHORITY = SidIdentifierAuthority{[6]byte{0, 0, 0, 0, 0, 16}}
98)
99
100const (
101	SECURITY_NULL_RID                   = 0
102	SECURITY_WORLD_RID                  = 0
103	SECURITY_LOCAL_RID                  = 0
104	SECURITY_CREATOR_OWNER_RID          = 0
105	SECURITY_CREATOR_GROUP_RID          = 1
106	SECURITY_DIALUP_RID                 = 1
107	SECURITY_NETWORK_RID                = 2
108	SECURITY_BATCH_RID                  = 3
109	SECURITY_INTERACTIVE_RID            = 4
110	SECURITY_LOGON_IDS_RID              = 5
111	SECURITY_SERVICE_RID                = 6
112	SECURITY_LOCAL_SYSTEM_RID           = 18
113	SECURITY_BUILTIN_DOMAIN_RID         = 32
114	SECURITY_PRINCIPAL_SELF_RID         = 10
115	SECURITY_CREATOR_OWNER_SERVER_RID   = 0x2
116	SECURITY_CREATOR_GROUP_SERVER_RID   = 0x3
117	SECURITY_LOGON_IDS_RID_COUNT        = 0x3
118	SECURITY_ANONYMOUS_LOGON_RID        = 0x7
119	SECURITY_PROXY_RID                  = 0x8
120	SECURITY_ENTERPRISE_CONTROLLERS_RID = 0x9
121	SECURITY_SERVER_LOGON_RID           = SECURITY_ENTERPRISE_CONTROLLERS_RID
122	SECURITY_AUTHENTICATED_USER_RID     = 0xb
123	SECURITY_RESTRICTED_CODE_RID        = 0xc
124	SECURITY_NT_NON_UNIQUE_RID          = 0x15
125)
126
127// Predefined domain-relative RIDs for local groups.
128// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
129const (
130	DOMAIN_ALIAS_RID_ADMINS                         = 0x220
131	DOMAIN_ALIAS_RID_USERS                          = 0x221
132	DOMAIN_ALIAS_RID_GUESTS                         = 0x222
133	DOMAIN_ALIAS_RID_POWER_USERS                    = 0x223
134	DOMAIN_ALIAS_RID_ACCOUNT_OPS                    = 0x224
135	DOMAIN_ALIAS_RID_SYSTEM_OPS                     = 0x225
136	DOMAIN_ALIAS_RID_PRINT_OPS                      = 0x226
137	DOMAIN_ALIAS_RID_BACKUP_OPS                     = 0x227
138	DOMAIN_ALIAS_RID_REPLICATOR                     = 0x228
139	DOMAIN_ALIAS_RID_RAS_SERVERS                    = 0x229
140	DOMAIN_ALIAS_RID_PREW2KCOMPACCESS               = 0x22a
141	DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS           = 0x22b
142	DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS      = 0x22c
143	DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS = 0x22d
144	DOMAIN_ALIAS_RID_MONITORING_USERS               = 0x22e
145	DOMAIN_ALIAS_RID_LOGGING_USERS                  = 0x22f
146	DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS            = 0x230
147	DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS             = 0x231
148	DOMAIN_ALIAS_RID_DCOM_USERS                     = 0x232
149	DOMAIN_ALIAS_RID_IUSERS                         = 0x238
150	DOMAIN_ALIAS_RID_CRYPTO_OPERATORS               = 0x239
151	DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP     = 0x23b
152	DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP = 0x23c
153	DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP        = 0x23d
154	DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP      = 0x23e
155)
156
157//sys	LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountSidW
158//sys	LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) = advapi32.LookupAccountNameW
159//sys	ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) = advapi32.ConvertSidToStringSidW
160//sys	ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) = advapi32.ConvertStringSidToSidW
161//sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
162//sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
163//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
164//sys	createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid
165//sys	isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) = advapi32.IsWellKnownSid
166//sys	FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
167//sys	EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
168//sys	getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) = advapi32.GetSidIdentifierAuthority
169//sys	getSidSubAuthorityCount(sid *SID) (count *uint8) = advapi32.GetSidSubAuthorityCount
170//sys	getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) = advapi32.GetSidSubAuthority
171//sys	isValidSid(sid *SID) (isValid bool) = advapi32.IsValidSid
172
173// The security identifier (SID) structure is a variable-length
174// structure used to uniquely identify users or groups.
175type SID struct{}
176
177// StringToSid converts a string-format security identifier
178// SID into a valid, functional SID.
179func StringToSid(s string) (*SID, error) {
180	var sid *SID
181	p, e := UTF16PtrFromString(s)
182	if e != nil {
183		return nil, e
184	}
185	e = ConvertStringSidToSid(p, &sid)
186	if e != nil {
187		return nil, e
188	}
189	defer LocalFree((Handle)(unsafe.Pointer(sid)))
190	return sid.Copy()
191}
192
193// LookupSID retrieves a security identifier SID for the account
194// and the name of the domain on which the account was found.
195// System specify target computer to search.
196func LookupSID(system, account string) (sid *SID, domain string, accType uint32, err error) {
197	if len(account) == 0 {
198		return nil, "", 0, syscall.EINVAL
199	}
200	acc, e := UTF16PtrFromString(account)
201	if e != nil {
202		return nil, "", 0, e
203	}
204	var sys *uint16
205	if len(system) > 0 {
206		sys, e = UTF16PtrFromString(system)
207		if e != nil {
208			return nil, "", 0, e
209		}
210	}
211	n := uint32(50)
212	dn := uint32(50)
213	for {
214		b := make([]byte, n)
215		db := make([]uint16, dn)
216		sid = (*SID)(unsafe.Pointer(&b[0]))
217		e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
218		if e == nil {
219			return sid, UTF16ToString(db), accType, nil
220		}
221		if e != ERROR_INSUFFICIENT_BUFFER {
222			return nil, "", 0, e
223		}
224		if n <= uint32(len(b)) {
225			return nil, "", 0, e
226		}
227	}
228}
229
230// String converts SID to a string format suitable for display, storage, or transmission.
231func (sid *SID) String() string {
232	var s *uint16
233	e := ConvertSidToStringSid(sid, &s)
234	if e != nil {
235		return ""
236	}
237	defer LocalFree((Handle)(unsafe.Pointer(s)))
238	return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:])
239}
240
241// Len returns the length, in bytes, of a valid security identifier SID.
242func (sid *SID) Len() int {
243	return int(GetLengthSid(sid))
244}
245
246// Copy creates a duplicate of security identifier SID.
247func (sid *SID) Copy() (*SID, error) {
248	b := make([]byte, sid.Len())
249	sid2 := (*SID)(unsafe.Pointer(&b[0]))
250	e := CopySid(uint32(len(b)), sid2, sid)
251	if e != nil {
252		return nil, e
253	}
254	return sid2, nil
255}
256
257// IdentifierAuthority returns the identifier authority of the SID.
258func (sid *SID) IdentifierAuthority() SidIdentifierAuthority {
259	return *getSidIdentifierAuthority(sid)
260}
261
262// SubAuthorityCount returns the number of sub-authorities in the SID.
263func (sid *SID) SubAuthorityCount() uint8 {
264	return *getSidSubAuthorityCount(sid)
265}
266
267// SubAuthority returns the sub-authority of the SID as specified by
268// the index, which must be less than sid.SubAuthorityCount().
269func (sid *SID) SubAuthority(idx uint32) uint32 {
270	if idx >= uint32(sid.SubAuthorityCount()) {
271		panic("sub-authority index out of range")
272	}
273	return *getSidSubAuthority(sid, idx)
274}
275
276// IsValid returns whether the SID has a valid revision and length.
277func (sid *SID) IsValid() bool {
278	return isValidSid(sid)
279}
280
281// Equals compares two SIDs for equality.
282func (sid *SID) Equals(sid2 *SID) bool {
283	return EqualSid(sid, sid2)
284}
285
286// IsWellKnown determines whether the SID matches the well-known sidType.
287func (sid *SID) IsWellKnown(sidType WELL_KNOWN_SID_TYPE) bool {
288	return isWellKnownSid(sid, sidType)
289}
290
291// LookupAccount retrieves the name of the account for this SID
292// and the name of the first domain on which this SID is found.
293// System specify target computer to search for.
294func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
295	var sys *uint16
296	if len(system) > 0 {
297		sys, err = UTF16PtrFromString(system)
298		if err != nil {
299			return "", "", 0, err
300		}
301	}
302	n := uint32(50)
303	dn := uint32(50)
304	for {
305		b := make([]uint16, n)
306		db := make([]uint16, dn)
307		e := LookupAccountSid(sys, sid, &b[0], &n, &db[0], &dn, &accType)
308		if e == nil {
309			return UTF16ToString(b), UTF16ToString(db), accType, nil
310		}
311		if e != ERROR_INSUFFICIENT_BUFFER {
312			return "", "", 0, e
313		}
314		if n <= uint32(len(b)) {
315			return "", "", 0, e
316		}
317	}
318}
319
320// Various types of pre-specified SIDs that can be synthesized and compared at runtime.
321type WELL_KNOWN_SID_TYPE uint32
322
323const (
324	WinNullSid                                    = 0
325	WinWorldSid                                   = 1
326	WinLocalSid                                   = 2
327	WinCreatorOwnerSid                            = 3
328	WinCreatorGroupSid                            = 4
329	WinCreatorOwnerServerSid                      = 5
330	WinCreatorGroupServerSid                      = 6
331	WinNtAuthoritySid                             = 7
332	WinDialupSid                                  = 8
333	WinNetworkSid                                 = 9
334	WinBatchSid                                   = 10
335	WinInteractiveSid                             = 11
336	WinServiceSid                                 = 12
337	WinAnonymousSid                               = 13
338	WinProxySid                                   = 14
339	WinEnterpriseControllersSid                   = 15
340	WinSelfSid                                    = 16
341	WinAuthenticatedUserSid                       = 17
342	WinRestrictedCodeSid                          = 18
343	WinTerminalServerSid                          = 19
344	WinRemoteLogonIdSid                           = 20
345	WinLogonIdsSid                                = 21
346	WinLocalSystemSid                             = 22
347	WinLocalServiceSid                            = 23
348	WinNetworkServiceSid                          = 24
349	WinBuiltinDomainSid                           = 25
350	WinBuiltinAdministratorsSid                   = 26
351	WinBuiltinUsersSid                            = 27
352	WinBuiltinGuestsSid                           = 28
353	WinBuiltinPowerUsersSid                       = 29
354	WinBuiltinAccountOperatorsSid                 = 30
355	WinBuiltinSystemOperatorsSid                  = 31
356	WinBuiltinPrintOperatorsSid                   = 32
357	WinBuiltinBackupOperatorsSid                  = 33
358	WinBuiltinReplicatorSid                       = 34
359	WinBuiltinPreWindows2000CompatibleAccessSid   = 35
360	WinBuiltinRemoteDesktopUsersSid               = 36
361	WinBuiltinNetworkConfigurationOperatorsSid    = 37
362	WinAccountAdministratorSid                    = 38
363	WinAccountGuestSid                            = 39
364	WinAccountKrbtgtSid                           = 40
365	WinAccountDomainAdminsSid                     = 41
366	WinAccountDomainUsersSid                      = 42
367	WinAccountDomainGuestsSid                     = 43
368	WinAccountComputersSid                        = 44
369	WinAccountControllersSid                      = 45
370	WinAccountCertAdminsSid                       = 46
371	WinAccountSchemaAdminsSid                     = 47
372	WinAccountEnterpriseAdminsSid                 = 48
373	WinAccountPolicyAdminsSid                     = 49
374	WinAccountRasAndIasServersSid                 = 50
375	WinNTLMAuthenticationSid                      = 51
376	WinDigestAuthenticationSid                    = 52
377	WinSChannelAuthenticationSid                  = 53
378	WinThisOrganizationSid                        = 54
379	WinOtherOrganizationSid                       = 55
380	WinBuiltinIncomingForestTrustBuildersSid      = 56
381	WinBuiltinPerfMonitoringUsersSid              = 57
382	WinBuiltinPerfLoggingUsersSid                 = 58
383	WinBuiltinAuthorizationAccessSid              = 59
384	WinBuiltinTerminalServerLicenseServersSid     = 60
385	WinBuiltinDCOMUsersSid                        = 61
386	WinBuiltinIUsersSid                           = 62
387	WinIUserSid                                   = 63
388	WinBuiltinCryptoOperatorsSid                  = 64
389	WinUntrustedLabelSid                          = 65
390	WinLowLabelSid                                = 66
391	WinMediumLabelSid                             = 67
392	WinHighLabelSid                               = 68
393	WinSystemLabelSid                             = 69
394	WinWriteRestrictedCodeSid                     = 70
395	WinCreatorOwnerRightsSid                      = 71
396	WinCacheablePrincipalsGroupSid                = 72
397	WinNonCacheablePrincipalsGroupSid             = 73
398	WinEnterpriseReadonlyControllersSid           = 74
399	WinAccountReadonlyControllersSid              = 75
400	WinBuiltinEventLogReadersGroup                = 76
401	WinNewEnterpriseReadonlyControllersSid        = 77
402	WinBuiltinCertSvcDComAccessGroup              = 78
403	WinMediumPlusLabelSid                         = 79
404	WinLocalLogonSid                              = 80
405	WinConsoleLogonSid                            = 81
406	WinThisOrganizationCertificateSid             = 82
407	WinApplicationPackageAuthoritySid             = 83
408	WinBuiltinAnyPackageSid                       = 84
409	WinCapabilityInternetClientSid                = 85
410	WinCapabilityInternetClientServerSid          = 86
411	WinCapabilityPrivateNetworkClientServerSid    = 87
412	WinCapabilityPicturesLibrarySid               = 88
413	WinCapabilityVideosLibrarySid                 = 89
414	WinCapabilityMusicLibrarySid                  = 90
415	WinCapabilityDocumentsLibrarySid              = 91
416	WinCapabilitySharedUserCertificatesSid        = 92
417	WinCapabilityEnterpriseAuthenticationSid      = 93
418	WinCapabilityRemovableStorageSid              = 94
419	WinBuiltinRDSRemoteAccessServersSid           = 95
420	WinBuiltinRDSEndpointServersSid               = 96
421	WinBuiltinRDSManagementServersSid             = 97
422	WinUserModeDriversSid                         = 98
423	WinBuiltinHyperVAdminsSid                     = 99
424	WinAccountCloneableControllersSid             = 100
425	WinBuiltinAccessControlAssistanceOperatorsSid = 101
426	WinBuiltinRemoteManagementUsersSid            = 102
427	WinAuthenticationAuthorityAssertedSid         = 103
428	WinAuthenticationServiceAssertedSid           = 104
429	WinLocalAccountSid                            = 105
430	WinLocalAccountAndAdministratorSid            = 106
431	WinAccountProtectedUsersSid                   = 107
432	WinCapabilityAppointmentsSid                  = 108
433	WinCapabilityContactsSid                      = 109
434	WinAccountDefaultSystemManagedSid             = 110
435	WinBuiltinDefaultSystemManagedGroupSid        = 111
436	WinBuiltinStorageReplicaAdminsSid             = 112
437	WinAccountKeyAdminsSid                        = 113
438	WinAccountEnterpriseKeyAdminsSid              = 114
439	WinAuthenticationKeyTrustSid                  = 115
440	WinAuthenticationKeyPropertyMFASid            = 116
441	WinAuthenticationKeyPropertyAttestationSid    = 117
442	WinAuthenticationFreshKeyAuthSid              = 118
443	WinBuiltinDeviceOwnersSid                     = 119
444)
445
446// Creates a SID for a well-known predefined alias, generally using the constants of the form
447// Win*Sid, for the local machine.
448func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) {
449	return CreateWellKnownDomainSid(sidType, nil)
450}
451
452// Creates a SID for a well-known predefined alias, generally using the constants of the form
453// Win*Sid, for the domain specified by the domainSid parameter.
454func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) {
455	n := uint32(50)
456	for {
457		b := make([]byte, n)
458		sid := (*SID)(unsafe.Pointer(&b[0]))
459		err := createWellKnownSid(sidType, domainSid, sid, &n)
460		if err == nil {
461			return sid, nil
462		}
463		if err != ERROR_INSUFFICIENT_BUFFER {
464			return nil, err
465		}
466		if n <= uint32(len(b)) {
467			return nil, err
468		}
469	}
470}
471
472const (
473	// do not reorder
474	TOKEN_ASSIGN_PRIMARY = 1 << iota
475	TOKEN_DUPLICATE
476	TOKEN_IMPERSONATE
477	TOKEN_QUERY
478	TOKEN_QUERY_SOURCE
479	TOKEN_ADJUST_PRIVILEGES
480	TOKEN_ADJUST_GROUPS
481	TOKEN_ADJUST_DEFAULT
482	TOKEN_ADJUST_SESSIONID
483
484	TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED |
485		TOKEN_ASSIGN_PRIMARY |
486		TOKEN_DUPLICATE |
487		TOKEN_IMPERSONATE |
488		TOKEN_QUERY |
489		TOKEN_QUERY_SOURCE |
490		TOKEN_ADJUST_PRIVILEGES |
491		TOKEN_ADJUST_GROUPS |
492		TOKEN_ADJUST_DEFAULT |
493		TOKEN_ADJUST_SESSIONID
494	TOKEN_READ  = STANDARD_RIGHTS_READ | TOKEN_QUERY
495	TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
496		TOKEN_ADJUST_PRIVILEGES |
497		TOKEN_ADJUST_GROUPS |
498		TOKEN_ADJUST_DEFAULT
499	TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE
500)
501
502const (
503	// do not reorder
504	TokenUser = 1 + iota
505	TokenGroups
506	TokenPrivileges
507	TokenOwner
508	TokenPrimaryGroup
509	TokenDefaultDacl
510	TokenSource
511	TokenType
512	TokenImpersonationLevel
513	TokenStatistics
514	TokenRestrictedSids
515	TokenSessionId
516	TokenGroupsAndPrivileges
517	TokenSessionReference
518	TokenSandBoxInert
519	TokenAuditPolicy
520	TokenOrigin
521	TokenElevationType
522	TokenLinkedToken
523	TokenElevation
524	TokenHasRestrictions
525	TokenAccessInformation
526	TokenVirtualizationAllowed
527	TokenVirtualizationEnabled
528	TokenIntegrityLevel
529	TokenUIAccess
530	TokenMandatoryPolicy
531	TokenLogonSid
532	MaxTokenInfoClass
533)
534
535// Group attributes inside of Tokengroups.Groups[i].Attributes
536const (
537	SE_GROUP_MANDATORY          = 0x00000001
538	SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002
539	SE_GROUP_ENABLED            = 0x00000004
540	SE_GROUP_OWNER              = 0x00000008
541	SE_GROUP_USE_FOR_DENY_ONLY  = 0x00000010
542	SE_GROUP_INTEGRITY          = 0x00000020
543	SE_GROUP_INTEGRITY_ENABLED  = 0x00000040
544	SE_GROUP_LOGON_ID           = 0xC0000000
545	SE_GROUP_RESOURCE           = 0x20000000
546	SE_GROUP_VALID_ATTRIBUTES   = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED | SE_GROUP_OWNER | SE_GROUP_USE_FOR_DENY_ONLY | SE_GROUP_LOGON_ID | SE_GROUP_RESOURCE | SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED
547)
548
549// Privilege attributes
550const (
551	SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001
552	SE_PRIVILEGE_ENABLED            = 0x00000002
553	SE_PRIVILEGE_REMOVED            = 0x00000004
554	SE_PRIVILEGE_USED_FOR_ACCESS    = 0x80000000
555	SE_PRIVILEGE_VALID_ATTRIBUTES   = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_REMOVED | SE_PRIVILEGE_USED_FOR_ACCESS
556)
557
558// Token types
559const (
560	TokenPrimary       = 1
561	TokenImpersonation = 2
562)
563
564// Impersonation levels
565const (
566	SecurityAnonymous      = 0
567	SecurityIdentification = 1
568	SecurityImpersonation  = 2
569	SecurityDelegation     = 3
570)
571
572type LUID struct {
573	LowPart  uint32
574	HighPart int32
575}
576
577type LUIDAndAttributes struct {
578	Luid       LUID
579	Attributes uint32
580}
581
582type SIDAndAttributes struct {
583	Sid        *SID
584	Attributes uint32
585}
586
587type Tokenuser struct {
588	User SIDAndAttributes
589}
590
591type Tokenprimarygroup struct {
592	PrimaryGroup *SID
593}
594
595type Tokengroups struct {
596	GroupCount uint32
597	Groups     [1]SIDAndAttributes // Use AllGroups() for iterating.
598}
599
600// AllGroups returns a slice that can be used to iterate over the groups in g.
601func (g *Tokengroups) AllGroups() []SIDAndAttributes {
602	return (*[(1 << 28) - 1]SIDAndAttributes)(unsafe.Pointer(&g.Groups[0]))[:g.GroupCount:g.GroupCount]
603}
604
605type Tokenprivileges struct {
606	PrivilegeCount uint32
607	Privileges     [1]LUIDAndAttributes // Use AllPrivileges() for iterating.
608}
609
610// AllPrivileges returns a slice that can be used to iterate over the privileges in p.
611func (p *Tokenprivileges) AllPrivileges() []LUIDAndAttributes {
612	return (*[(1 << 27) - 1]LUIDAndAttributes)(unsafe.Pointer(&p.Privileges[0]))[:p.PrivilegeCount:p.PrivilegeCount]
613}
614
615type Tokenmandatorylabel struct {
616	Label SIDAndAttributes
617}
618
619func (tml *Tokenmandatorylabel) Size() uint32 {
620	return uint32(unsafe.Sizeof(Tokenmandatorylabel{})) + GetLengthSid(tml.Label.Sid)
621}
622
623// Authorization Functions
624//sys	checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) = advapi32.CheckTokenMembership
625//sys	OpenProcessToken(process Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
626//sys	OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) = advapi32.OpenThreadToken
627//sys	ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
628//sys	RevertToSelf() (err error) = advapi32.RevertToSelf
629//sys	SetThreadToken(thread *Handle, token Token) (err error) = advapi32.SetThreadToken
630//sys	LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
631//sys	AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) = advapi32.AdjustTokenPrivileges
632//sys	AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) = advapi32.AdjustTokenGroups
633//sys	GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
634//sys	SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) = advapi32.SetTokenInformation
635//sys	DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
636//sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
637//sys	getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
638//sys	getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW
639//sys	getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW
640
641// An access token contains the security information for a logon session.
642// The system creates an access token when a user logs on, and every
643// process executed on behalf of the user has a copy of the token.
644// The token identifies the user, the user's groups, and the user's
645// privileges. The system uses the token to control access to securable
646// objects and to control the ability of the user to perform various
647// system-related operations on the local computer.
648type Token Handle
649
650// OpenCurrentProcessToken opens an access token associated with current
651// process with TOKEN_QUERY access. It is a real token that needs to be closed.
652//
653// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...)
654// with the desired access instead, or use GetCurrentProcessToken for a
655// TOKEN_QUERY token.
656func OpenCurrentProcessToken() (Token, error) {
657	var token Token
658	err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token)
659	return token, err
660}
661
662// GetCurrentProcessToken returns the access token associated with
663// the current process. It is a pseudo token that does not need
664// to be closed.
665func GetCurrentProcessToken() Token {
666	return Token(^uintptr(4 - 1))
667}
668
669// GetCurrentThreadToken return the access token associated with
670// the current thread. It is a pseudo token that does not need
671// to be closed.
672func GetCurrentThreadToken() Token {
673	return Token(^uintptr(5 - 1))
674}
675
676// GetCurrentThreadEffectiveToken returns the effective access token
677// associated with the current thread. It is a pseudo token that does
678// not need to be closed.
679func GetCurrentThreadEffectiveToken() Token {
680	return Token(^uintptr(6 - 1))
681}
682
683// Close releases access to access token.
684func (t Token) Close() error {
685	return CloseHandle(Handle(t))
686}
687
688// getInfo retrieves a specified type of information about an access token.
689func (t Token) getInfo(class uint32, initSize int) (unsafe.Pointer, error) {
690	n := uint32(initSize)
691	for {
692		b := make([]byte, n)
693		e := GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
694		if e == nil {
695			return unsafe.Pointer(&b[0]), nil
696		}
697		if e != ERROR_INSUFFICIENT_BUFFER {
698			return nil, e
699		}
700		if n <= uint32(len(b)) {
701			return nil, e
702		}
703	}
704}
705
706// GetTokenUser retrieves access token t user account information.
707func (t Token) GetTokenUser() (*Tokenuser, error) {
708	i, e := t.getInfo(TokenUser, 50)
709	if e != nil {
710		return nil, e
711	}
712	return (*Tokenuser)(i), nil
713}
714
715// GetTokenGroups retrieves group accounts associated with access token t.
716func (t Token) GetTokenGroups() (*Tokengroups, error) {
717	i, e := t.getInfo(TokenGroups, 50)
718	if e != nil {
719		return nil, e
720	}
721	return (*Tokengroups)(i), nil
722}
723
724// GetTokenPrimaryGroup retrieves access token t primary group information.
725// A pointer to a SID structure representing a group that will become
726// the primary group of any objects created by a process using this access token.
727func (t Token) GetTokenPrimaryGroup() (*Tokenprimarygroup, error) {
728	i, e := t.getInfo(TokenPrimaryGroup, 50)
729	if e != nil {
730		return nil, e
731	}
732	return (*Tokenprimarygroup)(i), nil
733}
734
735// GetUserProfileDirectory retrieves path to the
736// root directory of the access token t user's profile.
737func (t Token) GetUserProfileDirectory() (string, error) {
738	n := uint32(100)
739	for {
740		b := make([]uint16, n)
741		e := GetUserProfileDirectory(t, &b[0], &n)
742		if e == nil {
743			return UTF16ToString(b), nil
744		}
745		if e != ERROR_INSUFFICIENT_BUFFER {
746			return "", e
747		}
748		if n <= uint32(len(b)) {
749			return "", e
750		}
751	}
752}
753
754// IsElevated returns whether the current token is elevated from a UAC perspective.
755func (token Token) IsElevated() bool {
756	var isElevated uint32
757	var outLen uint32
758	err := GetTokenInformation(token, TokenElevation, (*byte)(unsafe.Pointer(&isElevated)), uint32(unsafe.Sizeof(isElevated)), &outLen)
759	if err != nil {
760		return false
761	}
762	return outLen == uint32(unsafe.Sizeof(isElevated)) && isElevated != 0
763}
764
765// GetLinkedToken returns the linked token, which may be an elevated UAC token.
766func (token Token) GetLinkedToken() (Token, error) {
767	var linkedToken Token
768	var outLen uint32
769	err := GetTokenInformation(token, TokenLinkedToken, (*byte)(unsafe.Pointer(&linkedToken)), uint32(unsafe.Sizeof(linkedToken)), &outLen)
770	if err != nil {
771		return Token(0), err
772	}
773	return linkedToken, nil
774}
775
776// GetSystemDirectory retrieves the path to current location of the system
777// directory, which is typically, though not always, `C:\Windows\System32`.
778func GetSystemDirectory() (string, error) {
779	n := uint32(MAX_PATH)
780	for {
781		b := make([]uint16, n)
782		l, e := getSystemDirectory(&b[0], n)
783		if e != nil {
784			return "", e
785		}
786		if l <= n {
787			return UTF16ToString(b[:l]), nil
788		}
789		n = l
790	}
791}
792
793// GetWindowsDirectory retrieves the path to current location of the Windows
794// directory, which is typically, though not always, `C:\Windows`. This may
795// be a private user directory in the case that the application is running
796// under a terminal server.
797func GetWindowsDirectory() (string, error) {
798	n := uint32(MAX_PATH)
799	for {
800		b := make([]uint16, n)
801		l, e := getWindowsDirectory(&b[0], n)
802		if e != nil {
803			return "", e
804		}
805		if l <= n {
806			return UTF16ToString(b[:l]), nil
807		}
808		n = l
809	}
810}
811
812// GetSystemWindowsDirectory retrieves the path to current location of the
813// Windows directory, which is typically, though not always, `C:\Windows`.
814func GetSystemWindowsDirectory() (string, error) {
815	n := uint32(MAX_PATH)
816	for {
817		b := make([]uint16, n)
818		l, e := getSystemWindowsDirectory(&b[0], n)
819		if e != nil {
820			return "", e
821		}
822		if l <= n {
823			return UTF16ToString(b[:l]), nil
824		}
825		n = l
826	}
827}
828
829// IsMember reports whether the access token t is a member of the provided SID.
830func (t Token) IsMember(sid *SID) (bool, error) {
831	var b int32
832	if e := checkTokenMembership(t, sid, &b); e != nil {
833		return false, e
834	}
835	return b != 0, nil
836}
837
838const (
839	WTS_CONSOLE_CONNECT        = 0x1
840	WTS_CONSOLE_DISCONNECT     = 0x2
841	WTS_REMOTE_CONNECT         = 0x3
842	WTS_REMOTE_DISCONNECT      = 0x4
843	WTS_SESSION_LOGON          = 0x5
844	WTS_SESSION_LOGOFF         = 0x6
845	WTS_SESSION_LOCK           = 0x7
846	WTS_SESSION_UNLOCK         = 0x8
847	WTS_SESSION_REMOTE_CONTROL = 0x9
848	WTS_SESSION_CREATE         = 0xa
849	WTS_SESSION_TERMINATE      = 0xb
850)
851
852const (
853	WTSActive       = 0
854	WTSConnected    = 1
855	WTSConnectQuery = 2
856	WTSShadow       = 3
857	WTSDisconnected = 4
858	WTSIdle         = 5
859	WTSListen       = 6
860	WTSReset        = 7
861	WTSDown         = 8
862	WTSInit         = 9
863)
864
865type WTSSESSION_NOTIFICATION struct {
866	Size      uint32
867	SessionID uint32
868}
869
870type WTS_SESSION_INFO struct {
871	SessionID         uint32
872	WindowStationName *uint16
873	State             uint32
874}
875
876//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
877//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
878//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
879
880type ACL struct {
881	aclRevision byte
882	sbz1        byte
883	aclSize     uint16
884	aceCount    uint16
885	sbz2        uint16
886}
887
888type SECURITY_DESCRIPTOR struct {
889	revision byte
890	sbz1     byte
891	control  SECURITY_DESCRIPTOR_CONTROL
892	owner    *SID
893	group    *SID
894	sacl     *ACL
895	dacl     *ACL
896}
897
898type SecurityAttributes struct {
899	Length             uint32
900	SecurityDescriptor *SECURITY_DESCRIPTOR
901	InheritHandle      uint32
902}
903
904type SE_OBJECT_TYPE uint32
905
906// Constants for type SE_OBJECT_TYPE
907const (
908	SE_UNKNOWN_OBJECT_TYPE     = 0
909	SE_FILE_OBJECT             = 1
910	SE_SERVICE                 = 2
911	SE_PRINTER                 = 3
912	SE_REGISTRY_KEY            = 4
913	SE_LMSHARE                 = 5
914	SE_KERNEL_OBJECT           = 6
915	SE_WINDOW_OBJECT           = 7
916	SE_DS_OBJECT               = 8
917	SE_DS_OBJECT_ALL           = 9
918	SE_PROVIDER_DEFINED_OBJECT = 10
919	SE_WMIGUID_OBJECT          = 11
920	SE_REGISTRY_WOW64_32KEY    = 12
921	SE_REGISTRY_WOW64_64KEY    = 13
922)
923
924type SECURITY_INFORMATION uint32
925
926// Constants for type SECURITY_INFORMATION
927const (
928	OWNER_SECURITY_INFORMATION            = 0x00000001
929	GROUP_SECURITY_INFORMATION            = 0x00000002
930	DACL_SECURITY_INFORMATION             = 0x00000004
931	SACL_SECURITY_INFORMATION             = 0x00000008
932	LABEL_SECURITY_INFORMATION            = 0x00000010
933	ATTRIBUTE_SECURITY_INFORMATION        = 0x00000020
934	SCOPE_SECURITY_INFORMATION            = 0x00000040
935	BACKUP_SECURITY_INFORMATION           = 0x00010000
936	PROTECTED_DACL_SECURITY_INFORMATION   = 0x80000000
937	PROTECTED_SACL_SECURITY_INFORMATION   = 0x40000000
938	UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
939	UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
940)
941
942type SECURITY_DESCRIPTOR_CONTROL uint16
943
944// Constants for type SECURITY_DESCRIPTOR_CONTROL
945const (
946	SE_OWNER_DEFAULTED       = 0x0001
947	SE_GROUP_DEFAULTED       = 0x0002
948	SE_DACL_PRESENT          = 0x0004
949	SE_DACL_DEFAULTED        = 0x0008
950	SE_SACL_PRESENT          = 0x0010
951	SE_SACL_DEFAULTED        = 0x0020
952	SE_DACL_AUTO_INHERIT_REQ = 0x0100
953	SE_SACL_AUTO_INHERIT_REQ = 0x0200
954	SE_DACL_AUTO_INHERITED   = 0x0400
955	SE_SACL_AUTO_INHERITED   = 0x0800
956	SE_DACL_PROTECTED        = 0x1000
957	SE_SACL_PROTECTED        = 0x2000
958	SE_RM_CONTROL_VALID      = 0x4000
959	SE_SELF_RELATIVE         = 0x8000
960)
961
962type ACCESS_MASK uint32
963
964// Constants for type ACCESS_MASK
965const (
966	DELETE                   = 0x00010000
967	READ_CONTROL             = 0x00020000
968	WRITE_DAC                = 0x00040000
969	WRITE_OWNER              = 0x00080000
970	SYNCHRONIZE              = 0x00100000
971	STANDARD_RIGHTS_REQUIRED = 0x000F0000
972	STANDARD_RIGHTS_READ     = READ_CONTROL
973	STANDARD_RIGHTS_WRITE    = READ_CONTROL
974	STANDARD_RIGHTS_EXECUTE  = READ_CONTROL
975	STANDARD_RIGHTS_ALL      = 0x001F0000
976	SPECIFIC_RIGHTS_ALL      = 0x0000FFFF
977	ACCESS_SYSTEM_SECURITY   = 0x01000000
978	MAXIMUM_ALLOWED          = 0x02000000
979	GENERIC_READ             = 0x80000000
980	GENERIC_WRITE            = 0x40000000
981	GENERIC_EXECUTE          = 0x20000000
982	GENERIC_ALL              = 0x10000000
983)
984
985type ACCESS_MODE uint32
986
987// Constants for type ACCESS_MODE
988const (
989	NOT_USED_ACCESS   = 0
990	GRANT_ACCESS      = 1
991	SET_ACCESS        = 2
992	DENY_ACCESS       = 3
993	REVOKE_ACCESS     = 4
994	SET_AUDIT_SUCCESS = 5
995	SET_AUDIT_FAILURE = 6
996)
997
998// Constants for AceFlags and Inheritance fields
999const (
1000	NO_INHERITANCE                     = 0x0
1001	SUB_OBJECTS_ONLY_INHERIT           = 0x1
1002	SUB_CONTAINERS_ONLY_INHERIT        = 0x2
1003	SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3
1004	INHERIT_NO_PROPAGATE               = 0x4
1005	INHERIT_ONLY                       = 0x8
1006	INHERITED_ACCESS_ENTRY             = 0x10
1007	INHERITED_PARENT                   = 0x10000000
1008	INHERITED_GRANDPARENT              = 0x20000000
1009	OBJECT_INHERIT_ACE                 = 0x1
1010	CONTAINER_INHERIT_ACE              = 0x2
1011	NO_PROPAGATE_INHERIT_ACE           = 0x4
1012	INHERIT_ONLY_ACE                   = 0x8
1013	INHERITED_ACE                      = 0x10
1014	VALID_INHERIT_FLAGS                = 0x1F
1015)
1016
1017type MULTIPLE_TRUSTEE_OPERATION uint32
1018
1019// Constants for MULTIPLE_TRUSTEE_OPERATION
1020const (
1021	NO_MULTIPLE_TRUSTEE    = 0
1022	TRUSTEE_IS_IMPERSONATE = 1
1023)
1024
1025type TRUSTEE_FORM uint32
1026
1027// Constants for TRUSTEE_FORM
1028const (
1029	TRUSTEE_IS_SID              = 0
1030	TRUSTEE_IS_NAME             = 1
1031	TRUSTEE_BAD_FORM            = 2
1032	TRUSTEE_IS_OBJECTS_AND_SID  = 3
1033	TRUSTEE_IS_OBJECTS_AND_NAME = 4
1034)
1035
1036type TRUSTEE_TYPE uint32
1037
1038// Constants for TRUSTEE_TYPE
1039const (
1040	TRUSTEE_IS_UNKNOWN          = 0
1041	TRUSTEE_IS_USER             = 1
1042	TRUSTEE_IS_GROUP            = 2
1043	TRUSTEE_IS_DOMAIN           = 3
1044	TRUSTEE_IS_ALIAS            = 4
1045	TRUSTEE_IS_WELL_KNOWN_GROUP = 5
1046	TRUSTEE_IS_DELETED          = 6
1047	TRUSTEE_IS_INVALID          = 7
1048	TRUSTEE_IS_COMPUTER         = 8
1049)
1050
1051// Constants for ObjectsPresent field
1052const (
1053	ACE_OBJECT_TYPE_PRESENT           = 0x1
1054	ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x2
1055)
1056
1057type EXPLICIT_ACCESS struct {
1058	AccessPermissions ACCESS_MASK
1059	AccessMode        ACCESS_MODE
1060	Inheritance       uint32
1061	Trustee           TRUSTEE
1062}
1063
1064// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.
1065type TrusteeValue uintptr
1066
1067func TrusteeValueFromString(str string) TrusteeValue {
1068	return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))
1069}
1070func TrusteeValueFromSID(sid *SID) TrusteeValue {
1071	return TrusteeValue(unsafe.Pointer(sid))
1072}
1073func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {
1074	return TrusteeValue(unsafe.Pointer(objectsAndSid))
1075}
1076func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {
1077	return TrusteeValue(unsafe.Pointer(objectsAndName))
1078}
1079
1080type TRUSTEE struct {
1081	MultipleTrustee          *TRUSTEE
1082	MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION
1083	TrusteeForm              TRUSTEE_FORM
1084	TrusteeType              TRUSTEE_TYPE
1085	TrusteeValue             TrusteeValue
1086}
1087
1088type OBJECTS_AND_SID struct {
1089	ObjectsPresent          uint32
1090	ObjectTypeGuid          GUID
1091	InheritedObjectTypeGuid GUID
1092	Sid                     *SID
1093}
1094
1095type OBJECTS_AND_NAME struct {
1096	ObjectsPresent          uint32
1097	ObjectType              SE_OBJECT_TYPE
1098	ObjectTypeName          *uint16
1099	InheritedObjectTypeName *uint16
1100	Name                    *uint16
1101}
1102
1103//sys	getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetSecurityInfo
1104//sys	SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo
1105//sys	getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) = advapi32.GetNamedSecurityInfoW
1106//sys	SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW
1107
1108//sys	buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) = advapi32.BuildSecurityDescriptorW
1109//sys	initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor
1110
1111//sys	getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl
1112//sys	getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl
1113//sys	getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl
1114//sys	getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner
1115//sys	getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup
1116//sys	getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength
1117//sys	getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl
1118//sys	isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor
1119
1120//sys	setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl
1121//sys	setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl
1122//sys	setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl
1123//sys	setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner
1124//sys	setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup
1125//sys	setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl
1126
1127//sys	convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
1128//sys	convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
1129
1130//sys	makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) = advapi32.MakeAbsoluteSD
1131//sys	makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD
1132
1133//sys	setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW
1134
1135// Control returns the security descriptor control bits.
1136func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) {
1137	err = getSecurityDescriptorControl(sd, &control, &revision)
1138	return
1139}
1140
1141// SetControl sets the security descriptor control bits.
1142func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error {
1143	return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet)
1144}
1145
1146// RMControl returns the security descriptor resource manager control bits.
1147func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) {
1148	err = getSecurityDescriptorRMControl(sd, &control)
1149	return
1150}
1151
1152// SetRMControl sets the security descriptor resource manager control bits.
1153func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) {
1154	setSecurityDescriptorRMControl(sd, &rmControl)
1155}
1156
1157// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil
1158// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns
1159// ERROR_OBJECT_NOT_FOUND.
1160func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) {
1161	var present bool
1162	err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted)
1163	if !present {
1164		err = ERROR_OBJECT_NOT_FOUND
1165	}
1166	return
1167}
1168
1169// SetDACL sets the absolute security descriptor DACL.
1170func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error {
1171	return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted)
1172}
1173
1174// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil
1175// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns
1176// ERROR_OBJECT_NOT_FOUND.
1177func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) {
1178	var present bool
1179	err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted)
1180	if !present {
1181		err = ERROR_OBJECT_NOT_FOUND
1182	}
1183	return
1184}
1185
1186// SetSACL sets the absolute security descriptor SACL.
1187func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error {
1188	return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted)
1189}
1190
1191// Owner returns the security descriptor owner and whether it was defaulted.
1192func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) {
1193	err = getSecurityDescriptorOwner(sd, &owner, &defaulted)
1194	return
1195}
1196
1197// SetOwner sets the absolute security descriptor owner.
1198func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error {
1199	return setSecurityDescriptorOwner(absoluteSD, owner, defaulted)
1200}
1201
1202// Group returns the security descriptor group and whether it was defaulted.
1203func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) {
1204	err = getSecurityDescriptorGroup(sd, &group, &defaulted)
1205	return
1206}
1207
1208// SetGroup sets the absolute security descriptor owner.
1209func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error {
1210	return setSecurityDescriptorGroup(absoluteSD, group, defaulted)
1211}
1212
1213// Length returns the length of the security descriptor.
1214func (sd *SECURITY_DESCRIPTOR) Length() uint32 {
1215	return getSecurityDescriptorLength(sd)
1216}
1217
1218// IsValid returns whether the security descriptor is valid.
1219func (sd *SECURITY_DESCRIPTOR) IsValid() bool {
1220	return isValidSecurityDescriptor(sd)
1221}
1222
1223// String returns the SDDL form of the security descriptor, with a function signature that can be
1224// used with %v formatting directives.
1225func (sd *SECURITY_DESCRIPTOR) String() string {
1226	var sddl *uint16
1227	err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil)
1228	if err != nil {
1229		return ""
1230	}
1231	defer LocalFree(Handle(unsafe.Pointer(sddl)))
1232	return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(sddl))[:])
1233}
1234
1235// ToAbsolute converts a self-relative security descriptor into an absolute one.
1236func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
1237	control, _, err := selfRelativeSD.Control()
1238	if err != nil {
1239		return
1240	}
1241	if control&SE_SELF_RELATIVE == 0 {
1242		err = ERROR_INVALID_PARAMETER
1243		return
1244	}
1245	var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32
1246	err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize,
1247		nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize)
1248	switch err {
1249	case ERROR_INSUFFICIENT_BUFFER:
1250	case nil:
1251		// makeAbsoluteSD is expected to fail, but it succeeds.
1252		return nil, ERROR_INTERNAL_ERROR
1253	default:
1254		return nil, err
1255	}
1256	if absoluteSDSize > 0 {
1257		absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0]))
1258	}
1259	var (
1260		dacl  *ACL
1261		sacl  *ACL
1262		owner *SID
1263		group *SID
1264	)
1265	if daclSize > 0 {
1266		dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0]))
1267	}
1268	if saclSize > 0 {
1269		sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0]))
1270	}
1271	if ownerSize > 0 {
1272		owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0]))
1273	}
1274	if groupSize > 0 {
1275		group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0]))
1276	}
1277	err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize,
1278		dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize)
1279	return
1280}
1281
1282// ToSelfRelative converts an absolute security descriptor into a self-relative one.
1283func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) {
1284	control, _, err := absoluteSD.Control()
1285	if err != nil {
1286		return
1287	}
1288	if control&SE_SELF_RELATIVE != 0 {
1289		err = ERROR_INVALID_PARAMETER
1290		return
1291	}
1292	var selfRelativeSDSize uint32
1293	err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize)
1294	switch err {
1295	case ERROR_INSUFFICIENT_BUFFER:
1296	case nil:
1297		// makeSelfRelativeSD is expected to fail, but it succeeds.
1298		return nil, ERROR_INTERNAL_ERROR
1299	default:
1300		return nil, err
1301	}
1302	if selfRelativeSDSize > 0 {
1303		selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0]))
1304	}
1305	err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize)
1306	return
1307}
1308
1309func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {
1310	sdBytes := make([]byte, selfRelativeSD.Length())
1311	copy(sdBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(selfRelativeSD))[:len(sdBytes)])
1312	return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&sdBytes[0]))
1313}
1314
1315// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a
1316// self-relative security descriptor object allocated on the Go heap.
1317func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) {
1318	var winHeapSD *SECURITY_DESCRIPTOR
1319	err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil)
1320	if err != nil {
1321		return
1322	}
1323	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1324	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1325}
1326
1327// GetSecurityInfo queries the security information for a given handle and returns the self-relative security
1328// descriptor result on the Go heap.
1329func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
1330	var winHeapSD *SECURITY_DESCRIPTOR
1331	err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
1332	if err != nil {
1333		return
1334	}
1335	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1336	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1337}
1338
1339// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
1340// descriptor result on the Go heap.
1341func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
1342	var winHeapSD *SECURITY_DESCRIPTOR
1343	err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
1344	if err != nil {
1345		return
1346	}
1347	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1348	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1349}
1350
1351// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and
1352// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor
1353// result on the Go heap.
1354func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) {
1355	var winHeapSD *SECURITY_DESCRIPTOR
1356	var winHeapSDSize uint32
1357	var firstAccessEntry *EXPLICIT_ACCESS
1358	if len(accessEntries) > 0 {
1359		firstAccessEntry = &accessEntries[0]
1360	}
1361	var firstAuditEntry *EXPLICIT_ACCESS
1362	if len(auditEntries) > 0 {
1363		firstAuditEntry = &auditEntries[0]
1364	}
1365	err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD)
1366	if err != nil {
1367		return
1368	}
1369	defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
1370	return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
1371}
1372
1373// NewSecurityDescriptor creates and initializes a new absolute security descriptor.
1374func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
1375	absoluteSD = &SECURITY_DESCRIPTOR{}
1376	err = initializeSecurityDescriptor(absoluteSD, 1)
1377	return
1378}
1379
1380// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL.
1381// Both explicitEntries and mergedACL are optional and can be nil.
1382func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) {
1383	var firstExplicitEntry *EXPLICIT_ACCESS
1384	if len(explicitEntries) > 0 {
1385		firstExplicitEntry = &explicitEntries[0]
1386	}
1387	var winHeapACL *ACL
1388	err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL)
1389	if err != nil {
1390		return
1391	}
1392	defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))
1393	aclBytes := make([]byte, winHeapACL.aclSize)
1394	copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes)])
1395	return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil
1396}
1397