/******************************************************************************* * * procs.cpp * * implementation of ProcEnumerateProcesses function * * copyright notice: Copyright 1997, Citrix Systems Inc. * Copyright (c) 1998 - 1999 Microsoft Corporation * * $Author: BillG $ Don Messerli * * $Log: X:\NT\PRIVATE\UTILS\CITRIX\WINUTILS\WINADMIN\VCS\PROCS.CPP $ * * Rev 1.1 02 Dec 1997 16:30:10 BillG * alpha update * * Rev 1.0 30 Jul 1997 17:12:02 butchd * Initial revision. * *******************************************************************************/ #ifndef UNICODE #define UNICODE #endif //#ifndef _X86_ //#define _X86_ //#endif #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_PROCESSNAME 18 VOID FetchProcessIDAndImageName(PTS_SYS_PROCESS_INFORMATION ProcessInfo, PULONG pPID, LPTSTR pImageName) { int i; TCHAR ImageName[MAX_PROCESSNAME+1]; // // Set the PID. // *pPID = (ULONG)(ULONG_PTR)(ProcessInfo->UniqueProcessId); // // Fetch and convert counted UNICODE string into a NULL // terminated UNICODE string. // if( !ProcessInfo->ImageName.Length == 0 ) { wcsncpy( ImageName, ProcessInfo->ImageName.Buffer, min(MAX_PROCESSNAME, ProcessInfo->ImageName.Length/2)); } ImageName[min(MAX_PROCESSNAME, ProcessInfo->ImageName.Length/2)] = 0; /* * We're UNICODE: simply copy the converted ImageName buffer * into the m_PLObject->m_ImageName field. */ lstrcpy(pImageName, ImageName); _wcslwr(pImageName); } /******************************************************************************* * * EnumerateProcesses - WinFrame helper function * * Enumerate all processes in system, passing back one with each call to this * routine. * * * ENTRY: * hServer: * handle of the aimed server * pEnumToken * pointer to the current token * pImageName (output) * Points to a buffer to store process name in. NOTE: this buffer is expected * to be at least MAX_PROCESSNAME+1 characters in size. * pLogonId (output) * Points to variable to store process LogonId in. * pPID (output) * Points to variable to store process PID in. * ppSID (output) * Points to a pointer which is set to point to the process' SID on exit. * * EXIT: * TRUE - information for the next process in the system has been placed into * the referenced PLObject and pSID variables. * FALSE - if the enumeration is done, GetLastError() will contain the * ERROR_NO_MORE_ITEMS error code. If another (true error) is * encountered, that code will be set. * ******************************************************************************/ BOOL WINAPI ProcEnumerateProcesses( HANDLE hServer, PENUMTOKEN pEnumToken, LPTSTR pImageName, PULONG pLogonId, PULONG pPID, PSID *ppSID ) { int i; PTS_SYS_PROCESS_INFORMATION ProcessInfo; PCITRIX_PROCESS_INFORMATION CitrixInfo; if ((pEnumToken == NULL) || (pImageName == NULL) || (pLogonId == NULL) || (pPID == NULL) || (ppSID == NULL) ) { return FALSE; } /* * Check for done with enumeration. */ if ( pEnumToken->Current == (ULONG)-1 ) { SetLastError(ERROR_NO_MORE_ITEMS); if (pEnumToken->bGAP == TRUE) // we used the GAP (GetAllProcesses) interface { // // Free ProcessArray and all child pointers allocated by the client stub. // WinStationFreeGAPMemory(GAP_LEVEL_BASIC, pEnumToken->ProcessArray, pEnumToken->NumberOfProcesses); pEnumToken->ProcessArray = NULL; pEnumToken->NumberOfProcesses = 0; return(FALSE); } else // we used the old Hydra 4 interface { WinStationFreeMemory(pEnumToken->pProcessBuffer); pEnumToken->pProcessBuffer = NULL; return(FALSE); } } /* * Check for beginning enumeration. */ if ( pEnumToken->Current == 0 ) { // // Try the new interface first (NT5 server ?) // if (WinStationGetAllProcesses( hServer, GAP_LEVEL_BASIC, &(pEnumToken->NumberOfProcesses), (PVOID *)&(pEnumToken->ProcessArray) ) ) { pEnumToken->bGAP = TRUE; } else { // // Check the return code indicating that the interface is not available. // DWORD dwError = GetLastError(); if (dwError != RPC_S_PROCNUM_OUT_OF_RANGE) { pEnumToken->pProcessBuffer = NULL; return(FALSE); } else // maybe a Hydra 4 server ? { if ( WinStationEnumerateProcesses( hServer, (PVOID *)&(pEnumToken->pProcessBuffer))) { pEnumToken->bGAP = FALSE; } else { DWORD error = GetLastError(); if(pEnumToken->pProcessBuffer != NULL) { WinStationFreeMemory(pEnumToken->pProcessBuffer); pEnumToken->pProcessBuffer = NULL; } return(FALSE); } } } } if (pEnumToken->bGAP == TRUE) { ProcessInfo = (PTS_SYS_PROCESS_INFORMATION)((pEnumToken->ProcessArray)[pEnumToken->Current].pTsProcessInfo); FetchProcessIDAndImageName(ProcessInfo,pPID,pImageName); // // Set the SessionId // *pLogonId = ProcessInfo->SessionId; // // set the SID // *ppSID = (pEnumToken->ProcessArray)[pEnumToken->Current].pSid; (pEnumToken->Current)++; if ( (pEnumToken->Current) >= (pEnumToken->NumberOfProcesses) ) { pEnumToken->Current = (ULONG)-1; // sets the end of enumeration } } else { /* * Parse and store the next process' information. */ ProcessInfo = (PTS_SYS_PROCESS_INFORMATION) &(((PUCHAR)(pEnumToken->pProcessBuffer))[pEnumToken->Current]); FetchProcessIDAndImageName(ProcessInfo,pPID,pImageName); /* * Point to the CITRIX_INFORMATION which follows the Threads */ CitrixInfo = (PCITRIX_PROCESS_INFORMATION) (((PUCHAR)ProcessInfo) + SIZEOF_TS4_SYSTEM_PROCESS_INFORMATION + (SIZEOF_TS4_SYSTEM_THREAD_INFORMATION * (int)ProcessInfo->NumberOfThreads)); /* * Fetch the LogonId and point to this SID for the primary * thread to use (copy). */ if( CitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) { *pLogonId = CitrixInfo->LogonId; *ppSID = CitrixInfo->ProcessSid; } else { *pLogonId = (ULONG)(-1); *ppSID = NULL; } /* * Increment the total offset count for next call. If this is the * last process, set the offset to -1 so that next call will indicate * the end of the enumeration. */ if ( ProcessInfo->NextEntryOffset != 0 ) (pEnumToken->Current) += ProcessInfo->NextEntryOffset; else pEnumToken->Current = (ULONG)-1; } return(TRUE); } // end EnumerateProcesses