lib/idnx/windows.rb in idnx-0.0.1 vs lib/idnx/windows.rb in idnx-0.1.0

- old
+ new

@@ -43,59 +43,62 @@ # LPSTR lpMultiByteStr, # int cbMultiByte, # LPCCH lpDefaultChar, # LPBOOL lpUsedDefaultChar # ); - attach_function :IdnToAscii, [:uint, :pointer, :int, :pointer, :int], :int - attach_function :MultiByteToWideChar, [:uint, :uint, :string, :int, :pointer, :int], :int - attach_function :WideCharToMultiByte, [:uint, :uint, :pointer, :int, :pointer, :int, :pointer, :pointer], :int + attach_function :IdnToAscii, %i[uint pointer int pointer int], :int + attach_function :MultiByteToWideChar, %i[uint uint string int pointer int], :int + attach_function :WideCharToMultiByte, %i[uint uint pointer int pointer int pointer pointer], :int module_function def lookup(hostname) # turn to wchar wchar_len = MultiByteToWideChar(WIN32OLE::CP_UTF8, MB_ERR_INVALID_CHARS, hostname, -1, nil, 0) raise Error, "Failed to convert \"#{hostname}\" to wchar" if wchar_len.zero? + wchar_ptr = FFI::MemoryPointer.new(:wchar_t, wchar_len) wchar_len = MultiByteToWideChar(WIN32OLE::CP_UTF8, 0, hostname, -1, wchar_ptr, wchar_len) raise Error, "Failed to convert \"#{hostname}\" to wchar" if wchar_len.zero? # translate to punycode punycode = FFI::MemoryPointer.new(:wchar_t, IDN_MAX_LENGTH) punycode_len = IdnToAscii(0, wchar_ptr, -1, punycode, IDN_MAX_LENGTH) wchar_ptr.free - if punycode_len == 0 + if punycode_len.zero? last_error = FFI::LastError.error # operation completed successfully, hostname is not an IDN # return hostname if last_error == 0 message = case last_error - when ERROR_INSUFFICIENT_BUFFER - "The supplied buffer size was not large enough, or it was incorrectly set to NULL" - when ERROR_INVALID_FLAGS - "The values supplied for flags were not valid" - when ERROR_INVALID_NAME - "An invalid name was supplied to the function" - when ERROR_INVALID_PARAMETER - "Any of the parameter values was invalid" - when ERROR_NO_UNICODE_TRANSLATION - "An invalid Unicode was found in a string" - else - "Failed to convert \"#{hostname}\"; (error: #{last_error})" \ - "\n\nhttps://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes-1" - end + when ERROR_INSUFFICIENT_BUFFER + "The supplied buffer size was not large enough, or it was incorrectly set to NULL" + when ERROR_INVALID_FLAGS + "The values supplied for flags were not valid" + when ERROR_INVALID_NAME + "An invalid name was supplied to the function" + when ERROR_INVALID_PARAMETER + "Any of the parameter values was invalid" + when ERROR_NO_UNICODE_TRANSLATION + "An invalid Unicode was found in a string" + else + "Failed to convert \"#{hostname}\"; (error: #{last_error})" \ + "\n\nhttps://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes-1" + end punycode.free raise Error, message end # turn to unicode unicode_len = WideCharToMultiByte(WIN32OLE::CP_UTF8, 0, punycode, -1, nil, 0, nil, nil) raise Error, "Failed to convert \"#{hostname}\" to utf8" if unicode_len.zero? + utf8_ptr = FFI::MemoryPointer.new(:char, unicode_len) unicode_len = WideCharToMultiByte(WIN32OLE::CP_UTF8, 0, punycode, -1, utf8_ptr, unicode_len, nil, nil) raise Error, "Failed to convert \"#{hostname}\" to utf8" if unicode_len.zero? + unicode = utf8_ptr.read_string(utf8_ptr.size) unicode.strip! # remove null-byte end end end