Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

winsta.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

NTSTATUS xxxInitTerminal (PTERMINAL pTerm)
NTSTATUS CreateGlobalAtomTable (PVOID *ppAtomTable)
HWINSTA xxxCreateWindowStation (POBJECT_ATTRIBUTES ObjectAttributes, KPROCESSOR_MODE OwnershipMode, DWORD dwDesiredAccess, HANDLE hKbdLayoutFile, DWORD offTable, PCWSTR pwszKLID, UINT uKbdInputLocale)
VOID FreeWindowStation (PWINDOWSTATION pwinsta)
VOID DestroyWindowStation (PEPROCESS Process, PVOID pobj, ACCESS_MASK amGranted, ULONG cProcessHandles, ULONG cSystemHandles)
NTSTATUS ParseWindowStation (PVOID pContainerObject, POBJECT_TYPE pObjectType, PACCESS_STATE pAccessState, KPROCESSOR_MODE AccessMode, ULONG Attributes, PUNICODE_STRING pstrCompleteName, PUNICODE_STRING pstrRemainingName, PVOID Context OPTIONAL, PSECURITY_QUALITY_OF_SERVICE pqos, PVOID *pObject)
BOOLEAN OkayToCloseWindowStation (PEPROCESS Process OPTIONAL, PVOID Object, HANDLE Handle)
HWINSTA _OpenWindowStation (POBJECT_ATTRIBUTES pObjA, DWORD dwDesiredAccess, KPROCESSOR_MODE AccessMode)
BOOL _CloseWindowStation (HWINSTA hwinsta)
BOOL xxxSetProcessWindowStation (HWINSTA hwinsta, KPROCESSOR_MODE AccessMode)
PWINDOWSTATION _GetProcessWindowStation (HWINSTA *phwinsta)
NTSTATUS _BuildNameList (PWINDOWSTATION pwinsta, PNAMELIST ccxpNameList, UINT cbNameList, PUINT pcbNeeded)
NTSTATUS ReferenceWindowStation (PETHREAD Thread, HWINSTA hwinsta, ACCESS_MASK amDesiredAccess, PWINDOWSTATION *ppwinsta, BOOL fUseDesktop)
UINT _SetWindowStationUser (PWINDOWSTATION pwinsta, PLUID pluidUser, PSID ccxpsidUser, DWORD cbsidUser)
BOOL _LockWorkStation (VOID)

Variables

CONST LPCWSTR lpszStdFormats []


Function Documentation

NTSTATUS _BuildNameList PWINDOWSTATION  pwinsta,
PNAMELIST  ccxpNameList,
UINT  cbNameList,
PUINT  pcbNeeded
 

Definition at line 1264 of file winsta.c.

References AccessCheckObject(), tagNAMELIST::awchNames, tagNAMELIST::cb, tagNAMELIST::cNames, DesktopMapping, DWORD, FALSE, grpWinStaList, KernelMode, _OBJECT_HEADER_NAME_INFO::Name, NTSTATUS(), NULL, OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, PBYTE, tagWINDOWSTATION::rpdeskList, Status, UINT, and WinStaMapping.

Referenced by NtUserBuildNameList().

01269 { 01270 PBYTE pobj; 01271 PWCHAR ccxpwchDest, ccxpwchMax; 01272 ACCESS_MASK amDesired; 01273 POBJECT_HEADER pHead; 01274 POBJECT_HEADER_NAME_INFO pNameInfo; 01275 DWORD iNext; 01276 NTSTATUS Status; 01277 CONST GENERIC_MAPPING *pGenericMapping; 01278 01279 /* 01280 * Note -- NameList is client-side, and so must be protected. 01281 */ 01282 01283 try { 01284 ccxpNameList->cNames = 0; 01285 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 01286 return STATUS_ACCESS_VIOLATION; 01287 } 01288 01289 ccxpwchDest = ccxpNameList->awchNames; 01290 ccxpwchMax = (PWCHAR)((PBYTE)ccxpNameList + cbNameList - sizeof(WCHAR)); 01291 01292 /* 01293 * If we're enumerating windowstations, pwinsta is NULL. Otherwise, 01294 * we're enumerating desktops. 01295 */ 01296 if (pwinsta == NULL) { 01297 pobj = (PBYTE)grpWinStaList; 01298 amDesired = WINSTA_ENUMERATE; 01299 pGenericMapping = &WinStaMapping; 01300 iNext = FIELD_OFFSET(WINDOWSTATION, rpwinstaNext); 01301 } else { 01302 pobj = (PBYTE)pwinsta->rpdeskList; 01303 amDesired = DESKTOP_ENUMERATE; 01304 pGenericMapping = &DesktopMapping; 01305 iNext = FIELD_OFFSET(DESKTOP, rpdeskNext); 01306 } 01307 01308 Status = STATUS_SUCCESS; 01309 *pcbNeeded = 0; 01310 while (pobj != NULL) { 01311 01312 if (AccessCheckObject(pobj, amDesired, KernelMode, pGenericMapping)) { 01313 01314 /* 01315 * Find object name 01316 */ 01317 pHead = OBJECT_TO_OBJECT_HEADER(pobj); 01318 pNameInfo = OBJECT_HEADER_TO_NAME_INFO(pHead); 01319 01320 /* 01321 * If we run out of space, reset the buffer 01322 * and continue so we can compute the needed 01323 * space. 01324 */ 01325 if ((PWCHAR)((PBYTE)ccxpwchDest + pNameInfo->Name.Length + 01326 sizeof(WCHAR)) >= ccxpwchMax) { 01327 *pcbNeeded += (UINT)((PBYTE)ccxpwchDest - (PBYTE)ccxpNameList); 01328 ccxpwchDest = ccxpNameList->awchNames; 01329 Status = STATUS_BUFFER_TOO_SMALL; 01330 } 01331 01332 try { 01333 ccxpNameList->cNames++; 01334 01335 /* 01336 * Copy and terminate the string 01337 */ 01338 RtlCopyMemory(ccxpwchDest, pNameInfo->Name.Buffer, 01339 pNameInfo->Name.Length); 01340 (PBYTE)ccxpwchDest += pNameInfo->Name.Length; 01341 *ccxpwchDest++ = 0; 01342 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 01343 return STATUS_ACCESS_VIOLATION; 01344 } 01345 } 01346 01347 pobj = *(PBYTE*)(pobj + iNext); 01348 } 01349 01350 /* 01351 * Put an empty string on the end. 01352 */ 01353 try { 01354 *ccxpwchDest++ = 0; 01355 01356 ccxpNameList->cb = (UINT)((PBYTE)ccxpwchDest - (PBYTE)ccxpNameList); 01357 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 01358 return STATUS_ACCESS_VIOLATION; 01359 } 01360 01361 *pcbNeeded += (UINT)((PBYTE)ccxpwchDest - (PBYTE)ccxpNameList); 01362 01363 return Status; 01364 }

BOOL _CloseWindowStation HWINSTA  hwinsta  ) 
 

Definition at line 1055 of file winsta.c.

References _GetProcessWindowStation(), BOOL, FALSE, and NT_SUCCESS.

Referenced by NtUserCloseWindowStation(), and NtUserResolveDesktop().

01057 { 01058 HWINSTA hwinstaCurrent; 01059 01060 _GetProcessWindowStation(&hwinstaCurrent); 01061 if (hwinsta != hwinstaCurrent) { 01062 return NT_SUCCESS(ZwClose(hwinsta)); 01063 } 01064 return FALSE; 01065 }

PWINDOWSTATION _GetProcessWindowStation HWINSTA *  phwinsta  ) 
 

Definition at line 1240 of file winsta.c.

