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 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
+