Author: fireball
Date: Sat Oct 10 14:55:34 2009
New Revision: 43360
URL:
http://svn.reactos.org/svn/reactos?rev=43360&view=rev
Log:
[wtsapi32]
Andrey Ivanov <andrey.v.ivanov(a)gmail.com>
- Implement WTSEnumerateProcessesA and WTSEnumerateProcessesW.
See issue #4658 for more details.
Modified:
trunk/reactos/dll/win32/wtsapi32/wtsapi32.c
trunk/reactos/dll/win32/wtsapi32/wtsapi32.rbuild
trunk/reactos/include/psdk/wtsapi32.h
Modified: trunk/reactos/dll/win32/wtsapi32/wtsapi32.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wtsapi32/wtsapi3…
==============================================================================
--- trunk/reactos/dll/win32/wtsapi32/wtsapi32.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wtsapi32/wtsapi32.c [iso-8859-1] Sat Oct 10 14:55:34 2009
@@ -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 @@
return TRUE;
}
+static PVOID WTSMallocMemory(SIZE_T nSize);
+
/************************************************************
* WTSCloseServer (WTSAPI32.@)
*/
@@ -65,18 +79,204 @@
}
/************************************************************
+* 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)
-{
- FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
- ppProcessInfo, pCount);
+ PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* 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 @@
* WTSEnumerateProcessesW (WTSAPI32.@)
*/
BOOL WINAPI WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version,
- PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount)
-{
- FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
- ppProcessInfo, pCount);
+ PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* 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;
}
@@ -133,12 +417,20 @@
}
/************************************************************
+* 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);
}
/************************************************************
Modified: trunk/reactos/dll/win32/wtsapi32/wtsapi32.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/wtsapi32/wtsapi3…
==============================================================================
--- trunk/reactos/dll/win32/wtsapi32/wtsapi32.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/wtsapi32/wtsapi32.rbuild [iso-8859-1] Sat Oct 10 14:55:34
2009
@@ -8,6 +8,7 @@
<define name="__WINESRC__" />
<file>wtsapi32.c</file>
<library>wine</library>
+ <library>advapi32</library>
<library>kernel32</library>
<library>ntdll</library>
</module>
Modified: trunk/reactos/include/psdk/wtsapi32.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/wtsapi32.h?re…
==============================================================================
--- trunk/reactos/include/psdk/wtsapi32.h [iso-8859-1] (original)
+++ trunk/reactos/include/psdk/wtsapi32.h [iso-8859-1] Sat Oct 10 14:55:34 2009
@@ -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
{