288 lines
8 KiB
C++
288 lines
8 KiB
C++
/*******************************************************************************
|
|
*
|
|
* 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 <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntcsrsrv.h>
|
|
#include <ntlsa.h>
|
|
#include <ntsam.h>
|
|
#include <windows.h>
|
|
#include <lmaccess.h>
|
|
#include <lmserver.h>
|
|
#include <lmwksta.h>
|
|
#include <lmapibuf.h>
|
|
#include <winsta.h>
|
|
|
|
#include <procs.h>
|
|
|
|
|
|
#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
|