module OCI8::Util

def self.check_load_error(exc)

def self.check_load_error(exc)
  check_os_specific_load_error(exc)
  case exc.message
  when /^OCI Library Initialization Error/
    # TODO
  end
end

def self.check_os_specific_load_error(exc)

def self.check_os_specific_load_error(exc)
  case exc.message
  when /^OCI\.DLL: 193\(/, /^193: / # "OCI.DLL: 193(%1 is not a valid Win32 application.)" in English
    check_win32_pe_arch(exc.message.split(' - ')[1], "ruby-oci8")
    dll_load_path_list.each do |path|
      check_win32_pe_arch(File.join(path, '\OCI.DLL'), "Oracle client")
    end
  when /^OCI.DLL: 126\(/, /^126: / # "OCI.DLL: 126(The specified module could not be found.)" in English
    oci_dll_files = dll_load_path_list.inject([]) do |files, path|
      file = File.join(path, '\OCI.DLL')
      files << file if File.exist?(file)
      files
    end
    if oci_dll_files.empty?
      raise LoadError, "Cannot find OCI.DLL in PATH."
    end
    if oci_dll_files.none? {|file| open(file, 'rb') {true} rescue false}
      raise LoadError, "OCI.DLL in PATH isn't readable."
    end
    first_error = nil
    oci_dll_files.each do |file|
      begin
        check_win32_pe_arch(file, "Oracle client")
        valid_arch = true
      rescue LoadError
        first_error ||= $!
        valid_arch = false
      end
      if valid_arch
        handle = LoadLibraryExA(file, nil, DONT_RESOLVE_DLL_REFERENCES)
        unless handle.null?
          FreeLibrary(handle)
          raise LoadError, <<EOS
 find DLLs depended by #{file}.
tp://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/install-instant-client.md#Windows
        end
        break
      end
    end
    raise first_error if first_error
  end
end # self.check_os_specific_load_error

def self.check_os_specific_load_error(exc)

def self.check_os_specific_load_error(exc)
  case exc.message
  when /^libaio\.so\.1:/ # "libaio.so.1: cannot open shared object file: No such file or directory" in English
    install_cmd = if File.executable? '/usr/bin/apt-get'
                    'apt-get install libaio1'
                  elsif File.executable? '/usr/bin/yum'
                    'yum install libaio'
                  end
    if install_cmd
      raise LoadError, "You need to install libaio.so.1. Run '#{install_cmd}'."
    else
      raise LoadError, "You need to install libaio.so.1."
    end
  end
end # self.check_os_specific_load_error

def self.check_os_specific_load_error(exc)

def self.check_os_specific_load_error(exc)
end

def self.check_win32_pe_arch(filename, package)

def self.check_win32_pe_arch(filename, package)
  open(filename, 'rb') do |f|
    # DOS header.
    if f.read(2) == 'MZ'
      f.seek(60, IO::SEEK_SET)
      pe_offset = f.read(4).unpack('V')[0]
      f.seek(pe_offset)
      # PE header.
      if f.read(4) == "PE\000\000"
        case f.read(2).unpack('v')[0]
        when 0x8664
          if [nil].pack('P').size == 4
            raise LoadError, "\"#{filename}\" is x64 DLL. Use 32-bit #{package} instead."
          end
          return true
        when 0x014c
          if [nil].pack('P').size == 8
            raise LoadError, "\"#{filename}\" is 32-bit DLL. Use x64 #{package} instead."
          end
          return true
        end
      end
    end
    raise LoadError, "\"#{filename}\" is not a valid Win32 application."
  end
  nil
rescue
  nil
end # self.check_win32_pe_arch

def self.dll_load_path_list

def self.dll_load_path_list
  buf = "\0" * MAX_PATH
  paths = []
  paths << buf[0, GetModuleFileNameA(nil, buf, MAX_PATH)].force_encoding("locale").gsub(/\\[^\\]*$/, '')
  paths << buf[0, GetSystemDirectoryA(buf, MAX_PATH)].force_encoding("locale")
  paths << buf[0, GetWindowsDirectoryA(buf, MAX_PATH)].force_encoding("locale")
  paths << "."
  paths + (ENV['PATH'].split(';').reject {|path| path.empty?})
end # self.dll_load_path_list