module NPGRT::Win32API

Constants

CP_ACP
CP_ANSI
CP_GBK
CP_UTF8
CloseFile
CloseSocket
Connect
CreatePipe
INI_VALUE_MAX
OS64
OpenSocket
PTRLEN
ReadFile
Recv
STARTUPINFOTYPE
Send
TYPE_VOIDP
W
Win32File
WriteFile

Public Instance Methods

addressof(dll, func) click to toggle source
# File lib/npgrt/win32api.rb, line 49
def addressof(dll, func)
        dl = api('kernel32', 'GetModuleHandle').call(dll) 
        dl = (dl == 0) ? dl : api('kernel32', 'LoadLibrary').call(dll)       
        api('kernel32', 'GetProcAddress').call dl, func
end
api(dll, func, params = nil, ret = "L") click to toggle source
# File lib/npgrt/win32api.rb, line 42
def api(dll, func, params = nil, ret = "L")
    API.new dll, func, params, ret
end
checked_api(dll, func, params = nil, ret = "L", info = "Error!", exclass = RuntimeError) click to toggle source
# File lib/npgrt/win32api.rb, line 46
def checked_api(dll, func, params = nil, ret = "L", info = "Error!", exclass = RuntimeError)
        lambda{|*a| raise exclass, info if 0 != API.new(dll, func, params, ret).call(*a)}
end
grant_all(addr, size) click to toggle source
# File lib/npgrt/win32api.rb, line 65
def grant_all(addr, size)
        api('Kernel32', 'VirtualProtect').call addr, size, 0x40, "RGBARGBARGBARGBA"
        addr
end
hfileread(handle, len) click to toggle source
# File lib/npgrt/win32api.rb, line 240
def hfileread(handle, len)
        buf = "\0"*len
        llen = [0].pack(TYPE_VOIDP)
      ret = ReadFile.call(handle, buf, len, llen, 0)
        outlen = llen.unpack(TYPE_VOIDP).first
        ret != 0 ? buf[0, outlen] : nil
end
hfilereada(handle, len) click to toggle source
# File lib/npgrt/win32api.rb, line 255
def hfilereada(handle, len)
        ret = hfileread(handle, len)
        !ret ? ret : to_codepage(to_unicode(ret+"\0\0", CP_ACP)+"\0\0")
end
hfilereadw(handle, len) click to toggle source
# File lib/npgrt/win32api.rb, line 260
def hfilereadw(handle, len)
        ret = hfileread(handle, len)
        !ret ? ret : to_codepage(ret+"\0\0")
end
hfilewrite(handle, buf, len = buf.to_str.length) click to toggle source
# File lib/npgrt/win32api.rb, line 248
def hfilewrite(handle, buf, len = buf.to_str.length)
        llen = [0].pack(TYPE_VOIDP)
        ret = WriteFile.call(handle, buf.to_str, len, llen, 0)
        outlen = llen.unpack(TYPE_VOIDP).first
        ret != 0 ? outlen : nil
end
iniread(app, key, ini = "Game.ini") click to toggle source
# File lib/npgrt/win32api.rb, line 114
def iniread(app, key, ini = "Game.ini")
        buf = "\0\0"*INI_VALUE_MAX
        ini = normalize_pathsep_os ini
        app, key, ini = [app, key, ini].map{|x| to_unicode(x + "\0\0")+"\0\0"}
        len = api('kernel32', 'GetPrivateProfileStringW').call(app, key, "", buf, INI_VALUE_MAX, ini)
        to_codepage buf
end
iniwrite(app, key, value, ini = "Game.ini") click to toggle source
# File lib/npgrt/win32api.rb, line 122
def iniwrite(app, key, value, ini = "Game.ini")
        ini = normalize_pathsep_os ini
        app, key, value, ini = [app, key, value, ini].map{|x| to_unicode(x + "\0\0")+"\0\0"} 
        api('kernel32', 'WritePrivateProfileStringW').call(
                app, key, value, ini
        )
