mirror of
https://github.com/reactos/reactos.git
synced 2025-01-02 20:43:18 +00:00
Implement NtUserBuildNamesList()
svn path=/trunk/; revision=10622
This commit is contained in:
parent
847119b3cd
commit
261286187f
2 changed files with 297 additions and 90 deletions
|
@ -22,6 +22,7 @@
|
|||
#define TAG_TIMERTD TAG('T', 'I', 'M', 'T') /* timer thread dereference list */
|
||||
#define TAG_TIMERBMP TAG('T', 'I', 'M', 'B') /* timers bitmap */
|
||||
#define TAG_CALLBACK TAG('C', 'B', 'C', 'K') /* callback memory */
|
||||
#define TAG_WINSTA TAG('W', 'S', 'T', 'A') /* window station */
|
||||
|
||||
/* objects */
|
||||
#define TAG_BEZIER TAG('B', 'E', 'Z', 'R') /* bezier */
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: winsta.c,v 1.64 2004/06/20 00:45:37 navaraf Exp $
|
||||
* $Id: winsta.c,v 1.65 2004/08/20 22:38:49 gvg Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -954,6 +954,295 @@ NtUserSetWindowStationUser(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static NTSTATUS FASTCALL
|
||||
BuildWindowStationNameList(
|
||||
ULONG dwSize,
|
||||
PVOID lpBuffer,
|
||||
PULONG pRequiredSize)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS Status;
|
||||
HANDLE DirectoryHandle;
|
||||
UNICODE_STRING DirectoryName;
|
||||
char InitialBuffer[256], *Buffer;
|
||||
ULONG Context, ReturnLength, BufferSize;
|
||||
DWORD EntryCount;
|
||||
PDIRECTORY_BASIC_INFORMATION DirEntry;
|
||||
WCHAR NullWchar;
|
||||
|
||||
/*
|
||||
* Generate name of window station directory
|
||||
*/
|
||||
if (!IntGetFullWindowStationName(&DirectoryName, NULL, NULL))
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to open the directory.
|
||||
*/
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&DirectoryName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Status = ZwOpenDirectoryObject(
|
||||
&DirectoryHandle,
|
||||
DIRECTORY_QUERY,
|
||||
&ObjectAttributes);
|
||||
|
||||
ExFreePool(DirectoryName.Buffer);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* First try to query the directory using a fixed-size buffer */
|
||||
Context = 0;
|
||||
Buffer = NULL;
|
||||
Status = ZwQueryDirectoryObject(DirectoryHandle, InitialBuffer, sizeof(InitialBuffer),
|
||||
FALSE, TRUE, &Context, &ReturnLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (STATUS_NO_MORE_ENTRIES == ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
|
||||
FALSE, &Context, NULL))
|
||||
{
|
||||
/* Our fixed-size buffer is large enough */
|
||||
Buffer = InitialBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == Buffer)
|
||||
{
|
||||
/* Need a larger buffer, check how large exactly */
|
||||
Status = ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, TRUE, &Context,
|
||||
&ReturnLength);
|
||||
if (STATUS_BUFFER_TOO_SMALL == Status)
|
||||
{
|
||||
BufferSize = ReturnLength;
|
||||
Buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_WINSTA);
|
||||
if (NULL == Buffer)
|
||||
{
|
||||
ObDereferenceObject(DirectoryHandle);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* We should have a sufficiently large buffer now */
|
||||
Context = 0;
|
||||
Status = ZwQueryDirectoryObject(DirectoryHandle, Buffer, BufferSize,
|
||||
FALSE, TRUE, &Context, &ReturnLength);
|
||||
if (! NT_SUCCESS(Status) ||
|
||||
STATUS_NO_MORE_ENTRIES != ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
|
||||
FALSE, &Context, NULL))
|
||||
{
|
||||
/* Something went wrong, maybe someone added a directory entry? Just give up. */
|
||||
ExFreePool(Buffer);
|
||||
ObDereferenceObject(DirectoryHandle);
|
||||
return NT_SUCCESS(Status) ? STATUS_INTERNAL_ERROR : Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZwClose(DirectoryHandle);
|
||||
|
||||
/*
|
||||
* Count the required size of buffer.
|
||||
*/
|
||||
ReturnLength = sizeof(DWORD);
|
||||
EntryCount = 0;
|
||||
for (DirEntry = (PDIRECTORY_BASIC_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length;
|
||||
DirEntry++)
|
||||
{
|
||||
ReturnLength += DirEntry->ObjectName.Length + sizeof(WCHAR);
|
||||
EntryCount++;
|
||||
}
|
||||
DPRINT("Required size: %d Entry count: %d\n", ReturnLength, EntryCount);
|
||||
if (NULL != pRequiredSize)
|
||||
{
|
||||
Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
if (Buffer != InitialBuffer)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
}
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the supplied buffer is large enough.
|
||||
*/
|
||||
if (dwSize < ReturnLength)
|
||||
{
|
||||
if (Buffer != InitialBuffer)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
}
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the resulting buffer contents.
|
||||
*/
|
||||
Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
if (Buffer != InitialBuffer)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
|
||||
|
||||
NullWchar = L'\0';
|
||||
for (DirEntry = (PDIRECTORY_BASIC_INFORMATION) Buffer; 0 != DirEntry->ObjectName.Length;
|
||||
DirEntry++)
|
||||
{
|
||||
Status = MmCopyToCaller(lpBuffer, DirEntry->ObjectName.Buffer, DirEntry->ObjectName.Length);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
if (Buffer != InitialBuffer)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->ObjectName.Length);
|
||||
Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
if (Buffer != InitialBuffer)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up
|
||||
*/
|
||||
if (NULL != Buffer && Buffer != InitialBuffer)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS FASTCALL
|
||||
BuildDesktopNameList(
|
||||
HWINSTA hWindowStation,
|
||||
ULONG dwSize,
|
||||
PVOID lpBuffer,
|
||||
PULONG pRequiredSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PWINSTATION_OBJECT WindowStation;
|
||||
KIRQL OldLevel;
|
||||
PLIST_ENTRY DesktopEntry;
|
||||
PDESKTOP_OBJECT DesktopObject;
|
||||
DWORD EntryCount;
|
||||
ULONG ReturnLength;
|
||||
WCHAR NullWchar;
|
||||
|
||||
Status = IntValidateWindowStationHandle(hWindowStation,
|
||||
KernelMode,
|
||||
0,
|
||||
&WindowStation);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(&WindowStation->Lock, &OldLevel);
|
||||
|
||||
/*
|
||||
* Count the required size of buffer.
|
||||
*/
|
||||
ReturnLength = sizeof(DWORD);
|
||||
EntryCount = 0;
|
||||
for (DesktopEntry = WindowStation->DesktopListHead.Flink;
|
||||
DesktopEntry != &WindowStation->DesktopListHead;
|
||||
DesktopEntry = DesktopEntry->Flink)
|
||||
{
|
||||
DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP_OBJECT, ListEntry);
|
||||
ReturnLength += DesktopObject->Name.Length + sizeof(WCHAR);
|
||||
EntryCount++;
|
||||
}
|
||||
DPRINT("Required size: %d Entry count: %d\n", ReturnLength, EntryCount);
|
||||
if (NULL != pRequiredSize)
|
||||
{
|
||||
Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
|
||||
ObDereferenceObject(WindowStation);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the supplied buffer is large enough.
|
||||
*/
|
||||
if (dwSize < ReturnLength)
|
||||
{
|
||||
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
|
||||
ObDereferenceObject(WindowStation);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the resulting buffer contents.
|
||||
*/
|
||||
Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
|
||||
ObDereferenceObject(WindowStation);
|
||||
return Status;
|
||||
}
|
||||
lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
|
||||
|
||||
NullWchar = L'\0';
|
||||
for (DesktopEntry = WindowStation->DesktopListHead.Flink;
|
||||
DesktopEntry != &WindowStation->DesktopListHead;
|
||||
DesktopEntry = DesktopEntry->Flink)
|
||||
{
|
||||
DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP_OBJECT, ListEntry);
|
||||
Status = MmCopyToCaller(lpBuffer, DesktopObject->Name.Buffer, DesktopObject->Name.Length);
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
|
||||
ObDereferenceObject(WindowStation);
|
||||
return Status;
|
||||
}
|
||||
lpBuffer = (PVOID) ((PCHAR) lpBuffer + DesktopObject->Name.Length);
|
||||
Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
|
||||
if (! NT_SUCCESS(Status))
|
||||
{
|
||||
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
|
||||
ObDereferenceObject(WindowStation);
|
||||
return Status;
|
||||
}
|
||||
lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up
|
||||
*/
|
||||
KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
|
||||
ObDereferenceObject(WindowStation);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* NtUserBuildNameList
|
||||
*
|
||||
|
@ -977,103 +1266,20 @@ NtUserSetWindowStationUser(
|
|||
* Otherwise it's size of buffer needed for function to succeed.
|
||||
*
|
||||
* Status
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtUserBuildNameList(
|
||||
HWINSTA hWinSta,
|
||||
HWINSTA hWindowStation,
|
||||
ULONG dwSize,
|
||||
PVOID lpBuffer,
|
||||
PULONG pRequiredSize)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status;
|
||||
HANDLE DirectoryHandle;
|
||||
ULONG EntryCount = 0;
|
||||
UNICODE_STRING DirectoryNameW;
|
||||
PWCHAR BufferChar;
|
||||
PDIRECTORY_OBJECT DirObj = NULL;
|
||||
PLIST_ENTRY CurrentEntry = NULL;
|
||||
POBJECT_HEADER CurrentObject = NULL;
|
||||
|
||||
/*
|
||||
* Generate full window station name
|
||||
*/
|
||||
|
||||
/* FIXME: Correct this for desktop */
|
||||
if (!IntGetFullWindowStationName(&DirectoryNameW, NULL, NULL))
|
||||
{
|
||||
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to open the directory.
|
||||
*/
|
||||
|
||||
Status = ObReferenceObjectByName(&DirectoryNameW, 0, NULL, DIRECTORY_QUERY,
|
||||
ObDirectoryType, UserMode, (PVOID*)&DirObj, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(DirectoryNameW.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the required size of buffer.
|
||||
*/
|
||||
|
||||
*pRequiredSize = sizeof(DWORD);
|
||||
for (CurrentEntry = DirObj->head.Flink; CurrentEntry != &DirObj->head;
|
||||
CurrentEntry = CurrentEntry->Flink)
|
||||
{
|
||||
CurrentObject = CONTAINING_RECORD(CurrentEntry, OBJECT_HEADER, Entry);
|
||||
*pRequiredSize += CurrentObject->Name.Length + sizeof(UNICODE_NULL);
|
||||
++EntryCount;
|
||||
}
|
||||
|
||||
DPRINT1("Required size: %d Entry count: %d\n", *pRequiredSize, EntryCount);
|
||||
|
||||
/*
|
||||
* Check if the supplied buffer is large enought.
|
||||
*/
|
||||
|
||||
if (*pRequiredSize > dwSize)
|
||||
{
|
||||
ExFreePool(DirectoryNameW.Buffer);
|
||||
ObDereferenceObject(DirectoryHandle);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the resulting buffer contents.
|
||||
*/
|
||||
|
||||
*((DWORD *)lpBuffer) = EntryCount;
|
||||
BufferChar = (PWCHAR)((INT_PTR)lpBuffer + 4);
|
||||
for (CurrentEntry = DirObj->head.Flink; CurrentEntry != &DirObj->head;
|
||||
CurrentEntry = CurrentEntry->Flink)
|
||||
{
|
||||
CurrentObject = CONTAINING_RECORD(CurrentEntry, OBJECT_HEADER, Entry);
|
||||
wcscpy(BufferChar, CurrentObject->Name.Buffer);
|
||||
DPRINT1("Name: %s\n", BufferChar);
|
||||
BufferChar += (CurrentObject->Name.Length / sizeof(WCHAR)) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free any resource.
|
||||
*/
|
||||
|
||||
ExFreePool(DirectoryNameW.Buffer);
|
||||
ObDereferenceObject(DirectoryHandle);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
#else
|
||||
UNIMPLEMENTED
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
/* The WindowStation name list and desktop name list are build in completely
|
||||
different ways. Call the appropriate function */
|
||||
return NULL == hWindowStation ? BuildWindowStationNameList(dwSize, lpBuffer, pRequiredSize) :
|
||||
BuildDesktopNameList(hWindowStation, dwSize, lpBuffer, pRequiredSize);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue