COMMON.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:19k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1994-1996 Microsoft Corporation.
  4. *       All rights reserved.
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. /*++
  11. Module Name:
  12.     common.c
  13. Abstract:
  14.     This module contains common apis used by tlist & kill.
  15. --*/
  16. #include <windows.h>
  17. #include <winperf.h>   // for Windows NT
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <tlhelp32.h>  // for Windows 95
  22. #include "common.h"
  23. //
  24. // manafest constants
  25. //
  26. #define INITIAL_SIZE        51200
  27. #define EXTEND_SIZE         25600
  28. #define REGKEY_PERF         "software\microsoft\windows nt\currentversion\perflib"
  29. #define REGSUBKEY_COUNTERS  "Counters"
  30. #define PROCESS_COUNTER     "process"
  31. #define PROCESSID_COUNTER   "id process"
  32. #define UNKNOWN_TASK        "unknown"
  33. //
  34. // Function pointer types for accessing Toolhelp32 functions dynamically.
  35. // By dynamically accessing these functions, we can do so only on Windows
  36. // 95 and still run on Windows NT, which does not have these functions.
  37. //
  38. typedef BOOL (WINAPI *PROCESSWALK)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
  39. typedef HANDLE (WINAPI *CREATESNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);
  40. //
  41. // prototypes
  42. //
  43. BOOL CALLBACK
  44. EnumWindowsProc(
  45.     HWND    hwnd,
  46.     DWORD   lParam
  47.     );
  48. DWORD
  49. GetTaskList95(
  50.     PTASK_LIST  pTask,
  51.     DWORD       dwNumTasks
  52.     )
  53. /*++
  54. Routine Description:
  55.     Provides an API for getting a list of tasks running at the time of the
  56.     API call.  This function uses Toolhelp32to get the task list and is 
  57.     therefore straight WIN32 calls that anyone can call.
  58. Arguments:
  59.     dwNumTasks       - maximum number of tasks that the pTask array can hold
  60. Return Value:
  61.     Number of tasks placed into the pTask array.
  62. --*/
  63. {
  64.    CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
  65.    PROCESSWALK    pProcess32First           = NULL;
  66.    PROCESSWALK    pProcess32Next            = NULL;
  67.    HANDLE         hKernel        = NULL;
  68.    HANDLE         hProcessSnap   = NULL;
  69.    PROCESSENTRY32 pe32           = {0};
  70.    DWORD          dwTaskCount    = 0;
  71.    // Guarantee to the code later on that we'll enum at least one task.
  72.    if (dwNumTasks == 0)
  73.       return 0;
  74.     // Obtain a module handle to KERNEL so that we can get the addresses of
  75.     // the 32-bit Toolhelp functions we need.
  76.     hKernel = GetModuleHandle("KERNEL32.DLL");
  77.     if (hKernel)
  78.     {
  79.         pCreateToolhelp32Snapshot =
  80.           (CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot");
  81.         pProcess32First = (PROCESSWALK)GetProcAddress(hKernel,
  82.                                                       "Process32First");
  83.         pProcess32Next  = (PROCESSWALK)GetProcAddress(hKernel,
  84.                                                       "Process32Next");
  85.     }
  86.     
  87.     // make sure we got addresses of all needed Toolhelp functions.
  88.     if (!(pProcess32First && pProcess32Next && pCreateToolhelp32Snapshot))
  89.        return 0;
  90.        
  91.     // Take a snapshot of all processes currently in the system.
  92.     hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  93.     if (hProcessSnap == (HANDLE)-1)
  94.         return 0;
  95.     // Walk the snapshot of processes and for each process, get information
  96.     // to display.
  97.     dwTaskCount = 0;
  98.     pe32.dwSize = sizeof(PROCESSENTRY32);   // must be filled out before use
  99.     if (pProcess32First(hProcessSnap, &pe32))
  100.     {
  101.         do
  102.         {
  103.             LPSTR pCurChar;
  104.             // strip path and leave executabe filename splitpath
  105.             for (pCurChar = (pe32.szExeFile + lstrlen (pe32.szExeFile));
  106.                  *pCurChar != '\' && pCurChar != pe32.szExeFile; 
  107.                  --pCurChar)
  108.             lstrcpy(pTask -> ProcessName, pCurChar);
  109.             pTask -> flags = 0;
  110.             pTask -> dwProcessId = pe32.th32ProcessID;
  111.             ++dwTaskCount;   // keep track of how many tasks we've got so far
  112.             ++pTask;         // get to next task info block.
  113.         }
  114.         while (dwTaskCount < dwNumTasks && pProcess32Next(hProcessSnap, &pe32));
  115.     }
  116.     else
  117.         dwTaskCount = 0;    // Couldn't walk the list of processes.
  118.     // Don't forget to clean up the snapshot object...
  119.     CloseHandle (hProcessSnap);
  120.     return dwTaskCount;
  121. }
  122. DWORD
  123. GetTaskListNT(
  124.     PTASK_LIST  pTask,
  125.     DWORD       dwNumTasks
  126.     )
  127. /*++
  128. Routine Description:
  129.     Provides an API for getting a list of tasks running at the time of the
  130.     API call.  This function uses the registry performance data to get the
  131.     task list and is therefore straight WIN32 calls that anyone can call.
  132. Arguments:
  133.     dwNumTasks       - maximum number of tasks that the pTask array can hold
  134. Return Value:
  135.     Number of tasks placed into the pTask array.
  136. --*/
  137. {
  138.     DWORD                        rc;
  139.     HKEY                         hKeyNames;
  140.     DWORD                        dwType;
  141.     DWORD                        dwSize;
  142.     LPBYTE                       buf = NULL;
  143.     CHAR                         szSubKey[1024];
  144.     LANGID                       lid;
  145.     LPSTR                        p;
  146.     LPSTR                        p2;
  147.     PPERF_DATA_BLOCK             pPerf;
  148.     PPERF_OBJECT_TYPE            pObj;
  149.     PPERF_INSTANCE_DEFINITION    pInst;
  150.     PPERF_COUNTER_BLOCK          pCounter;
  151.     PPERF_COUNTER_DEFINITION     pCounterDef;
  152.     DWORD                        i;
  153.     DWORD                        dwProcessIdTitle;
  154.     DWORD                        dwProcessIdCounter;
  155.     CHAR                         szProcessName[MAX_PATH];
  156.     DWORD                        dwLimit = dwNumTasks - 1;
  157.     //
  158.     // Look for the list of counters.  Always use the neutral
  159.     // English version, regardless of the local language.  We
  160.     // are looking for some particular keys, and we are always
  161.     // going to do our looking in English.  We are not going
  162.     // to show the user the counter names, so there is no need
  163.     // to go find the corresponding name in the local language.
  164.     //
  165.     lid = MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL );
  166.     sprintf( szSubKey, "%s\%03x", REGKEY_PERF, lid );
  167.     rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  168.                        szSubKey,
  169.                        0,
  170.                        KEY_READ,
  171.                        &hKeyNames
  172.                      );
  173.     if (rc != ERROR_SUCCESS) {
  174.         goto exit;
  175.     }
  176.     //
  177.     // get the buffer size for the counter names
  178.     //
  179.     rc = RegQueryValueEx( hKeyNames,
  180.                           REGSUBKEY_COUNTERS,
  181.                           NULL,
  182.                           &dwType,
  183.                           NULL,
  184.                           &dwSize
  185.                         );
  186.     if (rc != ERROR_SUCCESS) {
  187.         goto exit;
  188.     }
  189.     //
  190.     // allocate the counter names buffer
  191.     //
  192.     buf = (LPBYTE) malloc( dwSize );
  193.     if (buf == NULL) {
  194.         goto exit;
  195.     }
  196.     memset( buf, 0, dwSize );
  197.     //
  198.     // read the counter names from the registry
  199.     //
  200.     rc = RegQueryValueEx( hKeyNames,
  201.                           REGSUBKEY_COUNTERS,
  202.                           NULL,
  203.                           &dwType,
  204.                           buf,
  205.                           &dwSize
  206.                         );
  207.     if (rc != ERROR_SUCCESS) {
  208.         goto exit;
  209.     }
  210.     //
  211.     // now loop thru the counter names looking for the following counters:
  212.     //
  213.     //      1.  "Process"           process name
  214.     //      2.  "ID Process"        process id
  215.     //
  216.     // the buffer contains multiple null terminated strings and then
  217.     // finally null terminated at the end.  the strings are in pairs of
  218.     // counter number and counter name.
  219.     //
  220.     p = buf;
  221.     while (*p) {
  222.         if (p > buf) {
  223.             for( p2=p-2; isdigit(*p2); p2--) ;
  224.             }
  225.         if (stricmp(p, PROCESS_COUNTER) == 0) {
  226.             //
  227.             // look backwards for the counter number
  228.             //
  229.             for( p2=p-2; isdigit(*p2); p2--) ;
  230.             strcpy( szSubKey, p2+1 );
  231.         }
  232.         else
  233.         if (stricmp(p, PROCESSID_COUNTER) == 0) {
  234.             //
  235.             // look backwards for the counter number
  236.             //
  237.             for( p2=p-2; isdigit(*p2); p2--) ;
  238.             dwProcessIdTitle = atol( p2+1 );
  239.         }
  240.         //
  241.         // next string
  242.         //
  243.         p += (strlen(p) + 1);
  244.     }
  245.     //
  246.     // free the counter names buffer
  247.     //
  248.     free( buf );
  249.     //
  250.     // allocate the initial buffer for the performance data
  251.     //
  252.     dwSize = INITIAL_SIZE;
  253.     buf = malloc( dwSize );
  254.     if (buf == NULL) {
  255.         goto exit;
  256.     }
  257.     memset( buf, 0, dwSize );
  258.     while (TRUE) {
  259.         rc = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
  260.                               szSubKey,
  261.                               NULL,
  262.                               &dwType,
  263.                               buf,
  264.                               &dwSize
  265.                             );
  266.         pPerf = (PPERF_DATA_BLOCK) buf;
  267.         //
  268.         // check for success and valid perf data block signature
  269.         //
  270.         if ((rc == ERROR_SUCCESS) &&
  271.             (dwSize > 0) &&
  272.             (pPerf)->Signature[0] == (WCHAR)'P' &&
  273.             (pPerf)->Signature[1] == (WCHAR)'E' &&
  274.             (pPerf)->Signature[2] == (WCHAR)'R' &&
  275.             (pPerf)->Signature[3] == (WCHAR)'F' ) {
  276.             break;
  277.         }
  278.         //
  279.         // if buffer is not big enough, reallocate and try again
  280.         //
  281.         if (rc == ERROR_MORE_DATA) {
  282.             dwSize += EXTEND_SIZE;
  283.             buf = realloc( buf, dwSize );
  284.             memset( buf, 0, dwSize );
  285.         }
  286.         else {
  287.             goto exit;
  288.         }
  289.     }
  290.     //
  291.     // set the perf_object_type pointer
  292.     //
  293.     pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);
  294.     //
  295.     // loop thru the performance counter definition records looking
  296.     // for the process id counter and then save its offset
  297.     //
  298.     pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);
  299.     for (i=0; i<(DWORD)pObj->NumCounters; i++) {
  300.         if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle) {
  301.             dwProcessIdCounter = pCounterDef->CounterOffset;
  302.             break;
  303.         }
  304.         pCounterDef++;
  305.     }
  306.     dwNumTasks = min( dwLimit, (DWORD)pObj->NumInstances );
  307.     pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);
  308.     //
  309.     // loop thru the performance instance data extracting each process name
  310.     // and process id
  311.     //
  312.     for (i=0; i<dwNumTasks; i++) {
  313.         //
  314.         // pointer to the process name
  315.         //
  316.         p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);
  317.         //
  318.         // convert it to ascii
  319.         //
  320.         rc = WideCharToMultiByte( CP_ACP,
  321.                                   0,
  322.                                   (LPCWSTR)p,
  323.                                   -1,
  324.                                   szProcessName,
  325.                                   sizeof(szProcessName),
  326.                                   NULL,
  327.                                   NULL
  328.                                 );
  329.         if (!rc) {
  330.             //
  331.     // if we cant convert the string then use a default value
  332.             //
  333.             strcpy( pTask->ProcessName, UNKNOWN_TASK );
  334.         }
  335.         if (strlen(szProcessName)+4 <= sizeof(pTask->ProcessName)) {
  336.             strcpy( pTask->ProcessName, szProcessName );
  337.             strcat( pTask->ProcessName, ".exe" );
  338.         }
  339.         //
  340.         // get the process id
  341.         //
  342.         pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);
  343.         pTask->flags = 0;
  344.         pTask->dwProcessId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));
  345.         if (pTask->dwProcessId == 0) {
  346.             pTask->dwProcessId = (DWORD)-2;
  347.         }
  348.         //
  349.         // next process
  350.         //
  351.         pTask++;
  352.         pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);
  353.     }
  354. exit:
  355.     if (buf) {
  356.         free( buf );
  357.     }
  358.     RegCloseKey( hKeyNames );
  359.     RegCloseKey( HKEY_PERFORMANCE_DATA );
  360.     return dwNumTasks;
  361. }
  362. BOOL
  363. EnableDebugPriv95(
  364.     VOID
  365.     )
  366. /*++
  367. Routine Description:
  368.     Changes the process's privilege so that kill works properly.
  369. Arguments:
  370. Return Value:
  371.     TRUE             - success
  372.     FALSE            - failure
  373. Comments: 
  374.     Always returns TRUE
  375. --*/
  376. {
  377.    return TRUE;
  378. }
  379. BOOL
  380. EnableDebugPrivNT(
  381.     VOID
  382.     )
  383. /*++
  384. Routine Description:
  385.     Changes the process's privilege so that kill works properly.
  386. Arguments:
  387. Return Value:
  388.     TRUE             - success
  389.     FALSE            - failure
  390. --*/
  391. {
  392.     HANDLE hToken;
  393.     LUID DebugValue;
  394.     TOKEN_PRIVILEGES tkp;
  395.     //
  396.     // Retrieve a handle of the access token
  397.     //
  398.     if (!OpenProcessToken(GetCurrentProcess(),
  399.             TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  400.             &hToken)) {
  401.         printf("OpenProcessToken failed with %dn", GetLastError());
  402.         return FALSE;
  403.     }
  404.     //
  405.     // Enable the SE_DEBUG_NAME privilege
  406.     //
  407.     if (!LookupPrivilegeValue((LPSTR) NULL,
  408.             SE_DEBUG_NAME,
  409.             &DebugValue)) {
  410.         printf("LookupPrivilegeValue failed with %dn", GetLastError());
  411.         return FALSE;
  412.     }
  413.     tkp.PrivilegeCount = 1;
  414.     tkp.Privileges[0].Luid = DebugValue;
  415.     tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  416.     AdjustTokenPrivileges(hToken,
  417.         FALSE,
  418.         &tkp,
  419.         sizeof(TOKEN_PRIVILEGES),
  420.         (PTOKEN_PRIVILEGES) NULL,
  421.         (PDWORD) NULL);
  422.     //
  423.     // The return value of AdjustTokenPrivileges can't be tested
  424.     //
  425.     if (GetLastError() != ERROR_SUCCESS) {
  426.         printf("AdjustTokenPrivileges failed with %dn", GetLastError());
  427.         return FALSE;
  428.     }
  429.     return TRUE;
  430. }
  431. BOOL
  432. KillProcess(
  433.     PTASK_LIST tlist,
  434.     BOOL       fForce
  435.     )
  436. {
  437.     HANDLE            hProcess;
  438.     if (fForce || !tlist->hwnd) {
  439.         hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, tlist->dwProcessId );
  440.         if (hProcess) {
  441.             hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, tlist->dwProcessId );
  442.             if (hProcess == NULL) {
  443.                 return FALSE;
  444.             }
  445.             if (!TerminateProcess( hProcess, 1 )) {
  446.                 CloseHandle( hProcess );
  447.                 return FALSE;
  448.             }
  449.             CloseHandle( hProcess );
  450.             return TRUE;
  451.         }
  452.     }
  453.     //
  454.     // kill the process
  455.     //
  456.     PostMessage( tlist->hwnd, WM_CLOSE, 0, 0 );
  457.     return TRUE;
  458. }
  459. VOID
  460. GetWindowTitles(
  461.     PTASK_LIST_ENUM te
  462.     )
  463. {
  464.     //
  465.     // enumerate all windows
  466.     //
  467.     EnumWindows( EnumWindowsProc, (LPARAM) te );
  468. }
  469. BOOL CALLBACK
  470. EnumWindowsProc(
  471.     HWND    hwnd,
  472.     DWORD   lParam
  473.     )
  474. /*++
  475. Routine Description:
  476.     Callback function for window enumeration.
  477. Arguments:
  478.     hwnd             - window handle
  479.     lParam           - ** not used **
  480. Return Value:
  481.     TRUE  - continues the enumeration
  482. --*/
  483. {
  484.     DWORD             pid = 0;
  485.     DWORD             i;
  486.     CHAR              buf[TITLE_SIZE];
  487.     PTASK_LIST_ENUM   te = (PTASK_LIST_ENUM)lParam;
  488.     PTASK_LIST        tlist = te->tlist;
  489.     DWORD             numTasks = te->numtasks;
  490.     //
  491.     // get the processid for this window
  492.     //
  493.     if (!GetWindowThreadProcessId( hwnd, &pid )) {
  494.         return TRUE;
  495.     }
  496.     //
  497.     // look for the task in the task list for this window
  498.     //
  499.     for (i=0; i<numTasks; i++) {
  500.         if (tlist[i].dwProcessId == pid) {
  501.             tlist[i].hwnd = hwnd;
  502.             //
  503.     // we found the task so lets try to get the
  504.             // window text
  505.             //
  506.             if (GetWindowText( tlist[i].hwnd, buf, sizeof(buf) )) {
  507.                 //
  508. // got it, so lets save it
  509.                 //
  510.                 strcpy( tlist[i].WindowTitle, buf );
  511.             }
  512.             break;
  513.         }
  514.     }
  515.     //
  516.     // continue the enumeration
  517.     //
  518.     return TRUE;
  519. }
  520. BOOL
  521. MatchPattern(
  522.     PUCHAR String,
  523.     PUCHAR Pattern
  524.     )
  525. {
  526.     UCHAR   c, p, l;
  527.     for (; ;) {
  528.         switch (p = *Pattern++) {
  529.             case 0:                             // end of pattern
  530.                 return *String ? FALSE : TRUE;  // if end of string TRUE
  531.             case '*':
  532.                 while (*String) {               // match zero or more char
  533.                     if (MatchPattern (String++, Pattern))
  534.                         return TRUE;
  535.                 }
  536.                 return MatchPattern (String, Pattern);
  537.             case '?':
  538.                 if (*String++ == 0)             // match any one char
  539.                     return FALSE;                   // not end of string
  540.                 break;
  541.             case '[':
  542.                 if ( (c = *String++) == 0)      // match char set
  543.                     return FALSE;                   // syntax
  544.                 c = toupper(c);
  545.                 l = 0;
  546.                 while (p = *Pattern++) {
  547.                     if (p == ']')               // if end of char set, then
  548.                         return FALSE;           // no match found
  549.                     if (p == '-') {             // check a range of chars?
  550.                         p = *Pattern;           // get high limit of range
  551.                         if (p == 0  ||  p == ']')
  552.                             return FALSE;           // syntax
  553.                         if (c >= l  &&  c <= p)
  554.                             break;              // if in range, move on
  555.                     }
  556.                     l = p;
  557.                     if (c == p)                 // if char matches this element
  558.                         break;                  // move on
  559.                 }
  560.                 while (p  &&  p != ']')         // got a match in char set
  561.                     p = *Pattern++;             // skip to end of set
  562.                 break;
  563.             default:
  564.                 c = *String++;
  565.                 if (toupper(c) != p)            // check for exact char
  566.                     return FALSE;                   // not a match
  567.                 break;
  568.         }
  569.     }
  570. }