win32-security 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,381 +1,388 @@
1
- require 'windows/security'
2
- require 'windows/thread'
3
- require 'windows/process'
4
- require 'windows/error'
5
- require 'windows/msvcrt/string'
6
- require 'windows/msvcrt/buffer'
7
- require 'socket'
8
-
9
- # The Win32 module serves as a namespace only.
10
- module Win32
11
-
12
- # The Security class serves as a toplevel class namespace.
13
- class Security
14
-
15
- # The SID class encapsulates a Security Identifier.
16
- class SID
17
- include Windows::Security
18
- include Windows::Error
19
- include Windows::MSVCRT::String
20
- include Windows::MSVCRT::Buffer
21
- include Windows::Thread
22
- include Windows::Process
23
-
24
- extend Windows::Security
25
- extend Windows::Error
26
- extend Windows::MSVCRT::String
27
- extend Windows::MSVCRT::Buffer
28
-
29
- # Error class typically raised if any of the SID methods fail
30
- class Error < StandardError; end
31
-
32
- # The version of the Win32::Security::SID class.
33
- VERSION = '0.1.3'
34
-
35
- # Some constant SID's for your convenience, in string format.
36
- # See http://support.microsoft.com/kb/243330 for details.
37
-
38
- Null = 'S-1-0'
39
- Nobody = 'S-1-0-0'
40
- World = 'S-1-1'
41
- Everyone = 'S-1-1-0'
42
- Local = 'S-1-2'
43
- Creator = 'S-1-3'
44
- CreatorOwner = 'S-1-3-0'
45
- CreatorGroup = 'S-1-3-1'
46
- CreatorOwnerServer = 'S-1-3-2'
47
- CreatorGroupServer = 'S-1-3-3'
48
- NonUnique = 'S-1-4'
49
- Nt = 'S-1-5'
50
- Dialup = 'S-1-5-1'
51
- Network = 'S-1-5-2'
52
- Batch = 'S-1-5-3'
53
- Interactive = 'S-1-5-4'
54
- Service = 'S-1-5-6'
55
- Anonymous = 'S-1-5-7'
56
- Proxy = 'S-1-5-8'
57
- EnterpriseDomainControllers = 'S-1-5-9'
58
- PrincipalSelf = 'S-1-5-10'
59
- AuthenticatedUsers = 'S-1-5-11'
60
- RestrictedCode = 'S-1-5-12'
61
- TerminalServerUsers = 'S-1-5-13'
62
- LocalSystem = 'S-1-5-18'
63
- NtLocal = 'S-1-5-19'
64
- NtNetwork = 'S-1-5-20'
65
- BuiltinAdministrators = 'S-1-5-32-544'
66
- BuiltinUsers = 'S-1-5-32-545'
67
- Guests = 'S-1-5-32-546'
68
- PowerUsers = 'S-1-5-32-547'
69
- AccountOperators = 'S-1-5-32-548'
70
- ServerOperators = 'S-1-5-32-549'
71
- PrintOperators = 'S-1-5-32-550'
72
- BackupOperators = 'S-1-5-32-551'
73
- Replicators = 'S-1-5-32-552'
74
-
75
- # The binary SID object itself.
76
- attr_reader :sid
77
-
78
- # The account name passed to the constructor.
79
- attr_reader :account
80
-
81
- # The SID account type, e.g. 'user, 'group', etc.
82
- attr_reader :account_type
83
-
84
- # The domain the SID is on.
85
- attr_reader :domain
86
-
87
- # The host passed to the constructor, or the localhost if none
88
- # was specified.
89
- attr_reader :host
90
-
91
- # Converts a binary SID to a string in S-R-I-S-S... format.
92
- #
93
- def self.sid_to_string(sid)
94
- sid_addr = [sid].pack('p*').unpack('L')[0]
95
- sid_buf = 0.chr * 80
96
- sid_ptr = 0.chr * 4
97
-
98
- unless ConvertSidToStringSid(sid_addr, sid_ptr)
99
- raise Error, get_last_error
100
- end
101
-
102
- strcpy(sid_buf, sid_ptr.unpack('L')[0])
103
- sid_buf.strip
104
- end
105
-
106
- # Converts a string in S-R-I-S-S... format back to a binary SID.
107
- #
108
- def self.string_to_sid(string)
109
- sid_buf = 0.chr * 80
110
- string_addr = [string].pack('p*').unpack('L')[0]
111
-
112
- unless ConvertStringSidToSid(string_addr, sid_buf)
113
- raise Error, get_last_error
114
- end
115
-
116
- if RUBY_VERSION.to_f < 1.9
117
- sid_buf.strip
118
- else
119
- sid_buf.force_encoding('ASCII-8BIT').strip
120
- end
121
- end
122
-
123
- # Creates a new SID with +authority+ and up to 8 +subauthorities+,
124
- # and returns new Win32::Security::SID object.
125
- #
126
- # Example:
127
- #
128
- # sec = Security::SID.create(
129
- # Security::SID::SECURITY_WORLD_SID_AUTHORITY,
130
- # Security::SID::SECURITY_WORLD_RID
131
- # )
132
- #
133
- # p sec
134
- #
135
- # #<Win32::Security::SID:0x2c5a95c
136
- # @host="your_host",
137
- # @account="Everyone",
138
- # @account_type="well known group",
139
- # @sid="\001\001\000\000\000\000\000\001\000\000\000\000",
140
- # @domain=""
141
- # >
142
- #
143
- def self.create(authority, *sub_authorities)
144
- if sub_authorities.length > 8
145
- raise ArgumentError, "maximum of 8 subauthorities allowed"
146
- end
147
-
148
- sid = 0.chr * GetSidLengthRequired(sub_authorities.length)
149
-
150
- auth = 0.chr * 5 + authority.chr
151
-
152
- unless InitializeSid(sid, auth, sub_authorities.length)
153
- raise Error, get_last_error
154
- end
155
-
156
- sub_authorities.each_index do |i|
157
- value = [sub_authorities[i]].pack('L')
158
- auth_ptr = GetSidSubAuthority(sid, i)
159
- memcpy(auth_ptr, value, 4)
160
- end
161
-
162
- new(sid)
163
- end
164
-
165
- # Creates and returns a new Win32::Security::SID object, based on
166
- # the account name, which may also be a binary SID. If a host is
167
- # provided, then the information is retrieved from that host.
168
- # Otherwise, the local host is used.
169
- #
170
- # If no account is provided then it retrieves information for the
171
- # user account associated with the calling thread and the host argument
172
- # is ignored.
173
- #
174
- # Note that this does NOT create a new SID, but merely retrieves
175
- # information for an existing SID. To create a new SID, use the
176
- # SID.create method.
177
- #
178
- # Examples:
179
- #
180
- # # Current user
181
- # Win32::Security::SID.new
182
- #
183
- # # User 'john' on the localhost
184
- # Win32::Security::SID.new('john')
185
- #
186
- # # User 'jane' on a remote machine
187
- # Win32::Security::SID.new('jane', 'some_host')
188
- #
189
- # # Binary SID
190
- # Win32::Security::SID.new("\001\000\000\000\000\000\001\000\000\000\000")
191
- #
192
- def initialize(account=nil, host=Socket.gethostname)
193
- if account.nil?
194
- htoken = [0].pack('L')
195
- bool = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, 1, htoken)
196
- errno = GetLastError()
197
-
198
- if !bool
199
- if errno == ERROR_NO_TOKEN
200
- unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, htoken)
201
- raise get_last_error
202
- end
203
- else
204
- raise get_last_error(errno)
205
- end
206
- end
207
-
208
- htoken = htoken.unpack('V').first
209
- cbti = [0].pack('L')
210
- token_info = 0.chr * 36
211
-
212
- bool = GetTokenInformation(
213
- htoken,
214
- TokenOwner,
215
- token_info,
216
- token_info.size,
217
- cbti
218
- )
219
-
220
- unless bool
221
- raise Error, get_last_error
222
- end
223
- end
224
-
225
- bool = false
226
- sid = 0.chr * 28
227
- sid_cb = [sid.size].pack('L')
228
-
229
- domain_buf = 0.chr * 80
230
- domain_cch = [domain_buf.size].pack('L')
231
-
232
- sid_name_use = 0.chr * 4
233
-
234
- if account
235
- ordinal_val = account[0]
236
- ordinal_val = ordinal_val.ord if RUBY_VERSION.to_f >= 1.9
237
- else
238
- ordinal_val = nil
239
- end
240
-
241
- if ordinal_val.nil?
242
- bool = LookupAccountSid(
243
- nil,
244
- token_info.unpack('L')[0],
245
- sid,
246
- sid_cb,
247
- domain_buf,
248
- domain_cch,
249
- sid_name_use
250
- )
251
- elsif ordinal_val < 10 # Assume it's a binary SID.
252
- bool = LookupAccountSid(
253
- host,
254
- [account].pack('p*').unpack('L')[0],
255
- sid,
256
- sid_cb,
257
- domain_buf,
258
- domain_cch,
259
- sid_name_use
260
- )
261
- else
262
- bool = LookupAccountName(
263
- host,
264
- account,
265
- sid,
266
- sid_cb,
267
- domain_buf,
268
- domain_cch,
269
- sid_name_use
270
- )
271
- end
272
-
273
- unless bool
274
- raise Error, get_last_error
275
- end
276
-
277
- # The arguments are flipped depending on which path we took
278
- if ordinal_val.nil?
279
- buf = 0.chr * 260
280
- ptr = token_info.unpack('L')[0]
281
- memcpy(buf, ptr, token_info.size)
282
- @sid = buf.strip
283
- @account = sid.strip
284
- elsif ordinal_val < 10
285
- @sid = account
286
- @account = sid.strip
287
- else
288
- @sid = sid.strip
289
- @account = account
290
- end
291
-
292
- @host = host
293
- @domain = domain_buf.strip
294
-
295
- @account_type = get_account_type(sid_name_use.unpack('L')[0])
296
- end
297
-
298
- # Synonym for SID.new.
299
- #
300
- def self.open(account=nil, host=Socket.gethostname)
301
- new(account, host)
302
- end
303
-
304
- # Returns the binary SID in string format suitable for display,
305
- # storage or transmission.
306
- #
307
- def to_s
308
- sid_addr = [@sid].pack('p*').unpack('L').first
309
- sid_buf = 0.chr * 80
310
- sid_ptr = 0.chr * 4
311
-
312
- unless ConvertSidToStringSid(sid_addr, sid_ptr)
313
- raise Error, get_last_error
314
- end
315
-
316
- strcpy(sid_buf, sid_ptr.unpack('L').first)
317
- sid_buf.strip
318
- end
319
-
320
- alias to_str to_s
321
-
322
- # Returns whether or not the SID object is equal to +other+.
323
- #
324
- def ==(other)
325
- EqualSid(@sid, other.sid)
326
- end
327
-
328
- # Returns whether or not the SID is a valid sid.
329
- #
330
- def valid?
331
- IsValidSid(@sid)
332
- end
333
-
334
- # Returns whether or not the SID is a well known SID.
335
- #
336
- # Requires Windows XP or later. Earlier versions will raise a
337
- # NoMethodError.
338
- #
339
- def well_known?
340
- if defined? IsWellKnownSid
341
- IsWellKnownSid(@sid)
342
- else
343
- raise NoMethodError, 'requires Windows XP or later'
344
- end
345
- end
346
-
347
- # Returns the length of the SID object, in bytes.
348
- #
349
- def length
350
- GetLengthSid(@sid)
351
- end
352
-
353
- private
354
-
355
- # Converts a numeric account type into a human readable string.
356
- #
357
- def get_account_type(value)
358
- case value
359
- when SidTypeUser
360
- 'user'
361
- when SidTypeGroup
362
- 'group'
363
- when SidTypeDomain
364
- 'domain'
365
- when SidTypeAlias
366
- 'alias'
367
- when SidTypeWellKnownGroup
368
- 'well known group'
369
- when SidTypeDeletedAccount
370
- 'deleted account'
371
- when SidTypeInvalid
372
- 'invalid'
373
- when SidTypeUnknown
374
- 'unknown'
375
- when SidComputer
376
- 'computer'
377
- end
378
- end
379
- end
380
- end
381
- end
1
+ require 'windows/security'
2
+ require 'windows/thread'
3
+ require 'windows/process'
4
+ require 'windows/error'
5
+ require 'windows/msvcrt/string'
6
+ require 'windows/msvcrt/buffer'
7
+ require 'socket'
8
+
9
+ # The Win32 module serves as a namespace only.
10
+ module Win32
11
+
12
+ # The Security class serves as a toplevel class namespace.
13
+ class Security
14
+
15
+ # The SID class encapsulates a Security Identifier.
16
+ class SID
17
+ include Windows::Security
18
+ include Windows::Error
19
+ include Windows::MSVCRT::String
20
+ include Windows::MSVCRT::Buffer
21
+ include Windows::Thread
22
+ include Windows::Process
23
+
24
+ extend Windows::Security
25
+ extend Windows::Error
26
+ extend Windows::MSVCRT::String
27
+ extend Windows::MSVCRT::Buffer
28
+
29
+ # Error class typically raised if any of the SID methods fail
30
+ class Error < StandardError; end
31
+
32
+ # The version of the Win32::Security::SID class.
33
+ VERSION = '0.1.4'
34
+
35
+ # Some constant SID's for your convenience, in string format.
36
+ # See http://support.microsoft.com/kb/243330 for details.
37
+
38
+ Null = 'S-1-0'
39
+ Nobody = 'S-1-0-0'
40
+ World = 'S-1-1'
41
+ Everyone = 'S-1-1-0'
42
+ Local = 'S-1-2'
43
+ Creator = 'S-1-3'
44
+ CreatorOwner = 'S-1-3-0'
45
+ CreatorGroup = 'S-1-3-1'
46
+ CreatorOwnerServer = 'S-1-3-2'
47
+ CreatorGroupServer = 'S-1-3-3'
48
+ NonUnique = 'S-1-4'
49
+ Nt = 'S-1-5'
50
+ Dialup = 'S-1-5-1'
51
+ Network = 'S-1-5-2'
52
+ Batch = 'S-1-5-3'
53
+ Interactive = 'S-1-5-4'
54
+ Service = 'S-1-5-6'
55
+ Anonymous = 'S-1-5-7'
56
+ Proxy = 'S-1-5-8'
57
+ EnterpriseDomainControllers = 'S-1-5-9'
58
+ PrincipalSelf = 'S-1-5-10'
59
+ AuthenticatedUsers = 'S-1-5-11'
60
+ RestrictedCode = 'S-1-5-12'
61
+ TerminalServerUsers = 'S-1-5-13'
62
+ LocalSystem = 'S-1-5-18'
63
+ NtLocal = 'S-1-5-19'
64
+ NtNetwork = 'S-1-5-20'
65
+ BuiltinAdministrators = 'S-1-5-32-544'
66
+ BuiltinUsers = 'S-1-5-32-545'
67
+ Guests = 'S-1-5-32-546'
68
+ PowerUsers = 'S-1-5-32-547'
69
+ AccountOperators = 'S-1-5-32-548'
70
+ ServerOperators = 'S-1-5-32-549'
71
+ PrintOperators = 'S-1-5-32-550'
72
+ BackupOperators = 'S-1-5-32-551'
73
+ Replicators = 'S-1-5-32-552'
74
+
75
+ # The binary SID object itself.
76
+ attr_reader :sid
77
+
78
+ # The account name passed to the constructor.
79
+ attr_reader :account
80
+
81
+ # The SID account type, e.g. 'user, 'group', etc.
82
+ attr_reader :account_type
83
+
84
+ # The domain the SID is on.
85
+ attr_reader :domain
86
+
87
+ # The host passed to the constructor, or the localhost if none
88
+ # was specified.
89
+ attr_reader :host
90
+
91
+ # Converts a binary SID to a string in S-R-I-S-S... format.
92
+ #
93
+ def self.sid_to_string(sid)
94
+ sid_addr = [sid].pack('p*').unpack('L')[0]
95
+ sid_buf = 0.chr * 80
96
+ sid_ptr = 0.chr * 4
97
+
98
+ unless ConvertSidToStringSid(sid_addr, sid_ptr)
99
+ raise Error, get_last_error
100
+ end
101
+
102
+ strcpy(sid_buf, sid_ptr.unpack('L')[0])
103
+ sid_buf.strip
104
+ end
105
+
106
+ # Converts a string in S-R-I-S-S... format back to a binary SID.
107
+ #
108
+ def self.string_to_sid(string)
109
+ string_addr = [string].pack('p*').unpack('L')[0]
110
+ sid_ptr = 0.chr * 4
111
+
112
+ unless ConvertStringSidToSid(string_addr, sid_ptr)
113
+ raise Error, get_last_error
114
+ end
115
+
116
+ unless IsValidSid(sid_ptr.unpack('L')[0])
117
+ raise Error, get_last_error
118
+ end
119
+
120
+ sid_len = GetLengthSid(sid_ptr.unpack('L')[0])
121
+ sid_buf = 0.chr * sid_len
122
+
123
+ unless CopySid(sid_len, [sid_buf].pack('p*').unpack('L')[0], sid_ptr.unpack('L')[0])
124
+ raise Error, get_last_error
125
+ end
126
+
127
+ sid_buf
128
+ end
129
+
130
+ # Creates a new SID with +authority+ and up to 8 +subauthorities+,
131
+ # and returns new Win32::Security::SID object.
132
+ #
133
+ # Example:
134
+ #
135
+ # sec = Security::SID.create(
136
+ # Security::SID::SECURITY_WORLD_SID_AUTHORITY,
137
+ # Security::SID::SECURITY_WORLD_RID
138
+ # )
139
+ #
140
+ # p sec
141
+ #
142
+ # #<Win32::Security::SID:0x2c5a95c
143
+ # @host="your_host",
144
+ # @account="Everyone",
145
+ # @account_type="well known group",
146
+ # @sid="\001\001\000\000\000\000\000\001\000\000\000\000",
147
+ # @domain=""
148
+ # >
149
+ #
150
+ def self.create(authority, *sub_authorities)
151
+ if sub_authorities.length > 8
152
+ raise ArgumentError, "maximum of 8 subauthorities allowed"
153
+ end
154
+
155
+ sid = 0.chr * GetSidLengthRequired(sub_authorities.length)
156
+
157
+ auth = 0.chr * 5 + authority.chr
158
+
159
+ unless InitializeSid(sid, auth, sub_authorities.length)
160
+ raise Error, get_last_error
161
+ end
162
+
163
+ sub_authorities.each_index do |i|
164
+ value = [sub_authorities[i]].pack('L')
165
+ auth_ptr = GetSidSubAuthority(sid, i)
166
+ memcpy(auth_ptr, value, 4)
167
+ end
168
+
169
+ new(sid)
170
+ end
171
+
172
+ # Creates and returns a new Win32::Security::SID object, based on
173
+ # the account name, which may also be a binary SID. If a host is
174
+ # provided, then the information is retrieved from that host.
175
+ # Otherwise, the local host is used.
176
+ #
177
+ # If no account is provided then it retrieves information for the
178
+ # user account associated with the calling thread and the host argument
179
+ # is ignored.
180
+ #
181
+ # Note that this does NOT create a new SID, but merely retrieves
182
+ # information for an existing SID. To create a new SID, use the
183
+ # SID.create method.
184
+ #
185
+ # Examples:
186
+ #
187
+ # # Current user
188
+ # Win32::Security::SID.new
189
+ #
190
+ # # User 'john' on the localhost
191
+ # Win32::Security::SID.new('john')
192
+ #
193
+ # # User 'jane' on a remote machine
194
+ # Win32::Security::SID.new('jane', 'some_host')
195
+ #
196
+ # # Binary SID
197
+ # Win32::Security::SID.new("\001\000\000\000\000\000\001\000\000\000\000")
198
+ #
199
+ def initialize(account=nil, host=Socket.gethostname)
200
+ if account.nil?
201
+ htoken = [0].pack('L')
202
+ bool = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, 1, htoken)
203
+ errno = GetLastError()
204
+
205
+ if !bool
206
+ if errno == ERROR_NO_TOKEN
207
+ unless OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, htoken)
208
+ raise get_last_error
209
+ end
210
+ else
211
+ raise get_last_error(errno)
212
+ end
213
+ end
214
+
215
+ htoken = htoken.unpack('V').first
216
+ cbti = [0].pack('L')
217
+ token_info = 0.chr * 36
218
+
219
+ bool = GetTokenInformation(
220
+ htoken,
221
+ TokenOwner,
222
+ token_info,
223
+ token_info.size,
224
+ cbti
225
+ )
226
+
227
+ unless bool
228
+ raise Error, get_last_error
229
+ end
230
+ end
231
+
232
+ bool = false
233
+ sid = 0.chr * 28
234
+ sid_cb = [sid.size].pack('L')
235
+
236
+ domain_buf = 0.chr * 80
237
+ domain_cch = [domain_buf.size].pack('L')
238
+
239
+ sid_name_use = 0.chr * 4
240
+
241
+ if account
242
+ ordinal_val = account[0]
243
+ ordinal_val = ordinal_val.ord if RUBY_VERSION.to_f >= 1.9
244
+ else
245
+ ordinal_val = nil
246
+ end
247
+
248
+ if ordinal_val.nil?
249
+ bool = LookupAccountSid(
250
+ nil,
251
+ token_info.unpack('L')[0],
252
+ sid,
253
+ sid_cb,
254
+ domain_buf,
255
+ domain_cch,
256
+ sid_name_use
257
+ )
258
+ elsif ordinal_val < 10 # Assume it's a binary SID.
259
+ bool = LookupAccountSid(
260
+ host,
261
+ [account].pack('p*').unpack('L')[0],
262
+ sid,
263
+ sid_cb,
264
+ domain_buf,
265
+ domain_cch,
266
+ sid_name_use
267
+ )
268
+ else
269
+ bool = LookupAccountName(
270
+ host,
271
+ account,
272
+ sid,
273
+ sid_cb,
274
+ domain_buf,
275
+ domain_cch,
276
+ sid_name_use
277
+ )
278
+ end
279
+
280
+ unless bool
281
+ raise Error, get_last_error
282
+ end
283
+
284
+ # The arguments are flipped depending on which path we took
285
+ if ordinal_val.nil?
286
+ buf = 0.chr * 260
287
+ ptr = token_info.unpack('L')[0]
288
+ memcpy(buf, ptr, token_info.size)
289
+ @sid = buf.strip
290
+ @account = sid.strip
291
+ elsif ordinal_val < 10
292
+ @sid = account
293
+ @account = sid.strip
294
+ else
295
+ @sid = sid.strip
296
+ @account = account
297
+ end
298
+
299
+ @host = host
300
+ @domain = domain_buf.strip
301
+
302
+ @account_type = get_account_type(sid_name_use.unpack('L')[0])
303
+ end
304
+
305
+ # Synonym for SID.new.
306
+ #
307
+ def self.open(account=nil, host=Socket.gethostname)
308
+ new(account, host)
309
+ end
310
+
311
+ # Returns the binary SID in string format suitable for display,
312
+ # storage or transmission.
313
+ #
314
+ def to_s
315
+ sid_addr = [@sid].pack('p*').unpack('L').first
316
+ sid_buf = 0.chr * 80
317
+ sid_ptr = 0.chr * 4
318
+
319
+ unless ConvertSidToStringSid(sid_addr, sid_ptr)
320
+ raise Error, get_last_error
321
+ end
322
+
323
+ strcpy(sid_buf, sid_ptr.unpack('L').first)
324
+ sid_buf.strip
325
+ end
326
+
327
+ alias to_str to_s
328
+
329
+ # Returns whether or not the SID object is equal to +other+.
330
+ #
331
+ def ==(other)
332
+ EqualSid(@sid, other.sid)
333
+ end
334
+
335
+ # Returns whether or not the SID is a valid sid.
336
+ #
337
+ def valid?
338
+ IsValidSid(@sid)
339
+ end
340
+
341
+ # Returns whether or not the SID is a well known SID.
342
+ #
343
+ # Requires Windows XP or later. Earlier versions will raise a
344
+ # NoMethodError.
345
+ #
346
+ def well_known?
347
+ if defined? IsWellKnownSid
348
+ IsWellKnownSid(@sid)
349
+ else
350
+ raise NoMethodError, 'requires Windows XP or later'
351
+ end
352
+ end
353
+
354
+ # Returns the length of the SID object, in bytes.
355
+ #
356
+ def length
357
+ GetLengthSid(@sid)
358
+ end
359
+
360
+ private
361
+
362
+ # Converts a numeric account type into a human readable string.
363
+ #
364
+ def get_account_type(value)
365
+ case value
366
+ when SidTypeUser
367
+ 'user'
368
+ when SidTypeGroup
369
+ 'group'
370
+ when SidTypeDomain
371
+ 'domain'
372
+ when SidTypeAlias
373
+ 'alias'
374
+ when SidTypeWellKnownGroup
375
+ 'well known group'
376
+ when SidTypeDeletedAccount
377
+ 'deleted account'
378
+ when SidTypeInvalid
379
+ 'invalid'
380
+ when SidTypeUnknown
381
+ 'unknown'
382
+ when SidComputer
383
+ 'computer'
384
+ end
385
+ end
386
+ end
387
+ end
388
+ end