From 659c5c665e64a7c7ead359bc90b3eaa173e87545 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 5 Mar 2008 13:41:41 -0800 Subject: [PATCH] user32: Fix enumeration for EnumWindowStations and EnumDesktops --- dlls/user32/tests/winstation.c | 106 ++++++++++++++++++++++++++++++++++++++++ dlls/user32/winstation.c | 38 ++++++++++++-- 2 files changed, 138 insertions(+), 6 deletions(-) diff --git a/dlls/user32/tests/winstation.c b/dlls/user32/tests/winstation.c index 16a1c93..6085c2d 100644 --- a/dlls/user32/tests/winstation.c +++ b/dlls/user32/tests/winstation.c @@ -22,6 +22,7 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "winnls.h" #define DESKTOP_ALL_ACCESS 0x01ff @@ -248,6 +249,109 @@ static void test_handles(void) CloseHandle( hthread ); } +/* Enumeration tests */ + +static BOOL CALLBACK windowstationcallbackW(LPWSTR winsta, LPARAM lp) +{ + char temp[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, winsta, -1, temp, sizeof(temp), NULL, 0); + trace("windowstationcallbackW called with argument %s\n", temp); + return lp; +} + +static BOOL CALLBACK openwindowstationcallbackW(LPWSTR winsta, LPARAM lp) +{ + char temp[MAX_PATH]; + HWINSTA hwinsta; + + WideCharToMultiByte(CP_ACP, 0, winsta, -1, temp, sizeof(temp), NULL, 0); + trace("openwindowstationcallbackW called with argument %s\n", temp); + hwinsta = OpenWindowStationW(winsta, FALSE, WINSTA_ENUMERATE); + ok(!!hwinsta, "Could not open desktop %s!\n", temp); + if (hwinsta) + CloseWindowStation(hwinsta); + return lp; +} + +static void test_enumstations(void) +{ + BOOL ret; + +#if 0 /* Crashes instead */ + SetLastError(0xbabefeed); + ret = EnumWindowStationsW(NULL, 0); + ok(!ret, "EnumWindowStationsW returned succesfully!\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError()); +#endif + + SetLastError(0xdeadbeef); + ret = EnumWindowStationsW(openwindowstationcallbackW, 0x12345); + ok(ret == 0x12345, "EnumWindowStationsW returned %x\n", ret); + ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = EnumWindowStationsW(windowstationcallbackW, 0); + ok(!ret, "EnumWindowStationsW returned %x\n", ret); + ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); +} + +static BOOL CALLBACK desktopcallbackW(LPWSTR desktop, LPARAM lp) +{ + char temp[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, desktop, -1, temp, sizeof(temp), NULL, 0); + trace("desktopcallbackW called with argument %s\n", temp); + return lp; +} + +static BOOL CALLBACK opendesktopcallbackW(LPWSTR desktop, LPARAM lp) +{ + char temp[MAX_PATH]; + HDESK hdesk; + static int once; + + WideCharToMultiByte(CP_ACP, 0, desktop, -1, temp, sizeof(temp), NULL, 0); + trace("opendesktopcallbackW called with argument %s\n", temp); + if (once++) return lp; + + hdesk = OpenDesktopW(desktop, 0, FALSE, DESKTOP_ENUMERATE); + ok(!!hdesk, "Could not open desktop %s!\n", temp); + if (hdesk) + CloseDesktop(hdesk); + return lp; +} + +static void test_enumdesktops(void) +{ + BOOL ret; + +#if 0 /* Crashes instead */ + SetLastError(0xbabefeed); + ret = EnumDesktopsW(GetProcessWindowStation(), NULL, 0); + ok(!ret, "EnumDesktopsW returned succesfully!\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError()); +#endif + + SetLastError(0xdeadbeef); + ret = EnumDesktopsW(NULL, desktopcallbackW, 0x12345); + ok(ret == 0x12345, "EnumDesktopsW returned %x\n", ret); + ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = EnumDesktopsW(GetProcessWindowStation(), opendesktopcallbackW, 0x12345); + ok(ret == 0x12345, "EnumDesktopsW returned %x\n", ret); + ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = EnumDesktopsW(INVALID_HANDLE_VALUE, desktopcallbackW, 0x12345); + ok(!ret, "EnumDesktopsW returned %x\n", ret); + ok(GetLastError() == ERROR_INVALID_HANDLE, "LastError is set to %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = EnumDesktopsW(GetProcessWindowStation(), desktopcallbackW, 0); + ok(!ret, "EnumDesktopsW returned %x\n", ret); + ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError()); +} + START_TEST(winstation) { /* Check whether this platform supports WindowStation calls */ @@ -260,5 +364,7 @@ START_TEST(winstation) return; } + test_enumstations(); + test_enumdesktops(); test_handles(); } diff --git a/dlls/user32/winstation.c b/dlls/user32/winstation.c index 75cb286..4ddc01f 100644 --- a/dlls/user32/winstation.c +++ b/dlls/user32/winstation.c @@ -18,6 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "ntstatus.h" +#define WIN32_NO_STATUS + #include #include "windef.h" #include "winbase.h" @@ -211,18 +214,28 @@ BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam ) unsigned int index = 0; WCHAR name[MAX_PATH]; BOOL ret = TRUE; + DWORD error; while (ret) { SERVER_START_REQ( enum_winstation ) { req->index = index; - wine_server_set_reply( req, name, sizeof(name) ); - ret = !wine_server_call( req ); + wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) ); + error = wine_server_call( req ); + /* Null terminate! */ + name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0; index = reply->next; } SERVER_END_REQ; - if (ret) ret = func( name, lparam ); + if (error == STATUS_NO_MORE_ENTRIES) + break; + else if (error) + { + SetLastError( RtlNtStatusToDosError( error ) ); + return FALSE; + } + ret = func( name, lparam ); } return ret; } @@ -401,6 +414,10 @@ BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam unsigned int index = 0; WCHAR name[MAX_PATH]; BOOL ret = TRUE; + DWORD error; + + if (!winsta) + winsta = GetProcessWindowStation(); while (ret) { @@ -408,12 +425,21 @@ BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam { req->winstation = winsta; req->index = index; - wine_server_set_reply( req, name, sizeof(name) ); - ret = !wine_server_call( req ); + wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) ); + error = wine_server_call( req ); + /* Null terminate! */ + name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0; index = reply->next; } SERVER_END_REQ; - if (ret) ret = func( name, lparam ); + if (error == STATUS_NO_MORE_ENTRIES) + break; + else if (error) + { + SetLastError( RtlNtStatusToDosError( error ) ); + return FALSE; + } + ret = func(name, lparam); } return ret; } -- 1.5.4.1