ruby / fiddle

A libffi wrapper for Ruby.
BSD 2-Clause "Simplified" License
154 stars 37 forks source link

NetWkstaGetInfo() always fails with INVALID PARAMETER #99

Closed fujimotos closed 2 years ago

fujimotos commented 2 years ago

Environment

How to reproduce

Run the following script on Windows:

require "fiddle/import"
require "fiddle/types"
require "fiddle/import"

module M
  extend Fiddle::Importer
  dlload "netapi32.dll"
  include Fiddle::Win32Types
  extern "int NetWkstaGetInfo(void*, int, void*);"
  # NOTE! If we remove "#" from the following line, it works somehow.
  #extern "int NetWkstaUserGetInfo(void*, int, void*)"
end

buf = "\0" * Fiddle::SIZEOF_VOIDP
pbuf = Fiddle::Pointer[buf]
p M.NetWkstaGetInfo(nil, 102, pbuf)

Bug/Observe

Expected behavior

fujimotos commented 2 years ago

Here are the links for MSDN documentations:

kou commented 2 years ago

Could you confirm this with Ruby 3.0?

kou commented 2 years ago

Could you use DWORD or unsigned long not int for DWORD argument?

  extern "int NetWkstaGetInfo(void*, DWORD, void*);"
fujimotos commented 2 years ago

Could you confirm this with Ruby 3.0?

Yes. I can confirm it fails with error code 87 on Ruby 3.0.3.

% ruby -v
ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x64-mingw32]
% ruby issue99.rb
87

Could you use DWORD or unsigned long not int for DWORD argument?

The result is the same. It fails with invalid parameter error. I tested with:

require "fiddle/import"
require "fiddle/types"
require "fiddle/import"

module M
  extend Fiddle::Importer
  dlload "netapi32.dll"
  include Fiddle::Win32Types
  extern "int NetWkstaGetInfo(void*, DWORD, void*);"
end

buf = "\0" * Fiddle::SIZEOF_VOIDP
pbuf = Fiddle::Pointer[buf]
p M.NetWkstaGetInfo(nil, 102, pbuf)
kou commented 2 years ago

I think that this is not a Fiddle bug.

This is also caused with ffi gem:

require 'ffi'

module M
  extend FFI::Library
  ffi_lib 'netapi32.dll'
  attach_function :NetWkstaGetInfo, [ :string, :ulong, :pointer ], :ulong
  #attach_function :NetWkstaUserGetInfo, [ :string, :ulong, :pointer ], :ulong
end

FFI::MemoryPointer.new(:pointer, 1) do |pbuf|
  p M.NetWkstaGetInfo(nil, 102, pbuf)
end

It seems that netapi32.dll isn't fully initialized until multiple symbols are GetProcAddress()-ed. But I don't know the details because I can't see netapi32.dll's implementation. It's not free software.