|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.