Annotation of mstools/samples/sdktools/image/drwatson/process.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1993  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     process.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This code provides access to the task list.
                     12: 
                     13: Author:
                     14: 
                     15:     Wesley Witt (wesw) 16-June-1993
                     16: 
                     17: Environment:
                     18: 
                     19:     User Mode
                     20: 
                     21: --*/
                     22: 
                     23: #include <windows.h>
                     24: #include <winperf.h>
                     25: #include <stdio.h>
                     26: #include <string.h>
                     27: #include <stdlib.h>
                     28: #include "drwatson.h"
                     29: #include "proto.h"
                     30: #include "messages.h"
                     31: 
                     32: //
                     33: // task list structure returned from GetTaskList()
                     34: //
                     35: typedef struct _TASK_LIST {
                     36:     DWORD   dwProcessId;
                     37:     char    ProcessName[MAX_PATH];
                     38: } TASK_LIST, *PTASK_LIST;
                     39: 
                     40: 
                     41: //
                     42: // defines
                     43: //
                     44: #define INITIAL_SIZE        51200
                     45: #define EXTEND_SIZE         25600
                     46: #define REGKEY_PERF         "software\\microsoft\\windows nt\\currentversion\\perflib"
                     47: #define REGSUBKEY_COUNTERS  "counters"
                     48: #define PROCESS_COUNTER     "process"
                     49: #define PROCESSID_COUNTER   "id process"
                     50: #define UNKNOWN_TASK        "unknown"
                     51: 
                     52: 
                     53: //
                     54: // prototypes
                     55: //
                     56: PTASK_LIST GetTaskList( LPDWORD pdwNumTasks );
                     57: 
                     58: 
                     59: void
                     60: LogTaskList( void )
                     61: 
                     62: /*++
                     63: 
                     64: Routine Description:
                     65: 
                     66:     This function gets the current task list and logs the process id &
                     67:     process name to the log file.
                     68: 
                     69: Arguments:
                     70: 
                     71:     None.
                     72: 
                     73: Return Value:
                     74: 
                     75:     None.
                     76: 
                     77: --*/
                     78: 
                     79: {
                     80:     PTASK_LIST   pTask;
                     81:     PTASK_LIST   pTaskBegin;
                     82:     DWORD        dwNumTasks;
                     83: 
                     84: 
                     85:     lprintf( MSG_TASK_LIST );
                     86: 
                     87:     pTask = pTaskBegin = GetTaskList( &dwNumTasks );
                     88: 
                     89:     if (pTask == NULL) {
                     90:         printf( "ERROR: could not get the task list\n" );
                     91:     }
                     92: 
                     93:     while (dwNumTasks--) {
                     94:         lprintfs("%4d %s\r\n",pTask->dwProcessId, pTask->ProcessName );
                     95:         pTask++;
                     96:     }
                     97:     lprintfs( "\r\n" );
                     98: 
                     99:     free( pTaskBegin );
                    100: }
                    101: 
                    102: void
                    103: GetTaskName( ULONG pid, char *szTaskName, LPDWORD pdwSize )
                    104: 
                    105: /*++
                    106: 
                    107: Routine Description:
                    108: 
                    109:     Gets the task name for a given process id.
                    110: 
                    111: Arguments:
                    112: 
                    113:     pid              - Process id to look for.
                    114:     szTaskName       - Buffer to put the task name into.
                    115:     lpdwSize         - Pointer to a dword.  On entry it contains the
                    116:                        size of the szTaskName buffer.  On exit it contains
                    117:                        the number of characters in the buffer.
                    118: 
                    119: Return Value:
                    120: 
                    121:     None.
                    122: 
                    123: --*/
                    124: 
                    125: {
                    126:     PTASK_LIST   pTask;
                    127:     PTASK_LIST   pTaskBegin;
                    128:     DWORD        dwNumTasks;
                    129: 
                    130: 
                    131:     pTask = pTaskBegin = GetTaskList( &dwNumTasks );
                    132: 
                    133:     if (pTask == NULL) {
                    134:         strcpy( szTaskName, "unknown" );
                    135:         return;
                    136:     }
                    137: 
                    138:     while (dwNumTasks--) {
                    139:         if (pTask->dwProcessId == pid) {
                    140:             if (szTaskName) {
                    141:                 strncpy( szTaskName, pTask->ProcessName, *pdwSize );
                    142:             }
                    143:             *pdwSize = min( strlen(pTask->ProcessName), *pdwSize );
                    144:             break;
                    145:         }
                    146:         pTask++;
                    147:     }
                    148: 
                    149:     free( pTaskBegin );
                    150: }
                    151: 
                    152: PTASK_LIST
                    153: GetTaskList( LPDWORD pdwNumTasks )
                    154: 
                    155: /*++
                    156: 
                    157: Routine Description:
                    158: 
                    159:     Provides an API for getting a list of tasks running at the time of the
                    160:     API call.  This function uses the registry performance data to get the
                    161:     task list and is therefor straight WIN32 calls that anyone can call.
                    162: 
                    163: Arguments:
                    164: 
                    165:     ldwNumTasks      - pointer to a dword that will be set to the
                    166:                        number of tasks returned.
                    167: 
                    168: Return Value:
                    169: 
                    170:     PTASK_LIST       - pointer to an array of TASK_LIST records.
                    171: 
                    172: --*/
                    173: 
                    174: {
                    175:     DWORD                        rc;
                    176:     HKEY                         hKeyNames;
                    177:     DWORD                        dwType;
                    178:     DWORD                        dwSize;
                    179:     LPBYTE                       buf = NULL;
                    180:     char                         szSubKey[1024];
                    181:     LANGID                       lid;
                    182:     LPSTR                        p;
                    183:     LPSTR                        p2;
                    184:     PPERF_DATA_BLOCK             pPerf;
                    185:     PPERF_OBJECT_TYPE            pObj;
                    186:     PPERF_INSTANCE_DEFINITION    pInst;
                    187:     PPERF_COUNTER_BLOCK          pCounter;
                    188:     PPERF_COUNTER_DEFINITION     pCounterDef;
                    189:     DWORD                        i;
                    190:     DWORD                        dwProcessIdTitle;
                    191:     DWORD                        dwProcessIdCounter;
                    192:     PTASK_LIST                   pTask;
                    193:     PTASK_LIST                   pTaskReturn = NULL;
                    194:     char                         szProcessName[MAX_PATH];
                    195: 
                    196: 
                    197:     //
                    198:     // set the number of tasks to zero until we get some
                    199:     //
                    200:     *pdwNumTasks = 0;
                    201: 
                    202:     //
                    203:     // Look for the list of counters.  Always use the neutral
                    204:     // English version, regardless of the local language.  We
                    205:     // are looking for some particular keys, and we are always
                    206:     // going to do our looking in English.  We are not going
                    207:     // to show the user the counter names, so there is no need
                    208:     // to go find the corresponding name in the local language.
                    209:     //
                    210:     lid = MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL );
                    211:     sprintf( szSubKey, "%s\\%03x", REGKEY_PERF, lid );
                    212:     rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
                    213:                        szSubKey,
                    214:                        0,
                    215:                        KEY_READ,
                    216:                        &hKeyNames
                    217:                      );
                    218:     if (rc != ERROR_SUCCESS) {
                    219:         goto exit;
                    220:     }
                    221: 
                    222:     //
                    223:     // get the buffer size for the counter names
                    224:     //
                    225:     rc = RegQueryValueEx( hKeyNames,
                    226:                           REGSUBKEY_COUNTERS,
                    227:                           NULL,
                    228:                           &dwType,
                    229:                           NULL,
                    230:                           &dwSize
                    231:                         );
                    232: 
                    233:     if (rc != ERROR_SUCCESS) {
                    234:         goto exit;
                    235:     }
                    236: 
                    237:     //
                    238:     // allocate the counter names buffer
                    239:     //
                    240:     buf = (LPBYTE) malloc( dwSize );
                    241:     if (buf == NULL) {
                    242:         goto exit;
                    243:     }
                    244:     memset( buf, 0, dwSize );
                    245: 
                    246:     //
                    247:     // read the counter names from the registry
                    248:     //
                    249:     rc = RegQueryValueEx( hKeyNames,
                    250:                           REGSUBKEY_COUNTERS,
                    251:                           NULL,
                    252:                           &dwType,
                    253:                           buf,
                    254:                           &dwSize
                    255:                         );
                    256: 
                    257:     if (rc != ERROR_SUCCESS) {
                    258:         goto exit;
                    259:     }
                    260: 
                    261:     //
                    262:     // now loop thru the counter names looking for the following counters:
                    263:     //
                    264:     //      1.  "Process"           process name
                    265:     //      2.  "ID Process"        process id
                    266:     //
                    267:     // the buffer contains multiple null terminated strings and then
                    268:     // finally null terminated at the end.  the strings are in pairs of
                    269:     // counter number and counter name.
                    270:     //
                    271: 
                    272:     p = buf;
                    273:     while (*p) {
                    274:         if (stricmp(p, PROCESS_COUNTER) == 0) {
                    275:             //
                    276:             // look backwards for the counter number
                    277:             //
                    278:             for( p2=p-2; isdigit(*p2); p2--) ;
                    279:             strcpy( szSubKey, p2+1 );
                    280:         }
                    281:         else
                    282:         if (stricmp(p, PROCESSID_COUNTER) == 0) {
                    283:             //
                    284:             // look backwards for the counter number
                    285:             //
                    286:             for( p2=p-2; isdigit(*p2); p2--) ;
                    287:             dwProcessIdTitle = atol( p2+1 );
                    288:         }
                    289:         //
                    290:         // next string
                    291:         //
                    292:         p += (strlen(p) + 1);
                    293:     }
                    294: 
                    295:     //
                    296:     // free the counter names buffer
                    297:     //
                    298:     free( buf );
                    299: 
                    300: 
                    301:     //
                    302:     // allocate the initial buffer for the performance data
                    303:     //
                    304:     dwSize = INITIAL_SIZE;
                    305:     buf = malloc( dwSize );
                    306:     if (buf == NULL) {
                    307:         goto exit;
                    308:     }
                    309:     memset( buf, 0, dwSize );
                    310: 
                    311: 
                    312:     while (TRUE) {
                    313: 
                    314:         rc = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
                    315:                               szSubKey,
                    316:                               NULL,
                    317:                               &dwType,
                    318:                               buf,
                    319:                               &dwSize
                    320:                             );
                    321: 
                    322:         pPerf = (PPERF_DATA_BLOCK) buf;
                    323: 
                    324:         //
                    325:         // check for success and valid perf data block signature
                    326:         //
                    327:         if ((rc == ERROR_SUCCESS) &&
                    328:             (dwSize > 0) &&
                    329:             (pPerf)->Signature[0] == (WCHAR)'P' &&
                    330:             (pPerf)->Signature[1] == (WCHAR)'E' &&
                    331:             (pPerf)->Signature[2] == (WCHAR)'R' &&
                    332:             (pPerf)->Signature[3] == (WCHAR)'F' ) {
                    333:             break;
                    334:         }
                    335: 
                    336:         //
                    337:         // if buffer is not big enough, reallocate and try again
                    338:         //
                    339:         if (rc == ERROR_MORE_DATA) {
                    340:             dwSize += EXTEND_SIZE;
                    341:             buf = realloc( buf, dwSize );
                    342:             memset( buf, 0, dwSize );
                    343:         }
                    344:         else {
                    345:             goto exit;
                    346:         }
                    347:     }
                    348: 
                    349:     //
                    350:     // set the perf_object_type pointer
                    351:     //
                    352:     pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);
                    353: 
                    354:     //
                    355:     // loop thru the performance counter definition records looking
                    356:     // for the process id counter and then save its offset
                    357:     //
                    358:     pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);
                    359:     for (i=0; i<(DWORD)pObj->NumCounters; i++) {
                    360:         if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle) {
                    361:             dwProcessIdCounter = pCounterDef->CounterOffset;
                    362:             break;
                    363:         }
                    364:         pCounterDef++;
                    365:     }
                    366: 
                    367:     //
                    368:     // allocate a buffer for the returned task list
                    369:     //
                    370:     dwSize = pObj->NumInstances * sizeof(TASK_LIST);
                    371:     pTask = pTaskReturn = (PTASK_LIST) malloc( dwSize );
                    372:     if (pTask == NULL) {
                    373:         goto exit;
                    374:     }
                    375:     memset( pTask, 0, dwSize);
                    376: 
                    377:     //
                    378:     // loop thru the performance instance data extracting each process name
                    379:     // and process id
                    380:     //
                    381:     *pdwNumTasks = pObj->NumInstances;
                    382:     pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);
                    383:     for (i=0; i<(DWORD)pObj->NumInstances; i++) {
                    384:         //
                    385:         // pointer to the process name
                    386:         //
                    387:         p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);
                    388: 
                    389:         //
                    390:         // convert it to ascii
                    391:         //
                    392:         rc = WideCharToMultiByte( CP_ACP,
                    393:                                   0,
                    394:                                   (LPCWSTR)p,
                    395:                                   -1,
                    396:                                   szProcessName,
                    397:                                   sizeof(szProcessName),
                    398:                                   NULL,
                    399:                                   NULL
                    400:                                 );
                    401: 
                    402:         if (!rc) {
                    403:             //
                    404:             // if we cant convert the string then use a bogus value
                    405:             //
                    406:             strcpy( pTask->ProcessName, UNKNOWN_TASK );
                    407:         }
                    408: 
                    409:         if (strlen(szProcessName)+4 <= sizeof(pTask->ProcessName)) {
                    410:             strcpy( pTask->ProcessName, szProcessName );
                    411:             strcat( pTask->ProcessName, ".exe" );
                    412:         }
                    413: 
                    414:         //
                    415:         // get the process id
                    416:         //
                    417:         pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);
                    418:         pTask->dwProcessId = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));
                    419: 
                    420:         //
                    421:         // next process
                    422:         //
                    423:         pTask++;
                    424:         pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);
                    425:     }
                    426: 
                    427: exit:
                    428:     if (buf) {
                    429:         free( buf );
                    430:     }
                    431: 
                    432:     RegCloseKey( hKeyNames );
                    433: 
                    434:     return pTaskReturn;
                    435: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.