Add single sign-on support via SSPI on Windows (#8463)

* Add single sign-on support via SSPI on Windows

* Ensure plugins implement interface

* Ensure plugins implement interface

* Move functions used only by the SSPI auth method to sspi_windows.go

* Field SSPISeparatorReplacement of AuthenticationForm should not be required via binding, as binding will insist the field is non-empty even if another login type is selected

* Fix breaking of oauth authentication on download links. Do not create new session with SSPI authentication on download links.

* Update documentation for the new 'SPNEGO with SSPI' login source

* Mention in documentation that ROOT_URL should contain the FQDN of the server

* Make sure that Contexter is not checking for active login sources when the ORM engine is not initialized (eg. when installing)

* Always initialize and free SSO methods, even if they are not enabled, as a method can be activated while the app is running (from Authentication sources)

* Add option in SSPIConfig for removing of domains from logon names

* Update helper text for StripDomainNames option

* Make sure handleSignIn() is called after a new user object is created by SSPI auth method

* Remove default value from text of form field helper

Co-Authored-By: Lauris BH <lauris@nix.lv>

* Remove default value from text of form field helper

Co-Authored-By: Lauris BH <lauris@nix.lv>

* Remove default value from text of form field helper

Co-Authored-By: Lauris BH <lauris@nix.lv>

* Only make a query to the DB to check if SSPI is enabled on handlers that need that information for templates

* Remove code duplication

* Log errors in ActiveLoginSources

Co-Authored-By: Lauris BH <lauris@nix.lv>

* Revert suffix of randomly generated E-mails for Reverse proxy authentication

Co-Authored-By: Lauris BH <lauris@nix.lv>

* Revert unneeded white-space change in template

Co-Authored-By: Lauris BH <lauris@nix.lv>

* Add copyright comments at the top of new files

* Use loopback name for randomly generated emails

* Add locale tag for the SSPISeparatorReplacement field with proper casing

* Revert casing of SSPISeparatorReplacement field in locale file, moving it up, next to other form fields

* Update docs/content/doc/features/authentication.en-us.md

Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com>

* Remove Priority() method and define the order in which SSO auth methods should be executed in one place

* Log authenticated username only if it's not empty

* Rephrase helper text for automatic creation of users

* Return error if more than one active SSPI auth source is found

* Change newUser() function to return error, letting caller log/handle the error

* Move isPublicResource, isPublicPage and handleSignIn functions outside SSPI auth method to allow other SSO methods to reuse them if needed

* Refactor initialization of the list containing SSO auth methods

* Validate SSPI settings on POST

* Change SSPI to only perform authentication on its own login page, API paths and download links. Leave Toggle middleware to redirect non authenticated users to login page

* Make 'Default language' in SSPI config empty, unless changed by admin

* Show error if admin tries to add a second authentication source of type SSPI

* Simplify declaration of global variable

* Rebuild gitgraph.js on Linux

* Make sure config values containing only whitespace are not accepted
This commit is contained in:
QuaSoft 2019-11-23 01:33:31 +02:00 committed by Lauris BH
parent eb1b225d9a
commit 7b4d2f7a2a
174 changed files with 6363 additions and 1306 deletions

View file

@ -1,13 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// System calls for 386, Windows are implemented in runtime/syscall_windows.goc
//
TEXT ·getprocaddress(SB), 7, $0-16
JMP syscall·getprocaddress(SB)
TEXT ·loadlibrary(SB), 7, $0-12
JMP syscall·loadlibrary(SB)

View file

@ -1,13 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// System calls for amd64, Windows are implemented in runtime/syscall_windows.goc
//
TEXT ·getprocaddress(SB), 7, $0-32
JMP syscall·getprocaddress(SB)
TEXT ·loadlibrary(SB), 7, $0-24
JMP syscall·loadlibrary(SB)

View file

@ -1,11 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "textflag.h"
TEXT ·getprocaddress(SB),NOSPLIT,$0
B syscall·getprocaddress(SB)
TEXT ·loadlibrary(SB),NOSPLIT,$0
B syscall·loadlibrary(SB)

View file

@ -11,6 +11,18 @@ import (
"unsafe"
)
// We need to use LoadLibrary and GetProcAddress from the Go runtime, because
// the these symbols are loaded by the system linker and are required to
// dynamically load additional symbols. Note that in the Go runtime, these
// return syscall.Handle and syscall.Errno, but these are the same, in fact,
// as windows.Handle and windows.Errno, and we intend to keep these the same.
//go:linkname syscall_loadlibrary syscall.loadlibrary
func syscall_loadlibrary(filename *uint16) (handle Handle, err Errno)
//go:linkname syscall_getprocaddress syscall.getprocaddress
func syscall_getprocaddress(handle Handle, procname *uint8) (proc uintptr, err Errno)
// DLLError describes reasons for DLL load failures.
type DLLError struct {
Err error
@ -20,10 +32,6 @@ type DLLError struct {
func (e *DLLError) Error() string { return e.Msg }
// Implemented in runtime/syscall_windows.goc; we provide jumps to them in our assembly file.
func loadlibrary(filename *uint16) (handle uintptr, err syscall.Errno)
func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err syscall.Errno)
// A DLL implements access to a single DLL.
type DLL struct {
Name string
@ -40,7 +48,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
if err != nil {
return nil, err
}
h, e := loadlibrary(namep)
h, e := syscall_loadlibrary(namep)
if e != 0 {
return nil, &DLLError{
Err: e,
@ -50,7 +58,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
}
d := &DLL{
Name: name,
Handle: Handle(h),
Handle: h,
}
return d, nil
}
@ -71,7 +79,7 @@ func (d *DLL) FindProc(name string) (proc *Proc, err error) {
if err != nil {
return nil, err
}
a, e := getprocaddress(uintptr(d.Handle), namep)
a, e := syscall_getprocaddress(d.Handle, namep)
if e != 0 {
return nil, &DLLError{
Err: e,

View file

@ -6,4 +6,4 @@
package windows
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go eventlog.go service.go syscall_windows.go security_windows.go

View file

@ -9,14 +9,6 @@ import (
"unsafe"
)
const (
STANDARD_RIGHTS_REQUIRED = 0xf0000
STANDARD_RIGHTS_READ = 0x20000
STANDARD_RIGHTS_WRITE = 0x20000
STANDARD_RIGHTS_EXECUTE = 0x20000
STANDARD_RIGHTS_ALL = 0x1F0000
)
const (
NameUnknown = 0
NameFullyQualifiedDN = 1
@ -235,16 +227,15 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
}
}
// String converts SID to a string format
// suitable for display, storage, or transmission.
func (sid *SID) String() (string, error) {
// String converts SID to a string format suitable for display, storage, or transmission.
func (sid *SID) String() string {
var s *uint16
e := ConvertSidToStringSid(sid, &s)
if e != nil {
return "", e
return ""
}
defer LocalFree((Handle)(unsafe.Pointer(s)))
return UTF16ToString((*[256]uint16)(unsafe.Pointer(s))[:]), nil
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(s))[:])
}
// Len returns the length, in bytes, of a valid security identifier SID.
@ -656,21 +647,16 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
// system-related operations on the local computer.
type Token Handle
// OpenCurrentProcessToken opens the access token
// associated with current process. It is a real
// token that needs to be closed, unlike
// GetCurrentProcessToken.
// OpenCurrentProcessToken opens an access token associated with current
// process with TOKEN_QUERY access. It is a real token that needs to be closed.
//
// Deprecated: Explicitly call OpenProcessToken(CurrentProcess(), ...)
// with the desired access instead, or use GetCurrentProcessToken for a
// TOKEN_QUERY token.
func OpenCurrentProcessToken() (Token, error) {
p, e := GetCurrentProcess()
if e != nil {
return 0, e
}
var t Token
e = OpenProcessToken(p, TOKEN_QUERY|TOKEN_DUPLICATE, &t)
if e != nil {
return 0, e
}
return t, nil
var token Token
err := OpenProcessToken(CurrentProcess(), TOKEN_QUERY, &token)
return token, err
}
// GetCurrentProcessToken returns the access token associated with
@ -890,3 +876,521 @@ type WTS_SESSION_INFO struct {
//sys WTSQueryUserToken(session uint32, token *Token) (err error) = wtsapi32.WTSQueryUserToken
//sys WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
//sys WTSFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
type ACL struct {
aclRevision byte
sbz1 byte
aclSize uint16
aceCount uint16
sbz2 uint16
}
type SECURITY_DESCRIPTOR struct {
revision byte
sbz1 byte
control SECURITY_DESCRIPTOR_CONTROL
owner *SID
group *SID
sacl *ACL
dacl *ACL
}
type SecurityAttributes struct {
Length uint32
SecurityDescriptor *SECURITY_DESCRIPTOR
InheritHandle uint32
}
type SE_OBJECT_TYPE uint32
// Constants for type SE_OBJECT_TYPE
const (
SE_UNKNOWN_OBJECT_TYPE = 0
SE_FILE_OBJECT = 1
SE_SERVICE = 2
SE_PRINTER = 3
SE_REGISTRY_KEY = 4
SE_LMSHARE = 5
SE_KERNEL_OBJECT = 6
SE_WINDOW_OBJECT = 7
SE_DS_OBJECT = 8
SE_DS_OBJECT_ALL = 9
SE_PROVIDER_DEFINED_OBJECT = 10
SE_WMIGUID_OBJECT = 11
SE_REGISTRY_WOW64_32KEY = 12
SE_REGISTRY_WOW64_64KEY = 13
)
type SECURITY_INFORMATION uint32
// Constants for type SECURITY_INFORMATION
const (
OWNER_SECURITY_INFORMATION = 0x00000001
GROUP_SECURITY_INFORMATION = 0x00000002
DACL_SECURITY_INFORMATION = 0x00000004
SACL_SECURITY_INFORMATION = 0x00000008
LABEL_SECURITY_INFORMATION = 0x00000010
ATTRIBUTE_SECURITY_INFORMATION = 0x00000020
SCOPE_SECURITY_INFORMATION = 0x00000040
BACKUP_SECURITY_INFORMATION = 0x00010000
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
)
type SECURITY_DESCRIPTOR_CONTROL uint16
// Constants for type SECURITY_DESCRIPTOR_CONTROL
const (
SE_OWNER_DEFAULTED = 0x0001
SE_GROUP_DEFAULTED = 0x0002
SE_DACL_PRESENT = 0x0004
SE_DACL_DEFAULTED = 0x0008
SE_SACL_PRESENT = 0x0010
SE_SACL_DEFAULTED = 0x0020
SE_DACL_AUTO_INHERIT_REQ = 0x0100
SE_SACL_AUTO_INHERIT_REQ = 0x0200
SE_DACL_AUTO_INHERITED = 0x0400
SE_SACL_AUTO_INHERITED = 0x0800
SE_DACL_PROTECTED = 0x1000
SE_SACL_PROTECTED = 0x2000
SE_RM_CONTROL_VALID = 0x4000
SE_SELF_RELATIVE = 0x8000
)
type ACCESS_MASK uint32
// Constants for type ACCESS_MASK
const (
DELETE = 0x00010000
READ_CONTROL = 0x00020000
WRITE_DAC = 0x00040000
WRITE_OWNER = 0x00080000
SYNCHRONIZE = 0x00100000
STANDARD_RIGHTS_REQUIRED = 0x000F0000
STANDARD_RIGHTS_READ = READ_CONTROL
STANDARD_RIGHTS_WRITE = READ_CONTROL
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
STANDARD_RIGHTS_ALL = 0x001F0000
SPECIFIC_RIGHTS_ALL = 0x0000FFFF
ACCESS_SYSTEM_SECURITY = 0x01000000
MAXIMUM_ALLOWED = 0x02000000
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
GENERIC_ALL = 0x10000000
)
type ACCESS_MODE uint32
// Constants for type ACCESS_MODE
const (
NOT_USED_ACCESS = 0
GRANT_ACCESS = 1
SET_ACCESS = 2
DENY_ACCESS = 3
REVOKE_ACCESS = 4
SET_AUDIT_SUCCESS = 5
SET_AUDIT_FAILURE = 6
)
// Constants for AceFlags and Inheritance fields
const (
NO_INHERITANCE = 0x0
SUB_OBJECTS_ONLY_INHERIT = 0x1
SUB_CONTAINERS_ONLY_INHERIT = 0x2
SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3
INHERIT_NO_PROPAGATE = 0x4
INHERIT_ONLY = 0x8
INHERITED_ACCESS_ENTRY = 0x10
INHERITED_PARENT = 0x10000000
INHERITED_GRANDPARENT = 0x20000000
OBJECT_INHERIT_ACE = 0x1
CONTAINER_INHERIT_ACE = 0x2
NO_PROPAGATE_INHERIT_ACE = 0x4
INHERIT_ONLY_ACE = 0x8
INHERITED_ACE = 0x10
VALID_INHERIT_FLAGS = 0x1F
)
type MULTIPLE_TRUSTEE_OPERATION uint32
// Constants for MULTIPLE_TRUSTEE_OPERATION
const (
NO_MULTIPLE_TRUSTEE = 0
TRUSTEE_IS_IMPERSONATE = 1
)
type TRUSTEE_FORM uint32
// Constants for TRUSTEE_FORM
const (
TRUSTEE_IS_SID = 0
TRUSTEE_IS_NAME = 1
TRUSTEE_BAD_FORM = 2
TRUSTEE_IS_OBJECTS_AND_SID = 3
TRUSTEE_IS_OBJECTS_AND_NAME = 4
)
type TRUSTEE_TYPE uint32
// Constants for TRUSTEE_TYPE
const (
TRUSTEE_IS_UNKNOWN = 0
TRUSTEE_IS_USER = 1
TRUSTEE_IS_GROUP = 2
TRUSTEE_IS_DOMAIN = 3
TRUSTEE_IS_ALIAS = 4
TRUSTEE_IS_WELL_KNOWN_GROUP = 5
TRUSTEE_IS_DELETED = 6
TRUSTEE_IS_INVALID = 7
TRUSTEE_IS_COMPUTER = 8
)
// Constants for ObjectsPresent field
const (
ACE_OBJECT_TYPE_PRESENT = 0x1
ACE_INHERITED_OBJECT_TYPE_PRESENT = 0x2
)
type EXPLICIT_ACCESS struct {
AccessPermissions ACCESS_MASK
AccessMode ACCESS_MODE
Inheritance uint32
Trustee TRUSTEE
}
// This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions.
type TrusteeValue uintptr
func TrusteeValueFromString(str string) TrusteeValue {
return TrusteeValue(unsafe.Pointer(StringToUTF16Ptr(str)))
}
func TrusteeValueFromSID(sid *SID) TrusteeValue {
return TrusteeValue(unsafe.Pointer(sid))
}
func TrusteeValueFromObjectsAndSid(objectsAndSid *OBJECTS_AND_SID) TrusteeValue {
return TrusteeValue(unsafe.Pointer(objectsAndSid))
}
func TrusteeValueFromObjectsAndName(objectsAndName *OBJECTS_AND_NAME) TrusteeValue {
return TrusteeValue(unsafe.Pointer(objectsAndName))
}
type TRUSTEE struct {
MultipleTrustee *TRUSTEE
MultipleTrusteeOperation MULTIPLE_TRUSTEE_OPERATION
TrusteeForm TRUSTEE_FORM
TrusteeType TRUSTEE_TYPE
TrusteeValue TrusteeValue
}
type OBJECTS_AND_SID struct {
ObjectsPresent uint32
ObjectTypeGuid GUID
InheritedObjectTypeGuid GUID
Sid *SID
}
type OBJECTS_AND_NAME struct {
ObjectsPresent uint32
ObjectType SE_OBJECT_TYPE
ObjectTypeName *uint16
InheritedObjectTypeName *uint16
Name *uint16
}
//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
//sys SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) = advapi32.SetSecurityInfo
//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
//sys SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) = advapi32.SetNamedSecurityInfoW
//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
//sys initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) = advapi32.InitializeSecurityDescriptor
//sys getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) = advapi32.GetSecurityDescriptorControl
//sys getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorDacl
//sys getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorSacl
//sys getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner
//sys getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorGroup
//sys getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) = advapi32.GetSecurityDescriptorLength
//sys getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) [failretval!=0] = advapi32.GetSecurityDescriptorRMControl
//sys isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) = advapi32.IsValidSecurityDescriptor
//sys setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) = advapi32.SetSecurityDescriptorControl
//sys setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl
//sys setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl
//sys setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) = advapi32.SetSecurityDescriptorOwner
//sys setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) = advapi32.SetSecurityDescriptorGroup
//sys setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) = advapi32.SetSecurityDescriptorRMControl
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
//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
//sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD
//sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW
// Control returns the security descriptor control bits.
func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) {
err = getSecurityDescriptorControl(sd, &control, &revision)
return
}
// SetControl sets the security descriptor control bits.
func (sd *SECURITY_DESCRIPTOR) SetControl(controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) error {
return setSecurityDescriptorControl(sd, controlBitsOfInterest, controlBitsToSet)
}
// RMControl returns the security descriptor resource manager control bits.
func (sd *SECURITY_DESCRIPTOR) RMControl() (control uint8, err error) {
err = getSecurityDescriptorRMControl(sd, &control)
return
}
// SetRMControl sets the security descriptor resource manager control bits.
func (sd *SECURITY_DESCRIPTOR) SetRMControl(rmControl uint8) {
setSecurityDescriptorRMControl(sd, &rmControl)
}
// DACL returns the security descriptor DACL and whether it was defaulted. The dacl return value may be nil
// if a DACL exists but is an "empty DACL", meaning fully permissive. If the DACL does not exist, err returns
// ERROR_OBJECT_NOT_FOUND.
func (sd *SECURITY_DESCRIPTOR) DACL() (dacl *ACL, defaulted bool, err error) {
var present bool
err = getSecurityDescriptorDacl(sd, &present, &dacl, &defaulted)
if !present {
err = ERROR_OBJECT_NOT_FOUND
}
return
}
// SetDACL sets the absolute security descriptor DACL.
func (absoluteSD *SECURITY_DESCRIPTOR) SetDACL(dacl *ACL, present, defaulted bool) error {
return setSecurityDescriptorDacl(absoluteSD, present, dacl, defaulted)
}
// SACL returns the security descriptor SACL and whether it was defaulted. The sacl return value may be nil
// if a SACL exists but is an "empty SACL", meaning fully permissive. If the SACL does not exist, err returns
// ERROR_OBJECT_NOT_FOUND.
func (sd *SECURITY_DESCRIPTOR) SACL() (sacl *ACL, defaulted bool, err error) {
var present bool
err = getSecurityDescriptorSacl(sd, &present, &sacl, &defaulted)
if !present {
err = ERROR_OBJECT_NOT_FOUND
}
return
}
// SetSACL sets the absolute security descriptor SACL.
func (absoluteSD *SECURITY_DESCRIPTOR) SetSACL(sacl *ACL, present, defaulted bool) error {
return setSecurityDescriptorSacl(absoluteSD, present, sacl, defaulted)
}
// Owner returns the security descriptor owner and whether it was defaulted.
func (sd *SECURITY_DESCRIPTOR) Owner() (owner *SID, defaulted bool, err error) {
err = getSecurityDescriptorOwner(sd, &owner, &defaulted)
return
}
// SetOwner sets the absolute security descriptor owner.
func (absoluteSD *SECURITY_DESCRIPTOR) SetOwner(owner *SID, defaulted bool) error {
return setSecurityDescriptorOwner(absoluteSD, owner, defaulted)
}
// Group returns the security descriptor group and whether it was defaulted.
func (sd *SECURITY_DESCRIPTOR) Group() (group *SID, defaulted bool, err error) {
err = getSecurityDescriptorGroup(sd, &group, &defaulted)
return
}
// SetGroup sets the absolute security descriptor owner.
func (absoluteSD *SECURITY_DESCRIPTOR) SetGroup(group *SID, defaulted bool) error {
return setSecurityDescriptorGroup(absoluteSD, group, defaulted)
}
// Length returns the length of the security descriptor.
func (sd *SECURITY_DESCRIPTOR) Length() uint32 {
return getSecurityDescriptorLength(sd)
}
// IsValid returns whether the security descriptor is valid.
func (sd *SECURITY_DESCRIPTOR) IsValid() bool {
return isValidSecurityDescriptor(sd)
}
// String returns the SDDL form of the security descriptor, with a function signature that can be
// used with %v formatting directives.
func (sd *SECURITY_DESCRIPTOR) String() string {
var sddl *uint16
err := convertSecurityDescriptorToStringSecurityDescriptor(sd, 1, 0xff, &sddl, nil)
if err != nil {
return ""
}
defer LocalFree(Handle(unsafe.Pointer(sddl)))
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(sddl))[:])
}
// ToAbsolute converts a self-relative security descriptor into an absolute one.
func (selfRelativeSD *SECURITY_DESCRIPTOR) ToAbsolute() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
control, _, err := selfRelativeSD.Control()
if err != nil {
return
}
if control&SE_SELF_RELATIVE == 0 {
err = ERROR_INVALID_PARAMETER
return
}
var absoluteSDSize, daclSize, saclSize, ownerSize, groupSize uint32
err = makeAbsoluteSD(selfRelativeSD, nil, &absoluteSDSize,
nil, &daclSize, nil, &saclSize, nil, &ownerSize, nil, &groupSize)
switch err {
case ERROR_INSUFFICIENT_BUFFER:
case nil:
// makeAbsoluteSD is expected to fail, but it succeeds.
return nil, ERROR_INTERNAL_ERROR
default:
return nil, err
}
if absoluteSDSize > 0 {
absoluteSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, absoluteSDSize)[0]))
}
var (
dacl *ACL
sacl *ACL
owner *SID
group *SID
)
if daclSize > 0 {
dacl = (*ACL)(unsafe.Pointer(&make([]byte, daclSize)[0]))
}
if saclSize > 0 {
sacl = (*ACL)(unsafe.Pointer(&make([]byte, saclSize)[0]))
}
if ownerSize > 0 {
owner = (*SID)(unsafe.Pointer(&make([]byte, ownerSize)[0]))
}
if groupSize > 0 {
group = (*SID)(unsafe.Pointer(&make([]byte, groupSize)[0]))
}
err = makeAbsoluteSD(selfRelativeSD, absoluteSD, &absoluteSDSize,
dacl, &daclSize, sacl, &saclSize, owner, &ownerSize, group, &groupSize)
return
}
// ToSelfRelative converts an absolute security descriptor into a self-relative one.
func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURITY_DESCRIPTOR, err error) {
control, _, err := absoluteSD.Control()
if err != nil {
return
}
if control&SE_SELF_RELATIVE != 0 {
err = ERROR_INVALID_PARAMETER
return
}
var selfRelativeSDSize uint32
err = makeSelfRelativeSD(absoluteSD, nil, &selfRelativeSDSize)
switch err {
case ERROR_INSUFFICIENT_BUFFER:
case nil:
// makeSelfRelativeSD is expected to fail, but it succeeds.
return nil, ERROR_INTERNAL_ERROR
default:
return nil, err
}
if selfRelativeSDSize > 0 {
selfRelativeSD = (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&make([]byte, selfRelativeSDSize)[0]))
}
err = makeSelfRelativeSD(absoluteSD, selfRelativeSD, &selfRelativeSDSize)
return
}
func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {
sdBytes := make([]byte, selfRelativeSD.Length())
copy(sdBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(selfRelativeSD))[:len(sdBytes)])
return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&sdBytes[0]))
}
// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a
// self-relative security descriptor object allocated on the Go heap.
func SecurityDescriptorFromString(sddl string) (sd *SECURITY_DESCRIPTOR, err error) {
var winHeapSD *SECURITY_DESCRIPTOR
err = convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &winHeapSD, nil)
if err != nil {
return
}
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
}
// GetSecurityInfo queries the security information for a given handle and returns the self-relative security
// descriptor result on the Go heap.
func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
var winHeapSD *SECURITY_DESCRIPTOR
err = getSecurityInfo(handle, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
if err != nil {
return
}
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
}
// GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security
// descriptor result on the Go heap.
func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) {
var winHeapSD *SECURITY_DESCRIPTOR
err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD)
if err != nil {
return
}
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
}
// BuildSecurityDescriptor makes a new security descriptor using the input trustees, explicit access lists, and
// prior security descriptor to be merged, any of which can be nil, returning the self-relative security descriptor
// result on the Go heap.
func BuildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, accessEntries []EXPLICIT_ACCESS, auditEntries []EXPLICIT_ACCESS, mergedSecurityDescriptor *SECURITY_DESCRIPTOR) (sd *SECURITY_DESCRIPTOR, err error) {
var winHeapSD *SECURITY_DESCRIPTOR
var winHeapSDSize uint32
var firstAccessEntry *EXPLICIT_ACCESS
if len(accessEntries) > 0 {
firstAccessEntry = &accessEntries[0]
}
var firstAuditEntry *EXPLICIT_ACCESS
if len(auditEntries) > 0 {
firstAuditEntry = &auditEntries[0]
}
err = buildSecurityDescriptor(owner, group, uint32(len(accessEntries)), firstAccessEntry, uint32(len(auditEntries)), firstAuditEntry, mergedSecurityDescriptor, &winHeapSDSize, &winHeapSD)
if err != nil {
return
}
defer LocalFree(Handle(unsafe.Pointer(winHeapSD)))
return winHeapSD.copySelfRelativeSecurityDescriptor(), nil
}
// NewSecurityDescriptor creates and initializes a new absolute security descriptor.
func NewSecurityDescriptor() (absoluteSD *SECURITY_DESCRIPTOR, err error) {
absoluteSD = &SECURITY_DESCRIPTOR{}
err = initializeSecurityDescriptor(absoluteSD, 1)
return
}
// ACLFromEntries returns a new ACL on the Go heap containing a list of explicit entries as well as those of another ACL.
// Both explicitEntries and mergedACL are optional and can be nil.
func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL, err error) {
var firstExplicitEntry *EXPLICIT_ACCESS
if len(explicitEntries) > 0 {
firstExplicitEntry = &explicitEntries[0]
}
var winHeapACL *ACL
err = setEntriesInAcl(uint32(len(explicitEntries)), firstExplicitEntry, mergedACL, &winHeapACL)
if err != nil {
return
}
defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))
aclBytes := make([]byte, winHeapACL.aclSize)
copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes)])
return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil
}

