/*++

 Copyright (c) 2000 Microsoft Corporation

 Module Name:

    NBALive.cpp

 Abstract:

    On Win9x, SetWindowText used to pass the pointer directly to the window 
    proc in a WM_SETTEXT message. However, on NT, the string goes through the 
    standard message workers and get's converted to unicode etc. When it does 
    get to the window proc, it's not the original pointer.

    NBA Live 99 depends on the pointer being the same, since it sends more than 
    just the string. 

    The fix is to subclass the WindowProc on SetWindowText and change the 
    pointer (in lParam) to the one that was originally passed.

 Notes:
    
    This is an app specific shim.

 History:

    06/19/2000 linstev  Created

--*/

#include "precomp.h"

// This module has been given an official blessing to use the str routines.
#include "LegalStr.h"

IMPLEMENT_SHIM_BEGIN(NBALive)
#include "ShimHookMacro.h"

APIHOOK_ENUM_BEGIN
    APIHOOK_ENUM_ENTRY(SetWindowTextA) 
APIHOOK_ENUM_END


//
// Critical section for global variable access
//

CRITICAL_SECTION g_csGlobals;

//
// Text for window and previous windowproc
//

CHAR *g_szText; 
WNDPROC g_lpWndProc;

/*++

 The subclassed windowproc that we use to change the text pointer to the 
 original one passed to SetWindowTextA.

--*/

LRESULT
CALLBACK
WindowProcA(
    HWND hWnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam
    )
{
    if (uMsg == WM_SETTEXT) {
        if (lParam)  {
            if (strcmp(g_szText, (CHAR *) lParam) == 0)  {
                lParam = (LPARAM) g_szText;
            }
        }
    }

    return CallWindowProcA(g_lpWndProc, hWnd, uMsg, wParam, lParam);
}

/*++

 Subclass the windowproc for this call and fix the pointer that comes out in 
 the WM_SETTEXT message that is generated by SetWindowTextA.

--*/

BOOL 
APIHOOK(SetWindowTextA)(
    HWND hWnd,         
    LPCSTR lpString   
    )
{
    BOOL bRet = FALSE;

    //
    // Set the text for this window
    //

    EnterCriticalSection(&g_csGlobals);

    //
    // Subclass the window
    //
    
    g_lpWndProc = (WNDPROC) GetWindowLongA(hWnd, GWL_WNDPROC);

    if (g_lpWndProc)  {
        SetWindowLongA(hWnd, GWL_WNDPROC, (LONG_PTR) WindowProcA);
    }

    //
    // Call the original function which generates a WM_SETTEXT message
    //
    
    g_szText = (CHAR *) lpString;
    bRet = ORIGINAL_API(SetWindowTextA)(hWnd, lpString);

    //
    // Restore the wndproc
    //

    SetWindowLongA(hWnd, GWL_WNDPROC, (LONG_PTR) g_lpWndProc);

    LeaveCriticalSection(&g_csGlobals);

    return bRet;
}

/*++

 Register hooked functions

--*/

BOOL
NOTIFY_FUNCTION(
    DWORD fdwReason)
{
    if (fdwReason == DLL_PROCESS_ATTACH) {
        InitializeCriticalSection(&g_csGlobals);
    }

    return TRUE;
}

HOOK_BEGIN

    CALL_NOTIFY_FUNCTION
    APIHOOK_ENTRY(USER32.DLL, SetWindowTextA )

HOOK_END

IMPLEMENT_SHIM_END