References tagPROCESSINFO::hwinsta, PpiCurrent, and tagPROCESSINFO::rpwinsta.

Referenced by _CloseWindowStation(), NtUserActivateKeyboardLayout(), NtUserGetImeInfoEx(), NtUserGetKeyboardLayoutList(), NtUserGetProcessWindowStation(), NtUserLoadKeyboardLayoutEx(), NtUserOpenInputDesktop(), NtUserSetImeInfoEx(), NtUserUnloadKeyboardLayout(), ResetSharedDesktops(), xxxDefWindowProc(), xxxDestroyThreadInfo(), xxxDW_SendDestroyMessages(), and xxxFreeWindow().

01242 { 01243 PPROCESSINFO ppi; 01244 01245 ppi = PpiCurrent(); 01246 UserAssert(ppi); 01247 01248 if (phwinsta) 01249 *phwinsta = ppi->hwinsta; 01250 return ppi->rpwinsta; 01251 }

BOOL _LockWorkStation VOID   ) 
 

Definition at line 1517 of file winsta.c.

References _PostMessage(), BOOL, gspwndLogonNotify, NULL, and TRUE.

Referenced by NtUserLockWorkStation().

01519 { 01520 UserAssert(gspwndLogonNotify != NULL); 01521 01522 _PostMessage(gspwndLogonNotify, 01523 WM_LOGONNOTIFY, LOGON_LOCKWORKSTATION, 0); 01524 01525 return TRUE; 01526 }

HWINSTA _OpenWindowStation POBJECT_ATTRIBUTES  pObjA,
DWORD  dwDesiredAccess,
KPROCESSOR_MODE  AccessMode
 

Definition at line 1019 of file winsta.c.

References ExWindowStationObjectType, NT_SUCCESS, NTSTATUS(), NULL, ObOpenObjectByName(), and Status.

Referenced by _UserTestForWinStaAccess(), NtUserOpenWindowStation(), xxxResolveDesktop(), and xxxResolveDesktopForWOW().

01023 { 01024 HWINSTA hwinsta; 01025 NTSTATUS Status; 01026 01027 /* 01028 * Obja is client-side. Ob interfaces protect and capture is 01029 * appropriate. 01030 */ 01031 Status = ObOpenObjectByName( 01032 pObjA, 01033 *ExWindowStationObjectType, 01034 AccessMode, 01035 NULL, 01036 dwDesiredAccess, 01037 NULL, 01038 &hwinsta); 01039 if (!NT_SUCCESS(Status)) { 01040 RIPNTERR0(Status, RIP_VERBOSE, ""); 01041 hwinsta = NULL; 01042 } 01043 return hwinsta; 01044 }

UINT _SetWindowStationUser PWINDOWSTATION  pwinsta,
PLUID  pluidUser,
PSID  ccxpsidUser,
DWORD  cbsidUser
 

Definition at line 1459 of file winsta.c.

References FALSE, GetCurrentProcessId, gpidLogon, tagWINDOWSTATION::luidUser, NULL, tagWINDOWSTATION::psidUser, TRUE, and UINT.

Referenced by NtUserSetWindowStationUser().

01464 { 01465 01466 /* 01467 * Make sure the caller is the logon process 01468 */ 01469 if (GetCurrentProcessId() != gpidLogon) { 01470 RIPERR0(ERROR_ACCESS_DENIED, 01471 RIP_WARNING, 01472 "Access denied in _SetWindowStationUser: caller must be in the logon process"); 01473 01474 return FALSE; 01475 } 01476 01477 if (pwinsta->psidUser != NULL) 01478 UserFreePool(pwinsta->psidUser); 01479 01480 if (ccxpsidUser != NULL) { 01481 pwinsta->psidUser = UserAllocPoolWithQuota(cbsidUser, TAG_SECURITY); 01482 if (pwinsta->psidUser == NULL) { 01483 RIPERR0(ERROR_OUTOFMEMORY, 01484 RIP_WARNING, 01485 "Memory allocation failed in _SetWindowStationUser"); 01486 01487 return FALSE; 01488 } 01489 try { 01490 RtlCopyMemory(pwinsta->psidUser, ccxpsidUser, cbsidUser); 01491 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 01492 01493 UserFreePool(pwinsta->psidUser); 01494 pwinsta->psidUser = NULL; 01495 return FALSE; 01496 } 01497 } else { 01498 pwinsta->psidUser = NULL; 01499 } 01500 01501 pwinsta->luidUser = *pluidUser; 01502 01503 return TRUE; 01504 }

NTSTATUS CreateGlobalAtomTable PVOID *  ppAtomTable  ) 
 

Definition at line 212 of file winsta.c.

References ARRAY_SIZE, lpszStdFormats, NT_SUCCESS, NTSTATUS(), RtlAddAtomToAtomTable(), RtlCreateAtomTable(), RtlDestroyAtomTable(), RtlPinAtomInAtomTable(), and Status.

Referenced by CreateW32Job(), and xxxCreateWindowStation().

00214 { 00215 NTSTATUS Status; 00216 RTL_ATOM Atom; 00217 ULONG i; 00218 00219 Status = RtlCreateAtomTable(0, ppAtomTable); 00220 00221 if (!NT_SUCCESS(Status)) { 00222 RIPMSG0(RIP_WARNING, "Global atom table not created"); 00223 return Status; 00224 } 00225 00226 for (i = 0; i < ARRAY_SIZE(lpszStdFormats); i++) { 00227 Status = RtlAddAtomToAtomTable(*ppAtomTable, 00228 (PWSTR)lpszStdFormats[i], 00229 &Atom); 00230 if (!NT_SUCCESS(Status)) { 00231 RIPMSG1(RIP_WARNING, "RtlAddAtomToAtomTable failed to add atom %ws", 00232 lpszStdFormats[i]); 00233 00234 RtlDestroyAtomTable(*ppAtomTable); 00235 return Status; 00236 } 00237 00238 RtlPinAtomInAtomTable(*ppAtomTable, Atom); 00239 } 00240 return Status; 00241 }

VOID DestroyWindowStation PEPROCESS  Process,
PVOID  pobj,
ACCESS_MASK  amGranted,
ULONG  cProcessHandles,
ULONG  cSystemHandles
 

Definition at line 830 of file winsta.c.

References tagDESKTOP::dwConsoleThreadId, ExWindowStationObjectType, grpdeskLogon, grpWinStaList, LockDesktop, NULL, OBJECT_TO_OBJECT_HEADER, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, tagWINDOWSTATION::rpwinstaNext, TerminateConsole(), UnlockDesktop, UnlockWinSta, and VOID().

