Subject:
[ruby-ffi] Re: Using Windows Unicode functions
From:
Quintus
Date:
1/26/10 10:36 AM
To:
ruby-ffi

That works! Thank you! So, here's the working code:
------------------------------------
#Encoding: UTF-8
require "ffi"

module Test
  extend FFI::Library

  ffi_lib "user32"
  ffi_convention :stdcall

  attach_function :message_box, :MessageBoxW,
[:long, :buffer_in, :buffer_in, :int], :int
end

string = "Test with umlaut: ä\0".encode("UTF-16LE") #MS expects double
NUL at a unicode string's end
Test.message_box(0, string, string, 0)
----------------------------------------
Tested with ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-
mingw32].

Marvin

On 25 Jan., 01:12, Wayne Meissner <wmeiss...@gmail.com> wrote:
> You could try using :buffer_in instead of :string for the parameter
> types in MessageBoxW.
>
> :string in ruby-ffi means 'nul terminated C string', wheras UTF-16 is
> really more of a binary blob of data.  Ruby-ffi checks for nul chars
> in :string parameters (via StringValueCStr()) to avoid nul-byte
> poisoning attacks (assuming someone reads a string from an untrusted
> source), like most other C extensions do.
>
> 2010/1/19 Quintus <sutn...@gmx.net>:
>
>
>
> > Hi there,
>
> > I'm trying to access Windows functions through the ffi gem, but I
> > wasn't that successfull (otherwise I wouldn't post here, I
> > think  ;-)  ). So far, I've been using the win32-api gem which worked
> > quite well with the Windows Unicode functions (they require UTF-16LE
> > encoded strings, also known as the wchar_t C type I think), but I
> > wasn't able to construct that with ffi.
>
> > Here's my code so far:
> > -------------------------------------
> > #Encoding: UTF-8
> > require "ffi"
>
> > module Test
> >  extend FFI::Library
>
> >  ffi_lib "user32"
> >  ffi_convention :stdcall
>
> >  attach_function :message_box, :MessageBoxW,
> > [:long, :string, :string, :int], :int
> > end
>
> > module Test2
> >  extend FFI::Library
>
> >  CP_UTF8 = 65001
> >  MB_PRECOMPOSED = 0x00000001
>
> >  ffi_lib "kernel32"
> >  ffi_convention :stdcall
>
> >  attach_function :get_last_error, :GetLastError, [], :long
> >  attach_function :multi_byte_to_wide_char, :MultiByteToWideChar,
> > [:uint, :int, :string, :int, :buffer_out, :int], :int
> > end
>
> > buffer = "\0" * 100_000
>
> > #I know, I could use Rubys built-in encoding functions
> > #and I WILL do so, but for now this is to ensure
> > #everything is 100% correct as MS it expects.
> > ret = Test2.multi_byte_to_wide_char(Test2::CP_UTF8, 0, "Test",
> > "Test".length, buffer, buffer.length)
>
> > buffer.force_encoding("UTF-16LE")
> > puts buffer.encode("ISO-8859-1").rstrip #Everything displayed correct
>
> > #The following line causes the error:
> > Test.message_box(0, buffer, buffer, 0)
> > -------------------------------------
>
> > This is the error message:
> > -------------------------------------
> > t2.rb:32:in `message_box': string contains null byte (ArgumentError)
> >  from t2.rb:32:in `<main>'
> > -------------------------------------
> > An UTF-16LE encoded string *contains* NUL bytes, I know--but I want to
> > use Unicode functions, so: How to do that?
>
> > My ruby version: ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-
> > mingw32]
> > My OS: Windows Vista Home Premium SP2 (32 bit)
>
> > Marvin