Module: Win32

Defined in:
lib/init.rb

Defined Under Namespace

Modules: Advapi32, Kernel32, Shell32, User32

Constant Summary collapse

SIZEOF_CHAR =

Constants for Windows API data types and message box options.

Fiddle::SIZEOF_CHAR
SIZEOF_LONG =
Fiddle::SIZEOF_LONG
SEE_MASK_NOCLOSEPROCESS =
0x00000040
MB_OK =
0x00000000
MB_OKCANCEL =
0x00000001
MB_YESNO =
0x00000004
MB_ICONERROR =
0x00000010
MB_ICONQUESTION =
0x00000020
MB_ICONWARNING =
0x00000030
IDIOK =
1
IDICANCEL =
2
IDIYES =
6
IDINO =
7
KEY_ALL_ACCESS =
0xF003F
KEY_CREATE_SUB_KEY =
0x0004
KEY_ENUMERATE_SUB_KEYS =
0x0008
KEY_EXECUTE =
0x20019
KEY_NOTIFY =
0x0010
KEY_QUERY_VALUE =
0x0001
KEY_READ =
0x20019
KEY_SET_VALUE =
0x0002
KEY_WOW64_32KEY =
0x0200
KEY_WOW64_64KEY =
0x0100
KEY_WRITE =
0x20006
TokenElevation =
20
TOKEN_QUERY =
8
STILL_ACTIVE =
259
SW_SHOWNORMAL =
1
SW_SHOW =
5
PROCESS_QUERY_INFORMATION =
1024
PROCESS_VM_READ =
16
HKEY_LOCAL_MACHINE =
-2147483646
REG_NONE =
0
REG_SZ =
1
REG_EXPAND_SZ =
2
REG_BINARY =
3
REG_DWORD =
4
REG_DWORD_LITTLE_ENDIAN =
4
REG_DWORD_BIG_ENDIAN =
5
6
REG_MULTI_SZ =
7
REG_QWORD =
11
REG_QWORD_LITTLE_ENDIAN =
11

Class Method Summary collapse

Class Method Details

.admin?Boolean

Checks if the current user has administrative privileges.

Examples:

Win32.admin?

Returns:

  • (Boolean)

    true if the user is an administrator, false otherwise



628
629
630
631
632
633
634
635
636
637
# File 'lib/init.rb', line 628

def Win32.admin?
  if Win32.isXP?
    return true
  else
    r = Win32.OpenProcessToken(:ProcessHandle => Win32.GetCurrentProcess, :DesiredAccess => TOKEN_QUERY)
    token_handle = r[:TokenHandle]
    r = Win32.GetTokenInformation(:TokenInformationClass => TokenElevation, :TokenHandle => token_handle)
    return (r[:TokenIsElevated] != 0)
  end
end

.AdminShellExecute(args) ⇒ Object

Executes a command as an administrator.

Examples:

Win32.AdminShellExecute(lpFile: 'notepad.exe')

Parameters:

  • args (Hash)

    the arguments for executing the command



644
645
646
647
648
649
650
651
652
653
654
# File 'lib/init.rb', line 644

def Win32.AdminShellExecute(args)
  # open ruby/lich as admin and tell it to open something else
  if not caller.any? { |c| c =~ /eval|run/ }
    r = Win32.GetModuleFileName
    if r[:return] > 0
      if File.exist?(r[:lpFilename])
        Win32.ShellExecuteEx(:lpVerb => 'runas', :lpFile => r[:lpFilename], :lpParameters => "#{File.expand_path($PROGRAM_NAME)} shellexecute #{[Marshal.dump(args)].pack('m').gsub("\n", '')}")
      end
    end
  end
end

.CreateProcess(args) ⇒ Hash

Creates a new process with the specified parameters.

Parameters:

  • args (Hash)

    A hash containing the parameters for process creation.