00836 { 00837 PWINDOWSTATION pwinsta = pobj; 00838 PWINDOWSTATION *ppwinsta; 00839 PDESKTOP pdesk; 00840 PDESKTOP pdeskLock = NULL; 00841 00842 UserAssert(OBJECT_TO_OBJECT_HEADER(pobj)->Type == *ExWindowStationObjectType); 00843 00844 /* 00845 * If this is not the last handle, leave 00846 */ 00847 if (cSystemHandles != 1) 00848 return; 00849 00850 BEGIN_REENTERCRIT(); 00851 00852 /* 00853 * If the window station was linked into the terminal's list, 00854 * go ahead and unlink it. 00855 */ 00856 for (ppwinsta = &grpWinStaList; 00857 *ppwinsta != NULL && pwinsta != *ppwinsta; 00858 ppwinsta = &(*ppwinsta)->rpwinstaNext) 00859 ; 00860 if (*ppwinsta != NULL) { 00861 UnlockWinSta(ppwinsta); 00862 /* 00863 * Assert that unlocking it didn't destroy it. 00864 */ 00865 UserAssert(OBJECT_TO_OBJECT_HEADER(pobj)->Type == *ExWindowStationObjectType); 00866 00867 *ppwinsta = pwinsta->rpwinstaNext; 00868 /* 00869 * The instruction above transfered rpwinstaNext lock ownership to the previous 00870 * element in the list. Hence the value in pwinsta can no longer be considered valid. 00871 */ 00872 pwinsta->rpwinstaNext = NULL; 00873 } 00874 00875 /* 00876 * Notify all console threads and wait for them to 00877 * terminate. 00878 */ 00879 pdesk = pwinsta->rpdeskList; 00880 while (pdesk != NULL) { 00881 if (pdesk != grpdeskLogon && pdesk->dwConsoleThreadId) { 00882 LockDesktop(&pdeskLock, pdesk, LDL_FN_DESTROYWINDOWSTATION, 0); 00883 TerminateConsole(pdesk); 00884 00885 /* 00886 * Restart scan in case desktop list has changed 00887 */ 00888 pdesk = pwinsta->rpdeskList; 00889 UnlockDesktop(&pdeskLock, LDU_FN_DESTROYWINDOWSTATION, 0); 00890 } else 00891 pdesk = pdesk->rpdeskNext; 00892 } 00893 00894 END_REENTERCRIT(); 00895 00896 UNREFERENCED_PARAMETER(Process); 00897 UNREFERENCED_PARAMETER(cProcessHandles); 00898 UNREFERENCED_PARAMETER(amGranted); 00899 }

VOID FreeWindowStation PWINDOWSTATION  pwinsta  ) 
 

Definition at line 745 of file winsta.c.

References tagKL::dwKL_Flags, tagWINDOWSTATION::dwWSF_Flags, EVENT_INCREMENT, ExWindowStationObjectType, FALSE, ForceEmptyClipboard(), gpEventSwitchDesktop, gspwndLogonNotify, HH_KBDLYOUTFREEWINSTA, HMMarkObjectDestroy(), HYDRA_HINT, KeSetEvent(), KL_UNLOADED, Lock, NULL, ObDereferenceObject, OBJECT_TO_OBJECT_HEADER, tagWINDOWSTATION::pGlobalAtomTable, tagKL::pklNext, tagWINDOWSTATION::psidUser, tagWINDOWSTATION::rpdeskList, RtlDestroyAtomTable(), tagWINDOWSTATION::spklList, Unlock, VOID(), WSF_DYING, and WSF_NOIO.

00747 { 00748 UserAssert(OBJECT_TO_OBJECT_HEADER(pwinsta)->Type == *ExWindowStationObjectType); 00749 00750 /* 00751 * Mark the windowstation as dying. Make sure we're not recursing. 00752 */ 00753 UserAssert(!(pwinsta->dwWSF_Flags & WSF_DYING)); 00754 pwinsta->dwWSF_Flags |= WSF_DYING; 00755 00756 UserAssert(pwinsta->rpdeskList == NULL); 00757 00758 /* 00759 * Free up the other resources 00760 */ 00761 00762 if (!(pwinsta->dwWSF_Flags & WSF_NOIO) && (gpEventSwitchDesktop != NULL)) { 00763 KeSetEvent(gpEventSwitchDesktop, EVENT_INCREMENT, FALSE); 00764 ObDereferenceObject(gpEventSwitchDesktop); 00765 gpEventSwitchDesktop = NULL; 00766 } 00767 00768 BEGIN_REENTERCRIT(); 00769 00770 RtlDestroyAtomTable(pwinsta->pGlobalAtomTable); 00771 00772 ForceEmptyClipboard(pwinsta); 00773 00774 /* 00775 * Free up keyboard layouts 00776 */ 00777 if (!(pwinsta->dwWSF_Flags & WSF_NOIO) && pwinsta->spklList != NULL) { 00778 00779 PKL pkl = pwinsta->spklList; 00780 PKL pklFirst = pkl; 00781 00782 RIPMSG2(RIP_WARNING, "FreeWindowStation: pwinsta(%p)->spklList is not NULL, %p", pwinsta, pwinsta->spklList); 00783 00784 do { 00785 PKL pklNext = pkl->pklNext; 00786 00787 HMMarkObjectDestroy(pkl); 00788 pkl->dwKL_Flags |= KL_UNLOADED; 00789 00790 Lock(&pwinsta->spklList, pklNext); 00791 00792 pkl = pklNext; 00793 00794 } while (pkl != pkl->pklNext && pkl != pklFirst); 00795 00796 Unlock(&pwinsta->spklList); 00797 00798 HYDRA_HINT(HH_KBDLYOUTFREEWINSTA); 00799 00800 /* 00801 * make sure the logon notify window went away 00802 */ 00803 UserAssert(gspwndLogonNotify == NULL); 00804 } else { 00805 UserAssert(pwinsta->spklList == NULL); 00806 } 00807 00808 /* 00809 * Free the USER sid 00810 */ 00811 if (pwinsta->psidUser != NULL) { 00812 UserFreePool(pwinsta->psidUser); 00813 pwinsta->psidUser = NULL; 00814 } 00815 00816 END_REENTERCRIT(); 00817 }

BOOLEAN OkayToCloseWindowStation PEPROCESS Process  OPTIONAL,
PVOID  Object,
HANDLE  Handle
 

Definition at line 981 of file winsta.c.

References CheckHandleFlag(), CheckHandleInUse(), ExWindowStationObjectType, FALSE, Handle, HF_PROTECTED, KernelMode, OBJECT_TO_OBJECT_HEADER, and TRUE.

00985 { 00986 PWINDOWSTATION pwinsta = (PWINDOWSTATION)Object; 00987 00988 UNREFERENCED_PARAMETER(Process); 00989 00990 UserAssert(OBJECT_TO_OBJECT_HEADER(Object)->Type == *ExWindowStationObjectType); 00991 00992 /* 00993 * Kernel mode code can close anything. 00994 */ 00995 if (KeGetPreviousMode() == KernelMode) { 00996 return TRUE; 00997 } 00998 00999 /* 01000 * We can't close a windowstation that's being used. 01001 */ 01002 if (CheckHandleInUse(Handle) || CheckHandleFlag(Handle, HF_PROTECTED)) { 01003 RIPMSG1(RIP_WARNING, "Trying to close windowstation %#p while still in use", pwinsta); 01004 return FALSE; 01005 } 01006 01007 return TRUE; 01008 }

NTSTATUS ParseWindowStation PVOID  pContainerObject,
POBJECT_TYPE  pObjectType,
PACCESS_STATE  pAccessState,
KPROCESSOR_MODE  AccessMode,
ULONG  Attributes,
PUNICODE_STRING  pstrCompleteName,
PUNICODE_STRING  pstrRemainingName,
PVOID Context  OPTIONAL,
PSECURITY_QUALITY_OF_SERVICE  pqos,
PVOID *  pObject
 

Definition at line 911 of file winsta.c.

References ExDesktopObjectType, ExWindowStationObjectType, L, NTSTATUS(), NULL, OBJECT_TO_OBJECT_HEADER, ObReferenceObject, and ParseDesktop().

