HOOK.C


/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1993 - 1998 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/

/*****************************************************************************\
* hook.c - Windows message spy application dll
*
* Functions:
*
* DllMain()
* FindSpyWindow()
* HookProc()
* SpyGetMsgProc()
* SpyCallWndProc()
* DbgPrintf()
*
* Comments:
*
\*****************************************************************************/

#include <windows.h>
#include "..\hook.h"


PRIVATE HWND ghwndSpyHook = NULL; // the handle back to the spy executable
PRIVATE SPYMSGDATA gsmd;
PRIVATE COPYDATASTRUCT gcds = { 0, sizeof(SPYMSGDATA), &gsmd };


PRIVATE VOID FindSpyWindow(VOID);

#ifdef DBG
VOID DbgPrintf(LPTSTR fmt, ...);
#endif



/*****************************************************************************\
* DllMain (hModule,cbHeap,lpchCmdLine)
*
* Called when the libary is loaded
*
* Arguments:
* PVOID hModule - Module handle for the libary.
* ULONG ulReason - DLL purpose
* PCONTEXT pctx - not used
*
* Returns:
* TRUE - Everything is ok
* FALSE- Error.
\*****************************************************************************/

BOOL
APIENTRY DllMain(
PVOID hModule,
ULONG ulReason,
PCONTEXT pctx
)
{
UNREFERENCED_PARAMETER(hModule);
UNREFERENCED_PARAMETER(pctx);

//
// This function is called for every instance of the DLL. We must find
// and store the handle to the spy window every time an instance of the
// DLL is instantiated.
//
if ( ulReason == DLL_PROCESS_ATTACH ) {
FindSpyWindow();
}

return TRUE;
}



/*****************************************************************************\
* FindSpyWindow
*
* Finds the spy window and store a local copy in this instances data.
* This must be called everytime that a new instance of the DLL is
* created.
*
* Arguments:
* none
*
* Returns:
* VOID
\*****************************************************************************/

PRIVATE VOID
FindSpyWindow(
VOID
)
{
ghwndSpyHook = FindWindow(HOOKWINDOWCLASS, HOOKWINDOWNAME);
}


/*****************************************************************************\
* HookProc( hWnd, uiMessage, wParam, lParam )
*
* The hook proc for the windows hook being spied on
*
* Arguments:
* HWND hWnd - window handle for the parent window
* UINT uiMessage - message number
* WPARAM wParam - message-dependent
* LPARAM lParam - message-dependent
*
* Returns:
* 0 if processed, nonzero if ignored
\*****************************************************************************/

BOOL WINAPI
HookProc(
HWND hwnd,
UINT uiMessage,
WPARAM wParam,
LPARAM lParam
)
{
HWND hwndSpyingOn;
HWND hwndSpyApp;

if (ghwndSpyHook == NULL || !IsWindow(ghwndSpyHook))
{
//
// Spy has terminated. Find the new window.
//
FindSpyWindow();
}

if (ghwndSpyHook != NULL && hwnd != ghwndSpyHook)
{
hwndSpyingOn = (HWND)GetWindowLong(ghwndSpyHook, 0);
hwndSpyApp = (HWND)GetWindowLong(ghwndSpyHook, sizeof(HWND));
//DbgPrintf("H ghwndSpyHook:%8.8x", ghwndSpyHook);
//DbgPrintf("H hwndSpyingOn:%8.8x", hwndSpyingOn);
//DbgPrintf("H hwndSpyApp:%8.8x", hwndSpyApp);

//
// Send the message on asynchronously for Spy to deal with if
// it is the appropriate hwndSpyingOn window to spy on.
//

if (hwndSpyingOn == hwnd
|| (hwndSpyingOn == HWND_ALL && hwnd != hwndSpyApp
&& !IsChild(hwndSpyApp, hwnd)))
{
gsmd.wParam = wParam;
gsmd.lParam = lParam;

gcds.dwData = uiMessage;

//DbgPrintf("H Sending Message hwnd:%8.8x msg:%d", hwnd, uiMessage);
SendMessage(ghwndSpyHook, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)&gcds);
//DbgPrintf("H Sent Message hwnd:%8.8x msg:%d", hwnd, uiMessage);

//DbgPrintf("");
return TRUE;
}
//DbgPrintf("");
}

return FALSE;
}



/*****************************************************************************\
* SpyGetMsgProc
*
* The Get Message hook function.
*
\*****************************************************************************/

LRESULT CALLBACK
SpyGetMsgProc(
INT hc,
WPARAM wParam,
LPARAM lParam
)
{
PMSG pmsg;

pmsg = (PMSG)lParam;

if (hc >= 0 && pmsg && pmsg->hwnd)
{
return HookProc(pmsg->hwnd, pmsg->message, pmsg->wParam, pmsg->lParam);
}

//
// Note that CallNextHookEx ignores the first parameter (hhook) so
// it is acceptable (barely) to pass in a NULL.
//
return CallNextHookEx(NULL, hc, wParam, lParam);
}



/*****************************************************************************\
* SpyCallWndProc
*
* The Call Window Proc (Send Message) hook function.
*
\*****************************************************************************/

LRESULT CALLBACK
SpyCallWndProc(
INT hc,
WPARAM wParam,
LPARAM lParam
)
{
PCWPSTRUCT pcwps;

pcwps = (PCWPSTRUCT)lParam;

if (hc >= 0 && pcwps && pcwps->hwnd)
{
return HookProc(pcwps->hwnd, pcwps->message, pcwps->wParam, pcwps->lParam);
}

//
// Note that CallNextHookEx ignores the first parameter (hhook) so
// it is acceptable (barely) to pass in a NULL.
//
return CallNextHookEx(NULL, hc, wParam, lParam);
}



#ifdef DBG
/****************************************************************************
* DBGprintf
*
* This debugging function prints out a string to the debug output.
* An optional set of substitutional parameters can be specified,
* and the final output will be the processed result of these combined
* with the format string, just like printf. A newline is always
* output after every call to this function.
*
* Arguments:
* LPTSTR fmt - Format string (printf style).
* ... - Variable number of arguments.
* Returns:
* VOID
\****************************************************************************/

VOID DbgPrintf(
LPTSTR fmt,
...
)
{
va_list marker;
TCHAR szBuf[256];

va_start(marker, fmt);
wvsprintf(szBuf, fmt, marker);
va_end(marker);

OutputDebugString(szBuf);
OutputDebugString(TEXT("\r\n"));
}
#endif