win 0.3.11 → 0.3.16
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +20 -0
- data/VERSION +1 -1
- data/lib/win/gui/dialog.rb +30 -30
- data/lib/win/gui/input.rb +0 -1
- data/lib/win/gui/message.rb +25 -2
- data/lib/win/library.rb +114 -70
- data/lib/win/system/info.rb +163 -0
- data/lib/win/system/version.rb +571 -0
- data/spec/spec_helper.rb +15 -3
- data/spec/win/error_spec.rb +2 -2
- data/spec/win/gui/message_spec.rb +23 -7
- data/spec/win/library_spec.rb +181 -155
- data/spec/win/system/info_spec.rb +47 -0
- data/spec/win/system/version_spec.rb +169 -0
- metadata +9 -3
data/HISTORY
CHANGED
@@ -38,3 +38,23 @@
|
|
38
38
|
== 0.3.11 / 2010-06-03
|
39
39
|
|
40
40
|
* GetDlgCtrlID function added
|
41
|
+
|
42
|
+
== 0.3.12 / 2010-06-07
|
43
|
+
|
44
|
+
* Library::function improved: treatment of snake_case API fubctions changed
|
45
|
+
|
46
|
+
== 0.3.13 / 2010-06-09
|
47
|
+
|
48
|
+
* Win::System::Info module started
|
49
|
+
|
50
|
+
== 0.3.14 / 2010-06-10
|
51
|
+
|
52
|
+
* System::Version and System::Info functions added
|
53
|
+
|
54
|
+
== 0.3.15 / 2010-06-10
|
55
|
+
|
56
|
+
* System::Version specs added
|
57
|
+
|
58
|
+
== 0.3.16 / 2010-06-11
|
59
|
+
|
60
|
+
* System::Version module completed
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.16
|
data/lib/win/gui/dialog.rb
CHANGED
@@ -217,6 +217,36 @@ module Win
|
|
217
217
|
#
|
218
218
|
function :GetDlgItem, [:ulong, :int], :ulong, zeronil: true
|
219
219
|
|
220
|
+
##
|
221
|
+
# The GetDlgCtrlID function retrieves the identifier of the specified control. In other words,
|
222
|
+
# you give it a handle (say, for a button window inside a dialog), and it returns control ID
|
223
|
+
# that this window is associated with (say IDOK - meaning this window is in fact "OK" button.
|
224
|
+
#
|
225
|
+
# [*Syntax*] int GetDlgCtrlID( HWND hwndCtl );
|
226
|
+
#
|
227
|
+
# hwndCtl:: [in] Handle to the control.
|
228
|
+
#
|
229
|
+
# *Returns*:: If the function succeeds, the return value is the identifier of the control.
|
230
|
+
# If the function fails, the return value is zero. An invalid value for the hwndCtl parameter, for
|
231
|
+
# example, will cause the function to fail. To get extended error information, call GetLastError.
|
232
|
+
# ---
|
233
|
+
# *Remarks*:
|
234
|
+
# GetDlgCtrlID accepts child window handles as well as handles of controls in dialog boxes. An
|
235
|
+
# application sets the identifier for a child window when it creates the window by assigning the
|
236
|
+
# identifier value to the hmenu parameter when calling the CreateWindow or CreateWindowEx function.
|
237
|
+
# Although GetDlgCtrlID may return a value if hwndCtl is a handle to a top-level window, top-level
|
238
|
+
# windows cannot have identifiers and such a return value is never valid.
|
239
|
+
# ---
|
240
|
+
# *See* *Also*
|
241
|
+
# Dialog Boxes Overview, CreateWindow, CreateWindowEx, GetDlgItem
|
242
|
+
# ---
|
243
|
+
# <b>Enhanced (snake_case) API: returns nil instead of zero if function fails</b>
|
244
|
+
#
|
245
|
+
# :call-seq:
|
246
|
+
# control_id = get_dlg_ctrl_id(control_handle)
|
247
|
+
#
|
248
|
+
function :GetDlgCtrlID, [:HWND], :int, zeronil: true
|
249
|
+
|
220
250
|
##
|
221
251
|
# MessageBox Function
|
222
252
|
# --------------------------------------------------------------------------------
|
@@ -300,36 +330,6 @@ module Win
|
|
300
330
|
caption_pointer = FFI::MemoryPointer.from_string(caption)
|
301
331
|
api.call handle, text_pointer, caption_pointer, type }
|
302
332
|
|
303
|
-
##
|
304
|
-
# The GetDlgCtrlID function retrieves the identifier of the specified control. In other words,
|
305
|
-
# you give it a handle (say, for a button window inside a dialog), and it returns control ID
|
306
|
-
# that this window is associated with (say IDOK - meaning this window is in fact "OK" button.
|
307
|
-
#
|
308
|
-
# [*Syntax*] int GetDlgCtrlID( HWND hwndCtl );
|
309
|
-
#
|
310
|
-
# hwndCtl:: [in] Handle to the control.
|
311
|
-
#
|
312
|
-
# *Returns*:: If the function succeeds, the return value is the identifier of the control.
|
313
|
-
# If the function fails, the return value is zero. An invalid value for the hwndCtl parameter, for
|
314
|
-
# example, will cause the function to fail. To get extended error information, call GetLastError.
|
315
|
-
# ---
|
316
|
-
# *Remarks*:
|
317
|
-
# GetDlgCtrlID accepts child window handles as well as handles of controls in dialog boxes. An
|
318
|
-
# application sets the identifier for a child window when it creates the window by assigning the
|
319
|
-
# identifier value to the hmenu parameter when calling the CreateWindow or CreateWindowEx function.
|
320
|
-
# Although GetDlgCtrlID may return a value if hwndCtl is a handle to a top-level window, top-level
|
321
|
-
# windows cannot have identifiers and such a return value is never valid.
|
322
|
-
# ---
|
323
|
-
# *See* *Also*
|
324
|
-
# Dialog Boxes Overview, CreateWindow, CreateWindowEx, GetDlgItem
|
325
|
-
# ---
|
326
|
-
# <b>Enhanced (snake_case) API: returns nil instead of zero if function fails</b>
|
327
|
-
#
|
328
|
-
# :call-seq:
|
329
|
-
# control_id = get_dlg_ctrl_id(control_handle)
|
330
|
-
#
|
331
|
-
function :GetDlgCtrlID, [:HWND], :int, zeronil: true
|
332
|
-
|
333
333
|
# Untested:
|
334
334
|
|
335
335
|
##
|
data/lib/win/gui/input.rb
CHANGED
@@ -134,7 +134,6 @@ module Win
|
|
134
134
|
# Indicates NO data if dwFlags are NOT any of MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP
|
135
135
|
INPUT_MOUSE = 0
|
136
136
|
|
137
|
-
|
138
137
|
##
|
139
138
|
# The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate
|
140
139
|
# a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function.
|
data/lib/win/gui/message.rb
CHANGED
@@ -439,7 +439,7 @@ module Win
|
|
439
439
|
# with the dwThreadId parameter set to the identifier of the current thread.
|
440
440
|
# Msg:: <in> Specifies the message to be posted.
|
441
441
|
# wParam:: <in> Specifies additional message-specific information.
|
442
|
-
# lParam:: <in> Specifies additional message-specific information.
|
442
|
+
# lParam:: <in> Specifies additional message-specific information (can be either :pointer or :long).
|
443
443
|
#
|
444
444
|
# *Returns*:: Nonzero if the function succeeds, zero if it fails. For extended error info, call GetLastError.
|
445
445
|
# ---
|
@@ -456,11 +456,34 @@ module Win
|
|
456
456
|
# the operation will fail. The functions will return before the receiving thread has had a chance to
|
457
457
|
# process the message and the sender will free the memory before it is used. Use the PostQuitMessage
|
458
458
|
# instead of PostMessage to post WM_QUIT message.
|
459
|
+
# ---
|
460
|
+
# <b>Enhanced (snake_case) API: accepts either long or pointer lParam</b>
|
459
461
|
#
|
460
462
|
#:call-seq:
|
461
463
|
# success = post_message(handle, msg, w_param, l_param)
|
462
464
|
#
|
463
|
-
function :PostMessage, [:ulong, :uint, :uint, :pointer], :int,
|
465
|
+
function :PostMessage, [:ulong, :uint, :uint, :pointer], :int,
|
466
|
+
boolean: true, camel_name: :PostMessagePointer, snake_name: :post_message_pointer
|
467
|
+
function :PostMessage, [:ulong, :uint, :uint, :long], :int,
|
468
|
+
boolean: true, camel_name: :PostMessageLong, snake_name: :post_message_long
|
469
|
+
|
470
|
+
def PostMessage(handle, msg, w_param, l_param)
|
471
|
+
# Routes call depending on lParam type (:pointer or :long)
|
472
|
+
case l_param
|
473
|
+
when Fixnum
|
474
|
+
PostMessageLong(handle, msg, w_param, l_param)
|
475
|
+
else
|
476
|
+
PostMessagePointer(handle, msg, w_param, l_param)
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
def post_message(handle, msg, w_param, l_param, &block)
|
481
|
+
if block
|
482
|
+
block[PostMessage(handle, msg, w_param, l_param)]
|
483
|
+
else
|
484
|
+
PostMessage(handle, msg, w_param, l_param) != 0
|
485
|
+
end
|
486
|
+
end
|
464
487
|
|
465
488
|
##
|
466
489
|
# The SendMessage function sends the specified message to a window or windows. It calls the window procedure for
|
data/lib/win/library.rb
CHANGED
@@ -225,8 +225,9 @@ module Win
|
|
225
225
|
SHORT: :short, # A 16-bit integer. The range is –32768 through 32767 decimal.
|
226
226
|
SIZE_T: :ulong, # The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer.
|
227
227
|
SSIZE_T: :long, # Signed SIZE_T.
|
228
|
-
TBYTE: :
|
229
|
-
|
228
|
+
TBYTE: :char, # A WCHAR if UNICODE is defined, a CHAR otherwise.TCHAR:
|
229
|
+
# http://msdn.microsoft.com/en-us/library/c426s321%28VS.80%29.aspx
|
230
|
+
TCHAR: :char, # A WCHAR if UNICODE is defined, a CHAR otherwise.TCHAR:
|
230
231
|
UCHAR: :uchar, # Unsigned CHAR (8 bit)
|
231
232
|
UHALF_PTR: :uint, # Unsigned HALF_PTR. Use within a structure that contains a pointer and two small fields.
|
232
233
|
UINT: :uint, # Unsigned INT. The range is 0 through 4294967295 decimal.
|
@@ -274,70 +275,22 @@ module Win
|
|
274
275
|
# - do other stuff that you think is appropriate to make Windows API function behavior more Ruby-like...
|
275
276
|
# ---
|
276
277
|
# Accepts following options:
|
277
|
-
# :dll:: Use this dll instead of default 'user32'
|
278
|
-
# :
|
278
|
+
# :dll:: Use this dll instead of default ['user32', 'kernel32']
|
279
|
+
# :snake_name:: Overrides default snake_case method name being defined
|
280
|
+
# :camel_name:: Overrides default CamelCase name for function being attached
|
281
|
+
# :camel_only:: If true, no snake_case method is defined
|
279
282
|
# :alias(es):: Provides additional alias(es) for defined method
|
280
283
|
# :boolean:: Forces method to return true/false instead of nonzero/zero
|
281
284
|
# :zeronil:: Forces method to return nil if function result is zero
|
282
285
|
#
|
283
286
|
def function(name, params, returns, options={}, &def_block)
|
284
|
-
snake_name, effective_names, aliases = generate_names(name, options)
|
285
|
-
params, returns = generate_signature(params, returns)
|
286
|
-
libs = ffi_libraries.map(&:name)
|
287
|
-
boolean = options[:boolean]
|
288
|
-
zeronil = options[:zeronil]
|
289
|
-
|
290
|
-
effective_name = effective_names.inject(nil) do |func, effective_name|
|
291
|
-
func || begin
|
292
|
-
# tries to attach basic CamelCase method via FFI
|
293
|
-
attach_function(name, effective_name, params.dup, returns)
|
294
|
-
effective_name
|
295
|
-
rescue FFI::NotFoundError
|
296
|
-
nil
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
raise Win::Errors::NotFoundError.new(name, libs) unless effective_name
|
301
|
-
|
302
|
-
# Create API object that holds information about function names, params, etc
|
303
|
-
api = API.new(namespace, name, effective_name, params, returns, libs)
|
304
|
-
|
305
|
-
# Only define enhanced API if snake_name is different from original name (e.g. keybd_event),
|
306
|
-
# If names are the same, this function is already "attached", not possible to enhance its API
|
307
|
-
unless snake_name.to_s == name.to_s
|
308
|
-
method_body = if def_block
|
309
|
-
if zeronil
|
310
|
-
->(*args, &block){ (res = def_block.(api, *args, &block)) != 0 ? res : nil }
|
311
|
-
elsif boolean
|
312
|
-
->(*args, &block){ def_block.(api, *args, &block) != 0 }
|
313
|
-
else
|
314
|
-
->(*args, &block){ def_block.(api, *args, &block) }
|
315
|
-
end
|
316
|
-
else
|
317
|
-
if zeronil
|
318
|
-
->(*args, &block){ (res = block ? block[api.call(*args)] : api.call(*args)) != 0 ? res : nil }
|
319
|
-
elsif boolean
|
320
|
-
->(*args, &block){ block ? block[api.call(*args)] : api.call(*args) != 0 }
|
321
|
-
else
|
322
|
-
->(*args, &block){ block ? block[api.call(*args)] : api.call(*args) }
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
define_method snake_name, &method_body # define snake_case instance method
|
287
|
+
snake_name, camel_name, effective_names, aliases = generate_names(name, options)
|
327
288
|
|
328
|
-
|
289
|
+
api = define_api(name, camel_name, effective_names, params, returns, options)
|
329
290
|
|
330
|
-
|
331
|
-
self;
|
332
|
-
end # Extracting eigenclass
|
291
|
+
define_snake_method(snake_name, aliases, api, options, &def_block) unless options[:camel_only]
|
333
292
|
|
334
|
-
|
335
|
-
define_method snake_name, &method_body # define snake_case class method
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
aliases.each {|ali| alias_method ali, snake_name } # define aliases
|
340
|
-
api #return api object from function declaration
|
293
|
+
api # Return api object from function declaration # TODO: Do we even NEED api object?
|
341
294
|
end
|
342
295
|
|
343
296
|
# Try to define platform-specific function, rescue error, return message
|
@@ -350,15 +303,82 @@ module Win
|
|
350
303
|
end
|
351
304
|
end
|
352
305
|
|
306
|
+
# Defines CamelCase method calling Win32 API function, and associated API object
|
307
|
+
#
|
308
|
+
def define_api(name, camel_name, effective_names, params, returns, options)
|
309
|
+
params, returns = generate_signature(params.dup, returns)
|
310
|
+
|
311
|
+
ffi_lib *(ffi_libraries.map(&:name) << options[:dll]) if options[:dll]
|
312
|
+
libs = ffi_libraries.map(&:name)
|
313
|
+
|
314
|
+
effective_name = if options[:alternative]
|
315
|
+
|
316
|
+
alt_params, alt_returns, condition = generate_signature(*options.dup[:alternative])
|
317
|
+
api = function name, params, returns,
|
318
|
+
options.dup.merge( camel_only: true, camel_name: "#{camel_name}Original")
|
319
|
+
alt_api = function name, alt_params, alt_returns,
|
320
|
+
options.dup.merge( camel_only: true, camel_name: "#{camel_name}Alternative")
|
321
|
+
define_method camel_name do |*args|
|
322
|
+
(condition[*args] ? alt_api : api).call(*args)
|
323
|
+
end
|
324
|
+
api.effective_name
|
325
|
+
else
|
326
|
+
effective_names.inject(nil) do |func, effective_name|
|
327
|
+
func || begin
|
328
|
+
# Try to attach basic CamelCase method via FFI
|
329
|
+
attach_function(camel_name, effective_name, params.dup, returns)
|
330
|
+
effective_name
|
331
|
+
rescue FFI::NotFoundError
|
332
|
+
nil
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
raise Win::Errors::NotFoundError.new(name, libs) unless effective_name
|
338
|
+
|
339
|
+
# Create API object that holds information about defined and effective function names, params, etc.
|
340
|
+
# This object is further used by enhanced snake_case method to reflect on underlying API and
|
341
|
+
# intelligently call it.
|
342
|
+
API.new(namespace, camel_name, effective_name, params, returns, libs)
|
343
|
+
end
|
344
|
+
|
345
|
+
# Defines enhanced snake_case method and (optionally) aliases to it.
|
346
|
+
# Both instance method and module-level method with the same name is defined
|
347
|
+
#
|
348
|
+
def define_snake_method(snake_name, aliases, api, options, &def_block)
|
349
|
+
# Generate body for snake_case method
|
350
|
+
method_body = generate_snake_method_body(api, options, &def_block)
|
351
|
+
|
352
|
+
# Define snake_case instance method
|
353
|
+
define_method snake_name, &method_body
|
354
|
+
|
355
|
+
# We need to define module(class) level method, but something went wrong with module_function :(
|
356
|
+
# module_function snake_name # TODO: Doesn't work as a perfect replacement for eigen_class stuff. :( Why?
|
357
|
+
|
358
|
+
# OK, instead of module_method we're going to directly modify eigenclass
|
359
|
+
eigen_class = class << self;
|
360
|
+
self;
|
361
|
+
end
|
362
|
+
|
363
|
+
# Define snake_case class method inside eigenclass, that should do it
|
364
|
+
eigen_class.class_eval do
|
365
|
+
define_method snake_name, &method_body
|
366
|
+
end
|
367
|
+
|
368
|
+
# Define (instance method!) aliases, if any
|
369
|
+
aliases.each {|ali| alias_method ali, snake_name }
|
370
|
+
end
|
371
|
+
|
353
372
|
# Generates possible effective names for function in Win32 dll (name+A/W),
|
354
|
-
#
|
373
|
+
# camel_case, snake_case and aliases method names
|
355
374
|
#
|
356
375
|
def generate_names(name, options={})
|
357
376
|
name = name.to_s
|
358
377
|
effective_names = [name]
|
359
378
|
effective_names += ["#{name}A", "#{name}W"] unless name =~ /[WA]$/
|
360
379
|
aliases = ([options[:alias]] + [options[:aliases]]).flatten.compact
|
361
|
-
snake_name = options[:
|
380
|
+
snake_name = options[:snake_name] || name.snake_case
|
381
|
+
camel_name = options[:camel_name] || name.camel_case
|
362
382
|
case snake_name
|
363
383
|
when /^is_/
|
364
384
|
aliases << snake_name.sub(/^is_/, '') + '?'
|
@@ -367,17 +387,40 @@ module Win
|
|
367
387
|
when /^get_/
|
368
388
|
aliases << snake_name.sub(/^get_/, '')
|
369
389
|
end
|
370
|
-
[snake_name, effective_names, aliases]
|
390
|
+
[snake_name, camel_name, effective_names, aliases]
|
371
391
|
end
|
372
392
|
|
373
393
|
##
|
374
394
|
# Generates params and returns (signature) containing only FFI-compliant types
|
375
395
|
#
|
376
|
-
def generate_signature(params, returns)
|
396
|
+
def generate_signature(params, returns, condition=nil)
|
377
397
|
params = params.split(//) if params.respond_to?(:split) # Convert params string into array
|
378
398
|
params.map! {|param| TYPES[param.to_sym] || param} # Convert chars into FFI type symbols
|
379
399
|
returns = TYPES[returns.to_sym] || returns # Convert chars into FFI type symbols
|
380
|
-
[params, returns]
|
400
|
+
[params, returns, condition]
|
401
|
+
end
|
402
|
+
|
403
|
+
# Generates body for snake_case method according to directives contained in options
|
404
|
+
# options (:boolean, :zeronil) currently supported
|
405
|
+
#
|
406
|
+
def generate_snake_method_body(api, options, &def_block)
|
407
|
+
if def_block
|
408
|
+
if options[:zeronil]
|
409
|
+
->(*args, &block){ (res = def_block.(api, *args, &block)) != 0 ? res : nil }
|
410
|
+
elsif options[:boolean]
|
411
|
+
->(*args, &block){ def_block.(api, *args, &block) != 0 }
|
412
|
+
else
|
413
|
+
->(*args, &block){ def_block.(api, *args, &block) }
|
414
|
+
end
|
415
|
+
else
|
416
|
+
if options[:zeronil]
|
417
|
+
->(*args, &block){ (res = block ? block[api.call(*args)] : api.call(*args)) != 0 ? res : nil }
|
418
|
+
elsif options[:boolean]
|
419
|
+
->(*args, &block){ block ? block[api.call(*args)] : api.call(*args) != 0 }
|
420
|
+
else
|
421
|
+
->(*args, &block){ block ? block[api.call(*args)] : api.call(*args) }
|
422
|
+
end
|
423
|
+
end
|
381
424
|
end
|
382
425
|
|
383
426
|
##
|
@@ -424,12 +467,13 @@ module Win
|
|
424
467
|
class API
|
425
468
|
|
426
469
|
# The name of the DLL(s) that export this API function
|
427
|
-
attr_reader :
|
470
|
+
attr_reader :dll
|
471
|
+
alias_method :dll_name, :dll
|
428
472
|
|
429
473
|
# Ruby namespace (module) where this API function is attached
|
430
474
|
attr_reader :namespace
|
431
475
|
|
432
|
-
# The name of the function passed to the constructor
|
476
|
+
# The name of the (CamelCase) function passed to the constructor
|
433
477
|
attr_reader :function_name
|
434
478
|
|
435
479
|
# The name of the actual Windows API function. For example, if you passed 'GetUserName' to the
|
@@ -442,18 +486,18 @@ module Win
|
|
442
486
|
# The return type (:void for no return value)
|
443
487
|
attr_reader :return_type
|
444
488
|
|
445
|
-
def initialize( namespace, function_name, effective_function_name, prototype, return_type,
|
489
|
+
def initialize( namespace, function_name, effective_function_name, prototype, return_type, dll )
|
446
490
|
@namespace = namespace
|
447
|
-
@function_name = function_name
|
448
|
-
@effective_function_name = effective_function_name
|
491
|
+
@function_name = function_name.to_sym
|
492
|
+
@effective_function_name = effective_function_name.to_sym
|
449
493
|
@prototype = prototype
|
450
494
|
@return_type = return_type
|
451
|
-
@
|
495
|
+
@dll = dll
|
452
496
|
end
|
453
497
|
|
454
498
|
# Calls underlying CamelCase Windows API function with supplied args
|
455
499
|
def call( *args )
|
456
|
-
@namespace.send(@function_name
|
500
|
+
@namespace.send(@function_name, *args)
|
457
501
|
end
|
458
502
|
|
459
503
|
# alias_method :[], :call
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'win/library'
|
2
|
+
|
3
|
+
module Win
|
4
|
+
module System
|
5
|
+
|
6
|
+
# Contains constants and Win32 API functions related to dialog manipulation.
|
7
|
+
# Windows dialog basics can be found here:
|
8
|
+
# http://msdn.microsoft.com/en-us/library/ms644996#init_box
|
9
|
+
module Info
|
10
|
+
extend Win::Library
|
11
|
+
|
12
|
+
# Enum COMPUTER_NAME_FORMAT (for GetComputerNameEx)
|
13
|
+
|
14
|
+
ComputerNameNetBIOS = 0
|
15
|
+
ComputerNameDnsHostname = 1
|
16
|
+
ComputerNameDnsDomain = 2
|
17
|
+
ComputerNameDnsFullyQualified = 3
|
18
|
+
ComputerNamePhysicalNetBIOS = 4
|
19
|
+
ComputerNamePhysicalDnsHostname = 5
|
20
|
+
ComputerNamePhysicalDnsDomain = 6
|
21
|
+
ComputerNamePhysicalDnsFullyQualified = 7
|
22
|
+
ComputerNameMax = 8
|
23
|
+
|
24
|
+
class << self
|
25
|
+
# Helper method that creates def_block returning (possibly encoded) string as a result of
|
26
|
+
# api function call or nil if api call was not successful. TODO: put this into some kind of helper?
|
27
|
+
#
|
28
|
+
def return_sized_string( encode = nil ) #:nodoc:
|
29
|
+
lambda do |api, *args|
|
30
|
+
namespace.enforce_count( args, api.prototype, -2)
|
31
|
+
buffer = FFI::MemoryPointer.new :char, 1024
|
32
|
+
size = FFI::MemoryPointer.new(:long).write_long(buffer.size)
|
33
|
+
args += [buffer, size]
|
34
|
+
success = api.call(*args)
|
35
|
+
return nil unless success
|
36
|
+
num_chars = size.read_long
|
37
|
+
if encode
|
38
|
+
string = buffer.get_bytes(0, num_chars*2)
|
39
|
+
string = string.force_encoding('utf-16LE').encode(encode)
|
40
|
+
else
|
41
|
+
string = buffer.get_bytes(0, num_chars)
|
42
|
+
end
|
43
|
+
string.rstrip
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private :return_sized_string
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# GetComputerName Function.
|
52
|
+
# Retrieves the NetBIOS name of the local computer. This name is established at system startup, when the
|
53
|
+
# system reads it from the registry.
|
54
|
+
# GetComputerName retrieves only the NetBIOS name of the local computer. To retrieve the DNS host name,
|
55
|
+
# DNS domain name, or the fully qualified DNS name, call the GetComputerNameEx function. Additional
|
56
|
+
# information is provided by the IADsADSystemInfo interface.
|
57
|
+
# The behavior of this function can be affected if the local computer is a node in a cluster. For more
|
58
|
+
# information, see ResUtilGetEnvironmentWithNetName and UseNetworkName.
|
59
|
+
#
|
60
|
+
# [*Syntax*] BOOL GetComputerName( LPTSTR lpBuffer, LPDWORD lpnSize );
|
61
|
+
#
|
62
|
+
# lpBuffer:: A pointer to a buffer that receives the computer name or the cluster virtual server name. The buffer
|
63
|
+
# size should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters.
|
64
|
+
# lpnSize:: On input, specifies the size of the buffer, in TCHARs. On output, the number of TCHARs copied to the
|
65
|
+
# destination buffer, not including the terminating null character.
|
66
|
+
# If the buffer is too small, the function fails and GetLastError returns ERROR_BUFFER_OVERFLOW. The
|
67
|
+
# lpnSize parameter specifies the size of the buffer required, not including the terminating null char.
|
68
|
+
#
|
69
|
+
# *Returns*:: If the function succeeds, the return value is a nonzero value.
|
70
|
+
# If the function fails, the return value is zero. To get extended error info, call GetLastError.
|
71
|
+
# ---
|
72
|
+
# *Remarks*:
|
73
|
+
# The GetComputerName function retrieves the NetBIOS name established at system startup. Name changes
|
74
|
+
# made by the SetComputerName or SetComputerNameEx functions do not take effect until the user restarts
|
75
|
+
# the computer.
|
76
|
+
# If the caller is running under a client session, this function returns the server name. To retrieve
|
77
|
+
# the client name, use the WTSQuerySessionInformation function.
|
78
|
+
# DLL Requires Kernel32.dll.
|
79
|
+
# Unicode Implemented as GetComputerNameW (Unicode) and GetComputerNameA (ANSI).
|
80
|
+
# ---
|
81
|
+
# *See* *Also*
|
82
|
+
# Computer Names
|
83
|
+
# GetComputerNameEx
|
84
|
+
# SetComputerName
|
85
|
+
# SetComputerNameEx
|
86
|
+
# System Information Functions
|
87
|
+
#
|
88
|
+
# ---
|
89
|
+
# <b>Enhanced (snake_case) API: no arguments needed</b>
|
90
|
+
#
|
91
|
+
# :call-seq:
|
92
|
+
# name = [get_]computer_name()
|
93
|
+
#
|
94
|
+
function :GetComputerName, [:pointer, :pointer], :int8, &return_sized_string
|
95
|
+
|
96
|
+
##
|
97
|
+
# GetUserName Function.
|
98
|
+
# Retrieves the name of the user associated with the current thread.
|
99
|
+
# Use the GetUserNameEx function to retrieve the user name in a specified format. Additional information
|
100
|
+
# is provided by the IADsADSystemInfo interface.
|
101
|
+
#
|
102
|
+
# [*Syntax*] BOOL WINAPI GetUserName( LPTSTR lpBuffer, LPDWORD lpnSize );
|
103
|
+
#
|
104
|
+
# lpBuffer:: A pointer to the buffer to receive the user's logon name. If this buffer is not large enough to
|
105
|
+
# contain the entire user name, the function fails. A buffer size of (UNLEN + 1) characters will hold
|
106
|
+
# the maximum length user name including the terminating null character. UNLEN is defined in Lmcons.h.
|
107
|
+
# lpnSize:: On input, this variable specifies the size of the lpBuffer buffer, in TCHARs. On output, the variable
|
108
|
+
# receives the number of TCHARs copied to the buffer, including the terminating null character.
|
109
|
+
# If lpBuffer is too small, the function fails and GetLastError returns ERROR_INSUFFICIENT_BUFFER. This
|
110
|
+
# parameter receives the required buffer size, including the terminating null character.
|
111
|
+
# If it is greater than 32767, function fails and GetLastError returns ERROR_INSUFFICIENT_BUFFER.
|
112
|
+
#
|
113
|
+
# *Returns*:: If the function succeeds, the return value is a nonzero value, and the variable pointed to
|
114
|
+
# by lpnSize contains the number of TCHARs copied to the buffer specified by lpBuffer,
|
115
|
+
# including the terminating null character. If the function fails, the return value is zero.
|
116
|
+
# To get extended error information, call GetLastError.
|
117
|
+
# ---
|
118
|
+
# *Remarks*:
|
119
|
+
# If the current thread is impersonating another client, the GetUserName function returns the user name
|
120
|
+
# of the client that the thread is impersonating.
|
121
|
+
# Example Code
|
122
|
+
# For an example, see Getting System Information.
|
123
|
+
# Requirements
|
124
|
+
# Client Requires Windows Vista, Windows XP, or Windows 2000 Professional.
|
125
|
+
# Server Requires Windows Server 2008, Windows Server 2003, or Windows 2000 Server.
|
126
|
+
# Header Declared in Winbase.h; include Windows.h.
|
127
|
+
# Library Use Advapi32.lib.
|
128
|
+
# DLL Requires Advapi32.dll.
|
129
|
+
# Unicode Implemented as GetUserNameW (Unicode) and GetUserNameA (ANSI).
|
130
|
+
# ---
|
131
|
+
# *See* *Also*:
|
132
|
+
# GetUserNameEx
|
133
|
+
# LookupAccountName
|
134
|
+
# System Information Functions
|
135
|
+
#
|
136
|
+
# ---
|
137
|
+
# <b>Enhanced (snake_case) API: no arguments needed</b>
|
138
|
+
#
|
139
|
+
# :call-seq:
|
140
|
+
# username = [get_]user_name()
|
141
|
+
#
|
142
|
+
function :GetUserName, [:pointer, :pointer], :int8, :dll=> 'advapi32', &return_sized_string
|
143
|
+
|
144
|
+
# Untested
|
145
|
+
|
146
|
+
##
|
147
|
+
function :GetComputerNameEx, 'PPP', :int8, boolean: true
|
148
|
+
##
|
149
|
+
function :GetUserNameEx, 'LPP', :int8, boolean: true, dll: 'secur32'
|
150
|
+
##
|
151
|
+
function :ExpandEnvironmentStrings, 'PPL', :long
|
152
|
+
##
|
153
|
+
function :GetSystemInfo, 'P', :void
|
154
|
+
##
|
155
|
+
function :GetWindowsDirectory, 'PI', :int
|
156
|
+
##
|
157
|
+
# XP or later
|
158
|
+
try_function :GetSystemWow64Directory, 'PI', :int
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|