win 0.3.11 → 0.3.16

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.
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.11
1
+ 0.3.16
@@ -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
  ##
@@ -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.
@@ -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, boolean: true
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
@@ -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: :short, # A WCHAR if UNICODE is defined, a CHAR otherwise.TCHAR:
229
- TCHAR: :short, # A WCHAR if UNICODE is defined, a CHAR otherwise.TCHAR:
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
- # :rename:: Use this name instead of standard (conventional) function name
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
- # module_function snake_name # TODO: Doesn't work as a perfect replacement for eigen_class stuff. :( Why?
289
+ api = define_api(name, camel_name, effective_names, params, returns, options)
329
290
 
330
- eigen_class = class << self;
331
- self;
332
- end # Extracting eigenclass
291
+ define_snake_method(snake_name, aliases, api, options, &def_block) unless options[:camel_only]
333
292
 
334
- eigen_class.class_eval do
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
- # Rubyesque name and aliases for method(s) defined based on function name,
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[:rename] || name.snake_case
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 :dll_name
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, dll_name )
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
- @dll_name = dll_name
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.to_sym, *args)
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
+