Options Hash (args):

  • :lpApplicationName (String)

    The name of the application to create.

  • :lpCommandLine (String)

    The command line to execute.

  • :bInheritHandles (Boolean)

    Whether to inherit handles.

  • :dwCreationFlags (Integer)

    Flags for process creation.

  • :lpEnvironment (String)

    The environment block for the new process.

  • :lpCurrentDirectory (String)

    The current directory for the new process.

Returns:

  • (Hash)

    A hash containing the result of the process creation.

    • :return [Boolean] Indicates success or failure.

    • :hProcess [Integer] Handle to the created process.

    • :hThread [Integer] Handle to the created thread.

    • :dwProcessId [Integer] Process ID of the created process.

    • :dwThreadId [Integer] Thread ID of the created thread.



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/init.rb', line 215

def Win32.CreateProcess(args)
  if args[:lpCommandLine]
    lpCommandLine = args[:lpCommandLine].dup
  else
    lpCommandLine = nil
  end
  if args[:bInheritHandles] == false
    bInheritHandles = 0
  elsif args[:bInheritHandles] == true
    bInheritHandles = 1
  else
    bInheritHandles = args[:bInheritHandles].to_i
  end
  if args[:lpEnvironment].class == Array
    # fixme
  end
  lpStartupInfo = [68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  lpStartupInfo_index = { :lpDesktop => 2, :lpTitle => 3, :dwX => 4, :dwY => 5, :dwXSize => 6, :dwYSize => 7, :dwXCountChars => 8, :dwYCountChars => 9, :dwFillAttribute => 10, :dwFlags => 11, :wShowWindow => 12, :hStdInput => 15, :hStdOutput => 16, :hStdError => 17 }
  for sym in [:lpDesktop, :lpTitle]
    if args[sym]
      args[sym] = "#{args[sym]}\0" unless args[sym][-1, 1] == "\0"
      lpStartupInfo[lpStartupInfo_index[sym]] = Fiddle::Pointer.to_ptr(args[sym]).to_i
    end
  end
  for sym in [:dwX, :dwY, :dwXSize, :dwYSize, :dwXCountChars, :dwYCountChars, :dwFillAttribute, :dwFlags, :wShowWindow, :hStdInput, :hStdOutput, :hStdError]
    if args[sym]
      lpStartupInfo[lpStartupInfo_index[sym]] = args[sym]
    end
  end
  lpStartupInfo = lpStartupInfo.pack('LLLLLLLLLLLLSSLLLL')
  lpProcessInformation = [0, 0, 0, 0,].pack('LLLL')
  r = Kernel32.CreateProcess(args[:lpApplicationName], lpCommandLine, args[:lpProcessAttributes], args[:lpThreadAttributes], bInheritHandles, args[:dwCreationFlags].to_i, args[:lpEnvironment], args[:lpCurrentDirectory], lpStartupInfo, lpProcessInformation)
  lpProcessInformation = lpProcessInformation.unpack('LLLL')
  return :return => (r > 0 ? true : false), :hProcess => lpProcessInformation[0], :hThread => lpProcessInformation[1], :dwProcessId => lpProcessInformation[2], :dwThreadId => lpProcessInformation[3]
end

.GetCurrentProcessInteger

Win32.CreateProcess(:lpApplicationName => ‘Launcher.exe’, :lpCommandLine => ‘lich2323.sal’, :lpCurrentDirectory => ‘C:\PROGRA~1\SIMU’)

def Win32.OpenProcess(args={})
   return Kernel32.OpenProcess(args[:dwDesiredAccess].to_i, args[:bInheritHandle].to_i, args[:dwProcessId].to_i)
end

Retrieves the current process ID.

Returns:

  • (Integer)

    The current process ID.



260
261
262
# File 'lib/init.rb', line 260

def Win32.GetCurrentProcess
  return Kernel32.GetCurrentProcess
end

.GetExitCodeProcess(args) ⇒ Hash

Retrieves the exit code of a specified process.

Parameters:

  • args (Hash)

    A hash containing the parameters for exit code retrieval.

Options Hash (args):

  • :hProcess (Integer)

    Handle to the process.

Returns:

  • (Hash)

    A hash containing the result of the exit code retrieval.

    • :return [Integer] The result of the exit code retrieval.

    • :lpExitCode [Integer] The exit code of the specified process.



273
274
275
276
277
# File 'lib/init.rb', line 273

def Win32.GetExitCodeProcess(args)
  lpExitCode = [0].pack('L')
  r = Kernel32.GetExitCodeProcess(args[:hProcess].to_i, lpExitCode)
  return :return => r, :lpExitCode => lpExitCode.unpack('L')[0]
end

.GetLastErrorInteger

Retrieves the last error code from the Windows API.

Returns:

  • (Integer)

    The last error code.



194
195
196
# File 'lib/init.rb', line 194

def Win32.GetLastError
  return Kernel32.GetLastError()
end

.GetModuleFileName(args = {}) ⇒ Hash

Retrieves the file name of a specified module.

Parameters:

  • args (Hash) (defaults to: {})

    A hash containing the parameters for module file name retrieval.

Options Hash (args):

  • :hModule (Integer)

    Handle to the module.

  • :nSize (Integer)

    The size of the buffer for the file name.

Returns:

  • (Hash)

    A hash containing the result of the module file name retrieval.

    • :return [Integer] The result of the retrieval.

    • :lpFilename [String] The file name of the specified module.



289
290
291
292
293
294
# File 'lib/init.rb', line 289

def Win32.GetModuleFileName(args = {})
  args[:nSize] ||= 256
  buffer = "\0" * args[:nSize].to_i
  r = Kernel32.GetModuleFileName(args[:hModule].to_i, buffer, args[:nSize].to_i)
  return :return => r, :lpFilename => buffer.gsub("\0", '')
end

.GetTokenInformation(args) ⇒ Hash?

Retrieves information about a specified access token.

Examples:

Win32.GetTokenInformation(TokenHandle: some_token_handle, TokenInformationClass: TokenElevation)

Parameters:

  • args (Hash)

    the arguments for retrieving token information

Options Hash (args):

  • :TokenHandle (Integer)

    the handle to the access token

  • :TokenInformationClass (Integer)

    the class of information to retrieve

Returns:

  • (Hash, nil)

    a hash containing the result and elevation status, or nil if not applicable



360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/init.rb', line 360

def Win32.GetTokenInformation(args)
  if args[:TokenInformationClass] == TokenElevation
    token_information_length = SIZEOF_LONG
    token_information = [0].pack('L')
  else
    return nil
  end
  return_length = [0].pack('L')
  r = Advapi32.GetTokenInformation(args[:TokenHandle].to_i, args[:TokenInformationClass], token_information, token_information_length, return_length)
  if args[:TokenInformationClass] == TokenElevation
    return :return => r, :TokenIsElevated => token_information.unpack('L')[0]
  end
end

.GetVersionExHash

Retrieves version information about the operating system.

Returns:

  • (Hash)

    A hash containing the version information.

    • :return [Integer] The result of the version retrieval.

    • :dwOSVersionInfoSize [Integer] The size of the version information structure.

    • :dwMajorVersion [Integer] The major version number.

    • :dwMinorVersion [Integer] The minor version number.

    • :dwBuildNumber [Integer] The build number.

    • :dwPlatformId [Integer] The platform identifier.

    • :szCSDVersion [String] The service pack version string.

    • :wServicePackMajor [Integer] The major service pack number.

    • :wServicePackMinor [Integer] The minor service pack number.

    • :wSuiteMask [Integer] The suite mask.

    • :wProductType [Integer] The product type.



312
313
314
315
316
317
# File 'lib/init.rb', line 312

def Win32.GetVersionEx
  a = [156, 0, 0, 0, 0, ("\0" * 128), 0, 0, 0, 0, 0].pack('LLLLLa128SSSCC')
  r = Kernel32.GetVersionEx(a)
  a = a.unpack('LLLLLa128SSSCC')
  return :return => r, :dwOSVersionInfoSize => a[0], :dwMajorVersion => a[1], :dwMinorVersion => a[2], :dwBuildNumber => a[3], :dwPlatformId => a[4], :szCSDVersion => a[5].strip, :wServicePackMajor => a[6], :wServicePackMinor => a[7], :wSuiteMask => a[8], :wProductType => a[9]
end

.isXP?Boolean

Checks if the operating system is Windows XP.

Examples:

Win32.isXP?

Returns:

  • (Boolean)

    true if the OS is Windows XP, false otherwise



614
615
616
# File 'lib/init.rb', line 614

def Win32.isXP?
  return (Win32.GetVersionEx[:dwMajorVersion] < 6)
end

.MessageBox(args) ⇒ Integer

Displays a message box with the specified text and caption.

Examples:

Win32.MessageBox(lpText: "Hello, World!", uType: 0)

Parameters:

  • args (Hash)

    the arguments for the message box

Options Hash (args):

  • :hWnd (Integer)

    the handle to the owner window

  • :lpText (String)

    the text to be displayed in the message box

  • :lpCaption (String)

    the title of the message box (default: “Lich v#LICH_VERSION”)

  • :uType (Integer)

    the type of message box to be displayed

Returns:

  • (Integer)

    the result of the message box operation



335
336
337
338
# File 'lib/init.rb', line 335

def Win32.MessageBox(args)
  args[:lpCaption] ||= "Lich v#{LICH_VERSION}"
  return User32.MessageBox(args[:hWnd].to_i, args[:lpText], args[:lpCaption], args[:uType].to_i)
end

.OpenProcessToken(args) ⇒ Hash

Opens the access token associated with a process.

Examples:

Win32.OpenProcessToken(ProcessHandle: some_process_handle, DesiredAccess: TOKEN_QUERY)

Parameters:

  • args (Hash)

    the arguments for opening the process token

Options Hash (args):

  • :ProcessHandle (Integer)

    the handle to the process

  • :DesiredAccess (Integer)

    the access rights to request

Returns:

  • (Hash)

    a hash containing the result and the token handle



382
383
384
385
386
# File 'lib/init.rb', line 382

def Win32.OpenProcessToken(args)
  token_handle = [0].pack('L')
  r = Advapi32.OpenProcessToken(args[:ProcessHandle].to_i, args[:DesiredAccess].to_i, token_handle)
  return :return => r, :TokenHandle => token_handle.unpack('L')[0]
end

.RegCloseKey(args) ⇒ Integer

Closes a registry key handle.

Examples:

Win32.RegCloseKey(hKey: some_key_handle)

Parameters:

  • args (Hash)

    the arguments for closing the registry key

Options Hash (args):

  • :hKey (Integer)

    the handle to the key to close

Returns:

  • (Integer)

    the result of the close operation



502
503
504
# File 'lib/init.rb', line 502

def Win32.RegCloseKey(args)
  return Advapi32.RegCloseKey(args[:hKey])
end

.RegDeleteValue(args) ⇒ Integer

Deletes a specified value from a registry key.

Examples:

Win32.RegDeleteValue(hKey: some_key_handle, lpValueName: "MyValue")

Parameters:

  • args (Hash)

    the arguments for deleting the registry value

Options Hash (args):

  • :hKey (Integer)

    the handle to the key

  • :lpValueName (String)

    the name of the value to delete (default: 0)

Returns:

  • (Integer)

    the result of the delete operation



490
491
492
493
# File 'lib/init.rb', line 490

def Win32.RegDeleteValue(args)
  args[:lpValueName] ||= 0
  return Advapi32.RegDeleteValue(args[:hKey].to_i, args[:lpValueName])
end

.RegOpenKeyEx(args) ⇒ Hash

Opens a registry key.

Examples:

Win32.RegOpenKeyEx(hKey: some_key_handle, lpSubKey: "Software\\MyApp", samDesired: KEY_READ)

Parameters:

  • args (Hash)

    the arguments for opening the registry key

Options Hash (args):

  • :hKey (Integer)

    the handle to the key to be opened

  • :lpSubKey (String)

    the name of the subkey to open

  • :samDesired (Integer)

    the desired access rights

Returns:

  • (Hash)

    a hash containing the result and the handle to the opened key



397
398
399
400
401
# File 'lib/init.rb', line 397

def Win32.RegOpenKeyEx(args)
  phkResult = [0].pack('L')
  r = Advapi32.RegOpenKeyEx(args[:hKey].to_i, args[:lpSubKey].to_s, 0, args[:samDesired].to_i, phkResult)
  return :return => r, :phkResult => phkResult.unpack('L')[0]
end

.RegQueryValueEx(args) ⇒ Hash

Queries the value of a specified registry key.

Examples:

Win32.RegQueryValueEx(hKey: some_key_handle, lpValueName: "MyValue")

Parameters:

  • args (Hash)

    the arguments for querying the registry value

Options Hash (args):

  • :hKey (Integer)

    the handle to the key

  • :lpValueName (String)

    the name of the value to query (default: 0)

Returns:

  • (Hash)

    a hash containing the result, type, data length, and data



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'lib/init.rb', line 411

def Win32.RegQueryValueEx(args)
  args[:lpValueName] ||= 0
  lpcbData = [0].pack('L')
  r = Advapi32.RegQueryValueEx(args[:hKey].to_i, args[:lpValueName], 0, 0, 0, lpcbData)
  if r == 0
    lpcbData = lpcbData.unpack('L')[0]
    lpData = String.new.rjust(lpcbData, "\x00")
    lpcbData = [lpcbData].pack('L')
    lpType = [0].pack('L')
    r = Advapi32.RegQueryValueEx(args[:hKey].to_i, args[:lpValueName], 0, lpType, lpData, lpcbData)
    lpType = lpType.unpack('L')[0]
    lpcbData = lpcbData.unpack('L')[0]
    if [REG_EXPAND_SZ, REG_SZ, REG_LINK].include?(lpType)
      lpData.gsub!("\x00", '')
    elsif lpType == REG_MULTI_SZ
      lpData = lpData.gsub("\x00\x00", '').split("\x00")
    elsif lpType == REG_DWORD
      lpData = lpData.unpack('L')[0]
    elsif lpType == REG_QWORD
      lpData = lpData.unpack('Q')[0]
    elsif lpType == REG_BINARY
      # fixme
    elsif lpType == REG_DWORD_BIG_ENDIAN
      # fixme
    else
      # fixme
    end
    return :return => r, :lpType => lpType, :lpcbData => lpcbData, :lpData => lpData
  else
    return :return => r
  end
end

.RegSetValueEx(args) ⇒ Boolean

Sets the value of a specified registry key.

Examples:

Win32.RegSetValueEx(hKey: some_key_handle, lpValueName: "MyValue", dwType: REG_SZ, lpData: "Hello")

Parameters:

  • args (Hash)

    the arguments for setting the registry value

Options Hash (args):

  • :hKey (Integer)

    the handle to the key

  • :lpValueName (String)

    the name of the value to set (default: 0)

  • :dwType (Integer)

    the type of the value

  • :lpData (String, Array, Integer)

    the data to set

Returns:

  • (Boolean)

    true if successful, false otherwise



454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
# File 'lib/init.rb', line 454

def Win32.RegSetValueEx(args)
  if [REG_EXPAND_SZ, REG_SZ, REG_LINK].include?(args[:dwType]) and (args[:lpData].class == String)
    lpData = args[:lpData].dup
    lpData.concat("\x00")
    cbData = lpData.length
  elsif (args[:dwType] == REG_MULTI_SZ) and (args[:lpData].class == Array)
    lpData = args[:lpData].join("\x00").concat("\x00\x00")
    cbData = lpData.length
  elsif (args[:dwType] == REG_DWORD) and (args[:lpData].class == Integer)
    lpData = [args[:lpData]].pack('L')
    cbData = 4
  elsif (args[:dwType] == REG_QWORD) and (args[:lpData].class == Integer)
    lpData = [args[:lpData]].pack('Q')
    cbData = 8
  elsif args[:dwType] == REG_BINARY
    # fixme
    return false
  elsif args[:dwType] == REG_DWORD_BIG_ENDIAN
    # fixme
    return false
  else
    # fixme
    return false
  end
  args[:lpValueName] ||= 0
  return Advapi32.RegSetValueEx(args[:hKey].to_i, args[:lpValueName], 0, args[:dwType], lpData, cbData)
end

.ShellExecute(args) ⇒ Integer

Executes a shell command.

Examples:

Win32.ShellExecute(hwnd: some_handle, lpFile: 'notepad.exe')

Parameters:

  • args (Hash)

    the arguments for executing the shell command

Options Hash (args):

  • :hwnd (Integer)

    the handle to the owner window

  • :lpOperation (String)

    the operation to perform (default: 0)

  • :lpFile (String)

    the file to execute

  • :lpParameters (String)

    the parameters to pass to the executable (default: 0)

  • :lpDirectory (String)

    the working directory (default: 0)

  • :nShowCmd (Integer)

    the display option for the window (default: 1)

Returns:

  • (Integer)

    the result of the shell execution



557
558
559
560
561
562
563
# File 'lib/init.rb', line 557

def Win32.ShellExecute(args)
  args[:lpOperation] ||= 0
  args[:lpParameters] ||= 0
  args[:lpDirectory] ||= 0
  args[:nShowCmd] ||= 1
  return Shell32.ShellExecute(args[:hwnd].to_i, args[:lpOperation], args[:lpFile], args[:lpParameters], args[:lpDirectory], args[:nShowCmd])
end

.ShellExecuteEx(args) ⇒ Hash

Executes a shell command with extended options.

Examples:

Win32.ShellExecuteEx(lpVerb: 'open', lpFile: 'notepad.exe')

Parameters:

  • args (Hash)

    the arguments for executing the shell command

Options Hash (args):

  • :lpVerb (String)

    the operation to perform (e.g., “runas”)

  • :lpFile (String)

    the file to execute

  • :lpParameters (String)

    the parameters to pass to the executable

  • :lpDirectory (String)

    the working directory

  • :nShow (Integer)

    the display option for the window

Returns:

  • (Hash)

    a hash containing the result and process information



524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
# File 'lib/init.rb', line 524

def Win32.ShellExecuteEx(args)
  #         struct = [ (SIZEOF_LONG * 15), 0, 0, 0, 0, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 ]
  struct = [(SIZEOF_LONG * 15), 0, 0, 0, 0, 0, 0, SW_SHOW, 0, 0, 0, 0, 0, 0, 0]
  struct_index = { :cbSize => 0, :fMask => 1, :hwnd => 2, :lpVerb => 3, :lpFile => 4, :lpParameters => 5, :lpDirectory => 6, :nShow => 7, :hInstApp => 8, :lpIDList => 9, :lpClass => 10, :hkeyClass => 11, :dwHotKey => 12, :hIcon => 13, :hMonitor => 13, :hProcess => 14 }
  for sym in [:lpVerb, :lpFile, :lpParameters, :lpDirectory, :lpIDList, :lpClass]
    if args[sym]
      args[sym] = "#{args[sym]}\0" unless args[sym][-1, 1] == "\0"
      struct[struct_index[sym]] = Fiddle::Pointer.to_ptr(args[sym]).to_i
    end
  end
  for sym in [:fMask, :hwnd, :nShow, :hkeyClass, :dwHotKey, :hIcon, :hMonitor, :hProcess]
    if args[sym]
      struct[struct_index[sym]] = args[sym]
    end
  end
  struct = struct.pack('LLLLLLLLLLLLLLL')
  r = Shell32.ShellExecuteEx(struct)
  struct = struct.unpack('LLLLLLLLLLLLLLL')
  return :return => r, :hProcess => struct[struct_index[:hProcess]], :hInstApp => struct[struct_index[:hInstApp]]
end