end
memread(addr, size) click to toggle source
# File lib/npgrt/win32api.rb, line 59
def memread(addr, size)
        buf = "\0"*size
        api('Kernel32','RtlMoveMemory').call buf, addr, size
        buf
end
memread!(addr, size) click to toggle source
# File lib/npgrt/win32api.rb, line 70
def memread!(addr, size)
        memread(grant_all(addr, size), size)
end
memwrite(addr, buf, len = buf.length) click to toggle source
# File lib/npgrt/win32api.rb, line 55
def memwrite(addr, buf, len = buf.length)
        api('Kernel32', 'RtlMoveMemory').call addr, buf, len
end
memwrite!(addr, buf, len = buf.length) click to toggle source
# File lib/npgrt/win32api.rb, line 74
def memwrite!(addr, buf, len = buf.length)
        memwrite(grant_all(addr, len), buf, len)
end
open3(path, dir = nil, env = nil) { |stdin, stdout, stderr, proc_info| ... } click to toggle source
# File lib/npgrt/win32api.rb, line 281
def open3(path, dir = nil, env = nil)
        si = "\0"*STARTUPINFOTYPE[:sizeof]
        api('Kernel32', 'GetStartupInfoW').call si
        si[STARTUPINFOTYPE[:show], 2] = [0].pack("S")
        stdin, stdout, stderr = winpipe, winpipe, winpipe
        si[STARTUPINFOTYPE[:handles][0], PTRLEN] = [stdin[:in]].pack(TYPE_VOIDP)
        si[STARTUPINFOTYPE[:handles][1], PTRLEN] = [stdout[:out]].pack(TYPE_VOIDP)
        si[STARTUPINFOTYPE[:handles][2], PTRLEN] = [stderr[:out]].pack(TYPE_VOIDP)
        pi = "\0"*PTRLEN*4
        path =       to_unicode(path + "\0\0")+"\0\0"
        dir =        dir == nil ? nil : to_unicode(dir + "\0\0")+"\0\0"
        env = env == nil ? nil : to_unicode(env + "\0\0")+"\0\0"
        api('Kernel32', 'CreateProcessW').call(
                0,
                path,
                0,
                0,
                1,
                0,
                0,
                dir,
                si,
                pi,
        )
        CloseFile.call(stdin[:in])
        CloseFile.call(stdout[:out])
        CloseFile.call(stderr[:out])
        u = pi.unpack(TYPE_VOIDP*4)
        proc_info = Hash[ [:process, :thread, :pid, :tid].zip(u) ]
        CloseFile.call(proc_info[:process])
        CloseFile.call(proc_info[:thread])
        ret = yield stdin[:out], stdout[:in], stderr[:in], proc_info
        api('Kernel32', 'TerminateProcess').call proc_info[:process], ret
end
popen(path, dir = nil, env = nil) { |a,b| ... } click to toggle source
# File lib/npgrt/win32api.rb, line 316
def popen(path, dir = nil, env = nil)
        open3 path, dir, env do |a, b, c, d|
                yield a,b
        end
end
regclosekey(key) click to toggle source
# File lib/npgrt/win32api.rb, line 179
def regclosekey(key)
        api('advapi32', 'RegCloseKey').call key
end
regopenkey(path, valuename) click to toggle source
# File lib/npgrt/win32api.rb, line 158
def regopenkey(path, valuename)
        path =~ /([^\\]*)\\(.*)/
        whole, main, child = *$~
        main = REG.const_get(main)
        key = [0].pack(NPGRT::PtrType)
        child = to_unicode(child + "\0\0")+"\0\0"
        valuename = case valuename
                when 0, nil
                        0
                else
                        to_unicode(valuename+"\0\0")+"\0\0"
                end
        checked_api(
                'advapi32', 'RegOpenKeyW', nil, 'L', "Open Key #{path} Error!"
        ).call(
                     main, child, key
        )
        key = key.unpack(NPGRT::PtrType).first
        [key, valuename]
