about summary refs log tree commit diff stats
path: root/miasm/os_dep/win_api_x86_32.py
diff options
context:
space:
mode:
Diffstat (limited to 'miasm/os_dep/win_api_x86_32.py')
-rw-r--r--miasm/os_dep/win_api_x86_32.py3595
1 files changed, 0 insertions, 3595 deletions
diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py
deleted file mode 100644
index 6e568abb..00000000
--- a/miasm/os_dep/win_api_x86_32.py
+++ /dev/null
@@ -1,3595 +0,0 @@
-from __future__ import print_function
-#
-# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-from past.builtins import cmp
-import struct
-import os
-import stat
-import time
-import string
-import logging
-from zlib import crc32
-from io import StringIO
-import time
-import datetime
-
-from future.utils import PY3, viewitems, viewvalues
-
-try:
-    from Crypto.Hash import MD5, SHA
-except ImportError:
-    print("cannot find crypto, skipping")
-
-from miasm.jitter.csts import PAGE_READ, PAGE_WRITE, PAGE_EXEC
-from miasm.core.utils import pck16, pck32, hexdump, whoami, int_to_byte
-from miasm.os_dep.common import heap, windows_to_sbpath
-from miasm.os_dep.common import set_win_str_w, set_win_str_a
-from miasm.os_dep.common import get_fmt_args as _get_fmt_args
-from miasm.os_dep.common import get_win_str_a, get_win_str_w
-from miasm.os_dep.common import encode_win_str_a, encode_win_str_w
-from miasm.os_dep.win_api_x86_32_seh import tib_address
-
-log = logging.getLogger("win_api_x86_32")
-console_handler = logging.StreamHandler()
-console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s"))
-log.addHandler(console_handler)
-log.setLevel(logging.WARN)
-
-DATE_1601_TO_1970 = 116444736000000000
-
-MAX_PATH = 260
-
-
-"""
-typedef struct tagPROCESSENTRY32 {
-  DWORD     dwSize;
-  DWORD     cntUsage;
-  DWORD     th32ProcessID;
-  ULONG_PTR th32DefaultHeapID;
-  DWORD     th32ModuleID;
-  DWORD     cntThreads;
-  DWORD     th32ParentProcessID;
-  LONG      pcPriClassBase;
-  DWORD     dwFlags;
-  TCHAR     szExeFile[MAX_PATH];
-} PROCESSENTRY32, *PPROCESSENTRY32;
-"""
-
-
-ACCESS_DICT = {0x0: 0,
-               0x1: 0,
-               0x2: PAGE_READ,
-               0x4: PAGE_READ | PAGE_WRITE,
-               0x10: PAGE_EXEC,
-               0x20: PAGE_EXEC | PAGE_READ,
-               0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
-               0x80: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
-               # 0x80: PAGE_EXECUTE_WRITECOPY
-               0x100: 0
-               }
-
-ACCESS_DICT_INV = dict((x[1], x[0]) for x in viewitems(ACCESS_DICT))
-
-
-class whandle(object):
-
-    def __init__(self, name, info):
-        self.name = name
-        self.info = info
-
-    def __repr__(self):
-        return '<%r %r %r>' % (self.__class__.__name__, self.name, self.info)
-
-
-class handle_generator(object):
-
-    def __init__(self):
-        self.offset = 600
-        self.all_handles = {}
-
-    def add(self, name, info=None):
-        self.offset += 1
-        h = whandle(name, info)
-        self.all_handles[self.offset] = h
-
-        log.debug(repr(self))
-        return self.offset
-
-    def __repr__(self):
-        out = '<%r\n' % self.__class__.__name__
-        ks = list(self.all_handles)
-        ks.sort()
-
-        for k in ks:
-            out += "    %r %r\n" % (k, self.all_handles[k])
-        out += '>'
-        return out
-
-    def __contains__(self, e):
-        return e in self.all_handles
-
-    def __getitem__(self, item):
-        return self.all_handles.__getitem__(item)
-
-    def __delitem__(self, item):
-        self.all_handles.__delitem__(item)
-
-
-class c_winobjs(object):
-
-    def __init__(self):
-        self.alloc_ad = 0x20000000
-        self.alloc_align = 0x1000
-        self.heap = heap()
-        self.handle_toolhelpsnapshot = 0xaaaa00
-        self.toolhelpsnapshot_info = {}
-        self.handle_curprocess = 0xaaaa01
-        self.dbg_present = 0
-        self.tickcount = 0
-        self.dw_pid_dummy1 = 0x111
-        self.dw_pid_explorer = 0x222
-        self.dw_pid_dummy2 = 0x333
-        self.dw_pid_cur = 0x444
-        self.module_fname_nux = None
-        self.module_name = "test.exe"
-        self.module_path = "c:\\mydir\\" + self.module_name
-        self.hcurmodule = None
-        self.module_filesize = None
-        self.getversion = 0x0A280105
-        self.getforegroundwindow = 0x333333
-        self.cryptcontext_hwnd = 0x44400
-        self.cryptcontext_bnum = 0x44000
-        self.cryptcontext_num = 0
-        self.cryptcontext = {}
-        self.phhash_crypt_md5 = 0x55555
-        # key used by EncodePointer and DecodePointer
-        # (kernel32)
-        self.ptr_encode_key = 0xabababab
-        self.files_hwnd = {}
-        self.windowlong_dw = 0x77700
-        self.module_cur_hwnd = 0x88800
-        self.module_file_nul = 0x999000
-        self.runtime_dll = None
-        self.current_pe = None
-        self.tls_index = 0xf
-        self.tls_values = {}
-        self.handle_pool = handle_generator()
-        self.handle_mapped = {}
-        self.hkey_handles = {
-            0x80000001: b"hkey_current_user",
-            0x80000002: b"hkey_local_machine"
-        }
-        self.cur_dir = "c:\\tmp"
-
-        self.nt_mdl = {}
-        self.nt_mdl_ad = None
-        self.nt_mdl_cur = 0
-        self.win_event_num = 0x13370
-        self.cryptdll_md5_h = {}
-
-        self.lastwin32error = 0
-        self.mutex = {}
-        self.env_variables = {}
-        self.events_pool = {}
-        self.find_data = None
-
-        self.allocated_pages = {}
-        self.current_datetime = datetime.datetime(
-            year=2017, month=8, day=21,
-            hour=13, minute=37,
-            second=11, microsecond=123456
-        )
-
-winobjs = c_winobjs()
-
-
-process_list = [
-    [
-        0x40,  # DWORD     dwSize;
-        0,  # DWORD     cntUsage;
-        winobjs.dw_pid_dummy1,  # DWORD     th32ProcessID;
-        0x11111111,  # ULONG_PTR th32DefaultHeapID;
-        0x11111112,  # DWORD     th32ModuleID;
-        1,  # DWORD     cntThreads;
-        winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
-        0xbeef,  # LONG      pcPriClassBase;
-        0x0,  # DWORD     dwFlags;
-        "dummy1.exe"  # TCHAR     szExeFile[MAX_PATH];
-    ],
-    [
-        0x40,  # DWORD     dwSize;
-        0,  # DWORD     cntUsage;
-        winobjs.dw_pid_explorer,  # DWORD     th32ProcessID;
-        0x11111111,  # ULONG_PTR th32DefaultHeapID;
-        0x11111112,  # DWORD     th32ModuleID;
-        1,  # DWORD     cntThreads;
-        4,  # DWORD     th32ParentProcessID;
-        0xbeef,  # LONG      pcPriClassBase;
-        0x0,  # DWORD     dwFlags;
-        "explorer.exe"  # TCHAR     szExeFile[MAX_PATH];
-    ],
-
-    [
-        0x40,  # DWORD     dwSize;
-        0,  # DWORD     cntUsage;
-        winobjs.dw_pid_dummy2,  # DWORD     th32ProcessID;
-        0x11111111,  # ULONG_PTR th32DefaultHeapID;
-        0x11111112,  # DWORD     th32ModuleID;
-        1,  # DWORD     cntThreads;
-        winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
-        0xbeef,  # LONG      pcPriClassBase;
-        0x0,  # DWORD     dwFlags;
-        "dummy2.exe"  # TCHAR     szExeFile[MAX_PATH];
-    ],
-
-    [
-        0x40,  # DWORD     dwSize;
-        0,  # DWORD     cntUsage;
-        winobjs.dw_pid_cur,  # DWORD     th32ProcessID;
-        0x11111111,  # ULONG_PTR th32DefaultHeapID;
-        0x11111112,  # DWORD     th32ModuleID;
-        1,  # DWORD     cntThreads;
-        winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
-        0xbeef,  # LONG      pcPriClassBase;
-        0x0,  # DWORD     dwFlags;
-        winobjs.module_name  # TCHAR     szExeFile[MAX_PATH];
-    ],
-
-
-]
-
-
-class hobj(object):
-    pass
-
-
-class mdl(object):
-
-    def __init__(self, ad, l):
-        self.ad = ad
-        self.l = l
-
-    def __bytes__(self):
-        return struct.pack('LL', self.ad, self.l)
-
-    def __str__(self):
-        if PY3:
-            return repr(self)
-        return self.__bytes__()
-
-
-def kernel32_HeapAlloc(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["heap", "flags", "size"])
-    alloc_addr = winobjs.heap.alloc(jitter, args.size, cmt=hex(ret_ad))
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
-
-
-def kernel32_HeapFree(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["heap", "flags", "pmem"])
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_GlobalAlloc(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["uflags", "msize"])
-    alloc_addr = winobjs.heap.alloc(jitter, args.msize)
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
-
-
-def kernel32_LocalFree(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["lpvoid"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_LocalAlloc(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["uflags", "msize"])
-    alloc_addr = winobjs.heap.alloc(jitter, args.msize)
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
-
-def msvcrt_new(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["size"])
-    alloc_addr = winobjs.heap.alloc(jitter, args.size)
-    jitter.func_ret_cdecl(ret_ad, alloc_addr)
-
-globals()['msvcrt_??2@YAPAXI@Z'] = msvcrt_new
-
-def msvcrt_delete(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["ptr"])
-    jitter.func_ret_cdecl(ret_ad, 0)
-
-globals()['msvcrt_??3@YAXPAX@Z'] = msvcrt_delete
-
-def kernel32_GlobalFree(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["addr"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_IsDebuggerPresent(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, winobjs.dbg_present)
-
-
-def kernel32_CreateToolhelp32Snapshot(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["dwflags", "th32processid"])
-    jitter.func_ret_stdcall(ret_ad, winobjs.handle_toolhelpsnapshot)
-
-
-def kernel32_GetCurrentProcess(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, winobjs.handle_curprocess)
-
-
-def kernel32_GetCurrentProcessId(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, winobjs.dw_pid_cur)
-
-
-def kernel32_Process32First(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["s_handle", "ad_pentry"])
-
-    pentry = struct.pack(
-        'IIIIIIIII', *process_list[0][:-1]
-    ) + (process_list[0][-1] + '\x00').encode('utf8')
-    jitter.vm.set_mem(args.ad_pentry, pentry)
-    winobjs.toolhelpsnapshot_info[args.s_handle] = 0
-
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_Process32Next(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["s_handle", "ad_pentry"])
-
-    winobjs.toolhelpsnapshot_info[args.s_handle] += 1
-    if winobjs.toolhelpsnapshot_info[args.s_handle] >= len(process_list):
-        ret = 0
-    else:
-        ret = 1
-        n = winobjs.toolhelpsnapshot_info[args.s_handle]
-        pentry = struct.pack(
-            'IIIIIIIII', *process_list[n][:-1]) + (process_list[n][-1]+ '\x00').encode('utf8')
-        jitter.vm.set_mem(args.ad_pentry, pentry)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_GetTickCount(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    winobjs.tickcount += 1
-    jitter.func_ret_stdcall(ret_ad, winobjs.tickcount)
-
-
-def kernel32_GetVersion(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, winobjs.getversion)
-
-
-def kernel32_GetVersionEx(jitter, str_size, encode_str):
-    ret_ad, args = jitter.func_args_stdcall(["ptr_struct"])
-
-    size = jitter.vm.get_u32(args.ptr_struct)
-    if size in [0x14+str_size, 0x1c+str_size]:
-        tmp = struct.pack(
-            "IIIII%dsHHHBB" % str_size,
-            0x114,            # struct size
-            0x5,              # maj vers
-            0x2,              # min vers
-            0xa28,            # build nbr
-            0x2,              # platform id
-            encode_str("Service pack 4"),
-            3,                # wServicePackMajor
-            0,                # wServicePackMinor
-            0x100,            # wSuiteMask
-            1,                # wProductType
-            0                 # wReserved
-        )
-        tmp = tmp[:size]
-        jitter.vm.set_mem(args.ptr_struct, tmp)
-        ret = 1
-    else:
-        ret = 0
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-kernel32_GetVersionExA = lambda jitter: kernel32_GetVersionEx(jitter, 128,
-                                                              encode_win_str_a)
-kernel32_GetVersionExW = lambda jitter: kernel32_GetVersionEx(jitter, 256,
-                                                              encode_win_str_w)
-
-
-def kernel32_GetPriorityClass(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hwnd"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_SetPriorityClass(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hwnd", "dwpclass"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_CloseHandle(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hwnd"])
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-def kernel32_EncodePointer(jitter):
-    """
-        PVOID EncodePointer(
-            _In_ PVOID Ptr
-        );
-
-        Encoding globally available pointers helps protect them from being
-        exploited. The EncodePointer function obfuscates the pointer value
-        with a secret so that it cannot be predicted by an external agent.
-        The secret used by EncodePointer is different for each process.
-
-        A pointer must be decoded before it can be used.
-
-    """
-    ret, args = jitter.func_args_stdcall(1)
-    jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key)
-    return True
-
-def kernel32_DecodePointer(jitter):
-    """
-        PVOID DecodePointer(
-           PVOID Ptr
-        );
-
-        The function returns the decoded pointer.
-
-    """
-    ret, args = jitter.func_args_stdcall(1)
-    jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key)
-    return True
-
-def user32_GetForegroundWindow(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, winobjs.getforegroundwindow)
-
-
-def user32_FindWindowA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["pclassname", "pwindowname"])
-    if args.pclassname:
-        classname = get_win_str_a(jitter, args.pclassname)
-        log.info("FindWindowA classname %s", classname)
-    if args.pwindowname:
-        windowname = get_win_str_a(jitter, args.pwindowname)
-        log.info("FindWindowA windowname %s", windowname)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def user32_GetTopWindow(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hwnd"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def user32_BlockInput(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["blockit"])
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def advapi32_CryptAcquireContext(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["phprov", "pszcontainer",
-                                             "pszprovider", "dwprovtype",
-                                             "dwflags"])
-    prov = get_str(args.pszprovider) if args.pszprovider else "NONE"
-    log.debug('prov: %r', prov)
-    jitter.vm.set_u32(args.phprov, winobjs.cryptcontext_hwnd)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def advapi32_CryptAcquireContextA(jitter):
-    advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def advapi32_CryptAcquireContextW(jitter):
-    advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def advapi32_CryptCreateHash(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hprov", "algid", "hkey",
-                                             "dwflags", "phhash"])
-
-    winobjs.cryptcontext_num += 1
-
-    if args.algid == 0x00008003:
-        log.debug('algo is MD5')
-        jitter.vm.set_u32(
-            args.phhash,
-            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num
-        )
-        winobjs.cryptcontext[
-            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj()
-        winobjs.cryptcontext[
-            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = MD5.new()
-    elif args.algid == 0x00008004:
-        log.debug('algo is SHA1')
-        jitter.vm.set_u32(
-            args.phhash,
-            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num
-        )
-        winobjs.cryptcontext[
-            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj()
-        winobjs.cryptcontext[
-            winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = SHA.new()
-    else:
-        raise ValueError('un impl algo1')
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def advapi32_CryptHashData(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hhash", "pbdata", "dwdatalen",
-                                             "dwflags"])
-
-    if not args.hhash in winobjs.cryptcontext:
-        raise ValueError("unknown crypt context")
-
-    data = jitter.vm.get_mem(args.pbdata, args.dwdatalen)
-    log.debug('will hash %X', args.dwdatalen)
-    log.debug(repr(data[:0x10]) + "...")
-    winobjs.cryptcontext[args.hhash].h.update(data)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def advapi32_CryptGetHashParam(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hhash", "param", "pbdata",
-                                             "dwdatalen", "dwflags"])
-
-    if not args.hhash in winobjs.cryptcontext:
-        raise ValueError("unknown crypt context")
-
-    if args.param == 2:
-        # HP_HASHVAL
-        # XXX todo: save h state?
-        h = winobjs.cryptcontext[args.hhash].h.digest()
-        jitter.vm.set_mem(args.pbdata, h)
-        jitter.vm.set_u32(args.dwdatalen, len(h))
-    elif args.param == 4:
-        # HP_HASHSIZE
-        ret = winobjs.cryptcontext[args.hhash].h.digest_size
-        jitter.vm.set_u32(args.pbdata, ret)
-        jitter.vm.set_u32(args.dwdatalen, 4)
-    else:
-        raise ValueError('not impl', args.param)
-
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def advapi32_CryptReleaseContext(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hhash", "flags"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def advapi32_CryptDeriveKey(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hprov", "algid", "hbasedata",
-                                             "dwflags", "phkey"])
-
-    if args.algid == 0x6801:
-        log.debug('using DES')
-    else:
-        raise ValueError('un impl algo2')
-    h = winobjs.cryptcontext[args.hbasedata].h.digest()
-    log.debug('hash %r', h)
-    winobjs.cryptcontext[args.hbasedata].h_result = h
-    jitter.vm.set_u32(args.phkey, args.hbasedata)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def advapi32_CryptDestroyHash(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hhash"])
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def advapi32_CryptDecrypt(jitter):
-    # ret_ad, _ = jitter.func_args_stdcall(["hkey", "hhash", "final",
-    #                                       "dwflags", "pbdata",
-    #                                       "pdwdatalen"])
-    raise ValueError("Not implemented")
-    # jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_CreateFile(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["lpfilename", "access",
-                                             "dwsharedmode",
-                                             "lpsecurityattr",
-                                             "dwcreationdisposition",
-                                             "dwflagsandattr",
-                                             "htemplatefile"])
-    if args.lpfilename == 0:
-        jitter.func_ret_stdcall(ret_ad, 0xffffffff)
-        return
-
-    fname = get_str(args.lpfilename)
-    log.info('CreateFile fname %s', fname)
-    ret = 0xffffffff
-
-    log.debug("%r %r", fname.lower(), winobjs.module_path.lower())
-    is_original_file = fname.lower() == winobjs.module_path.lower()
-
-    if fname.upper() in [r"\\.\SICE", r"\\.\NTICE", r"\\.\SIWVID", r'\\.\SIWDEBUG']:
-        pass
-    elif fname.upper() in ['NUL']:
-        ret = winobjs.module_cur_hwnd
-    else:
-        # sandbox path
-        sb_fname = windows_to_sbpath(fname)
-        if args.access & 0x80000000 or args.access == 1:
-            # read and maybe write
-            if args.dwcreationdisposition == 2:
-                # create_always
-                if os.access(sb_fname, os.R_OK):
-                    # but file exist
-                    pass
-                else:
-                    raise NotImplementedError("Untested case")  # to test
-                    # h = open(sb_fname, 'rb+')
-            elif args.dwcreationdisposition == 3:
-                # open_existing
-                if os.access(sb_fname, os.R_OK):
-                    s = os.stat(sb_fname)
-                    if stat.S_ISDIR(s.st_mode):
-                        ret = winobjs.handle_pool.add(sb_fname, 0x1337)
-                    else:
-                        open_mode = 'rb'
-                        if (args.access & 0x40000000) or args.access == 2:
-                            open_mode = 'r+b'
-                        h = open(sb_fname, open_mode)
-                        ret = winobjs.handle_pool.add(sb_fname, h)
-                else:
-                    log.warning("FILE %r (%s) DOES NOT EXIST!", fname, sb_fname)
-            elif args.dwcreationdisposition == 1:
-                # create new
-                if os.access(sb_fname, os.R_OK):
-                    # file exist
-                    # ret = 80
-                    winobjs.lastwin32error = 80
-                else:
-                    # first create an empty file
-                    open(sb_fname, 'wb').close()
-                    # then open
-                    h = open(sb_fname, 'r+b')
-                    ret = winobjs.handle_pool.add(sb_fname, h)
-            elif args.dwcreationdisposition == 4:
-                # open_always
-                if os.access(sb_fname, os.R_OK):
-                    s = os.stat(sb_fname)
-                    if stat.S_ISDIR(s.st_mode):
-                        ret = winobjs.handle_pool.add(sb_fname, 0x1337)
-                    else:
-                        h = open(sb_fname, 'r+b')
-                        ret = winobjs.handle_pool.add(sb_fname, h)
-                else:
-                    raise NotImplementedError("Untested case")
-            else:
-                raise NotImplementedError("Untested case")
-        elif (args.access & 0x40000000) or args.access == 2:
-            # write but not read
-            if args.dwcreationdisposition == 3:
-                # open existing
-                if is_original_file:
-                    # cannot open self in write mode!
-                    pass
-                elif os.access(sb_fname, os.R_OK):
-                    s = os.stat(sb_fname)
-                    if stat.S_ISDIR(s.st_mode):
-                        # open dir
-                        ret = winobjs.handle_pool.add(sb_fname, 0x1337)
-                    else:
-                        h = open(sb_fname, 'wb')
-                        ret = winobjs.handle_pool.add(sb_fname, h)
-                else:
-                    raise NotImplementedError("Untested case")  # to test
-            elif args.dwcreationdisposition == 5:
-                # truncate_existing
-                if is_original_file:
-                    pass
-                else:
-                    raise NotImplementedError("Untested case")  # to test
-            else:
-                # raise NotImplementedError("Untested case") # to test
-                h = open(sb_fname, 'wb')
-                ret = winobjs.handle_pool.add(sb_fname, h)
-        else:
-            raise NotImplementedError("Untested case")
-
-        # h = open(sb_fname, 'rb+')
-        # ret = winobjs.handle_pool.add(sb_fname, h)
-    log.debug('CreateFile ret %x', ret)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_CreateFileA(jitter):
-    kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_CreateFileW(jitter):
-    kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_ReadFile(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpbuffer",
-                                             "nnumberofbytestoread",
-                                             "lpnumberofbytesread",
-                                             "lpoverlapped"])
-    if args.hwnd == winobjs.module_cur_hwnd:
-        pass
-    elif args.hwnd in winobjs.handle_pool:
-        pass
-    else:
-        raise ValueError('unknown hwnd!')
-
-    data = None
-    if args.hwnd in winobjs.files_hwnd:
-        data = winobjs.files_hwnd[
-            winobjs.module_cur_hwnd].read(args.nnumberofbytestoread)
-    elif args.hwnd in winobjs.handle_pool:
-        wh = winobjs.handle_pool[args.hwnd]
-        data = wh.info.read(args.nnumberofbytestoread)
-    else:
-        raise ValueError('unknown filename')
-
-    if data is not None:
-        if (args.lpnumberofbytesread):
-            jitter.vm.set_u32(args.lpnumberofbytesread, len(data))
-        jitter.vm.set_mem(args.lpbuffer, data)
-
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_GetFileSize(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpfilesizehight"])
-
-    if args.hwnd == winobjs.module_cur_hwnd:
-        ret = len(open(winobjs.module_fname_nux, "rb").read())
-    elif args.hwnd in winobjs.handle_pool:
-        wh = winobjs.handle_pool[args.hwnd]
-        ret = len(open(wh.name, "rb").read())
-    else:
-        raise ValueError('unknown hwnd!')
-
-    if args.lpfilesizehight != 0:
-        jitter.vm.set_u32(args.lpfilesizehight, ret)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_GetFileSizeEx(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpfilesizehight"])
-
-    if args.hwnd == winobjs.module_cur_hwnd:
-        l = len(open(winobjs.module_fname_nux, "rb").read())
-    elif args.hwnd in winobjs.handle_pool:
-        wh = winobjs.handle_pool[args.hwnd]
-        l = len(open(wh.name, "rb").read())
-    else:
-        raise ValueError('unknown hwnd!')
-
-    if args.lpfilesizehight == 0:
-        raise NotImplementedError("Untested case")
-    jitter.vm.set_mem(args.lpfilesizehight, pck32(
-        l & 0xffffffff) + pck32((l >> 32) & 0xffffffff))
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_FlushInstructionCache(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hprocess", "lpbasead", "dwsize"])
-    jitter.func_ret_stdcall(ret_ad, 0x1337)
-
-
-def kernel32_VirtualProtect(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['lpvoid', 'dwsize',
-                                             'flnewprotect',
-                                             'lpfloldprotect'])
-    # XXX mask hpart
-    flnewprotect = args.flnewprotect & 0xFFF
-    if not flnewprotect in ACCESS_DICT:
-        raise ValueError('unknown access dw!')
-
-    if args.lpfloldprotect:
-        old = jitter.vm.get_mem_access(args.lpvoid)
-        jitter.vm.set_u32(args.lpfloldprotect, ACCESS_DICT_INV[old])
-
-    paddr = args.lpvoid - (args.lpvoid % winobjs.alloc_align)
-    paddr_max = (args.lpvoid + args.dwsize + winobjs.alloc_align - 1)
-    paddr_max_round = paddr_max - (paddr_max % winobjs.alloc_align)
-    psize = paddr_max_round - paddr
-    for addr, items in list(winobjs.allocated_pages.items()):
-        alloc_addr, alloc_size = items
-        if (paddr + psize <= alloc_addr or
-            paddr > alloc_addr + alloc_size):
-            continue
-        size = jitter.vm.get_all_memory()[addr]["size"]
-        # Page is included in Protect area
-        if (paddr <= addr < addr + size <= paddr + psize):
-            log.warn("set page %x %x", addr, ACCESS_DICT[flnewprotect])
-            jitter.vm.set_mem_access(addr, ACCESS_DICT[flnewprotect])
-            continue
-
-        # Page is partly in Protect area: splitting is needed
-        if (addr <= paddr < addr + size or
-            addr <= paddr + psize < addr + size):
-
-            old_access = jitter.vm.get_mem_access(addr)
-
-            # splits = [
-            #     addr -> max(paddr, addr)
-            #     max(paddr, addr) -> min(addr + size, paddr + psize)
-            #     min(addr + size, paddr + psize) -> addr + size
-            # ]
-            splits = [
-                (addr, old_access,
-                 jitter.vm.get_mem(addr, max(paddr, addr) - addr)),
-                (max(paddr, addr), ACCESS_DICT[flnewprotect],
-                 jitter.vm.get_mem(
-                     max(paddr, addr),
-                     min(addr + size, paddr + psize) - max(paddr, addr))),
-                (min(addr + size, paddr + psize), old_access,
-                 jitter.vm.get_mem(
-                     min(addr + size, paddr + psize),
-                     addr + size - min(addr + size, paddr + psize)))
-            ]
-
-            jitter.vm.remove_memory_page(addr)
-            for split_addr, split_access, split_data in splits:
-                if not split_data:
-                    continue
-                log.warn("create page %x %x", split_addr,
-                         ACCESS_DICT[flnewprotect])
-                jitter.vm.add_memory_page(
-                    split_addr, split_access, split_data,
-                    "VirtualProtect split ret 0x%X" % ret_ad)
-                winobjs.allocated_pages[split_addr] = (alloc_addr, alloc_size)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_VirtualAlloc(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['lpvoid', 'dwsize',
-                                             'alloc_type', 'flprotect'])
-
-
-    if not args.flprotect in ACCESS_DICT:
-        raise ValueError('unknown access dw!')
-
-    if args.lpvoid == 0:
-        alloc_addr = winobjs.heap.next_addr(args.dwsize)
-        winobjs.allocated_pages[alloc_addr] = (alloc_addr, args.dwsize)
-        jitter.vm.add_memory_page(
-            alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * args.dwsize,
-            "Alloc in %s ret 0x%X" % (whoami(), ret_ad))
-    else:
-        all_mem = jitter.vm.get_all_memory()
-        if args.lpvoid in all_mem:
-            alloc_addr = args.lpvoid
-            jitter.vm.set_mem_access(args.lpvoid, ACCESS_DICT[args.flprotect])
-        else:
-            alloc_addr = winobjs.heap.next_addr(args.dwsize)
-            winobjs.allocated_pages[alloc_addr] = (alloc_addr, args.dwsize)
-            # alloc_addr = args.lpvoid
-            jitter.vm.add_memory_page(
-                alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * args.dwsize,
-                "Alloc in %s ret 0x%X" % (whoami(), ret_ad))
-
-    log.info('VirtualAlloc addr: 0x%x', alloc_addr)
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
-
-
-def kernel32_VirtualFree(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["lpvoid", "dwsize", "alloc_type"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def user32_GetWindowLongA(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hwnd", "nindex"])
-    jitter.func_ret_stdcall(ret_ad, winobjs.windowlong_dw)
-
-
-def user32_SetWindowLongA(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["hwnd", "nindex", "newlong"])
-    jitter.func_ret_stdcall(ret_ad, winobjs.windowlong_dw)
-
-
-def kernel32_GetModuleFileName(jitter, funcname, set_str):
-    ret_ad, args = jitter.func_args_stdcall(["hmodule", "lpfilename", "nsize"])
-
-    if args.hmodule in [0, winobjs.hcurmodule]:
-        p = winobjs.module_path[:]
-    elif (winobjs.runtime_dll and
-          args.hmodule in viewvalues(winobjs.runtime_dll.name2off)):
-        name_inv = dict(
-            [
-                (x[1], x[0])
-                for x in viewitems(winobjs.runtime_dll.name2off)
-            ]
-        )
-        p = name_inv[args.hmodule]
-    else:
-        log.warning(('Unknown module 0x%x.' +
-                     'Set winobjs.hcurmodule and retry'), args.hmodule)
-        p = None
-
-    if p is None:
-        l = 0
-    elif args.nsize < len(p):
-        p = p[:args.nsize]
-        l = len(p)
-    else:
-        l = len(p)
-
-    if p:
-        set_str(args.lpfilename, p)
-
-    jitter.func_ret_stdcall(ret_ad, l)
-
-
-def kernel32_GetModuleFileNameA(jitter):
-    kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetModuleFileNameW(jitter):
-    kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def kernel32_CreateMutex(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["mutexattr", "initowner",
-                                             "lpname"])
-
-    if args.lpname:
-        name = get_str(args.lpname)
-        log.info("CreateMutex %r", name)
-    else:
-        name = None
-    if args.initowner:
-        if name in winobjs.mutex:
-            raise NotImplementedError("Untested case")
-            # ret = 0
-        else:
-            winobjs.mutex[name] = id(name) & 0xFFFFFFFF
-            ret = winobjs.mutex[name]
-    else:
-        if name in winobjs.mutex:
-            raise NotImplementedError("Untested case")
-            # ret = 0
-        else:
-            winobjs.mutex[name] = id(name) & 0xFFFFFFFF
-            ret = winobjs.mutex[name]
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_CreateMutexA(jitter):
-    kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_CreateMutexW(jitter):
-    kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def shell32_SHGetSpecialFolderLocation(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwndowner", "nfolder", "ppidl"])
-    jitter.vm.set_u32(args.ppidl, args.nfolder)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_SHGetPathFromIDList(jitter, funcname, set_str):
-    ret_ad, args = jitter.func_args_stdcall(["pidl", "ppath"])
-
-    if args.pidl == 7:  # CSIDL_STARTUP:
-        s = "c:\\doc\\user\\startmenu\\programs\\startup"
-        set_str(args.ppath, s)
-    else:
-        raise ValueError('pidl not implemented', args.pidl)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def shell32_SHGetPathFromIDListW(jitter):
-    kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def shell32_SHGetPathFromIDListA(jitter):
-    kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetLastError(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, winobjs.lastwin32error)
-
-
-def kernel32_SetLastError(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["errcode"])
-    # lasterr addr
-    # ad = tib_address + 0x34
-    # jitter.vm.set_mem(ad, pck32(args.errcode))
-    winobjs.lastwin32error = args.errcode
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_RestoreLastError(jitter):
-    kernel32_SetLastError(jitter)
-
-
-def kernel32_LoadLibrary(jitter, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["dllname"])
-
-    libname = get_str(args.dllname, 0x100)
-    ret = winobjs.runtime_dll.lib_get_add_base(libname)
-    log.info("Loading %r ret 0x%x", libname, ret)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_LoadLibraryA(jitter):
-    kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char))
-
-
-def kernel32_LoadLibraryW(jitter):
-    kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char))
-
-
-def kernel32_LoadLibraryEx(jitter, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["dllname", "hfile", "flags"])
-
-    if args.hfile != 0:
-        raise NotImplementedError("Untested case")
-    libname = get_str(args.dllname, 0x100)
-    ret = winobjs.runtime_dll.lib_get_add_base(libname)
-    log.info("Loading %r ret 0x%x", libname, ret)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_LoadLibraryExA(jitter):
-    kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char))
-
-
-def kernel32_LoadLibraryExW(jitter):
-    kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char))
-
-
-def kernel32_GetProcAddress(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["libbase", "fname"])
-    fname = args.fname
-    if fname >= 0x10000:
-        fname = jitter.get_c_str(fname, 0x100)
-        if not fname:
-            fname = None
-    if fname is not None:
-        ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname)
-    else:
-        ad = 0
-    log.info("GetProcAddress %r %r ret 0x%x", args.libbase, fname, ad)
-    jitter.add_breakpoint(ad, jitter.handle_lib)
-    jitter.func_ret_stdcall(ret_ad, ad)
-
-
-def kernel32_GetModuleHandle(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["dllname"])
-
-    if args.dllname:
-        libname = get_str(args.dllname)
-        if libname:
-            ret = winobjs.runtime_dll.lib_get_add_base(libname)
-        else:
-            log.warning('unknown module!')
-            ret = 0
-        log.info("GetModuleHandle %r ret 0x%x", libname, ret)
-    else:
-        ret = winobjs.current_pe.NThdr.ImageBase
-        log.info("GetModuleHandle default ret 0x%x", ret)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_GetModuleHandleA(jitter):
-    kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_GetModuleHandleW(jitter):
-    kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_VirtualLock(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["lpaddress", "dwsize"])
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-class systeminfo(object):
-    oemId = 0
-    dwPageSize = 0x1000
-    lpMinimumApplicationAddress = 0x10000
-    lpMaximumApplicationAddress = 0x7ffeffff
-    dwActiveProcessorMask = 0x1
-    numberOfProcessors = 0x1
-    ProcessorsType = 586
-    dwAllocationgranularity = 0x10000
-    wProcessorLevel = 0x6
-    ProcessorRevision = 0xf0b
-
-    def pack(self):
-        return struct.pack('IIIIIIIIHH',
-                           self.oemId,
-                           self.dwPageSize,
-                           self.lpMinimumApplicationAddress,
-                           self.lpMaximumApplicationAddress,
-                           self.dwActiveProcessorMask,
-                           self.numberOfProcessors,
-                           self.ProcessorsType,
-                           self.dwAllocationgranularity,
-                           self.wProcessorLevel,
-                           self.ProcessorRevision)
-
-
-def kernel32_GetSystemInfo(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["sys_ptr"])
-    sysinfo = systeminfo()
-    jitter.vm.set_mem(args.sys_ptr, sysinfo.pack())
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_IsWow64Process(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["process", "bool_ptr"])
-    jitter.vm.set_u32(args.bool_ptr, 0)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_GetCommandLine(jitter, set_str):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    alloc_addr = winobjs.heap.alloc(jitter, 0x1000)
-    set_str(alloc_addr, '"%s"' % winobjs.module_path)
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
-
-
-def kernel32_GetCommandLineA(jitter):
-    kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetCommandLineW(jitter):
-    kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_w(jitter, addr, value))
-
-
-def shell32_CommandLineToArgvW(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["pcmd", "pnumargs"])
-    cmd = get_win_str_w(jitter, args.pcmd)
-    if cmd.startswith('"') and cmd.endswith('"'):
-        cmd = cmd[1:-1]
-    log.info("CommandLineToArgv %r", cmd)
-    tks = cmd.split(' ')
-    addr = winobjs.heap.alloc(jitter, len(cmd) * 2 + 4 * len(tks))
-    addr_ret = winobjs.heap.alloc(jitter, 4 * (len(tks) + 1))
-    o = 0
-    for i, t in enumerate(tks):
-        set_win_str_w(jitter, addr + o, t)
-        jitter.vm.set_u32(addr_ret + 4 * i, addr + o)
-        o += len(t)*2 + 2
-
-    jitter.vm.set_u32(addr_ret + 4 * (i+1), 0)
-    jitter.vm.set_u32(args.pnumargs, len(tks))
-    jitter.func_ret_stdcall(ret_ad, addr_ret)
-
-def cryptdll_MD5Init(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ad_ctx"])
-    index = len(winobjs.cryptdll_md5_h)
-    h = MD5.new()
-    winobjs.cryptdll_md5_h[index] = h
-
-    jitter.vm.set_u32(args.ad_ctx, index)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def cryptdll_MD5Update(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ad_ctx", "ad_input", "inlen"])
-
-    index = jitter.vm.get_u32(args.ad_ctx)
-    if not index in winobjs.cryptdll_md5_h:
-        raise ValueError('unknown h context', index)
-
-    data = jitter.vm.get_mem(args.ad_input, args.inlen)
-    winobjs.cryptdll_md5_h[index].update(data)
-    log.debug(hexdump(data))
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def cryptdll_MD5Final(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ad_ctx"])
-
-    index = jitter.vm.get_u32(args.ad_ctx)
-    if not index in winobjs.cryptdll_md5_h:
-        raise ValueError('unknown h context', index)
-    h = winobjs.cryptdll_md5_h[index].digest()
-    jitter.vm.set_mem(args.ad_ctx + 88, h)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_RtlInitAnsiString(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ad_ctx", "ad_str"])
-
-    s = get_win_str_a(jitter, args.ad_str)
-    l = len(s)
-    jitter.vm.set_mem(args.ad_ctx,
-                      pck16(l) + pck16(l + 1) + pck32(args.ad_str))
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_RtlHashUnicodeString(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ad_ctxu", "case_i", "h_id",
-                                             "phout"])
-
-    if args.h_id != 1:
-        raise ValueError('unk hash unicode', args.h_id)
-
-    l1, l2, ptra = struct.unpack('HHL', jitter.vm.get_mem(args.ad_ctxu, 8))
-    s = jitter.vm.get_mem(ptra, l1)
-    s = s[:-1]
-    hv = 0
-
-    if args.case_i:
-        s = s.lower()
-    for c in s:
-        hv = ((65599 * hv) + ord(c)) & 0xffffffff
-    jitter.vm.set_u32(args.phout, hv)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_RtlMoveMemory(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ad_dst", "ad_src", "m_len"])
-    data = jitter.vm.get_mem(args.ad_src, args.m_len)
-    jitter.vm.set_mem(args.ad_dst, data)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_RtlAnsiCharToUnicodeChar(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['ad_ad_ch'])
-    ad_ch = jitter.vm.get_u32(args.ad_ad_ch)
-    ch = ord(jitter.vm.get_mem(ad_ch, 1))
-    jitter.vm.set_u32(args.ad_ad_ch, ad_ch + 1)
-    jitter.func_ret_stdcall(ret_ad, ch)
-
-
-def ntdll_RtlFindCharInUnicodeString(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["flags", "main_str_ad",
-                                             "search_chars_ad", "pos_ad"])
-
-    if args.flags != 0:
-        raise ValueError('unk flags')
-
-    ml1, ml2, mptra = struct.unpack('HHL',
-                                    jitter.vm.get_mem(args.main_str_ad, 8))
-    sl1, sl2, sptra = struct.unpack(
-        'HHL', jitter.vm.get_mem(args.search_chars_ad, 8))
-    main_data = jitter.vm.get_mem(mptra, ml1)[:-1]
-    search_data = jitter.vm.get_mem(sptra, sl1)[:-1]
-
-    pos = None
-    for i, c in enumerate(main_data):
-        for s in search_data:
-            if s == c:
-                pos = i
-                break
-        if pos:
-            break
-    if pos is None:
-        ret = 0xC0000225
-        jitter.vm.set_u32(args.pos_ad, 0)
-    else:
-        ret = 0
-        jitter.vm.set_u32(args.pos_ad, pos)
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def ntdll_RtlComputeCrc32(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["dwinit", "pdata", "ilen"])
-    data = jitter.vm.get_mem(args.pdata, args.ilen)
-    crc_r = crc32(data, args.dwinit)
-    jitter.func_ret_stdcall(ret_ad, crc_r)
-
-
-def ntdll_RtlExtendedIntegerMultiply(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['multiplicand_low',
-                                             'multiplicand_high',
-                                             'multiplier'])
-    a = (args.multiplicand_high << 32) + args.multiplicand_low
-    a = a * args.multiplier
-    jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
-
-
-def ntdll_RtlLargeIntegerAdd(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['a_low', 'a_high',
-                                             'b_low', 'b_high'])
-    a = (args.a_high << 32) + args.a_low + (args.b_high << 32) + args.b_low
-    jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
-
-
-def ntdll_RtlLargeIntegerShiftRight(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['a_low', 'a_high', 's_count'])
-    a = ((args.a_high << 32) + args.a_low) >> args.s_count
-    jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
-
-
-def ntdll_RtlEnlargedUnsignedMultiply(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['a', 'b'])
-    a = args.a * args.b
-    jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
-
-
-def ntdll_RtlLargeIntegerSubtract(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['a_low', 'a_high',
-                                             'b_low', 'b_high'])
-    a = (args.a_high << 32) + args.a_low - (args.b_high << 32) + args.b_low
-    jitter.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff)
-
-
-def ntdll_RtlCompareMemory(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['ad1', 'ad2', 'm_len'])
-    data1 = jitter.vm.get_mem(args.ad1, args.m_len)
-    data2 = jitter.vm.get_mem(args.ad2, args.m_len)
-
-    i = 0
-    while data1[i] == data2[i]:
-        i += 1
-        if i >= args.m_len:
-            break
-
-    jitter.func_ret_stdcall(ret_ad, i)
-
-
-def user32_GetMessagePos(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, 0x00110022)
-
-
-def kernel32_Sleep(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(['t'])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_ZwUnmapViewOfSection(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(['h', 'ad'])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_IsBadReadPtr(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(['lp', 'ucb'])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_KeInitializeEvent(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['my_event', 'my_type',
-                                             'my_state'])
-    jitter.vm.set_u32(args.my_event, winobjs.win_event_num)
-    winobjs.win_event_num += 1
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_RtlGetVersion(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['ptr_version'])
-
-    s = struct.pack("IIIII",
-                    0x114,  # struct size
-                    0x5,   # maj vers
-                    0x2,  # min vers
-                    0x666,  # build nbr
-                    0x2,   # platform id
-                    ) + encode_win_str_w("Service pack 4")
-
-    jitter.vm.set_mem(args.ptr_version, s)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_RtlVerifyVersionInfo(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['ptr_version'])
-
-    s = jitter.vm.get_mem(args.ptr_version, 0x5 * 4)
-    s_size, s_majv, s_minv, s_buildn, s_platform = struct.unpack('IIIII', s)
-    raise NotImplementedError("Untested case")
-    # jitter.vm.set_mem(args.ptr_version, s)
-    # jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def hal_ExAcquireFastMutex(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def mdl2ad(n):
-    return winobjs.nt_mdl_ad + 0x10 * n
-
-
-def ad2mdl(ad):
-    return ((ad - winobjs.nt_mdl_ad) & 0xFFFFFFFF) // 0x10
-
-
-def ntoskrnl_IoAllocateMdl(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["v_addr", "l", "second_buf",
-                                             "chargequota", "pirp"])
-    m = mdl(args.v_addr, args.l)
-    winobjs.nt_mdl[winobjs.nt_mdl_cur] = m
-    jitter.vm.set_mem(mdl2ad(winobjs.nt_mdl_cur), bytes(m))
-    jitter.func_ret_stdcall(ret_ad, mdl2ad(winobjs.nt_mdl_cur))
-    winobjs.nt_mdl_cur += 1
-
-
-def ntoskrnl_MmProbeAndLockPages(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["p_mdl", "access_mode", "op"])
-
-    if not ad2mdl(args.p_mdl) in winobjs.nt_mdl:
-        raise ValueError('unk mdl', hex(args.p_mdl))
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_MmMapLockedPagesSpecifyCache(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["p_mdl", "access_mode",
-                                             "cache_type", "base_ad",
-                                             "bugcheckonfailure",
-                                             "priority"])
-    if not ad2mdl(args.p_mdl) in winobjs.nt_mdl:
-        raise ValueError('unk mdl', hex(args.p_mdl))
-
-    jitter.func_ret_stdcall(ret_ad, winobjs.nt_mdl[ad2mdl(args.p_mdl)].ad)
-
-
-def ntoskrnl_MmProtectMdlSystemAddress(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["p_mdl", "prot"])
-    if not ad2mdl(args.p_mdl) in winobjs.nt_mdl:
-        raise ValueError('unk mdl', hex(args.p_mdl))
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_MmUnlockPages(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['p_mdl'])
-    if not ad2mdl(args.p_mdl) in winobjs.nt_mdl:
-        raise ValueError('unk mdl', hex(args.p_mdl))
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_IoFreeMdl(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['p_mdl'])
-    if not ad2mdl(args.p_mdl) in winobjs.nt_mdl:
-        raise ValueError('unk mdl', hex(args.p_mdl))
-    del(winobjs.nt_mdl[ad2mdl(args.p_mdl)])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def hal_ExReleaseFastMutex(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_RtlQueryRegistryValues(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["relativeto", "path",
-                                             "querytable",
-                                             "context",
-                                             "environ"])
-    # path = get_win_str_w(jitter, args.path)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntoskrnl_ExAllocatePoolWithTagPriority(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["pool_type",
-                                             "nbr_of_bytes",
-                                             "tag", "priority"])
-    alloc_addr = winobjs.heap.next_addr(args.nbr_of_bytes)
-    jitter.vm.add_memory_page(
-        alloc_addr, PAGE_READ | PAGE_WRITE, b"\x00" * args.nbr_of_bytes,
-        "Alloc in %s ret 0x%X" % (whoami(), ret_ad))
-
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
-
-
-def my_lstrcmp(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2"])
-    s1 = get_str(args.ptr_str1)
-    s2 = get_str(args.ptr_str2)
-    log.info("Compare %r with %r", s1, s2)
-    jitter.func_ret_stdcall(ret_ad, cmp(s1, s2))
-
-def msvcrt_wcscmp(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s1 = get_win_str_w(jitter, args.ptr_str1)
-    s2 = get_win_str_w(jitter, args.ptr_str2)
-    log.debug("%s('%s','%s')" % (whoami(), s1, s2))
-    jitter.func_ret_cdecl(ret_ad, cmp(s1, s2))
-
-def msvcrt__wcsicmp(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s1 = get_win_str_w(jitter, args.ptr_str1)
-    s2 = get_win_str_w(jitter, args.ptr_str2)
-    log.debug("%s('%s','%s')" % (whoami(), s1, s2))
-    jitter.func_ret_cdecl(ret_ad, cmp(s1.lower(), s2.lower()))
-
-def msvcrt__wcsnicmp(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2", "count"])
-    s1 = get_win_str_w(jitter, args.ptr_str1)
-    s2 = get_win_str_w(jitter, args.ptr_str2)
-    log.debug("%s('%s','%s',%d)" % (whoami(), s1, s2, args.count))
-    jitter.func_ret_cdecl(ret_ad, cmp(s1.lower()[:args.count], s2.lower()[:args.count]))
-
-def msvcrt_wcsncpy(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["dst", "src", "n"])
-    src = get_win_str_w(jitter, args.src)
-    dst = src[:args.n]
-    jitter.vm.set_mem(args.dst, b"\x00\x00" * args.n)
-    jitter.vm.set_mem(args.dst, dst.encode("utf-16le"))
-    jitter.func_ret_cdecl(ret_ad, args.dst)
-
-def kernel32_lstrcmpA(jitter):
-    my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_lstrcmpiA(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower())
-
-
-def kernel32_lstrcmpW(jitter):
-    my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_lstrcmpiW(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_w(jitter, x).lower())
-
-
-def kernel32_lstrcmpi(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower())
-
-
-def my_strcpy(jitter, funcname, get_str, set_str):
-    ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2"])
-    s2 = get_str(args.ptr_str2)
-    set_str(args.ptr_str1, s2)
-    log.info("Copy '%r'", s2)
-    jitter.func_ret_stdcall(ret_ad, args.ptr_str1)
-
-
-def kernel32_lstrcpyW(jitter):
-    my_strcpy(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def kernel32_lstrcpyA(jitter):
-    my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_lstrcpy(jitter):
-    my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-def msvcrt__mbscpy(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s2 = get_win_str_w(jitter, args.ptr_str2)
-    set_win_str_w(jitter, args.ptr_str1, s2)
-    jitter.func_ret_cdecl(ret_ad, args.ptr_str1)
-
-def msvcrt_wcscpy(jitter):
-    return msvcrt__mbscpy(jitter)
-
-
-def kernel32_lstrcpyn(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2",
-                                             "mlen"])
-    s2 = get_win_str_a(jitter, args.ptr_str2)
-    if len(s2) >= args.mlen:
-        s2 = s2[:args.mlen - 1]
-    log.info("Copy '%r'", s2)
-    set_win_str_a(jitter, args.ptr_str1, s2)
-    jitter.func_ret_stdcall(ret_ad, args.ptr_str1)
-
-
-def my_strlen(jitter, funcname, get_str, mylen):
-    ret_ad, args = jitter.func_args_stdcall(["src"])
-    src = get_str(args.src)
-    length = mylen(src)
-    log.info("Len of '%r' -> 0x%x", src, length)
-    jitter.func_ret_stdcall(ret_ad, length)
-
-
-def kernel32_lstrlenA(jitter):
-    my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len)
-
-
-def kernel32_lstrlenW(jitter):
-    my_strlen(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), len)
-
-
-def kernel32_lstrlen(jitter):
-    my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len)
-
-
-def my_lstrcat(jitter, funcname, get_str, set_str):
-    ret_ad, args = jitter.func_args_stdcall(['ptr_str1', 'ptr_str2'])
-    s1 = get_str(args.ptr_str1)
-    s2 = get_str(args.ptr_str2)
-    set_str(args.ptr_str1, s1 + s2)
-    jitter.func_ret_stdcall(ret_ad, args.ptr_str1)
-
-
-def kernel32_lstrcatA(jitter):
-    my_lstrcat(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_lstrcatW(jitter):
-    my_lstrcat(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def kernel32_GetUserGeoID(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["geoclass"])
-    if args.geoclass == 14:
-        ret = 12345678
-    elif args.geoclass == 16:
-        ret = 55667788
-    else:
-        raise ValueError('unknown geolcass')
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def my_GetVolumeInformation(jitter, funcname, get_str, set_str):
-    ret_ad, args = jitter.func_args_stdcall(["lprootpathname",
-                                             "lpvolumenamebuffer",
-                                             "nvolumenamesize",
-                                             "lpvolumeserialnumber",
-                                             "lpmaximumcomponentlength",
-                                             "lpfilesystemflags",
-                                             "lpfilesystemnamebuffer",
-                                             "nfilesystemnamesize"])
-    if args.lprootpathname:
-        s = get_str(args.lprootpathname)
-        log.info('GetVolumeInformation %r', s)
-
-
-    if args.lpvolumenamebuffer:
-        s = "volumename"
-        s = s[:args.nvolumenamesize]
-        set_str(args.lpvolumenamebuffer, s)
-
-    if args.lpvolumeserialnumber:
-        jitter.vm.set_u32(args.lpvolumeserialnumber, 11111111)
-    if args.lpmaximumcomponentlength:
-        jitter.vm.set_u32(args.lpmaximumcomponentlength, 0xff)
-    if args.lpfilesystemflags:
-        jitter.vm.set_u32(args.lpfilesystemflags, 22222222)
-
-    if args.lpfilesystemnamebuffer:
-        s = "filesystemname"
-        s = s[:args.nfilesystemnamesize]
-        set_str(args.lpfilesystemnamebuffer, s)
-
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_GetVolumeInformationA(jitter):
-    my_GetVolumeInformation(
-        jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetVolumeInformationW(jitter):
-    my_GetVolumeInformation(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def kernel32_MultiByteToWideChar(jitter):
-    MB_ERR_INVALID_CHARS = 0x8
-    CP_ACP  = 0x000
-    CP_1252 = 0x4e4
-
-    ret_ad, args = jitter.func_args_stdcall(["codepage", "dwflags",
-                                             "lpmultibytestr",
-                                             "cbmultibyte",
-                                             "lpwidecharstr",
-                                             "cchwidechar"])
-    if args.codepage != CP_ACP and args.codepage != CP_1252:
-        raise NotImplementedError
-    # according to MSDN:
-    # "Note that, if cbMultiByte is 0, the function fails."
-    if args.cbmultibyte == 0:
-        raise ValueError
-    # according to MSDN:
-    # "Alternatively, this parameter can be set to -1 if the string is
-    #  null-terminated."
-    if args.cbmultibyte == 0xffffffff:
-        src_len = 0
-        while jitter.vm.get_mem(args.lpmultibytestr + src_len, 1) != b'\0':
-            src_len += 1
-        src = jitter.vm.get_mem(args.lpmultibytestr, src_len)
-    else:
-        src = jitter.vm.get_mem(args.lpmultibytestr, args.cbmultibyte)
-    if args.dwflags & MB_ERR_INVALID_CHARS:
-        # will raise an exception if decoding fails
-        s = src.decode("cp1252", errors="replace").encode("utf-16le")
-    else:
-        # silently replace undecodable chars with U+FFFD
-        s = src.decode("cp1252", errors="replace").encode("utf-16le")
-    if args.cchwidechar > 0:
-        # return value is number of bytes written
-        retval = min(args.cchwidechar, len(s))
-        jitter.vm.set_mem(args.lpwidecharstr, s[:retval])
-    else:
-        # return value is number of bytes to write
-        # i.e., size of dest. buffer to allocate
-        retval = len(s)
-    jitter.func_ret_stdcall(ret_ad, retval)
-
-
-def kernel32_WideCharToMultiByte(jitter):
-    """
-        int WideCharToMultiByte(
-          UINT                               CodePage,
-          DWORD                              dwFlags,
-          _In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr,
-          int                                cchWideChar,
-          LPSTR                              lpMultiByteStr,
-          int                                cbMultiByte,
-          LPCCH                              lpDefaultChar,
-          LPBOOL                             lpUsedDefaultChar
-        );
-
-    """
-    CP_ACP  = 0x000
-    CP_1252 = 0x4e4
-
-    ret, args = jitter.func_args_stdcall([
-        'CodePage', 'dwFlags', 'lpWideCharStr', 'cchWideChar',
-        'lpMultiByteStr', 'cbMultiByte', 'lpDefaultChar', 'lpUsedDefaultChar',
-      ])
-    if args.CodePage != CP_ACP and args.CodePage != CP_1252:
-        raise NotImplementedError
-    cchWideChar = args.cchWideChar
-    if cchWideChar == 0xffffffff:
-        cchWideChar = len(get_win_str_w(jitter, args.lpWideCharStr)) + 1
-    src = jitter.vm.get_mem(args.lpWideCharStr, cchWideChar * 2)
-    dst = src.decode("utf-16le").encode("cp1252", errors="replace")
-    if args.cbMultiByte > 0:
-        # return value is the number of bytes written
-        retval = min(args.cbMultiByte, len(dst))
-        jitter.vm.set_mem(args.lpMultiByteStr, dst[:retval])
-    else:
-        # return value is the size of the buffer to allocate
-        # to get the multibyte string
-        retval = len(dst)
-    jitter.func_ret_stdcall(ret, retval)
-
-
-def my_GetEnvironmentVariable(jitter, funcname, get_str, set_str, mylen):
-    ret_ad, args = jitter.func_args_stdcall(["lpname", "lpbuffer",
-                                             "nsize"])
-
-    s = get_str(args.lpname)
-    log.info('GetEnvironmentVariable %r', s)
-    if s in winobjs.env_variables:
-        v = winobjs.env_variables[s]
-    else:
-        log.warning('WARNING unknown env variable %r', s)
-        v = ""
-    set_str(args.lpbuffer, v)
-    jitter.func_ret_stdcall(ret_ad, mylen(v))
-
-
-def kernel32_GetEnvironmentVariableA(jitter):
-    my_GetEnvironmentVariable(jitter, whoami(),
-                              lambda addr:get_win_str_a(jitter, addr),
-                              lambda addr,value: set_win_str_a(jitter, addr, value),
-                              len)
-
-
-def kernel32_GetEnvironmentVariableW(jitter):
-    my_GetEnvironmentVariable(jitter, whoami(),
-                              lambda addr:get_win_str_w(jitter, addr),
-                              lambda addr,value: set_win_str_w(jitter, addr, value),
-                              len)
-
-
-def my_GetSystemDirectory(jitter, funcname, set_str):
-    ret_ad, args = jitter.func_args_stdcall(["lpbuffer", "usize"])
-    s = "c:\\windows\\system32"
-    l = len(s)
-    set_str(args.lpbuffer, s)
-    jitter.func_ret_stdcall(ret_ad, l)
-
-
-
-def kernel32_GetSystemDirectoryA(jitter):
-    my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetSystemDirectoryW(jitter):
-    my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def my_CreateDirectory(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(['lppath', 'secattrib'])
-    # path = get_str(jitter, args.lppath)
-    jitter.func_ret_stdcall(ret_ad, 0x1337)
-
-
-def kernel32_CreateDirectoryW(jitter):
-    my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_CreateDirectoryA(jitter):
-    my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-
-def my_CreateEvent(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["lpeventattributes",
-                                             "bmanualreset",
-                                             "binitialstate",
-                                             "lpname"])
-    s = get_str(args.lpname) if args.lpname else None
-    if not s in winobjs.events_pool:
-        winobjs.events_pool[s] = (args.bmanualreset, args.binitialstate)
-    else:
-        log.warning('WARNING: known event')
-    jitter.func_ret_stdcall(ret_ad, id(s) & 0xFFFFFFFF)
-
-
-def kernel32_CreateEventA(jitter):
-    my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_CreateEventW(jitter):
-    my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_WaitForSingleObject(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['handle', 'dwms'])
-
-    t_start = time.time() * 1000
-    found = False
-    while True:
-        if args.dwms and args.dwms + t_start > time.time() * 1000:
-            ret = 0x102
-            break
-        for key, value in viewitems(winobjs.events_pool):
-            if key != args.handle:
-                continue
-            found = True
-            if value[1] == 1:
-                ret = 0
-                break
-        if not found:
-            log.warning('unknown handle')
-            ret = 0xffffffff
-            break
-        time.sleep(0.1)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_SetFileAttributesA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["lpfilename",
-                                             "dwfileattributes"])
-    if args.lpfilename:
-        # fname = get_win_str_a(jitter, args.lpfilename)
-        ret = 1
-    else:
-        ret = 0
-        jitter.vm.set_u32(tib_address + 0x34, 3)
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def ntdll_RtlMoveMemory(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["dst", "src", "l"])
-    s = jitter.vm.get_mem(args.src, args.l)
-    jitter.vm.set_mem(args.dst, s)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def ntdll_ZwQuerySystemInformation(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["systeminformationclass",
-                                             "systeminformation",
-                                             "systeminformationl",
-                                             "returnl"])
-    if args.systeminformationclass == 2:
-        # SYSTEM_PERFORMANCE_INFORMATION
-        o = struct.pack('II', 0x22222222, 0x33333333)
-        o += b"\x00" * args.systeminformationl
-        o = o[:args.systeminformationl]
-        jitter.vm.set_mem(args.systeminformation, o)
-    else:
-        raise ValueError('unknown sysinfo class',
-                         args.systeminformationclass)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_ZwProtectVirtualMemory(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["handle", "lppvoid",
-                                             "pdwsize",
-                                             "flnewprotect",
-                                             "lpfloldprotect"])
-
-    ad = jitter.vm.get_u32(args.lppvoid)
-    # dwsize = upck32(jitter.vm.get_mem(args.pdwsize, 4))
-    # XXX mask hpart
-    flnewprotect = args.flnewprotect & 0xFFF
-
-    if not flnewprotect in ACCESS_DICT:
-        raise ValueError('unknown access dw!')
-    jitter.vm.set_mem_access(ad, ACCESS_DICT[flnewprotect])
-
-    # XXX todo real old protect
-    jitter.vm.set_u32(args.lpfloldprotect, 0x40)
-
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def ntdll_ZwAllocateVirtualMemory(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["handle", "lppvoid",
-                                             "zerobits", "pdwsize",
-                                             "alloc_type",
-                                             "flprotect"])
-
-    # ad = upck32(jitter.vm.get_mem(args.lppvoid, 4))
-    dwsize = jitter.vm.get_u32(args.pdwsize)
-
-    if not args.flprotect in ACCESS_DICT:
-        raise ValueError('unknown access dw!')
-
-    alloc_addr = winobjs.heap.next_addr(dwsize)
-    jitter.vm.add_memory_page(
-        alloc_addr, ACCESS_DICT[args.flprotect], b"\x00" * dwsize,
-        "Alloc in %s ret 0x%X" % (whoami(), ret_ad))
-    jitter.vm.set_u32(args.lppvoid, alloc_addr)
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_ZwFreeVirtualMemory(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["handle", "lppvoid",
-                                             "pdwsize", "alloc_type"])
-    # ad = upck32(jitter.vm.get_mem(args.lppvoid, 4))
-    # dwsize = upck32(jitter.vm.get_mem(args.pdwsize, 4))
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_RtlInitString(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["pstring", "source"])
-    s = get_win_str_a(jitter, args.source)
-    l = len(s) + 1
-    o = struct.pack('HHI', l, l, args.source)
-    jitter.vm.set_mem(args.pstring, o)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_RtlAnsiStringToUnicodeString(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["dst", "src", "alloc_str"])
-
-    l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8))
-    s = get_win_str_a(jitter, p_src)
-    l = (len(s) + 1) * 2
-    if args.alloc_str:
-        alloc_addr = winobjs.heap.next_addr(l)
-        jitter.vm.add_memory_page(
-            alloc_addr, PAGE_READ | PAGE_WRITE, b"\x00" * l,
-            "Alloc in %s ret 0x%X" % (whoami(), ret_ad))
-    else:
-        alloc_addr = p_src
-    set_win_str_w(jitter, alloc_addr, s)
-    o = struct.pack('HHI', l, l, alloc_addr)
-    jitter.vm.set_mem(args.dst, o)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_LdrLoadDll(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["path", "flags",
-                                             "modname", "modhandle"])
-
-    l1, l2, p_src = struct.unpack('HHI',
-                                  jitter.vm.get_mem(args.modname, 0x8))
-    s = get_win_str_w(jitter, p_src)
-    libname = s.lower()
-
-    ad = winobjs.runtime_dll.lib_get_add_base(libname)
-    log.info("Loading %r ret 0x%x", s, ad)
-    jitter.vm.set_u32(args.modhandle, ad)
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_RtlFreeUnicodeString(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['src'])
-    # l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8))
-    # s = get_win_str_w(jitter, p_src)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_LdrGetProcedureAddress(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["libbase", "pfname",
-                                             "opt", "p_ad"])
-
-    l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.pfname, 0x8))
-    fname = get_win_str_a(jitter, p_src)
-
-    ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname)
-    jitter.add_breakpoint(ad, jitter.handle_lib)
-
-    jitter.vm.set_u32(args.p_ad, ad)
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def ntdll_memset(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['addr', 'c', 'size'])
-    jitter.vm.set_mem(args.addr, int_to_byte(args.c) * args.size)
-    jitter.func_ret_cdecl(ret_ad, args.addr)
-
-
-def msvcrt_memset(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['addr', 'c', 'size'])
-    jitter.vm.set_mem(args.addr, int_to_byte(args.c) * args.size)
-    jitter.func_ret_cdecl(ret_ad, args.addr)
-
-def msvcrt_strrchr(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
-    s = get_win_str_a(jitter, args.pstr)
-    c = int_to_byte(args.c).decode()
-    ret = args.pstr + s.rfind(c)
-    log.info("strrchr(%x '%s','%s') = %x" % (args.pstr,s,c,ret))
-    jitter.func_ret_cdecl(ret_ad, ret)
-
-def msvcrt_wcsrchr(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
-    s = get_win_str_w(jitter, args.pstr)
-    c = int_to_byte(args.c).decode()
-    ret = args.pstr + (s.rfind(c)*2)
-    log.info("wcsrchr(%x '%s',%s) = %x" % (args.pstr,s,c,ret))
-    jitter.func_ret_cdecl(ret_ad, ret)
-
-def msvcrt_memcpy(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['dst', 'src', 'size'])
-    s = jitter.vm.get_mem(args.src, args.size)
-    jitter.vm.set_mem(args.dst, s)
-    jitter.func_ret_cdecl(ret_ad, args.dst)
-
-def msvcrt_realloc(jitter):
-    ret_ad,args = jitter.func_args_cdecl(['ptr','new_size'])
-    if args.ptr == 0:
-        addr = winobjs.heap.alloc(jitter, args.new_size)
-    else:
-        addr = winobjs.heap.alloc(jitter, args.new_size)
-        size = winobjs.heap.get_size(jitter.vm, args.ptr)
-        data = jitter.vm.get_mem(args.ptr, size)
-        jitter.vm.set_mem(addr, data)
-    jitter.func_ret_cdecl(ret_ad, addr)
-
-def msvcrt_memcmp(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['ps1', 'ps2', 'size'])
-    s1 = jitter.vm.get_mem(args.ps1, args.size)
-    s2 = jitter.vm.get_mem(args.ps2, args.size)
-    ret = cmp(s1, s2)
-    jitter.func_ret_cdecl(ret_ad, ret)
-
-
-def shlwapi_PathFindExtensionA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = get_win_str_a(jitter, args.path_ad)
-    i = path.rfind('.')
-    if i == -1:
-        i = args.path_ad + len(path)
-    else:
-        i = args.path_ad + i
-    jitter.func_ret_stdcall(ret_ad, i)
-
-
-def shlwapi_PathRemoveFileSpecW(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = get_win_str_w(jitter, args.path_ad)
-    i = path.rfind('\\')
-    if i == -1:
-        i = 0
-    jitter.vm.set_mem(args.path_ad + i * 2, b"\x00\x00")
-    path = get_win_str_w(jitter, args.path_ad)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def shlwapi_PathIsPrefixW(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['ptr_prefix', 'ptr_path'])
-    prefix = get_win_str_w(jitter, args.ptr_prefix)
-    path = get_win_str_w(jitter, args.ptr_path)
-
-    if path.startswith(prefix):
-        ret = 1
-    else:
-        ret = 0
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def shlwapi_PathIsDirectoryW(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['ptr_path'])
-    fname = get_win_str_w(jitter, args.ptr_path)
-
-    sb_fname = windows_to_sbpath(fname)
-
-    s = os.stat(sb_fname)
-    ret = 0
-    if stat.S_ISDIR(s.st_mode):
-        ret = 1
-
-    jitter.func_ret_cdecl(ret_ad, ret)
-
-
-def shlwapi_PathIsFileSpec(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = get_str(args.path_ad)
-    if path.find(':') != -1 and path.find('\\') != -1:
-        ret = 0
-    else:
-        ret = 1
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def shlwapi_PathGetDriveNumber(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = get_str(args.path_ad)
-    l = ord(path[0].upper()) - ord('A')
-    if 0 <= l <= 25:
-        ret = l
-    else:
-        ret = -1
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def shlwapi_PathGetDriveNumberA(jitter):
-    shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def shlwapi_PathGetDriveNumberW(jitter):
-    shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def shlwapi_PathIsFileSpecA(jitter):
-    shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def shlwapi_PathIsFileSpecW(jitter):
-    shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def shlwapi_StrToIntA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['i_str_ad'])
-    i_str = get_win_str_a(jitter, args.i_str_ad)
-    try:
-        i = int(i_str)
-    except:
-        log.warning('WARNING cannot convert int')
-        i = 0
-
-    jitter.func_ret_stdcall(ret_ad, i)
-
-
-def shlwapi_StrToInt64Ex(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(['pstr', 'flags', 'pret'])
-    i_str = get_str(args.pstr)
-
-    if args.flags == 0:
-        r = int(i_str)
-    elif args.flags == 1:
-        r = int(i_str, 16)
-    else:
-        raise ValueError('cannot decode int')
-
-    jitter.vm.set_mem(args.pret, struct.pack('q', r))
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def shlwapi_StrToInt64ExA(jitter):
-    shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def shlwapi_StrToInt64ExW(jitter):
-    shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def user32_IsCharAlpha(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["c"])
-    try:
-        c = int_to_byte(args.c)
-    except:
-        log.error('bad char %r', args.c)
-        c = "\x00"
-    if c.isalpha(jitter):
-        ret = 1
-    else:
-        ret = 0
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def user32_IsCharAlphaA(jitter):
-    user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def user32_IsCharAlphaW(jitter):
-    user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def user32_IsCharAlphaNumericA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["c"])
-    c = int_to_byte(args.c)
-    if c.isalnum(jitter):
-        ret = 1
-    else:
-        ret = 0
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-def get_fmt_args(jitter, fmt, cur_arg, get_str):
-    return _get_fmt_args(fmt, cur_arg, get_str, jitter.get_arg_n_cdecl)
-
-def msvcrt_sprintf_str(jitter, get_str):
-    ret_ad, args = jitter.func_args_cdecl(['string', 'fmt'])
-    cur_arg, fmt = 2, args.fmt
-    return ret_ad, args, get_fmt_args(jitter, fmt, cur_arg, get_str)
-
-def msvcrt_sprintf(jitter):
-    ret_ad, args, output = msvcrt_sprintf_str(jitter, lambda addr:get_win_str_a(jitter, addr))
-    ret = len(output)
-    log.info("sprintf() = '%s'" % (output))
-    jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8'))
-    return jitter.func_ret_cdecl(ret_ad, ret)
-
-def msvcrt_swprintf(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['string', 'fmt'])
-    cur_arg, fmt = 2, args.fmt
-    output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_w(jitter, addr))
-    ret = len(output)
-    log.info("swprintf('%s') = '%s'" % (get_win_str_w(jitter, args.fmt), output))
-    jitter.vm.set_mem(args.string, output.encode("utf-16le") + b'\x00\x00')
-    return jitter.func_ret_cdecl(ret_ad, ret)
-
-def msvcrt_fprintf(jitter):
-    ret_addr, args = jitter.func_args_cdecl(['file', 'fmt'])
-    cur_arg, fmt = 2, args.fmt
-    output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_a(jitter, addr))
-    ret = len(output)
-    log.info("fprintf(%x, '%s') = '%s'" % (args.file, lambda addr:get_win_str_a(jitter, addr)(args.fmt), output))
-
-    fd = jitter.vm.get_u32(args.file + 0x10)
-    if not fd in winobjs.handle_pool:
-        raise NotImplementedError("Untested case")
-    winobjs.handle_pool[fd].info.write(output)
-
-    return jitter.func_ret_cdecl(ret_addr, ret)
-
-def shlwapi_StrCmpNIA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2",
-                                             "nchar"])
-    s1 = get_win_str_a(jitter, args.ptr_str1).lower()
-    s2 = get_win_str_a(jitter, args.ptr_str2).lower()
-    s1 = s1[:args.nchar]
-    s2 = s2[:args.nchar]
-    jitter.func_ret_stdcall(ret_ad, cmp(s1, s2))
-
-
-def advapi32_RegCreateKeyW(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hkey", "subkey",
-                                             "phandle"])
-    s_subkey = get_win_str_w(jitter, args.subkey).lower() if args.subkey else ""
-
-    ret_hkey = 0
-    ret = 2
-    if args.hkey in winobjs.hkey_handles:
-        ret = 0
-        if s_subkey:
-            ret_hkey = hash(s_subkey) & 0xffffffff
-            winobjs.hkey_handles[ret_hkey] = s_subkey
-        else:
-            ret_hkey = args.hkey
-
-    log.info("RegCreateKeyW(%x, '%s') = (%x,%d)" % (args.hkey, s_subkey, ret_hkey, ret))
-    jitter.vm.set_u32(args.phandle, ret_hkey)
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-def kernel32_GetCurrentDirectoryA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["size","buf"])
-    dir_ = winobjs.cur_dir
-    log.debug("GetCurrentDirectory() = '%s'" % dir_)
-    set_win_str_a(jitter, args.buf, dir_[:args.size-1])
-    ret = len(dir_)
-    if args.size <= len(dir_):
-        ret += 1
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-def advapi32_RegOpenKeyEx(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["hkey", "subkey",
-                                             "reserved", "access",
-                                             "phandle"])
-    s_subkey = get_str(args.subkey).lower() if args.subkey else ""
-
-    ret_hkey = 0
-    ret = 2
-    if args.hkey in winobjs.hkey_handles:
-        if s_subkey:
-            h = hash(s_subkey) & 0xffffffff
-            if h in winobjs.hkey_handles:
-                ret_hkey = h
-                ret = 0
-        else:
-            log.error('unknown skey')
-
-    jitter.vm.set_u32(args.phandle, ret_hkey)
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def advapi32_RegOpenKeyExA(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def advapi32_RegOpenKeyExW(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def advapi32_RegSetValue(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["hkey", "psubkey",
-                                             "valuetype", "pvalue",
-                                             "vlen"])
-    if args.psubkey:
-        log.info("Subkey %s", get_str(args.psubkey))
-    if args.pvalue:
-        log.info("Value %s", get_str(args.pvalue))
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-def advapi32_RegSetValueEx(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["hkey", "lpvaluename",
-                                             "reserved", "dwtype",
-                                             "lpdata", "cbData"])
-    hkey = winobjs.hkey_handles.get(args.hkey, "unknown HKEY")
-    value_name = get_str(args.lpvaluename) if args.lpvaluename else ""
-    data = get_str(args.lpdata) if args.lpdata else ""
-    log.info("%s('%s','%s'='%s',%x)" % (funcname, hkey, value_name, data, args.dwtype))
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-def advapi32_RegCloseKey(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hkey"])
-    del winobjs.hkey_handles[args.hkey]
-    log.info("RegCloseKey(%x)" % args.hkey)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-def advapi32_RegSetValueExA(jitter):
-    advapi32_RegSetValueEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def advapi32_RegSetValueExW(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def advapi32_RegSetValueA(jitter):
-    advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def advapi32_RegSetValueW(jitter):
-    advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_GetThreadLocale(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, 0x40c)
-
-def kernel32_SetCurrentDirectory(jitter, get_str):
-    ret_ad, args = jitter.func_args_stdcall(['dir'])
-    dir_ = get_str(args.dir)
-    log.debug("SetCurrentDirectory('%s') = 1" % dir_)
-    winobjs.cur_dir = dir_
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-def kernel32_SetCurrentDirectoryW(jitter):
-    return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_w(jitter, addr))
-
-def kernel32_SetCurrentDirectoryA(jitter):
-    return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_a(jitter, addr))
-
-def msvcrt_wcscat(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['ptr_str1', 'ptr_str2'])
-    s1 = get_win_str_w(jitter, args.ptr_str1)
-    s2 = get_win_str_w(jitter, args.ptr_str2)
-    log.info("strcat('%s','%s')" % (s1,s2))
-    set_win_str_w(jitter, args.ptr_str1, s1 + s2)
-    jitter.func_ret_cdecl(ret_ad, args.ptr_str1)
-
-
-def kernel32_GetLocaleInfo(jitter, funcname, set_str):
-    ret_ad, args = jitter.func_args_stdcall(["localeid", "lctype",
-                                             "lplcdata", "cchdata"])
-
-    buf = None
-    ret = 0
-    if args.localeid == 0x40c:
-        if args.lctype == 0x3:
-            buf = "ENGLISH"
-            buf = buf[:args.cchdata - 1]
-            set_str(args.lplcdata, buf)
-            ret = len(buf)
-    else:
-        raise ValueError('unimpl localeid')
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_GetLocaleInfoA(jitter):
-    kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetLocaleInfoW(jitter):
-    kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def kernel32_TlsAlloc(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    winobjs.tls_index += 1
-    jitter.func_ret_stdcall(ret_ad, winobjs.tls_index)
-
-
-def kernel32_TlsFree(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["tlsindex"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_TlsSetValue(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["tlsindex", "tlsvalue"])
-    winobjs.tls_values[args.tlsindex] = args.tlsvalue
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_TlsGetValue(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["tlsindex"])
-    if not args.tlsindex in winobjs.tls_values:
-        raise ValueError("unknown tls val", repr(args.tlsindex))
-    jitter.func_ret_stdcall(ret_ad, winobjs.tls_values[args.tlsindex])
-
-
-def user32_GetKeyboardType(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["typeflag"])
-
-    ret = 0
-    if args.typeflag == 0:
-        ret = 4
-    else:
-        raise ValueError('unimpl keyboard type')
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-class startupinfo(object):
-    """
-        typedef struct _STARTUPINFOA {
-          /* 00000000 */ DWORD  cb;
-          /* 00000004 */ LPSTR  lpReserved;
-          /* 00000008 */ LPSTR  lpDesktop;
-          /* 0000000C */ LPSTR  lpTitle;
-          /* 00000010 */ DWORD  dwX;
-          /* 00000014 */ DWORD  dwY;
-          /* 00000018 */ DWORD  dwXSize;
-          /* 0000001C */ DWORD  dwYSize;
-          /* 00000020 */ DWORD  dwXCountChars;
-          /* 00000024 */ DWORD  dwYCountChars;
-          /* 00000028 */ DWORD  dwFillAttribute;
-          /* 0000002C */ DWORD  dwFlags;
-          /* 00000030 */ WORD   wShowWindow;
-          /* 00000032 */ WORD   cbReserved2;
-          /* 00000034 */ LPBYTE lpReserved2;
-          /* 00000038 */ HANDLE hStdInput;
-          /* 0000003C */ HANDLE hStdOutput;
-          /* 00000040 */ HANDLE hStdError;
-        } STARTUPINFOA, *LPSTARTUPINFOA;
-
-    """
-    # TODO: fill with relevant values
-    # for now, struct is just a placeholder
-    cb = 0x0
-    lpReserved = 0x0
-    lpDesktop = 0x0
-    lpTitle = 0x0
-    dwX = 0x0
-    dwY = 0x0
-    dwXSize = 0x0
-    dwYSize = 0x0
-    dwXCountChars = 0x0
-    dwYCountChars = 0x0
-    dwFillAttribute = 0x0
-    dwFlags = 0x0
-    wShowWindow = 0x0
-    cbReserved2 = 0x0
-    lpReserved2 = 0x0
-    hStdInput = 0x0
-    hStdOutput = 0x0
-    hStdError = 0x0
-
-    def pack(self):
-        return struct.pack('IIIIIIIIIIIIHHIIII',
-                self.cb,
-                self.lpReserved,
-                self.lpDesktop,
-                self.lpTitle,
-                self.dwX,
-                self.dwY,
-                self.dwXSize,
-                self.dwYSize,
-                self.dwXCountChars,
-                self.dwYCountChars,
-                self.dwFillAttribute,
-                self.dwFlags,
-                self.wShowWindow,
-                self.cbReserved2,
-                self.lpReserved2,
-                self.hStdInput,
-                self.hStdOutput,
-                self.hStdError)
-
-
-def kernel32_GetStartupInfo(jitter, funcname, set_str):
-    """
-        void GetStartupInfo(
-          LPSTARTUPINFOW lpStartupInfo
-        );
-
-        Retrieves the contents of the STARTUPINFO structure that was specified
-        when the calling process was created.
-
-        https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getstartupinfow
-
-    """
-    ret_ad, args = jitter.func_args_stdcall(["ptr"])
-    jitter.vm.set_mem(args.ptr, startupinfo().pack())
-    jitter.func_ret_stdcall(ret_ad, args.ptr)
-
-
-def kernel32_GetStartupInfoA(jitter):
-    kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetStartupInfoW(jitter):
-    kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-def kernel32_GetCurrentThreadId(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, 0x113377)
-
-
-def kernel32_InitializeCriticalSection(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(["lpcritic"])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def user32_GetSystemMetrics(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["nindex"])
-
-    ret = 0
-    if args.nindex in [0x2a, 0x4a]:
-        ret = 0
-    else:
-        raise ValueError('unimpl index')
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def wsock32_WSAStartup(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["version", "pwsadata"])
-    jitter.vm.set_mem(args.pwsadata, b"\x01\x01\x02\x02WinSock 2.0\x00")
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def get_current_filetime():
-    """
-    Get current filetime
-    https://msdn.microsoft.com/en-us/library/ms724228
-    """
-    curtime = winobjs.current_datetime
-    unixtime = int(time.mktime(curtime.timetuple()))
-    filetime = (int(unixtime * 1000000 + curtime.microsecond) * 10 +
-                DATE_1601_TO_1970)
-    return filetime
-
-
-def unixtime_to_filetime(unixtime):
-    """
-    Convert unixtime to filetime
-    https://msdn.microsoft.com/en-us/library/ms724228
-    """
-    return (unixtime * 10000000) + DATE_1601_TO_1970
-
-
-def filetime_to_unixtime(filetime):
-    """
-    Convert filetime to unixtime
-    # https://msdn.microsoft.com/en-us/library/ms724228
-    """
-    return int((filetime - DATE_1601_TO_1970) // 10000000)
-
-
-def datetime_to_systemtime(curtime):
-
-    s = struct.pack('HHHHHHHH',
-                    curtime.year,      # year
-                    curtime.month,     # month
-                    curtime.weekday(), # dayofweek
-                    curtime.day,       # day
-                    curtime.hour,      # hour
-                    curtime.minute ,   # minutes
-                    curtime.second,    # seconds
-                    int(curtime.microsecond // 1000),  # millisec
-                    )
-    return s
-
-
-def kernel32_GetSystemTimeAsFileTime(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["lpSystemTimeAsFileTime"])
-
-    current_filetime = get_current_filetime()
-    filetime = struct.pack('II',
-                           current_filetime & 0xffffffff,
-                           (current_filetime>>32) & 0xffffffff)
-
-    jitter.vm.set_mem(args.lpSystemTimeAsFileTime, filetime)
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_GetLocalTime(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["lpsystemtime"])
-    systemtime = datetime_to_systemtime(winobjs.current_datetime)
-    jitter.vm.set_mem(args.lpsystemtime, systemtime)
-    jitter.func_ret_stdcall(ret_ad, args.lpsystemtime)
-
-
-def kernel32_GetSystemTime(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["lpsystemtime"])
-    systemtime = datetime_to_systemtime(winobjs.current_datetime)
-    jitter.vm.set_mem(args.lpsystemtime, systemtime)
-    jitter.func_ret_stdcall(ret_ad, args.lpsystemtime)
-
-
-def kernel32_CreateFileMapping(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["hfile", "lpattr", "flprotect",
-                                             "dwmaximumsizehigh",
-                                             "dwmaximumsizelow", "lpname"])
-
-    if args.hfile == 0xffffffff:
-        # Create null mapping
-        if args.dwmaximumsizehigh:
-            raise NotImplementedError("Untested case")
-        hmap = StringIO("\x00" * args.dwmaximumsizelow)
-        hmap_handle = winobjs.handle_pool.add('filemem', hmap)
-
-        ret = winobjs.handle_pool.add('filemapping', hmap_handle)
-    else:
-        if not args.hfile in winobjs.handle_pool:
-            raise ValueError('unknown handle')
-        ret = winobjs.handle_pool.add('filemapping', args.hfile)
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_CreateFileMappingA(jitter):
-    kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_CreateFileMappingW(jitter):
-    kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_MapViewOfFile(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hfile", "flprotect",
-                                             "dwfileoffsethigh",
-                                             "dwfileoffsetlow",
-                                             "length"])
-
-    if not args.hfile in winobjs.handle_pool:
-        raise ValueError('unknown handle')
-    hmap = winobjs.handle_pool[args.hfile]
-    if not hmap.info in winobjs.handle_pool:
-        raise ValueError('unknown file handle')
-
-    hfile_o = winobjs.handle_pool[hmap.info]
-    fd = hfile_o.info
-    fd.seek((args.dwfileoffsethigh << 32) | args.dwfileoffsetlow)
-    data = fd.read(args.length) if args.length else fd.read()
-    length = len(data)
-
-    log.debug('MapViewOfFile len: %x', len(data))
-
-    if not args.flprotect in ACCESS_DICT:
-        raise ValueError('unknown access dw!')
-
-    alloc_addr = winobjs.heap.alloc(jitter, len(data))
-    jitter.vm.set_mem(alloc_addr, data)
-
-    winobjs.handle_mapped[alloc_addr] = (hfile_o, args.dwfileoffsethigh,
-                                         args.dwfileoffsetlow, length)
-
-    jitter.func_ret_stdcall(ret_ad, alloc_addr)
-
-
-def kernel32_UnmapViewOfFile(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['ad'])
-
-    if not args.ad in winobjs.handle_mapped:
-        raise NotImplementedError("Untested case")
-    """
-    hfile_o, dwfileoffsethigh, dwfileoffsetlow, length = winobjs.handle_mapped[ad]
-    off = (dwfileoffsethigh<<32) | dwfileoffsetlow
-    s = jitter.vm.get_mem(ad, length)
-    hfile_o.info.seek(off)
-    hfile_o.info.write(s)
-    hfile_o.info.close()
-    """
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_GetDriveType(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(['pathname'])
-
-    p = get_str(args.pathname)
-    p = p.upper()
-
-    log.debug('Drive: %r', p)
-
-    ret = 0
-    if p[0] == "C":
-        ret = 3
-
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_GetDriveTypeA(jitter):
-    kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_GetDriveTypeW(jitter):
-    kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_GetDiskFreeSpace(jitter, funcname, get_str):
-    ret_ad, args = jitter.func_args_stdcall(["lprootpathname",
-                                             "lpsectorpercluster",
-                                             "lpbytespersector",
-                                             "lpnumberoffreeclusters",
-                                             "lptotalnumberofclusters"])
-    jitter.vm.set_u32(args.lpsectorpercluster, 8)
-    jitter.vm.set_u32(args.lpbytespersector, 0x200)
-    jitter.vm.set_u32(args.lpnumberoffreeclusters, 0x222222)
-    jitter.vm.set_u32(args.lptotalnumberofclusters, 0x333333)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_GetDiskFreeSpaceA(jitter):
-    kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
-
-
-def kernel32_GetDiskFreeSpaceW(jitter):
-    kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
-
-
-def kernel32_VirtualQuery(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["ad", "lpbuffer", "dwl"])
-
-    all_mem = jitter.vm.get_all_memory()
-    found = None
-    for basead, m in viewitems(all_mem):
-        if basead <= args.ad < basead + m['size']:
-            found = args.ad, m
-            break
-    if not found:
-        raise ValueError('cannot find mem', hex(args.ad))
-
-    if args.dwl != 0x1c:
-        raise ValueError('strange mem len', hex(args.dwl))
-    s = struct.pack('IIIIIII',
-                    args.ad,
-                    basead,
-                    ACCESS_DICT_INV[m['access']],
-                    m['size'],
-                    0x1000,
-                    ACCESS_DICT_INV[m['access']],
-                    0x01000000)
-    jitter.vm.set_mem(args.lpbuffer, s)
-    jitter.func_ret_stdcall(ret_ad, args.dwl)
-
-
-def kernel32_GetProcessAffinityMask(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hprocess",
-                                             "procaffmask",
-                                             "systemaffmask"])
-    jitter.vm.set_u32(args.procaffmask, 1)
-    jitter.vm.set_u32(args.systemaffmask, 1)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def msvcrt_rand(jitter):
-    ret_ad, _ = jitter.func_args_cdecl(0)
-    jitter.func_ret_stdcall(ret_ad, 0x666)
-
-def msvcrt_srand(jitter):
-    ret_ad, _ = jitter.func_args_cdecl(['seed'])
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-def msvcrt_wcslen(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["pwstr"])
-    s = get_win_str_w(jitter, args.pwstr)
-    jitter.func_ret_cdecl(ret_ad, len(s))
-
-def kernel32_SetFilePointer(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwnd", "dinstance",
-                                             "p_dinstance_high",
-                                             "movemethod"])
-
-    if args.hwnd == winobjs.module_cur_hwnd:
-        pass
-    elif args.hwnd in winobjs.handle_pool:
-        pass
-    else:
-        raise ValueError('unknown hwnd!')
-
-    # data = None
-    if args.hwnd in winobjs.files_hwnd:
-        winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(args.dinstance, args.movemethod)
-    elif args.hwnd in winobjs.handle_pool:
-        wh = winobjs.handle_pool[args.hwnd]
-        wh.info.seek(args.dinstance, args.movemethod)
-    else:
-        raise ValueError('unknown filename')
-    jitter.func_ret_stdcall(ret_ad, args.dinstance)
-
-
-def kernel32_SetFilePointerEx(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwnd", "dinstance_l",
-                                             "dinstance_h",
-                                             "pnewfileptr",
-                                             "movemethod"])
-    dinstance = args.dinstance_l | (args.dinstance_h << 32)
-    if dinstance:
-        raise ValueError('Not implemented')
-    if args.pnewfileptr:
-        raise ValueError('Not implemented')
-    if args.hwnd == winobjs.module_cur_hwnd:
-        pass
-    elif args.hwnd in winobjs.handle_pool:
-        pass
-    else:
-        raise ValueError('unknown hwnd!')
-
-    # data = None
-    if args.hwnd in winobjs.files_hwnd:
-        winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(dinstance, args.movemethod)
-    elif args.hwnd in winobjs.handle_pool:
-        wh = winobjs.handle_pool[args.hwnd]
-        wh.info.seek(dinstance, args.movemethod)
-    else:
-        raise ValueError('unknown filename')
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_SetEndOfFile(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['hwnd'])
-    if args.hwnd in winobjs.handle_pool:
-        wh = winobjs.handle_pool[args.hwnd]
-        wh.info.seek(0, 2)
-    else:
-        raise ValueError('unknown filename')
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_FlushFileBuffers(jitter):
-    ret_ad, args = jitter.func_args_stdcall(['hwnd'])
-    if args.hwnd in winobjs.handle_pool:
-        pass
-    else:
-        raise ValueError('unknown filename')
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_WriteFile(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwnd", "lpbuffer",
-                                             "nnumberofbytestowrite",
-                                             "lpnumberofbyteswrite",
-                                             "lpoverlapped"])
-    data = jitter.vm.get_mem(args.lpbuffer, args.nnumberofbytestowrite)
-
-    if args.hwnd == winobjs.module_cur_hwnd:
-        pass
-    elif args.hwnd in winobjs.handle_pool:
-        pass
-    else:
-        raise ValueError('unknown hwnd!')
-
-    if args.hwnd in winobjs.files_hwnd:
-        winobjs.files_hwnd[winobjs.module_cur_hwnd].write(data)
-    elif args.hwnd in winobjs.handle_pool:
-        wh = winobjs.handle_pool[args.hwnd]
-        wh.info.write(data)
-    else:
-        raise ValueError('unknown filename')
-
-    if (args.lpnumberofbyteswrite):
-        jitter.vm.set_u32(args.lpnumberofbyteswrite, len(data))
-
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def user32_IsCharUpperA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["c"])
-    ret = 0 if args.c & 0x20 else 1
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def user32_IsCharLowerA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["c"])
-    ret = 1 if args.c & 0x20 else 0
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-
-def kernel32_GetSystemDefaultLangID(jitter):
-    ret_ad, _ = jitter.func_args_stdcall(0)
-    jitter.func_ret_stdcall(ret_ad, 0x409)  # encglish
-
-
-def msvcrt_malloc(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["msize"])
-    addr = winobjs.heap.alloc(jitter, args.msize)
-    jitter.func_ret_cdecl(ret_ad, addr)
-
-
-def msvcrt_free(jitter):
-    ret_ad, _ = jitter.func_args_cdecl(["ptr"])
-    jitter.func_ret_cdecl(ret_ad, 0)
-
-
-def msvcrt_fseek(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['stream', 'offset', 'orig'])
-    fd = jitter.vm.get_u32(args.stream + 0x10)
-
-    if not fd in winobjs.handle_pool:
-        raise NotImplementedError("Untested case")
-    o = winobjs.handle_pool[fd]
-    o.info.seek(args.offset, args.orig)
-    jitter.func_ret_cdecl(ret_ad, 0)
-
-
-def msvcrt_ftell(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["stream"])
-    fd = jitter.vm.get_u32(args.stream + 0x10)
-
-    if not fd in winobjs.handle_pool:
-        raise NotImplementedError("Untested case")
-    o = winobjs.handle_pool[fd]
-    off = o.info.tell()
-    jitter.func_ret_cdecl(ret_ad, off)
-
-
-def msvcrt_rewind(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["stream"])
-    fd = jitter.vm.get_u32(args.stream + 0x10)
-    if not fd in winobjs.handle_pool:
-        raise NotImplementedError("Untested case")
-    o = winobjs.handle_pool[fd]
-    # off = o.info.seek(0, 0)
-    jitter.func_ret_cdecl(ret_ad, 0)
-
-
-def msvcrt_fread(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["buf", "size", "nmemb", "stream"])
-    fd = jitter.vm.get_u32(args.stream + 0x10)
-    if not fd in winobjs.handle_pool:
-        raise NotImplementedError("Untested case")
-
-    data = winobjs.handle_pool[fd].info.read(args.size * args.nmemb)
-    jitter.vm.set_mem(args.buf, data)
-    jitter.func_ret_cdecl(ret_ad, args.nmemb)
-
-
-def msvcrt_fwrite(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["buf", "size", "nmemb", "stream"])
-    fd = jitter.vm.get_u32(args.stream + 0x10)
-    if not fd in winobjs.handle_pool:
-        raise NotImplementedError("Unknown file handle!")
-
-    data = jitter.vm.get_mem(args.buf, args.size*args.nmemb)
-    winobjs.handle_pool[fd].info.write(data)
-    jitter.func_ret_cdecl(ret_ad, args.nmemb)
-
-
-def msvcrt_fclose(jitter):
-    ret_ad, args = jitter.func_args_cdecl(['stream'])
-    fd = jitter.vm.get_u32(args.stream + 0x10)
-
-    if not fd in winobjs.handle_pool:
-        raise NotImplementedError("Untested case")
-    o = winobjs.handle_pool[fd]
-    # off = o.info.close()
-    jitter.func_ret_cdecl(ret_ad, 0)
-
-
-def msvcrt_atexit(jitter):
-    ret_ad, _ = jitter.func_args_cdecl(["func"])
-    jitter.func_ret_cdecl(ret_ad, 0)
-
-
-def user32_MessageBoxA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["hwnd", "lptext",
-                                             "lpcaption", "utype"])
-
-    text = get_win_str_a(jitter, args.lptext)
-    caption = get_win_str_a(jitter, args.lpcaption)
-
-    log.info('Caption: %r Text: %r', caption, text)
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def kernel32_myGetTempPath(jitter, set_str):
-    ret_ad, args = jitter.func_args_stdcall(["l", "buf"])
-    l = 'c:\\temp\\'
-    if len(l) < args.l:
-        set_str(args.buf, l)
-    jitter.func_ret_stdcall(ret_ad, len(l))
-
-
-def kernel32_GetTempPathA(jitter):
-    kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_a(jitter, addr, value))
-
-
-def kernel32_GetTempPathW(jitter):
-    kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_w(jitter, addr, value))
-
-
-temp_num = 0
-
-
-def kernel32_GetTempFileNameA(jitter):
-    global temp_num
-    ret_ad, args = jitter.func_args_stdcall(["path", "ext", "unique", "buf"])
-
-    temp_num += 1
-    ext = get_win_str_a(jitter, args.ext) if args.ext else 'tmp'
-    path = get_win_str_a(jitter, args.path) if args.path else "xxx"
-    fname = path + "\\" + "temp%.4d" % temp_num + "." + ext
-    jitter.vm.set_mem(args.buf, fname.encode('utf-8'))
-
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-class win32_find_data(object):
-    fileattrib = 0
-    creationtime = 0
-    lastaccesstime = 0
-    lastwritetime = 0
-    filesizehigh = 0
-    filesizelow = 0
-    dwreserved0 = 0
-    dwreserved1 = 0x1337beef
-    cfilename = ""
-    alternamefilename = ""
-
-    def __init__(self, **kargs):
-        for k, v in viewitems(kargs):
-            setattr(self, k, v)
-
-    def toStruct(self, encode_str=encode_win_str_w):
-        s = struct.pack('=IQQQIIII',
-                        self.fileattrib,
-                        self.creationtime,
-                        self.lastaccesstime,
-                        self.lastwritetime,
-                        self.filesizehigh,
-                        self.filesizelow,
-                        self.dwreserved0,
-                        self.dwreserved1)
-        fname = encode_str(self.cfilename) + b'\x00' * MAX_PATH
-        fname = fname[:MAX_PATH]
-        s += fname
-        fname = encode_str(self.alternamefilename) + b'\x00' * 14
-        fname = fname[:14]
-        s += fname
-        return s
-
-
-class find_data_mngr(object):
-
-    def __init__(self):
-        self.patterns = {}
-        self.flist = []
-        # handle number -> (flist index, current index in list)
-        self.handles = {}
-
-    def add_list(self, pattern, flist):
-        index = len(self.flist)
-        self.flist.append(flist)
-
-        self.patterns[pattern] = index
-
-    def findfirst(self, pattern):
-        assert(pattern in self.patterns)
-        findex = self.patterns[pattern]
-        h = len(self.handles) + 1
-        self.handles[h] = [findex, 0]
-        return h
-
-    def findnext(self, h):
-        assert(h in self.handles)
-        findex, index = self.handles[h]
-        if index >= len(self.flist[findex]):
-            return None
-        fname = self.flist[findex][index]
-        self.handles[h][1] += 1
-
-        return fname
-
-def my_FindFirstFile(jitter, pfilepattern, pfindfiledata, get_win_str, encode_str):
-    filepattern = get_win_str(jitter, pfilepattern)
-    h = winobjs.find_data.findfirst(filepattern)
-
-    fname = winobjs.find_data.findnext(h)
-    fdata = win32_find_data(cfilename=fname)
-
-    jitter.vm.set_mem(pfindfiledata, fdata.toStruct(encode_str=encode_str))
-    return h
-
-def kernel32_FindFirstFileA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"])
-    h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata,
-                           get_win_str_a, encode_win_str_a)
-    jitter.func_ret_stdcall(ret_ad, h)
-
-def kernel32_FindFirstFileW(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"])
-    h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata,
-                           get_win_str_w, encode_win_str_w)
-    jitter.func_ret_stdcall(ret_ad, h)
-
-def kernel32_FindFirstFileExA(jitter):
-    ret_ad, args = jitter.func_args_stdcall([
-        "lpFileName",
-        "fInfoLevelId",
-        "lpFindFileData",
-        "fSearchOp",
-        "lpSearchFilter",
-        "dwAdditionalFlags"])
-    h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData,
-                         get_win_str_a, encode_win_str_a)
-    jitter.func_ret_stdcall(ret_ad, h)
-
-def kernel32_FindFirstFileExW(jitter):
-    ret_ad, args = jitter.func_args_stdcall([
-        "lpFileName",
-        "fInfoLevelId",
-        "lpFindFileData",
-        "fSearchOp",
-        "lpSearchFilter",
-        "dwAdditionalFlags"])
-    h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData,
-                         get_win_str_w, encode_win_str_w)
-    jitter.func_ret_stdcall(ret_ad, h)
-
-def my_FindNextFile(jitter, encode_str):
-    ret_ad, args = jitter.func_args_stdcall(["handle", "pfindfiledata"])
-    fname = winobjs.find_data.findnext(args.handle)
-    if fname is None:
-        winobjs.lastwin32error = 0x12 # ERROR_NO_MORE_FILES
-        ret = 0
-    else:
-        ret = 1
-        fdata = win32_find_data(cfilename=fname)
-        jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct(encode_str=encode_str))
-    jitter.func_ret_stdcall(ret_ad, ret)
-
-kernel32_FindNextFileA = lambda jitter: my_FindNextFile(jitter, encode_win_str_a)
-kernel32_FindNextFileW = lambda jitter: my_FindNextFile(jitter, encode_win_str_w)
-
-def kernel32_GetNativeSystemInfo(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["sys_ptr"])
-    sysinfo = systeminfo()
-    jitter.vm.set_mem(args.sys_ptr, sysinfo.pack())
-    jitter.func_ret_stdcall(ret_ad, 0)
-
-
-def raw2guid(r):
-    o = struct.unpack('IHHHBBBBBB', r)
-    return '{%.8X-%.4X-%.4X-%.4X-%.2X%.2X%.2X%.2X%.2X%.2X}' % o
-
-
-digs = string.digits + string.ascii_lowercase
-
-
-def int2base(x, base):
-    if x < 0:
-        sign = -1
-    elif x == 0:
-        return '0'
-    else:
-        sign = 1
-    x *= sign
-    digits = []
-    while x:
-        digits.append(digs[x % base])
-        x /= base
-    if sign < 0:
-        digits.append('-')
-    digits.reverse()
-    return ''.join(digits)
-
-
-def msvcrt__ultow(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["value", "p", "radix"])
-
-    value = args.value & 0xFFFFFFFF
-    if not args.radix in [10, 16, 20]:
-        raise ValueError("Not tested")
-    s = int2base(value, args.radix)
-    set_win_str_w(jitter, args.p, s)
-    jitter.func_ret_cdecl(ret_ad, args.p)
-
-
-def msvcrt_myfopen(jitter, get_str):
-    ret_ad, args = jitter.func_args_cdecl(["pfname", "pmode"])
-
-    fname = get_str(args.pfname)
-    rw = get_str(args.pmode)
-    log.info("fopen %r, %r", fname, rw)
-
-    if rw in ['r', 'rb', 'wb+','wb','wt']:
-        sb_fname = windows_to_sbpath(fname)
-        h = open(sb_fname, rw)
-        eax = winobjs.handle_pool.add(sb_fname, h)
-        dwsize = 0x20
-        alloc_addr = winobjs.heap.alloc(jitter, dwsize)
-        pp = pck32(0x11112222) + pck32(0) + pck32(0) + pck32(0) + pck32(eax)
-        jitter.vm.set_mem(alloc_addr, pp)
-
-    else:
-        raise ValueError('unknown access mode %s' % rw)
-
-    jitter.func_ret_cdecl(ret_ad, alloc_addr)
-
-
-def msvcrt__wfopen(jitter):
-    msvcrt_myfopen(jitter, lambda addr:get_win_str_w(jitter, addr))
-
-
-def msvcrt_fopen(jitter):
-    msvcrt_myfopen(jitter, lambda addr:get_win_str_a(jitter, addr))
-
-
-def msvcrt_strlen(jitter):
-    ret_ad, args = jitter.func_args_cdecl(["src"])
-
-    s = get_win_str_a(jitter, args.src)
-    jitter.func_ret_cdecl(ret_ad, len(s))
-
-
-def kernel32_QueryPerformanceCounter(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["lpPerformanceCount"])
-    jitter.vm.set_mem(args.lpPerformanceCount, struct.pack('<Q', 0x1))
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_InitializeCriticalSectionEx(jitter):
-    '''
-      LPCRITICAL_SECTION lpCriticalSection,
-      DWORD              dwSpinCount,
-      DWORD              Flags
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["lpCriticalSection", "dwSpinCount", "Flags"])
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_EnterCriticalSection(jitter):
-    '''
-    void EnterCriticalSection(
-      LPCRITICAL_SECTION lpCriticalSection
-    );
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["lpCriticalSection"])
-    jitter.func_ret_stdcall(ret_ad, 0x0)
-
-
-def kernel32_LeaveCriticalSection(jitter):
-    '''
-    void LeaveCriticalSection(
-      LPCRITICAL_SECTION lpCriticalSection
-    );
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["lpCriticalSection"])
-    jitter.func_ret_stdcall(ret_ad, 0x0)
-
-
-class FLS(object):
-    def __init__(self):
-        self.slots = []
-
-    def kernel32_FlsAlloc(self, jitter):
-        '''
-        DWORD FlsAlloc(
-          PFLS_CALLBACK_FUNCTION lpCallback
-        );
-        '''
-        ret_ad, args = jitter.func_args_stdcall(["lpCallback"])
-        index = len(self.slots)
-        self.slots.append(0x0)
-        jitter.func_ret_stdcall(ret_ad, index)
-
-    def kernel32_FlsSetValue(self, jitter):
-        '''
-        BOOL FlsSetValue(
-          DWORD dwFlsIndex,
-          PVOID lpFlsData
-        );
-        '''
-        ret_ad, args = jitter.func_args_stdcall(["dwFlsIndex", "lpFlsData"])
-        self.slots[args.dwFlsIndex] = args.lpFlsData
-        jitter.func_ret_stdcall(ret_ad, 1)
-
-    def kernel32_FlsGetValue(self, jitter):
-        '''
-        PVOID FlsGetValue(
-          DWORD dwFlsIndex
-        );
-        '''
-        ret_ad, args = jitter.func_args_stdcall(["dwFlsIndex"])
-        jitter.func_ret_stdcall(ret_ad, self.slots[args.dwFlsIndex])
-
-fls = FLS()
-
-
-def kernel32_GetProcessHeap(jitter):
-    '''
-    HANDLE GetProcessHeap();
-    '''
-    ret_ad, args = jitter.func_args_stdcall([])
-    hHeap = 0x67676767
-    jitter.func_ret_stdcall(ret_ad, hHeap)
-
-
-STD_INPUT_HANDLE = 0xfffffff6
-STD_OUTPUT_HANDLE = 0xfffffff5
-STD_ERROR_HANDLE = 0xfffffff4
-
-
-def kernel32_GetStdHandle(jitter):
-    '''
-    HANDLE WINAPI GetStdHandle(
-      _In_ DWORD nStdHandle
-    );
-
-    STD_INPUT_HANDLE (DWORD)-10
-    The standard input device. Initially, this is the console input buffer, CONIN$.
-
-    STD_OUTPUT_HANDLE (DWORD)-11
-    The standard output device. Initially, this is the active console screen buffer, CONOUT$.
-
-    STD_ERROR_HANDLE (DWORD)-12
-    The standard error device. Initially, this is the active console screen buffer, CONOUT$.
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["nStdHandle"])
-    jitter.func_ret_stdcall(ret_ad, {
-        STD_OUTPUT_HANDLE: 1,
-        STD_ERROR_HANDLE: 2,
-        STD_INPUT_HANDLE: 3,
-    }[args.nStdHandle])
-
-
-FILE_TYPE_UNKNOWN = 0x0000
-FILE_TYPE_CHAR = 0x0002
-
-
-def kernel32_GetFileType(jitter):
-    '''
-    DWORD GetFileType(
-      HANDLE hFile
-    );
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["hFile"])
-    jitter.func_ret_stdcall(ret_ad, {
-        # STD_OUTPUT_HANDLE
-        1: FILE_TYPE_CHAR,
-        # STD_ERROR_HANDLE
-        2: FILE_TYPE_CHAR,
-        # STD_INPUT_HANDLE
-        3: FILE_TYPE_CHAR,
-    }.get(args.hFile, FILE_TYPE_UNKNOWN))
-
-
-def kernel32_IsProcessorFeaturePresent(jitter):
-    '''
-    BOOL IsProcessorFeaturePresent(
-      DWORD ProcessorFeature
-    );
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["ProcessorFeature"])
-    jitter.func_ret_stdcall(ret_ad, {
-        # PF_ARM_64BIT_LOADSTORE_ATOMIC
-        25: False,
-        # PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE
-        24: False,
-        # PF_ARM_EXTERNAL_CACHE_AVAILABLE
-        26: False,
-        # PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE
-        27: False,
-        # PF_ARM_VFP_32_REGISTERS_AVAILABLE
-        18: False,
-        # PF_3DNOW_INSTRUCTIONS_AVAILABLE
-        7: False,
-        # PF_CHANNELS_ENABLED
-        16: True,
-        # PF_COMPARE_EXCHANGE_DOUBLE
-        2: False,
-        # PF_COMPARE_EXCHANGE128
-        14: False,
-        # PF_COMPARE64_EXCHANGE128
-        15: False,
-        # PF_FASTFAIL_AVAILABLE
-        23: False,
-        # PF_FLOATING_POINT_EMULATED
-        1: False,
-        # PF_FLOATING_POINT_PRECISION_ERRATA
-        0: True,
-        # PF_MMX_INSTRUCTIONS_AVAILABLE
-        3: True,
-        # PF_NX_ENABLED
-        12: True,
-        # PF_PAE_ENABLED
-        9: True,
-        # PF_RDTSC_INSTRUCTION_AVAILABLE
-        8: True,
-        # PF_RDWRFSGSBASE_AVAILABLE
-        22: True,
-        # PF_SECOND_LEVEL_ADDRESS_TRANSLATION
-        20: True,
-        # PF_SSE3_INSTRUCTIONS_AVAILABLE
-        13: True,
-        # PF_VIRT_FIRMWARE_ENABLED
-        21: False,
-        # PF_XMMI_INSTRUCTIONS_AVAILABLE
-        6: True,
-        # PF_XMMI64_INSTRUCTIONS_AVAILABLE
-        10: True,
-        # PF_XSAVE_ENABLED
-        17: False,
-    }[args.ProcessorFeature])
-
-
-def kernel32_GetACP(jitter):
-    '''
-    UINT GetACP();
-    '''
-    ret_ad, args = jitter.func_args_stdcall([])
-    # Windows-1252: Latin 1 / Western European  Superset of ISO-8859-1 (without C1 controls).
-    jitter.func_ret_stdcall(ret_ad, 1252)
-
-
-# ref: https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
-VALID_CODE_PAGES = {
-    37,437,500,708,709,710,720,737,775,850,852,855,857,858,860,861,862,863,864,865,866,869,870,874,875,
-    932,936,949,950,1026,1047,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1200,1201,1250,1251,1252,
-    1253,1254,1255,1256,1257,1258,1361,10000,10001,10002,10003,10004,10005,10006,10007,10008,10010,10017,
-    10021,10029,10079,10081,10082,12000,12001,20000,20001,20002,20003,20004,20005,20105,20106,20107,20108,
-    20127,20261,20269,20273,20277,20278,20280,20284,20285,20290,20297,20420,20423,20424,20833,20838,20866,
-    20871,20880,20905,20924,20932,20936,20949,21025,21027,21866,28591,28592,28593,28594,28595,28596,28597,
-    28598,28599,28603,28605,29001,38598,50220,50221,50222,50225,50227,50229,50930,50931,50933,50935,50936,
-    50937,50939,51932,51936,51949,51950,52936,54936,57002,57003,57004,57005,57006,57007,57008,57009,57010,
-    57011,65000,65001
-}
-
-
-def kernel32_IsValidCodePage(jitter):
-    '''
-    BOOL IsValidCodePage(
-      UINT CodePage
-    );
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["CodePage"])
-    jitter.func_ret_stdcall(ret_ad, args.CodePage in VALID_CODE_PAGES)
-
-
-def kernel32_GetCPInfo(jitter):
-    '''
-    BOOL GetCPInfo(
-      UINT     CodePage,
-      LPCPINFO lpCPInfo
-    );
-    '''
-    ret_ad, args = jitter.func_args_stdcall(["CodePage", "lpCPInfo"])
-    assert args.CodePage == 1252
-    # ref: http://www.rensselaer.org/dept/cis/software/g77-mingw32/include/winnls.h
-    #define MAX_LEADBYTES       12
-    #define MAX_DEFAULTCHAR	2
-    jitter.vm.set_mem(args.lpCPInfo, struct.pack('<I', 0x1) + b'??' + b'\x00' * 12)
-    jitter.func_ret_stdcall(ret_ad, 1)
-
-
-def kernel32_GetStringTypeW(jitter):
-    """
-        BOOL GetStringTypeW(
-          DWORD                         dwInfoType,
-          _In_NLS_string_(cchSrc)LPCWCH lpSrcStr,
-          int                           cchSrc,
-          LPWORD                        lpCharType
-        );
-
-        Retrieves character type information for the characters in the specified
-        Unicode source string. For each character in the string, the function
-        sets one or more bits in the corresponding 16-bit element of the output
-        array. Each bit identifies a given character type, for example, letter,
-        digit, or neither.
-
-    """
-    # These types support ANSI C and POSIX (LC_CTYPE) character typing
-    # functions.A bitwise-OR of these values is retrieved in the array in the
-    # output buffer when dwInfoType is set to CT_CTYPE1. For DBCS locales, the
-    # type attributes apply to both narrow characters and wide characters. The
-    # Japanese hiragana and katakana characters, and the kanji ideograph
-    # characters all have the C1_ALPHA attribute.
-    CT_TYPE1 = 0x01
-    # TODO handle other types of information
-    # (CT_TYPE2, CT_TYPE3)
-    # for now, they raise NotImplemented
-    CT_TYPE2 = 0x02
-    CT_TYPE3 = 0x03
-
-    C1_UPPER   = 0x0001  # Uppercase
-    C1_LOWER   = 0x0002  # Lowercase
-    C1_DIGIT   = 0x0004  # Decimal digits
-    C1_SPACE   = 0x0008  # Space characters
-    C1_PUNCT   = 0x0010  # Punctuation
-    C1_CNTRL   = 0x0020  # Control characters
-    C1_BLANK   = 0x0040  # Blank characters
-    C1_XDIGIT  = 0x0080  # Hexadecimal digits
-    C1_ALPHA   = 0x0100  # Any linguistic character: alphabetical, syllabary, or ideographic
-    C1_DEFINED = 0x0200  # A defined character, but not one of the other C1_* types
-
-    # the following sets have been generated from the Linux python library curses
-    # e.g., C1_PUNCT_SET = [chr(i) for i in range(256) if curses.ascii.ispunct(chr(i))]
-    C1_PUNCT_SET = ['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',',
-            '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']',
-            '^', '_', '`', '{', '|', '}', '~']
-    C1_CNTRL_SET = ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06',
-            '\x07', '\x08', '\t', '\n', '\x0b', '\x0c', '\r', '\x0e', '\x0f',
-            '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
-            '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
-            '\x7f']
-    C1_BLANK_SET = ['\t', ' ']
-    C1_XDIGIT_SET = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
-            'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f']
-
-    ret, args = jitter.func_args_stdcall(['dwInfoType', 'lpSrcStr', 'cchSrc',
-        'lpCharType'])
-    s = jitter.vm.get_mem(args.lpSrcStr, args.cchSrc).decode("utf-16")
-    if args.dwInfoType == CT_TYPE1:
-        # iterate over characters from the decoded W string
-        for i, c in enumerate(s):
-            # TODO handle non-ascii characters
-            if not c.isascii():
-                continue
-            val = 0
-            if c.isupper():
-                val |= C1_UPPER
-            if c.islower():
-                val |= C1_LOWER
-            if c.isdigit():
-                val |= C1_DIGIT
-            if c.isspace():
-                val |= C1_SPACE
-            if c in C1_PUNCT_SET:
-                val |= C1_PUNCT
-            if c in C1_CNTRL_SET:
-                val |= C1_CNTRL
-            if c in C1_BLANK_SET:
-                val |= C1_BLANK
-            if c in C1_XDIGIT_SET:
-                val |= C1_XDIGIT
-            if c.isalpha():
-                val |= C1_ALPHA
-            if val == 0:
-                val = C1_DEFINED
-            jitter.vm.set_u16(args.lpCharType + i * 2, val)
-    elif args.dwInfoType == CT_TYPE2:
-        raise NotImplemented
-    elif args.dwInfoType == CT_TYPE3:
-        raise NotImplemented
-    else:
-        raise ValueError("CT_TYPE unknown: %i" % args.dwInfoType)
-    jitter.func_ret_stdcall(ret, 1)
-    return True