Subject:
Re: [ruby-ffi] Using Windows Unicode functions
From:
Wayne Meissner
Date:
1/24/10 6:12 PM
To:
ruby-ffi@googlegroups.com

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 <sutniuq@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
>