00922 { 00923 PWINDOWSTATION pwinsta = pContainerObject; 00924 00925 UserAssert(OBJECT_TO_OBJECT_HEADER(pContainerObject)->Type == *ExWindowStationObjectType); 00926 00927 /* 00928 * If nothing remains to be parsed, return the windowstation. 00929 */ 00930 *pObject = NULL; 00931 if (pstrRemainingName->Length == 0) { 00932 if (pObjectType != *ExWindowStationObjectType) 00933 return STATUS_OBJECT_TYPE_MISMATCH; 00934 00935 ObReferenceObject(pwinsta); 00936 *pObject = pwinsta; 00937 return STATUS_SUCCESS; 00938 } 00939 00940 /* 00941 * Skip leading path separator, if present. 00942 */ 00943 if (*(pstrRemainingName->Buffer) == OBJ_NAME_PATH_SEPARATOR) { 00944 pstrRemainingName->Buffer++; 00945 pstrRemainingName->Length -= sizeof(WCHAR); 00946 pstrRemainingName->MaximumLength -= sizeof(WCHAR); 00947 } 00948 00949 /* 00950 * Validate the desktop name. 00951 */ 00952 if (wcschr(pstrRemainingName->Buffer, L'\\')) 00953 return STATUS_OBJECT_PATH_INVALID; 00954 if (pObjectType == *ExDesktopObjectType) { 00955 return ParseDesktop( 00956 pContainerObject, 00957 pObjectType, 00958 pAccessState, 00959 AccessMode, 00960 Attributes, 00961 pstrCompleteName, 00962 pstrRemainingName, 00963 Context, 00964 pqos, 00965 pObject); 00966 } 00967 00968 return STATUS_OBJECT_TYPE_MISMATCH; 00969 }

NTSTATUS ReferenceWindowStation PETHREAD  Thread,
HWINSTA  hwinsta,
ACCESS_MASK  amDesiredAccess,
PWINDOWSTATION ppwinsta,
BOOL  fUseDesktop
 

Definition at line 1366 of file winsta.c.

References AccessCheckObject(), tagPROCESSINFO::amwinsta, ExWindowStationObjectType, KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PpiFromProcess, PtiFromThread, RETURN_IF_ACCESS_DENIED, tagTHREADINFO::rpdesk, tagPROCESSINFO::rpwinsta, tagDESKTOP::rpwinstaParent, Status, _ETHREAD::ThreadsProcess, and WinStaMapping.

Referenced by CheckClipboardAccess(), UserGlobalAtomTableCallout(), and xxxSnapWindow().

01372 { 01373 PPROCESSINFO ppi; 01374 PTHREADINFO pti; 01375 PWINDOWSTATION pwinsta = NULL; 01376 NTSTATUS Status; 01377 01378 /* 01379 * We prefer to use the thread's desktop to dictate which 01380 * windowstation/Atom table to use rather than the process. 01381 * This allows NetDDE, which has threads running under 01382 * different desktops on different windowstations but whos 01383 * process is set to only one of these windowstations, to 01384 * get global atoms properly without having to change its 01385 * process windowstation a billion times and synchronize. 01386 */ 01387 ppi = PpiFromProcess(Thread->ThreadsProcess); 01388 pti = PtiFromThread(Thread); 01389 01390 /* 01391 * First, try to get the windowstation from the pti, and then 01392 * from the ppi. 01393 */ 01394 if (ppi != NULL) { 01395 if (!fUseDesktop || pti == NULL || pti->rpdesk == NULL || 01396 ppi->rpwinsta == pti->rpdesk->rpwinstaParent) { 01397 01398 /* 01399 * Use the windowstation assigned to the process. 01400 */ 01401 pwinsta = ppi->rpwinsta; 01402 if (pwinsta != NULL) { 01403 RETURN_IF_ACCESS_DENIED(ppi->amwinsta, amDesiredAccess, 01404 STATUS_ACCESS_DENIED); 01405 } 01406 } 01407 01408 /* 01409 * If we aren't using the process' windowstation, try to 01410 * go through the thread's desktop. 01411 */ 01412 if (pwinsta == NULL && pti != NULL && pti->rpdesk != NULL) { 01413 01414 /* 01415 * Perform access check the parent windowstation. This 01416 * is an expensive operation. 01417 */ 01418 pwinsta = pti->rpdesk->rpwinstaParent; 01419 if (!AccessCheckObject(pwinsta, amDesiredAccess, KernelMode, &WinStaMapping)) 01420 return STATUS_ACCESS_DENIED; 01421 } 01422 } 01423 01424 /* 01425 * If we still don't have a windowstation and a handle was 01426 * passed in, use it. 01427 */ 01428 if (pwinsta == NULL) { 01429 if (hwinsta != NULL) { 01430 Status = ObReferenceObjectByHandle( 01431 hwinsta, 01432 amDesiredAccess, 01433 *ExWindowStationObjectType, 01434 KernelMode, 01435 &pwinsta, 01436 NULL); 01437 if (!NT_SUCCESS(Status)) 01438 return Status; 01439 ObDereferenceObject(pwinsta); 01440 } else { 01441 return STATUS_NOT_FOUND; 01442 } 01443 } 01444 01445 *ppwinsta = pwinsta; 01446 01447 return STATUS_SUCCESS; 01448 }

HWINSTA xxxCreateWindowStation POBJECT_ATTRIBUTES  ObjectAttributes,
KPROCESSOR_MODE  OwnershipMode,
DWORD  dwDesiredAccess,
HANDLE  hKbdLayoutFile,
DWORD  offTable,
PCWSTR  pwszKLID,
UINT  uKbdInputLocale
 

Definition at line 243 of file winsta.c.

References BEGINATOMICCHECK, _HANDLEENTRY::bFlags, CreateGlobalAtomTable(), CreateSecurityDescriptor(), DeferWinEventNotify, DESKTOPCLASS, DWORD, tagWINDOWSTATION::dwSessionId, tagTERMINAL::dwTERMF_Flags, tagWINDOWSTATION::dwWSF_Flags, ENDATOMICCHECK, ExEventObjectType, EXITATOMICCHECK, ExWindowStationObjectType, FALSE, gbRemoteSession, ghEventSwitchDesktop, gpepCSRSS, gpEventSwitchDesktop, gpidLogon, grpWinStaList, gSessionId, gTermIO, gTermNOIO, HANDLEF_POOL, tagTHREADINFO::hdesk, HMChangeOwnerThread(), hModuleWin, HMPheFromObject, IsWinEventNotifyDeferredOK, KeAttachProcess(), KeDetachProcess(), KernelMode, L, Lock, LockWinSta, LogDesktop, MAX_SESSION_PATH, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, ObInsertObject(), OBJECT_HEADER_TO_NAME_INFO, OBJECT_TO_OBJECT_HEADER, ObjectAttributes, ObOpenObjectByPointer(), ObReferenceObject, ObReferenceObjectByHandle(), ObSetSecurityDescriptorInfo(), PagedPool, _EPROCESS::Pcb, tagWINDOWSTATION::pGlobalAtomTable, tagTHREADINFO::ppi, PsGetCurrentProcess, tagWINDOWSTATION::pTerm, PtiCurrent, tagTERMINAL::ptiDesktop, tagTHREADINFO::rpdesk, tagWINDOWSTATION::rpwinstaNext, RtlCopySid(), RtlInitUnicodeString(), RtlLengthSid(), SeAssignSecurity(), SeCaptureSubjectContext(), SeDeassignSecurity(), SeExports, SeLockSubjectContext(), SeReleaseSubjectContext(), SetVisible(), SeUnlockSubjectContext(), _SE_EXPORTS::SeWorldSid, tagTERMINAL::spwndDesktopOwner, Status, SV_SET, TERMF_INITIALIZED, TERMF_NOIO, TIF_DISABLEHOOKS, tagTHREADINFO::TIF_flags, TRUE, USHORT, VER31, WINDOWSTATION, WinStaMapping, WSF_NOIO, xxxCreateWindowEx(), xxxInitTerminal(), xxxInitWindowStation(), xxxLoadKeyboardLayoutEx(), zzzEndDeferWinEventNotify, and zzzSetDesktop().

Referenced by NtUserCreateWindowStation(), and xxxConnectService().

