diff --git a/reactos/lib/user32/include/winsta.h b/reactos/lib/user32/include/winsta.h index 027148132fa..6bf2062fc19 100644 --- a/reactos/lib/user32/include/winsta.h +++ b/reactos/lib/user32/include/winsta.h @@ -1,6 +1,15 @@ -/* +/* $Id: winsta.h,v 1.2 2004/08/21 19:50:39 gvg Exp $ + * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll * FILE: include/winsta.h * PURPOSE: Window stations */ + +#ifndef USER32_WINSTA_H_INCLUDED +#define USER32_WINSTA_H_INCLUDED + +extern BOOL FASTCALL EnumNamesA(HWINSTA WindowStation, NAMEENUMPROCA EnumFunc, LPARAM Context, BOOL Desktops); +extern BOOL FASTCALL EnumNamesW(HWINSTA WindowStation, NAMEENUMPROCW EnumFunc, LPARAM Context, BOOL Desktops); + +#endif /* USER32_WINSTA_H_INCLUDED */ diff --git a/reactos/lib/user32/misc/desktop.c b/reactos/lib/user32/misc/desktop.c index a03f9fdc524..67b4d26b7bd 100644 --- a/reactos/lib/user32/misc/desktop.c +++ b/reactos/lib/user32/misc/desktop.c @@ -1,4 +1,4 @@ -/* $Id: desktop.c,v 1.33 2004/08/17 21:47:36 weiden Exp $ +/* $Id: desktop.c,v 1.34 2004/08/21 19:50:39 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -10,6 +10,7 @@ */ #include "user32.h" +#include "winsta.h" #include #include #include @@ -370,32 +371,30 @@ CreateDesktopW(LPCWSTR lpszDesktop, /* - * @unimplemented + * @implemented */ BOOL STDCALL EnumDesktopsA( - HWINSTA hwinsta, - DESKTOPENUMPROCA lpEnumFunc, - LPARAM lParam) + HWINSTA WindowStation, + DESKTOPENUMPROCA EnumFunc, + LPARAM Context) { - UNIMPLEMENTED; - return FALSE; + return EnumNamesA(WindowStation, EnumFunc, Context, TRUE); } /* - * @unimplemented + * @implemented */ BOOL STDCALL EnumDesktopsW( - HWINSTA hwinsta, - DESKTOPENUMPROCW lpEnumFunc, - LPARAM lParam) + HWINSTA WindowStation, + DESKTOPENUMPROCW EnumFunc, + LPARAM Context) { - UNIMPLEMENTED; - return FALSE; + return EnumNamesW(WindowStation, EnumFunc, Context, TRUE); } diff --git a/reactos/lib/user32/misc/winsta.c b/reactos/lib/user32/misc/winsta.c index bf8045404e0..0ee8aadf56c 100644 --- a/reactos/lib/user32/misc/winsta.c +++ b/reactos/lib/user32/misc/winsta.c @@ -1,4 +1,4 @@ -/* $Id: winsta.c,v 1.16 2004/08/15 21:36:28 chorns Exp $ +/* $Id: winsta.c,v 1.17 2004/08/21 19:50:39 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -76,59 +76,200 @@ CreateWindowStationW(LPWSTR lpwinsta, lpsa, 0, 0, 0); } +/* + * Common code for EnumDesktopsA/W and EnumWindowStationsA/W + */ +BOOL FASTCALL +EnumNamesW(HWINSTA WindowStation, + NAMEENUMPROCW EnumFunc, + LPARAM Context, + BOOL Desktops) +{ + char Buffer[256]; + PVOID NameList; + PWCHAR Name; + NTSTATUS Status; + ULONG RequiredSize; + ULONG CurrentEntry, EntryCount; + BOOL Ret; + + /* + * Check parameters + */ + if (NULL == WindowStation && Desktops) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + /* + * Try with fixed-size buffer + */ + Status = NtUserBuildNameList(WindowStation, sizeof(Buffer), Buffer, &RequiredSize); + if (NT_SUCCESS(Status)) + { + /* Fixed-size buffer is large enough */ + NameList = (PWCHAR) Buffer; + } + else if (Status == STATUS_BUFFER_TOO_SMALL) + { + /* Allocate a larger buffer */ + NameList = HeapAlloc(GetProcessHeap(), 0, RequiredSize); + if (NULL == NameList) + { + return FALSE; + } + /* Try again */ + Status = NtUserBuildNameList(WindowStation, RequiredSize, NameList, NULL); + if (! NT_SUCCESS(Status)) + { + HeapFree(GetProcessHeap(), 0, NameList); + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + } + else + { + /* Some unrecognized error occured */ + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + + /* + * Enum the names one by one + */ + EntryCount = *((DWORD *) NameList); + Name = (PWCHAR) ((PCHAR) NameList + sizeof(DWORD)); + Ret = TRUE; + for (CurrentEntry = 0; CurrentEntry < EntryCount && Ret; ++CurrentEntry) + { + Ret = (*EnumFunc)(Name, Context); + Name += wcslen(Name) + 1; + } + + /* + * Cleanup + */ + if (NameList != Buffer) + { + HeapFree(GetProcessHeap(), 0, NameList); + } + + return Ret; +} + + +/* For W->A conversion */ +typedef struct tagENUMNAMESASCIICONTEXT +{ + NAMEENUMPROCA UserEnumFunc; + LPARAM UserContext; +} ENUMNAMESASCIICONTEXT, *PENUMNAMESASCIICONTEXT; /* - * @unimplemented + * Callback used by Ascii versions. Converts the Unicode name to + * Ascii and then calls the user callback + */ +BOOL CALLBACK +EnumNamesCallback(LPWSTR Name, LPARAM Param) +{ + PENUMNAMESASCIICONTEXT Context = (PENUMNAMESASCIICONTEXT) Param; + char FixedNameA[32]; + LPSTR NameA; + int Len; + BOOL Ret; + + /* + * Determine required size of Ascii string and see if we can use + * fixed buffer + */ + Len = WideCharToMultiByte(CP_ACP, 0, Name, -1, NULL, 0, NULL, NULL); + if (Len <= 0) + { + /* Some strange error occured */ + return FALSE; + } + else if (Len <= sizeof(FixedNameA)) + { + /* Fixed-size buffer is large enough */ + NameA = FixedNameA; + } + else + { + /* Allocate a larger buffer */ + NameA = HeapAlloc(GetProcessHeap(), 0, Len); + if (NULL == NameA) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + } + + /* + * Do the Unicode ->Ascii conversion + */ + if (0 == WideCharToMultiByte(CP_ACP, 0, Name, -1, NameA, Len, NULL, NULL)) + { + /* Something went wrong, clean up */ + if (NameA != FixedNameA) + { + HeapFree(GetProcessHeap(), 0, NameA); + } + return FALSE; + } + + /* + * Call user callback + */ + Ret = Context->UserEnumFunc(NameA, Context->UserContext); + + /* + * Clean up + */ + if (NameA != FixedNameA) + { + HeapFree(GetProcessHeap(), 0, NameA); + } + + return Ret; +} + +/* + * Common code for EnumDesktopsA and EnumWindowStationsA + */ +BOOL FASTCALL +EnumNamesA(HWINSTA WindowStation, + NAMEENUMPROCA EnumFunc, + LPARAM Context, + BOOL Desktops) +{ + ENUMNAMESASCIICONTEXT PrivateContext; + + PrivateContext.UserEnumFunc = EnumFunc; + PrivateContext.UserContext = Context; + + return EnumNamesW(WindowStation, EnumNamesCallback, (LPARAM) &PrivateContext, Desktops); +} + +/* + * @implemented */ BOOL STDCALL -EnumWindowStationsA(WINSTAENUMPROCA lpEnumFunc, - LPARAM lParam) +EnumWindowStationsA(WINSTAENUMPROCA EnumFunc, + LPARAM Context) { - UNIMPLEMENTED; - return FALSE; + return EnumNamesA(NULL, EnumFunc, Context, FALSE); } /* - * @unimplemented + * @implemented */ BOOL STDCALL -EnumWindowStationsW(WINSTAENUMPROCW lpEnumFunc, - LPARAM lParam) +EnumWindowStationsW(WINSTAENUMPROCW EnumFunc, + LPARAM Context) { - PWCHAR Buffer; - NTSTATUS Status; - ULONG dwRequiredSize; - ULONG CurrentEntry, EntryCount; - - Buffer = HeapAlloc(GetProcessHeap(), 0, 200); - if (Buffer == NULL) - { - return FALSE; - } - Status = NtUserBuildNameList(0, 200, Buffer, &dwRequiredSize); - if (Status == STATUS_BUFFER_TOO_SMALL) - { - Buffer = HeapReAlloc(GetProcessHeap(), 0, Buffer, dwRequiredSize); - if (Buffer == NULL) - { - return FALSE; - } - Status = NtUserBuildNameList(0, dwRequiredSize, Buffer, &dwRequiredSize); - } - if (Status != STATUS_SUCCESS) - { - HeapFree(GetProcessHeap(), 0, Buffer); - return FALSE; - } - EntryCount = *((DWORD *)Buffer); - Buffer += sizeof(DWORD) / sizeof(WCHAR); - for (CurrentEntry = 0; CurrentEntry < EntryCount; ++CurrentEntry) - { - (*lpEnumFunc)(Buffer, lParam); - Buffer += wcslen(Buffer) + 1; - } - return TRUE; + return EnumNamesW(NULL, EnumFunc, Context, FALSE); }