765 lines
23 KiB
C
765 lines
23 KiB
C
/*******************************************************************************
|
|
* process.c
|
|
*
|
|
* Published Terminal Server APIs
|
|
*
|
|
* - process routines
|
|
*
|
|
* Copyright 1998, Citrix Systems Inc.
|
|
* Copyright (C) 1997-1999 Microsoft Corp.
|
|
/******************************************************************************/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntddkbd.h>
|
|
#include <ntddmou.h>
|
|
#include <windows.h>
|
|
#include <winbase.h>
|
|
#include <winerror.h>
|
|
#include <allproc.h>
|
|
|
|
#if(WINVER >= 0x0500)
|
|
#include <ntstatus.h>
|
|
#include <winsta.h>
|
|
#else
|
|
#include <citrix\cxstatus.h>
|
|
#include <citrix\winsta.h>
|
|
#endif
|
|
|
|
#include <utildll.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <wtsapi32.h>
|
|
|
|
|
|
/*=============================================================================
|
|
== External procedures defined
|
|
=============================================================================*/
|
|
|
|
BOOL WINAPI WTSEnumerateProcessesW( HANDLE, DWORD, DWORD, PWTS_PROCESS_INFOW *, DWORD * );
|
|
BOOL WINAPI WTSEnumerateProcessesA( HANDLE, DWORD, DWORD, PWTS_PROCESS_INFOA *, DWORD * );
|
|
BOOL WINAPI WTSTerminateProcess( HANDLE, DWORD, DWORD );
|
|
|
|
|
|
/*=============================================================================
|
|
== Procedures used
|
|
=============================================================================*/
|
|
|
|
VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
|
|
VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
|
|
|
|
/*=============================================================================
|
|
* Internal function
|
|
=============================================================================*/
|
|
|
|
BOOL
|
|
GetProcessSid(HANDLE Server,
|
|
HANDLE hUniqueProcessId,
|
|
LARGE_INTEGER ProcessStartTime,
|
|
PBYTE * pProcessUserSid //Return the SID (allocated here..)
|
|
);
|
|
|
|
/*=======================================================================
|
|
* Private structure definitions
|
|
*=========================================================================*/
|
|
typedef struct _SID_INFO {
|
|
struct _SID_INFO * pNext;
|
|
PBYTE pSid;
|
|
} SID_INFO;
|
|
|
|
/****************************************************************************
|
|
*
|
|
* WTSEnumerateProcessesW (UNICODE)
|
|
*
|
|
* Returns a list of Terminal Server Processes on the specified server
|
|
*
|
|
* ENTRY:
|
|
* hServer (input)
|
|
* Handle to a Terminal server (or WTS_CURRENT_SERVER)
|
|
* Reserved (input)
|
|
* Must be zero
|
|
* Version (input)
|
|
* Version of the enumeration request (must be 1)
|
|
* ppProcessInfo (output)
|
|
* Points to the address of a variable to receive the enumeration results,
|
|
* which are returned as an array of WTS_PROCESS_INFO structures. The
|
|
* buffer is allocated within this API and is disposed of using
|
|
* WTSFreeMemory.
|
|
* pCount (output)
|
|
* Points to the address of a variable to receive the number of
|
|
* WTS_PROCESS_INFO structures returned
|
|
*
|
|
* EXIT:
|
|
*
|
|
* TRUE -- The enumerate operation succeeded.
|
|
*
|
|
* FALSE -- The operation failed. Extended error status is available
|
|
* using GetLastError.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#if(WINVER >= 0x0500)
|
|
BOOL
|
|
WINAPI
|
|
WTSEnumerateProcessesW(
|
|
IN HANDLE hServer,
|
|
IN DWORD Reserved,
|
|
IN DWORD Version,
|
|
OUT PWTS_PROCESS_INFOW * ppProcessInfo,
|
|
OUT DWORD * pCount
|
|
)
|
|
{
|
|
PBYTE pProcessBuffer = NULL;
|
|
PTS_SYS_PROCESS_INFORMATION pProcessInfo;
|
|
PCITRIX_PROCESS_INFORMATION pCitrixInfo;
|
|
ULONG ProcessCount;
|
|
ULONG Offset;
|
|
ULONG DataLength;
|
|
PWTS_PROCESS_INFOW pProcessW;
|
|
PBYTE pProcessData;
|
|
ULONG i;
|
|
ULONG Length;
|
|
PTS_ALL_PROCESSES_INFO ProcessArray = NULL;
|
|
DWORD dwError;
|
|
|
|
|
|
SID_INFO sidInfoHead; //The head of the Sid temp storage
|
|
SID_INFO * pSidInfo; //Point to a list of temp storage for the
|
|
//variable length SID
|
|
sidInfoHead.pNext = NULL;
|
|
sidInfoHead.pSid = NULL;
|
|
pSidInfo = &sidInfoHead;
|
|
|
|
|
|
/*
|
|
* Validate parameters
|
|
*/
|
|
if ( Reserved != 0 || Version != 1 ) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
goto badparam;
|
|
}
|
|
|
|
if (!ppProcessInfo || !pCount) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
goto badparam;
|
|
}
|
|
|
|
//
|
|
// Try the new interface first (Windows 2000 server)
|
|
//
|
|
if (WinStationGetAllProcesses( hServer,
|
|
GAP_LEVEL_BASIC,
|
|
&ProcessCount,
|
|
&ProcessArray) )
|
|
{
|
|
DataLength = 0;
|
|
|
|
for (i=0; i<ProcessCount; i++)
|
|
{
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION)(ProcessArray[i].pTsProcessInfo);
|
|
DataLength += (pProcessInfo->ImageName.Length + sizeof(WCHAR));
|
|
if (ProcessArray[i].pSid)
|
|
{
|
|
DataLength += GetLengthSid( ProcessArray[i].pSid );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Allocate user buffer
|
|
*/
|
|
pProcessW = LocalAlloc( LPTR, (ProcessCount * sizeof(WTS_PROCESS_INFOW)) + DataLength );
|
|
if ( pProcessW == NULL ) {
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
goto GAPErrorReturn;
|
|
}
|
|
|
|
/*
|
|
* Update user parameters
|
|
*/
|
|
*ppProcessInfo = pProcessW;
|
|
*pCount = ProcessCount;
|
|
|
|
/*
|
|
* Copy data to new buffer
|
|
*/
|
|
pProcessData = (PBYTE)pProcessW + (ProcessCount * sizeof(WTS_PROCESS_INFOW));
|
|
for ( i=0; i < ProcessCount; i++ ) {
|
|
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION)(ProcessArray[i].pTsProcessInfo);
|
|
|
|
Length = pProcessInfo->ImageName.Length; // number of bytes
|
|
|
|
pProcessW->pProcessName = (LPWSTR) pProcessData;
|
|
memcpy( pProcessData, pProcessInfo->ImageName.Buffer, Length );
|
|
*(pProcessData += Length) = (WCHAR)0;
|
|
pProcessData += sizeof(WCHAR);
|
|
|
|
pProcessW->ProcessId = (ULONG)(ULONG_PTR)pProcessInfo->UniqueProcessId;
|
|
pProcessW->SessionId = pProcessInfo->SessionId;
|
|
if (ProcessArray[i].pSid)
|
|
{
|
|
Length = GetLengthSid( ProcessArray[i].pSid );
|
|
pProcessW->pUserSid = (LPWSTR) pProcessData;
|
|
memcpy( pProcessData, ProcessArray[i].pSid, Length );
|
|
pProcessData += Length;
|
|
}
|
|
|
|
pProcessW++;
|
|
}
|
|
//
|
|
// Free ppProcessArray and all child pointers allocated by the client stub.
|
|
//
|
|
WinStationFreeGAPMemory(GAP_LEVEL_BASIC, ProcessArray, ProcessCount);
|
|
|
|
}
|
|
else // Maybe a TS 4.0 server ?
|
|
{
|
|
//
|
|
// Check the return code indicating that the interface is not available.
|
|
//
|
|
dwError = GetLastError();
|
|
if (dwError != RPC_S_PROCNUM_OUT_OF_RANGE)
|
|
{
|
|
goto badenum;
|
|
}
|
|
else
|
|
{
|
|
// It might be a TS4.0 server
|
|
// Try the old interface
|
|
//
|
|
//
|
|
// Enumerate Processes and check for an error
|
|
//
|
|
if ( !WinStationEnumerateProcesses( hServer, &pProcessBuffer ) ) {
|
|
goto badenum;
|
|
}
|
|
|
|
//
|
|
// Count the number of processes and total up the size of the data
|
|
//
|
|
ProcessCount = 0;
|
|
DataLength = 0;
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
|
|
Offset = 0;
|
|
do {
|
|
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
|
|
|
|
ProcessCount++;
|
|
|
|
DataLength += (pProcessInfo->ImageName.Length + sizeof(WCHAR));
|
|
|
|
pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
|
|
(((PUCHAR)pProcessInfo) +
|
|
SIZEOF_TS4_SYSTEM_PROCESS_INFORMATION +
|
|
(SIZEOF_TS4_SYSTEM_THREAD_INFORMATION * (int)pProcessInfo->NumberOfThreads));
|
|
|
|
if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
|
|
if ( pCitrixInfo->ProcessSid )
|
|
DataLength += GetLengthSid( pCitrixInfo->ProcessSid );
|
|
}
|
|
|
|
Offset = pProcessInfo->NextEntryOffset;
|
|
|
|
} while ( Offset != 0 );
|
|
|
|
/*
|
|
* Allocate user buffer
|
|
*/
|
|
pProcessW = LocalAlloc( LPTR, (ProcessCount * sizeof(WTS_PROCESS_INFOW)) + DataLength );
|
|
if ( pProcessW == NULL ) {
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
goto badalloc;
|
|
}
|
|
|
|
/*
|
|
* Update user parameters
|
|
*/
|
|
*ppProcessInfo = pProcessW;
|
|
*pCount = ProcessCount;
|
|
|
|
/*
|
|
* Copy data to new buffer
|
|
*/
|
|
pProcessData = (PBYTE)pProcessW + (ProcessCount * sizeof(WTS_PROCESS_INFOW));
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
|
|
Offset = 0;
|
|
for ( i=0; i < ProcessCount; i++ ) {
|
|
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
|
|
|
|
Length = pProcessInfo->ImageName.Length; // number of bytes
|
|
|
|
pProcessW->pProcessName = (LPWSTR) pProcessData;
|
|
memcpy( pProcessData, pProcessInfo->ImageName.Buffer, Length );
|
|
*(pProcessData += Length) = (WCHAR)0;
|
|
pProcessData += sizeof(WCHAR);
|
|
|
|
pProcessW->ProcessId = pProcessInfo->UniqueProcessId;
|
|
|
|
/*
|
|
* Point to the CITRIX_INFORMATION which follows the Threads
|
|
*/
|
|
pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
|
|
(((PUCHAR)pProcessInfo) +
|
|
SIZEOF_TS4_SYSTEM_PROCESS_INFORMATION +
|
|
(SIZEOF_TS4_SYSTEM_THREAD_INFORMATION * (int)pProcessInfo->NumberOfThreads));
|
|
|
|
if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
|
|
pProcessW->SessionId = pCitrixInfo->LogonId;
|
|
if ( pCitrixInfo->ProcessSid ) {
|
|
Length = GetLengthSid( pCitrixInfo->ProcessSid );
|
|
pProcessW->pUserSid = (LPWSTR) pProcessData;
|
|
memcpy( pProcessData, pCitrixInfo->ProcessSid, Length );
|
|
pProcessData += Length;
|
|
}
|
|
} else {
|
|
pProcessW->SessionId = (ULONG) -1;
|
|
}
|
|
|
|
pProcessW++;
|
|
Offset = pProcessInfo->NextEntryOffset;
|
|
}
|
|
|
|
/*
|
|
* Free original Process list buffer
|
|
*/
|
|
WinStationFreeMemory( pProcessBuffer );
|
|
|
|
}
|
|
}
|
|
return( TRUE );
|
|
|
|
/*=============================================================================
|
|
== Error return
|
|
=============================================================================*/
|
|
|
|
GAPErrorReturn:
|
|
//
|
|
// Free ppProcessArray and all child pointers allocated by the client stub.
|
|
//
|
|
WinStationFreeGAPMemory(GAP_LEVEL_BASIC, ProcessArray, ProcessCount);
|
|
goto enderror;
|
|
|
|
badalloc:
|
|
WinStationFreeMemory( pProcessBuffer );
|
|
|
|
badenum:
|
|
badparam:
|
|
enderror:
|
|
if (ppProcessInfo) *ppProcessInfo = NULL;
|
|
if (pCount) *pCount = 0;
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
#else //#if(WINVER>=0x0500)
|
|
|
|
BOOL
|
|
WINAPI
|
|
WTSEnumerateProcessesW(
|
|
IN HANDLE hServer,
|
|
IN DWORD Reserved,
|
|
IN DWORD Version,
|
|
OUT PWTS_PROCESS_INFOW * ppProcessInfo,
|
|
OUT DWORD * pCount
|
|
)
|
|
{
|
|
PBYTE pProcessBuffer;
|
|
PTS_SYS_PROCESS_INFORMATION pProcessInfo;
|
|
PCITRIX_PROCESS_INFORMATION pCitrixInfo;
|
|
ULONG ProcessCount;
|
|
ULONG Offset;
|
|
ULONG DataLength;
|
|
PWTS_PROCESS_INFOW pProcessW;
|
|
PBYTE pProcessData;
|
|
ULONG i;
|
|
ULONG Length;
|
|
|
|
/*
|
|
* Validate parameters
|
|
*/
|
|
if ( Reserved != 0 || Version != 1 ) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
goto badparam;
|
|
}
|
|
|
|
|
|
if (!ppProcessInfo || !pCount) {
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
goto badparam;
|
|
}
|
|
|
|
/*
|
|
* Enumerate Processes and check for an error
|
|
*/
|
|
if ( !WinStationEnumerateProcesses( hServer, &pProcessBuffer ) ) {
|
|
goto badenum;
|
|
}
|
|
|
|
/*
|
|
* Count the number of processes and total up the size of the data
|
|
*/
|
|
ProcessCount = 0;
|
|
DataLength = 0;
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
|
|
Offset = 0;
|
|
do {
|
|
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
|
|
|
|
ProcessCount++;
|
|
|
|
DataLength += (pProcessInfo->ImageName.Length + sizeof(WCHAR));
|
|
|
|
pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
|
|
((PBYTE)pProcessInfo +
|
|
sizeof(SYSTEM_PROCESS_INFORMATION) +
|
|
(sizeof(SYSTEM_THREAD_INFORMATION) *
|
|
pProcessInfo->NumberOfThreads));
|
|
|
|
if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
|
|
if ( pCitrixInfo->ProcessSid )
|
|
DataLength += GetLengthSid( pCitrixInfo->ProcessSid );
|
|
}
|
|
|
|
Offset = pProcessInfo->NextEntryOffset;
|
|
|
|
} while ( Offset != 0 );
|
|
|
|
/*
|
|
* Allocate user buffer
|
|
*/
|
|
pProcessW = LocalAlloc( LPTR, (ProcessCount * sizeof(WTS_PROCESS_INFOW)) + DataLength );
|
|
if ( pProcessW == NULL ) {
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
goto badalloc;
|
|
}
|
|
|
|
/*
|
|
* Update user parameters
|
|
*/
|
|
*ppProcessInfo = pProcessW;
|
|
*pCount = ProcessCount;
|
|
|
|
/*
|
|
* Copy data to new buffer
|
|
*/
|
|
pProcessData = (PBYTE)pProcessW + (ProcessCount * sizeof(WTS_PROCESS_INFOW));
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) pProcessBuffer;
|
|
Offset = 0;
|
|
for ( i=0; i < ProcessCount; i++ ) {
|
|
|
|
pProcessInfo = (PTS_SYS_PROCESS_INFORMATION) ((PBYTE)pProcessInfo + Offset);
|
|
|
|
Length = pProcessInfo->ImageName.Length; // number of bytes
|
|
|
|
pProcessW->pProcessName = (LPWSTR) pProcessData;
|
|
memcpy( pProcessData, pProcessInfo->ImageName.Buffer, Length );
|
|
*(pProcessData += Length) = (WCHAR)0;
|
|
pProcessData += sizeof(WCHAR);
|
|
|
|
pProcessW->ProcessId = (ULONG) pProcessInfo->UniqueProcessId;
|
|
|
|
/*
|
|
* Point to the CITRIX_INFORMATION which follows the Threads
|
|
*/
|
|
pCitrixInfo = (PCITRIX_PROCESS_INFORMATION)
|
|
((PBYTE)pProcessInfo +
|
|
sizeof(SYSTEM_PROCESS_INFORMATION) +
|
|
(sizeof(SYSTEM_THREAD_INFORMATION) *
|
|
pProcessInfo->NumberOfThreads));
|
|
|
|
if ( pCitrixInfo->MagicNumber == CITRIX_PROCESS_INFO_MAGIC ) {
|
|
pProcessW->SessionId = pCitrixInfo->LogonId;
|
|
if ( pCitrixInfo->ProcessSid ) {
|
|
Length = GetLengthSid( pCitrixInfo->ProcessSid );
|
|
pProcessW->pUserSid = (LPWSTR) pProcessData;
|
|
memcpy( pProcessData, pCitrixInfo->ProcessSid, Length );
|
|
pProcessData += Length;
|
|
}
|
|
} else {
|
|
pProcessW->SessionId = (ULONG) -1;
|
|
}
|
|
|
|
pProcessW++;
|
|
Offset = pProcessInfo->NextEntryOffset;
|
|
}
|
|
|
|
/*
|
|
* Free original Process list buffer
|
|
*/
|
|
WinStationFreeMemory( pProcessBuffer );
|
|
|
|
return( TRUE );
|
|
|
|
/*=============================================================================
|
|
== Error return
|
|
=============================================================================*/
|
|
|
|
badalloc:
|
|
WinStationFreeMemory( pProcessBuffer );
|
|
|
|
badenum:
|
|
badparam:
|
|
if (ppProcessInfo) *ppProcessInfo = NULL;
|
|
if (pCount) *pCount = 0;
|
|
|
|
return( FALSE );
|
|
}
|
|
#endif //#if(WINVER>=0x0500)
|
|
|
|
/****************************************************************************
|
|
*
|
|
* WTSEnumerateProcessesA (ANSI stub)
|
|
*
|
|
* Returns a list of Terminal Server Processes on the specified server
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* see WTSEnumerateProcessesW
|
|
*
|
|
* EXIT:
|
|
*
|
|
* TRUE -- The enumerate operation succeeded.
|
|
*
|
|
* FALSE -- The operation failed. Extended error status is available
|
|
* using GetLastError.
|
|
*
|
|
****************************************************************************/
|
|
|
|
BOOL
|
|
WINAPI
|
|
WTSEnumerateProcessesA(
|
|
IN HANDLE hServer,
|
|
IN DWORD Reserved,
|
|
IN DWORD Version,
|
|
OUT PWTS_PROCESS_INFOA * ppProcessInfo,
|
|
OUT DWORD * pCount
|
|
)
|
|
{
|
|
PWTS_PROCESS_INFOW pProcessW;
|
|
PWTS_PROCESS_INFOA pProcessA;
|
|
PBYTE pProcessData;
|
|
ULONG Length;
|
|
ULONG DataLength; // number of bytes of name data
|
|
ULONG NameCount;
|
|
ULONG i;
|
|
|
|
/*
|
|
* Enumerate processes (UNICODE)
|
|
*/
|
|
if ( !WTSEnumerateProcessesW( hServer,
|
|
Reserved,
|
|
Version,
|
|
&pProcessW,
|
|
&NameCount ) ) {
|
|
goto badenum;
|
|
}
|
|
|
|
/*
|
|
* Calculate the length of the name data
|
|
*/
|
|
for ( i=0, DataLength=0; i < NameCount; i++ ) {
|
|
DataLength += (wcslen(pProcessW[i].pProcessName) + 1);
|
|
if ( pProcessW[i].pUserSid )
|
|
DataLength += GetLengthSid( pProcessW[i].pUserSid );
|
|
}
|
|
|
|
/*
|
|
* Allocate user buffer
|
|
*/
|
|
pProcessA = LocalAlloc( LPTR, (NameCount * sizeof(WTS_PROCESS_INFOA)) + DataLength );
|
|
if ( pProcessA == NULL )
|
|
goto badalloc2;
|
|
|
|
/*
|
|
* Convert unicode process list to ansi
|
|
*/
|
|
pProcessData = (PBYTE)pProcessA + (NameCount * sizeof(WTS_PROCESS_INFOA));
|
|
for ( i=0; i < NameCount; i++ ) {
|
|
|
|
pProcessA[i].SessionId = pProcessW[i].SessionId;
|
|
pProcessA[i].ProcessId = pProcessW[i].ProcessId;
|
|
|
|
Length = wcslen(pProcessW[i].pProcessName) + 1;
|
|
pProcessA[i].pProcessName = pProcessData;
|
|
UnicodeToAnsi( pProcessData, DataLength, pProcessW[i].pProcessName );
|
|
DataLength -= Length;
|
|
pProcessData += Length;
|
|
|
|
if ( pProcessW[i].pUserSid ) {
|
|
Length = GetLengthSid( pProcessW[i].pUserSid );
|
|
pProcessA[i].pUserSid = pProcessData;
|
|
memcpy( pProcessData, pProcessW[i].pUserSid, Length );
|
|
DataLength -= Length;
|
|
pProcessData += Length;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Free unicode process list buffer
|
|
*/
|
|
LocalFree( pProcessW );
|
|
|
|
/*
|
|
* Update user parameters
|
|
*/
|
|
if (ppProcessInfo) {
|
|
*ppProcessInfo = pProcessA;
|
|
} else {
|
|
SetLastError(ERROR_INVALID_USER_BUFFER);
|
|
return(FALSE);
|
|
}
|
|
if (pCount) {
|
|
*pCount = NameCount;
|
|
} else {
|
|
SetLastError(ERROR_INVALID_USER_BUFFER);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
return( TRUE );
|
|
|
|
/*=============================================================================
|
|
== Error return
|
|
=============================================================================*/
|
|
|
|
|
|
badalloc2:
|
|
LocalFree( pProcessW );
|
|
|
|
badenum:
|
|
// make sure the passed parameter buffer pointer is not NULL
|
|
if (ppProcessInfo) *ppProcessInfo = NULL;
|
|
if (pCount) *pCount = 0;
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* WTSTerminateProcess
|
|
*
|
|
* Terminate the specified process
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* hServer (input)
|
|
* handle to Terminal server
|
|
* ProcessId (input)
|
|
* process id of the process to terminate
|
|
* ExitCode (input)
|
|
* Termination status for each thread in the process
|
|
*
|
|
*
|
|
* EXIT:
|
|
*
|
|
* TRUE -- The terminate operation succeeded.
|
|
*
|
|
* FALSE -- The operation failed. Extended error status is available
|
|
* using GetLastError.
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL WINAPI
|
|
WTSTerminateProcess(
|
|
HANDLE hServer,
|
|
DWORD ProcessId,
|
|
DWORD ExitCode
|
|
)
|
|
{
|
|
return( WinStationTerminateProcess( hServer, ProcessId, ExitCode ) );
|
|
}
|
|
#if(WINVER >= 0x0500)
|
|
//======================================================================//
|
|
// Private functions //
|
|
//======================================================================//
|
|
BOOL
|
|
GetProcessSid(HANDLE hServer,
|
|
HANDLE hUniqueProcessId,
|
|
LARGE_INTEGER ProcessStartTime,
|
|
PBYTE * ppSid //Return the SID (allocated here..)
|
|
)
|
|
{
|
|
DWORD dwSidSize;
|
|
BYTE tmpSid[128]; //temp storage
|
|
FILETIME startTime;
|
|
|
|
dwSidSize = sizeof(tmpSid);
|
|
*ppSid = NULL;
|
|
|
|
//Convert the time format
|
|
startTime.dwLowDateTime = ProcessStartTime.LowPart;
|
|
startTime.dwHighDateTime = ProcessStartTime.HighPart;
|
|
|
|
//-------------------------------------------//
|
|
// Get the SID with the temp Sid storage //
|
|
//-------------------------------------------//
|
|
if (!WinStationGetProcessSid(hServer,
|
|
(DWORD)(ULONG_PTR)hUniqueProcessId,
|
|
startTime,
|
|
(PBYTE)&tmpSid,
|
|
&dwSidSize
|
|
)) {
|
|
//-------------------------------------------//
|
|
// Sid is too big for the temp storage //
|
|
//Get the size of the sid and do it again //
|
|
//-------------------------------------------//
|
|
NTSTATUS status;
|
|
if ((status = GetLastError()) == STATUS_BUFFER_TOO_SMALL) {
|
|
*ppSid = LocalAlloc(LPTR, dwSidSize);
|
|
if (!*ppSid) {
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
goto ErrorReturn;
|
|
}
|
|
} else if (dwSidSize == 0) {
|
|
*ppSid = NULL;
|
|
return TRUE;
|
|
} else {
|
|
SetLastError(status);
|
|
goto ErrorReturn;
|
|
}
|
|
//-------------------------------------------//
|
|
// Call the server again to get the SID
|
|
//-------------------------------------------//
|
|
if (!WinStationGetProcessSid(hServer,
|
|
(DWORD)(ULONG_PTR)hUniqueProcessId,
|
|
startTime,
|
|
(PBYTE)ppSid,
|
|
&dwSidSize
|
|
)) {
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
} else {
|
|
|
|
//-------------------------------------------//
|
|
// Temp Sid is large enough //
|
|
// Allocate the correct size and copy the //
|
|
// Sid //
|
|
//-------------------------------------------//
|
|
*ppSid = LocalAlloc(LPTR, dwSidSize);
|
|
if (*ppSid) {
|
|
memcpy(*ppSid, tmpSid, dwSidSize);
|
|
} else {
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
ErrorReturn:
|
|
if (*ppSid) {
|
|
LocalFree(*ppSid);
|
|
*ppSid = NULL;
|
|
}
|
|
return FALSE;
|
|
}
|
|
#endif //#if(WINVER >= 0x0500)
|
|
|