tags:

views:

45

answers:

1

I have injected my DLL into a target application where I've hooked few WINAPI-functions as well. One of them is DrawTextExW. I'm trying to replace all 'l' letters to '!' before it prints it out. My solution works fine for a few seconds, but then the target application crashes. I really don't understand why.

Here's the function:

Edit - Working solution:

int WINAPI DetouredDrawTextExW(__in    HDC hdc,
                               __inout LPWSTR lpchText,
                               __in    int cchText,
                               __inout LPRECT lprc,
                               __in    UINT dwDTFormat,
                               __in    LPDRAWTEXTPARAMS lpDTParams)
{
    std::wstring s_wc(lpchText, cchText);

    std::replace(s_wc.begin(), s_wc.end(), L'l', L'!');

    return ::DrawTextExW(hdc, const_cast<wchar_t *>(s_wc.c_str()), 
        s_wc.length(), lprc, dwDTFormat, lpDTParams);
}

So, can somebody point it out to me what I'm doing wrong?

+1  A: 

I see that you ignore cchText, could you be receiving an non-NULL-terminated string with a positive value for cchText, resulting in reading past the end of the string into invalid memory? That error would present as a Win32 exception in the constructor of s_wc, though.

Also, you aren't checking for DT_MODIFYSTRING in the dwDTFormat parameter. If that flag is present, then ::DrawTextExW() could be overwriting invalid memory. That would present as a Win32 exception in ::DrawTextExW() or perhaps as a C++ exception in the s_wc destructor.

edit

Here's uncompiled, untested code that I believe obeys the contract of ::DrawTextExW()

int WINAPI DetouredDrawTextExW(__in    HDC hdc,
                               __inout LPWSTR lpchText,
                               __in    int cchText,
                               __inout LPRECT lprc,
                               __in    UINT dwDTFormat,
                               __in    LPDRAWTEXTPARAMS lpDTParams)
{
    std::vector<wchar_t> v_wc;
    int strSize = cchText == -1 ? wcslen(lpchText) : cchText;
    v_wc.resize(strSize + 4);
    std::copy(lpchText, lpchText + strSize, &v_wc.front());
    std::replace(v_wc.begin(), v_wc.end() - 4, L'l', L'!');

    int result = ::DrawTextExW(hdc, &v_wc.front(), 
        strSize, lprc, dwDTFormat, lpDTParams);
    if (dwDTFormat & DT_MODIFYSTRING)
    {
      std::copy(&v_wc.front(), &v_wc.front() + v_wc.size(), lpchText);
    }
}
David Gladfelter
Thanks for reply, but you were ultimately right from the beginning. I ignored cchText. The string, according to the specs, doesn't have to be null-terminated. Therefore std::wstring(lpchText, cchText) did the trick.
nhaa123