Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Unicode support for DDT

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Lothar Pink
    replied
    Demo file: test_ucwrap.bas

    This is a small demo file creating and displaying an unicode-enabled DDT dialog.
    It also displays some japanese characters (but you need MS Mincho installed for seeing them,
    I think this one comes with Win2000 or XP). I haven't used a language file or stringtable
    for the strings in that test file, just a small BinBas of a japanese unicode file.

    (On a side note, I have copied the japanese text from some google result, I don't understand
    japanese )

    Code:
    #COMPILE EXE
    #DIM ALL
    
    #INCLUDE "WIN32API.INC"
    
    MACRO DbgEnter(x) = ! nop
    MACRO DbgLeave(x) = ! nop
    MACRO Dbg(x) = ! nop
    %TEST_UNICODE_ANSI = 0
    
    #INCLUDE "UCWRAP.BI"
    #INCLUDE "UCWRAP.INC"
    
    FUNCTION BinBas() AS STRING
    
        FUNCTION = PEEK$( CODEPTR( BinBas_Data ), 68 )
        EXIT FUNCTION
    
    BinBas_Data:
    !db 255,254,218,048,252,048,184,048,110,048,186,078,023,108,166,094,146,048
    !db 205,083,032,102,087,048,095,048,233,048,243,048,173,048,243,048,176,048
    !db 146,048,076,136,106,048,070,048,181,048,252,048,193,048,168,048,243,048
    !db 184,048,243,048,110,048,229,101,044,103,158,138,072,114
    
    END FUNCTION
    
    CALLBACK FUNCTION TestProc
        LOCAL txt AS STRING
    
        SELECT CASE CBMSG
        CASE %WM_COMMAND
            SELECT CASE CBCTL
            CASE %IDOK
                CONTROL GET TEXT CBHNDL, 1002 TO txt
                
                MSGBOX txt, , UCODE$("Test output")
                
            CASE %IDCANCEL
                DIALOG END CBHNDL
                
            END SELECT
            
        END SELECT
    
    END FUNCTION
    
    
    FUNCTION PBMAIN () AS LONG
        LOCAL hDlg AS LONG
    
        UCWrapper_PatchToUnicode
    
        'msgbox ucode$("patched."), , UCODE$("title")
        
        DIALOG FONT "MS Mincho", 9
    
        DIALOG NEW %HWND_DESKTOP, UCODE$("dialog testa"), , , 200, 100, %WS_POPUP OR %WS_CAPTION OR %WS_SYSMENU, %WS_EX_RTLREADING TO hDlg
        SetWindowLong hDlg, %GWL_EXSTYLE, GetWindowLong(hDlg, %GWL_EXSTYLE) OR %WS_EX_RTLREADING
    
        CONTROL ADD LABEL, hDlg, 1001, BinBas(), 1, 1, 190, 25
        
        CONTROL ADD TEXTBOX, hDlg, 1002, UCODE$("textbox"), 1, 30, 100, 12
        
        CONTROL ADD BUTTON, hDlg, %IDOK, UCODE$("Display"), 100, 80, 45, 15
        CONTROL ADD BUTTON, hDlg, %IDCANCEL, UCODE$("Cancel"), 150, 80, 45, 15
    
        DIALOG SHOW MODAL hDlg CALL TestProc
    
    END FUNCTION

    ------------------


    [This message has been edited by Lothar Pink (edited January 08, 2007).]

    Leave a comment:


  • Lothar Pink
    replied
    Source file UCWRAP.INC

    Code:
    FUNCTION UCWrapper_InsertMenuItem(BYVAL hMenu AS LONG, BYVAL uItem AS DWORD, BYVAL fByPosition AS LONG, BYVAL lpmii AS DWORD) AS LONG
        ' insert menu item call stub
        DbgEnter("UCWrapper_InsertMenuItem")
    
        LOCAL sTxt AS STRING
        LOCAL lRet AS LONG
        LOCAL pmii AS MENUITEMINFO PTR
        LOCAL mii AS MENUITEMINFO
    
        pmii = lpmii
        mii = @pmii
        IF ISFALSE gUCWrapper.lUseUnicode AND ISFALSE mii.fType THEN
            ' transform to ansi
            sTxt = UCWrapper_GetUnicodeSZString(mii.dwTypeData)
            sTxt = ACODE$(sTxt) + $NUL
            mii.dwTypeData = STRPTR(sTxt)
    
        END IF
    
        CALL DWORD gUCWrapper.fp.pInsertMenuItem USING UCWrapper_InsertMenuItem(hMenu, uItem, fByPosition, VARPTR(mii)) TO lRet
    
        DbgLeave("UCWrapper_InsertMenuItem")
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_Dyn_TextOut(BYVAL hdc AS LONG, BYVAL nXStart AS LONG, BYVAL nYStart AS LONG, BYVAL lpString AS DWORD, BYVAL cbString AS LONG) AS LONG
        ' always-unicode-textout for use inside prog (no hooking / patching)
        DbgEnter("UCWrapper_Dyn_TextOut")
        STATIC hLib AS LONG
        STATIC hProc AS LONG
    
        LOCAL sTxt AS STRING
        LOCAL lRet AS LONG
    
        IF hProc = 0 THEN
            hLib = GetModuleHandle("GDI32.DLL")
            hProc = GetProcAddress(hLib, "TextOut" + IIF$(gUCWrapper.lUseUnicode, "W", "A"))
    
        END IF
    
        IF hProc THEN
            IF ISFALSE gUCWrapper.lUseUnicode THEN
                sTxt = ACODE$(UCWrapper_GetUnicodeSZString(lpString)) + $NUL
                CALL DWORD hProc USING UCWrapper_Dyn_TextOut(hdc, nXStart, nYStart, STRPTR(sTxt), cbString) TO lRet
    
            ELSE
                CALL DWORD hProc USING UCWrapper_Dyn_TextOut(hdc, nXStart, nYStart, lpString, cbString) TO lRet
    
            END IF
    
        END IF
    
        DbgLeave("UCWrapper_Dyn_TextOut")
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_Dyn_DrawText(BYVAL hdc AS LONG, BYVAL lpString AS DWORD, BYVAL nCount AS LONG,  BYVAL lpRect AS DWORD, BYVAL uFormat AS DWORD) AS LONG
        ' always-unicode-drawtext for use inside prog (no hooking/patching)
        DbgEnter("UCWrapper_Dyn_DrawText")
    
        STATIC hLib AS LONG
        STATIC hProc AS LONG
    
        LOCAL sTxt AS STRING
        LOCAL lRet AS LONG
    
        IF hProc = 0 THEN
            hLib = GetModuleHandle("USER32.DLL")
            hProc = GetProcAddress(hLib, "DrawText" + IIF$(gUCWrapper.lUseUnicode, "W", "A"))
    
        END IF
    
        IF hProc THEN
            IF ISFALSE gUCWrapper.lUseUnicode THEN
                sTxt = ACODE$(UCWrapper_GetUnicodeSZString(lpString)) + $NUL
                CALL DWORD hProc USING UCWrapper_Dyn_DrawText(hdc, STRPTR(sTxt), nCount, lpRect, uFormat) TO lRet
    
            ELSE
                CALL DWORD hProc USING UCWrapper_Dyn_DrawText(hdc, lpString, nCount, lpRect, uFormat) TO lRet
    
            END IF
    
        END IF
    
        DbgLeave("UCWrapper_Dyn_DrawText")
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_GetUnicodeSZString(BYVAL lpAddress AS DWORD) AS STRING
        ' returns unicode string at lpAddress
        LOCAL pw AS WORD PTR
        LOCAL sRet AS STRING
        DbgEnter("UCWrapper_GetUnicodeSZString")
    
        IF lpAddress THEN
            pw = lpAddress
    
            DO WHILE @pw
                sRet = sRet + MKWRD$(@pw)
    
                pw = pw + 2
    
            LOOP
    
        END IF
    
        DbgLeave("UCWrapper_GetUnicodeSZString")
        FUNCTION = sRet
    END FUNCTION
    
    #IF 0 ' NOT NEEDED
    FUNCTION UCWrapper_MultiByteToWideChar(BYVAL CodePage AS DWORD, BYVAL dwFlags AS DWORD, BYVAL lpMultiByteStr AS DWORD, BYVAL cbMultiByte AS LONG, _
                                           BYVAL lpWideCharStr AS DWORD, BYVAL cchWideChar AS LONG) AS LONG
        ' patches the multibytetowidechar function so it does NO conversion when creating the dialog box template
        DbgEnter("UCWrapper_MultiByteToWideChar")
        LOCAL szStr AS ASCIIZ PTR
        LOCAL sStr AS STRING
        LOCAL lRet AS LONG
    
    
        IF cbMultiByte = -1 THEN
            szStr = lpMultiByteStr
            sStr = @szStr + $NUL + $NUL
    
        ELSE
            sStr = PEEK$(lpMultiByteStr, cbMultiByte)
    
        END IF
    
        lRet = LEN(sStr)
    
        PRINT #1, sStr + $CRLF
    
        IF ISTRUE lpWideCharStr AND ISTRUE cchWideChar THEN
            POKE$ lpWideCharStr, sStr
    
        END IF
    
        DbgLeave("UCWrapper_MultiByteToWideChar")
    
        FUNCTION = lRet
    END FUNCTION
    #ENDIF
    
    FUNCTION UCWrapper_CreateDialogIndirectParam(BYVAL hInstance AS LONG, BYVAL lpTemplate AS DWORD, BYVAL hwndParent AS LONG, BYVAL lpDialogFunc AS DWORD, _
                                                 BYVAL lParamInit AS LONG) AS LONG
        DbgEnter("UCWrapper_CreateDialogIndirectParam")
        LOCAL lLastChar AS LONG
        LOCAL pwChar AS WORD PTR
        LOCAL sTitle AS STRING
    
        LOCAL dwStart AS LONG
        LOCAL dwLen AS LONG
    
        LOCAL lRet AS LONG
    
        ' since PB converts to unicode, we have to re-convert the "ultra-wide-char" title back to wide-char.
        pwChar = lpTemplate + SIZEOF(DLGTEMPLATE) + 4
    
        DO UNTIL @pwChar = 0 AND lLastChar = 0
            IF @pwChar THEN sTitle = sTitle + MKWRD$(@pwChar)
    
            lLastChar = @pwChar
            pwChar = pwChar + 2
    
        LOOP
    
        pwChar = pwChar + 2
        dwStart = pwChar
    
        DO UNTIL @pwChar = 0
            dwLen = dwLen + 2
            pwChar = pwChar + 2
    
        LOOP
    
        sTitle = sTitle + NUL$(2)
        POKE$ lpTemplate + SIZEOF(DLGTEMPLATE) + 4, sTitle
        MoveMemory BYVAL lpTemplate + SIZEOF(DLGTEMPLATE) + 4 + LEN(sTitle) + 0, BYVAL dwStart, dwLen + 2
    
        Dbg("UC: " + FORMAT$(gUCWrapper.lUseUnicode))
        ' no transformation needed
    
        CALL DWORD gUCWrapper.fp.pCreateDialogIndirectParam USING UCWrapper_CreateDialogIndirectParam(hInstance, lpTemplate, hwndParent, lpDialogFunc, _
                   lParamInit) TO lRet
    
        DbgLeave("UCWrapper_CreateDialogIndirectParam")
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_CreateWindowEx(BYVAL dwExStyle AS DWORD, BYVAL lpClassName AS DWORD, BYVAL lpWindowName AS DWORD, BYVAL dwStyle AS DWORD, BYVAL x AS LONG, _
                                      BYVAL y AS LONG, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG, BYVAL hwndParent AS LONG, BYVAL hMenu AS LONG, _
                                      BYVAL hInstance AS LONG, BYVAL lpParam AS LONG) AS LONG
        DbgEnter("UCWrapper_CreateWindowEx")
        LOCAL lRet AS LONG
    
        LOCAL pszClass AS ASCIIZ PTR
        LOCAL ucClassName AS STRING
        LOCAL ansiWindowName AS STRING
    
    
        Dbg("UC: " + FORMAT$(gUCWrapper.lUseUnicode))
    
        IF ISFALSE gUCWrapper.lUseUnicode THEN
            'ansiClassName = ACODE$(UCWrapper_GetUnicodeSZString(lpClassName)) + $NUL
            ansiWindowName = ACODE$(UCWrapper_GetUnicodeSZString(lpWindowName)) + $NUL
    
            CALL DWORD gUCWrapper.fp.pCreateWindowEx USING UCWrapper_CreateWindowEx(dwExStyle, BYVAL lpClassName, STRPTR(ansiWindowName), dwStyle, x, y, _
                       nWidth, nHeight, hwndParent, hMenu, hInstance, lpParam) TO lRet
    
        ELSE
            pszClass = lpClassName
            ucClassName = UCODE$(@pszClass) + NUL$(2)
            CALL DWORD gUCWrapper.fp.pCreateWindowEx USING UCWrapper_CreateWindowEx(dwExStyle, STRPTR(ucClassName), lpWindowName, dwStyle, x, y, _
                       nWidth, nHeight, hwndParent, hMenu, hInstance, lpParam) TO lRet
    
        END IF
    
        DbgLeave("UCWrapper_CreateWindowEx")
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_DispatchMessage(BYVAL lpmsg AS DWORD) AS LONG
        ' no debug code here -> perf.
        LOCAL lRet AS LONG
    
        CALL DWORD gUCWrapper.fp.pDispatchMessage USING UCWrapper_DispatchMessage(lpmsg) TO lRet
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_GetWindowText(BYVAL hwnd AS LONG, BYVAL lpString AS DWORD, BYVAL nMaxCount AS LONG) AS LONG
        DbgEnter("UCWrapper_GetWindowText")
        LOCAL sBuf AS STRING
    
        LOCAL lRet AS LONG
    
        Dbg("UC: " + FORMAT$(gUCWrapper.lUseUnicode))
    
        IF ISFALSE gUCWrapper.lUseUnicode THEN
            sBuf = NUL$(nMaxCount \ 2 - 2)
            CALL DWORD gUCWrapper.fp.pGetWindowText USING UCWrapper_GetWindowText(hwnd, STRPTR(sBuf), nMaxCount) TO lRet
            POKE$ lpString, UCODE$(sBuf) + NUL$(2)
    
        ELSE
            LOCAL hLib AS LONG
            LOCAL hProc AS LONG
    
            hLib = GetModuleHandle("USER32.DLL")
            hProc = GetProcAddress(hLib, "InternalGetWindowText")
    
            IF hProc THEN
                CALL DWORD hProc USING InternalGetWindowText(hwnd, BYVAL lpString, nMaxCount \ 2) TO lRet
    
                IF lRet = 0 THEN
                    CALL DWORD gUCWrapper.fp.pGetWindowText USING UCWrapper_GetWindowText(hwnd, lpString, nMaxCount \ 2) TO lRet
    
                END IF
    
            ELSE
                CALL DWORD gUCWrapper.fp.pGetWindowText USING UCWrapper_GetWindowText(hwnd, lpString, nMaxCount \ 2) TO lRet
    
            END IF
    
        END IF
    
        DbgLeave("UCWrapper_GetWindowText")
    
        FUNCTION = lRet * 2 ' needed so CONTROL GET TEXT gets right number of characters
    END FUNCTION
    
    FUNCTION UCWrapper_GetWindowTextLength(BYVAL hwnd AS LONG) AS LONG
        DbgEnter("UCWrapper_GetWindowTextLength")
        LOCAL lRet AS LONG
    
        Dbg("UC: " + FORMAT$(gUCWrapper.lUseUnicode))
    
        CALL DWORD gUCWrapper.fp.pGetWindowTextLength USING UCWrapper_GetWindowTextLength(hwnd) TO lRet
    
        IF gUCWrapper.lUseUnicode THEN
            ' return double length so double buffer is allocated
            lRet = lRet * 2 + 2
    
        END IF
    
        DbgLeave("UCWrapper_GetWindowTextLength")
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_IsDialogMessage(BYVAL hDlg AS LONG, BYVAL lpmsg AS DWORD) AS LONG
        ' no debug code here -> perf.
        LOCAL lRet AS LONG
    
        CALL DWORD gUCWrapper.fp.pIsDialogMessage USING UCWrapper_IsDialogMessage(hDlg, lpmsg) TO lRet
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_MessageBox(BYVAL hwnd AS LONG, BYVAL lpText AS DWORD, BYVAL lpCaption AS DWORD, BYVAL uType AS DWORD) AS LONG
        DbgEnter("UCWrapper_MessageBox")
        LOCAL lRet AS LONG
        LOCAL ansiText AS STRING
        LOCAL ansiCaption AS STRING
    
        Dbg("UC: " + FORMAT$(gUCWrapper.lUseUnicode))
    
        IF ISFALSE gUCWrapper.lUseUnicode THEN
            ' transform to ansi
            ansiText = ACODE$(UCWrapper_GetUnicodeSZString(lpText)) + $NUL
            ansiCaption = ACODE$(UCWrapper_GetUnicodeSZString(lpCaption)) + $NUL
    
            CALL DWORD gUCWrapper.fp.pMessageBox USING UCWrapper_MessageBox(hwnd, STRPTR(ansiText), STRPTR(ansiCaption), uType) TO lRet
    
        ELSE
            ' call directly
            CALL DWORD gUCWrapper.fp.pMessageBox USING UCWrapper_MessageBox(hwnd, lpText, lpCaption, uType) TO lRet
    
        END IF
    
        DbgLeave("UCWrapper_MessageBox")
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_PeekMessage(BYVAL lpmsg AS DWORD, BYVAL hwnd AS LONG, BYVAL wMsgFilterMin AS LONG, BYVAL wMsgFilterMax AS LONG, _
                                   BYVAL wRemoveMsg AS LONG) AS LONG
        ' no debug code here -> perf.
        LOCAL lRet AS LONG
    
        CALL DWORD gUCWrapper.fp.pPeekMessage USING UCWrapper_PeekMessage(lpmsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg) TO lRet
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_PostMessage(BYVAL hwnd AS LONG, BYVAL msg AS DWORD, BYVAL wparam AS DWORD, BYVAL lparam AS DWORD) AS LONG
        ' no debug code here -> perf.
        LOCAL lRet AS LONG
    
        CALL DWORD gUCWrapper.fp.pPostMessage USING UCWrapper_PostMessage(hwnd, msg, wparam, lparam) TO lRet
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_SendMessage(BYVAL hwnd AS LONG, BYVAL msg AS DWORD, BYVAL wparam AS DWORD, BYVAL lparam AS DWORD) AS LONG
        ' no debug code here -> perf.
        LOCAL lRet AS LONG
    
        CALL DWORD gUCWrapper.fp.pSendMessage USING UCWrapper_SendMessage(hwnd, msg, wparam, lparam) TO lRet
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_SetWindowText(BYVAL hwnd AS LONG, BYVAL lpString AS DWORD) AS LONG
        DbgEnter("UCWrapper_SetWindowText")
        LOCAL lRet AS LONG
        LOCAL ansiString AS STRING
    
        Dbg("UC: " + FORMAT$(gUCWrapper.lUseUnicode))
    
        IF ISFALSE gUCWrapper.lUseUnicode THEN
            ' transform
            ansiString = ACODE$(UCWrapper_GetUnicodeSZString(lpString)) + $NUL
            CALL DWORD gUCWrapper.fp.pSetWindowText USING UCWrapper_SetWindowText(hwnd, STRPTR(ansiString)) TO lRet
    
        ELSE
            ' call directly
            CALL DWORD gUCWrapper.fp.pSetWindowText USING UCWrapper_SetWindowText(hwnd, lpString) TO lRet
    
        END IF
    
        DbgLeave("UCWrapper_SetWindowText")
    
        FUNCTION = lRet
    END FUNCTION
    
    FUNCTION UCWrapper_PatchFunction(BYVAL hModule AS DWORD, BYVAL hLib AS LONG, sFuncName AS STRING, BYVAL pPatch AS DWORD) AS DWORD
        ' patches a function inside a module
        ' hModule: base address
        ' sFuncName: function to patch
        ' pPatch: pointer to patch function
        ' returns orig function name
        DbgEnter("UCWrapper_PatchFunction")
        LOCAL lpImageDosHeader AS IMAGE_DOS_HEADER PTR
        LOCAL lpImageNtHeaders AS IMAGE_NT_HEADERS PTR
        LOCAL lpImageImportDescriptor AS IMAGE_IMPORT_DESCRIPTOR PTR
        LOCAL lpImageImportByName AS IMAGE_IMPORT_BY_NAME PTR
        LOCAL lpFuncNameRef AS DWORD PTR
        LOCAL lpFuncAddr AS DWORD PTR
        LOCAL flOldProtect AS DWORD
    
        LOCAL dwRet AS DWORD
    
        LOCAL hProc AS DWORD
    
        hProc = GetProcAddress(hLib, BYCOPY sFuncName)
        'msgbox format$(hModule) + " " + sFuncName
    
        lpImageDosHeader = hModule
        IF @lpImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE THEN
            ' invalid DOS signature
            EXIT FUNCTION
    
        END IF
    
        lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
        IF @lpImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE THEN
            ' invalid NT signature
            EXIT FUNCTION
    
        END IF
    
        IF @lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SIZEOF(@lpImageNtHeaders.OptionalHeader) OR _
           @lpImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC THEN
            ' invalid NT header
            EXIT FUNCTION
    
        END IF
    
        IF @lpImageNtHeaders.OptionalHeader.NumberOfRvaAndSizes <= %IMAGE_DIRECTORY_ENTRY_IMPORT THEN
            ' no import section
            EXIT FUNCTION
    
        END IF
    
        lpImageImportDescriptor = lpImageDosHeader + @lpImageNtHeaders.OptionalHeader.DataDirectory(%IMAGE_DIRECTORY_ENTRY_IMPORT).VirtualAddress
        IF lpImageImportDescriptor = lpImageDosHeader THEN
            ' no import table
            EXIT FUNCTION
    
        END IF
    
        DO WHILE @lpImageImportDescriptor.OriginalFirstThunk <> 0
            'msgbox "outerloop"
            lpFuncNameRef = @lpImageImportDescriptor.OriginalFirstThunk + lpImageDosHeader
            lpFuncAddr = @lpImageImportDescriptor.FirstThunk + lpImageDosHeader
    
            DO WHILE @lpFuncNameRef <> 0
                'MSGBOX "innerloop"
                lpImageImportByName = @lpFuncNameRef + lpImageDosHeader
                'msgbox "innerloop2"
                IF ISFALSE (@lpFuncNameRef AND %IMAGE_ORDINAL_FLAG) THEN
                    'MSGBOX "inif" + str$(lpImageImportByName) + str$(@lpFuncNameRef) + str$(lpImageDosHeader) + str$(lpFuncNameRef) + str$(lpFuncAddr)
                    'msgbox format$(@lpFuncAddr)
                    'MSGBOX FORMAT$(hProc) + str$(@lpFuncAddr) + str$(lpFuncAddr)
                    IF @lpFuncAddr = hProc THEN '@lpImageImportByName.ImpName = sFuncName THEN
                        'msgbox "inif2"
                        IF VirtualProtect(BYVAL lpFuncAddr, 4, %PAGE_READWRITE, flOldProtect) = 0 THEN
                            ' virtual protect error
                            EXIT FUNCTION
    
                        END IF
    
                        dwRet = @lpFuncAddr
                        @lpFuncAddr = pPatch
    
                        IF FlushInstructionCache(GetCurrentProcess(), BYVAL @lpFuncAddr, 4) = 0 THEN
                            EXIT FUNCTION
    
                        END IF
    
                        IF flOldProtect <> %PAGE_READWRITE THEN
                            VirtualProtect BYVAL lpFuncAddr, 4, flOldProtect, flOldProtect
                            FUNCTION = dwRet
                            EXIT FUNCTION
    
                        END IF
    
                    END IF
    
                END IF
                'msgbox "innerloop3"
    
                INCR lpFuncNameRef
                INCR lpFuncAddr
    
            LOOP
    
            INCR lpImageImportDescriptor
    
        LOOP
    
        'IF dwRet = 0 THEN msgbox sFuncName
    
        DbgLeave("UCWrapper_PatchFunction")
        FUNCTION = dwRet
    END FUNCTION
    
    SUB UCWrapper_PatchToUnicode
        ' patches calls in PE import header to unicode calls
        DbgEnter("UCWrapper_PatchToUnicode")
        LOCAL ovi AS OSVERSIONINFO
        LOCAL hModule AS LONG
        LOCAL hLib AS LONG
        LOCAL sExt AS STRING
    
        ovi.dwOSVersionInfoSize = SIZEOF(ovi)
        GetVersionEx ovi
    
        gUCWrapper.lUseUnicode = (ovi.dwPlatformId = (%VER_PLATFORM_WIN32_NT)) AND ISFALSE %TEST_UNICODE_ANSI
    
        Dbg("Is Unicode: " + FORMAT$(gUCWrapper.lUseUnicode))
    
        hLib = GetModuleHandle("USER32.DLL")
    
        IF gUCWrapper.lUseUnicode THEN
            sExt = "W"
    
        ELSE
            sExt = "A"
    
        END IF
    
        hModule = GetModuleHandle(BYVAL %NULL)
    
        IF hModule THEN
            IF UCWrapper_PatchFunction(hModule, hLib, "CreateDialogIndirectParamA", CODEPTR(UCWrapper_CreateDialogIndirectParam)) THEN
                gUCWrapper.fp.pCreateDialogIndirectParam = GetProcAddress(hLib, "CreateDialogIndirectParam" + sExt)
    
            END IF
    
            IF UCWrapper_PatchFunction(hModule, hLib, "CreateWindowExA", CODEPTR(UCWrapper_CreateWindowEx)) THEN
                gUCWrapper.fp.pCreateWindowEx = GetProcAddress(hLib, "CreateWindowEx" + sExt)
    
            END IF
    
            IF UCWrapper_PatchFunction(hModule, hLib, "InsertMenuItemA", CODEPTR(UCWrapper_InsertMenuItem)) THEN
                gUCWrapper.fp.pInsertMenuItem = GetProcAddress(hLib, "InsertMenuItem" + sExt)
    
            END IF
    
            IF UCWrapper_PatchFunction(hModule, hLib, "GetWindowTextA", CODEPTR(UCWrapper_GetWindowText)) THEN
                gUCWrapper.fp.pGetWindowText = GetProcAddress(hLib, "GetWindowText" + sExt)
    
            END IF
    
            IF UCWrapper_PatchFunction(hModule, hLib, "GetWindowTextLengthA", CODEPTR(UCWrapper_GetWindowTextLength)) THEN
                gUCWrapper.fp.pGetWindowTextLength = GetProcAddress(hLib, "GetWindowTextLength" + sExt)
    
            END IF
    
            'IF UCWrapper_PatchFunction(hModule, "IsDialogMessageA", CODEPTR(UCWrapper_IsDialogMessage)) THEN
            '    gUCWrapper.fp.pIsDialogMessage = GetProcAddress(hLib, "IsDialogMessage" + sExt)
            '
            'END IF
    
            IF UCWrapper_PatchFunction(hModule, hLib, "MessageBoxA", CODEPTR(UCWrapper_MessageBox)) THEN
                gUCWrapper.fp.pMessageBox = GetProcAddress(hLib, "MessageBox" + sExt)
    
            END IF
    
            'IF UCWrapper_PatchFunction(hModule, "PeekMessageA", CODEPTR(UCWrapper_PeekMessage)) THEN
            '    gUCWrapper.fp.pPeekMessage = GetProcAddress(hLib, "PeekMessage" + sExt)
            '
            'END IF
    
            'IF UCWrapper_PatchFunction(hModule, "PostMessageA", CODEPTR(UCWrapper_PostMessage)) THEN
            '    gUCWrapper.fp.pPostMessage = GetProcAddress(hLib, "PostMessage" + sExt)
            '
            'END IF
    
            IF UCWrapper_PatchFunction(hModule, hLib, "SendMessageA", CODEPTR(UCWrapper_SendMessage)) THEN
                gUCWrapper.fp.pSendMessage = GetProcAddress(hLib, "SendMessage" + sExt)
    
            END IF
    
            IF UCWrapper_PatchFunction(hModule, hLib, "SetWindowTextA", CODEPTR(UCWrapper_SetWindowText)) THEN
                gUCWrapper.fp.pSetWindowText = GetProcAddress(hLib, "SetWindowText" + sExt)
    
            END IF
    
            'UCWrapper_PatchFunction hModule, "MultiByteToWideChar", CODEPTR(UCWrapper_MultiByteToWideChar)
    
        END IF
    
        DbgLeave("UCWrapper_PatchToUnicode")
    
    END SUB

    ------------------

    Leave a comment:


  • Lothar Pink
    replied
    Header file UCWRAP.BI

    Code:
    %IMAGE_ORDINAL_FLAG = &H80000000
    
    TYPE IMAGE_IMPORT_BY_NAME
        Hint AS WORD
        ImpName AS ASCIIZ * 254
    
    END TYPE
    
    TYPE IMAGE_IMPORT_DESCRIPTOR
        OriginalFirstThunk AS DWORD
        TimeDateStamp AS DWORD
        ForwarderChain AS DWORD
        pName AS DWORD
        FirstThunk AS DWORD
    
    END TYPE
    
    TYPE UCWrapper_FunctionPointersType
        pCreateDialogIndirectParam AS DWORD
        pCreateWindowEx AS DWORD
        pDispatchMessage AS DWORD
        pGetMenuItemInfo AS DWORD      ' not needed?
        pGetWindowLong AS DWORD        ' not needed? doesn't retrieve any unicode strings
        pGetWindowText AS DWORD
        pGetWindowTextLength AS DWORD
        pIsDialogMessage AS DWORD
        pLoadImage AS DWORD            ' not needed
        pMessageBox AS DWORD
        pPeekMessage AS DWORD
        pPostMessage AS DWORD
        pSendMessage AS DWORD
        pSetWindowLong AS DWORD        ' not needed
        pSetWindowText AS DWORD
        pSystemParametersInfo AS DWORD ' not needed
        pInsertMenuItem AS DWORD
    
    END TYPE
    
    TYPE UCWrapper_UCWrapperType
        fp AS UCWrapper_FunctionPointersType
    
        lUseUnicode AS LONG                 ' use unicode flag
    
    END TYPE
    
    GLOBAL gUCWrapper AS UCWrapper_UCWrapperType
    
    DECLARE FUNCTION UCWrapper_Dyn_TextOut(BYVAL hdc AS LONG, BYVAL nXStart AS LONG, BYVAL nYStart AS LONG, BYVAL lpString AS DWORD, BYVAL cbString AS LONG) AS LONG
    DECLARE FUNCTION UCWrapper_Dyn_DrawText(BYVAL hdc AS LONG, BYVAL lpString AS DWORD, BYVAL nCount AS LONG,  BYVAL lpRect AS DWORD, BYVAL uFormat AS DWORD) AS LONG
    DECLARE FUNCTION UCWrapper_GetUnicodeSZString(BYVAL lpAddress AS DWORD) AS STRING
    DECLARE FUNCTION UCWrapper_CreateDialogIndirectParam(BYVAL hInstance AS LONG, BYVAL lpTemplate AS DWORD, BYVAL hwndParent AS LONG, BYVAL lpDialogFunc AS DWORD, _
                                                 BYVAL lParamInit AS LONG) AS LONG
    DECLARE FUNCTION UCWrapper_CreateWindowEx(BYVAL dwExStyle AS DWORD, BYVAL lpClassName AS DWORD, BYVAL lpWindowName AS DWORD, BYVAL dwStyle AS DWORD, BYVAL x AS LONG, _
                                      BYVAL y AS LONG, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG, BYVAL hwndParent AS LONG, BYVAL hMenu AS LONG, _
                                      BYVAL hInstance AS LONG, BYVAL lpParam AS LONG) AS LONG
    DECLARE FUNCTION UCWrapper_DispatchMessage(BYVAL lpmsg AS DWORD) AS LONG
    DECLARE FUNCTION UCWrapper_GetWindowText(BYVAL hwnd AS LONG, BYVAL lpString AS DWORD, BYVAL nMaxCount AS LONG) AS LONG
    DECLARE FUNCTION UCWrapper_GetWindowTextLength(BYVAL hwnd AS LONG) AS LONG
    DECLARE FUNCTION UCWrapper_IsDialogMessage(BYVAL hDlg AS LONG, BYVAL lpmsg AS DWORD) AS LONG
    DECLARE FUNCTION UCWrapper_MessageBox(BYVAL hwnd AS LONG, BYVAL lpText AS DWORD, BYVAL lpCaption AS DWORD, BYVAL uType AS DWORD) AS LONG
    DECLARE FUNCTION UCWrapper_PeekMessage(BYVAL lpmsg AS DWORD, BYVAL hwnd AS LONG, BYVAL wMsgFilterMin AS LONG, BYVAL wMsgFilterMax AS LONG, _
                                   BYVAL wRemoveMsg AS LONG) AS LONG
    DECLARE FUNCTION UCWrapper_PostMessage(BYVAL hwnd AS LONG, BYVAL msg AS DWORD, BYVAL wparam AS DWORD, BYVAL lparam AS DWORD) AS LONG
    DECLARE FUNCTION UCWrapper_SendMessage(BYVAL hwnd AS LONG, BYVAL msg AS DWORD, BYVAL wparam AS DWORD, BYVAL lparam AS DWORD) AS LONG
    DECLARE FUNCTION UCWrapper_SetWindowText(BYVAL hwnd AS LONG, BYVAL lpString AS DWORD) AS LONG
    DECLARE FUNCTION UCWrapper_PatchFunction(BYVAL hModule AS DWORD, BYVAL hLib AS LONG, sFuncName AS STRING, BYVAL pPatch AS DWORD) AS DWORD
    DECLARE SUB UCWrapper_PatchToUnicode
    DECLARE FUNCTION InternalGetWindowText (BYVAL hWnd AS LONG, lpString AS ASCIIZ, BYVAL cch AS LONG) AS LONG

    ------------------

    Leave a comment:


  • Lothar Pink
    started a topic Unicode support for DDT

    Unicode support for DDT

    The following modules make it possible to use Unicode strings with DDT. The tool
    replaces the calls to ANSI functions inside the EXE files' import header with calls
    to UNICODE. If unicode API is not available, then function call parameters are translated
    back to ANSI.
    Please note that this is beta code at best, and not all DDT functionality has been tested;
    so use at your own risk. I already have successfully translated an application to UNICODE using that
    tool, however, some manual corrections might be necessary.

    Please add the following lines of code to your application before including the modules:
    Code:
    MACRO DbgEnter(x) = ! nop
    MACRO DbgLeave(x) = ! nop
    MACRO Dbg(x) = ! nop
    %TEST_UNICODE_ANSI = 0

    ------------------
Working...
X