49702059d79576b824cf2b8a65835b929445ca6f
[reactos.git] / win32ss / user / ntuser / winsta.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Window stations
5 * FILE: win32ss/user/ntuser/winsta.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * TODO: The process window station is created on
8 * the first USER32/GDI32 call not related
9 * to window station/desktop handling
10 */
11
12 #include <win32k.h>
13 DBG_DEFAULT_CHANNEL(UserWinsta);
14
15 /* GLOBALS *******************************************************************/
16
17 /* Currently active window station */
18 PWINSTATION_OBJECT InputWindowStation = NULL;
19
20 /* Winlogon SAS window */
21 HWND hwndSAS = NULL;
22
23 /* Full path to WindowStations directory */
24 UNICODE_STRING gustrWindowStationsDir;
25
26 /* INITIALIZATION FUNCTIONS ****************************************************/
27
28 INIT_FUNCTION
29 NTSTATUS
30 NTAPI
31 InitWindowStationImpl(VOID)
32 {
33 GENERIC_MAPPING IntWindowStationMapping = { WINSTA_READ,
34 WINSTA_WRITE,
35 WINSTA_EXECUTE,
36 WINSTA_ACCESS_ALL};
37
38 /* Set Winsta Object Attributes */
39 ExWindowStationObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(WINSTATION_OBJECT);
40 ExWindowStationObjectType->TypeInfo.GenericMapping = IntWindowStationMapping;
41 ExWindowStationObjectType->TypeInfo.ValidAccessMask = WINSTA_ACCESS_ALL;
42
43 return STATUS_SUCCESS;
44 }
45
46 NTSTATUS
47 NTAPI
48 UserCreateWinstaDirectory(VOID)
49 {
50 PPEB Peb;
51 NTSTATUS Status;
52 WCHAR wstrWindowStationsDir[MAX_PATH];
53 OBJECT_ATTRIBUTES ObjectAttributes;
54 HANDLE hWinstaDir;
55
56 /* Create the WindowStations directory and cache its path for later use */
57 Peb = NtCurrentPeb();
58 if(Peb->SessionId == 0)
59 {
60 if (!RtlCreateUnicodeString(&gustrWindowStationsDir, WINSTA_OBJ_DIR))
61 {
62 return STATUS_INSUFFICIENT_RESOURCES;
63 }
64 }
65 else
66 {
67 swprintf(wstrWindowStationsDir,
68 L"%ws\\%lu%ws",
69 SESSION_DIR,
70 Peb->SessionId,
71 WINSTA_OBJ_DIR);
72
73 if (!RtlCreateUnicodeString(&gustrWindowStationsDir, wstrWindowStationsDir))
74 {
75 return STATUS_INSUFFICIENT_RESOURCES;
76 }
77 }
78
79 InitializeObjectAttributes(&ObjectAttributes,
80 &gustrWindowStationsDir,
81 0,
82 NULL,
83 NULL);
84 Status = ZwCreateDirectoryObject(&hWinstaDir, 0, &ObjectAttributes);
85 if (!NT_SUCCESS(Status))
86 {
87 ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir, Status);
88 return Status;
89 }
90
91 TRACE("Created directory %wZ for session %lu\n", &gustrWindowStationsDir, Peb->SessionId);
92
93 return Status;
94 }
95
96 /* OBJECT CALLBACKS **********************************************************/
97
98 NTSTATUS
99 APIENTRY
100 IntWinStaObjectDelete(
101 _In_ PVOID Parameters)
102 {
103 PWIN32_DELETEMETHOD_PARAMETERS DeleteParameters = Parameters;
104 PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeleteParameters->Object;
105
106 TRACE("Deleting window station (0x%p)\n", WinSta);
107
108 WinSta->Flags |= WSS_DYING;
109
110 UserEmptyClipboardData(WinSta);
111
112 RtlDestroyAtomTable(WinSta->AtomTable);
113
114 RtlFreeUnicodeString(&WinSta->Name);
115
116 return STATUS_SUCCESS;
117 }
118
119 NTSTATUS
120 APIENTRY
121 IntWinStaObjectParse(
122 _In_ PVOID Parameters)
123 {
124 PWIN32_PARSEMETHOD_PARAMETERS ParseParameters = Parameters;
125 PUNICODE_STRING RemainingName = ParseParameters->RemainingName;
126
127 /* Assume we don't find anything */
128 *ParseParameters->Object = NULL;
129
130 /* Check for an empty name */
131 if (!RemainingName->Length)
132 {
133 /* Make sure this is a window station, can't parse a desktop now */
134 if (ParseParameters->ObjectType != ExWindowStationObjectType)
135 {
136 /* Fail */
137 return STATUS_OBJECT_TYPE_MISMATCH;
138 }
139
140 /* Reference the window station and return */
141 ObReferenceObject(ParseParameters->ParseObject);
142 *ParseParameters->Object = ParseParameters->ParseObject;
143 return STATUS_SUCCESS;
144 }
145
146 /* Check for leading slash */
147 if (RemainingName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
148 {
149 /* Skip it */
150 RemainingName->Buffer++;
151 RemainingName->Length -= sizeof(WCHAR);
152 RemainingName->MaximumLength -= sizeof(WCHAR);
153 }
154
155 /* Check if there is still a slash */
156 if (wcschr(RemainingName->Buffer, OBJ_NAME_PATH_SEPARATOR))
157 {
158 /* In this case, fail */
159 return STATUS_OBJECT_PATH_INVALID;
160 }
161
162 /*
163 * Check if we are parsing a desktop.
164 */
165 if (ParseParameters->ObjectType == ExDesktopObjectType)
166 {
167 /* Then call the desktop parse routine */
168 return IntDesktopObjectParse(ParseParameters->ParseObject,
169 ParseParameters->ObjectType,
170 ParseParameters->AccessState,
171 ParseParameters->AccessMode,
172 ParseParameters->Attributes,
173 ParseParameters->CompleteName,
174 RemainingName,
175 ParseParameters->Context,
176 ParseParameters->SecurityQos,
177 ParseParameters->Object);
178 }
179
180 /* Should hopefully never get here */
181 return STATUS_OBJECT_TYPE_MISMATCH;
182 }
183
184 NTSTATUS
185 NTAPI
186 IntWinstaOkToClose(
187 _In_ PVOID Parameters)
188 {
189 PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS OkToCloseParameters = Parameters;
190 PPROCESSINFO ppi;
191
192 ppi = PsGetCurrentProcessWin32Process();
193
194 if(ppi && (OkToCloseParameters->Handle == ppi->hwinsta))
195 {
196 return STATUS_ACCESS_DENIED;
197 }
198
199 return STATUS_SUCCESS;
200 }
201
202 /* PRIVATE FUNCTIONS **********************************************************/
203
204 /*
205 * IntValidateWindowStationHandle
206 *
207 * Validates the window station handle.
208 *
209 * Remarks
210 * If the function succeeds, the handle remains referenced. If the
211 * fucntion fails, last error is set.
212 */
213
214 NTSTATUS FASTCALL
215 IntValidateWindowStationHandle(
216 HWINSTA WindowStation,
217 KPROCESSOR_MODE AccessMode,
218 ACCESS_MASK DesiredAccess,
219 PWINSTATION_OBJECT *Object,
220 POBJECT_HANDLE_INFORMATION pObjectHandleInfo)
221 {
222 NTSTATUS Status;
223
224 if (WindowStation == NULL)
225 {
226 ERR("Invalid window station handle\n");
227 EngSetLastError(ERROR_INVALID_HANDLE);
228 return STATUS_INVALID_HANDLE;
229 }
230
231 Status = ObReferenceObjectByHandle(WindowStation,
232 DesiredAccess,
233 ExWindowStationObjectType,
234 AccessMode,
235 (PVOID*)Object,
236 pObjectHandleInfo);
237
238 if (!NT_SUCCESS(Status))
239 SetLastNtError(Status);
240
241 return Status;
242 }
243
244 BOOL FASTCALL
245 co_IntInitializeDesktopGraphics(VOID)
246 {
247 TEXTMETRICW tmw;
248 UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY");
249 PDESKTOP pdesk;
250
251 ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
252 if (NULL == ScreenDeviceContext)
253 {
254 IntDestroyPrimarySurface();
255 return FALSE;
256 }
257 GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_PUBLIC);
258
259 if (! IntCreatePrimarySurface())
260 {
261 return FALSE;
262 }
263
264 hSystemBM = NtGdiCreateCompatibleDC(ScreenDeviceContext);
265
266 NtGdiSelectFont(hSystemBM, NtGdiGetStockObject(SYSTEM_FONT));
267 GreSetDCOwner(hSystemBM, GDI_OBJ_HMGR_PUBLIC);
268
269 /* Update the SERVERINFO */
270 gpsi->aiSysMet[SM_CXSCREEN] = gppdevPrimary->gdiinfo.ulHorzRes;
271 gpsi->aiSysMet[SM_CYSCREEN] = gppdevPrimary->gdiinfo.ulVertRes;
272 gpsi->Planes = NtGdiGetDeviceCaps(ScreenDeviceContext, PLANES);
273 gpsi->BitsPixel = NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL);
274 gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel;
275 gpsi->dmLogPixels = NtGdiGetDeviceCaps(ScreenDeviceContext, LOGPIXELSY);
276 if (NtGdiGetDeviceCaps(ScreenDeviceContext, RASTERCAPS) & RC_PALETTE)
277 {
278 gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
279 }
280 else
281 gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
282 // Font is realized and this dc was previously set to internal DC_ATTR.
283 gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar);
284 gpsi->tmSysFont = tmw;
285
286 /* Put the pointer in the center of the screen */
287 gpsi->ptCursor.x = gpsi->aiSysMet[SM_CXSCREEN] / 2;
288 gpsi->ptCursor.y = gpsi->aiSysMet[SM_CYSCREEN] / 2;
289
290 /* Attach monitor */
291 UserAttachMonitor((HDEV)gppdevPrimary);
292
293 /* Setup the cursor */
294 co_IntLoadDefaultCursors();
295
296 /* Setup the icons */
297 co_IntSetWndIcons();
298
299 /* Setup Menu */
300 MenuInit();
301
302 /* Show the desktop */
303 pdesk = IntGetActiveDesktop();
304 ASSERT(pdesk);
305 co_IntShowDesktop(pdesk, gpsi->aiSysMet[SM_CXSCREEN], gpsi->aiSysMet[SM_CYSCREEN], TRUE);
306
307 return TRUE;
308 }
309
310 VOID FASTCALL
311 IntEndDesktopGraphics(VOID)
312 {
313 if (NULL != ScreenDeviceContext)
314 { // No need to allocate a new dcattr.
315 GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_POWNED);
316 GreDeleteObject(ScreenDeviceContext);
317 ScreenDeviceContext = NULL;
318 }
319 IntHideDesktop(IntGetActiveDesktop());
320 IntDestroyPrimarySurface();
321 }
322
323 HDC FASTCALL
324 IntGetScreenDC(VOID)
325 {
326 return ScreenDeviceContext;
327 }
328
329 BOOL FASTCALL
330 CheckWinstaAttributeAccess(ACCESS_MASK DesiredAccess)
331 {
332 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
333 if ( gpidLogon != PsGetCurrentProcessId() )
334 {
335 if (!(ppi->W32PF_flags & W32PF_IOWINSTA))
336 {
337 ERR("Requires Interactive Window Station\n");
338 EngSetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
339 return FALSE;
340 }
341 if (!RtlAreAllAccessesGranted(ppi->amwinsta, DesiredAccess))
342 {
343 ERR("Access Denied\n");
344 EngSetLastError(ERROR_ACCESS_DENIED);
345 return FALSE;
346 }
347 }
348 return TRUE;
349 }
350
351
352 /* PUBLIC FUNCTIONS ***********************************************************/
353
354 /*
355 * NtUserCreateWindowStation
356 *
357 * Creates a new window station.
358 *
359 * Parameters
360 * lpszWindowStationName
361 * Pointer to a null-terminated string specifying the name of the
362 * window station to be created. Window station names are
363 * case-insensitive and cannot contain backslash characters (\).
364 * Only members of the Administrators group are allowed to specify a
365 * name.
366 *
367 * dwDesiredAccess
368 * Requested type of access
369 *
370 * lpSecurity
371 * Security descriptor
372 *
373 * Unknown3, Unknown4, Unknown5
374 * Unused
375 *
376 * Return Value
377 * If the function succeeds, the return value is a handle to the newly
378 * created window station. If the specified window station already
379 * exists, the function succeeds and returns a handle to the existing
380 * window station. If the function fails, the return value is NULL.
381 *
382 * Todo
383 * Correct the prototype to match the Windows one (with 7 parameters
384 * on Windows XP).
385 *
386 * Status
387 * @implemented
388 */
389
390 HWINSTA APIENTRY
391 NtUserCreateWindowStation(
392 POBJECT_ATTRIBUTES ObjectAttributes,
393 ACCESS_MASK dwDesiredAccess,
394 DWORD Unknown2,
395 DWORD Unknown3,
396 DWORD Unknown4,
397 DWORD Unknown5,
398 DWORD Unknown6)
399 {
400 UNICODE_STRING WindowStationName;
401 PWINSTATION_OBJECT WindowStationObject;
402 HWINSTA WindowStation;
403 NTSTATUS Status;
404
405 TRACE("NtUserCreateWindowStation called\n");
406
407 Status = ObOpenObjectByName(ObjectAttributes,
408 ExWindowStationObjectType,
409 UserMode,
410 NULL,
411 dwDesiredAccess,
412 NULL,
413 (PVOID*)&WindowStation);
414
415 if (NT_SUCCESS(Status))
416 {
417 TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes->ObjectName);
418 return (HWINSTA)WindowStation;
419 }
420
421 /*
422 * No existing window station found, try to create new one
423 */
424
425 /* Capture window station name */
426 _SEH2_TRY
427 {
428 ProbeForRead( ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1);
429 Status = IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName, ObjectAttributes->ObjectName);
430 }
431 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
432 {
433 Status =_SEH2_GetExceptionCode();
434 }
435 _SEH2_END
436
437 if (! NT_SUCCESS(Status))
438 {
439 ERR("Failed reading capturing window station name\n");
440 SetLastNtError(Status);
441 return NULL;
442 }
443
444 /* Create the window station object */
445 Status = ObCreateObject(UserMode,
446 ExWindowStationObjectType,
447 ObjectAttributes,
448 UserMode,
449 NULL,
450 sizeof(WINSTATION_OBJECT),
451 0,
452 0,
453 (PVOID*)&WindowStationObject);
454
455 if (!NT_SUCCESS(Status))
456 {
457 ERR("ObCreateObject failed with %lx for window station %wZ\n", Status, &WindowStationName);
458 ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING);
459 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
460 return 0;
461 }
462
463 /* Initialize the window station */
464 RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT));
465
466 InitializeListHead(&WindowStationObject->DesktopListHead);
467 WindowStationObject->Name = WindowStationName;
468 WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId;
469 Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
470 if (!NT_SUCCESS(Status))
471 {
472 ERR("RtlCreateAtomTable failed with %lx for window station %wZ\n", Status, &WindowStationName);
473 ObDereferenceObject(WindowStationObject);
474 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
475 return 0;
476 }
477
478 Status = ObInsertObject((PVOID)WindowStationObject,
479 NULL,
480 dwDesiredAccess,
481 0,
482 NULL,
483 (PVOID*)&WindowStation);
484
485 if (!NT_SUCCESS(Status))
486 {
487 ERR("ObInsertObject failed with %lx for window station\n", Status);
488 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
489 return 0;
490 }
491
492 if (InputWindowStation == NULL)
493 {
494 ERR("Initializing input window station\n");
495 InputWindowStation = WindowStationObject;
496
497 WindowStationObject->Flags &= ~WSS_NOIO;
498
499 InitCursorImpl();
500 }
501 else
502 {
503 WindowStationObject->Flags |= WSS_NOIO;
504 }
505
506 TRACE("NtUserCreateWindowStation created object %p with name %wZ handle %p\n",
507 WindowStation, &WindowStationObject->Name, WindowStation);
508 return WindowStation;
509 }
510
511 /*
512 * NtUserOpenWindowStation
513 *
514 * Opens an existing window station.
515 *
516 * Parameters
517 * lpszWindowStationName
518 * Name of the existing window station.
519 *
520 * dwDesiredAccess
521 * Requested type of access.
522 *
523 * Return Value
524 * If the function succeeds, the return value is the handle to the
525 * specified window station. If the function fails, the return value
526 * is NULL.
527 *
528 * Remarks
529 * The returned handle can be closed with NtUserCloseWindowStation.
530 *
531 * Status
532 * @implemented
533 */
534
535 HWINSTA APIENTRY
536 NtUserOpenWindowStation(
537 POBJECT_ATTRIBUTES ObjectAttributes,
538 ACCESS_MASK dwDesiredAccess)
539 {
540 HWINSTA hwinsta;
541 NTSTATUS Status;
542
543 Status = ObOpenObjectByName(ObjectAttributes,
544 ExWindowStationObjectType,
545 UserMode,
546 NULL,
547 dwDesiredAccess,
548 NULL,
549 (PVOID*)&hwinsta);
550
551 if (!NT_SUCCESS(Status))
552 {
553 ERR("NtUserOpenWindowStation failed\n");
554 SetLastNtError(Status);
555 return 0;
556 }
557
558 TRACE("Opened window station %wZ with handle %p\n", ObjectAttributes->ObjectName, hwinsta);
559
560 return hwinsta;
561 }
562
563 /*
564 * NtUserCloseWindowStation
565 *
566 * Closes a window station handle.
567 *
568 * Parameters
569 * hWinSta
570 * Handle to the window station.
571 *
572 * Return Value
573 * Status
574 *
575 * Remarks
576 * The window station handle can be created with NtUserCreateWindowStation
577 * or NtUserOpenWindowStation. Attemps to close a handle to the window
578 * station assigned to the calling process will fail.
579 *
580 * Status
581 * @implemented
582 */
583
584 BOOL
585 APIENTRY
586 NtUserCloseWindowStation(
587 HWINSTA hWinSta)
588 {
589 PWINSTATION_OBJECT Object;
590 NTSTATUS Status;
591
592 TRACE("NtUserCloseWindowStation called (%p)\n", hWinSta);
593
594 if (hWinSta == UserGetProcessWindowStation())
595 {
596 ERR("Attempted to close process window station\n");
597 return FALSE;
598 }
599
600 Status = IntValidateWindowStationHandle(hWinSta,
601 UserMode,
602 0,
603 &Object,
604 0);
605
606 if (!NT_SUCCESS(Status))
607 {
608 ERR("Validation of window station handle (%p) failed\n", hWinSta);
609 return FALSE;
610 }
611
612 ObDereferenceObject(Object);
613
614 TRACE("Closing window station handle (%p)\n", hWinSta);
615
616 Status = ObCloseHandle(hWinSta, UserMode);
617 if (!NT_SUCCESS(Status))
618 {
619 SetLastNtError(Status);
620 return FALSE;
621 }
622
623 return TRUE;
624 }
625
626 /*
627 * NtUserGetObjectInformation
628 *
629 * The NtUserGetObjectInformation function retrieves information about a
630 * window station or desktop object.
631 *
632 * Parameters
633 * hObj
634 * Handle to the window station or desktop object for which to
635 * return information. This can be a handle of type HDESK or HWINSTA
636 * (for example, a handle returned by NtUserCreateWindowStation,
637 * NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop).
638 *
639 * nIndex
640 * Specifies the object information to be retrieved.
641 *
642 * pvInfo
643 * Pointer to a buffer to receive the object information.
644 *
645 * nLength
646 * Specifies the size, in bytes, of the buffer pointed to by the
647 * pvInfo parameter.
648 *
649 * lpnLengthNeeded
650 * Pointer to a variable receiving the number of bytes required to
651 * store the requested information. If this variable's value is
652 * greater than the value of the nLength parameter when the function
653 * returns, the function returns FALSE, and none of the information
654 * is copied to the pvInfo buffer. If the value of the variable pointed
655 * to by lpnLengthNeeded is less than or equal to the value of nLength,
656 * the entire information block is copied.
657 *
658 * Return Value
659 * If the function succeeds, the return value is nonzero. If the function
660 * fails, the return value is zero.
661 *
662 * Status
663 * @unimplemented
664 */
665
666 BOOL APIENTRY
667 NtUserGetObjectInformation(
668 HANDLE hObject,
669 DWORD nIndex,
670 PVOID pvInformation,
671 DWORD nLength,
672 PDWORD nLengthNeeded)
673 {
674 NTSTATUS Status;
675 PWINSTATION_OBJECT WinStaObject = NULL;
676 PDESKTOP DesktopObject = NULL;
677 USEROBJECTFLAGS ObjectFlags;
678 PVOID pvData = NULL;
679 DWORD nDataSize = 0;
680
681 _SEH2_TRY
682 {
683 if (nLengthNeeded)
684 ProbeForWrite(nLengthNeeded, sizeof(*nLengthNeeded), 1);
685 ProbeForWrite(pvInformation, nLength, 1);
686 }
687 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
688 {
689 SetLastNtError(_SEH2_GetExceptionCode());
690 return FALSE;
691 }
692 _SEH2_END;
693
694 /* Try window station */
695 TRACE("Trying to open window station %p\n", hObject);
696 Status = ObReferenceObjectByHandle(hObject,
697 0,
698 ExWindowStationObjectType,
699 UserMode,
700 (PVOID*)&WinStaObject,
701 NULL);
702
703 if (Status == STATUS_OBJECT_TYPE_MISMATCH)
704 {
705 /* Try desktop */
706 TRACE("Trying to open desktop %p\n", hObject);
707 WinStaObject = NULL;
708 Status = IntValidateDesktopHandle(hObject,
709 UserMode,
710 0,
711 &DesktopObject);
712 }
713
714 if (!NT_SUCCESS(Status))
715 {
716 ERR("Failed: 0x%x\n", Status);
717 goto Exit;
718 }
719
720 TRACE("WinSta or Desktop opened!!\n");
721
722 /* Get data */
723 switch (nIndex)
724 {
725 case UOI_FLAGS:
726 {
727 /* This is a default implementation that does almost nothing */
728 ObjectFlags.fInherit = FALSE;
729 ObjectFlags.fReserved = FALSE;
730 ObjectFlags.dwFlags = 0;
731
732 pvData = &ObjectFlags;
733 nDataSize = sizeof(ObjectFlags);
734 Status = STATUS_SUCCESS;
735 ERR("UOI_FLAGS unimplemented!\n");
736 break;
737 }
738
739 case UOI_NAME:
740 {
741 if (WinStaObject != NULL)
742 {
743 pvData = WinStaObject->Name.Buffer;
744 nDataSize = WinStaObject->Name.Length + sizeof(WCHAR);
745 Status = STATUS_SUCCESS;
746 }
747 else if (DesktopObject != NULL)
748 {
749 pvData = DesktopObject->pDeskInfo->szDesktopName;
750 nDataSize = (wcslen(DesktopObject->pDeskInfo->szDesktopName) + 1) * sizeof(WCHAR);
751 Status = STATUS_SUCCESS;
752 }
753 else
754 {
755 Status = STATUS_INVALID_PARAMETER;
756 }
757 break;
758 }
759
760 case UOI_TYPE:
761 {
762 if (WinStaObject != NULL)
763 {
764 pvData = L"WindowStation";
765 nDataSize = sizeof(L"WindowStation");
766 Status = STATUS_SUCCESS;
767 }
768 else if (DesktopObject != NULL)
769 {
770 pvData = L"Desktop";
771 nDataSize = sizeof(L"Desktop");
772 Status = STATUS_SUCCESS;
773 }
774 else
775 {
776 Status = STATUS_INVALID_PARAMETER;
777 }
778 break;
779 }
780
781 case UOI_USER_SID:
782 Status = STATUS_NOT_IMPLEMENTED;
783 ERR("UOI_USER_SID unimplemented!\n");
784 break;
785
786 default:
787 Status = STATUS_INVALID_PARAMETER;
788 break;
789 }
790
791 Exit:
792 if ((Status == STATUS_SUCCESS) && (nLength < nDataSize))
793 Status = STATUS_BUFFER_TOO_SMALL;
794
795 _SEH2_TRY
796 {
797 if (nLengthNeeded)
798 *nLengthNeeded = nDataSize;
799
800 /* Try to copy data to caller */
801 if (Status == STATUS_SUCCESS)
802 {
803 TRACE("Trying to copy data to caller (len = %lu, len needed = %lu)\n", nLength, nDataSize);
804 RtlCopyMemory(pvInformation, pvData, nDataSize);
805 }
806 }
807 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
808 {
809 Status = _SEH2_GetExceptionCode();
810 }
811 _SEH2_END;
812
813 /* Release objects */
814 if (DesktopObject != NULL)
815 ObDereferenceObject(DesktopObject);
816 if (WinStaObject != NULL)
817 ObDereferenceObject(WinStaObject);
818
819 if (!NT_SUCCESS(Status))
820 {
821 SetLastNtError(Status);
822 return FALSE;
823 }
824
825 return TRUE;
826 }
827
828 /*
829 * NtUserSetObjectInformation
830 *
831 * The NtUserSetObjectInformation function sets information about a
832 * window station or desktop object.
833 *
834 * Parameters
835 * hObj
836 * Handle to the window station or desktop object for which to set
837 * object information. This value can be a handle of type HDESK or
838 * HWINSTA.
839 *
840 * nIndex
841 * Specifies the object information to be set.
842 *
843 * pvInfo
844 * Pointer to a buffer containing the object information.
845 *
846 * nLength
847 * Specifies the size, in bytes, of the information contained in the
848 * buffer pointed to by pvInfo.
849 *
850 * Return Value
851 * If the function succeeds, the return value is nonzero. If the function
852 * fails the return value is zero.
853 *
854 * Status
855 * @unimplemented
856 */
857
858 BOOL
859 APIENTRY
860 NtUserSetObjectInformation(
861 HANDLE hObject,
862 DWORD nIndex,
863 PVOID pvInformation,
864 DWORD nLength)
865 {
866 /* FIXME: ZwQueryObject */
867 /* FIXME: ZwSetInformationObject */
868 SetLastNtError(STATUS_UNSUCCESSFUL);
869 return FALSE;
870 }
871
872
873
874
875 HWINSTA FASTCALL
876 UserGetProcessWindowStation(VOID)
877 {
878 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
879
880 return ppi->hwinsta;
881 }
882
883
884 /*
885 * NtUserGetProcessWindowStation
886 *
887 * Returns a handle to the current process window station.
888 *
889 * Return Value
890 * If the function succeeds, the return value is handle to the window
891 * station assigned to the current process. If the function fails, the
892 * return value is NULL.
893 *
894 * Status
895 * @implemented
896 */
897
898 HWINSTA APIENTRY
899 NtUserGetProcessWindowStation(VOID)
900 {
901 return UserGetProcessWindowStation();
902 }
903
904 BOOL FASTCALL
905 UserSetProcessWindowStation(HWINSTA hWindowStation)
906 {
907 PPROCESSINFO ppi;
908 NTSTATUS Status;
909 HWINSTA hwinstaOld;
910 OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
911 PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
912
913 ppi = PsGetCurrentProcessWin32Process();
914
915 /* Reference the new window station */
916 if(hWindowStation !=NULL)
917 {
918 Status = IntValidateWindowStationHandle(hWindowStation,
919 UserMode,
920 0,
921 &NewWinSta,
922 &ObjectHandleInfo);
923 if (!NT_SUCCESS(Status))
924 {
925 TRACE("Validation of window station handle (%p) failed\n",
926 hWindowStation);
927 SetLastNtError(Status);
928 return FALSE;
929 }
930 }
931
932 OldWinSta = ppi->prpwinsta;
933 hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess);
934
935 /* Dereference the previous window station */
936 if(OldWinSta != NULL)
937 {
938 ObDereferenceObject(OldWinSta);
939 }
940
941 /* Check if we have a stale handle (it should happen for console apps) */
942 if(hwinstaOld != ppi->hwinsta)
943 {
944 ObCloseHandle(hwinstaOld, UserMode);
945 }
946
947 /*
948 * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
949 */
950
951 PsSetProcessWindowStation(ppi->peProcess, hWindowStation);
952
953 ppi->prpwinsta = NewWinSta;
954 ppi->hwinsta = hWindowStation;
955 ppi->amwinsta = hWindowStation != NULL ? ObjectHandleInfo.GrantedAccess : 0;
956 TRACE("WS : Granted Access 0x%08lx\n",ppi->amwinsta);
957
958 if (RtlAreAllAccessesGranted(ppi->amwinsta, WINSTA_READSCREEN))
959 {
960 ppi->W32PF_flags |= W32PF_READSCREENACCESSGRANTED;
961 }
962 else
963 {
964 ppi->W32PF_flags &= ~W32PF_READSCREENACCESSGRANTED;
965 }
966
967 if (NewWinSta && !(NewWinSta->Flags & WSS_NOIO) )
968 {
969 ppi->W32PF_flags |= W32PF_IOWINSTA;
970 }
971 else // Might be closed if the handle is null.
972 {
973 ppi->W32PF_flags &= ~W32PF_IOWINSTA;
974 }
975 return TRUE;
976 }
977
978 /*
979 * NtUserSetProcessWindowStation
980 *
981 * Assigns a window station to the current process.
982 *
983 * Parameters
984 * hWinSta
985 * Handle to the window station.
986 *
987 * Return Value
988 * Status
989 *
990 * Status
991 * @implemented
992 */
993
994 BOOL APIENTRY
995 NtUserSetProcessWindowStation(HWINSTA hWindowStation)
996 {
997 BOOL ret;
998
999 UserEnterExclusive();
1000
1001 ret = UserSetProcessWindowStation(hWindowStation);
1002
1003 UserLeave();
1004
1005 return ret;
1006 }
1007
1008 /*
1009 * NtUserLockWindowStation
1010 *
1011 * Locks switching desktops. Only the logon application is allowed to call this function.
1012 *
1013 * Status
1014 * @implemented
1015 */
1016
1017 BOOL APIENTRY
1018 NtUserLockWindowStation(HWINSTA hWindowStation)
1019 {
1020 PWINSTATION_OBJECT Object;
1021 NTSTATUS Status;
1022
1023 TRACE("About to set process window station with handle (%p)\n",
1024 hWindowStation);
1025
1026 if (gpidLogon != PsGetCurrentProcessId())
1027 {
1028 ERR("Unauthorized process attempted to lock the window station!\n");
1029 EngSetLastError(ERROR_ACCESS_DENIED);
1030 return FALSE;
1031 }
1032
1033 Status = IntValidateWindowStationHandle(hWindowStation,
1034 UserMode,
1035 0,
1036 &Object,
1037 0);
1038 if (!NT_SUCCESS(Status))
1039 {
1040 TRACE("Validation of window station handle (%p) failed\n",
1041 hWindowStation);
1042 SetLastNtError(Status);
1043 return FALSE;
1044 }
1045
1046 Object->Flags |= WSS_LOCKED;
1047
1048 ObDereferenceObject(Object);
1049 return TRUE;
1050 }
1051
1052 /*
1053 * NtUserUnlockWindowStation
1054 *
1055 * Unlocks switching desktops. Only the logon application is allowed to call this function.
1056 *
1057 * Status
1058 * @implemented
1059 */
1060
1061 BOOL APIENTRY
1062 NtUserUnlockWindowStation(HWINSTA hWindowStation)
1063 {
1064 PWINSTATION_OBJECT Object;
1065 NTSTATUS Status;
1066 BOOL Ret;
1067
1068 TRACE("About to set process window station with handle (%p)\n",
1069 hWindowStation);
1070
1071 if (gpidLogon != PsGetCurrentProcessId())
1072 {
1073 ERR("Unauthorized process attempted to unlock the window station!\n");
1074 EngSetLastError(ERROR_ACCESS_DENIED);
1075 return FALSE;
1076 }
1077
1078 Status = IntValidateWindowStationHandle(hWindowStation,
1079 UserMode,
1080 0,
1081 &Object,
1082 0);
1083 if (!NT_SUCCESS(Status))
1084 {
1085 TRACE("Validation of window station handle (%p) failed\n",
1086 hWindowStation);
1087 SetLastNtError(Status);
1088 return FALSE;
1089 }
1090
1091 Ret = (Object->Flags & WSS_LOCKED) == WSS_LOCKED;
1092 Object->Flags &= ~WSS_LOCKED;
1093
1094 ObDereferenceObject(Object);
1095 return Ret;
1096 }
1097
1098 static NTSTATUS FASTCALL
1099 BuildWindowStationNameList(
1100 ULONG dwSize,
1101 PVOID lpBuffer,
1102 PULONG pRequiredSize)
1103 {
1104 OBJECT_ATTRIBUTES ObjectAttributes;
1105 NTSTATUS Status;
1106 HANDLE DirectoryHandle;
1107 char InitialBuffer[256], *Buffer;
1108 ULONG Context, ReturnLength, BufferSize;
1109 DWORD EntryCount;
1110 POBJECT_DIRECTORY_INFORMATION DirEntry;
1111 WCHAR NullWchar;
1112
1113 /*
1114 * Try to open the directory.
1115 */
1116 InitializeObjectAttributes(&ObjectAttributes,
1117 &gustrWindowStationsDir,
1118 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1119 NULL,
1120 NULL);
1121
1122 Status = ZwOpenDirectoryObject(&DirectoryHandle,
1123 DIRECTORY_QUERY,
1124 &ObjectAttributes);
1125
1126 if (!NT_SUCCESS(Status))
1127 {
1128 return Status;
1129 }
1130
1131 /* First try to query the directory using a fixed-size buffer */
1132 Context = 0;
1133 Buffer = NULL;
1134 Status = ZwQueryDirectoryObject(DirectoryHandle,
1135 InitialBuffer,
1136 sizeof(InitialBuffer),
1137 FALSE,
1138 TRUE,
1139 &Context,
1140 &ReturnLength);
1141 if (NT_SUCCESS(Status))
1142 {
1143 if (STATUS_NO_MORE_ENTRIES == ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
1144 FALSE, &Context, NULL))
1145 {
1146 /* Our fixed-size buffer is large enough */
1147 Buffer = InitialBuffer;
1148 }
1149 }
1150
1151 if (NULL == Buffer)
1152 {
1153 /* Need a larger buffer, check how large exactly */
1154 Status = ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, TRUE, &Context,
1155 &ReturnLength);
1156 if (!NT_SUCCESS(Status))
1157 {
1158 ERR("ZwQueryDirectoryObject failed\n");
1159 ZwClose(DirectoryHandle);
1160 return Status;
1161 }
1162
1163 BufferSize = ReturnLength;
1164 Buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_WINSTA);
1165 if (NULL == Buffer)
1166 {
1167 ZwClose(DirectoryHandle);
1168 return STATUS_NO_MEMORY;
1169 }
1170
1171 /* We should have a sufficiently large buffer now */
1172 Context = 0;
1173 Status = ZwQueryDirectoryObject(DirectoryHandle, Buffer, BufferSize,
1174 FALSE, TRUE, &Context, &ReturnLength);
1175 if (! NT_SUCCESS(Status) ||
1176 STATUS_NO_MORE_ENTRIES != ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
1177 FALSE, &Context, NULL))
1178 {
1179 /* Something went wrong, maybe someone added a directory entry? Just give up. */
1180 ExFreePoolWithTag(Buffer, TAG_WINSTA);
1181 ZwClose(DirectoryHandle);
1182 return NT_SUCCESS(Status) ? STATUS_INTERNAL_ERROR : Status;
1183 }
1184 }
1185
1186 ZwClose(DirectoryHandle);
1187
1188 /*
1189 * Count the required size of buffer.
1190 */
1191 ReturnLength = sizeof(DWORD);
1192 EntryCount = 0;
1193 for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer;
1194 0 != DirEntry->Name.Length;
1195 DirEntry++)
1196 {
1197 ReturnLength += DirEntry->Name.Length + sizeof(WCHAR);
1198 EntryCount++;
1199 }
1200 TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount);
1201 if (NULL != pRequiredSize)
1202 {
1203 Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
1204 if (! NT_SUCCESS(Status))
1205 {
1206 if (Buffer != InitialBuffer)
1207 {
1208 ExFreePoolWithTag(Buffer, TAG_WINSTA);
1209 }
1210 return STATUS_BUFFER_TOO_SMALL;
1211 }
1212 }
1213
1214 /*
1215 * Check if the supplied buffer is large enough.
1216 */
1217 if (dwSize < ReturnLength)
1218 {
1219 if (Buffer != InitialBuffer)
1220 {
1221 ExFreePoolWithTag(Buffer, TAG_WINSTA);
1222 }
1223 return STATUS_BUFFER_TOO_SMALL;
1224 }
1225
1226 /*
1227 * Generate the resulting buffer contents.
1228 */
1229 Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
1230 if (! NT_SUCCESS(Status))
1231 {
1232 if (Buffer != InitialBuffer)
1233 {
1234 ExFreePoolWithTag(Buffer, TAG_WINSTA);
1235 }
1236 return Status;
1237 }
1238 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
1239
1240 NullWchar = L'\0';
1241 for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer;
1242 0 != DirEntry->Name.Length;
1243 DirEntry++)
1244 {
1245 Status = MmCopyToCaller(lpBuffer, DirEntry->Name.Buffer, DirEntry->Name.Length);
1246 if (! NT_SUCCESS(Status))
1247 {
1248 if (Buffer != InitialBuffer)
1249 {
1250 ExFreePoolWithTag(Buffer, TAG_WINSTA);
1251 }
1252 return Status;
1253 }
1254 lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->Name.Length);
1255 Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
1256 if (! NT_SUCCESS(Status))
1257 {
1258 if (Buffer != InitialBuffer)
1259 {
1260 ExFreePoolWithTag(Buffer, TAG_WINSTA);
1261 }
1262 return Status;
1263 }
1264 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
1265 }
1266
1267 /*
1268 * Clean up
1269 */
1270 if (Buffer != InitialBuffer)
1271 {
1272 ExFreePoolWithTag(Buffer, TAG_WINSTA);
1273 }
1274
1275 return STATUS_SUCCESS;
1276 }
1277
1278 static NTSTATUS FASTCALL
1279 BuildDesktopNameList(
1280 HWINSTA hWindowStation,
1281 ULONG dwSize,
1282 PVOID lpBuffer,
1283 PULONG pRequiredSize)
1284 {
1285 NTSTATUS Status;
1286 PWINSTATION_OBJECT WindowStation;
1287 PLIST_ENTRY DesktopEntry;
1288 PDESKTOP DesktopObject;
1289 DWORD EntryCount;
1290 ULONG ReturnLength;
1291 WCHAR NullWchar;
1292 UNICODE_STRING DesktopName;
1293
1294 Status = IntValidateWindowStationHandle(hWindowStation,
1295 UserMode,
1296 0,
1297 &WindowStation,
1298 0);
1299 if (! NT_SUCCESS(Status))
1300 {
1301 return Status;
1302 }
1303
1304 /*
1305 * Count the required size of buffer.
1306 */
1307 ReturnLength = sizeof(DWORD);
1308 EntryCount = 0;
1309 for (DesktopEntry = WindowStation->DesktopListHead.Flink;
1310 DesktopEntry != &WindowStation->DesktopListHead;
1311 DesktopEntry = DesktopEntry->Flink)
1312 {
1313 DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
1314 RtlInitUnicodeString(&DesktopName, DesktopObject->pDeskInfo->szDesktopName);
1315 ReturnLength += DesktopName.Length + sizeof(WCHAR);
1316 EntryCount++;
1317 }
1318 TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount);
1319 if (NULL != pRequiredSize)
1320 {
1321 Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
1322 if (! NT_SUCCESS(Status))
1323 {
1324 ObDereferenceObject(WindowStation);
1325 return STATUS_BUFFER_TOO_SMALL;
1326 }
1327 }
1328
1329 /*
1330 * Check if the supplied buffer is large enough.
1331 */
1332 if (dwSize < ReturnLength)
1333 {
1334 ObDereferenceObject(WindowStation);
1335 return STATUS_BUFFER_TOO_SMALL;
1336 }
1337
1338 /*
1339 * Generate the resulting buffer contents.
1340 */
1341 Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
1342 if (! NT_SUCCESS(Status))
1343 {
1344 ObDereferenceObject(WindowStation);
1345 return Status;
1346 }
1347 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
1348
1349 NullWchar = L'\0';
1350 for (DesktopEntry = WindowStation->DesktopListHead.Flink;
1351 DesktopEntry != &WindowStation->DesktopListHead;
1352 DesktopEntry = DesktopEntry->Flink)
1353 {
1354 DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
1355 RtlInitUnicodeString(&DesktopName, DesktopObject->pDeskInfo->szDesktopName);
1356 Status = MmCopyToCaller(lpBuffer, DesktopName.Buffer, DesktopName.Length);
1357 if (! NT_SUCCESS(Status))
1358 {
1359 ObDereferenceObject(WindowStation);
1360 return Status;
1361 }
1362 lpBuffer = (PVOID) ((PCHAR)lpBuffer + DesktopName.Length);
1363 Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
1364 if (! NT_SUCCESS(Status))
1365 {
1366 ObDereferenceObject(WindowStation);
1367 return Status;
1368 }
1369 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
1370 }
1371
1372 /*
1373 * Clean up and return
1374 */
1375 ObDereferenceObject(WindowStation);
1376 return STATUS_SUCCESS;
1377 }
1378
1379 /*
1380 * NtUserBuildNameList
1381 *
1382 * Function used for enumeration of desktops or window stations.
1383 *
1384 * Parameters
1385 * hWinSta
1386 * For enumeration of window stations this parameter must be set to
1387 * zero. Otherwise it's handle for window station.
1388 *
1389 * dwSize
1390 * Size of buffer passed by caller.
1391 *
1392 * lpBuffer
1393 * Buffer passed by caller. If the function succeeds, the buffer is
1394 * filled with window station/desktop count (in first DWORD) and
1395 * NULL-terminated window station/desktop names.
1396 *
1397 * pRequiredSize
1398 * If the function succeeds, this is the number of bytes copied.
1399 * Otherwise it's size of buffer needed for function to succeed.
1400 *
1401 * Status
1402 * @implemented
1403 */
1404
1405 NTSTATUS APIENTRY
1406 NtUserBuildNameList(
1407 HWINSTA hWindowStation,
1408 ULONG dwSize,
1409 PVOID lpBuffer,
1410 PULONG pRequiredSize)
1411 {
1412 /* The WindowStation name list and desktop name list are build in completely
1413 different ways. Call the appropriate function */
1414 return NULL == hWindowStation ? BuildWindowStationNameList(dwSize, lpBuffer, pRequiredSize) :
1415 BuildDesktopNameList(hWindowStation, dwSize, lpBuffer, pRequiredSize);
1416 }
1417
1418 /*
1419 * @implemented
1420 */
1421 BOOL APIENTRY
1422 NtUserSetLogonNotifyWindow(HWND hWnd)
1423 {
1424 if (gpidLogon != PsGetCurrentProcessId())
1425 {
1426 return FALSE;
1427 }
1428
1429 if (!IntIsWindow(hWnd))
1430 {
1431 return FALSE;
1432 }
1433
1434 hwndSAS = hWnd;
1435
1436 return TRUE;
1437 }
1438
1439 BOOL
1440 APIENTRY
1441 NtUserLockWorkStation(VOID)
1442 {
1443 BOOL ret;
1444 PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
1445
1446 UserEnterExclusive();
1447
1448 if (pti->rpdesk == IntGetActiveDesktop())
1449 {
1450 ret = UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_LOCK_WORKSTATION, 0);
1451 }
1452 else
1453 {
1454 ret = FALSE;
1455 }
1456
1457 UserLeave();
1458
1459 return ret;
1460 }
1461
1462 BOOL APIENTRY
1463 NtUserSetWindowStationUser(
1464 HWINSTA hWindowStation,
1465 PLUID pluid,
1466 PSID psid,
1467 DWORD size)
1468 {
1469 NTSTATUS Status;
1470 PWINSTATION_OBJECT WindowStation = NULL;
1471 BOOL Ret = FALSE;
1472
1473 UserEnterExclusive();
1474
1475 if (gpidLogon != PsGetCurrentProcessId())
1476 {
1477 EngSetLastError(ERROR_ACCESS_DENIED);
1478 goto Leave;
1479 }
1480
1481 Status = IntValidateWindowStationHandle(hWindowStation,
1482 UserMode,
1483 0,
1484 &WindowStation,
1485 0);
1486 if (!NT_SUCCESS(Status))
1487 {
1488 goto Leave;
1489 }
1490
1491 if (WindowStation->psidUser)
1492 {
1493 ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY);
1494 }
1495
1496 WindowStation->psidUser = ExAllocatePoolWithTag(PagedPool, size, USERTAG_SECURITY);
1497 if (WindowStation->psidUser == NULL)
1498 {
1499 EngSetLastError(ERROR_OUTOFMEMORY);
1500 goto Leave;
1501 }
1502
1503 _SEH2_TRY
1504 {
1505 ProbeForRead( psid, size, 1);
1506 ProbeForRead( pluid, sizeof(LUID), 1);
1507
1508 RtlCopyMemory(WindowStation->psidUser, psid, size);
1509 WindowStation->luidUser = *pluid;
1510 }
1511 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1512 {
1513 Status = _SEH2_GetExceptionCode();
1514 }
1515 _SEH2_END;
1516
1517 if (!NT_SUCCESS(Status))
1518 {
1519 ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY);
1520 WindowStation->psidUser = 0;
1521 goto Leave;
1522 }
1523
1524 Ret = TRUE;
1525
1526 Leave:
1527 if (WindowStation) ObDereferenceObject(WindowStation);
1528 UserLeave();
1529 return Ret;
1530 }
1531
1532
1533 /* EOF */