/*****************************************************/
/* -- Program to kill any application possessing a   */
/*    visible window the user can pick with the      */
/*    mouse.                                         */
/*****************************************************/

#include <windows.h>
#include "killer.h"

/* Globals. */
HINSTANCE   hins;       /* Instance of this app. */
TIMERPROC   lpfnTimer;  /* Timer proc instance. */

/* Prototypes. */
BOOL CALLBACK KillerDlg(HWND, UINT, WPARAM, LPARAM);
void          KillWnd(HWND);
void CALLBACK TimerProc(HWND, UINT, UINT, DWORD);

int CALLBACK
WinMain(HINSTANCE hinsThis, HINSTANCE hinsPrev,
  LPSTR lszCommand, int wShowWindow)
/*****************************************************/
/* -- Entry point.                                   */
/*****************************************************/
    {
    DLGPROC lpfnDialog;

    hins = hinsThis;

    /* Create a dialog instead of a main window. */
    /* No need to register a class this way. */
    if ((lpfnDialog = (DLGPROC)MakeProcInstance(
      (FARPROC)KillerDlg, hinsThis)) == (DLGPROC)NULL)
        return FALSE;

    DialogBox(hinsThis, "Killer", NULL, lpfnDialog);

    FreeProcInstance((FARPROC)lpfnDialog);
    return TRUE;
    }

BOOL CALLBACK
KillerDlg(HWND hwnd, UINT wm, WPARAM wParam,
  LPARAM lParam)
/*****************************************************/
/* -- Dialog proc for killing other apps.            */
/*****************************************************/
    {
    static  HWND    hwndPick;

    switch (wm)
        {
    default:
        return FALSE;

    case WM_INITDIALOG:
        {
        RECT    rect;
        int     dx  = GetSystemMetrics(SM_CXSCREEN);

        int     dy  = GetSystemMetrics(SM_CYSCREEN);

        /* Center the dialog on the screen. */
        GetWindowRect(hwnd, &rect);
        SetWindowPos(hwnd, NULL,
          (dx - (rect.right - rect.left)) / 2,
          (dy - (rect.bottom - rect.top)) / 2,
          0, 0, SWP_NOSIZE | SWP_NOZORDER);

        /* Start with focus on the pick PushButton. */
        SetFocus(GetDlgItem(hwnd, didPick));
        }
        return FALSE;

    case WM_COMMAND:
        switch (wParam)
            {
        default:
            return FALSE;

        case didPick:
            /* Capture the mouse so that we can */
            /* click on another app's window and get */
            /* a message. */
            SetCapture(hwnd);

            /* Let the user know we are in "pick" */
            /* mode. */
            SetCursor(LoadCursor(NULL, IDC_UPARROW));
            break;

        case didKill:
            if (IsWindow(hwndPick))
                {
                /* Do our thing! */
                SetDlgItemText(hwnd, didWindow, NULL);
                KillWnd(hwndPick);
                }
            break;

        case IDCANCEL:
            /* We will get this when the user picks */
            /* "Close" on our system menu. */
            EndDialog(hwnd, FALSE);
            break;
            }
        break;

    case WM_LBUTTONDOWN:
        {
        POINT   pt;
        char    szBuf[10];

        if (GetCapture() != hwnd)
            return FALSE;   /* Wasn't in pick mode. */

        ReleaseCapture();
        SetCursor(LoadCursor(NULL, IDC_ARROW));

        /* Pick the window under the cursor. */

        GetCursorPos(&pt);
        hwndPick = WindowFromPoint(pt);

        /* Get the topmost ancestor of the window */
        /* picked. */
        for (;;)
            {
            HWND    hwndParent;

            if ((hwndParent = GetParent(hwndPick)) ==
              NULL)
                break;

            hwndPick = hwndParent;
            }

        /* Let the user know which window has been */
        /* picked. */
        wsprintf(szBuf, "%x", (UINT)hwndPick);
        SetDlgItemText(hwnd, didWindow, szBuf);
        }
        break;
        }

    return TRUE;
    }

void
KillWnd(HWND hwnd)
/*****************************************************/
/* -- Kill the given window handle.                  */
/*****************************************************/
    {
    if (lpfnTimer != NULL)
        return; /* A kill is already pending. */

    if ((lpfnTimer = (TIMERPROC)MakeProcInstance(
      (FARPROC)TimerProc, hins)) == NULL)
        return;

    PostMessage(hwnd, WM_TIMER, 0, (LPARAM)lpfnTimer);
    /* Note that we can't free the proc instance */
    /* handle here since this the target app hasn't */
    /* received the message yet.  So we free it in */
    /* the callback. */
    }

void CALLBACK
TimerProc(HWND hwnd, UINT wm, UINT wParam,
  DWORD lParam)
/*****************************************************/
/* -- Timer callback.                                */
/* -- Destroy the window timer message was sent to.  */
/*****************************************************/
    {
    FreeProcInstance((FARPROC)lpfnTimer);
    lpfnTimer = NULL;
    DestroyWindow(hwnd);
    }


