home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj9209.zip / UNLOAD.ASC < prev    next >
INI File  |  1992-08-19  |  13KB  |  309 lines

  1. [LISTING ONE]
  2.  
  3. ////////////////////////////////////////////////////////////////////////////
  4. // UNLOAD.C     Copyright (c) 1992 by Mike Sax
  5. // Unload is a small programmer's utility that lets you remove any program
  6. // or DLL that is stuck in memory.
  7. ////////////////////////////////////////////////////////////////////////////
  8. #define STRICT 1
  9. #include <windows.h>
  10. #include <string.h>
  11. #include <toolhelp.h>
  12. #include "unload.h"
  13.  
  14. // Global variables:
  15. static HINSTANCE ghInstance;
  16.  
  17. // Exported functions:
  18. BOOL FAR PASCAL _export MainDlgProc(HWND hDlg, unsigned message, WORD wParam,
  19.                                     LONG lParam);
  20. BOOL FAR PASCAL _export WarningDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
  21.                                     LONG lParam);
  22. BOOL FAR PASCAL _export EnumTaskWindowsFunc(HWND hWnd, DWORD lParam);
  23.  
  24. // Internal functions:
  25. void static FillupComboBox(HANDLE hComboBox);
  26. void static ShowItemInfo(HWND hDlg, HWND hComboBox);
  27. void static KillTask(HTASK hTask, int nMethod);
  28. BOOL static IsDLL(HMODULE hModule);
  29.  
  30. // The WinMain function is called at the beginning of our program
  31. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  32.                    LPSTR lpCmdLine, int nCmdShow)
  33.     {
  34.     ghInstance = hInstance;
  35.     (void)lpCmdLine;
  36.     if (!hPrevInstance)
  37.         {
  38.         WNDCLASS  wc;
  39.         // Register private dialog class
  40.         wc.style = 0l;
  41.         wc.lpfnWndProc = DefDlgProc;
  42.         wc.cbClsExtra = 0;
  43.         wc.cbWndExtra = DLGWINDOWEXTRA;
  44.         wc.hInstance = ghInstance;
  45.         wc.hIcon = LoadIcon(hInstance, "Unload");
  46.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  47.         wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  48.         wc.lpszMenuName =  NULL;
  49.         wc.lpszClassName = "Unload";
  50.         if (!RegisterClass(&wc))
  51.             return -1;
  52.         }
  53.     // Use a dialog box as our main window and pass the nCmdShow parameter
  54.     // in lParam of MainDlgProc's WM_INITDIALOG.
  55.     return DialogBoxParam(ghInstance, "Unload", NULL, (DLGPROC)
  56.                 MakeProcInstance((FARPROC)MainDlgProc, ghInstance),
  57.                 (LONG)nCmdShow);
  58.     // Proc Instance will be automatically cleaned up by Windows.
  59.     }
  60. // MainDlgProc handles all messages for our main window.
  61. BOOL FAR PASCAL _export MainDlgProc(HWND hDlg, unsigned message, WORD wParam,
  62.                                     LONG lParam)
  63.     {
  64.     switch (message)
  65.         {
  66.         case WM_INITDIALOG:
  67.             // We passed the nCmdShow parameter of WinMain in lParam
  68.             ShowWindow(hDlg, LOWORD(lParam));
  69.             break;
  70.         case WM_CLOSE:
  71.             EndDialog(hDlg, FALSE);
  72.             break;
  73.         case WM_COMMAND:
  74.             switch(wParam)
  75.                 {
  76.                 // Combobox notification message
  77.                 case IDD_COMBOBOX:
  78.                     if (HIWORD(lParam) == CBN_DROPDOWN)
  79.                         FillupComboBox((HANDLE)LOWORD(lParam));
  80.                     else if (HIWORD(lParam) == CBN_SELCHANGE)
  81.                         {
  82.                         static BOOL bFirst = TRUE;
  83.                         if (bFirst)
  84.                             {
  85.                    SetDlgItemText(hDlg, IDD_MESSAGE, "Compuserve: 75470,1403");
  86.                             bFirst = FALSE;
  87.                             }
  88.                         ShowItemInfo(hDlg, (HANDLE)LOWORD(lParam));
  89.                         }
  90.                     break;
  91.                 // User pressed the "Unload" button
  92.                 case IDD_UNLOAD:
  93.                     {
  94.                     FARPROC lpProc;
  95.                     int nCurSel = (int)SendDlgItemMessage(hDlg, IDD_COMBOBOX,
  96.                                     CB_GETCURSEL, 0, 0l);
  97.                     // If no item selected, do nothing
  98.                     if (nCurSel == CB_ERR)
  99.                         {
  100.                         MessageBeep(0);
  101.                         break;
  102.                         }
  103.                     lpProc = MakeProcInstance((FARPROC)WarningDlgProc,
  104.                              ghInstance);
  105.                     // Call "Unload" dialog box and pass the module handle
  106.                     // in lParam of WarningDlgProc's WM_INITDIALOG
  107.                     if (DialogBoxParam(ghInstance, "WARNING", hDlg,
  108.                         (DLGPROC)lpProc, SendDlgItemMessage(hDlg,
  109.                             IDD_COMBOBOX, CB_GETITEMDATA, nCurSel, 0l)))
  110.                         {
  111.                         // Give Windows a chance to process the WM_QUIT
  112.                         // or WM_CLOSE messages we might have posted
  113.                         Yield();
  114.                         FillupComboBox(GetDlgItem(hDlg, IDD_COMBOBOX));
  115.                         }
  116.                     FreeProcInstance(lpProc);
  117.                     }
  118.                 }
  119.             break;
  120.         default:
  121.             return FALSE;       // We did not process the message
  122.         }
  123.     return TRUE;                // We processed the message
  124.     }
  125. // FillupComboBox fills up the combo box with a list of all modules
  126. // that are currently loaded.  Every item in the list box also contains
  127. // a "long" data item (attached using CB_SETITEMDATA) that is a combination
  128. // of the module handle and the usage count.
  129. void static FillupComboBox(HANDLE hComboBox)
  130.     {
  131.     int nIndex;
  132.     BOOL bSucces;
  133.     HMODULE hSelectedModule;
  134.     MODULEENTRY ModuleEntry;
  135.     // Keep the module handle of the item that is currently selected
  136.     nIndex = SendMessage(hComboBox, CB_GETCURSEL, 0, 0l);
  137.     hSelectedModule = (HMODULE) ((CB_ERR == nIndex) ? -1 :
  138.             HIWORD(SendMessage(hComboBox, CB_GETITEMDATA, nIndex, 0l)));
  139.     SendMessage(hComboBox, CB_RESETCONTENT, 0, 0l);
  140.     ModuleEntry.dwSize = sizeof (MODULEENTRY);
  141.     bSucces = ModuleFirst(&ModuleEntry);
  142.     while(bSucces)
  143.         {
  144.         if (IsDLL(ModuleEntry.hModule))
  145.             AnsiLower(ModuleEntry.szModule);
  146.         nIndex = (int)SendMessage(hComboBox, CB_ADDSTRING, 0,
  147.                                   (LONG) (LPSTR) ModuleEntry.szModule);
  148.         if ((nIndex != CB_ERR) && (nIndex != CB_ERRSPACE))
  149.             {
  150.             SendMessage(hComboBox, CB_SETITEMDATA, nIndex,
  151.                         MAKELONG(ModuleEntry.wcUsage, ModuleEntry.hModule));
  152.             bSucces = ModuleNext(&ModuleEntry);
  153.             }
  154.         else
  155.             bSucces = FALSE;
  156.         }
  157.     // Check if the previously selected module is still in the list and
  158.     // if so, reselect it.
  159.     for (nIndex = SendMessage(hComboBox, CB_GETCOUNT, 0, 0l) - 1;
  160.          nIndex >= 0 ; --nIndex)
  161.          if ((HMODULE) HIWORD(SendMessage(hComboBox, CB_GETITEMDATA,
  162.              nIndex, 0)) == hSelectedModule)
  163.              {
  164.              SendMessage(hComboBox, CB_SETCURSEL, nIndex, 0l);
  165.              break;
  166.              }
  167.     ShowItemInfo(GetParent(hComboBox), hComboBox);
  168.     }
  169. // Show information about the currently selected item in the combobox.
  170. void static ShowItemInfo(HWND hDlg, HWND hComboBox)
  171.     {
  172.     int nCurSel;
  173.     nCurSel = (int)SendMessage(hComboBox, CB_GETCURSEL, 0, 0l);
  174.     if (CB_ERR == nCurSel)
  175.         {
  176.         SetDlgItemText(hDlg, IDD_FILENAME, "");
  177.         SetDlgItemText(hDlg, IDD_MODULE, "");
  178.         SetDlgItemText(hDlg, IDD_KIND, "");
  179.         SetDlgItemText(hDlg, IDD_USAGE, "");
  180.         EnableWindow(GetDlgItem(hDlg, IDD_UNLOAD), FALSE);
  181.         }
  182.     else
  183.         {
  184.         char szScrap[MAX_PATH + 1];
  185.         char *pcFilename;
  186.         DWORD dwData;
  187.         dwData = SendMessage(hComboBox, CB_GETITEMDATA, nCurSel, 0l);
  188.         GetModuleFileName((HMODULE)HIWORD(dwData), szScrap, MAX_PATH);
  189.         // Remove the path from the filename
  190.         pcFilename = strrchr(szScrap, '\\');
  191.         pcFilename = (pcFilename == NULL) ? szScrap : pcFilename + 1;
  192.         SetDlgItemText(hDlg, IDD_KIND, (IsDLL((HMODULE)HIWORD(dwData)) ?
  193.                                         "Library" : "Program"));
  194.         SetDlgItemText(hDlg, IDD_FILENAME, pcFilename);
  195.         SetDlgItemInt(hDlg, IDD_USAGE, LOWORD(dwData), FALSE);
  196.         wsprintf(szScrap, "%04x", HIWORD(dwData));
  197.         SetDlgItemText(hDlg, IDD_MODULE, (LPSTR) szScrap);
  198.         EnableWindow(GetDlgItem(hDlg, IDD_UNLOAD), LOWORD(dwData));
  199.         }
  200.     }
  201. // When the user pressed the Unload button, the "warning dialog" appears
  202. BOOL FAR PASCAL _export WarningDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
  203.                                        LONG lParam)
  204.     {
  205.     static HMODULE hModule; // Only one dialog can be active!
  206.     switch(wMessage)
  207.         {
  208.         case WM_INITDIALOG:
  209.             // The handle of the module to be freed is in the hiword of iParam,
  210.             // passed on using DialogBoxParam. Since we use same dialog box for
  211.             // both programs and libraries, we have to adjust our dialog a
  212.             // a little, depending on the type of dialog.
  213.             if (IsDLL((HMODULE)HIWORD(lParam)))
  214.                 {
  215.                 EnableWindow(GetDlgItem(hDlg, IDD_TERMINATE), FALSE);
  216.                 EnableWindow(GetDlgItem(hDlg, IDD_DESTROY), FALSE);
  217.                 }
  218.             else
  219.                SetDlgItemText(hDlg, IDD_REFERENCEZERO, "Post WM_QUIT message");
  220.             CheckDlgButton(hDlg, IDD_REFERENCEZERO, 1);
  221.             hModule = (HMODULE)HIWORD(lParam);
  222.             break;
  223.         case WM_COMMAND:
  224.             switch(wParam)
  225.                 {
  226.                 case IDOK:
  227.                     {
  228.                     if (IsDLL(hModule))
  229.                         {
  230.                         int nUsage = GetModuleUsage(hModule);
  231.                         while (nUsage--)
  232.                             FreeLibrary(hModule);
  233.                         }
  234.                     else
  235.                         {
  236.                         BOOL bSucces;
  237.                         TASKENTRY TaskEntry;
  238.                         int nMethod =
  239.                         (IsDlgButtonChecked(hDlg, IDD_REFERENCEZERO)) ? 0 :
  240.                         (IsDlgButtonChecked(hDlg, IDD_TERMINATE)) ? 1 : 2;
  241.                         TaskEntry.dwSize = sizeof(TASKENTRY);
  242.                         bSucces = TaskFirst(&TaskEntry);
  243.                         while(bSucces)
  244.                             {
  245.                             if (TaskEntry.hModule == hModule)
  246.                                 KillTask(TaskEntry.hTask, nMethod);
  247.                             bSucces = TaskNext(&TaskEntry);
  248.                             }
  249.                         }
  250.                     EndDialog(hDlg, TRUE);
  251.                     }
  252.                     break;
  253.                 case IDCANCEL:
  254.                     EndDialog(hDlg, FALSE);
  255.                     break;
  256.                 }
  257.             break;
  258.         case WM_CLOSE:
  259.             EndDialog(hDlg, FALSE);
  260.             break;
  261.         default:
  262.             return FALSE;
  263.         }
  264.     return TRUE;
  265.     }
  266. // KillTask kills a task using a method of your choice.  It is called
  267. // from the "Warning" dialog box when the user presses Ok.
  268. void static KillTask(HTASK hTask, int nMethod)
  269.     {
  270.     switch(nMethod)
  271.         {
  272.         case 0:     // Post WM_QUIT message
  273.             PostAppMessage(hTask, WM_QUIT, 0, 0l);
  274.             break;
  275.         case 1:     // Terminate application
  276.             TerminateApp(hTask, NO_UAE_BOX);
  277.             break;
  278.         case 2:     // Close all the task's windows
  279.             {
  280.             FARPROC lpProc = MakeProcInstance((FARPROC)EnumTaskWindowsFunc,
  281.                                               ghInstance);
  282.             EnumTaskWindows(hTask,(WNDENUMPROC)lpProc, 0l);
  283.             FreeProcInstance(lpProc);
  284.             }
  285.             break;
  286.         }
  287.     }
  288. // EnumTaskWindowsFunc is called for every toplevel window that belongs to
  289. // a task. It simply posts a WM_CLOSE message to this window.
  290. BOOL FAR PASCAL _export EnumTaskWindowsFunc(HWND hWnd, DWORD lParam)
  291.     {
  292.     (void)lParam;                       // Avoid compiler warnings
  293.     if (GetParent(hWnd) == NULL)
  294.         PostMessage(hWnd, WM_CLOSE, 0, 0l);
  295.     return TRUE;
  296.     }
  297. // IsDLL returns TRUE if the specified module is a Dynamic Link Library, or
  298. // FALSE if it is a program.
  299. BOOL static IsDLL(HMODULE hModule)
  300.     {
  301.     int i;
  302.     // The module handle is really the selector of a far pointer to
  303.     // the new-style .EXE header of the module.  The bit at 0x8000 of
  304.     // the word at offset 0xC in this structure is set if it's a DLL.
  305.     MemoryRead((WORD)hModule, 0xCl, &i, sizeof(i));
  306.     return (i & 0x8000) ? TRUE : FALSE;
  307.     }
  308.  
  309.