View file

@ -57,6 +57,10 @@ const (
FILE_VOLUME_IS_COMPRESSED = 0x00008000
FILE_VOLUME_QUOTAS = 0x00000020
// Flags for LockFileEx.
LOCKFILE_FAIL_IMMEDIATELY = 0x00000001
LOCKFILE_EXCLUSIVE_LOCK = 0x00000002
// Return values of SleepEx and other APC functions
STATUS_USER_APC = 0x000000C0
WAIT_IO_COMPLETION = STATUS_USER_APC
@ -136,6 +140,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) = LoadLibraryExW
//sys FreeLibrary(handle Handle) (err error)
//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error)
//sys GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
//sys GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) = kernel32.GetModuleHandleExW
//sys GetVersion() (ver uint32, err error)
//sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
//sys ExitProcess(exitcode uint32)
@ -160,6 +166,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys DeleteFile(path *uint16) (err error) = DeleteFileW
//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW
//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
//sys LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error)
//sys UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error)
//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
//sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
//sys SetEndOfFile(handle Handle) (err error)
@ -173,13 +181,11 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys CancelIoEx(s Handle, o *Overlapped) (err error)
//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
//sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error)
//sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) = shell32.ShellExecuteW
//sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW
//sys shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) = shell32.SHGetKnownFolderPath
//sys TerminateProcess(handle Handle, exitcode uint32) (err error)
//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW
//sys GetCurrentProcess() (pseudoHandle Handle, err error)
//sys GetCurrentThread() (pseudoHandle Handle, err error)
//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]
@ -284,6 +290,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) = FindNextVolumeMountPointW
//sys FindVolumeClose(findVolume Handle) (err error)
//sys FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error)
//sys GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) = GetDiskFreeSpaceExW
//sys GetDriveType(rootPathName *uint16) (driveType uint32) = GetDriveTypeW
//sys GetLogicalDrives() (drivesBitMask uint32, err error) [failretval==0]
//sys GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) [failretval==0] = GetLogicalDriveStringsW
@ -296,6 +303,10 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW
//sys SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW
//sys MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW
//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx
//sys InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) = advapi32.InitiateSystemShutdownExW
//sys SetProcessShutdownParameters(level uint32, flags uint32) (err error) = kernel32.SetProcessShutdownParameters
//sys GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) = kernel32.GetProcessShutdownParameters
//sys clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) = ole32.CLSIDFromString
//sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2
//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid
@ -305,6 +316,34 @@ func NewCallbackCDecl(fn interface{}) uintptr {
// syscall interface implementation for other packages
// GetCurrentProcess returns the handle for the current process.
// It is a pseudo handle that does not need to be closed.
// The returned error is always nil.
//
// Deprecated: use CurrentProcess for the same Handle without the nil
// error.
func GetCurrentProcess() (Handle, error) {
return CurrentProcess(), nil
}
// CurrentProcess returns the handle for the current process.
// It is a pseudo handle that does not need to be closed.
func CurrentProcess() Handle { return Handle(^uintptr(1 - 1)) }
// GetCurrentThread returns the handle for the current thread.
// It is a pseudo handle that does not need to be closed.
// The returned error is always nil.
//
// Deprecated: use CurrentThread for the same Handle without the nil
// error.
func GetCurrentThread() (Handle, error) {
return CurrentThread(), nil
}
// CurrentThread returns the handle for the current thread.
// It is a pseudo handle that does not need to be closed.
func CurrentThread() Handle { return Handle(^uintptr(2 - 1)) }
// GetProcAddressByOrdinal retrieves the address of the exported
// function from module by ordinal.
func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err error) {

View file

@ -62,11 +62,6 @@ var signals = [...]string{
}
const (
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
GENERIC_ALL = 0x10000000
FILE_LIST_DIRECTORY = 0x00000001
FILE_APPEND_DATA = 0x00000004
FILE_WRITE_ATTRIBUTES = 0x00000100
@ -158,13 +153,6 @@ const (
WAIT_OBJECT_0 = 0x00000000
WAIT_FAILED = 0xFFFFFFFF
// Standard access rights.
DELETE = 0x00010000
READ_CONTROL = 0x00020000
SYNCHRONIZE = 0x00100000
WRITE_DAC = 0x00040000
WRITE_OWNER = 0x00080000
// Access rights for process.
PROCESS_CREATE_PROCESS = 0x0080
PROCESS_CREATE_THREAD = 0x0002
@ -483,12 +471,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
return
}
type SecurityAttributes struct {
Length uint32
SecurityDescriptor uintptr
InheritHandle uint32
}
type Overlapped struct {
Internal uintptr
InternalHigh uintptr
@ -1688,3 +1670,75 @@ type OsVersionInfoEx struct {
ProductType byte
_ byte
}
const (
EWX_LOGOFF = 0x00000000
EWX_SHUTDOWN = 0x00000001
EWX_REBOOT = 0x00000002
EWX_FORCE = 0x00000004
EWX_POWEROFF = 0x00000008
EWX_FORCEIFHUNG = 0x00000010
EWX_QUICKRESOLVE = 0x00000020
EWX_RESTARTAPPS = 0x00000040
EWX_HYBRID_SHUTDOWN = 0x00400000
EWX_BOOTOPTIONS = 0x01000000
SHTDN_REASON_FLAG_COMMENT_REQUIRED = 0x01000000
SHTDN_REASON_FLAG_DIRTY_PROBLEM_ID_REQUIRED = 0x02000000
SHTDN_REASON_FLAG_CLEAN_UI = 0x04000000
SHTDN_REASON_FLAG_DIRTY_UI = 0x08000000
SHTDN_REASON_FLAG_USER_DEFINED = 0x40000000
SHTDN_REASON_FLAG_PLANNED = 0x80000000
SHTDN_REASON_MAJOR_OTHER = 0x00000000
SHTDN_REASON_MAJOR_NONE = 0x00000000
SHTDN_REASON_MAJOR_HARDWARE = 0x00010000
SHTDN_REASON_MAJOR_OPERATINGSYSTEM = 0x00020000
SHTDN_REASON_MAJOR_SOFTWARE = 0x00030000
SHTDN_REASON_MAJOR_APPLICATION = 0x00040000
SHTDN_REASON_MAJOR_SYSTEM = 0x00050000
SHTDN_REASON_MAJOR_POWER = 0x00060000
SHTDN_REASON_MAJOR_LEGACY_API = 0x00070000
SHTDN_REASON_MINOR_OTHER = 0x00000000
SHTDN_REASON_MINOR_NONE = 0x000000ff
SHTDN_REASON_MINOR_MAINTENANCE = 0x00000001
SHTDN_REASON_MINOR_INSTALLATION = 0x00000002
SHTDN_REASON_MINOR_UPGRADE = 0x00000003
SHTDN_REASON_MINOR_RECONFIG = 0x00000004
SHTDN_REASON_MINOR_HUNG = 0x00000005
SHTDN_REASON_MINOR_UNSTABLE = 0x00000006
SHTDN_REASON_MINOR_DISK = 0x00000007
SHTDN_REASON_MINOR_PROCESSOR = 0x00000008
SHTDN_REASON_MINOR_NETWORKCARD = 0x00000009
SHTDN_REASON_MINOR_POWER_SUPPLY = 0x0000000a
SHTDN_REASON_MINOR_CORDUNPLUGGED = 0x0000000b
SHTDN_REASON_MINOR_ENVIRONMENT = 0x0000000c
SHTDN_REASON_MINOR_HARDWARE_DRIVER = 0x0000000d
SHTDN_REASON_MINOR_OTHERDRIVER = 0x0000000e
SHTDN_REASON_MINOR_BLUESCREEN = 0x0000000F
SHTDN_REASON_MINOR_SERVICEPACK = 0x00000010
SHTDN_REASON_MINOR_HOTFIX = 0x00000011
SHTDN_REASON_MINOR_SECURITYFIX = 0x00000012
SHTDN_REASON_MINOR_SECURITY = 0x00000013
SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY = 0x00000014
SHTDN_REASON_MINOR_WMI = 0x00000015
SHTDN_REASON_MINOR_SERVICEPACK_UNINSTALL = 0x00000016
SHTDN_REASON_MINOR_HOTFIX_UNINSTALL = 0x00000017
SHTDN_REASON_MINOR_SECURITYFIX_UNINSTALL = 0x00000018
SHTDN_REASON_MINOR_MMC = 0x00000019
SHTDN_REASON_MINOR_SYSTEMRESTORE = 0x0000001a
SHTDN_REASON_MINOR_TERMSRV = 0x00000020
SHTDN_REASON_MINOR_DC_PROMOTION = 0x00000021
SHTDN_REASON_MINOR_DC_DEMOTION = 0x00000022
SHTDN_REASON_UNKNOWN = SHTDN_REASON_MINOR_NONE
SHTDN_REASON_LEGACY_API = SHTDN_REASON_MAJOR_LEGACY_API | SHTDN_REASON_FLAG_PLANNED
SHTDN_REASON_VALID_BIT_MASK = 0xc0ffffff
SHUTDOWN_NORETRY = 0x1
)
// Flags used for GetModuleHandleEx
const (
GET_MODULE_HANDLE_EX_FLAG_PIN = 1
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4
)

File diff suppressed because it is too large Load diff