[WTSAPI32][PSDK] Addendum to 27ed609a: Some of the WTS_INFO_CLASS values are NT6...
[reactos.git] / dll / win32 / wtsapi32 / wtsapi32.c
index 642e9ae..60658fd 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <config.h>
+#include "config.h"
 #include <stdarg.h>
-//#include <stdlib.h>
-#include <windef.h>
-#include <winbase.h>
-#include <wtsapi32.h>
-#include <wine/debug.h>
+#include <stdlib.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "wine/winternl.h"
+#include "wtsapi32.h"
+#include "wine/debug.h"
+#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(wtsapi);
 
-static HMODULE WTSAPI32_hModule;
-
-BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
-    TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
-
-    switch (fdwReason) {
-        case DLL_PROCESS_ATTACH:
-        {
-            DisableThreadLibraryCalls(hinstDLL);
-            WTSAPI32_hModule = hinstDLL;
-            break;
-        }
-        case DLL_PROCESS_DETACH:
-        {
-            break;
-        }
-    }
-
-    return TRUE;
-}
+#ifdef __REACTOS__ /* FIXME: Inspect */
+#define GetCurrentProcessToken() ((HANDLE)~(ULONG_PTR)3)
+#endif
 
 /************************************************************
  *                WTSCloseServer  (WTSAPI32.@)
@@ -82,6 +68,15 @@ BOOL WINAPI WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
     return TRUE;
 }
 
+/************************************************************
+ *                WTSEnableChildSessions  (WTSAPI32.@)
+ */
+BOOL WINAPI WTSEnableChildSessions(BOOL enable)
+{
+    FIXME("Stub %d\n", enable);
+    return TRUE;
+}
+
 /************************************************************
  *                WTSEnumerateProcessesA  (WTSAPI32.@)
  */
@@ -105,14 +100,85 @@ 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)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
-    if (!ppProcessInfo || !pCount) return FALSE;
+    if (hServer != WTS_CURRENT_SERVER_HANDLE)
+    {
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+        return FALSE;
+    }
 
-    *pCount = 0;
-    *ppProcessInfo = NULL;
+    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;
 }
 
