-
Notifications
You must be signed in to change notification settings - Fork 12
/
translate.go
102 lines (88 loc) · 2.74 KB
/
translate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* NameTranslator translates distinguished names (DNs) among the various formats supported by Active Directory objects.
The translation is performed by the directory server.
Example, converting an NT4-style object to an RFC 1779 name:
tr, err := adsi.NameTranslator("")
if err != nil {
return err
}
if err := tr.Init("mydomain", api.ADS_NAME_INITTYPE_DOMAIN); err != nil {
return err
}
if err := tr.Set(`mydomain\john`, api.ADS_NAME_TYPE_NT4); err != nil {
return err
}
x, err := tr.Get(api.ADS_NAME_TYPE_1779)
if err != nil {
return err
}
See also https://docs.microsoft.com/en-us/windows/win32/api/iads/nn-iads-iadsnametranslate
*/
package adsi
import (
"sync"
"github.com/go-adsi/adsi/api"
"github.com/scjalliance/comshim"
)
// NameTranslator provides active directory name translation services via the
// IADsNameTranslate interface.
type NameTranslator struct {
m sync.RWMutex
iface *api.IADsNameTranslate
}
func (nt *NameTranslator) closed() bool {
return (nt.iface == nil)
}
// NewNameTranslator creates a new NameTranslator bound to server.
// For the local host, leave server blank ("").
func NewNameTranslator(server string) (*NameTranslator, error) {
comshim.Add(1)
tr, err := api.NewIADsNameTranslate(server)
if err != nil {
return &NameTranslator{}, err
}
return &NameTranslator{iface: tr}, nil
}
// Close will release resources consumed by the translator. It should be
// called when the translator is no longer needed.
func (nt *NameTranslator) Close() {
nt.m.Lock()
defer nt.m.Unlock()
if nt.closed() {
return
}
nt.iface.Release()
comshim.Done()
}
// Init initializes the translator to use either Domain, Server, or GC for translation.
// See ADS_NAME_INITTYPE_ENUM for possible values. adsPath is required for
// Domain and Server types, corresponding to the domain name or the server name respectively.
// Init must be called first.
func (nt *NameTranslator) Init(adsPath string, initType uint32) error {
nt.m.Lock()
defer nt.m.Unlock()
if nt.closed() {
return ErrClosed
}
return nt.iface.Init(adsPath, initType)
}
// Get attempts to get the result of a translation in the specified format. See
// ADS_NAME_TYPE_ENUM for the available options. Get must be called last.
func (nt *NameTranslator) Get(formatType uint32) (string, error) {
nt.m.Lock()
defer nt.m.Unlock()
if nt.closed() {
return "", ErrClosed
}
return nt.iface.Get(formatType)
}
// Set sets the input object to be translated. The adsPath must resolve to a valid domain object,
// in the format matching setType (an ADS_NAME_TYPE_ENUM). Set must be called after Init and
// before Get.
func (nt *NameTranslator) Set(adsPath string, setType uint32) error {
nt.m.Lock()
defer nt.m.Unlock()
if nt.closed() {
return ErrClosed
}
return nt.iface.Set(adsPath, setType)
}