end
regread(path, valuename = 0, type = :REG_SZ) click to toggle source
# File lib/npgrt/win32api.rb, line 182
def regread(path, valuename = 0, type = :REG_SZ)      
        type = REG.const_get(type) if Symbol === type        
        key, valuename = regopenkey(path, valuename)
        len = REG::BYTEINC
        plen = [len].pack(NPGRT::PtrType)
        buf = "\0\0"*len
        ptype = [type].pack(NPGRT::PtrType)
        ret = api('advapi32', 'RegQueryValueExW').call(key, valuename, 0, ptype, buf, plen)
        while ret == REG::EMOREDATA
                len += REG::BYTEINC
                plen =  [len].pack(NPGRT::PtrType)
                buf = "\0\0"*len
                ret = api('advapi32', 'RegQueryValueExW').call(key, valuename, 0, ptype, buf, plen)
        
        end
        if ret == REG::ESUCCESS
                return buf[0, plen.unpack(NPGRT::PtrType).first*2]
        else
                raise "Query Key #{path} failed"
        end
ensure
        regclosekey key
end
regstrread(type, valuename = "") click to toggle source
# File lib/npgrt/win32api.rb, line 206
def regstrread(type, valuename = "")
        val = regread(type, valuename)
        to_codepage val + "\0\0"
end
regstrwrite(path, valuename = nil, value = "") click to toggle source
# File lib/npgrt/win32api.rb, line 227
def regstrwrite(path, valuename = nil, value = "")
        regwrite(path, valuename, to_unicode(value+"\0\0")+"\0\0", :REG_SZ)
end
regwrite(path, valuename = nil, value = "", type = :REG_SZ) click to toggle source
# File lib/npgrt/win32api.rb, line 211
def regwrite(path, valuename = nil, value = "", type = :REG_SZ)
        key, valuename = regopenkey(path, valuename)
        type = REG.const_get(type) if Symbol === type        
        raise "RegWrite #{path} Error!" if 0 != api('advapi32', 'RegSetValueExW').call(
                key,
                valuename,
                0,
                type,
                value,
                value.length
        )
        return true
ensure
        regclosekey key
end
simplehttpread(addr, hostname = addr[/http:\/\/([^\/]*)/, 1], resource = addr[/http:\/\/([^\/]*)(.*)$/, 2]) { |responseheader, nil| ... } click to toggle source
# File lib/npgrt/win32api.rb, line 369
def simplehttpread(addr, hostname = addr[/http:\/\/([^\/]*)/, 1], 
                   resource = addr[/http:\/\/([^\/]*)(.*)$/, 2])
        request = "GET #{resource} HTTP/1.1\r\n"\
                  "host:#{hostname}\r\n"\
                  "\r\n\r\n\r\n\r\n"
        t = tcpnew
        if hostname[0][/[0-9]/]
                u = addr = api('ws2_32', 'inet_addr').call(
                        to_codepage(to_unicode(hostname+"\0\0")+"\0", CP_ANSI)+"\0"
                )
        else
                hostent = api('ws2_32', 'gethostbyname').call(
                        to_codepage(to_unicode(hostname+"\0\0")+"\0", CP_ANSI)+"\0"
                )

                addr = memread(hostent+PTRLEN*3, PTRLEN)
                addr = addr.unpack(TYPE_VOIDP).first
                addr = memread(addr, PTRLEN)
                addr = addr.unpack(TYPE_VOIDP).first
                addr = memread(addr, PTRLEN)
                u = addr.unpack("L").first
        end          
        uaddr =  [2, 0, 0, 80, u].pack("CCCCLx8")
        
        raise "Can't connect to Server " if -1 == Connect.call(t, uaddr, 16)
        socketwrite t, request
        responseheader = ""
        while v = socketread(t, 20480)       
                responseheader << v
                if pos = responseheader.index("\r\n\r\n")
                        responsebody   = responseheader[pos+4..-1]
                        responseheader = responseheader[0...pos]
                        break
                end
                yield responseheader, nil if block_given?
        end

        if !(length = responseheader[/Content-length:\s*(\d+)/i, 1])
                length = 1e100
        else
                length = length.to_i
        end
        
        while responsebody.length < length && (v = socketread(t, 20480)) 
                responsebody << v
                yield responseheader, responsebody if block_given?
        end
        tcpclose t
        true