00251 { 00252 PWINDOWSTATION pwinsta; 00253 PTHREADINFO ptiCurrent; 00254 PDESKTOP pdeskTemp; 00255 HDESK hdeskTemp; 00256 PSECURITY_DESCRIPTOR psd; 00257 PSECURITY_DESCRIPTOR psdCapture; 00258 PPROCESSINFO ppiSave; 00259 NTSTATUS Status; 00260 PACCESS_ALLOWED_ACE paceList = NULL, pace; 00261 ULONG ulLength, ulLengthSid; 00262 HANDLE hEvent; 00263 HWINSTA hwinsta; 00264 DWORD dwDisableHooks; 00265 PTERMINAL pTerm = NULL; 00266 PWND pwnd; 00267 WCHAR szBaseNamedObjectDirectory[MAX_SESSION_PATH]; 00268 00269 UserAssert(IsWinEventNotifyDeferredOK()); 00270 00271 /* 00272 * Get the pointer to the security descriptor so we can 00273 * assign it to the new object later. 00274 */ 00275 psdCapture = ObjectAttributes->SecurityDescriptor; 00276 00277 /* 00278 * The first windowstation that gets created is Winsta0 and 00279 * it's the only interactive one. 00280 */ 00281 if (grpWinStaList == NULL) { 00282 00283 /* 00284 * Assert that winlogon is the first to call CreateWindowStation 00285 */ 00286 UserAssert(PsGetCurrentProcess()->UniqueProcessId == gpidLogon); 00287 00288 pTerm = &gTermIO; 00289 } else { 00290 pTerm = &gTermNOIO; 00291 00292 UserAssert(grpWinStaList->rpwinstaNext == NULL || 00293 pTerm->dwTERMF_Flags & TERMF_NOIO); 00294 00295 pTerm->dwTERMF_Flags |= TERMF_NOIO; 00296 } 00297 00298 /* 00299 * Create the WindowStation object 00300 */ 00301 Status = ObCreateObject(KernelMode, *ExWindowStationObjectType, 00302 ObjectAttributes, OwnershipMode, NULL, sizeof(WINDOWSTATION), 00303 0, 0, &pwinsta); 00304 00305 if (!NT_SUCCESS(Status)) { 00306 RIPNTERR0(Status, RIP_WARNING, "Failed to create windowstation"); 00307 return NULL; 00308 } 00309 00310 /* 00311 * Initialize everything 00312 */ 00313 RtlZeroMemory(pwinsta, sizeof(WINDOWSTATION)); 00314 00315 /* 00316 * Store the session id of the session who created the windowstation 00317 */ 00318 pwinsta->dwSessionId = gSessionId; 00319 00320 pwinsta->pTerm = pTerm; 00321 00322 /* 00323 * All the windowstations in the system terminal are non-interactive. 00324 */ 00325 if (pTerm->dwTERMF_Flags & TERMF_NOIO) { 00326 pwinsta->dwWSF_Flags = WSF_NOIO; 00327 } 00328 00329 /* 00330 * Create the global atom table and populate it with the default OLE atoms 00331 * Pin each atom so they can't be deleted by bogus applications like Winword 00332 */ 00333 Status = CreateGlobalAtomTable(&pwinsta->pGlobalAtomTable); 00334 00335 if (pwinsta->pGlobalAtomTable == NULL) { 00336 UserAssert(!NT_SUCCESS(Status)); 00337 RIPNTERR0(Status, RIP_WARNING, "CreateGlobalAtomTable failed"); 00338 goto create_error; 00339 } 00340 00341 /* 00342 * create the desktop thread 00343 * and the RIT (only for the IO terminal) 00344 */ 00345 if (!(pTerm->dwTERMF_Flags & TERMF_INITIALIZED)) { 00346 00347 Status = xxxInitTerminal(pTerm); 00348 00349 if (!NT_SUCCESS(Status)) { 00350 RIPNTERR0(Status, RIP_WARNING, "xxxInitTerminal failed"); 00351 goto create_error; 00352 } 00353 } 00354 00355 if (!(pwinsta->dwWSF_Flags & WSF_NOIO)) { 00356 if (!xxxInitWindowStation(pwinsta)) { 00357 RIPNTERR0(STATUS_NO_MEMORY, RIP_WARNING, "xxxInitWindowStation failed"); 00358 goto create_error; 00359 } 00360 } 00361 00362 /* 00363 * Create only one desktop owner window per terminal. 00364 */ 00365 if (pTerm->spwndDesktopOwner == NULL) { 00366 00367 /* 00368 * Switch ppi values so window will be created using the 00369 * system's desktop window class. 00370 */ 00371 ptiCurrent = PtiCurrent(); 00372 ppiSave = ptiCurrent->ppi; 00373 ptiCurrent->ppi = pTerm->ptiDesktop->ppi; 00374 00375 UserAssert(pTerm->ptiDesktop->ppi->W32PF_Flags & W32PF_CLASSESREGISTERED); 00376 00377 pdeskTemp = ptiCurrent->rpdesk; /* save current desktop */ 00378 hdeskTemp = ptiCurrent->hdesk; 00379 if (pdeskTemp) { 00380 ObReferenceObject(pdeskTemp); 00381 LogDesktop(pdeskTemp, LD_REF_FN_CREATEWINDOWSTATION, TRUE, (ULONG_PTR)PtiCurrent()); 00382 } 00383 00384 /* 00385 * The following code is not supposed to leave the critical section because 00386 * CreateWindowStation is an API so the current thread can be on any state 00387 * setting its pdesk to NULL it's kind of bogus 00388 */ 00389 DeferWinEventNotify(); 00390 BEGINATOMICCHECK(); 00391 zzzSetDesktop(ptiCurrent, NULL, NULL); 00392 00393 00394 /* 00395 * HACK HACK HACK!!! (adams) In order to create the desktop window 00396 * with the correct desktop, we set the desktop of the current thread 00397 * to the new desktop. But in so doing we allow hooks on the current 00398 * thread to also hook this new desktop. This is bad, because we don't 00399 * want the desktop window to be hooked while it is created. So we 00400 * temporarily disable hooks of the current thread and desktop, and 00401 * reenable them after switching back to the original desktop. 00402 */ 00403 00404 dwDisableHooks = ptiCurrent->TIF_flags & TIF_DISABLEHOOKS; 00405 ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS; 00406 00407 /* 00408 * Create the desktop owner window 00409 * 00410 * CONSIDER (adams): Do we want to limit the desktop size so that the 00411 * width and height of a rect will fit in 16bit coordinates? 00412 * 00413 * SHRT_MIN / 2, SHRT_MIN / 2, SHRT_MAX, SHRT_MAX, 00414 * 00415 * Or do we want to limit it so just any point has 16bit coordinates? 00416 * 00417 * -SHRT_MIN, -SHRT_MIN, SHRT_MAX * 2, SHRT_MAX * 2 00418 */ 00419 00420 pwnd = xxxCreateWindowEx( 00421 (DWORD)0, 00422 (PLARGE_STRING)DESKTOPCLASS, 00423 NULL, 00424 (WS_POPUP | WS_CLIPCHILDREN), 00425 SHRT_MIN / 2, 00426 SHRT_MIN / 2, 00427 SHRT_MAX, 00428 SHRT_MAX, 00429 NULL, 00430 NULL, 00431 hModuleWin, 00432 (LPWSTR)NULL, 00433 VER31 00434 ); 00435 00436 if (pwnd == NULL) { 00437 RIPMSG0(RIP_WARNING, "xxxCreateWindowStation: Failed to create mother desktop window"); 00438 Status = STATUS_NO_MEMORY; 00439 EXITATOMICCHECK(); 00440 zzzEndDeferWinEventNotify(); 00441 /* 00442 * Restore caller's ppi 00443 */ 00444 ptiCurrent->ppi = ppiSave; 00445 00446 /* 00447 * Restore the previous desktop 00448 */ 00449 zzzSetDesktop(ptiCurrent, pdeskTemp, hdeskTemp); 00450 00451 goto create_error; 00452 } 00453 00454 /* 00455 * Mark this handle entry that is allocated out of pool 00456 */ 00457 { 00458 PHE phe; 00459 00460 UserAssert(ptiCurrent->rpdesk == NULL); 00461 00462 phe = HMPheFromObject(pwnd); 00463 phe->bFlags |= HANDLEF_POOL; 00464 } 00465 00466 Lock(&(pTerm->spwndDesktopOwner), pwnd); 00467 00468 UserAssert(ptiCurrent->TIF_flags & TIF_DISABLEHOOKS); 00469 ptiCurrent->TIF_flags = (ptiCurrent->TIF_flags & ~TIF_DISABLEHOOKS) | dwDisableHooks; 00470 00471 SetVisible(pTerm->spwndDesktopOwner, SV_SET); 00472 HMChangeOwnerThread(pTerm->spwndDesktopOwner, pTerm->ptiDesktop); 00473 00474 /* 00475 * Restore caller's ppi 00476 */ 00477 ptiCurrent->ppi = ppiSave; 00478 00479 /* 00480 * Restore the previous desktop 00481 */ 00482 zzzSetDesktop(ptiCurrent, pdeskTemp, hdeskTemp); 00483 00484 ENDATOMICCHECK(); 00485 zzzEndDeferWinEventNotify(); 00486 00487 if (pdeskTemp) { 00488 LogDesktop(pdeskTemp, LD_DEREF_FN_CREATEWINDOWSTATION, FALSE, (ULONG_PTR)PtiCurrent()); 00489 ObDereferenceObject(pdeskTemp); 00490 } 00491 } 00492 00493 /* 00494 * If this is the visible windowstation, assign it to 00495 * the server and create the desktop switch notification 00496 * event. 00497 */ 00498 if (!(pwinsta->dwWSF_Flags & WSF_NOIO)) { 00499 UNICODE_STRING strName; 00500 HANDLE hRootDir; 00501 OBJECT_ATTRIBUTES obja; 00502 00503 /* 00504 * Create desktop switch notification event. 00505 */ 00506 ulLengthSid = RtlLengthSid(SeExports->SeWorldSid); 00507 ulLength = ulLengthSid + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); 00508 00509 /* 00510 * Allocate the ACE list 00511 */ 00512 paceList = (PACCESS_ALLOWED_ACE)UserAllocPoolWithQuota(ulLength, TAG_SECURITY); 00513 00514 if (paceList == NULL) { 00515 Status = STATUS_NO_MEMORY; 00516 goto create_error; 00517 } 00518 00519 /* 00520 * Initialize ACE 0 00521 */ 00522 pace = paceList; 00523 pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; 00524 pace->Header.AceSize = (USHORT)ulLength; 00525 pace->Header.AceFlags = 0; 00526 pace->Mask = SYNCHRONIZE; 00527 RtlCopySid(ulLengthSid, &pace->SidStart, SeExports->SeWorldSid); 00528 00529 /* 00530 * Create the SD 00531 */ 00532 psd = CreateSecurityDescriptor(paceList, ulLength, FALSE); 00533 00534 UserFreePool(paceList); 00535 00536 if (psd == NULL) { 00537 Status = STATUS_NO_MEMORY; 00538 goto create_error; 00539 } 00540 00541 /* 00542 * Create the named event. 00543 */ 00544 UserAssert(ghEventSwitchDesktop == NULL); 00545 00546 if (gbRemoteSession) { 00547 swprintf(szBaseNamedObjectDirectory, L"\\Sessions\\%ld\\BaseNamedObjects", 00548 gSessionId); 00549 RtlInitUnicodeString(&strName, szBaseNamedObjectDirectory); 00550 } else { 00551 RtlInitUnicodeString(&strName, L"\\BaseNamedObjects"); 00552 } 00553 00554 InitializeObjectAttributes( &obja, 00555 &strName, 00556 OBJ_CASE_INSENSITIVE, 00557 NULL, 00558 NULL 00559 ); 00560 Status = ZwOpenDirectoryObject( &hRootDir, 00561 DIRECTORY_ALL_ACCESS & 00562 ~(DELETE | WRITE_DAC | WRITE_OWNER), 00563 &obja 00564 ); 00565 if (NT_SUCCESS(Status)) { 00566 RtlInitUnicodeString(&strName, L"WinSta0_DesktopSwitch"); 00567 InitializeObjectAttributes(&obja, &strName, OBJ_OPENIF, hRootDir, psd); 00568 Status = ZwCreateEvent(&hEvent, EVENT_ALL_ACCESS, &obja, 00569 NotificationEvent, FALSE); 00570 ZwClose(hRootDir); 00571 00572 if (NT_SUCCESS(Status)) { 00573 Status = ObReferenceObjectByHandle(hEvent, EVENT_ALL_ACCESS, *ExEventObjectType, 00574 KernelMode, &gpEventSwitchDesktop, NULL); 00575 if (NT_SUCCESS(Status)) { 00576 00577 /* 00578 * Attach to the system process and create a handle to the 00579 * object. This will ensure that the object name is retained 00580 * when hEvent is closed. This is simpler than creating a 00581 * permanent object, which takes the 00582 * SeCreatePermanentPrivilege. 00583 */ 00584 KeAttachProcess(&gpepCSRSS->Pcb); 00585 00586 Status = ObOpenObjectByPointer( 00587 gpEventSwitchDesktop, 00588 0, 00589 NULL, 00590 EVENT_ALL_ACCESS, 00591 NULL, 00592 KernelMode, 00593 &ghEventSwitchDesktop); 00594 KeDetachProcess(); 00595 } 00596 ZwClose(hEvent); 00597 } 00598 } 00599 if (!NT_SUCCESS(Status)) 00600 goto create_error; 00601 00602 UserFreePool(psd); 00603 } 00604 00605 /* 00606 * Create a handle to the windowstation 00607 */ 00608 Status = ObInsertObject(pwinsta, NULL, dwDesiredAccess, 1, 00609 &pwinsta, &hwinsta); 00610 00611 if (Status == STATUS_OBJECT_NAME_EXISTS) { 00612 00613 /* 00614 * The windowstation already exists, so deref and leave. 00615 */ 00616 ObDereferenceObject(pwinsta); 00617 00618 } else if (NT_SUCCESS(Status)) { 00619 PSECURITY_DESCRIPTOR psdParent, psdNew; 00620 SECURITY_SUBJECT_CONTEXT Context; 00621 POBJECT_DIRECTORY pParentDirectory; 00622 SECURITY_INFORMATION siNew; 00623 00624 /* 00625 * Create security descriptor for the windowstation. 00626 * ObInsertObject only supports non-container 00627 * objects, so we must assign our own security descriptor. 00628 */ 00629 SeCaptureSubjectContext(&Context); 00630 SeLockSubjectContext(&Context); 00631 00632 pParentDirectory = OBJECT_HEADER_TO_NAME_INFO( 00633 OBJECT_TO_OBJECT_HEADER(pwinsta))->Directory; 00634 if (pParentDirectory != NULL) 00635 psdParent = OBJECT_TO_OBJECT_HEADER(pParentDirectory)->SecurityDescriptor; 00636 else 00637 psdParent = NULL; 00638 00639 Status = SeAssignSecurity( 00640 psdParent, 00641 psdCapture, 00642 &psdNew, 00643 TRUE, 00644 &Context, 00645 (PGENERIC_MAPPING)&WinStaMapping, 00646 PagedPool); 00647 00648 SeUnlockSubjectContext(&Context); 00649 SeReleaseSubjectContext(&Context); 00650 00651 if (!NT_SUCCESS(Status)) { 00652 #if DBG 00653 if (Status == STATUS_ACCESS_DENIED) { 00654 RIPNTERR0(Status, RIP_WARNING, "Access denied during object creation"); 00655 } else { 00656 RIPNTERR1(Status, RIP_ERROR, 00657 "Can't create security descriptor! Status = %#lx", 00658 Status); 00659 } 00660 #endif 00661 } else { 00662 00663 /* 00664 * Call the security method to copy the security descriptor 00665 */ 00666 siNew = (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | 00667 DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION); 00668 Status = ObSetSecurityDescriptorInfo( 00669 pwinsta, 00670 &siNew, 00671 psdNew, 00672 &OBJECT_TO_OBJECT_HEADER(pwinsta)->SecurityDescriptor, 00673 PagedPool, 00674 (PGENERIC_MAPPING)&WinStaMapping); 00675 SeDeassignSecurity(&psdNew); 00676 00677 if (NT_SUCCESS(Status)) { 00678 00679 PWINDOWSTATION* ppwinsta; 00680 00681 /* 00682 * Put it on the tail of the global windowstation list 00683 */ 00684 ppwinsta = &grpWinStaList; 00685 while (*ppwinsta != NULL) 00686 ppwinsta = &(*ppwinsta)->rpwinstaNext; 00687 LockWinSta(ppwinsta, pwinsta); 00688 00689 /* 00690 * For interactive window stations load the keyboard 00691 * layout. !!! 00692 */ 00693 if (!(pwinsta->dwWSF_Flags & WSF_NOIO) && pwszKLID != NULL) { 00694 if (xxxLoadKeyboardLayoutEx( 00695 pwinsta, 00696 hKbdLayoutFile, 00697 (HKL)NULL, 00698 offTable, 00699 pwszKLID, 00700 uKbdInputLocale, 00701 KLF_ACTIVATE | KLF_INITTIME) == NULL) { 00702 Status = STATUS_UNSUCCESSFUL; 00703 } 00704 } 00705 } 00706 } 00707 ObDereferenceObject(pwinsta); 00708 } 00709 00710 if (!NT_SUCCESS(Status)) { 00711 RIPNTERR1(Status, 00712 RIP_WARNING, 00713 "CreateWindowStation: Failed with Status 0x%x", 00714 Status); 00715 return NULL; 00716 } 00717 00718 return hwinsta; 00719 00720 /* 00721 * Goto here if an error occurs so things can be cleaned up 00722 */ 00723 create_error: 00724 00725 RIPNTERR1(Status, 00726 RIP_WARNING, 00727 "CreateWindowStation: Failed with Status 0x%x", 00728 Status); 00729 00730 ObDereferenceObject(pwinsta); 00731 00732 return NULL; 00733 }

NTSTATUS xxxInitTerminal PTERMINAL  pTerm  ) 
 

Definition at line 26 of file winsta.c.

References CheckCritIn, CreateSystemThread(), CreateTerminalInput(), tagTERMINAL::dwTERMF_Flags, EnterCrit, ExEventObjectType, FALSE, KernelMode, KeWaitForSingleObject(), LeaveCrit, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, ObReferenceObjectByHandle(), tagTERMINAL::pEventInputReady, tagTERMINAL::pEventTermInit, PKSTART_ROUTINE, Status, TERMF_DTINITFAILED, TERMF_INITIALIZED, TERMF_NOIO, WrUserRequest, and xxxDesktopThread().

Referenced by xxxCreateWindowStation().

00028 { 00029 NTSTATUS Status; 00030 PKEVENT pEventTermInit; 00031 HANDLE hEventInputReady, hEventTermInit; 00032 HANDLE hThreadDesktop; 00033 00034 CheckCritIn(); 00035 00036 UserAssert(!(pTerm->dwTERMF_Flags & TERMF_INITIALIZED)); 00037 00038 if (pTerm->pEventInputReady != NULL) { 00039 00040 /* 00041 * if we make it here it means that another thread is 00042 * executing xxxInitTerminal for the same terminal and it 00043 * left the critical section. 00044 */ 00045 UserAssert(pTerm->pEventTermInit != NULL); 00046 00047 /* 00048 * use a local variable so we can safely reset 00049 * pTerm->pEventTermInit when we're done with it 00050 */ 00051 pEventTermInit = pTerm->pEventTermInit; 00052 00053 ObReferenceObject(pEventTermInit); 00054 00055 LeaveCrit(); 00056 00057 goto Wait; 00058 } 00059 00060 /* 00061 * Create the input ready event. RIT and desktop thread will wait for it. 00062 * It will be set when the first desktop in this terminal will be created. 00063 */ 00064 Status = ZwCreateEvent( 00065 &hEventInputReady, 00066 EVENT_ALL_ACCESS, 00067 NULL, 00068 NotificationEvent, 00069 FALSE); 00070 00071 if (!NT_SUCCESS(Status)) 00072 return Status; 00073 00074 Status = ObReferenceObjectByHandle( 00075 hEventInputReady, 00076 EVENT_ALL_ACCESS, 00077 *ExEventObjectType, 00078 KernelMode, 00079 &pTerm->pEventInputReady, NULL); 00080 00081 ZwClose(hEventInputReady); 00082 00083 if (!NT_SUCCESS(Status)) 00084 return Status; 00085 00086 /* 00087 * Device and RIT initialization. Don't do it for 00088 * the system terminal. 00089 */ 00090 if (!(pTerm->dwTERMF_Flags & TERMF_NOIO)) { 00091 if (!CreateTerminalInput(pTerm)) { 00092 ObDereferenceObject(pTerm->pEventInputReady); 00093 return STATUS_NO_MEMORY; 00094 } 00095 } 00096 00097 /* 00098 * create an event to syncronize the terminal initialization 00099 */ 00100 Status = ZwCreateEvent( 00101 &hEventTermInit, 00102 EVENT_ALL_ACCESS, 00103 NULL, 00104 NotificationEvent, 00105 FALSE); 00106 00107 if (!NT_SUCCESS(Status)) { 00108 ObDereferenceObject(pTerm->pEventInputReady); 00109 return Status; 00110 } 00111 00112 Status = ObReferenceObjectByHandle( 00113 hEventTermInit, 00114 EVENT_ALL_ACCESS, 00115 *ExEventObjectType, 00116 KernelMode, 00117 &pTerm->pEventTermInit, NULL); 00118 00119 ZwClose(hEventTermInit); 00120 00121 if (!NT_SUCCESS(Status)) { 00122 ObDereferenceObject(pTerm->pEventInputReady); 00123 return Status; 00124 } 00125 00126 /* 00127 * use a local variable so we can safely reset 00128 * pTerm->pEventTermInit when we're done with it 00129 */ 00130 pEventTermInit = pTerm->pEventTermInit; 00131 00132 LeaveCrit(); 00133 00134 /* 00135 * Create the desktop thread. 00136 */ 00137 Status = CreateSystemThread( 00138 (PKSTART_ROUTINE)xxxDesktopThread, 00139 pTerm, 00140 &hThreadDesktop); 00141 00142 if (!NT_SUCCESS(Status)) { 00143 EnterCrit(); 00144 ObDereferenceObject(pTerm->pEventInputReady); 00145 ObDereferenceObject(pEventTermInit); 00146 return STATUS_NO_MEMORY; 00147 } 00148 00149 ZwClose(hThreadDesktop); 00150 00151 Wait: 00152 KeWaitForSingleObject(pEventTermInit, 00153 WrUserRequest, 00154 KernelMode, 00155 FALSE, 00156 NULL); 00157 00158 EnterCrit(); 00159 00160 /* 00161 * dereference the terminal init event. It will eventually 00162 * go away. 00163 */ 00164 ObDereferenceObject(pEventTermInit); 00165 00166 pTerm->pEventTermInit = NULL; 00167 00168 if (pTerm->dwTERMF_Flags & TERMF_DTINITFAILED) { 00169 return STATUS_NO_MEMORY; 00170 } 00171 00172 pTerm->dwTERMF_Flags |= TERMF_INITIALIZED; 00173 return STATUS_SUCCESS; 00174 }

BOOL xxxSetProcessWindowStation HWINSTA  hwinsta,
KPROCESSOR_MODE  AccessMode
 

Definition at line 1077 of file winsta.c.

References tagPROCESSINFO::amwinsta, BOOL, tagWINDOWSTATION::dwWSF_Flags, ExWindowStationObjectType, FALSE, _OBJECT_HANDLE_INFORMATION::GrantedAccess, HF_PROTECTED, tagPROCESSINFO::hwinsta, LockWinSta, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PpiFromProcess, PsGetCurrentProcess, PsGetCurrentThread, tagPROCESSINFO::rpwinsta, RtlAreAllAccessesGranted(), SetHandleFlag(), Status, THREAD_TO_PROCESS, TRUE, _EPROCESS::Win32WindowStation, WSF_NOIO, and xxxUserDuplicateObject().

Referenced by NtUserSetProcessWindowStation(), and xxxCreateThreadInfo().

01080 { 01081 PETHREAD Thread = PsGetCurrentThread(); 01082 PEPROCESS Process = PsGetCurrentProcess(); 01083 HWINSTA hwinstaDup; 01084 NTSTATUS Status; 01085 PPROCESSINFO ppi; 01086 PWINDOWSTATION pwinsta; 01087 PWINDOWSTATION pwinstaOld; 01088 OBJECT_HANDLE_INFORMATION ohi; 01089 OBJECT_HANDLE_INFORMATION ohiOld; 01090 01091 if (Process == NULL) { 01092 UserAssert(Process); 01093 return FALSE; 01094 } 01095 01096 if (Thread == NULL) { 01097 UserAssert(Thread); 01098 return FALSE; 01099 } 01100 01101 ppi = PpiFromProcess(THREAD_TO_PROCESS(Thread)); 01102 01103 if (!NT_SUCCESS(ObReferenceObjectByHandle( 01104 hwinsta, 01105 0, 01106 *ExWindowStationObjectType, 01107 AccessMode, 01108 &pwinsta, 01109 &ohi))) { 01110 return FALSE; 01111 } 01112 01113 /* 01114 * Bug 38780. Lock the handle to window station so that an app cannot free the 01115 * this handle by calling GetProcessWindowStation() & CloseHandle() 01116 */ 01117 01118 /* 01119 * Unprotect the old hwinsta 01120 */ 01121 if (ppi->hwinsta) { 01122 SetHandleFlag(ppi->hwinsta, HF_PROTECTED, FALSE); 01123 } 01124 01125 /* 01126 * Save the WindowStation information 01127 */ 01128 LockWinSta(&ppi->rpwinsta, pwinsta); 01129 ObDereferenceObject(pwinsta); 01130 ppi->hwinsta = hwinsta; 01131 01132 /* 01133 * Protect the new Window Station Handle 01134 */ 01135 SetHandleFlag(ppi->hwinsta, HF_PROTECTED, TRUE); 01136 01137 /* 01138 * Check the old Atom Manager WindowStation to see if we are 01139 * changing this process' WindowStation. 01140 */ 01141 if (Process->Win32WindowStation) { 01142 /* 01143 * Get a pointer to the old WindowStation object to see if it's 01144 * the same WindowStation that we are setting. 01145 */ 01146 Status = ObReferenceObjectByHandle( 01147 Process->Win32WindowStation, 01148 0, 01149 *ExWindowStationObjectType, 01150 AccessMode, 01151 &pwinstaOld, 01152 &ohiOld); 01153 if (NT_SUCCESS(Status)) { 01154 /* 01155 * Are they different WindowStations? If so, NULL out the 01156 * atom manager cache so we will reset it below. 01157 */ 01158 if (pwinsta != pwinstaOld) { 01159 ZwClose(Process->Win32WindowStation); 01160 Process->Win32WindowStation = NULL; 01161 } 01162 ObDereferenceObject(pwinstaOld); 01163 01164 } else { 01165 /* 01166 * Their Atom Manager handle is bad? Give them a new one. 01167 */ 01168 Process->Win32WindowStation = NULL; 01169 #if DBG 01170 RIPMSG2(RIP_WARNING, 01171 "SetProcessWindowStation: Couldn't reference old WindowStation (0x%X) Status=0x%X", 01172 Process->Win32WindowStation, 01173 Status); 01174 #endif 01175 } 01176 } 01177 01178 /* 01179 * Duplicate the WindowStation handle and stash it in the atom 01180 * manager's cache (Process->Win32WindowStation). We duplicate 01181 * the handle in case 01182 */ 01183 if (Process->Win32WindowStation == NULL) { 01184 Status = xxxUserDuplicateObject( 01185 NtCurrentProcess(), 01186 hwinsta, 01187 NtCurrentProcess(), 01188 &hwinstaDup, 01189 0, 01190 0, 01191 DUPLICATE_SAME_ACCESS); 01192 01193 if (NT_SUCCESS(Status)) { 01194 Process->Win32WindowStation = hwinstaDup; 01195 } 01196 #if DBG 01197 else { 01198 RIPMSG2(RIP_WARNING, 01199 "SetProcessWindowStation: Couldn't duplicate WindowStation handle (0x%X) Status=0x%X", 01200 hwinsta, 01201 Status); 01202 } 01203 #endif 01204 } 01205 01206 ppi->amwinsta = ohi.GrantedAccess; 01207 01208 /* 01209 * Cache WSF_NOIO flag in the W32PROCESS so that GDI can access it. 01210 */ 01211 if (pwinsta->dwWSF_Flags & WSF_NOIO) { 01212 ppi->W32PF_Flags &= ~W32PF_IOWINSTA; 01213 } else { 01214 ppi->W32PF_Flags |= W32PF_IOWINSTA; 01215 } 01216 01217 /* 01218 * Do the access check now for readscreen so that 01219 * blts off of the display will be as fast as possible. 01220 */ 01221 if (RtlAreAllAccessesGranted(ohi.GrantedAccess, WINSTA_READSCREEN)) { 01222 ppi->W32PF_Flags |= W32PF_READSCREENACCESSGRANTED; 01223 } else { 01224 ppi->W32PF_Flags &= ~W32PF_READSCREENACCESSGRANTED; 01225 } 01226 01227 return TRUE; 01228 }


Variable Documentation

CONST LPCWSTR lpszStdFormats[] [static]
 

Initial value:

{ L"StdExit", L"StdNewDocument", L"StdOpenDocument", L"StdEditDocument", L"StdNewfromTemplate", L"StdCloseDocument", L"StdShowItem", L"StdDoVerbItem", L"System", L"OLEsystem", L"StdDocumentName", L"Protocols", L"Topics", L"Formats", L"Status", L"EditEnvItems", L"True", L"False", L"Change", L"Save", L"Close", L"MSDraw" }

Definition at line 187 of file winsta.c.

Referenced by CreateGlobalAtomTable().


Generated on Sat May 15 19:46:09 2004 for test by doxygen 1.3.7