# -*- coding: cp936 -*-
__author__='ÌìÖ®ÒÝÏÉ'
from winappdbg import EventHandler, Debug
from winappdbg.win32 import *
from ctypes import Structure as Struct
from configobj import ConfigObj
import os
os.chdir(os.path.dirname(__file__))
import psyco
psyco.full()

class lvcolumn(Struct):
    _fields_=[('mask',UINT),
              ('fmt',INT),
              ('cx',INT),
              ('pszText',PVOID),
              ('cchTextMax',INT),
              ('iSubItem',INT),
              ('iOrder',INT),
              ('iImage',INT)]
class lvitem(Struct):
    _fields_=[('mask',UINT),
              ('iItem',INT),
              ('iSubItem',INT),
              ('state',UINT),
              ('stateMask',UINT),
              ('pszText',PVOID),
              ('cchTextMax',INT),
              ('iImage',INT)]
class msgbox(Struct):
    _fields_=[('cbSize',UINT),
              ('hwndOwner',HWND),
              ('hInstance',HINSTANCE),
              ('lpszText',PVOID),
              ('lpszCaption',PVOID),
              ('dwStyle',DWORD),
              ('lpszIcon',PVOID),
              ('dwContextHelpId',DWORD_PTR),
              ('lpfnMsgBoxCallback',PVOID),
              ('dwLanguageId',DWORD)]
class openfilename(Struct):
    _fields_=[('lStructSize',DWORD),
              ('hwndOwner',HWND),
              ('hInstance',HINSTANCE),
              ('lpstrFilter',PVOID),
              ('lpstrCustomFilter',LPSTR),
              ('nMaxCustFilter',DWORD),
              ('nFilterIndex',DWORD),
              ('lpstrFile',LPSTR),
              ('nMaxFile',DWORD),
              ('lpstrFileTitle',LPSTR),
              ('nMaxFileTitle',DWORD),
              ('lpstrInitialDir',PVOID),
              ('lpstrTitle',PVOID),
              ('Flags',DWORD),
              ('nFileOffset',WORD),
              ('nFileExtension',WORD),
              ('lpstrDefExt',PVOID),
              ('lCustData',LPARAM),
              ('lpfnHook',DWORD),
              ('lpTemplateName',PVOID)]

class MyEventHandler( EventHandler ):
    apiHooks = {
        'comdlg32.dll' : [
            ( 'GetOpenFileNameA' , (PVOID,) ),( 'GetSaveFileNameA' , (PVOID,) )
        ],
        'user32.dll' : [
            #  Function            Parameters
            ( 'CreateWindowExA' , (DWORD, PVOID, PVOID, DWORD, INT, INT, INT, INT, HWND, HWND, HANDLE, LPVOID) ),
            ( 'SetWindowTextA' , (HWND, PVOID) ),
            ( 'SendMessageA' , (HWND, UINT, WPARAM, LPARAM) ),
            ( 'AppendMenuA' , (HWND, UINT, UINT, PVOID)),
            ( 'TabbedTextOutA' , (HDC, INT, INT, PVOID, INT, INT, PVOID, INT) ),
            ( 'MessageBoxA' , (HWND, PVOID, PVOID, UINT) ),
            ( 'MessageBoxIndirectA' , (PVOID,) )
        ],
    }
    def pre_GetOpenFileNameA(self, event, ra, lpofn):
        handlefilter(event, lpofn)
    def pre_GetSaveFileNameA(self, event, ra, lpofn):
        handlefilter(event, lpofn)
    def pre_SendMessageA(self, event, ra, hWnd, Msg, wParam, lParam):
        if Msg == 323 :
            replacetext(event, lParam)
        elif Msg == 4123:
            tmp = event.get_process().read_structure(lParam, lvcolumn)
            replacetext(event, tmp.pszText)
        elif Msg == 4103 or Msg == 4102:
            tmp = event.get_process().read_structure(lParam, lvitem)
            if isinstance(tmp.pszText, int):
                replacetext(event, tmp.pszText + (Msg - 4102) * 4)
    def pre_MessageBoxIndirectA(self, event, ra, lpMsgBoxParams):
        tmp = event.get_process().read_structure(lpMsgBoxParams, msgbox)
        replacetext(event, tmp.lpszText)
    def pre_TabbedTextOutA(self, event, ra, hDc, X, Y, lpString, nCount, nTabPositions, TabStopPositions, nTabOrigin):
        replacetext(event, lpString)
    def pre_MessageBoxA(self, event, ra, hWnd, lpText, lpCaption, uType):
        replacetext(event, lpText)
    def pre_AppendMenuA(self, event, ra, hMenu, uFlags, uIDNewItem, lpNewItem):
        replacetext(event, lpNewItem)
    def pre_SetWindowTextA(self, event, ra, hWnd, lpString):
        replacetext(event, lpString)
    def pre_CreateWindowExA( self, event, ra, dwExStyle, lpClassName, lpWindowName,
             dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu,
                                hInstance, lpParam ):
        replacetext(event, lpWindowName)

def handlefilter(event, lpofn):
    process = event.get_process()
    tmp = process.read_structure(lpofn, openfilename).lpstrFilter
    while tmp is not 0:
        string = process.peek_string(tmp)
        if len(string):
            if ja2cn(string) in strs['text']:
                process.write(tmp, strs['text'][ja2cn(string)])
            tmp += len(string) + 1
        else:
            tmp = 0

def replacetext(event, pointer):
    process = event.get_process()
    if process.is_address_writeable(pointer):
        text = process.peek_string(pointer)
        matched = False
        for string in text.split("\r\n"):
            try:
                for target in strs['middle']:
                    if target in string:
                        string = string.replace(target, cn2ja(strs['middle'][target]))
                if string in strs['special']: tobe = strs['special'][string]
                else:
                    tobe = ja2cn(string)
                    if tobe in strs['text'] and len(tobe) >= len(strs['text'][tobe]):
                        tobe = strs['text'][tobe] 
                        matched = True
                    if len(tobe) < len(string): tobe += ''.join(['\r' if len(tobe) < 20 else ' ' for _ in xrange(len(string) - len(tobe))])
                process.write(pointer, tobe)
            except (WindowsError, UnicodeDecodeError, UnicodeEncodeError):
                pass
            finally:
                if not matched:
                    print string
                    for target in strs['special']:
                        if target == string:
                            process.write(pointer, strs['special'][target])
                    for item in strs['prefix']:
                        if string.startswith(cn2ja(item)):
                            process.write(pointer, strs['prefix'][item] + ''.join('\r' for i in xrange(len(item) - len(strs['prefix'][item]))))
                            break
		    for item in strs['suffix']:
		        if string.endswith(cn2ja(item)):
		            process.write(pointer + len(string) - len(item), strs['suffix'][item])
	                    break
            pointer += len(string) + 2

ja2cn = lambda word : word.decode('shift-jis').encode('gbk')
cn2ja = lambda word : word.decode('gbk').encode('shift-jis')

def main():
    global strs
    strs = dict(ConfigObj('Strings.ini'))
    with Debug( MyEventHandler(), bKillOnExit=True) as debug:
        debug.execl('..\\' + strs['config']['binary'])
        debug.loop()

if __name__ == '__main__':
    main()
