mirror of
https://github.com/reactos/reactos.git
synced 2025-01-04 21:38:43 +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_TIMERTD TAG('T', 'I', 'M', 'T') /* timer thread dereference list */
|
||||||
#define TAG_TIMERBMP TAG('T', 'I', 'M', 'B') /* timers bitmap */
|
#define TAG_TIMERBMP TAG('T', 'I', 'M', 'B') /* timers bitmap */
|
||||||
#define TAG_CALLBACK TAG('C', 'B', 'C', 'K') /* callback memory */
|
#define TAG_CALLBACK TAG('C', 'B', 'C', 'K') /* callback memory */
|
||||||
|
#define TAG_WINSTA TAG('W', 'S', 'T', 'A') /* window station */
|
||||||
|
|
||||||
/* objects */
|
/* objects */
|
||||||
#define TAG_BEZIER TAG('B', 'E', 'Z', 'R') /* bezier */
|
#define TAG_BEZIER TAG('B', 'E', 'Z', 'R') /* bezier */
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -954,6 +954,295 @@ NtUserSetWindowStationUser(
|
||||||
return 0;
|
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
|
* NtUserBuildNameList
|
||||||
*
|
*
|
||||||
|
@ -977,103 +1266,20 @@ NtUserSetWindowStationUser(
|
||||||
* Otherwise it's size of buffer needed for function to succeed.
|
* Otherwise it's size of buffer needed for function to succeed.
|
||||||
*
|
*
|
||||||
* Status
|
* Status
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
NtUserBuildNameList(
|
NtUserBuildNameList(
|
||||||
HWINSTA hWinSta,
|
HWINSTA hWindowStation,
|
||||||
ULONG dwSize,
|
ULONG dwSize,
|
||||||
PVOID lpBuffer,
|
PVOID lpBuffer,
|
||||||
PULONG pRequiredSize)
|
PULONG pRequiredSize)
|
||||||
{
|
{
|
||||||
#if 0
|
/* The WindowStation name list and desktop name list are build in completely
|
||||||
NTSTATUS Status;
|
different ways. Call the appropriate function */
|
||||||
HANDLE DirectoryHandle;
|
return NULL == hWindowStation ? BuildWindowStationNameList(dwSize, lpBuffer, pRequiredSize) :
|
||||||
ULONG EntryCount = 0;
|
BuildDesktopNameList(hWindowStation, dwSize, lpBuffer, pRequiredSize);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue