/* 
 * TERMINAT.C -- Terminate Apps and Tasks
 *		 Copyright (c) 1991, Gordon Harris, Data Arts
 */


#define WIN31
#define STRICT
#include <windows.h>
#ifdef STRICT
#include <windowsx.h>
#endif
#ifdef DEBUG
#include <debug.h>
#endif
#include <toolhelp.h>
#include "terminat.h"


BOOL FAR PASCAL DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);

char szAppName[] = "Terminat";
HINSTANCE hInst;


int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)
   {
   FARPROC lpfnDlg;

   hInst = hInstance;

   if (hPrevInst)
      return 0;

   lpfnDlg = (FARPROC) MakeProcInstance((FARPROC)DlgProc, hInstance);
   DialogBox(hInstance, "TERMINAT", NULL, (DLGPROC)lpfnDlg);
   FreeProcInstance((FARPROC)lpfnDlg);

   return 0;
   }


BOOL FAR PASCAL EnumProc (HWND hwnd, LPARAM lParam);

MODULEENTRY me;
TASKENTRY   te;


   int n, j;
   HMENU hMenu;
   char szNum[10];
   char szMsg[120];
   static HWND hwnd;
   static HWND hBut;
   static FARPROC lpfn;
   LONG   l;


   switch(message)
      {
      case WM_INITDIALOG:

	 hMenu = GetSystemMenu(hDlg,FALSE);
	 DeleteMenu (hMenu, SC_MAXIMIZE, MF_BYCOMMAND);
	 DeleteMenu (hMenu, SC_SIZE,	 MF_BYCOMMAND);
	 AppendMenu(hMenu, MF_SEPARATOR, 0, (LPSTR)NULL);
	 AppendMenu(hMenu, MF_STRING, ID_REREAD, (LPSTR)"&Reread task list");

	 /* Give our minimized dialog box an icon.. */
	 SetClassWord(hDlg, GCW_HICON, (WPARAM) LoadIcon(hInst, szAppName));
	 te.dwSize = sizeof(TASKENTRY);
	 me.dwSize = sizeof(MODULEENTRY);
	 lpfn = (FARPROC) MakeProcInstance((FARPROC) EnumProc, hInst);
	 hwnd = GetDlgItem(hDlg, ID_LIST);
	 hBut = GetDlgItem(hDlg, ID_CLOSE);
	 PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);

	 return TRUE;

      case WM_ICONERASEBKGND:	 WM_PAINTICON No longer defined in windows.h??
	 /* Give our minimized dialog box an icon.. */
	 SetClassWord(hDlg, GCW_HICON, (WPARAM) LoadIcon(hInst, szAppName));
	 return FALSE;

      case WM_SYSCOMMAND:
	 switch (wParam)
	    {
	    case ID_REREAD:
	       MessageBeep(MB_ICONQUESTION);
	       PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	       return TRUE;
	    case SC_CLOSE:
	       EndDialog(hDlg, TRUE);
	       return TRUE;
	    }
          break;

      case WM_ACTIVATEAPP:
	 if (wParam)
	    PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	 break;

      case WM_COMMAND:
	 switch(wParam)
	    {
	    case ID_LIST:
	       n = SendDlgItemMessage(hDlg, ID_LIST, LB_GETCURSEL, 0, 0L);
	       if (n == LB_ERR)
		  return TRUE;
	       l = SendDlgItemMessage(hDlg, ID_LIST, LB_GETITEMDATA, n, 0L);
	       if (HIWORD(lParam) == LBN_SELCHANGE)
		  EnableWindow(GetDlgItem(hDlg, ID_CLOSE), HIWORD(l));
	       else if (HIWORD(lParam) == LBN_DBLCLK)
		  {
		  if (HIWORD(l))
		     {
		     TaskFindHandle(&te, (HANDLE)LOWORD(l));
		     wsprintf(szMsg, "Task   %04X %s hInst %04X hModule %04X SS %04X SP %04X sTop %04X sMin %04X sBot %04X",
			   te.hTask, (LPSTR)te.szModule, te.hInst, te.hModule, te.wSS, te.wSP, te.wStackTop, te.wStackMinimum, te.wStackBottom);
		     }
		  else
		     {
		     ModuleFindHandle(&me, (HANDLE)LOWORD(l));
		     wsprintf(szMsg, "Module %04X %s refcount %d", me.hModule, (LPSTR)me.szExePath, me.wcUsage);
		     }
		  MessageBox(hDlg, szMsg, szAppName, MB_ICONINFORMATION | MB_OK);
		  }
	       return TRUE;

	    /* Populate our listbox.. */
	    case ID_GETLIST:
	       EnableWindow(GetDlgItem(hDlg, ID_CLOSE), FALSE);
	       SendDlgItemMessage(hDlg, ID_LIST, WM_SETREDRAW, 0, 0L);
	       j = SendDlgItemMessage(hDlg, ID_LIST, LB_GETCURSEL, 0, 0L);
	       SendDlgItemMessage(hDlg, ID_LIST, LB_RESETCONTENT, 0, 0L);

	       /* Enumerate the loaded modules.. */
	       me.dwSize = sizeof(MODULEENTRY);
	       ModuleFirst(&me);
	       do {
		  n = SendDlgItemMessage(hDlg, ID_LIST, LB_ADDSTRING, 0, (LONG)(LPSTR)me.szModule);
		  SendDlgItemMessage(hDlg, ID_LIST, LB_SETITEMDATA, n,
			(LONG)MAKELONG(me.hModule,0)); // HIWORD == 0 == module
		  } while (ModuleNext(&me));
	       if (n != LB_ERR)
		  SendDlgItemMessage(hDlg, ID_LIST, LB_SETCURSEL, n, 0L);
	       else
		  SendDlgItemMessage(hDlg, ID_LIST, LB_SETCURSEL, 0, 0L);


	       /* Now enumerate the tasks.. */
	       te.dwSize = sizeof(TASKENTRY);
	       TaskFirst(&te);
	       do {
		  /* Find the module which matches the task.. */
		  n = SendDlgItemMessage(hDlg, ID_LIST, LB_FINDSTRING, 0, (LONG)(LPSTR)te.szModule);
		  /* Replace the module handle with the task handle.. */
		  if (n != LB_ERR)
		     SendDlgItemMessage(hDlg, ID_LIST, LB_SETITEMDATA, n,
			      (LONG)MAKELONG(te.hTask,1)); // HIWORD == 1 == task
		  } while (TaskNext(&te));

	       if (j != LB_ERR)
		  SendDlgItemMessage(hDlg, ID_LIST, LB_SETCURSEL, j, 0L);
	       else
		  SendDlgItemMessage(hDlg, ID_LIST, LB_SETCURSEL, 0, 0L);

	       SendDlgItemMessage(hDlg, ID_LIST, WM_SETREDRAW, 1, 0L);
	       InvalidateRect(GetDlgItem(hDlg, ID_LIST), NULL, TRUE);
	       return TRUE;

	    case ID_TERMINATE:
	       n = SendDlgItemMessage(hDlg, ID_LIST, LB_GETCURSEL, 0, 0L);
	       if (n == LB_ERR)
		  return TRUE;
	       l = SendDlgItemMessage(hDlg, ID_LIST, LB_GETITEMDATA, n, 0L);
	       /* If this is a task, terminate it.. */
	       if ( HIWORD(l) && IsTask( (HTASK) LOWORD(l)) )
		  TerminateApp((HANDLE)LOWORD(l), NO_UAE_BOX);
	       /* Else, reduce the reference count to 0.. */
	       else
		  {
		  j = 0;
		  while (n = FreeModule((HINSTANCE)LOWORD(l)))
		     {
		     if (j == n)
			break;
		     j = n;
		     }
		  }

	       PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	       return TRUE;

	    case ID_CLOSE:
	       n = SendDlgItemMessage(hDlg, ID_LIST, LB_GETCURSEL, 0, 0L);
	       if (n == LB_ERR)
		  return TRUE;
	       l = SendDlgItemMessage(hDlg, ID_LIST, LB_GETITEMDATA, n, 0L);
	       if (HIWORD(l) && IsTask((HTASK) LOWORD(l)) )
		  EnumTaskWindows((HTASK)LOWORD(l), (WNDENUMPROC)lpfn, 0L); //Kill the app..
	       PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	       return TRUE;

	    case ID_QUIT:
	       EndDialog(hDlg, TRUE);
	       return TRUE;
	    }
	  break;

      case WM_DESTROY:
	 FreeProcInstance((FARPROC)lpfn);

      }
   return FALSE;
   }


