NTAPI
UserCreateWinstaDirectory(VOID)
{
- PPEB Peb;
NTSTATUS Status;
- WCHAR wstrWindowStationsDir[MAX_PATH];
+ PPEB Peb;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hWinstaDir;
+ WCHAR wstrWindowStationsDir[MAX_PATH];
/* Create the WindowStations directory and cache its path for later use */
Peb = NtCurrentPeb();
}
else
{
- swprintf(wstrWindowStationsDir,
- L"%ws\\%lu%ws",
- SESSION_DIR,
- Peb->SessionId,
- WINSTA_OBJ_DIR);
+ Status = RtlStringCbPrintfW(wstrWindowStationsDir,
+ sizeof(wstrWindowStationsDir),
+ L"%ws\\%lu%ws",
+ SESSION_DIR,
+ Peb->SessionId,
+ WINSTA_OBJ_DIR);
+ if (!NT_SUCCESS(Status))
+ return Status;
if (!RtlCreateUnicodeString(&gustrWindowStationsDir, wstrWindowStationsDir))
{
InitializeObjectAttributes(&ObjectAttributes,
&gustrWindowStationsDir,
- 0,
+ OBJ_KERNEL_HANDLE,
NULL,
NULL);
- Status = ZwCreateDirectoryObject(&hWinstaDir, 0, &ObjectAttributes);
+ Status = ZwCreateDirectoryObject(&hWinstaDir, DIRECTORY_CREATE_OBJECT, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir, Status);
/* OBJECT CALLBACKS **********************************************************/
NTSTATUS
-APIENTRY
+NTAPI
IntWinStaObjectDelete(
_In_ PVOID Parameters)
{
}
NTSTATUS
-APIENTRY
+NTAPI
IntWinStaObjectParse(
_In_ PVOID Parameters)
{
NTSTATUS
NTAPI
-IntWinstaOkToClose(
+IntWinStaOkToClose(
_In_ PVOID Parameters)
{
PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS OkToCloseParameters = Parameters;
* lpSecurity
* Security descriptor
*
- * Unknown3, Unknown4, Unknown5
+ * Unknown3, Unknown4, Unknown5, Unknown6
* Unused
*
* Return Value
* exists, the function succeeds and returns a handle to the existing
* window station. If the function fails, the return value is NULL.
*
- * Todo
- * Correct the prototype to match the Windows one (with 7 parameters
- * on Windows XP).
- *
* Status
* @implemented
*/
-HWINSTA APIENTRY
-NtUserCreateWindowStation(
- POBJECT_ATTRIBUTES ObjectAttributes,
- ACCESS_MASK dwDesiredAccess,
+NTSTATUS
+FASTCALL
+IntCreateWindowStation(
+ OUT HWINSTA* phWinSta,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN KPROCESSOR_MODE AccessMode,
+ IN ACCESS_MASK dwDesiredAccess,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6)
{
- UNICODE_STRING WindowStationName;
- PWINSTATION_OBJECT WindowStationObject;
- HWINSTA WindowStation;
NTSTATUS Status;
+ HWINSTA WindowStation;
+ PWINSTATION_OBJECT WindowStationObject;
- TRACE("NtUserCreateWindowStation called\n");
+ TRACE("IntCreateWindowStation called\n");
+
+ ASSERT(phWinSta);
+ *phWinSta = NULL;
Status = ObOpenObjectByName(ObjectAttributes,
ExWindowStationObjectType,
- UserMode,
+ AccessMode,
NULL,
dwDesiredAccess,
NULL,
(PVOID*)&WindowStation);
-
if (NT_SUCCESS(Status))
{
- TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes->ObjectName);
- return (HWINSTA)WindowStation;
+ TRACE("IntCreateWindowStation opened window station %wZ\n",
+ ObjectAttributes->ObjectName);
+ *phWinSta = WindowStation;
+ return Status;
}
/*
- * No existing window station found, try to create new one
+ * No existing window station found, try to create new one.
*/
- /* Capture window station name */
- _SEH2_TRY
- {
- ProbeForRead( ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1);
- Status = IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName, ObjectAttributes->ObjectName);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status =_SEH2_GetExceptionCode();
- }
- _SEH2_END
-
- if (! NT_SUCCESS(Status))
- {
- ERR("Failed reading capturing window station name\n");
- SetLastNtError(Status);
- return NULL;
- }
-
/* Create the window station object */
- Status = ObCreateObject(UserMode,
+ Status = ObCreateObject(KernelMode,
ExWindowStationObjectType,
ObjectAttributes,
- UserMode,
+ AccessMode,
NULL,
sizeof(WINSTATION_OBJECT),
0,
0,
(PVOID*)&WindowStationObject);
-
if (!NT_SUCCESS(Status))
{
- ERR("ObCreateObject failed with %lx for window station %wZ\n", Status, &WindowStationName);
- ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING);
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- return 0;
+ ERR("ObCreateObject failed with %lx for window station %wZ\n",
+ Status, ObjectAttributes->ObjectName);
+ SetLastNtError(Status);
+ return Status;
}
/* Initialize the window station */
RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT));
InitializeListHead(&WindowStationObject->DesktopListHead);
- WindowStationObject->Name = WindowStationName;
+ WindowStationObject->Name = *ObjectAttributes->ObjectName;
+ ObjectAttributes->ObjectName = NULL; // FIXME! (see NtUserCreateWindowStation())
WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId;
Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
if (!NT_SUCCESS(Status))
{
- ERR("RtlCreateAtomTable failed with %lx for window station %wZ\n", Status, &WindowStationName);
+ ERR("RtlCreateAtomTable failed with %lx for window station %wZ\n", Status, ObjectAttributes->ObjectName);
ObDereferenceObject(WindowStationObject);
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- return 0;
+ SetLastNtError(Status);
+ return Status;
}
- Status = ObInsertObject((PVOID)WindowStationObject,
+ Status = ObInsertObject(WindowStationObject,
NULL,
dwDesiredAccess,
0,
NULL,
(PVOID*)&WindowStation);
-
if (!NT_SUCCESS(Status))
{
ERR("ObInsertObject failed with %lx for window station\n", Status);
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- return 0;
+ SetLastNtError(Status);
+ return Status;
}
+ // FIXME! TODO: Add this new window station to a linked list
+
if (InputWindowStation == NULL)
{
ERR("Initializing input window station\n");
WindowStationObject->Flags |= WSS_NOIO;
}
- TRACE("NtUserCreateWindowStation created object %p with name %wZ handle %p\n",
- WindowStation, &WindowStationObject->Name, WindowStation);
- return WindowStation;
+ TRACE("IntCreateWindowStation created object 0x%p with name %wZ handle 0x%p\n",
+ WindowStationObject, &WindowStationObject->Name, WindowStation);
+
+ *phWinSta = WindowStation;
+ return STATUS_SUCCESS;
+}
+
+HWINSTA
+APIENTRY
+NtUserCreateWindowStation(
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN ACCESS_MASK dwDesiredAccess,
+ DWORD Unknown2,
+ DWORD Unknown3,
+ DWORD Unknown4,
+ DWORD Unknown5,
+ DWORD Unknown6)
+{
+ NTSTATUS Status;
+ HWINSTA hWinSta;
+ OBJECT_ATTRIBUTES LocalObjectAttributes;
+ UNICODE_STRING WindowStationName;
+
+ TRACE("NtUserCreateWindowStation called\n");
+
+ /* Capture window station name */
+ _SEH2_TRY
+ {
+ ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));
+ LocalObjectAttributes = *ObjectAttributes;
+ Status = IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName,
+ LocalObjectAttributes.ObjectName);
+ LocalObjectAttributes.ObjectName = &WindowStationName;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status =_SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Failed reading or capturing window station name, Status 0x%08lx\n", Status);
+ SetLastNtError(Status);
+ return NULL;
+ }
+
+ // TODO: Capture and use the SecurityQualityOfService!
+
+ Status = IntCreateWindowStation(&hWinSta,
+ &LocalObjectAttributes,
+ UserMode,
+ dwDesiredAccess,
+ Unknown2,
+ Unknown3,
+ Unknown4,
+ Unknown5,
+ Unknown6);
+
+ // FIXME! Because in some situations we store the allocated window station name
+ // inside the window station, we must not free it now! We know this fact when
+ // IntCreateWindowStation() sets LocalObjectAttributes.ObjectName to NULL.
+ // This hack must be removed once we just use the stored Ob name instead
+ // (in which case we will always free the allocated name here).
+ if (LocalObjectAttributes.ObjectName)
+ ExFreePoolWithTag(LocalObjectAttributes.ObjectName->Buffer, TAG_STRING);
+
+ if (NT_SUCCESS(Status))
+ {
+ TRACE("NtUserCreateWindowStation created a window station with handle 0x%p\n", hWinSta);
+ }
+ else
+ {
+ ASSERT(hWinSta == NULL);
+ TRACE("NtUserCreateWindowStation failed to create a window station!\n");
+ }
+
+ return hWinSta;
}
/*
goto Exit;
}
- TRACE("WinSta or Desktop opened!!\n");
+ TRACE("WinSta or Desktop opened!\n");
/* Get data */
switch (nIndex)
{
case UOI_FLAGS:
{
- /* This is a default implementation that does almost nothing */
- ObjectFlags.fInherit = FALSE;
+ OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
+ ULONG BytesWritten;
+
ObjectFlags.fReserved = FALSE;
+
+ /* Check whether this handle is inheritable */
+ Status = ZwQueryObject(hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION),
+ &BytesWritten);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ZwQueryObject failed, Status 0x%08lx\n", Status);
+ break;
+ }
+ ObjectFlags.fInherit = HandleInfo.Inherit;
+
ObjectFlags.dwFlags = 0;
+ if (WinStaObject != NULL)
+ {
+ if (!(WinStaObject->Flags & WSS_NOIO))
+ ObjectFlags.dwFlags |= WSF_VISIBLE;
+ }
+ else if (DesktopObject != NULL)
+ {
+ FIXME("Setting DF_ALLOWOTHERACCOUNTHOOK is unimplemented.\n");
+ }
+ else
+ {
+ ERR("No associated WinStaObject nor DesktopObject!\n");
+ }
pvData = &ObjectFlags;
nDataSize = sizeof(ObjectFlags);
Status = STATUS_SUCCESS;
- ERR("UOI_FLAGS unimplemented!\n");
break;
}
case UOI_NAME:
{
+ // FIXME: Use either ObQueryNameString() or read directly that name inside the Object section!
if (WinStaObject != NULL)
{
pvData = WinStaObject->Name.Buffer;
ppi = PsGetCurrentProcessWin32Process();
/* Reference the new window station */
- if(hWindowStation !=NULL)
+ if (hWindowStation != NULL)
{
Status = IntValidateWindowStationHandle(hWindowStation,
UserMode,
hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess);
/* Dereference the previous window station */
- if(OldWinSta != NULL)
+ if (OldWinSta != NULL)
{
ObDereferenceObject(OldWinSta);
}
/* Check if we have a stale handle (it should happen for console apps) */
- if(hwinstaOld != ppi->hwinsta)
+ if (hwinstaOld != ppi->hwinsta)
{
ObCloseHandle(hwinstaOld, UserMode);
}
ppi->W32PF_flags &= ~W32PF_READSCREENACCESSGRANTED;
}
- if (NewWinSta && !(NewWinSta->Flags & WSS_NOIO) )
+ if (NewWinSta && !(NewWinSta->Flags & WSS_NOIO))
{
ppi->W32PF_flags |= W32PF_IOWINSTA;
}
POBJECT_DIRECTORY_INFORMATION DirEntry;
WCHAR NullWchar;
+ //
+ // FIXME: Fully wrong! Since, by calling NtUserCreateWindowStation
+ // with judicious parameters one can create window stations elsewhere
+ // than in Windows\WindowStations directory, Win32k definitely MUST
+ // maintain a list of window stations it has created, and not rely
+ // on the enumeration of Windows\WindowStations !!!
+ //
+
/*
* Try to open the directory.
*/
return ret;
}
-BOOL APIENTRY
+BOOL
+NTAPI
NtUserSetWindowStationUser(
- HWINSTA hWindowStation,
- PLUID pluid,
- PSID psid,
- DWORD size)
+ IN HWINSTA hWindowStation,
+ IN PLUID pluid,
+ IN PSID psid OPTIONAL,
+ IN DWORD size)
{
+ BOOL Ret = FALSE;
NTSTATUS Status;
PWINSTATION_OBJECT WindowStation = NULL;
- BOOL Ret = FALSE;
+ LUID luidUser;
UserEnterExclusive();
goto Leave;
}
+ /* Validate the window station */
Status = IntValidateWindowStationHandle(hWindowStation,
UserMode,
0,
&WindowStation,
- 0);
+ NULL);
if (!NT_SUCCESS(Status))
{
goto Leave;
}
- if (WindowStation->psidUser)
- {
- ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY);
- }
-
- WindowStation->psidUser = ExAllocatePoolWithTag(PagedPool, size, USERTAG_SECURITY);
- if (WindowStation->psidUser == NULL)
- {
- EngSetLastError(ERROR_OUTOFMEMORY);
- goto Leave;
- }
-
+ /* Capture the user LUID */
_SEH2_TRY
{
- ProbeForRead( psid, size, 1);
- ProbeForRead( pluid, sizeof(LUID), 1);
-
- RtlCopyMemory(WindowStation->psidUser, psid, size);
- WindowStation->luidUser = *pluid;
+ ProbeForRead(pluid, sizeof(LUID), 1);
+ luidUser = *pluid;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(goto Leave);
}
_SEH2_END;
- if (!NT_SUCCESS(Status))
+ /* Reset the window station user LUID */
+ RtlZeroMemory(&WindowStation->luidUser, sizeof(LUID));
+
+ /* Reset the window station user SID */
+ if (WindowStation->psidUser)
{
ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY);
- WindowStation->psidUser = 0;
- goto Leave;
+ WindowStation->psidUser = NULL;
+ }
+
+ /* Copy the new user SID if one has been provided */
+ if (psid)
+ {
+ WindowStation->psidUser = ExAllocatePoolWithTag(PagedPool, size, USERTAG_SECURITY);
+ if (WindowStation->psidUser == NULL)
+ {
+ EngSetLastError(ERROR_OUTOFMEMORY);
+ goto Leave;
+ }
+
+ Status = STATUS_SUCCESS;
+ _SEH2_TRY
+ {
+ ProbeForRead(psid, size, 1);
+ RtlCopyMemory(WindowStation->psidUser, psid, size);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY);
+ WindowStation->psidUser = NULL;
+ goto Leave;
+ }
}
+ /* Copy the new user LUID */
+ WindowStation->luidUser = luidUser;
+
Ret = TRUE;
Leave:
- if (WindowStation) ObDereferenceObject(WindowStation);
+ if (WindowStation)
+ ObDereferenceObject(WindowStation);
+
UserLeave();
return Ret;
}