/* * ntparent.c - demonstrates retrieving the parent process ID * on Windows NT using the NT Native API * * * * * © 1999 ProXima - Engineering Office for Software Development and Consulting * * http://www.proxima.de * proxima@proxima.de * * Revision: * * 07-May-199 jk v1.0 initial state * * * * * Compile: cl ntparent.c * * That's it ;-) * * */ #include #include #include #define _NAME "parent - ProXima Process Parent Detector for Windows NT V1.0" #define _WWW "WWW:\thttp://www.proxima.de" #define _EMAIL "EMail:\tproxima@proxima.de" #define _USAGE "\n\nUsage:\tparent \n\n" // NT specific data types and enumerations typedef LONG NTSTATUS; typedef struct _tagPROCESS_BASIC_INFORMATION { DWORD ExitStatus; DWORD PebBaseAddress; DWORD AffinityMask; DWORD BasePriority; ULONG UniqueProcessId; ULONG InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION; typedef enum _tagPROCESSINFOCLASS { ProcessBasicInformation, ProcessQuotaLimits, ProcessIoCounters, ProcessVmCounters, ProcessTimes, ProcessBasePriority, ProcessRaisePriority, ProcessDebugPort, ProcessExceptionPort, ProcessAccessToken, ProcessLdtInformation, ProcessLdtSize, ProcessDefaultHardErrorMode, ProcessIoPortHandlers, // Note: this is kernel mode only ProcessPooledUsageAndLimits, ProcessWorkingSetWatch, ProcessUserModeIOPL, ProcessEnableAlignmentFaultFixup, ProcessPriorityClass, MaxProcessInfoClass } PROCESSINFOCLASS; // convenience macros #define DYNLOADED_FPTR( ptrname, procname, dllname)\ FPTR_##procname ptrname = \ ( FPTR_##procname ) GetProcAddress ( GetModuleHandle ( _TEXT( #dllname)), #procname); #define CREATE_DYNFUNC_5( ptrname, procname, dllname, rettype, callconv, a1, a2, a3, a4, a5)\ typedef rettype (callconv *FPTR_##procname) ( a1, a2, a3, a4, a5);\ DYNLOADED_FPTR( ptrname, procname, dllname); // foward declarations DWORD GetParentProcessID ( DWORD dwPID); BOOL IsNT (); /*__pxm_c() * * Function: int main ( int argc, char** argv) * * Description: * * main entry point * * Parameters: * * * Return value: * * */ int main ( int argc, char** argv) { DWORD dwPID; char* pc; // print banner printf ( "\n\n%s %s %s\n\n%s\n%s\n\n\n", _NAME, __DATE__, __TIME__, _WWW, _EMAIL ); // bail out if not NT if ( !IsNT ()) { printf ( "This program can only be used on Windows NT!\n"); return ( -1); } // check command line argument count, must be 2 if ( 2 != argc) { printf ( _USAGE); return ( -2); } // 2nd arg must be a valid decimal number dwPID = ( DWORD) strtol ( *( argv + 1), &pc, 10); if ( *pc) { printf ( _USAGE); return ( -3); } printf ( "Parent PID for '%d' is '%d'\n", dwPID, GetParentProcessID ( dwPID) ); return ( 0); } /*__pxm_c() * * Function: BOOL IsNT () * * Description: * * Checks if the caller is running on WinNT * * Parameters: * * * Return value: * * TRUE if NT, false otherwise * */ BOOL IsNT () { OSVERSIONINFO osviVerInfo; osviVerInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO); GetVersionEx ( &osviVerInfo); return ( VER_PLATFORM_WIN32_NT == osviVerInfo.dwPlatformId); } /*__pxm_c( WinNT) * * Function: DWORD GetParentProcessID ( DWORD dwPID) * * Description: * * Returns the parent process ID of the process specified in the * 'dwPID' parameter. * * * Parameters: * * dwPID - process ID to find parent for * * Return value: * * parent process ID on success, -1 otherwise * */ DWORD GetParentProcessID ( DWORD dwPID) { NTSTATUS ntStatus; DWORD dwParentPID = 0xffffffff; HANDLE hProcess; PROCESS_BASIC_INFORMATION pbi; ULONG ulRetLen; // create entry point for 'NtQueryInformationProcess()' CREATE_DYNFUNC_5 ( NtQueryInformationProcess, NtQueryInformationProcess, ntdll, NTSTATUS, __stdcall, HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG ); // get process handle hProcess = OpenProcess ( PROCESS_QUERY_INFORMATION, FALSE, dwPID ); // could fail due to invalid PID or insufficiant privileges if ( !hProcess) return ( 0xffffffff); // gather information ntStatus = NtQueryInformationProcess ( hProcess, ProcessBasicInformation, ( void*) &pbi, sizeof ( PROCESS_BASIC_INFORMATION), &ulRetLen ); // copy PID on success if ( !ntStatus) dwParentPID = pbi.InheritedFromUniqueProcessId; CloseHandle ( hProcess); return ( dwParentPID); }