From 159a7b00133485a0d6d89caac91b66996fbfb439 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 22 Jun 2014 19:04:38 +0200
Subject: [PATCH] wtsapi32: Partial implementation of WTSEnumerateProcessesW.

---
 dlls/wtsapi32/tests/wtsapi.c |  1 -
 dlls/wtsapi32/wtsapi32.c     | 78 +++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 74 insertions(+), 5 deletions(-)

diff --git a/dlls/wtsapi32/tests/wtsapi.c b/dlls/wtsapi32/tests/wtsapi.c
index 341d9e6..648d7b9 100644
--- a/dlls/wtsapi32/tests/wtsapi.c
+++ b/dlls/wtsapi32/tests/wtsapi.c
@@ -85,7 +85,6 @@ static void test_WTSEnumerateProcessesW(void)
     {
         found = found || !lstrcmpW(pname, info[i].pProcessName);
     }
-    todo_wine
     ok(found || broken(!ret), "process name %s not found\n", wine_dbgstr_w(pname));
     WTSFreeMemory(info);
 }
diff --git a/dlls/wtsapi32/wtsapi32.c b/dlls/wtsapi32/wtsapi32.c
index 5569502..ca13d2f 100644
--- a/dlls/wtsapi32/wtsapi32.c
+++ b/dlls/wtsapi32/wtsapi32.c
@@ -18,8 +18,11 @@
 #include "config.h"
 #include <stdarg.h>
 #include <stdlib.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
+#include "winternl.h"
 #include "wtsapi32.h"
 #include "wine/debug.h"
 #include "wine/heap.h"
@@ -94,8 +97,13 @@ BOOL WINAPI WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version
 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);
+    WTS_PROCESS_INFOW *processInfo;
+    SYSTEM_PROCESS_INFORMATION *spi;
+    ULONG size = 0x4000;
+    void *buf = NULL;
+    NTSTATUS status;
+    DWORD count;
+    WCHAR *name;
 
     if (!ppProcessInfo || !pCount || Reserved != 0 || Version != 1)
     {
@@ -103,9 +111,71 @@ BOOL WINAPI WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version
         return FALSE;
     }
 
-    *pCount = 0;
-    *ppProcessInfo = NULL;
+    if (hServer != WTS_CURRENT_SERVER_HANDLE)
+    {
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return FALSE;
+    }
+
+    do
+    {
+        size *= 2;
+        HeapFree(GetProcessHeap(), 0, buf);
+        buf = HeapAlloc(GetProcessHeap(), 0, size);
+        if (!buf)
+        {
+            SetLastError(ERROR_OUTOFMEMORY);
+            return FALSE;
+        }
+        status = NtQuerySystemInformation(SystemProcessInformation, buf, size, NULL);
+    }
+    while (status == STATUS_INFO_LENGTH_MISMATCH);
+
+    if (status != STATUS_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(), 0, buf);
+        SetLastError(RtlNtStatusToDosError(status));
+        return FALSE;
+    }
+
+    spi = buf;
+    count = size = 0;
+    for (;;)
+    {
+        size += sizeof(WTS_PROCESS_INFOW) + spi->ProcessName.Length + sizeof(WCHAR);
+        count++;
+        if (spi->NextEntryOffset == 0) break;
+        spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->NextEntryOffset);
+    }
+
+    processInfo = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!processInfo)
+    {
+        HeapFree(GetProcessHeap(), 0, buf);
+        SetLastError(ERROR_OUTOFMEMORY);
+        return FALSE;
+    }
+    name = (WCHAR *)&processInfo[count];
+
+    *ppProcessInfo = processInfo;
+    *pCount = count;
+
+    spi = buf;
+    while (count--)
+    {
+        processInfo->SessionId = 0;
+        processInfo->ProcessId = HandleToUlong(spi->UniqueProcessId);
+        processInfo->pProcessName = name;
+        processInfo->pUserSid = NULL;
+        memcpy( name, spi->ProcessName.Buffer, spi->ProcessName.Length );
+        name[ spi->ProcessName.Length/sizeof(WCHAR) ] = 0;
+
+        processInfo++;
+        name += (spi->ProcessName.Length + sizeof(WCHAR))/sizeof(WCHAR);
+        spi = (SYSTEM_PROCESS_INFORMATION *)(((PCHAR)spi) + spi->NextEntryOffset);
+    }
 
+    HeapFree(GetProcessHeap(), 0, buf);
     return TRUE;
 }
 
-- 
1.9.1