end
sockaddr(host, port) click to toggle source
# File lib/npgrt/win32api.rb, line 341
def sockaddr(host, port)
        [2, port, *host].pack("snCCCCx8")
end
socketread(h, size) click to toggle source
# File lib/npgrt/win32api.rb, line 357
def socketread(h, size)
        buf = "\0" * size
        ret = Recv.call h, buf, size, 0
        case ret
        when -1, 0
                nil
        else
                buf[0, ret]
        end
end
socketwrite(h, buf) click to toggle source
# File lib/npgrt/win32api.rb, line 353
def socketwrite(h, buf)
        Send.call h, buf, buf.length, 0
end
strread(addr) click to toggle source
# File lib/npgrt/win32api.rb, line 103
def strread(addr)
        len = api('Kernel32', 'lstrlenA').call(addr)
        to_codepage(to_unicode(memread(addr, len+1), CP_ANSI), CP_UTF8)
end
tcpclose(u) click to toggle source
# File lib/npgrt/win32api.rb, line 349
def tcpclose(u)
        CloseSocket.call u
end
tcpnew(addr = nil) click to toggle source
# File lib/npgrt/win32api.rb, line 334
def tcpnew(addr = nil)
        addr = sockaddr(*addr) if Array === addr
        so = OpenSocket.call 2, 1, 6
        Connect.call so, addr, addr.size if addr
        so
end
to_codepage(string, codepage = CP_UTF8) click to toggle source
# File lib/npgrt/win32api.rb, line 90
def to_codepage(string, codepage = CP_UTF8)
        len = api('Kernel32', 'WideCharToMultiByte').call codepage[:cp], 0, string, -1, 0, 0, 0, 0
        buf = "\0"*len
        api('Kernel32',  'WideCharToMultiByte').call codepage[:cp], 0, string, -1, buf, len, 0, 0
        if buf.respond_to?(:force_encoding)
                buf.force_encoding(defined?($RGSS_SCRIPTS) ?
                                 'utf-8' :          
                                 codepage[:encoding])
        else
                buf
        end[0..-1].sub(/\0+$/){}
end
to_unicode(string, codepage = CP_UTF8) click to toggle source
# File lib/npgrt/win32api.rb, line 83
def to_unicode(string, codepage = CP_UTF8)
        len = api('Kernel32', 'MultiByteToWideChar').call codepage[:cp], 0, string, -1, 0, 0
        buf = "\0\0"*len
        api('Kernel32', 'MultiByteToWideChar').call codepage[:cp], 0, string, -1, buf, len
        buf[0..-3]
end
udpclose(u) click to toggle source
# File lib/npgrt/win32api.rb, line 345
def udpclose(u)
        CloseSocket.call u
end
udpnew(addr = nil) click to toggle source
# File lib/npgrt/win32api.rb, line 327
def udpnew(addr = nil)
        addr = sockaddr(*addr) if Array === addr
        so = OpenSocket.call 2, 2, 0
        Connect.call so, addr, addr.size if addr
        so
end
winpipe() click to toggle source
# File lib/npgrt/win32api.rb, line 273
def winpipe
        buf = "\0"*(PTRLEN*2)
        sa = [8+PTRLEN, nil, 1].pack(TYPE_VOIDP + "p" + TYPE_VOIDP)
        addr = [buf].pack("p").unpack(TYPE_VOIDP).first
        CreatePipe.call addr, addr+PTRLEN, sa, 1
        ret = buf.unpack(TYPE_VOIDP*2)
        {:in => ret[0], :out => ret[1]}
end
wstrread(addr) click to toggle source
# File lib/npgrt/win32api.rb, line 108
def wstrread(addr)
        len = api('Kernel32', 'lstrlenW').call(addr)
        to_codepage(memread(addr, len*2+2))
end