@@ -141,7 +207,9 @@ BOOL WINAPI WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Versi
 BOOL WINAPI WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version,
     PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount)
 {
-    FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
+    static int once;
+
+    if (!once++) FIXME("Stub %p 0x%08x 0x%08x %p %p\n", hServer, Reserved, Version,
           ppSessionInfo, pCount);
 
     if (!ppSessionInfo || !pCount) return FALSE;
@@ -174,7 +242,7 @@ BOOL WINAPI WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
  */
 void WINAPI WTSFreeMemory(PVOID pMemory)
 {
-    FIXME("Stub %p\n", pMemory);
+    heap_free(pMemory);
 }
 
 /************************************************************
@@ -217,11 +285,74 @@ BOOL WINAPI WTSQuerySessionInformationA(
     LPSTR* Buffer,
     DWORD* BytesReturned)
 {
+#ifdef __REACTOS__
+    const size_t wcsErrorCode = -1;
+    LPWSTR buffer = NULL;
+    LPSTR ansiBuffer = NULL;
+    DWORD bytesReturned = 0;
+    BOOL result = FALSE;
+    size_t len;
+
+    if (!BytesReturned || !Buffer)
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+    if (!WTSQuerySessionInformationW(hServer, SessionId, WTSInfoClass, &buffer, &bytesReturned))
+    {
+        ansiBuffer = (LPSTR)buffer;
+        *Buffer = ansiBuffer;
+        *BytesReturned = bytesReturned;
+        return FALSE;
+    }
+
+    switch (WTSInfoClass)
+    {
+        case WTSInitialProgram:
+        case WTSApplicationName:
+        case WTSWorkingDirectory:
+        case WTSOEMId:
+        case WTSUserName:
+        case WTSWinStationName:
+        case WTSDomainName:
+        case WTSClientName:
+        case WTSClientDirectory:
+        {
+            len = wcstombs(NULL, buffer, 0);
+            if (len != wcsErrorCode)
+            {
+                len++;
+                ansiBuffer = heap_alloc_zero(len);
+                if (ansiBuffer && (wcstombs(ansiBuffer, buffer, len) != wcsErrorCode))
+                {
+                    result = TRUE;
+                    bytesReturned = len;
+                }
+            }
+            WTSFreeMemory(buffer);
+            break;
+        }
+
+        default:
+        {
+            result = TRUE;
+            ansiBuffer = (LPSTR)buffer;
+            break;
+        }
+    }
+
+    *Buffer = ansiBuffer;
+    *BytesReturned = bytesReturned;
+
+    return result;
+#else
     /* FIXME: Forward request to winsta.dll::WinStationQueryInformationA */
     FIXME("Stub %p 0x%08x %d %p %p\n", hServer, SessionId, WTSInfoClass,
         Buffer, BytesReturned);
 
     return FALSE;
+#endif
 }
 
 /************************************************************
@@ -234,11 +365,139 @@ BOOL WINAPI WTSQuerySessionInformationW(
     LPWSTR* Buffer,
     DWORD* BytesReturned)
 {
+#ifdef __REACTOS__
+    if (!BytesReturned || !Buffer)
+    {
+        SetLastError(ERROR_INVALID_USER_BUFFER);
+        return FALSE;
+    }
+
+#if (NTDDI_VERSION >= NTDDI_WS08)
+    if (WTSInfoClass > WTSIsRemoteSession)
+#else
+    if (WTSInfoClass > WTSClientProtocolType)
+#endif
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    switch (WTSInfoClass)
+    {
+        case WTSSessionId:
+        {
+            const DWORD size = sizeof(ULONG);
+            ULONG* output = heap_alloc_zero(size);
+            if (!output)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return FALSE;
+            }
+
+            *output = NtCurrentTeb()->Peb->SessionId;
+            *Buffer = (LPWSTR)output;
+            *BytesReturned = size;
+            return TRUE;
+        }
+
+        case WTSUserName:
+        {
+            WCHAR* username;
+            DWORD count = 0;
+
+            GetUserNameW(NULL, &count);
+            if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+                return FALSE;
+            username = heap_alloc(count * sizeof(WCHAR));
+            if (!username)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return FALSE;
+            }
+
+            GetUserNameW(username, &count);
+            *Buffer = username;
+            *BytesReturned = count * sizeof(WCHAR);
+            return TRUE;
+        }
+
+        case WTSConnectState:
+        {
+            const DWORD size = sizeof(DWORD);
+            WCHAR* output = heap_alloc_zero(size);
+            if (!output)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return FALSE;
+            }
+
+            *Buffer = output;
+            *BytesReturned = size;
+            return TRUE;
+        }
+
+        case WTSClientProtocolType:
+        {
+            const DWORD size = sizeof(WORD);
+            WCHAR* output = heap_alloc_zero(size);
+            if (!output)
+            {
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+                return FALSE;
+            }
+
+            *Buffer = output;
+            *BytesReturned = size;
+            return TRUE;
+        }
+
+#if (NTDDI_VERSION >= NTDDI_WS08)
+        case WTSIdleTime:
+        case WTSLogonTime:
+        case WTSIncomingBytes:
+        case WTSOutgoingBytes:
+        case WTSIncomingFrames:
+        case WTSOutgoingFrames:
+        {
+            SetLastError(ERROR_NOT_SUPPORTED);
+            return FALSE;
+        }
+#endif /* (NTDDI_VERSION >= NTDDI_WS08) */
+
+        default:
+        {
+            if (BytesReturned)
+                *BytesReturned = 0;
+
+            break;
+        }
+    }
+
     /* FIXME: Forward request to winsta.dll::WinStationQueryInformationW */
     FIXME("Stub %p 0x%08x %d %p %p\n", hServer, SessionId, WTSInfoClass,
         Buffer, BytesReturned);
 
     return FALSE;
+#else
+    /* FIXME: Forward request to winsta.dll::WinStationQueryInformationW */
+    FIXME("Stub %p 0x%08x %d %p %p\n", hServer, SessionId, WTSInfoClass,
+        Buffer, BytesReturned);
+
+    if (WTSInfoClass == WTSUserName)
+    {
+        WCHAR *username;
+        DWORD count = 0;
+
+        GetUserNameW(NULL, &count);
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
+        if (!(username = heap_alloc(count * sizeof(WCHAR)))) return FALSE;
+        GetUserNameW(username, &count);
+        *Buffer = username;
+        *BytesReturned = count * sizeof(WCHAR);
+        return TRUE;
+    }
+    return FALSE;
+#endif
 }
 
 /************************************************************
@@ -247,7 +506,16 @@ BOOL WINAPI WTSQuerySessionInformationW(
 BOOL WINAPI WTSQueryUserToken(ULONG session_id, PHANDLE token)
 {
     FIXME("%u %p\n", session_id, token);
-    return FALSE;
+
+    if (!token)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    return DuplicateHandle(GetCurrentProcess(), GetCurrentProcessToken(),
+                           GetCurrentProcess(), token,
+                           0, FALSE, DUPLICATE_SAME_ACCESS);
 }
 
 /************************************************************
@@ -281,7 +549,7 @@ BOOL WINAPI WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)
 }
 
 /************************************************************
- *                WTSRegisterSessionNotification (WTSAPI32.@)
+ *                WTSRegisterSessionNotificationEx (WTSAPI32.@)
  */
 BOOL WINAPI WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags)
 {