/*
BOOL FAR PASCAL xDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
   {
   int n, j;
   HMENU hMenu;
   char szMsg[120];
   static HWND hLst;
   static HWND hBut;
   static FARPROC lpfn;
   LONG   l;


   switch(message)
      {
      case WM_INITDIALOG:

	 hMenu = GetSystemMenu(hDlg,FALSE);
	 DeleteMenu (hMenu, SC_MAXIMIZE, MF_BYCOMMAND);
	 DeleteMenu (hMenu, SC_SIZE,	 MF_BYCOMMAND);
	 AppendMenu(hMenu, MF_SEPARATOR, 0, (LPSTR)NULL);
	 AppendMenu(hMenu, MF_STRING, ID_REREAD, (LPSTR)"&Reread task list");

	 // Give our minimized dialog box an icon..
	 SetClassWord(hDlg, GCW_HICON, (WPARAM) LoadIcon(hInst, szAppName));
	 te.dwSize = sizeof(TASKENTRY);
	 me.dwSize = sizeof(MODULEENTRY);
	 lpfn = (FARPROC) MakeProcInstance((FARPROC) EnumProc, hInst);
	 hLst = GetDlgItem(hDlg, ID_LIST);
	 hBut = GetDlgItem(hDlg, ID_CLOSE);
	 PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);

	 return TRUE;

      //case WM_PAINTICON:    //No longer defined in windows.h??
      case WM_ICONERASEBKGND:
	 // Give our minimized dialog box an icon..
	 SetClassWord(hDlg, GCW_HICON, (WPARAM) LoadIcon(hInst, szAppName));
	 return FALSE;

      case WM_SYSCOMMAND:
	 switch (wParam)
	    {
	    case ID_REREAD:
	       MessageBeep(MB_ICONQUESTION);
	       PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	       return TRUE;
	    case SC_CLOSE:
	       EndDialog(hDlg, TRUE);
	       return TRUE;
	    }
          break;

      case WM_ACTIVATEAPP:
	 if (wParam)
	    PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	 break;

      case WM_COMMAND:
	 #ifdef STRICT
	 #define DLGLIST   GetDlgItem(hDlg, ID_LIST)
	 #define DLGCLOSE  GetDlgItem(hDlg, ID_CLOSE)
	 #endif
	 switch(wParam)
	    {
	    case ID_LIST:
	       n = ListBox_GetCurSel(hLst);
	       if (n == LB_ERR)
		  return TRUE;
	       l = ListBox_GetItemData(hLst, n);
	       if (HIWORD(lParam) == LBN_SELCHANGE)
		  Button_Enable(hBut, HIWORD(l));
	       else if (HIWORD(lParam) == LBN_DBLCLK)
		  {
		  if (HIWORD(l))
		     {
		     TaskFindHandle(&te, (HANDLE)LOWORD(l));
		     wsprintf(szMsg, "Task   %04X %s hInst %04X hModule %04X SS %04X SP %04X sTop %04X sMin %04X sBot %04X",
			   te.hTask, (LPSTR)te.szModule, te.hInst, te.hModule, te.wSS, te.wSP, te.wStackTop, te.wStackMinimum, te.wStackBottom);
		     }
		  else
		     {
		     ModuleFindHandle(&me, (HANDLE)LOWORD(l));
		     wsprintf(szMsg, "Module %04X %s refcount %d", me.hModule, (LPSTR)me.szExePath, me.wcUsage);
		     }
		  MessageBox(hDlg, szMsg, szAppName, MB_ICONINFORMATION | MB_OK);
		  }
	       return TRUE;

	    // Populate our listbox..
	    case ID_GETLIST:
	       Button_Enable(hBut, FALSE);
	       SetWindowRedraw(hLst, FALSE);

	       j = ListBox_GetCurSel(hLst);
	       ListBox_ResetContent(hLst);

	       // Enumerate the loaded modules..
	       me.dwSize = sizeof(MODULEENTRY);
	       ModuleFirst(&me);
	       do {
		  n = ListBox_AddString(hLst, me.szModule);
		  ListBox_SetItemData(hLst, n, MAKELONG(me.hModule,0)); // HIWORD == 0 == module
		  } while (ModuleNext(&me));


	       // Now enumerate the tasks..
	       te.dwSize = sizeof(TASKENTRY);
	       TaskFirst(&te);
	       do {
		  // Find the module which matches the task..
		  n = ListBox_FindString(hLst, 0, te.szModule);
		  // Replace the module handle with the task handle..
		  if (n != LB_ERR)
		     ListBox_SetItemData(hLst, n, MAKELONG(te.hTask,1)); // HIWORD == 1 == task
		  } while (TaskNext(&te));

	       if (j != LB_ERR)
		  ListBox_SetCurSel(hLst, j);
	       else
		  ListBox_SetCurSel(hLst, 0);

	       SetWindowRedraw(hLst, TRUE);

	       InvalidateRect(hLst, NULL, TRUE);
	       return TRUE;

	    case ID_TERMINATE:
	       n = ListBox_GetCurSel(hLst);
	       if (n == LB_ERR)
		  return TRUE;
	       l = ListBox_GetItemData(hLst, n);
	       // If this is a task, terminate it..
	       if ( HIWORD(l) && IsTask( (HTASK) LOWORD(l)) )
		  TerminateApp((HANDLE)LOWORD(l), NO_UAE_BOX);
	       // Else, reduce the reference count to 0..
	       else
		  {
		  j = 0;
		  while (n = FreeModule((HINSTANCE)LOWORD(l)))
		     {
		     if (j == n)
			break;
		     j = n;
		     }
		  }

	       PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	       return TRUE;

	    case ID_CLOSE:
	       n = ListBox_GetCurSel(hLst);
	       if (n == LB_ERR)
		  return TRUE;
	       l = ListBox_GetItemData(hLst, n);
	       if (HIWORD(l) && IsTask((HTASK) LOWORD(l)) )
		  EnumTaskWindows((HTASK)LOWORD(l), (WNDENUMPROC)lpfn, 0L); //Kill the app..
	       PostMessage(hDlg, WM_COMMAND, ID_GETLIST, 0L);
	       return TRUE;

	    case ID_QUIT:
	       EndDialog(hDlg, TRUE);
	       return TRUE;
	    }
	  break;

      case WM_DESTROY:
	 FreeProcInstance((FARPROC)lpfn);

      }
   return FALSE;
   }

*/





BOOL FAR PASCAL EnumProc (HWND hwnd, LPARAM lParam)
   {
   PostMessage(hwnd, WM_CLOSE, 0, 0L);
   MessageBeep(MB_ICONEXCLAMATION);
   return 0;
   }
