mirror of
https://github.com/reactos/reactos.git
synced 2025-06-05 09:20:30 +00:00
[wtsapi32]
Andrey Ivanov <andrey.v.ivanov@gmail.com> - Implement WTSEnumerateProcessesA and WTSEnumerateProcessesW. See issue #4658 for more details. svn path=/trunk/; revision=43360
This commit is contained in:
parent
d605c0c30a
commit
dfa73d9163
3 changed files with 311 additions and 12 deletions
|
@ -15,13 +15,25 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include "config.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include "windef.h"
|
||||
|
||||
#include "winbase.h"
|
||||
#include "wtsapi32.h"
|
||||
#include "wine/debug.h"
|
||||
#include "winnls.h"
|
||||
#include "aclapi.h"
|
||||
#include "debug.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "ntstatus.h"
|
||||
#endif
|
||||
|
||||
#include "ketypes.h"
|
||||
#include "extypes.h"
|
||||
#include "exfuncs.h"
|
||||
#include "rtlfuncs.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(wtsapi);
|
||||
|
||||
|
@ -47,6 +59,8 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static PVOID WTSMallocMemory(SIZE_T nSize);
|
||||
|
||||
/************************************************************
|
||||
* WTSCloseServer (WTSAPI32.@)
|
||||
*/
|
||||
|
@ -64,19 +78,205 @@ BOOL WINAPI WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* QueryProcesses
|
||||
* Helper function for getting processes list from NtQuerySystemInformation
|
||||
*/
|
||||
static PSYSTEM_PROCESS_INFORMATION QueryProcesses()
|
||||
{
|
||||
PSYSTEM_PROCESS_INFORMATION SysProcessesInfo = NULL;
|
||||
NTSTATUS Status;
|
||||
ULONG BufferSize = 0x8000;
|
||||
ULONG ReturnedBufferSize = 0;
|
||||
do
|
||||
{
|
||||
/* free the buffer, and reallocate it to the new size. RATIONALE: since we
|
||||
ignore the buffer's contents at this point, there's no point in a realloc()
|
||||
that could end up copying a large chunk of data we'd discard anyway */
|
||||
WTSFreeMemory(SysProcessesInfo);
|
||||
SysProcessesInfo = (PSYSTEM_PROCESS_INFORMATION)WTSMallocMemory(BufferSize);
|
||||
|
||||
if (SysProcessesInfo == NULL)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* query the information */
|
||||
Status = NtQuerySystemInformation(SystemProcessInformation,
|
||||
SysProcessesInfo,
|
||||
BufferSize,
|
||||
&ReturnedBufferSize);
|
||||
|
||||
/* adjust necessary buffer size with returned value or double its size */
|
||||
BufferSize = ReturnedBufferSize;
|
||||
}
|
||||
while (Status == STATUS_INFO_LENGTH_MISMATCH);
|
||||
return SysProcessesInfo;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* GetNextProcess
|
||||
* Helper function for iterating NtQuerySystemInformation response
|
||||
*/
|
||||
static PSYSTEM_PROCESS_INFORMATION GetNextProcess(PSYSTEM_PROCESS_INFORMATION Process)
|
||||
{
|
||||
if (Process->NextEntryOffset == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)Process + Process->NextEntryOffset);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* CountProcesses
|
||||
* Helper function for calculating process count
|
||||
* Also calculates necessary space for ImageName unicode strings
|
||||
*/
|
||||
static DWORD CountProcesses(IN PSYSTEM_PROCESS_INFORMATION Process, OUT PDWORD pImageNameLength)
|
||||
{
|
||||
DWORD ProcessCount = 0;
|
||||
DWORD Length = 0;
|
||||
*pImageNameLength = 0;
|
||||
while (Process != NULL)
|
||||
{
|
||||
++ProcessCount;
|
||||
Length = Process->ImageName.Length + sizeof(WCHAR);
|
||||
*pImageNameLength += ALIGN_UP(Length, 8);
|
||||
Process = GetNextProcess(Process);
|
||||
}
|
||||
return ProcessCount;
|
||||
}
|
||||
/************************************************************
|
||||
* GetProcessOwner
|
||||
* Helper function for getting owner SID for process
|
||||
*/
|
||||
static BOOL GetProcessOwner(DWORD ProcessId, PSID pSid, DWORD BufferSize)
|
||||
{
|
||||
BOOL Success = FALSE;
|
||||
HANDLE hProcess = NULL;
|
||||
PSID ProcessUser = NULL;
|
||||
PSECURITY_DESCRIPTOR ProcessSD = NULL;
|
||||
DWORD Error;
|
||||
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | READ_CONTROL, FALSE, ProcessId);
|
||||
if (hProcess != NULL)
|
||||
{
|
||||
ProcessUser = NULL;
|
||||
ProcessSD = NULL;
|
||||
Error = GetSecurityInfo(hProcess,
|
||||
SE_KERNEL_OBJECT,
|
||||
OWNER_SECURITY_INFORMATION,
|
||||
&ProcessUser,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&ProcessSD);
|
||||
if (!Error)
|
||||
{
|
||||
if (ProcessUser != NULL)
|
||||
{
|
||||
Success = !RtlCopySid(BufferSize, pSid, ProcessUser);
|
||||
}
|
||||
LocalFree(ProcessSD);
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* WTSEnumerateProcessesA (WTSAPI32.@)
|
||||
*/
|
||||
BOOL WINAPI WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version,
|
||||
PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount)
|
||||
PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount)
|
||||
{
|
||||
FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
|
||||
ppProcessInfo, pCount);
|
||||
PSYSTEM_PROCESS_INFORMATION SysProcessInfo = NULL;
|
||||
PSYSTEM_PROCESS_INFORMATION SysProcess;
|
||||
PBYTE Data;
|
||||
PWTS_PROCESS_INFOA Process;
|
||||
ULONG BufferSize = 0;
|
||||
DWORD ProcessCount = 0;
|
||||
DWORD Offset;
|
||||
DWORD Length;
|
||||
DWORD ProcessId;
|
||||
|
||||
if (!ppProcessInfo || !pCount) return FALSE;
|
||||
|
||||
*pCount = 0;
|
||||
*ppProcessInfo = NULL;
|
||||
|
||||
if (Version != 1)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (hServer != WTS_CURRENT_SERVER_HANDLE)
|
||||
{
|
||||
FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
|
||||
ppProcessInfo, pCount);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SysProcessInfo = QueryProcesses();
|
||||
if (SysProcessInfo == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
// Calculates buffer size for processes information
|
||||
ProcessCount = CountProcesses(SysProcessInfo, &BufferSize);
|
||||
// Doubles space for strings (in case of UTF-8 or UTF-7 is used as default code page)
|
||||
BufferSize *= 2;
|
||||
// And count space for records and SIDs
|
||||
BufferSize += ProcessCount * (sizeof(WTS_PROCESS_INFOA) + SECURITY_MAX_SID_SIZE);
|
||||
|
||||
Data = (PBYTE)WTSMallocMemory(BufferSize);
|
||||
if (Data == NULL)
|
||||
{
|
||||
WTSFreeMemory(SysProcessInfo);
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// WTS_PROCESS_INFOW structures are put in beginning of the buffer
|
||||
// FileName paths and SIDs should be located later after this part
|
||||
// That way user will be able to free buffer memory
|
||||
// with single WTSFreeMemory call
|
||||
for (SysProcess = SysProcessInfo, Process = (PWTS_PROCESS_INFOA)Data,
|
||||
Offset = ProcessCount * sizeof(WTS_PROCESS_INFOA);
|
||||
SysProcess != NULL;
|
||||
SysProcess = GetNextProcess(SysProcess), ++Process)
|
||||
{
|
||||
ProcessId = PtrToUint(SysProcess->UniqueProcessId);
|
||||
Process->SessionId = SysProcess->SessionId;
|
||||
// Get unique process id
|
||||
Process->ProcessId = ProcessId;
|
||||
Process->pProcessName = (LPSTR)(Data + Offset);
|
||||
RtlUnicodeToMultiByteN(Process->pProcessName, BufferSize - Offset, &Length,
|
||||
SysProcess->ImageName.Buffer, SysProcess->ImageName.Length);
|
||||
Process->pProcessName[Length++] = 0;
|
||||
Offset += ALIGN_UP(Length, 8);
|
||||
Process->pUserSid = NULL;
|
||||
if (ProcessId > 0)
|
||||
{
|
||||
Process->pUserSid = (PSID)(Data + Offset);
|
||||
if (GetProcessOwner(ProcessId, Process->pUserSid, BufferSize - Offset))
|
||||
{
|
||||
Length = RtlLengthSid(Process->pUserSid);
|
||||
Offset += ALIGN_UP(Length, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process->pUserSid = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WTSFreeMemory(SysProcessInfo);
|
||||
|
||||
// Now we may assign output values
|
||||
*pCount = ProcessCount;
|
||||
*ppProcessInfo = (PWTS_PROCESS_INFOA)Data;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -85,15 +285,99 @@ BOOL WINAPI WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version
|
|||
* WTSEnumerateProcessesW (WTSAPI32.@)
|
||||
*/
|
||||
BOOL WINAPI WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version,
|
||||
PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount)
|
||||
PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount)
|
||||
{
|
||||
FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
|
||||
ppProcessInfo, pCount);
|
||||
PSYSTEM_PROCESS_INFORMATION SysProcessInfo = NULL;
|
||||
PSYSTEM_PROCESS_INFORMATION SysProcess;
|
||||
PBYTE Data;
|
||||
PWTS_PROCESS_INFOW Process;
|
||||
ULONG BufferSize;
|
||||
DWORD ProcessCount = 0;
|
||||
DWORD Offset;
|
||||
DWORD Length;
|
||||
DWORD ProcessId;
|
||||
|
||||
if (!ppProcessInfo || !pCount) return FALSE;
|
||||
|
||||
*pCount = 0;
|
||||
*ppProcessInfo = NULL;
|
||||
|
||||
if (Version != 1)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (hServer != WTS_CURRENT_SERVER_HANDLE)
|
||||
{
|
||||
FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
|
||||
ppProcessInfo, pCount);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SysProcessInfo = QueryProcesses();
|
||||
if (SysProcessInfo == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* Calculating necessary buffer length */
|
||||
ProcessCount = CountProcesses(SysProcessInfo, &BufferSize);
|
||||
BufferSize += ProcessCount * (sizeof(WTS_PROCESS_INFOW) + SECURITY_MAX_SID_SIZE);
|
||||
|
||||
Data = (PBYTE)WTSMallocMemory(BufferSize);
|
||||
if (Data == NULL)
|
||||
{
|
||||
WTSFreeMemory(SysProcessInfo);
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// WTS_PROCESS_INFOW structures are put in beginning of the buffer
|
||||
// FileName paths and SIDs should be located later after this part
|
||||
// That way user will be able to free buffer memory
|
||||
// with single WTSFreeMemory call
|
||||
for (SysProcess = SysProcessInfo, Process = (PWTS_PROCESS_INFOW)Data,
|
||||
Offset = ProcessCount * sizeof(WTS_PROCESS_INFOW);
|
||||
SysProcess != NULL;
|
||||
SysProcess = GetNextProcess(SysProcess), ++Process)
|
||||
{
|
||||
ProcessId = PtrToUint(SysProcess->UniqueProcessId);
|
||||
Process->SessionId = SysProcess->SessionId;
|
||||
// Get unique process id
|
||||
Process->ProcessId = ProcessId;
|
||||
Process->pProcessName = (LPWSTR)(Data + Offset);
|
||||
if (SysProcess->ImageName.Buffer != NULL)
|
||||
{
|
||||
Length = SysProcess->ImageName.Length + sizeof(WCHAR);
|
||||
RtlCopyMemory(Process->pProcessName, SysProcess->ImageName.Buffer, Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
*Process->pProcessName = L'\0';
|
||||
Length = sizeof(*Process->pProcessName);
|
||||
}
|
||||
Offset += ALIGN_UP(Length, 8);
|
||||
Process->pUserSid = NULL;
|
||||
if (ProcessId > 0)
|
||||
{
|
||||
Process->pUserSid = (PSID)(Data + Offset);
|
||||
if (GetProcessOwner(ProcessId, Process->pUserSid, BufferSize - Offset))
|
||||
{
|
||||
Length = RtlLengthSid(Process->pUserSid);
|
||||
Offset += ALIGN_UP(Length, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process->pUserSid = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WTSFreeMemory(SysProcessInfo);
|
||||
|
||||
// Now we may assign output values
|
||||
*pCount = ProcessCount;
|
||||
*ppProcessInfo = (PWTS_PROCESS_INFOW)Data;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -132,13 +416,21 @@ BOOL WINAPI WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* WTSMallocMemory
|
||||
* Complimentary function to WTSFreeMemory from API
|
||||
*/
|
||||
static PVOID WTSMallocMemory(SIZE_T nSize)
|
||||
{
|
||||
return HeapAlloc(GetProcessHeap(), 0, nSize);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* WTSFreeMemory (WTSAPI32.@)
|
||||
*/
|
||||
void WINAPI WTSFreeMemory(PVOID pMemory)
|
||||
{
|
||||
FIXME("Stub %p\n", pMemory);
|
||||
return;
|
||||
HeapFree(GetProcessHeap(), 0, pMemory);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<define name="__WINESRC__" />
|
||||
<file>wtsapi32.c</file>
|
||||
<library>wine</library>
|
||||
<library>advapi32</library>
|
||||
<library>kernel32</library>
|
||||
<library>ntdll</library>
|
||||
</module>
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Current server information
|
||||
*/
|
||||
#define WTS_CURRENT_SERVER ((HANDLE)NULL)
|
||||
#define WTS_CURRENT_SERVER_HANDLE ((HANDLE)NULL)
|
||||
#define WTS_CURRENT_SERVER_NAME (NULL)
|
||||
|
||||
typedef enum tagWTS_INFO_CLASS
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue