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

desktop.c File Reference

#include "precomp.h"

Go to the source code of this file.

Classes

struct  _DESKTOP_CONTEXT

Defines

#define OBJECTS_COUNT   4

Typedefs

typedef _DESKTOP_CONTEXT DESKTOP_CONTEXT
typedef _DESKTOP_CONTEXTPDESKTOP_CONTEXT

Functions

VOID FreeView (PEPROCESS Process, PDESKTOP pdesk)
PVOID DesktopAlloc (PDESKTOP pdesk, UINT uSize, DWORD tag)
VOID xxxDesktopThread (PTERMINAL pTerm)
VOID xxxRealizeDesktop (PWND pwnd)
LRESULT xxxDesktopWndProc (PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam)
BOOL xxxSetDeskPattern (PUNICODE_STRING pProfileUserName, LPWSTR lpszPattern, BOOL fCreation)
VOID RecolorDeskPattern (VOID)
NTSTATUS xxxCreateDesktop2 (PWINDOWSTATION pwinsta, PACCESS_STATE pAccessState, KPROCESSOR_MODE AccessMode, PUNICODE_STRING pstrName, PDESKTOP_CONTEXT Context, PVOID *pObject)
BOOL xxxCreateDisconnectDesktop (HWINSTA hwinsta, PWINDOWSTATION pwinsta)
VOID CleanupDirtyDesktops (VOID)
HDESK xxxCreateDesktop (POBJECT_ATTRIBUTES ccxObjectAttributes, KPROCESSOR_MODE ProbeMode, PUNICODE_STRING ccxpstrDevice, LPDEVMODE ccxlpdevmode, DWORD dwFlags, DWORD dwDesiredAccess)
NTSTATUS ParseDesktop (PVOID pContainerObject, POBJECT_TYPE pObjectType, PACCESS_STATE pAccessState, KPROCESSOR_MODE AccessMode, ULONG Attributes, PUNICODE_STRING pstrCompleteName, PUNICODE_STRING pstrRemainingName, PVOID Context, PSECURITY_QUALITY_OF_SERVICE pqos, PVOID *pObject)
BOOL DestroyDesktop (PDESKTOP pdesk)
VOID FreeDesktop (PVOID pobj)
HANDLE CreateDesktopHeap (PWIN32HEAP *ppheapRet, ULONG ulHeapSize)
PDESKTOPVIEW GetDesktopView (PPROCESSINFO ppi, PDESKTOP pdesk)
PVOID _MapDesktopObject (HANDLE h)
VOID MapDesktop (OB_OPEN_REASON OpenReason, PEPROCESS Process, PVOID pobj, ACCESS_MASK amGranted, ULONG cHandles)
VOID UnmapDesktop (PEPROCESS Process, PVOID pobj, ACCESS_MASK amGranted, ULONG cProcessHandles, ULONG cSystemHandles)
BOOLEAN OkayToCloseDesktop (PEPROCESS Process OPTIONAL, PVOID Object, HANDLE Handle)
VOID xxxUserResetDisplayDevice ()
BOOL OpenDesktopCompletion (PDESKTOP pdesk, HDESK hdesk, DWORD dwFlags, BOOL *pbShutDown)
HDESK xxxOpenDesktop (POBJECT_ATTRIBUTES ccxObjA, KPROCESSOR_MODE AccessMode, DWORD dwFlags, DWORD dwDesiredAccess, BOOL *pbShutDown)
BOOL xxxSwitchDesktop (PWINDOWSTATION pwinsta, PDESKTOP pdesk, BOOL bCreateNew)
VOID zzzSetDesktop (PTHREADINFO pti, PDESKTOP pdesk, HDESK hdesk)
BOOL xxxSetThreadDesktop (HDESK hdesk, PDESKTOP pdesk)
NTSTATUS xxxUserDuplicateObject (IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
BOOLEAN xxxUserFindHandleForObject (IN PEPROCESS Process, IN PVOID Object OPTIONAL, IN POBJECT_TYPE ObjectType OPTIONAL, IN POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL, OUT PHANDLE Handle)
HDESK xxxGetThreadDesktop (DWORD dwThread, HDESK hdeskConsole, KPROCESSOR_MODE AccessMode)
HDESK xxxGetInputDesktop (VOID)
BOOL xxxCloseDesktop (HDESK hdesk, KPROCESSOR_MODE AccessMode)
VOID TerminateConsole (PDESKTOP pdesk)
BOOL CheckHandleFlag (HANDLE hObject, DWORD dwFlag)
BOOL SetHandleFlag (HANDLE hObject, DWORD dwFlag, BOOL fSet)
BOOL CheckHandleInUse (HANDLE hObject)
VOID SetHandleInUse (HANDLE hObject)
NTSTATUS xxxResolveDesktopForWOW (IN OUT PUNICODE_STRING pstrDesktop)
HDESK xxxResolveDesktop (HANDLE hProcess, PUNICODE_STRING pstrDesktop, HWINSTA *phwinsta, BOOL fInherit, BOOL *pbShutDown)

Variables

BOOL fGdiEnabled
PEPROCESS gProcessInUse
HANDLE gHandleInUse


Define Documentation

#define OBJECTS_COUNT   4
 

Definition at line 112 of file desktop.c.

Referenced by xxxDesktopThread().


Typedef Documentation

typedef struct _DESKTOP_CONTEXT DESKTOP_CONTEXT
 

typedef struct _DESKTOP_CONTEXT * PDESKTOP_CONTEXT
 


Function Documentation

PVOID _MapDesktopObject HANDLE  h  ) 
 

Definition at line 2798 of file desktop.c.

References GetDesktopView(), HMObjectFlags, HMValidateHandle(), NULL, OCF_DESKTOPHEAP, PBYTE, PDESKOBJHEAD, PpiCurrent, TYPE_GENERIC, and tagDESKTOPVIEW::ulClientDelta.

02800 { 02801 PDESKOBJHEAD pobj; 02802 PDESKTOPVIEW pdv; 02803 02804 /* 02805 * Validate the handle 02806 */ 02807 pobj = HMValidateHandle(h, TYPE_GENERIC); 02808 if (pobj == NULL) 02809 return NULL; 02810 02811 UserAssert(HMObjectFlags(pobj) & OCF_DESKTOPHEAP); 02812 02813 /* 02814 * Locate the client's view of the desktop. Realistically, 02815 * this should never fail for valid objects. 02816 */ 02817 pdv = GetDesktopView(PpiCurrent(), pobj->rpdesk); 02818 if (pdv == NULL) { 02819 RIPMSG1(RIP_WARNING, "MapDesktopObject: can not map handle %#p", h); 02820 return NULL; 02821 } 02822 02823 UserAssert(pdv->ulClientDelta != 0); 02824 return (PVOID)((PBYTE)pobj - pdv->ulClientDelta); 02825 }

BOOL CheckHandleFlag HANDLE  hObject,
DWORD  dwFlag
 

Definition at line 4464 of file desktop.c.

References tagPROCESSINFO::bmHandleFlags, BOOL, EnterHandleFlagsCrit(), FALSE, HF_LIMIT, Index, LeaveHandleFlagsCrit(), NULL, PEXHANDLE, and PpiCurrent.

Referenced by _GetUserObjectInformation(), OkayToCloseDesktop(), OkayToCloseWindowStation(), and zzzSetDesktop().

04467 { 04468 PPROCESSINFO ppi; 04469 ULONG Index = ((PEXHANDLE)&hObject)->Index * HF_LIMIT + dwFlag; 04470 BOOL fRet = FALSE; 04471 04472 EnterHandleFlagsCrit(); 04473 04474 if ((ppi = PpiCurrent()) != NULL) { 04475 fRet = (Index < ppi->bmHandleFlags.SizeOfBitMap && 04476 RtlCheckBit(&ppi->bmHandleFlags, Index)); 04477 } 04478 04479 LeaveHandleFlagsCrit(); 04480 04481 return fRet; 04482 }

BOOL CheckHandleInUse HANDLE  hObject  ) 
 

Definition at line 4557 of file desktop.c.

References BOOL, EnterHandleFlagsCrit(), gHandleInUse, gProcessInUse, LeaveHandleFlagsCrit(), and PsGetCurrentProcess.

Referenced by OkayToCloseDesktop(), and OkayToCloseWindowStation().

04559 { 04560 BOOL fRet; 04561 04562 EnterHandleFlagsCrit(); 04563 fRet = ((gProcessInUse == PsGetCurrentProcess()) && 04564 (gHandleInUse == hObject)); 04565 LeaveHandleFlagsCrit(); 04566 04567 return fRet; 04568 }

VOID CleanupDirtyDesktops VOID   ) 
 

Definition at line 1761 of file desktop.c.

References CheckCritIn, DF_DESKCREATED, grpdeskLogon, grpWinStaList, tagWND::head, LockDesktop, NULL, tagWINDOWSTATION::pTerm, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, tagWINDOWSTATION::rpwinstaNext, tagTERMINAL::spwndDesktopOwner, UnlockDesktop, and VOID().

Referenced by xxxCreateDesktop().

01763 { 01764 PWINDOWSTATION pwinsta; 01765 PDESKTOP* ppdesk; 01766 01767 CheckCritIn(); 01768 01769 for (pwinsta = grpWinStaList; pwinsta != NULL; pwinsta = pwinsta->rpwinstaNext) { 01770 01771 ppdesk = &pwinsta->rpdeskList; 01772 01773 while (*ppdesk != NULL) { 01774 01775 if (!((*ppdesk)->dwDTFlags & DF_DESKCREATED)) { 01776 RIPMSG1(RIP_WARNING, "Desktop %#p in a dirty state", *ppdesk); 01777 01778 if (grpdeskLogon == *ppdesk) { 01779 UnlockDesktop(&grpdeskLogon, LDU_DESKLOGON, 0); 01780 } 01781 01782 if (pwinsta->pTerm->spwndDesktopOwner && 01783 pwinsta->pTerm->spwndDesktopOwner->head.rpdesk == *ppdesk) { 01784 01785 UnlockDesktop(&(pwinsta->pTerm->spwndDesktopOwner->head.rpdesk), 01786 LDU_MOTHERDESK_DESK, (ULONG_PTR)(pwinsta->pTerm->spwndDesktopOwner)); 01787 } 01788 01789 LockDesktop(ppdesk, (*ppdesk)->rpdeskNext, LDL_WINSTA_DESKLIST1, (ULONG_PTR)pwinsta); 01790 } else { 01791 ppdesk = &(*ppdesk)->rpdeskNext; 01792 } 01793 } 01794 } 01795 }

HANDLE CreateDesktopHeap PWIN32HEAP *  ppheapRet,
ULONG  ulHeapSize
 

Definition at line 2696 of file desktop.c.

References Error, NT_SUCCESS, NTSTATUS(), NULL, Status, UserCommitDesktopMemory(), and UserCreateHeap().

Referenced by xxxCreateDesktop2().

02699 { 02700 HANDLE hsection; 02701 LARGE_INTEGER SectionSize; 02702 SIZE_T ulViewSize; 02703 NTSTATUS Status; 02704 PWIN32HEAP pheap; 02705 PVOID pHeapBase; 02706 02707 /* 02708 * Create desktop heap section and map it into the kernel 02709 */ 02710 SectionSize.QuadPart = ulHeapSize; 02711 02712 Status = Win32CreateSection(&hsection, 02713 SECTION_ALL_ACCESS, 02714 (POBJECT_ATTRIBUTES)NULL, 02715 &SectionSize, 02716 PAGE_EXECUTE_READWRITE, 02717 SEC_RESERVE, 02718 (HANDLE)NULL, 02719 NULL, 02720 TAG_SECTION_DESKTOP); 02721 02722 if (!NT_SUCCESS( Status )) { 02723 RIPNTERR0(Status, RIP_WARNING, "Can't create section for desktop heap."); 02724 return NULL; 02725 } 02726 02727 ulViewSize = ulHeapSize; 02728 pHeapBase = NULL; 02729 02730 Status = Win32MapViewInSessionSpace(hsection, &pHeapBase, &ulViewSize); 02731 02732 if (!NT_SUCCESS(Status)) { 02733 RIPNTERR0(Status, 02734 RIP_WARNING, 02735 "Can't map section for desktop heap into system space."); 02736 goto Error; 02737 } 02738 02739 /* 02740 * Create desktop heap. 02741 */ 02742 if ((pheap = UserCreateHeap( 02743 hsection, 02744 0, 02745 pHeapBase, 02746 ulHeapSize, 02747 UserCommitDesktopMemory)) == NULL) { 02748 02749 RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_WARNING, "Can't create Desktop heap."); 02750 02751 Win32UnmapViewInSessionSpace(pHeapBase); 02752 Error: 02753 Win32DestroySection(hsection); 02754 *ppheapRet = NULL; 02755 return NULL; 02756 } 02757 02758 UserAssert(Win32HeapGetHandle(pheap) == pHeapBase); 02759 *ppheapRet = pheap; 02760 02761 return hsection; 02762 }

PVOID DesktopAlloc PDESKTOP  pdesk,
UINT  uSize,
DWORD  tag
 

Definition at line 47 of file desktop.c.

References DF_DESTROYED, tagDESKTOP::dwDTFlags, NULL, and tagDESKTOP::pheapDesktop.

Referenced by _InitPwSB(), CreateProp(), DefSetText(), HMAllocObject(), xxxCreateDefaultImeWindow(), xxxCreateDesktop2(), xxxInsertMenuItem(), xxxRemoveDeleteMenuHelper(), and xxxSetLPITEMInfo().

00051 { 00052 if (pdesk->dwDTFlags & DF_DESTROYED) { 00053 RIPMSG2(RIP_ERROR, 00054 "DesktopAlloc: tag %d pdesk %#p is destroyed", 00055 tag, 00056 pdesk); 00057 return NULL; 00058 } 00059 00060 return Win32HeapAlloc(pdesk->pheapDesktop, uSize, tag, 0); 00061 }

BOOL DestroyDesktop PDESKTOP  pdesk  ) 
 

Definition at line 2478 of file desktop.c.

References BOOL, DF_DESTROYED, tagDESKTOP::dwDTFlags, EVENT_INCREMENT, FALSE, KeSetEvent(), LockDesktop, NULL, tagWINDOWSTATION::pTerm, tagTERMINAL::rpdeskDestroy, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, tagDESKTOP::rpwinstaParent, TRACE_DESKTOP, TRUE, and UnlockDesktop.

Referenced by UnmapDesktop().

02480 { 02481 PWINDOWSTATION pwinsta = pdesk->rpwinstaParent; 02482 PTERMINAL pTerm; 02483 PDESKTOP *ppdesk; 02484 02485 if (pdesk->dwDTFlags & DF_DESTROYED) { 02486 RIPMSG1(RIP_WARNING, "DestroyDesktop: Already destroyed:%#p", pdesk); 02487 return FALSE; 02488 } 02489 02490 /* 02491 * Unlink the desktop, if it has not yet been unlinked. 02492 */ 02493 if (pwinsta != NULL) { 02494 02495 ppdesk = &pwinsta->rpdeskList; 02496 while (*ppdesk != NULL && *ppdesk != pdesk) { 02497 ppdesk = &((*ppdesk)->rpdeskNext); 02498 } 02499 02500 if (*ppdesk != NULL) { 02501 02502 /* 02503 * remove desktop from the list 02504 */ 02505 LockDesktop(ppdesk, pdesk->rpdeskNext, LDL_WINSTA_DESKLIST2, (ULONG_PTR)pwinsta); 02506 UnlockDesktop(&pdesk->rpdeskNext, LDU_DESK_DESKNEXT, (ULONG_PTR)pwinsta); 02507 } 02508 } 02509 02510 /* 02511 * Link it into the destruction list and signal the desktop thread. 02512 */ 02513 pTerm = pwinsta->pTerm; 02514 02515 LockDesktop(&pdesk->rpdeskNext, pTerm->rpdeskDestroy, LDL_DESK_DESKNEXT2, 0); 02516 LockDesktop(&pTerm->rpdeskDestroy, pdesk, LDL_TERM_DESKDESTROY2, (ULONG_PTR)pTerm); 02517 KeSetEvent(pTerm->pEventDestroyDesktop, EVENT_INCREMENT, FALSE); 02518 02519 pdesk->dwDTFlags |= DF_DESTROYED; 02520 02521 TRACE_DESKTOP(("pdesk %#p '%ws' marked as destroyed\n", pdesk, GetDesktopName(pdesk))); 02522 02523 return TRUE; 02524 }

VOID FreeDesktop PVOID  pobj  ) 
 

Definition at line 2535 of file desktop.c.

References tagSHAREDINFO::aheList, BOOL, _HANDLEENTRY::bType, DbgPrint, DbgTrackRemoveDesktop, DF_DESKWNDDESTROYED, DF_DYING, tagDESKTOP::dwDTFlags, ExDesktopObjectType, FALSE, FreeView(), giheLast, gpepCSRSS, gSharedInfo, tagDESKTOP::hsectionDesktop, NT_SUCCESS, NTSTATUS(), NULL, OBJECT_TO_OBJECT_HEADER, tagCLS::pclsClone, tagCLS::pclsNext, tagPROCESSINFO::pclsPrivateList, tagPROCESSINFO::pclsPublicList, tagDESKTOP::pDeskInfo, _HANDLEENTRY::phead, tagDESKTOP::pheapDesktop, tagPROCESSINFO::ppiNext, tagDESKTOP::rpwinstaParent, tagDESKTOPINFO::spwnd, Status, TRUE, TYPE_CALLPROC, TYPE_HOOK, TYPE_MENU, TYPE_WINDOW, UnlockWinSta, and VOID().

Referenced by Win32UserInitialize().

02537 { 02538 PDESKTOP pdesk = (PDESKTOP)pobj; 02539 NTSTATUS Status; 02540 02541 BEGIN_REENTERCRIT(); 02542 02543 UserAssert(OBJECT_TO_OBJECT_HEADER(pobj)->Type == *ExDesktopObjectType); 02544 02545 #ifdef LOGDESKTOPLOCKS 02546 02547 if (pdesk->pLog != NULL) { 02548 02549 /* 02550 * By the time we get here the lock count for lock/unlock 02551 * tracking code should be 0 02552 */ 02553 if (pdesk->nLockCount != 0) { 02554 RIPMSG3(RIP_WARNING, 02555 "FreeDesktop pdesk %#p, pLog %#p, nLockCount %d should be 0", 02556 pdesk, pdesk->pLog, pdesk->nLockCount); 02557 } 02558 UserFreePool(pdesk->pLog); 02559 pdesk->pLog = NULL; 02560 } 02561 #endif // LOGDESKTOPLOCKS 02562 02563 #if DBG 02564 if (pdesk->pDeskInfo && (pdesk->pDeskInfo->spwnd != NULL)) { 02565 02566 /* 02567 * assert if the desktop has a desktop window but the flag 02568 * that says the window is destroyed is not set 02569 */ 02570 UserAssert(pdesk->dwDTFlags & DF_DESKWNDDESTROYED); 02571 } 02572 #endif // DBG 02573 02574 /* 02575 * Mark the desktop as dying. Make sure we aren't recursing. 02576 */ 02577 UserAssert(!(pdesk->dwDTFlags & DF_DYING)); 02578 pdesk->dwDTFlags |= DF_DYING; 02579 02580 #ifdef DEBUG_DESK 02581 { 02582 /* 02583 * Verify that the desktop has been cleaned out. 02584 */ 02585 #if 0 02586 PPROCESSINFO ppi; 02587 PCLS pcls, pclsClone; 02588 #endif 02589 PHE pheT, pheMax; 02590 BOOL fDirty = FALSE; 02591 02592 #if 0 02593 for (ppi = gppiFirst; ppi != NULL; ppi = ppi->ppiNext) { 02594 for (pcls = ppi->pclsPrivateList; pcls != NULL; pcls = pcls->pclsNext) { 02595 if (pcls->pheapDesktop == pdesk->pheapDesktop) { 02596 DbgPrint("ppi %08x private class at %08x exists\n", ppi, pcls); 02597 fDirty = TRUE; 02598 } 02599 for (pclsClone = pcls->pclsClone; pclsClone != NULL; 02600 pclsClone = pclsClone->pclsNext) { 02601 if (pclsClone->pheapDesktop == pdesk->pheapDesktop) { 02602 DbgPrint("ppi %08x private class clone at %08x exists\n", ppi, pclsClone); 02603 fDirty = TRUE; 02604 } 02605 } 02606 } 02607 for (pcls = ppi->pclsPublicList; pcls != NULL; pcls = pcls->pclsNext) { 02608 if (pcls->pheapDesktop == pdesk->pheapDesktop) { 02609 DbgPrint("ppi %08x public class at %08x exists\n", ppi, pcls); 02610 fDirty = TRUE; 02611 } 02612 for (pclsClone = pcls->pclsClone; pclsClone != NULL; 02613 pclsClone = pclsClone->pclsNext) { 02614 if (pclsClone->pheapDesktop == pdesk->pheapDesktop) { 02615 DbgPrint("ppi %08x public class clone at %08x exists\n", ppi, pclsClone); 02616 fDirty = TRUE; 02617 } 02618 } 02619 } 02620 } 02621 #endif 02622 02623 pheMax = &gSharedInfo.aheList[giheLast]; 02624 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 02625 switch (pheT->bType) { 02626 case TYPE_WINDOW: 02627 if (((PWND)pheT->phead)->head.rpdesk == pdesk) { 02628 DbgPrint("Window at %08x exists\n", pheT->phead); 02629 break; 02630 } 02631 continue; 02632 case TYPE_MENU: 02633 if (((PMENU)pheT->phead)->head.rpdesk == pdesk) { 02634 DbgPrint("Menu at %08x exists\n", pheT->phead); 02635 break; 02636 } 02637 continue; 02638 case TYPE_CALLPROC: 02639 if (((PCALLPROCDATA)pheT->phead)->head.rpdesk == pdesk) { 02640 DbgPrint("Callproc at %08x exists\n", pheT->phead); 02641 break; 02642 } 02643 continue; 02644 case TYPE_HOOK: 02645 if (((PHOOK)pheT->phead)->head.rpdesk == pdesk) { 02646 DbgPrint("Hook at %08x exists\n", pheT->phead); 02647 break; 02648 } 02649 continue; 02650 default: 02651 continue; 02652 } 02653 fDirty = TRUE; 02654 } 02655 if (fDirty) { 02656 RIPMSG0(RIP_ERROR,"Desktop cleanup failed\n"); 02657 } 02658 } 02659 #endif 02660 02661 /* 02662 * If the desktop is mapped into CSR, unmap it. Note the 02663 * handle count values passed in will cause the desktop 02664 * to be unmapped and skip the desktop destruction tests. 02665 */ 02666 FreeView(gpepCSRSS, pdesk); 02667 02668 if (pdesk->pheapDesktop != NULL) { 02669 02670 PVOID hheap = Win32HeapGetHandle(pdesk->pheapDesktop); 02671 02672 Win32HeapDestroy(pdesk->pheapDesktop); 02673 02674 Status = Win32UnmapViewInSessionSpace(hheap); 02675 02676 UserAssert(NT_SUCCESS(Status)); 02677 Win32DestroySection(pdesk->hsectionDesktop); 02678 } 02679 02680 UnlockWinSta(&pdesk->rpwinstaParent); 02681 02682 DbgTrackRemoveDesktop(pdesk); 02683 02684 END_REENTERCRIT(); 02685 }

VOID FreeView PEPROCESS  Process,
PDESKTOP  pdesk
 

Definition at line 2949 of file desktop.c.

References GetDesktopView(), MmUnmapViewOfSection(), NT_SUCCESS, NTSTATUS(), NULL, PBYTE, tagPROCESSINFO::pdvList, tagDESKTOPVIEW::pdvNext, tagDESKTOP::pheapDesktop, PpiFromProcess, tagPROCESSINFO::ptiList, tagTHREADINFO::ptiSibling, tagTHREADINFO::rpdesk, Status, tagDESKTOPVIEW::ulClientDelta, and VOID().

Referenced by FreeDesktop(), and UnmapDesktop().

02952 { 02953 PPROCESSINFO ppi; 02954 NTSTATUS Status; 02955 PDESKTOPVIEW pdv; 02956 PDESKTOPVIEW *ppdv; 02957 02958 /* 02959 * Bug 277291: gpepCSRSS can be NULL when FreeView is 02960 * called from FreeDesktop. 02961 */ 02962 if (Process == NULL) { 02963 return; 02964 } 02965 02966 ppi = PpiFromProcess(Process); 02967 02968 /* 02969 * If there is no ppi, then the process is gone and nothing 02970 * needs to be unmapped. 02971 */ 02972 if (ppi != NULL) { 02973 pdv = GetDesktopView(ppi, pdesk); 02974 02975 /* 02976 * Because mapping cannot be done when a handle is 02977 * inherited, there may not be a view of the desktop. 02978 * Only unmap if there is a view. 02979 */ 02980 if (pdv != NULL) { 02981 Status = MmUnmapViewOfSection(Process, 02982 (PBYTE)Win32HeapGetHandle(pdesk->pheapDesktop) - pdv->ulClientDelta); 02983 UserAssert(NT_SUCCESS(Status) || Status == STATUS_PROCESS_IS_TERMINATING); 02984 if (!NT_SUCCESS(Status)) { 02985 RIPMSG1(RIP_WARNING, "FreeView unmap status = 0x%#lx", Status); 02986 } 02987 02988 /* 02989 * Unlink and delete the view. 02990 */ 02991 for (ppdv = &ppi->pdvList; *ppdv && *ppdv != pdv; 02992 ppdv = &(*ppdv)->pdvNext) 02993 ; 02994 UserAssert(*ppdv); 02995 *ppdv = pdv->pdvNext; 02996 UserFreePool(pdv); 02997 } 02998 02999 #if DBG 03000 /* 03001 * No thread in this process should be on this desktop 03002 */ 03003 { 03004 PTHREADINFO pti = ppi->ptiList; 03005 while (pti != NULL) { 03006 if (pti->rpdesk == pdesk) { 03007 RIPMSG2(RIP_ERROR, "FreeView: pti %#p still on pdesk %#p", pti, pdesk); 03008 } 03009 pti = pti->ptiSibling; 03010 } 03011 } 03012 #endif 03013 } 03014 }

PDESKTOPVIEW GetDesktopView PPROCESSINFO  ppi,
PDESKTOP  pdesk
 

Definition at line 2773 of file desktop.c.

References gpepCSRSS, NULL, tagDESKTOPVIEW::pdesk, tagPROCESSINFO::pdvList, and tagDESKTOPVIEW::pdvNext.

Referenced by _MapDesktopObject(), FreeView(), MapDesktop(), NtUserPostThreadMessage(), OpenDesktopCompletion(), UserCommitDesktopMemory(), ValidateHwnd(), xxxCreateDesktop(), xxxResolveDesktop(), xxxSetThreadDesktop(), and zzzSetDesktop().

02776 { 02777 PDESKTOPVIEW pdv; 02778 02779 if(ppi->Process != gpepCSRSS && pdesk == NULL) { 02780 RIPMSG1(RIP_WARNING, "Process %#p isn't CSRSS but pdesk is NULL in GetDesktopView", ppi); 02781 } 02782 02783 for (pdv = ppi->pdvList; pdv != NULL; pdv = pdv->pdvNext) 02784 if (pdv->pdesk == pdesk) 02785 break; 02786 return pdv; 02787 }

VOID MapDesktop OB_OPEN_REASON  OpenReason,
PEPROCESS  Process,
PVOID  pobj,
ACCESS_MASK  amGranted,
ULONG  cHandles
 

Definition at line 2836 of file desktop.c.

References BOOL, ExDesktopObjectType, ExRaiseStatus(), FALSE, GetDesktopView(), tagDESKTOP::hsectionDesktop, MmMapViewOfSection(), NT_SUCCESS, NTSTATUS(), NULL, OB_OPEN_REASON, ObInheritHandle, OBJECT_TO_OBJECT_HEADER, PBYTE, tagPROCESSINFO::pdvList, tagDESKTOP::pheapDesktop, PpiFromProcess, Status, TRUE, and VOID().

Referenced by Win32UserInitialize().

02842 { 02843 PPROCESSINFO ppi; 02844 PDESKTOP pdesk = (PDESKTOP)pobj; 02845 NTSTATUS Status; 02846 SIZE_T ulViewSize; 02847 LARGE_INTEGER liOffset; 02848 PDESKTOPVIEW pdvNew; 02849 PBYTE pClientBase; 02850 BOOL bFailed = FALSE; 02851 02852 UserAssert(OBJECT_TO_OBJECT_HEADER(pobj)->Type == *ExDesktopObjectType); 02853 02854 /* 02855 * Ignore handle inheritance because MmMapViewOfSection 02856 * cannot be called during process creation. 02857 */ 02858 if (OpenReason == ObInheritHandle) 02859 return; 02860 02861 /* 02862 * If there is no ppi, we can't map the desktop 02863 */ 02864 ppi = PpiFromProcess(Process); 02865 if (ppi == NULL) 02866 return; 02867 02868 /* 02869 * If the desktop has already been mapped we're done. 02870 */ 02871 if (GetDesktopView(ppi, pdesk) != NULL) 02872 return; 02873 02874 /* 02875 * Allocate a view of the desktop 02876 */ 02877 pdvNew = UserAllocPoolWithQuota(sizeof(*pdvNew), TAG_PROCESSINFO); 02878 if (pdvNew == NULL) { 02879 RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_VERBOSE, ""); 02880 02881 /* 02882 * Raise an exception so that the object manager 02883 * knows OpenProcedure wasn't successful 02884 */ 02885 ExRaiseStatus(STATUS_NO_MEMORY); 02886 return; 02887 } 02888 02889 BEGIN_REENTERCRIT(); 02890 02891 /* 02892 * Read/write access has been granted. Map the desktop 02893 * memory into the client process. 02894 */ 02895 ulViewSize = 0; 02896 liOffset.QuadPart = 0; 02897 pClientBase = NULL; 02898 02899 Status = MmMapViewOfSection(pdesk->hsectionDesktop, 02900 Process, 02901 &pClientBase, 02902 0, 02903 0, 02904 &liOffset, 02905 &ulViewSize, 02906 ViewUnmap, 02907 SEC_NO_CHANGE, 02908 PAGE_EXECUTE_READ); 02909 02910 if (!NT_SUCCESS(Status)) { 02911 #if DBG 02912 if ( Status != STATUS_NO_MEMORY && 02913 Status != STATUS_PROCESS_IS_TERMINATING && 02914 Status != STATUS_COMMITMENT_LIMIT) { 02915 RIPMSG1(RIP_WARNING, "MapDesktop - failed to map to client process (status == %lX). Contact ChrisWil",Status); 02916 } 02917 #endif 02918 02919 RIPNTERR0(Status, RIP_VERBOSE, ""); 02920 UserFreePool(pdvNew); 02921 bFailed = TRUE; 02922 goto Exit; 02923 } 02924 02925 /* 02926 * Link the view into the ppi 02927 */ 02928 pdvNew->pdesk = pdesk; 02929 pdvNew->ulClientDelta = (ULONG_PTR)((PBYTE)Win32HeapGetHandle(pdesk->pheapDesktop) - pClientBase); 02930 pdvNew->pdvNext = ppi->pdvList; 02931 ppi->pdvList = pdvNew; 02932 02933 Exit: 02934 END_REENTERCRIT(); 02935 02936 /* 02937 * If something failed raise an exception so that the object manager 02938 * knows OpenProcedure wasn't successful 02939 */ 02940 if (bFailed) { 02941 ExRaiseStatus(STATUS_NO_MEMORY); 02942 } 02943 02944 UNREFERENCED_PARAMETER(cHandles); 02945 UNREFERENCED_PARAMETER(amGranted); 02946 }

BOOLEAN OkayToCloseDesktop PEPROCESS Process  OPTIONAL,
PVOID  Object,
HANDLE  Handle
 

Definition at line 3089 of file desktop.c.

References CheckHandleFlag(), CheckHandleInUse(), DF_DESKCREATED, tagDESKTOP::dwDTFlags, ExDesktopObjectType, FALSE, Handle, HF_PROTECTED, KernelMode, OBJECT_TO_OBJECT_HEADER, and TRUE.

Referenced by Win32UserInitialize().

03093 { 03094 PDESKTOP pdesk = (PDESKTOP)Object; 03095 03096 UNREFERENCED_PARAMETER(Process); 03097 03098 UserAssert(OBJECT_TO_OBJECT_HEADER(Object)->Type == *ExDesktopObjectType); 03099 03100 /* 03101 * Kernel mode code can close anything. 03102 */ 03103 if (KeGetPreviousMode() == KernelMode) { 03104 return TRUE; 03105 } 03106 03107 /* 03108 * We can't close the desktop if we're still initializing it. 03109 */ 03110 if (!(pdesk->dwDTFlags & DF_DESKCREATED)) { 03111 RIPMSG1(RIP_WARNING, "Trying to close desktop %#p during initialization", pdesk); 03112 return FALSE; 03113 } 03114 03115 /* 03116 * We can't close a desktop that's being used. 03117 */ 03118 if (CheckHandleInUse(Handle) || CheckHandleFlag(Handle, HF_PROTECTED)) { 03119 RIPMSG1(RIP_WARNING, "Trying to close desktop %#p while still in use", pdesk); 03120 return FALSE; 03121 } 03122 03123 return TRUE; 03124 }

BOOL OpenDesktopCompletion PDESKTOP  pdesk,
HDESK  hdesk,
DWORD  dwFlags,
BOOL *  pbShutDown
 

Definition at line 3192 of file desktop.c.

References BOOL, dwFlags, tagWINDOWSTATION::dwWSF_Flags, FALSE, GetDesktopView(), GetProcessLuid(), gpidLogon, HF_DESKTOPHOOK, tagWINDOWSTATION::luidEndSession, NT_SUCCESS, NTSTATUS(), NULL, PpiCurrent, tagDESKTOP::rpwinstaParent, RtlEqualLuid(), SetHandleFlag(), Status, TRUE, WSF_OPENLOCK, and WSF_REALSHUTDOWN.

Referenced by NtUserOpenInputDesktop(), and xxxOpenDesktop().

03197 { 03198 PPROCESSINFO ppi = PpiCurrent(); 03199 PWINDOWSTATION pwinsta; 03200 BOOL fMapped; 03201 03202 /* 03203 * If the desktop was not mapped in as a result of the open, 03204 * fail. 03205 */ 03206 fMapped = (GetDesktopView(ppi, pdesk) != NULL); 03207 if (!fMapped) { 03208 03209 RIPMSG0(RIP_WARNING, "OpenDesktopCompletion failed." 03210 " The desktop is not mapped"); 03211 03212 /* 03213 * Desktop mapping failed. Status is set by MapDesktop 03214 */ 03215 return FALSE; 03216 } else { 03217 03218 /* 03219 * Fail if the windowstation is locked 03220 */ 03221 pwinsta = pdesk->rpwinstaParent; 03222 if (pwinsta->dwWSF_Flags & WSF_OPENLOCK && 03223 ppi->Process->UniqueProcessId != gpidLogon) { 03224 LUID luidCaller; 03225 NTSTATUS Status; 03226 03227 /* 03228 * If logoff is occuring and the caller does not 03229 * belong to the session that is ending, allow the 03230 * open to proceed. 03231 */ 03232 Status = GetProcessLuid(NULL, &luidCaller); 03233 03234 if (!NT_SUCCESS(Status) || 03235 (pwinsta->dwWSF_Flags & WSF_REALSHUTDOWN) || 03236 RtlEqualLuid(&luidCaller, &pwinsta->luidEndSession)) { 03237 03238 RIPERR0(ERROR_BUSY, RIP_WARNING, "OpenDesktopCompletion failed"); 03239 03240 /* 03241 * Set the shut down flag 03242 */ 03243 *pbShutDown = TRUE; 03244 return FALSE; 03245 } 03246 } 03247 } 03248 03249 SetHandleFlag(hdesk, HF_DESKTOPHOOK, dwFlags & DF_ALLOWOTHERACCOUNTHOOK); 03250 03251 return TRUE; 03252 }

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

Definition at line 2391 of file desktop.c.

References ExDesktopObjectType, ExWindowStationObjectType, NTSTATUS(), NULL, OBJECT_TO_OBJECT_HEADER, ObReferenceObject, POBJECT_NAME, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, RtlEqualUnicodeString(), Status, and xxxCreateDesktop2().

02402 { 02403 PWINDOWSTATION pwinsta = pContainerObject; 02404 PDESKTOP pdesk; 02405 PUNICODE_STRING pstrName; 02406 NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND; 02407 02408 *pObject = NULL; 02409 02410 BEGIN_REENTERCRIT(); 02411 02412 UserAssert(OBJECT_TO_OBJECT_HEADER(pContainerObject)->Type == *ExWindowStationObjectType); 02413 UserAssert(pObjectType == *ExDesktopObjectType); 02414 02415 /* 02416 * See if the desktop exists 02417 */ 02418 for (pdesk = pwinsta->rpdeskList; pdesk != NULL; pdesk = pdesk->rpdeskNext) { 02419 pstrName = POBJECT_NAME(pdesk); 02420 if (pstrName && RtlEqualUnicodeString(pstrRemainingName, pstrName, 02421 (BOOLEAN)((Attributes & OBJ_CASE_INSENSITIVE) != 0))) { 02422 if (Context != NULL) { 02423 if (!(Attributes & OBJ_OPENIF)) { 02424 02425 /* 02426 * We are attempting to create a desktop and one 02427 * already exists. 02428 */ 02429 Status = STATUS_OBJECT_NAME_COLLISION; 02430 goto Exit; 02431 02432 } else { 02433 Status = STATUS_OBJECT_NAME_EXISTS; 02434 } 02435 } else { 02436 Status = STATUS_SUCCESS; 02437 } 02438 02439 ObReferenceObject(pdesk); 02440 02441 *pObject = pdesk; 02442 goto Exit; 02443 } 02444 } 02445 02446 /* 02447 * Handle creation request 02448 */ 02449 if (Context != NULL) { 02450 Status = xxxCreateDesktop2(pContainerObject, 02451 pAccessState, 02452 AccessMode, 02453 pstrRemainingName, 02454 Context, 02455 pObject); 02456 } 02457 02458 Exit: 02459 END_REENTERCRIT(); 02460 02461 return Status; 02462 02463 UNREFERENCED_PARAMETER(pObjectType); 02464 UNREFERENCED_PARAMETER(pstrCompleteName); 02465 UNREFERENCED_PARAMETER(pqos); 02466 }

VOID RecolorDeskPattern VOID   ) 
 

Definition at line 1242 of file desktop.c.

References BYTE, CXYDESKPATTERN, ghbmDesktop, ghdcMem, ghdcMem2, HDCBITS, NULL, SYSHBR, SYSMET, SYSRGB, and VOID().

01243 { 01244 HBITMAP hbmOldDesk; 01245 HBITMAP hbmOldMem; 01246 HBITMAP hbmMem; 01247 HBRUSH hBrushTemp; 01248 if (ghbmDesktop == NULL) 01249 return; 01250 01251 /* 01252 * Redo the desktop pattern in the new colors. 01253 */ 01254 01255 if (hbmOldDesk = GreSelectBitmap(ghdcMem, ghbmDesktop)) { 01256 01257 if (!SYSMET(SAMEDISPLAYFORMAT)) { 01258 01259 BYTE bmi[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*2]; 01260 PBITMAPINFO pbmi = (PBITMAPINFO) &bmi; 01261 01262 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 01263 pbmi->bmiHeader.biWidth = CXYDESKPATTERN; 01264 pbmi->bmiHeader.biHeight = CXYDESKPATTERN; 01265 pbmi->bmiHeader.biPlanes = 1; 01266 pbmi->bmiHeader.biBitCount = 1; 01267 pbmi->bmiHeader.biCompression = BI_RGB; 01268 pbmi->bmiHeader.biSizeImage = 0; 01269 pbmi->bmiHeader.biXPelsPerMeter = 0; 01270 pbmi->bmiHeader.biYPelsPerMeter = 0; 01271 pbmi->bmiHeader.biClrUsed = 2; 01272 pbmi->bmiHeader.biClrImportant = 2; 01273 01274 pbmi->bmiColors[0].rgbBlue = (BYTE)((SYSRGB(DESKTOP) >> 16) & 0xff); 01275 pbmi->bmiColors[0].rgbGreen = (BYTE)((SYSRGB(DESKTOP) >> 8) & 0xff); 01276 pbmi->bmiColors[0].rgbRed = (BYTE)((SYSRGB(DESKTOP) ) & 0xff); 01277 01278 pbmi->bmiColors[1].rgbBlue = (BYTE)((SYSRGB(WINDOWTEXT) >> 16) & 0xff); 01279 pbmi->bmiColors[1].rgbGreen = (BYTE)((SYSRGB(WINDOWTEXT) >> 8) & 0xff); 01280 pbmi->bmiColors[1].rgbRed = (BYTE)((SYSRGB(WINDOWTEXT) ) & 0xff); 01281 01282 hbmMem = GreCreateDIBitmapReal( 01283 HDCBITS(), 0, NULL, 01284 pbmi,DIB_RGB_COLORS,sizeof(bmi),0, 01285 NULL,0,NULL,0,0); 01286 01287 } else { 01288 01289 hbmMem = GreCreateCompatibleBitmap( 01290 HDCBITS(), CXYDESKPATTERN, CXYDESKPATTERN); 01291 } 01292 01293 if (hbmMem) { 01294 01295 if (hbmOldMem = GreSelectBitmap(ghdcMem2, hbmMem)) { 01296 01297 GreSetTextColor(ghdcMem2, SYSRGB(DESKTOP)); 01298 GreSetBkColor(ghdcMem2, SYSRGB(WINDOWTEXT)); 01299 01300 GreBitBlt(ghdcMem2, 01301 0, 01302 0, 01303 CXYDESKPATTERN, 01304 CXYDESKPATTERN, 01305 ghdcMem, 01306 0, 01307 0, 01308 SRCCOPY, 01309 0); 01310 01311 if (hBrushTemp = GreCreatePatternBrush(hbmMem)) { 01312 01313 if (SYSHBR(DESKTOP) != NULL) { 01314 GreMarkDeletableBrush(SYSHBR(DESKTOP)); 01315 GreDeleteObject(SYSHBR(DESKTOP)); 01316 } 01317 01318 GreMarkUndeletableBrush(hBrushTemp); 01319 SYSHBR(DESKTOP) = hBrushTemp; 01320 } 01321 01322 GreSetBrushOwnerPublic(hBrushTemp); 01323 GreSelectBitmap(ghdcMem2, hbmOldMem); 01324 } 01325 01326 GreDeleteObject(hbmMem); 01327 } 01328 01329 GreSelectBitmap(ghdcMem, hbmOldDesk); 01330 } 01331 }

BOOL SetHandleFlag HANDLE  hObject,
DWORD  dwFlag,
BOOL  fSet
 

Definition at line 4494 of file desktop.c.

References tagPROCESSINFO::bmHandleFlags, BOOL, Buffer, EnterHandleFlagsCrit(), FALSE, HF_LIMIT, Index, LeaveHandleFlagsCrit(), NULL, PpiCurrent, RtlClearBits(), RtlInitializeBitMap(), RtlSetBits(), and TRUE.

Referenced by _SetUserObjectInformation(), EnterHandleFlagsCrit(), NtUserOpenInputDesktop(), OpenDesktopCompletion(), xxxCloseDesktop(), xxxCreateDesktop(), xxxGetInputDesktop(), xxxGetThreadDesktop(), xxxOpenDesktop(), xxxSetProcessWindowStation(), and zzzSetDesktop().

04498 { 04499 PPROCESSINFO ppi; 04500 ULONG Index = ((PEXHANDLE)&hObject)->Index * HF_LIMIT + dwFlag; 04501 PRTL_BITMAP pbm; 04502 ULONG cBits; 04503 PULONG Buffer; 04504 BOOL fRet = TRUE; 04505 04506 UserAssert(dwFlag < HF_LIMIT); 04507 04508 EnterHandleFlagsCrit(); 04509 04510 if ((ppi = PpiCurrent()) != NULL) { 04511 pbm = &ppi->bmHandleFlags; 04512 if (fSet) { 04513 04514 /* 04515 * Expand the bitmap if needed 04516 */ 04517 if (Index >= pbm->SizeOfBitMap) { 04518 /* 04519 * Index is zero-based - cBits is an exact number of dwords 04520 */ 04521 cBits = ((Index + 1) + 0x1F) & ~0x1F; 04522 Buffer = UserAllocPoolWithQuotaZInit(cBits / 8, TAG_PROCESSINFO); 04523 if (Buffer == NULL) { 04524 fRet = FALSE; 04525 goto Exit; 04526 } 04527 if (pbm->Buffer) { 04528 RtlCopyMemory(Buffer, pbm->Buffer, pbm->SizeOfBitMap / 8); 04529 UserFreePool(pbm->Buffer); 04530 } 04531 04532 RtlInitializeBitMap(pbm, Buffer, cBits); 04533 } 04534 04535 RtlSetBits(pbm, Index, 1); 04536 } else if (Index < pbm->SizeOfBitMap) { 04537 RtlClearBits(pbm, Index, 1); 04538 } 04539 } 04540 04541 Exit: 04542 LeaveHandleFlagsCrit(); 04543 04544 return fRet; 04545 }

VOID SetHandleInUse HANDLE  hObject  ) 
 

Definition at line 4579 of file desktop.c.

References EnterHandleFlagsCrit(), gHandleInUse, gProcessInUse, LeaveHandleFlagsCrit(), PsGetCurrentProcess, and VOID().

Referenced by NtUserGetObjectInformation(), and NtUserSetObjectInformation().

04581 { 04582 EnterHandleFlagsCrit(); 04583 gProcessInUse = PsGetCurrentProcess(); 04584 gHandleInUse = hObject; 04585 LeaveHandleFlagsCrit(); 04586 }

VOID TerminateConsole PDESKTOP  pdesk  ) 
 

Definition at line 4420 of file desktop.c.

References _PostThreadMessage(), tagDESKTOP::dwConsoleThreadId, LockThreadByClientId(), NT_SUCCESS, NTSTATUS(), NULL, PtiFromThread, Status, UnlockThread, and VOID().

Referenced by DestroyWindowStation(), and UnmapDesktop().

04422 { 04423 NTSTATUS Status; 04424 PETHREAD Thread; 04425 PTHREADINFO pti; 04426 04427 if (pdesk->dwConsoleThreadId == 0) 04428 return; 04429 04430 /* 04431 * Locate the console thread. 04432 */ 04433 Status = LockThreadByClientId((HANDLE)LongToHandle( pdesk->dwConsoleThreadId ), &Thread); 04434 if (!NT_SUCCESS(Status)) 04435 return; 04436 04437 /* 04438 * Post a quit message to the console. 04439 */ 04440 pti = PtiFromThread(Thread); 04441 UserAssert(pti != NULL); 04442 if (pti != NULL) { 04443 _PostThreadMessage(pti, WM_QUIT, 0, 0); 04444 } 04445 04446 /* 04447 * Clear thread id so we don't post twice 04448 */ 04449 pdesk->dwConsoleThreadId = 0; 04450 04451 UnlockThread(Thread); 04452 }

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

Definition at line 3017 of file desktop.c.

References DestroyDesktop(), tagDESKTOP::dwConsoleThreadId, ExDesktopObjectType, FreeView(), gpepCSRSS, OBJECT_TO_OBJECT_HEADER, tagDESKTOP::PtiList, TerminateConsole(), and VOID().

Referenced by Win32UserInitialize().

03023 { 03024 PDESKTOP pdesk = (PDESKTOP)pobj; 03025 03026 BEGIN_REENTERCRIT(); 03027 03028 UserAssert(OBJECT_TO_OBJECT_HEADER(pobj)->Type == *ExDesktopObjectType); 03029 03030 /* 03031 * Update cSystemHandles with the correct information 03032 */ 03033 cSystemHandles = OBJECT_TO_OBJECT_HEADER(pobj)->HandleCount + 1; 03034 03035 /* 03036 * Only unmap the desktop if this is the last process handle and 03037 * the process is not CSR. 03038 */ 03039 if (cProcessHandles == 1 && Process != gpepCSRSS) { 03040 FreeView(Process, pdesk); 03041 } 03042 03043 if (cSystemHandles > 2) 03044 goto Exit; 03045 03046 if (cSystemHandles == 2 && pdesk->dwConsoleThreadId != 0) { 03047 03048 /* 03049 * If a console thread exists and we're down to two handles, 03050 * it means that the last application handle to the 03051 * desktop is being closed. Terminate the console 03052 * thread so the desktop can be freed. 03053 */ 03054 TerminateConsole(pdesk); 03055 } else if (cSystemHandles == 1) { 03056 03057 /* 03058 * If this is the last handle to this desktop in the system, 03059 * destroy the desktop. 03060 */ 03061 03062 /* 03063 * No pti should be linked to this desktop. 03064 */ 03065 if ((&pdesk->PtiList != pdesk->PtiList.Flink) 03066 || (&pdesk->PtiList != pdesk->PtiList.Blink)) { 03067 03068 RIPMSG1(RIP_WARNING, "UnmapDesktop: PtiList not Empty. pdesk:%#p", pdesk); 03069 } 03070 03071 DestroyDesktop(pdesk); 03072 } 03073 03074 Exit: 03075 END_REENTERCRIT(); 03076 03077 UNREFERENCED_PARAMETER(amGranted); 03078 }

BOOL xxxCloseDesktop HDESK  hdesk,
KPROCESSOR_MODE  AccessMode
 

Definition at line 4332 of file desktop.c.

References BOOL, CloseProtectedHandle(), tagDESKTOP::dwSessionId, ExDesktopObjectType, FALSE, gpepCSRSS, gSessionId, tagTHREADINFO::hdesk, tagPROCESSINFO::hdeskStartup, HF_DESKTOPHOOK, LogDesktop, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PpiCurrent, PtiCurrent, tagPROCESSINFO::ptiList, tagTHREADINFO::ptiSibling, tagPROCESSINFO::rpdeskStartup, SetHandleFlag(), Status, TRUE, and UnlockDesktop.

Referenced by NtUserCloseDesktop(), NtUserResolveDesktop(), xxxCreateDesktop(), and xxxCreateDisconnectDesktop().

04335 { 04336 PDESKTOP pdesk; 04337 PTHREADINFO ptiT; 04338 PPROCESSINFO ppi; 04339 NTSTATUS Status; 04340 04341 ppi = PpiCurrent(); 04342 04343 /* 04344 * Get a pointer to the desktop. 04345 */ 04346 Status = ObReferenceObjectByHandle( 04347 hdesk, 04348 0, 04349 *ExDesktopObjectType, 04350 AccessMode, 04351 &pdesk, 04352 NULL); 04353 if (!NT_SUCCESS(Status)) { 04354 RIPNTERR0(Status, RIP_VERBOSE, ""); 04355 return FALSE; 04356 } 04357 04358 UserAssert(pdesk->dwSessionId == gSessionId); 04359 04360 LogDesktop(pdesk, LD_REF_FN_CLOSEDESKTOP, TRUE, (ULONG_PTR)PtiCurrent()); 04361 04362 if (ppi->Process != gpepCSRSS) { 04363 04364 /* 04365 * Disallow closing of the desktop if the handle is in use by 04366 * any threads in the process. 04367 */ 04368 for (ptiT = ppi->ptiList; ptiT != NULL; ptiT = ptiT->ptiSibling) { 04369 if (ptiT->hdesk == hdesk) { 04370 RIPERR2(ERROR_BUSY, RIP_WARNING, 04371 "CloseDesktop: Desktop %#p still in use by thread %#p", 04372 pdesk, ptiT); 04373 LogDesktop(pdesk, LD_DEREF_FN_CLOSEDESKTOP1, FALSE, (ULONG_PTR)PtiCurrent()); 04374 ObDereferenceObject(pdesk); 04375 return FALSE; 04376 } 04377 } 04378 04379 /* 04380 * If this is the startup desktop, unlock it 04381 */ 04382 /* 04383 * Bug 41394. Make sure that hdesk == ppi->hdeskStartup. We might 04384 * be getting a handle to the desktop object that is different 04385 * from ppi->hdeskStartup but we still end up 04386 * setting ppi->hdeskStartup to NULL. 04387 */ 04388 if ((pdesk == ppi->rpdeskStartup) && (hdesk == ppi->hdeskStartup)) { 04389 UnlockDesktop(&ppi->rpdeskStartup, LDU_PPI_DESKSTARTUP2, (ULONG_PTR)ppi); 04390 ppi->hdeskStartup = NULL; 04391 } 04392 } 04393 04394 /* 04395 * Clear hook flag 04396 */ 04397 SetHandleFlag(hdesk, HF_DESKTOPHOOK, FALSE); 04398 04399 /* 04400 * Close the handle 04401 */ 04402 Status = CloseProtectedHandle(hdesk); 04403 04404 LogDesktop(pdesk, LD_DEREF_FN_CLOSEDESKTOP2, FALSE, (ULONG_PTR)PtiCurrent()); 04405 ObDereferenceObject(pdesk); 04406 UserAssert(NT_SUCCESS(Status)); 04407 04408 return TRUE; 04409 }

HDESK xxxCreateDesktop POBJECT_ATTRIBUTES  ccxObjectAttributes,
KPROCESSOR_MODE  ProbeMode,
PUNICODE_STRING  ccxpstrDevice,
LPDEVMODE  ccxlpdevmode,
DWORD  dwFlags,
DWORD  dwDesiredAccess
 

Definition at line 1797 of file desktop.c.

References BeginAtomicCheck, BOOL, CheckCritIn, CleanupDirtyDesktops(), CloseProtectedHandle(), DeferWinEventNotify, DESKTOPCLASS, DF_DESKCREATED, tagDESKTOP::dwDTFlags, _DESKTOP_CONTEXT::dwFlags, dwFlags, DWORD, tagTERMINAL::dwTERMF_Flags, tagWINDOWSTATION::dwWSF_Flags, EndAtomicCheck, EnterCrit, Error, EVENT_INCREMENT, ExDesktopObjectType, ExWindowStationObjectType, FALSE, tagDISPLAYINFO::fDesktopIsRect, fGdiEnabled, gatomMessage, gbRemoteSession, GetDesktopView(), gpepCSRSS, gpEventDiconnectDesktop, gptiRit, grpdeskLogon, grpdeskRitInput, gspdeskDisconnect, gspwndFullScreen, gTermIO, tagTHREADINFO::hdesk, HF_DESKTOPHOOK, HF_PROTECTED, HH_DISCONNECTDESKTOP, HMChangeOwnerThread(), hModuleWin, tagWND::hrgnClip, tagDISPLAYINFO::hrgnScreen, HYDRA_HINT, IsWinEventNotifyDeferredOK, KernelMode, KeSetEvent(), LeaveCrit, LinkWindow(), Lock, LogDesktop, _DESKTOP_CONTEXT::lpDevMode, MapDesktop(), MENUCLASS, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObOpenHandle, ObOpenObjectByName(), ObReferenceObjectByHandle(), tagDESKTOP::pDeskInfo, tagDESKTOP::pDispInfo, tagTERMINAL::pEventInputReady, tagTHREADINFO::ppi, PpiCurrent, PpiFromProcess, tagDESKTOPINFO::ppiShellProcess, _DESKTOP_CONTEXT::pstrDevice, tagWINDOWSTATION::pTerm, PtiCurrent, tagTERMINAL::ptiDesktop, tagTHREADINFO::pwinsta, PWND_BOTTOM, tagDISPLAYINFO::rcScreen, tagTHREADINFO::rpdesk, tagPROCESSINFO::rpdeskStartup, tagDESKTOP::rpwinstaParent, SetFullScreen, SetHandleFlag(), tagDESKTOPINFO::spwnd, tagTERMINAL::spwndDesktopOwner, tagDESKTOP::spwndMenu, tagDESKTOP::spwndMessage, tagWND::spwndOwner, tagWND::spwndParent, tagDESKTOP::spwndTooltip, Status, TERMF_NOIO, ThreadLock, ThreadLockWithPti, ThreadUnlock, TIF_DISABLEHOOKS, tagTHREADINFO::TIF_flags, TOOLTIPCLASS, TRACE_INIT, TRUE, Unlock, UnlockDesktop, UserSleep(), VER31, WSF_NOIO, xxxCloseDesktop(), xxxCreateDisconnectDesktop(), xxxCreateWindowEx(), xxxDestroyWindow(), xxxSetWindowPos(), xxxSwitchDesktop(), zzzEndDeferWinEventNotify, and zzzSetDesktop().

Referenced by NtUserCreateDesktop(), xxxConnectService(), and xxxCreateDisconnectDesktop().

01804 { 01805 HWINSTA hwinsta; 01806 HDESK hdesk; 01807 DESKTOP_CONTEXT Context; 01808 PDESKTOP pdesk; 01809 PDESKTOPINFO pdi; 01810 PWINDOWSTATION pwinsta; 01811 PDESKTOP pdeskTemp; 01812 HDESK hdeskTemp; 01813 PWND pwndDesktop = NULL; 01814 PWND pwndMessage = NULL; 01815 PWND pwndTooltip = NULL; 01816 PWND pwndMenu = NULL; 01817 TL tlpwnd; 01818 PTHREADINFO ptiCurrent = PtiCurrent(); 01819 BOOL fWasNull; 01820 BOOL bSuccess; 01821 PPROCESSINFO ppi; 01822 PPROCESSINFO ppiSave; 01823 PTERMINAL pTerm; 01824 NTSTATUS Status; 01825 DWORD dwDisableHooks; 01826 01827 #if DBG 01828 /* 01829 * Too many jumps in this function to use BEGIN/ENDATOMICHCECK 01830 */ 01831 DWORD dwCritSecUseSave = gdwCritSecUseCount; 01832 #endif 01833 01834 CheckCritIn(); 01835 01836 UserAssert(IsWinEventNotifyDeferredOK()); 01837 01838 /* 01839 * Capture directory handle and check for create access. 01840 */ 01841 try { 01842 hwinsta = ccxObjectAttributes->RootDirectory; 01843 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 01844 return NULL; 01845 } 01846 if (hwinsta != NULL) { 01847 Status = ObReferenceObjectByHandle( 01848 hwinsta, 01849 WINSTA_CREATEDESKTOP, 01850 *ExWindowStationObjectType, 01851 ProbeMode, 01852 &pwinsta, 01853 NULL); 01854 if (NT_SUCCESS(Status)) { 01855 ObDereferenceObject(pwinsta); 01856 } else { 01857 RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed"); 01858 return NULL; 01859 } 01860 } 01861 01862 /* 01863 * Set up creation context 01864 */ 01865 Context.lpDevMode = ccxlpdevmode; 01866 Context.pstrDevice = ccxpstrDevice; 01867 Context.dwFlags = dwFlags; 01868 01869 /* 01870 * Create the desktop -- the object manager uses try blocks 01871 */ 01872 Status = ObOpenObjectByName( 01873 ccxObjectAttributes, 01874 *ExDesktopObjectType, 01875 ProbeMode, 01876 NULL, 01877 dwDesiredAccess, 01878 &Context, 01879 &hdesk); 01880 01881 if (!NT_SUCCESS(Status)) { 01882 01883 RIPNTERR1(Status, 01884 RIP_WARNING, 01885 "xxxCreateDesktop: ObOpenObjectByName failed with Status 0x%x", 01886 Status); 01887 01888 /* 01889 * Cleanup desktop objects that were created in xxxCreateDesktop2 01890 * but later on the Ob manager failed the creation for other 01891 * reasons (ex: no quota) 01892 */ 01893 CleanupDirtyDesktops(); 01894 01895 return NULL; 01896 } 01897 01898 /* 01899 * If the desktop already exists, we're done. This will only happen 01900 * if OBJ_OPENIF was specified. 01901 */ 01902 if (Status == STATUS_OBJECT_NAME_EXISTS) { 01903 SetHandleFlag(hdesk, HF_PROTECTED, TRUE); 01904 RIPMSG0(RIP_WARNING, "xxxCreateDesktop: Object name exists"); 01905 return hdesk; 01906 } 01907 01908 /* 01909 * Reference the desktop to finish initialization 01910 */ 01911 Status = ObReferenceObjectByHandle( 01912 hdesk, 01913 0, 01914 *ExDesktopObjectType, 01915 KernelMode, 01916 &pdesk, 01917 NULL); 01918 if (!NT_SUCCESS(Status)) { 01919 RIPNTERR0(Status, RIP_VERBOSE, ""); 01920 CloseProtectedHandle(hdesk); 01921 return NULL; 01922 } 01923 01924 pdesk->dwDTFlags |= DF_DESKCREATED; 01925 01926 LogDesktop(pdesk, LD_REF_FN_CREATEDESKTOP, TRUE, (ULONG_PTR)PtiCurrent()); 01927 01928 pwinsta = pdesk->rpwinstaParent; 01929 pTerm = pwinsta->pTerm; 01930 pdi = pdesk->pDeskInfo; 01931 01932 pdi->ppiShellProcess = NULL; 01933 01934 /* 01935 * If the desktop was not mapped in as a result of the open, 01936 * fail. 01937 */ 01938 ppi = PpiCurrent(); 01939 if (GetDesktopView(ppi, pdesk) == NULL) { 01940 01941 /* 01942 * Desktop mapping failed. 01943 */ 01944 CloseProtectedHandle(hdesk); 01945 01946 LogDesktop(pdesk, LD_DEREF_FN_CREATEDESKTOP1, FALSE, (ULONG_PTR)PtiCurrent()); 01947 01948 ObDereferenceObject(pdesk); 01949 RIPNTERR0(STATUS_ACCESS_DENIED, RIP_WARNING, "Desktop mapping failed"); 01950 return NULL; 01951 } 01952 01953 if (gpepCSRSS != NULL) { 01954 /* 01955 * Map the desktop into CSRSS to ensure that the 01956 * hard error handler can get access. 01957 */ 01958 try { 01959 MapDesktop(ObOpenHandle, gpepCSRSS, pdesk, 0, 1); 01960 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 01961 01962 /* 01963 * Desktop mapping failed. 01964 */ 01965 CloseProtectedHandle(hdesk); 01966 01967 LogDesktop(pdesk, LD_DEREF_FN_CREATEDESKTOP2, FALSE, (ULONG_PTR)PtiCurrent()); 01968 01969 ObDereferenceObject(pdesk); 01970 RIPNTERR0(STATUS_ACCESS_DENIED, RIP_WARNING, "Desktop mapping failed (2)"); 01971 return NULL; 01972 } 01973 01974 UserAssert(GetDesktopView(PpiFromProcess(gpepCSRSS), pdesk) != NULL); 01975 } 01976 01977 /* 01978 * Set hook flags 01979 */ 01980 SetHandleFlag(hdesk, HF_DESKTOPHOOK, dwFlags & DF_ALLOWOTHERACCOUNTHOOK); 01981 01982 /* 01983 * Set up to create the desktop window. 01984 */ 01985 fWasNull = (ptiCurrent->ppi->rpdeskStartup == NULL); 01986 pdeskTemp = ptiCurrent->rpdesk; // save current desktop 01987 hdeskTemp = ptiCurrent->hdesk; 01988 01989 /* 01990 * Switch ppi values so window will be created using the 01991 * system's desktop window class. 01992 */ 01993 ppiSave = ptiCurrent->ppi; 01994 ptiCurrent->ppi = pTerm->ptiDesktop->ppi; 01995 01996 DeferWinEventNotify(); 01997 BeginAtomicCheck(); 01998 01999 zzzSetDesktop(ptiCurrent, pdesk, hdesk); 02000 02001 /* 02002 * Create the desktop window 02003 */ 02004 /* 02005 * HACK HACK HACK!!! (adams) In order to create the desktop window 02006 * with the correct desktop, we set the desktop of the current thread 02007 * to the new desktop. But in so doing we allow hooks on the current 02008 * thread to also hook this new desktop. This is bad, because we don't 02009 * want the desktop window to be hooked while it is created. So we 02010 * temporarily disable hooks of the current thread and its desktop, 02011 * and reenable them after switching back to the original desktop. 02012 */ 02013 02014 dwDisableHooks = ptiCurrent->TIF_flags & TIF_DISABLEHOOKS; 02015 ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS; 02016 02017 pwndDesktop = xxxCreateWindowEx( 02018 (DWORD)0, 02019 (PLARGE_STRING)DESKTOPCLASS, 02020 NULL, 02021 (WS_POPUP | WS_CLIPCHILDREN), 02022 pdesk->pDispInfo->rcScreen.left, 02023 pdesk->pDispInfo->rcScreen.top, 02024 pdesk->pDispInfo->rcScreen.right - pdesk->pDispInfo->rcScreen.left, 02025 pdesk->pDispInfo->rcScreen.bottom - pdesk->pDispInfo->rcScreen.top, 02026 NULL, 02027 NULL, 02028 hModuleWin, 02029 NULL, 02030 VER31); 02031 02032 if (pwndDesktop == NULL) { 02033 RIPMSG1(RIP_WARNING, 02034 "xxxCreateDesktop: Failed to create the desktop window for pdesk %#p", 02035 pdesk); 02036 goto Error; 02037 } 02038 02039 /* 02040 * NOTE: In order for the message window to be created without 02041 * the desktop as it's owner, it needs to be created before 02042 * setting pdi->spwnd to the desktop window. This is a complete 02043 * hack and should be fixed. 02044 */ 02045 pwndMessage = xxxCreateWindowEx( 02046 (DWORD)0, 02047 (PLARGE_STRING)gatomMessage, 02048 NULL, 02049 (WS_POPUP | WS_CLIPCHILDREN), 02050 0, 02051 0, 02052 100, 02053 100, 02054 NULL, 02055 NULL, 02056 hModuleWin, 02057 NULL, 02058 VER31); 02059 02060 if (pwndMessage == NULL) { 02061 RIPMSG0(RIP_WARNING, "xxxCreateDesktop: Failed to create the message window"); 02062 goto Error; 02063 } 02064 02065 UserAssert(pdi->spwnd == NULL); 02066 02067 Lock(&(pdi->spwnd), pwndDesktop); 02068 02069 SetFullScreen(pwndDesktop, GDIFULLSCREEN); 02070 02071 /* 02072 * set this windows to the fullscreen window if we don't have one yet 02073 */ 02074 02075 /* 02076 * LATER mikeke 02077 * this can be a problem if a desktop is created while we are in 02078 * FullScreenCleanup() 02079 */ 02080 02081 /* 02082 * Don't set gspwndFullScreen if fGdiEnabled has been cleared 02083 * (we may be in the middle of a disconnect). 02084 */ 02085 UserAssert(fGdiEnabled == TRUE); 02086 02087 if (gspwndFullScreen == NULL && !(pwinsta->dwWSF_Flags & WSF_NOIO)) { 02088 Lock(&(gspwndFullScreen), pwndDesktop); 02089 } 02090 02091 /* 02092 * NT Bug 388747: Link the message window to the mother desktop window 02093 * so that it properly has a parent. We will do this before we link the 02094 * desktop window just so the initial message window appears after the 02095 * initial desktop window (a minor optimization, but not necessary). 02096 */ 02097 Lock(&pwndMessage->spwndParent, pTerm->spwndDesktopOwner); 02098 LinkWindow(pwndMessage, NULL, pTerm->spwndDesktopOwner); 02099 Lock(&pdesk->spwndMessage, pwndMessage); 02100 Unlock(&pwndMessage->spwndOwner); 02101 02102 /* 02103 * Link it as a child but don't use WS_CHILD style 02104 */ 02105 LinkWindow(pwndDesktop, NULL, pTerm->spwndDesktopOwner); 02106 Lock(&pwndDesktop->spwndParent, pTerm->spwndDesktopOwner); 02107 Unlock(&pwndDesktop->spwndOwner); 02108 02109 /* 02110 * Make it regional if it's display configuration is regional. 02111 */ 02112 if (!pdesk->pDispInfo->fDesktopIsRect) { 02113 pwndDesktop->hrgnClip = pdesk->pDispInfo->hrgnScreen; 02114 } 02115 02116 /* 02117 * Create shared menu window and tooltip window 02118 */ 02119 ThreadLock(pdesk->spwndMessage, &tlpwnd); 02120 02121 /* 02122 * Create the tooltip window only for desktops in 02123 * interactive windowstations. 02124 */ 02125 if (!(pwinsta->dwWSF_Flags & WSF_NOIO)) { 02126 pwndTooltip = xxxCreateWindowEx( 02127 WS_EX_TOOLWINDOW | WS_EX_TOPMOST, 02128 (PLARGE_STRING)TOOLTIPCLASS, 02129 NULL, 02130 WS_POPUP | WS_BORDER, 02131 0, 02132 0, 02133 100, 02134 100, 02135 pdesk->spwndMessage, 02136 NULL, 02137 hModuleWin, 02138 NULL, 02139 VER31); 02140 02141 02142 if (pwndTooltip == NULL) { 02143 ThreadUnlock(&tlpwnd); 02144 RIPMSG0(RIP_WARNING, "xxxCreateDesktop: Failed to create the tooltip window"); 02145 goto Error; 02146 } 02147 02148 Lock(&pdesk->spwndTooltip, pwndTooltip); 02149 } 02150 02151 pwndMenu = xxxCreateWindowEx( 02152 WS_EX_TOOLWINDOW | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE, 02153 (PLARGE_STRING)MENUCLASS, 02154 NULL, 02155 WS_POPUP | WS_BORDER, 02156 0, 02157 0, 02158 100, 02159 100, 02160 pdesk->spwndMessage, 02161 NULL, 02162 hModuleWin, 02163 NULL, 02164 WINVER); 02165 02166 ThreadUnlock(&tlpwnd); 02167 02168 if (pwndMenu == NULL) { 02169 RIPMSG0(RIP_WARNING, "xxxCreateDesktop: Failed to create the menu window"); 02170 goto Error; 02171 } 02172 02173 Lock(&(pdesk->spwndMenu), pwndMenu); 02174 02175 /* 02176 * Set the flag in the popupmenu structure that tells this 02177 * popup menu belongs to the pdesk->spwndMenu 02178 */ 02179 ((PMENUWND)pdesk->spwndMenu)->ppopupmenu->fDesktopMenu = TRUE; 02180 /* 02181 * Unlock spwndPopupMenu since the menu is not in use but mainly 02182 * so we won't have to special case this later when the menu is used. 02183 */ 02184 Unlock(&((PMENUWND)pdesk->spwndMenu)->ppopupmenu->spwndPopupMenu); 02185 02186 HMChangeOwnerThread(pdi->spwnd, pTerm->ptiDesktop); 02187 HMChangeOwnerThread(pwndMessage, pTerm->ptiDesktop); 02188 HMChangeOwnerThread(pdesk->spwndMenu, pTerm->ptiDesktop); 02189 02190 if (!(pwinsta->dwWSF_Flags & WSF_NOIO)) { 02191 HMChangeOwnerThread(pwndTooltip, pTerm->ptiDesktop); 02192 } 02193 02194 /* 02195 * Restore caller's ppi 02196 */ 02197 PtiCurrent()->ppi = ppiSave; 02198 02199 /* 02200 * HACK HACK HACK (adams): Renable hooks. 02201 */ 02202 UserAssert(ptiCurrent->TIF_flags & TIF_DISABLEHOOKS); 02203 ptiCurrent->TIF_flags = (ptiCurrent->TIF_flags & ~TIF_DISABLEHOOKS) | dwDisableHooks; 02204 02205 /* 02206 * Restore the previous desktop 02207 */ 02208 zzzSetDesktop(ptiCurrent, pdeskTemp, hdeskTemp); 02209 02210 EndAtomicCheck(); 02211 UserAssert(dwCritSecUseSave == gdwCritSecUseCount); 02212 zzzEndDeferWinEventNotify(); 02213 02214 /* 02215 * If this is the first desktop, let the worker threads run now 02216 * that there is someplace to send input to. Reassign the event 02217 * to handle desktop destruction. 02218 */ 02219 if (pTerm->pEventInputReady != NULL) { 02220 02221 /* 02222 * Set the windowstation for RIT and desktop thread 02223 * so when EventInputReady is signaled the RIT and the desktop 02224 * will have a windowstation. 02225 */ 02226 if (!(pTerm->dwTERMF_Flags & TERMF_NOIO)) { 02227 gptiRit->pwinsta = pwinsta; 02228 } else { 02229 /* 02230 * let the desktop thread of the system terminal have 02231 * a rpdesk. 02232 */ 02233 zzzSetDesktop(pTerm->ptiDesktop, pdesk, NULL); 02234 } 02235 02236 pTerm->ptiDesktop->pwinsta = pwinsta; 02237 02238 KeSetEvent(pTerm->pEventInputReady, EVENT_INCREMENT, FALSE); 02239 02240 if (!(pTerm->dwTERMF_Flags & TERMF_NOIO)) { 02241 02242 LeaveCrit(); 02243 while (grpdeskRitInput == NULL) { 02244 UserSleep(20); 02245 RIPMSG0(RIP_WARNING, "Waiting for grpdeskRitInput to be set ..."); 02246 } 02247 EnterCrit(); 02248 } 02249 02250 ObDereferenceObject(pTerm->pEventInputReady); 02251 pTerm->pEventInputReady = NULL; 02252 } 02253 02254 02255 /* 02256 * HACK HACK: 02257 * LATER 02258 * 02259 * If we have a devmode passed in, then switch desktops ... 02260 */ 02261 02262 if (ccxlpdevmode) { 02263 02264 TRACE_INIT(("xxxCreateDesktop: about to call switch desktop\n")); 02265 02266 bSuccess = xxxSwitchDesktop(pwinsta, pdesk, TRUE); 02267 if (!bSuccess) { 02268 RIPMSG0(RIP_ERROR, "Failed to switch desktop on Create\n"); 02269 } 02270 02271 } else if (pTerm == &gTermIO){ 02272 02273 UserAssert(grpdeskRitInput != NULL); 02274 02275 /* 02276 * Force the window to the bottom of the z-order if there 02277 * is an active desktop so any drawing done on the desktop 02278 * window will not be seen. This will also allow 02279 * IsWindowVisible to work for apps on invisible 02280 * desktops. 02281 */ 02282 ThreadLockWithPti(ptiCurrent, pwndDesktop, &tlpwnd); 02283 xxxSetWindowPos(pwndDesktop, PWND_BOTTOM, 0, 0, 0, 0, 02284 SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | 02285 SWP_NOREDRAW | SWP_NOSIZE | SWP_NOSENDCHANGING); 02286 ThreadUnlock(&tlpwnd); 02287 } 02288 02289 /* 02290 * If it was null when we came in, make it null going out, or else 02291 * we'll have the wrong desktop selected into this. 02292 */ 02293 if (fWasNull) 02294 UnlockDesktop(&ptiCurrent->ppi->rpdeskStartup, 02295 LDU_PPI_DESKSTARTUP1, (ULONG_PTR)(ptiCurrent->ppi)); 02296 02297 if (gbRemoteSession && 02298 gspdeskDisconnect == NULL && 02299 pdesk == grpdeskLogon) { 02300 02301 UserAssert(hdesk != NULL); 02302 02303 /* 02304 * Create the 'disconnect' desktop 02305 */ 02306 if (!xxxCreateDisconnectDesktop(hwinsta, pwinsta)) { 02307 RIPMSG0(RIP_WARNING, "Failed to create the 'disconnect' desktop"); 02308 02309 LogDesktop(pdesk, LD_DEREF_FN_CREATEDESKTOP3, FALSE, (ULONG_PTR)PtiCurrent()); 02310 ObDereferenceObject(pdesk); 02311 02312 xxxCloseDesktop(hdesk, KernelMode); 02313 02314 return NULL; 02315 } 02316 02317 /* 02318 * Signal that the disconnect desktop got created. 02319 */ 02320 KeSetEvent(gpEventDiconnectDesktop, EVENT_INCREMENT, FALSE); 02321 02322 HYDRA_HINT(HH_DISCONNECTDESKTOP); 02323 } 02324 02325 Cleanup: 02326 02327 LogDesktop(pdesk, LD_DEREF_FN_CREATEDESKTOP3, FALSE, (ULONG_PTR)PtiCurrent()); 02328 ObDereferenceObject(pdesk); 02329 02330 TRACE_INIT(("xxxCreateDesktop: Leaving\n")); 02331 02332 if (hdesk != NULL) { 02333 SetHandleFlag(hdesk, HF_PROTECTED, TRUE); 02334 } 02335 return hdesk; 02336 02337 Error: 02338 02339 EndAtomicCheck(); 02340 UserAssert(dwCritSecUseSave == gdwCritSecUseCount); 02341 zzzEndDeferWinEventNotify(); 02342 02343 UserAssert(pwndMenu == NULL); 02344 02345 if (pwndTooltip != NULL) { 02346 xxxDestroyWindow(pwndTooltip); 02347 Unlock(&pdesk->spwndTooltip); 02348 } 02349 if (pwndMessage != NULL) { 02350 xxxDestroyWindow(pwndMessage); 02351 Unlock(&pdesk->spwndMessage); 02352 } 02353 if (pwndDesktop != NULL) { 02354 xxxDestroyWindow(pwndDesktop); 02355 Unlock(&pdi->spwnd); 02356 Unlock(&gspwndFullScreen); 02357 } 02358 /* 02359 * Restore caller's ppi 02360 */ 02361 PtiCurrent()->ppi = ppiSave; 02362 02363 UserAssert(ptiCurrent->TIF_flags & TIF_DISABLEHOOKS); 02364 ptiCurrent->TIF_flags = (ptiCurrent->TIF_flags & ~TIF_DISABLEHOOKS) | dwDisableHooks; 02365 zzzSetDesktop(ptiCurrent, pdeskTemp, hdeskTemp); 02366 02367 CloseProtectedHandle(hdesk); 02368 hdesk = NULL; 02369 02370 /* 02371 * If it was null when we came in, make it null going out, or else 02372 * we'll have the wrong desktop selected into this. 02373 */ 02374 if (fWasNull) 02375 UnlockDesktop(&ptiCurrent->ppi->rpdeskStartup, 02376 LDU_PPI_DESKSTARTUP1, (ULONG_PTR)(ptiCurrent->ppi)); 02377 02378 goto Cleanup; 02379 02380 }

NTSTATUS xxxCreateDesktop2 PWINDOWSTATION  pwinsta,
PACCESS_STATE  pAccessState,
KPROCESSOR_MODE  AccessMode,
PUNICODE_STRING  pstrName,
PDESKTOP_CONTEXT  Context,
PVOID *  pObject
 

Definition at line 1343 of file desktop.c.

References BOOL, CheckCritIn, CopyRect, CreateDesktopHeap(), DbgTrackAddDesktop, DESKTOP, DesktopAlloc(), DesktopMapping, DISPLAYINFO, tagDISPLAYINFO::dmLogPixels, DTAG_DESKTOPINFO, tagDESKTOP::dwDesktopId, tagDESKTOP::dwSessionId, tagWINDOWSTATION::dwWSF_Flags, Error, ExDesktopObjectType, FALSE, gbRemoteSession, gdwDesktopId, gdwDesktopSectionSize, gdwNOIOSectionSize, GetProcessLuid(), gpDispInfo, gpidLogon, grpdeskLogon, gSessionId, gspdeskDisconnect, GW_DESKTOP_ID, tagDISPLAYINFO::hDev, tagWND::head, tagDESKTOP::hsectionDesktop, KernelMode, LockDesktop, LockWinSta, LogDesktop, _DESKTOP_CONTEXT::lpDevMode, tagWINDOWSTATION::luidEndSession, NT_SUCCESS, NTSTATUS(), NULL, ObAssignSecurity(), ObCheckCreateObjectAccess(), ObCreateObject(), ObDereferenceObject, OBJECT_TO_OBJECT_HEADER, ObjectAttributes, PBYTE, tagDESKTOP::pDeskInfo, tagDESKTOP::pDispInfo, tagDESKTOP::pheapDesktop, tagDISPLAYINFO::pmdev, tagDISPLAYINFO::pMonitorFirst, tagDISPLAYINFO::pMonitorPrimary, PsGetCurrentProcess, _DESKTOP_CONTEXT::pstrDevice, tagWINDOWSTATION::pTerm, tagDESKTOP::PtiList, tagDESKTOPINFO::pvDesktopBase, tagDESKTOPINFO::pvDesktopLimit, tagDESKTOPINFO::pvwplShellHook, tagDISPLAYINFO::rcScreen, _ACCESS_STATE::RemainingDesiredAccess, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, tagDESKTOP::rpwinstaParent, RtlEqualLuid(), RtlMapGenericMask(), tagTERMINAL::spwndDesktopOwner, Status, TRUE, _EPROCESS::UniqueProcessId, UserMode, WSF_NOIO, WSF_OPENLOCK, WSF_SHUTDOWN, and xxxUserResetDisplayDevice().

Referenced by ParseDesktop().

01350 { 01351 LUID luidCaller; 01352 OBJECT_ATTRIBUTES ObjectAttributes; 01353 PEPROCESS Process; 01354 PDESKTOP pdesk; 01355 PDESKTOPINFO pdi; 01356 ULONG ulHeapSize; 01357 NTSTATUS Status; 01358 01359 CheckCritIn(); 01360 01361 /* 01362 * If this is a desktop creation, make sure 01363 * that the windowstation grants create access. 01364 */ 01365 if (!ObCheckCreateObjectAccess( 01366 pwinsta, 01367 WINSTA_CREATEDESKTOP, 01368 pAccessState, 01369 pstrName, 01370 TRUE, 01371 AccessMode, 01372 &Status)) { 01373 01374 return Status; 01375 } 01376 /* 01377 * Fail if the windowstation is locked 01378 */ 01379 Process = PsGetCurrentProcess(); 01380 01381 if (pwinsta->dwWSF_Flags & WSF_OPENLOCK && 01382 Process->UniqueProcessId != gpidLogon) { 01383 01384 /* 01385 * If logoff is occuring and the caller does not 01386 * belong to the session that is ending, allow the 01387 * open to proceed. 01388 */ 01389 Status = GetProcessLuid(NULL, &luidCaller); 01390 01391 if (!NT_SUCCESS(Status) || 01392 !(pwinsta->dwWSF_Flags & WSF_SHUTDOWN) || 01393 RtlEqualLuid(&luidCaller, &pwinsta->luidEndSession)) { 01394 return STATUS_DEVICE_BUSY; 01395 } 01396 } 01397 01398 /* 01399 * If a devmode has been specified, we also must be able 01400 * to switch desktops. 01401 */ 01402 if (Context->lpDevMode != NULL && (pwinsta->dwWSF_Flags & WSF_OPENLOCK) && 01403 Process->UniqueProcessId != gpidLogon) { 01404 return STATUS_DEVICE_BUSY; 01405 } 01406 01407 /* 01408 * Allocate the new object 01409 */ 01410 InitializeObjectAttributes(&ObjectAttributes, pstrName, 0, NULL, NULL); 01411 Status = ObCreateObject( 01412 KernelMode, 01413 *ExDesktopObjectType, 01414 &ObjectAttributes, 01415 UserMode, 01416 NULL, 01417 sizeof(DESKTOP), 01418 0, 01419 0, 01420 &pdesk); 01421 if (!NT_SUCCESS(Status)) { 01422 RIPMSG1(RIP_WARNING, "xxxCreateDesktop2: ObCreateObject failed with Status 0x%x", 01423 Status); 01424 return Status; 01425 } 01426 RtlZeroMemory(pdesk, sizeof(DESKTOP)); 01427 01428 /* 01429 * Store the session id of the session who created the desktop 01430 */ 01431 pdesk->dwSessionId = gSessionId; 01432 01433 /* 01434 * Create security descriptor 01435 */ 01436 Status = ObAssignSecurity( 01437 pAccessState, 01438 OBJECT_TO_OBJECT_HEADER(pwinsta)->SecurityDescriptor, 01439 pdesk, 01440 *ExDesktopObjectType); 01441 01442 if (!NT_SUCCESS(Status)) 01443 goto Error; 01444 01445 /* 01446 * Set up desktop heap. The first desktop (logon desktop) uses a 01447 * small heap (128). 01448 */ 01449 if (!(pwinsta->dwWSF_Flags & WSF_NOIO) && (pwinsta->rpdeskList == NULL)) { 01450 #ifdef _WIN64 01451 /* 01452 * Temporary fix. When winlogon starts creating processes on the right 01453 * desktop, we'll have to figure out what this size should really be. 01454 */ 01455 ulHeapSize = gdwDesktopSectionSize; 01456 #else 01457 ulHeapSize = 128; 01458 #endif 01459 } else { 01460 if (pwinsta->dwWSF_Flags & WSF_NOIO) { 01461 ulHeapSize = gdwNOIOSectionSize; 01462 } else { 01463 01464 /* 01465 * The disconnected desktop should be small also. 01466 */ 01467 if (gbRemoteSession && gspdeskDisconnect == NULL) 01468 ulHeapSize = 64; 01469 else 01470 ulHeapSize = gdwDesktopSectionSize; 01471 } 01472 } 01473 01474 ulHeapSize *= 1024; 01475 /* 01476 * Create the desktop heap. 01477 */ 01478 pdesk->hsectionDesktop = CreateDesktopHeap(&pdesk->pheapDesktop, ulHeapSize); 01479 if (pdesk->hsectionDesktop == NULL) { 01480 RIPMSG1(RIP_WARNING, "xxxCreateDesktop: CreateDesktopHeap failed for pdesk %#p", 01481 pdesk); 01482 goto ErrorOutOfMemory; 01483 } 01484 01485 if (pwinsta->rpdeskList == NULL || (pwinsta->dwWSF_Flags & WSF_NOIO)) { 01486 01487 /* 01488 * The first desktop or invisible desktops must also 01489 * use the default settings. This is because specifying 01490 * the devmode causes a desktop switch, which must be 01491 * avoided in this case. 01492 */ 01493 Context->lpDevMode = NULL; 01494 } 01495 01496 /* 01497 * Allocate desktopinfo 01498 */ 01499 pdi = (PDESKTOPINFO)DesktopAlloc(pdesk, sizeof(DESKTOPINFO), DTAG_DESKTOPINFO); 01500 if (pdi == NULL) { 01501 RIPMSG0(RIP_WARNING, "xxxCreateDesktop: failed DeskInfo Alloc"); 01502 goto ErrorOutOfMemory; 01503 } 01504 01505 /* 01506 * Initialize everything. 01507 */ 01508 pdesk->pDeskInfo = pdi; 01509 InitializeListHead(&pdesk->PtiList); 01510 01511 /* 01512 * If a DEVMODE or another device name is passed in, then use that 01513 * information. 01514 * Otherwise use the default information (gpDispInfo). 01515 */ 01516 01517 if (Context->lpDevMode) { 01518 01519 BOOL bDisabled = FALSE; 01520 PMDEV pmdev = NULL; 01521 LONG ChangeStat = GRE_DISP_CHANGE_FAILED; 01522 01523 /* 01524 * Allocate a display-info for this device. 01525 */ 01526 pdesk->pDispInfo = (PDISPLAYINFO)UserAllocPoolZInit( 01527 sizeof(DISPLAYINFO), TAG_DISPLAYINFO); 01528 01529 if (!pdesk->pDispInfo) { 01530 RIPMSG1(RIP_WARNING, "xxxCreateDesktop: failed to allocate pDispInfo for pdesk %#p", 01531 pdesk); 01532 goto ErrorOutOfMemory; 01533 } 01534 01535 if ((bDisabled = DrvDisableMDEV(gpDispInfo->pmdev, TRUE)) == TRUE) { 01536 01537 ChangeStat = DrvChangeDisplaySettings(Context->pstrDevice, 01538 NULL, 01539 Context->lpDevMode, 01540 LongToPtr( gdwDesktopId ), 01541 UserMode, 01542 FALSE, 01543 TRUE, 01544 NULL, 01545 &pmdev, 01546 GRE_DEFAULT, 01547 FALSE); 01548 } 01549 01550 if (ChangeStat != GRE_DISP_CHANGE_SUCCESSFUL) { 01551 01552 if (bDisabled) { 01553 DrvEnableMDEV(gpDispInfo->pmdev, TRUE); 01554 } 01555 01556 // 01557 // If there is a failure, then repaint the whole screen. 01558 // 01559 01560 RIPMSG1(RIP_WARNING, "xxxCreateDesktop2 callback for pdesk %#p !", 01561 pdesk); 01562 01563 xxxUserResetDisplayDevice(); 01564 01565 Status = STATUS_UNSUCCESSFUL; 01566 goto Error; 01567 } 01568 01569 pdesk->pDispInfo->hDev = pmdev->hdevParent; 01570 pdesk->pDispInfo->pmdev = pmdev; 01571 pdesk->dwDesktopId = gdwDesktopId++; 01572 01573 CopyRect(&pdesk->pDispInfo->rcScreen, &gpDispInfo->rcScreen); 01574 pdesk->pDispInfo->dmLogPixels = gpDispInfo->dmLogPixels; 01575 01576 pdesk->pDispInfo->pMonitorFirst = NULL; 01577 pdesk->pDispInfo->pMonitorPrimary = NULL; 01578 01579 } else { 01580 01581 pdesk->pDispInfo = gpDispInfo; 01582 pdesk->dwDesktopId = GW_DESKTOP_ID; 01583 01584 } 01585 01586 /* 01587 * Heap is HEAP_ZERO_MEMORY, so we should be zero-initialized already. 01588 */ 01589 UserAssert(pdi->pvwplShellHook == NULL); 01590 01591 pdi->pvDesktopBase = Win32HeapGetHandle(pdesk->pheapDesktop); 01592 pdi->pvDesktopLimit = (PBYTE)pdi->pvDesktopBase + ulHeapSize; 01593 01594 /* 01595 * Reference the parent windowstation 01596 */ 01597 LockWinSta(&(pdesk->rpwinstaParent), pwinsta); 01598 01599 /* 01600 * Link the desktop into the windowstation list 01601 */ 01602 if (pwinsta->rpdeskList == NULL) { 01603 01604 if (!(pwinsta->dwWSF_Flags & WSF_NOIO)) 01605 LockDesktop(&grpdeskLogon, pdesk, LDL_DESKLOGON, 0); 01606 /* 01607 * Make the first desktop the "owner" of the top 01608 * desktop window. This is needed to ensure that 01609 * xxxSetWindowPos will work on desktop windows. 01610 */ 01611 LockDesktop(&(pwinsta->pTerm->spwndDesktopOwner->head.rpdesk), 01612 pdesk, LDL_MOTHERDESK_DESK2, (ULONG_PTR)(pwinsta->pTerm->spwndDesktopOwner)); 01613 } 01614 01615 01616 LockDesktop(&pdesk->rpdeskNext, pwinsta->rpdeskList, LDL_DESK_DESKNEXT1, (ULONG_PTR)pwinsta); 01617 LockDesktop(&pwinsta->rpdeskList, pdesk, LDL_WINSTA_DESKLIST1, (ULONG_PTR)pwinsta); 01618 01619 /* 01620 * Mask off invalid access bits 01621 */ 01622 if (pAccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED) { 01623 pAccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED; 01624 pAccessState->RemainingDesiredAccess |= GENERIC_ALL; 01625 } 01626 01627 RtlMapGenericMask( &pAccessState->RemainingDesiredAccess, (PGENERIC_MAPPING)&DesktopMapping); 01628 pAccessState->RemainingDesiredAccess &= 01629 (DesktopMapping.GenericAll | ACCESS_SYSTEM_SECURITY); 01630 01631 *pObject = pdesk; 01632 01633 /* 01634 * Add the desktop to the global list of desktops in this win32k. 01635 * This is HYDRA only 01636 */ 01637 DbgTrackAddDesktop(pdesk); 01638 01639 return STATUS_SUCCESS; 01640 01641 ErrorOutOfMemory: 01642 Status = STATUS_NO_MEMORY; 01643 // fall-through 01644 01645 Error: 01646 LogDesktop(pdesk, LD_DEREF_FN_2CREATEDESKTOP, FALSE, 0); 01647 ObDereferenceObject(pdesk); 01648 01649 UserAssert(!NT_SUCCESS(Status)); 01650 01651 return Status; 01652 }

BOOL xxxCreateDisconnectDesktop HWINSTA  hwinsta,
PWINDOWSTATION  pwinsta
 

Definition at line 1654 of file desktop.c.

References BOOL, CloseProtectedHandle(), CreateEmptyRgn(), FALSE, gbConnected, ghDisconnectDesk, ghDisconnectWinSta, gpepCSRSS, gspdeskDisconnect, KeAttachProcess(), KeDetachProcess(), KernelMode, LogDesktop, NT_SUCCESS, NTSTATUS(), NULL, ObOpenObjectByPointer(), ObReferenceObjectByHandle(), _EPROCESS::Pcb, tagDESKTOP::pDeskInfo, RtlInitUnicodeString(), SelectWindowRgn(), tagDESKTOPINFO::spwnd, Status, TRUE, xxxCloseDesktop(), and xxxCreateDesktop().

Referenced by xxxCreateDesktop().

01657 { 01658 UNICODE_STRING strDesktop; 01659 OBJECT_ATTRIBUTES oa; 01660 HDESK hdeskDisconnect; 01661 HRGN hrgn; 01662 NTSTATUS Status; 01663 01664 /* 01665 * If not created yet, then create the Disconnected desktop 01666 * (used when WinStation is disconnected), and lock the desktop 01667 * and desktop window to ensure they never get deleted. 01668 */ 01669 RtlInitUnicodeString(&strDesktop, TEXT("Disconnect")); 01670 InitializeObjectAttributes(&oa, &strDesktop, 01671 OBJ_OPENIF | OBJ_CASE_INSENSITIVE, hwinsta, NULL); 01672 01673 hdeskDisconnect = xxxCreateDesktop(&oa, KernelMode, 01674 NULL, NULL, 0, MAXIMUM_ALLOWED); 01675 01676 if (hdeskDisconnect == NULL) { 01677 RIPMSG0(RIP_WARNING, "Could not create Disconnect desktop"); 01678 return FALSE; 01679 } 01680 01681 /* 01682 * Keep around an extra reference to the disconnect desktop from 01683 * the CSR so it will stay around even if winlogon exits. 01684 */ 01685 Status = ObReferenceObjectByHandle(hdeskDisconnect, 01686 0, 01687 NULL, 01688 KernelMode, 01689 &gspdeskDisconnect, 01690 NULL); 01691 if (!NT_SUCCESS(Status)) { 01692 01693 RIPMSG1(RIP_WARNING, "Disconnect Desktop reference failed 0x%x", Status); 01694 01695 xxxCloseDesktop(hdeskDisconnect, KernelMode); 01696 gspdeskDisconnect = NULL; 01697 return FALSE; 01698 } 01699 01700 LogDesktop(gspdeskDisconnect, LDL_DESKDISCONNECT, TRUE, 0); 01701 01702 /* 01703 * Set the region of the desktop window to be (0, 0, 0, 0) so 01704 * that there is no hittesting going on the 'disconnect' desktop 01705 */ 01706 hrgn = CreateEmptyRgn(); 01707 01708 UserAssert(gspdeskDisconnect->pDeskInfo != NULL); 01709 01710 SelectWindowRgn(gspdeskDisconnect->pDeskInfo->spwnd, hrgn); 01711 01712 KeAttachProcess(&gpepCSRSS->Pcb); 01713 01714 Status = ObOpenObjectByPointer( 01715 gspdeskDisconnect, 01716 0, 01717 NULL, 01718 EVENT_ALL_ACCESS, 01719 NULL, 01720 KernelMode, 01721 &ghDisconnectDesk); 01722 01723 if (NT_SUCCESS(Status)) { 01724 01725 Status = ObOpenObjectByPointer( 01726 pwinsta, 01727 0, 01728 NULL, 01729 EVENT_ALL_ACCESS, 01730 NULL, 01731 KernelMode, 01732 &ghDisconnectWinSta); 01733 } 01734 01735 KeDetachProcess(); 01736 01737 if (!NT_SUCCESS(Status)) { 01738 01739 RIPMSG0(RIP_WARNING, "Could not create Disconnect desktop"); 01740 01741 if (ghDisconnectDesk != NULL) { 01742 CloseProtectedHandle(ghDisconnectDesk); 01743 ghDisconnectDesk = NULL; 01744 } 01745 01746 xxxCloseDesktop(hdeskDisconnect, KernelMode); 01747 return FALSE; 01748 } 01749 01750 /* 01751 * Don't want to do alot of paints if we disconnected before this. 01752 */ 01753 if (!gbConnected) { 01754 RIPMSG0(RIP_WARNING, 01755 "RemoteDisconnect was issued during CreateDesktop(\"Winlogon\"..."); 01756 } 01757 01758 return TRUE; 01759 }

VOID xxxDesktopThread PTERMINAL  pTerm  ) 
 

Definition at line 114 of file desktop.c.

References _DestroyMenu(), aDeviceTemplate, CheckCritIn, ClearWakeBit(), tagQ::cLockCount, CMSHUNGAPPTIMEOUT, CreateKernelEvent(), tagTHREADINFO::cWindows, DEVICE_TYPE_MOUSE, DF_DESKWNDDESTROYED, DF_DYING, DF_MOUSEMOVETRK, DF_TOOLTIPSHOWING, diStatic, tagDESKTOP::dwDTFlags, DWORD, tagTERMINAL::dwTERMF_Flags, tagWINDOWSTATION::dwWSF_Flags, EnterCrit, EVENT_INCREMENT, ExEventObjectType, FALSE, FHungApp(), FindNCHit(), FreeKernelEvent(), gbRemoteSession, GETPTI, glinp, gpDispInfo, gpEventHungThread, gpevtDesktopDestroyed, grpdeskLogon, grpdeskRitInput, grpWinStaList, gspdeskDisconnect, gspwndFullScreen, gspwndMouseOwner, gspwndShouldBeForeground, tagTHREADINFO::hdesk, tagDISPLAYINFO::hDev, HWq, InitSystemThread(), ISTS, IsWinEventNotifyDeferredOK, KernelMode, KeSetEvent(), KeWaitForSingleObject(), L, LeaveCrit, LockDesktop, msg, MSGWAITCALLBACK, NT_SUCCESS, NULL, ObDereferenceObject, OBJECTS_COUNT, ObReferenceObjectByPointer(), tagTHREADINFO::pDeskInfo, tagDESKTOP::pDeskInfo, tagDESKTOP::pDispInfo, tagTERMINAL::pEventDestroyDesktop, tagTERMINAL::pEventInputReady, tagTERMINAL::pEventTermInit, tagDEVICE_TEMPLATE::pkeHidChange, tagDISPLAYINFO::pmdev, PMENUWND, tagDISPLAYINFO::pMonitorFirst, PostShellHookMessages(), tagTHREADINFO::pq, tagTERMINAL::pqDesktop, ProcessDeviceChanges(), PsTerminateSystemThread(), PtiCurrentShared, tagTERMINAL::ptiDesktop, tagLASTINPUT::ptLastClick, tagTHREADINFO::pwinsta, RemoteDisableScreen(), tagTHREADINFO::rpdesk, tagTERMINAL::rpdeskDestroy, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, tagWINDOWSTATION::rpwinstaNext, tagDESKTOP::rpwinstaParent, RtlInitUnicodeString(), SetVisible(), tagDESKTOP::spmenuDialogSys, tagDESKTOP::spmenuHScroll, tagDESKTOP::spmenuSys, tagDESKTOP::spmenuVScroll, tagDESKTOPINFO::spwnd, tagDESKTOPINFO::spwndBkGnd, tagDESKTOP::spwndForeground, tagDESKTOP::spwndMenu, tagDESKTOP::spwndMessage, tagDESKTOPINFO::spwndProgman, tagDESKTOPINFO::spwndShell, tagDESKTOPINFO::spwndTaskman, tagDESKTOP::spwndTooltip, tagDESKTOP::spwndTrack, tagDESKTOP::spwndTray, SV_UNSET, TERMF_DTDESTROYED, TERMF_DTINITFAILED, TERMF_DTINITSUCCESS, TERMF_NOIO, TestWF, ThreadLockAlways, ThreadLockAlwaysWithPti, ThreadLockDesktop, ThreadLockWinSta, ThreadUnlock, ThreadUnlockDesktop, ThreadUnlockWinSta, TRACE_DESKTOP, TRUE, UINT, Unlock, UnlockDesktop, UnlockDesktopMenu(), UnlockDesktopSysMenu(), VOID(), WFVISIBLE, WrUserRequest, WSF_NOIO, WSF_SWITCHLOCK, xxxDestroyWindow(), xxxDispatchMessage(), xxxMinimizeHungWindow(), xxxMsgWaitForMultipleObjects(), xxxPeekMessage, xxxSetThreadDesktop(), xxxSetWindowPos(), xxxSwitchDesktop(), and zzzDestroyQueue().

Referenced by xxxInitTerminal().

00116 { 00117 KPRIORITY Priority; 00118 PTHREADINFO ptiCurrent; 00119 PQ pqOriginal; 00120 UNICODE_STRING strThreadName; 00121 PKEVENT *apRITEvents; 00122 PKEVENT pEvent; 00123 MSGWAITCALLBACK pfnHidChangeRoutine = NULL; 00124 DWORD nEvents = 0; 00125 UINT idMouseInput; 00126 UINT idDesktopDestroy; 00127 UINT idPumpMessages; 00128 UINT idHungThread; 00129 PKWAIT_BLOCK WaitBlockArray; 00130 00131 UserAssert(pTerm != NULL); 00132 00133 /* 00134 * Set the desktop thread's priority to low realtime. 00135 */ 00136 Priority = LOW_REALTIME_PRIORITY; 00137 ZwSetInformationThread(NtCurrentThread(), 00138 ThreadPriority, 00139 &Priority, 00140 sizeof(KPRIORITY)); 00141 00142 /* 00143 * There are just two TERMINAL structures. One is for the 00144 * interactive windowstation and the other is for all the 00145 * non-interactive windowstations. 00146 */ 00147 if (pTerm->dwTERMF_Flags & TERMF_NOIO) { 00148 RtlInitUnicodeString(&strThreadName, L"NOIO_DT"); 00149 } else { 00150 RtlInitUnicodeString(&strThreadName, L"IO_DT"); 00151 } 00152 00153 if (!NT_SUCCESS(InitSystemThread(&strThreadName))) { 00154 pTerm->dwTERMF_Flags |= TERMF_DTINITFAILED; 00155 KeSetEvent(pTerm->pEventTermInit, EVENT_INCREMENT, FALSE); 00156 RIPMSG0(RIP_ERROR, "Fail to create the desktop thread"); 00157 return; 00158 } 00159 00160 ptiCurrent = PtiCurrentShared(); 00161 00162 pTerm->ptiDesktop = ptiCurrent; 00163 pTerm->pqDesktop = pqOriginal = ptiCurrent->pq; 00164 00165 (pqOriginal->cLockCount)++; 00166 ptiCurrent->pDeskInfo = &diStatic; 00167 00168 /* 00169 * Set the winsta to NULL. It will be set to the right 00170 * windowstation in xxxCreateDesktop before pEventInputReady 00171 * is set. 00172 */ 00173 ptiCurrent->pwinsta = NULL; 00174 00175 /* 00176 * Allocate non-paged array. Include an extra entry for 00177 * the thread's input event. 00178 */ 00179 apRITEvents = UserAllocPoolNonPaged((OBJECTS_COUNT * sizeof(PKEVENT)), 00180 TAG_SYSTEM); 00181 00182 if (apRITEvents == NULL) { 00183 pTerm->dwTERMF_Flags |= TERMF_DTINITFAILED; 00184 KeSetEvent(pTerm->pEventTermInit, EVENT_INCREMENT, FALSE); 00185 return; 00186 } 00187 00188 WaitBlockArray = UserAllocPoolNonPaged((OBJECTS_COUNT * sizeof(KWAIT_BLOCK)), 00189 TAG_SYSTEM); 00190 if (WaitBlockArray == NULL) { 00191 pTerm->dwTERMF_Flags |= TERMF_DTINITFAILED; 00192 KeSetEvent(pTerm->pEventTermInit, EVENT_INCREMENT, FALSE); 00193 UserFreePool(apRITEvents); 00194 return; 00195 } 00196 00197 idMouseInput = 0xFFFF; 00198 idDesktopDestroy = 0xFFFF; 00199 idHungThread = 0xFFFF; 00200 00201 /* 00202 * Reference the mouse input event. The system terminal doesn't 00203 * wait for any mouse input. 00204 */ 00205 if (!(pTerm->dwTERMF_Flags & TERMF_NOIO)) { 00206 pfnHidChangeRoutine = (MSGWAITCALLBACK)ProcessDeviceChanges; 00207 idMouseInput = nEvents++; 00208 UserAssert(aDeviceTemplate[DEVICE_TYPE_MOUSE].pkeHidChange); 00209 apRITEvents[idMouseInput] = aDeviceTemplate[DEVICE_TYPE_MOUSE].pkeHidChange; 00210 } 00211 00212 /* 00213 * Create the desktop destruction event. 00214 */ 00215 idDesktopDestroy = nEvents++; 00216 apRITEvents[idDesktopDestroy] = CreateKernelEvent(SynchronizationEvent, FALSE); 00217 if (apRITEvents[idDesktopDestroy] == NULL) { 00218 pTerm->dwTERMF_Flags |= TERMF_DTINITFAILED; 00219 KeSetEvent(pTerm->pEventTermInit, EVENT_INCREMENT, FALSE); 00220 UserFreePool(apRITEvents); 00221 UserFreePool(WaitBlockArray); 00222 return; 00223 } 00224 pTerm->pEventDestroyDesktop = apRITEvents[idDesktopDestroy]; 00225 00226 /* 00227 * Hung thread not needed for noninteractive windowstations. 00228 */ 00229 if (!(pTerm->dwTERMF_Flags & TERMF_NOIO)) { 00230 idHungThread = nEvents++; 00231 apRITEvents[idHungThread] = CreateKernelEvent(SynchronizationEvent, FALSE); 00232 if (apRITEvents[idHungThread] == NULL) { 00233 pTerm->dwTERMF_Flags |= TERMF_DTINITFAILED; 00234 KeSetEvent(pTerm->pEventTermInit, EVENT_INCREMENT, FALSE); 00235 FreeKernelEvent(&apRITEvents[idDesktopDestroy]); 00236 UserFreePool(apRITEvents); 00237 UserFreePool(WaitBlockArray); 00238 return; 00239 } 00240 00241 gpEventHungThread = apRITEvents[idHungThread]; 00242 } 00243 00244 EnterCrit(); 00245 UserAssert(IsWinEventNotifyDeferredOK()); 00246 00247 /* 00248 * Set the event that tells the initialization of desktop 00249 * thread is done. 00250 */ 00251 pTerm->dwTERMF_Flags |= TERMF_DTINITSUCCESS; 00252 KeSetEvent(pTerm->pEventTermInit, EVENT_INCREMENT, FALSE); 00253 00254 /* 00255 * Prepare to wait on input ready event. 00256 */ 00257 pEvent = pTerm->pEventInputReady; 00258 ObReferenceObjectByPointer(pEvent, 00259 EVENT_ALL_ACCESS, 00260 *ExEventObjectType, 00261 KernelMode); 00262 00263 LeaveCrit(); 00264 00265 KeWaitForSingleObject(pEvent, WrUserRequest, KernelMode, FALSE, NULL); 00266 ObDereferenceObject(pEvent); 00267 00268 EnterCrit(); 00269 00270 /* 00271 * Adjust the event ids 00272 */ 00273 idMouseInput += WAIT_OBJECT_0; 00274 idDesktopDestroy += WAIT_OBJECT_0; 00275 idHungThread += WAIT_OBJECT_0; 00276 idPumpMessages = WAIT_OBJECT_0 + nEvents; 00277 00278 /* 00279 * message loop lasts until we get a WM_QUIT message 00280 * upon which we shall return from the function 00281 */ 00282 while (TRUE) { 00283 DWORD result; 00284 00285 /* 00286 * Wait for any message sent or posted to this queue, while calling 00287 * ProcessDeviceChanges whenever the mouse change event (pkeHidChange) 00288 * is set. 00289 */ 00290 result = xxxMsgWaitForMultipleObjects(nEvents, 00291 apRITEvents, 00292 pfnHidChangeRoutine, 00293 WaitBlockArray); 00294 00295 #if DBG 00296 gDesktopsBusy++; // diagnostic 00297 if (gDesktopsBusy >= 2) { 00298 RIPMSG0(RIP_WARNING, "2 or more desktop threads busy"); 00299 } 00300 #endif 00301 00302 /* 00303 * result tells us the type of event we have: 00304 * a message or a signalled handle 00305 * 00306 * if there are one or more messages in the queue ... 00307 */ 00308 if (result == (DWORD)idPumpMessages) { 00309 00310 /* 00311 * block-local variable 00312 */ 00313 MSG msg ; 00314 00315 CheckCritIn(); 00316 00317 /* 00318 * read all of the messages in this next loop 00319 * removing each message as we read it 00320 */ 00321 while (xxxPeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 00322 00323 /* 00324 * if it's a quit message we're out of here 00325 */ 00326 if (msg.message == WM_QUIT && ptiCurrent->cWindows == 1) { 00327 00328 TRACE_DESKTOP(("WM_QUIT: Destroying the desktop thread. cWindows %d\n", 00329 ptiCurrent->cWindows)); 00330 00331 /* 00332 * The window station is gone, so 00333 * 00334 * DON'T USE PWINSTA ANYMORE 00335 */ 00336 00337 /* 00338 * We could have received a mouse message in between the 00339 * desktop destroy event and the WM_QUIT message in which 00340 * case we may need to clear spwndTrack again to make sure 00341 * that a window (gotta be the desktop) isn't locked in. 00342 */ 00343 Unlock(&ptiCurrent->rpdesk->spwndTrack); 00344 00345 /* 00346 * If we're running on the last interactive desktop, 00347 * then we never unlocked pdesk->pDeskInfo->spwnd. 00348 * However, it seems to me that the system stops 00349 * running before we make it here; otherwise, (or 00350 * for a Hydra-like thing) we need to unlock that 00351 * window here..... 00352 */ 00353 UserAssert(ptiCurrent->rpdesk != NULL && 00354 ptiCurrent->rpdesk->pDeskInfo != NULL && 00355 ptiCurrent->rpdesk->pDeskInfo->spwnd != NULL); 00356 00357 Unlock(&ptiCurrent->rpdesk->pDeskInfo->spwnd); 00358 00359 /* 00360 * Because there is no desktop, we need to fake a 00361 * desktop info structure so that the IsHooked() 00362 * macro can test a "valid" fsHooks value. 00363 */ 00364 ptiCurrent->pDeskInfo = &diStatic; 00365 00366 /* 00367 * The desktop window is all that's left, so 00368 * let's exit. The thread cleanup code will 00369 * handle destruction of the window. 00370 */ 00371 00372 /* 00373 * If the thread is not using the original queue, 00374 * destroy it. 00375 */ 00376 UserAssert(pqOriginal->cLockCount); 00377 (pqOriginal->cLockCount)--; 00378 if (ptiCurrent->pq != pqOriginal) { 00379 zzzDestroyQueue(pqOriginal, ptiCurrent); // DeferWinEventNotify() ?? IANJA ?? 00380 } 00381 00382 #if DBG 00383 gDesktopsBusy--; // diagnostic 00384 #endif 00385 00386 LeaveCrit(); 00387 00388 /* 00389 * Deref the events now that we're done with them. 00390 * Also free the wait array. 00391 */ 00392 if (!(pTerm->dwTERMF_Flags & TERMF_NOIO)) { 00393 FreeKernelEvent(&gpEventHungThread); 00394 } 00395 FreeKernelEvent(&apRITEvents[idDesktopDestroy]); 00396 UserFreePool(apRITEvents); 00397 UserFreePool(WaitBlockArray); 00398 00399 /* 00400 * Terminate the thread. This will call the 00401 * Win32k thread cleanup code. 00402 */ 00403 TRACE_DESKTOP(("call PsTerminateSystemThread\n")); 00404 00405 pTerm->ptiDesktop = NULL; 00406 pTerm->pqDesktop = NULL; 00407 00408 pTerm->dwTERMF_Flags &= TERMF_DTDESTROYED; 00409 00410 PsTerminateSystemThread(0); 00411 } 00412 00413 UserAssert(msg.message != WM_QUIT); 00414 00415 /* 00416 * otherwise dispatch it 00417 */ 00418 xxxDispatchMessage(&msg); 00419 00420 } // end of PeekMessage while loop 00421 00422 } else if (result == idDesktopDestroy) { 00423 00424 PDESKTOP *ppdesk; 00425 PDESKTOP pdesk; 00426 PWND pwnd; 00427 PMENU pmenu; 00428 TL tlpwinsta; 00429 PWINDOWSTATION pwinsta; 00430 TL tlpdesk; 00431 TL tlpwnd; 00432 PDESKTOP pdeskTemp; 00433 HDESK hdeskTemp; 00434 TL tlpdeskTemp; 00435 00436 /* 00437 * Destroy desktops on the destruction list. 00438 */ 00439 for (ppdesk = &pTerm->rpdeskDestroy; *ppdesk != NULL; ) { 00440 /* 00441 * Unlink from the list. 00442 */ 00443 pdesk = *ppdesk; 00444 00445 TRACE_DESKTOP(("Destroying desktop '%ws' %#p ...\n", 00446 GetDesktopName(pdesk), pdesk)); 00447 00448 UserAssert(!(pdesk->dwDTFlags & DF_DYING)); 00449 00450 ThreadLockDesktop(ptiCurrent, pdesk, &tlpdesk, LDLT_FN_DESKTOPTHREAD_DESK); 00451 pwinsta = pdesk->rpwinstaParent; 00452 ThreadLockWinSta(ptiCurrent, pdesk->rpwinstaParent, &tlpwinsta); 00453 00454 LockDesktop(ppdesk, pdesk->rpdeskNext, LDL_TERM_DESKDESTROY1, (ULONG_PTR)pTerm); 00455 UnlockDesktop(&pdesk->rpdeskNext, LDU_DESK_DESKNEXT, 0); 00456 00457 /* 00458 * !!! If this is the current desktop, switch to another one. 00459 */ 00460 if (pdesk == grpdeskRitInput) { 00461 PDESKTOP pdeskNew; 00462 00463 TRACE_DESKTOP(("Destroying the current active desktop\n")); 00464 00465 if (pwinsta->dwWSF_Flags & WSF_SWITCHLOCK) { 00466 00467 TRACE_DESKTOP(("The windowstation is locked\n")); 00468 00469 /* 00470 * this should be the interactive windowstation 00471 */ 00472 UserAssert(!(pwinsta->dwWSF_Flags & WSF_NOIO)); 00473 00474 /* 00475 * Switch to the disconnected desktop if the logon desktop 00476 * is being destroyed, or there is no logon desktop, or 00477 * if the logon desktop has already been destroyed. 00478 */ 00479 if (gbRemoteSession && gspdeskDisconnect && 00480 (pdesk == grpdeskLogon || 00481 grpdeskLogon == NULL || 00482 (grpdeskLogon->dwDTFlags & DF_DESKWNDDESTROYED))) { 00483 TRACE_DESKTOP(("disable the screen and switch to the disconnect desktop\n")); 00484 RemoteDisableScreen(); 00485 goto skip; 00486 00487 } else { 00488 TRACE_DESKTOP(("Switch to the logon desktop '%ws' %#p ...\n", 00489 GetDesktopName(grpdeskLogon), grpdeskLogon)); 00490 00491 pdeskNew = grpdeskLogon; 00492 } 00493 } else { 00494 pdeskNew = pwinsta->rpdeskList; 00495 if (pdeskNew == pdesk) 00496 pdeskNew = pdesk->rpdeskNext; 00497 00498 /* 00499 * You can hit this assert if you exit winlogon before 00500 * logging in. I.E. all desktop's close so there is 00501 * no "next" one to switch to. I'm assuming that there 00502 * is a check for a NULL desktop in xxxSwitchDesktop(). 00503 * 00504 * You can't switch to a NULL desktop. But this means 00505 * there isn't any input desktop so clear it manually. 00506 */ 00507 if (gbRemoteSession) { 00508 if (pdeskNew == NULL) { 00509 00510 TRACE_DESKTOP(("NO INPUT FOR DT FROM THIS POINT ON ...\n")); 00511 00512 ClearWakeBit(ptiCurrent, QS_INPUT | QS_EVENT | QS_MOUSEMOVE, FALSE); 00513 } 00514 } else { 00515 UserAssert(pdeskNew); 00516 } 00517 } 00518 00519 TRACE_DESKTOP(("Switch to desktop '%ws' %#p\n", 00520 GetDesktopName(pdeskNew), pdeskNew)); 00521 00522 xxxSwitchDesktop(pwinsta, pdeskNew, FALSE); 00523 } 00524 skip: 00525 00526 /* 00527 * Close the display if this desktop did not use 00528 * the global display. 00529 */ 00530 if ((pdesk->pDispInfo->hDev != NULL) && 00531 (pdesk->pDispInfo->hDev != gpDispInfo->hDev)) { 00532 00533 TRACE_DESKTOP(("Destroy MDEV\n")); 00534 00535 DrvDestroyMDEV(pdesk->pDispInfo->pmdev); 00536 GreFreePool(pdesk->pDispInfo->pmdev); 00537 pdesk->pDispInfo->pmdev = NULL; 00538 } 00539 00540 if (pdesk->pDispInfo != gpDispInfo) { 00541 UserAssert(pdesk->pDispInfo->pMonitorFirst == NULL); 00542 UserFreePool(pdesk->pDispInfo); 00543 pdesk->pDispInfo = NULL; 00544 } 00545 00546 /* 00547 * Destroy desktop and menu windows. 00548 */ 00549 pdeskTemp = ptiCurrent->rpdesk; // save current desktop 00550 hdeskTemp = ptiCurrent->hdesk; 00551 ThreadLockDesktop(ptiCurrent, pdeskTemp, &tlpdeskTemp, LDLT_FN_DESKTOPTHREAD_DESKTEMP); 00552 xxxSetThreadDesktop(NULL, pdesk); 00553 Unlock(&pdesk->spwndForeground); 00554 Unlock(&pdesk->spwndTray); 00555 00556 Unlock(&pdesk->spwndTrack); 00557 pdesk->dwDTFlags &= ~DF_MOUSEMOVETRK; 00558 00559 if (pdesk->spmenuSys != NULL) { 00560 pmenu = pdesk->spmenuSys; 00561 if (UnlockDesktopSysMenu(&pdesk->spmenuSys)) 00562 _DestroyMenu(pmenu); 00563 } 00564 00565 if (pdesk->spmenuDialogSys != NULL) { 00566 pmenu = pdesk->spmenuDialogSys; 00567 if (UnlockDesktopSysMenu(&pdesk->spmenuDialogSys)) 00568 _DestroyMenu(pmenu); 00569 } 00570 00571 if (pdesk->spmenuHScroll != NULL) { 00572 pmenu = pdesk->spmenuHScroll; 00573 if (UnlockDesktopMenu(&pdesk->spmenuHScroll)) 00574 _DestroyMenu(pmenu); 00575 } 00576 00577 if (pdesk->spmenuVScroll != NULL) { 00578 pmenu = pdesk->spmenuVScroll; 00579 if (UnlockDesktopMenu(&pdesk->spmenuVScroll)) 00580 _DestroyMenu(pmenu); 00581 } 00582 00583 /* 00584 * If this desktop doesn't have a pDeskInfo, then 00585 * something is wrong. All desktops should have 00586 * this until the object is freed. 00587 */ 00588 if (pdesk->pDeskInfo == NULL) { 00589 RIPMSG0(RIP_ERROR, 00590 "xxxDesktopThread: There is no pDeskInfo for this desktop"); 00591 } 00592 00593 if (pdesk->pDeskInfo) { 00594 if (pdesk->pDeskInfo->spwnd == gspwndFullScreen) 00595 Unlock(&gspwndFullScreen); 00596 00597 if (pdesk->pDeskInfo->spwndShell) 00598 Unlock(&pdesk->pDeskInfo->spwndShell); 00599 00600 if (pdesk->pDeskInfo->spwndBkGnd) 00601 Unlock(&pdesk->pDeskInfo->spwndBkGnd); 00602 00603 if (pdesk->pDeskInfo->spwndTaskman) 00604 Unlock(&pdesk->pDeskInfo->spwndTaskman); 00605 00606 if (pdesk->pDeskInfo->spwndProgman) 00607 Unlock(&pdesk->pDeskInfo->spwndProgman); 00608 } 00609 00610 UserAssert(!(pdesk->dwDTFlags & DF_DYING)); 00611 00612 if (pdesk->spwndMenu != NULL) { 00613 00614 pwnd = pdesk->spwndMenu; 00615 00616 /* 00617 * Hide this window without activating anyone else. 00618 */ 00619 if (TestWF(pwnd, WFVISIBLE)) { 00620 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); 00621 xxxSetWindowPos(pwnd, 00622 NULL, 00623 0, 00624 0, 00625 0, 00626 0, 00627 SWP_HIDEWINDOW | SWP_NOACTIVATE | 00628 SWP_NOMOVE | SWP_NOSIZE | 00629 SWP_NOZORDER | SWP_NOREDRAW | 00630 SWP_NOSENDCHANGING); 00631 00632 ThreadUnlock(&tlpwnd); 00633 } 00634 00635 /* 00636 * Reset the flag in the popupmenu structure that tells this 00637 * popup menu belongs to the pdesk->spwndMenu so it can go away. 00638 */ 00639 ((PMENUWND)pwnd)->ppopupmenu->fDesktopMenu = FALSE; 00640 ((PMENUWND)pwnd)->ppopupmenu->fDelayedFree = FALSE; 00641 #if DBG 00642 /* We used to zero out this popup when closing the menu. 00643 * now we zero it out when about to re-use it. 00644 * So make ValidatepPopupMenu happy by clearing the 00645 * leftover ppopupmenuRoot, if any. 00646 */ 00647 ((PMENUWND)pwnd)->ppopupmenu->ppopupmenuRoot = NULL; 00648 #endif 00649 00650 if (Unlock(&pdesk->spwndMenu)) { 00651 xxxDestroyWindow(pwnd); 00652 } 00653 } 00654 00655 if (pdesk->spwndMessage != NULL) { 00656 00657 pwnd = pdesk->spwndMessage; 00658 00659 if (Unlock(&pdesk->spwndMessage)) { 00660 xxxDestroyWindow(pwnd); 00661 } 00662 } 00663 00664 if (pdesk->spwndTooltip != NULL) { 00665 00666 pwnd = pdesk->spwndTooltip; 00667 00668 if (Unlock(&pdesk->spwndTooltip)) { 00669 xxxDestroyWindow(pwnd); 00670 } 00671 UserAssert(!(pdesk->dwDTFlags & DF_TOOLTIPSHOWING)); 00672 } 00673 00674 UserAssert(!(pdesk->dwDTFlags & DF_DYING)); 00675 00676 /* 00677 * If the dying desktop is the owner of the desktop 00678 * owner window, reassign it to the first available 00679 * desktop. This is needed to ensure that 00680 * xxxSetWindowPos will work on desktop windows. 00681 */ 00682 if (pTerm->spwndDesktopOwner != NULL && 00683 pTerm->spwndDesktopOwner->head.rpdesk == pdesk) { 00684 00685 PDESKTOP pdeskR; 00686 00687 /* 00688 * Find out to what desktop the mother desktop window 00689 * should go. Careful with the NOIO case where there 00690 * might be several windowstations using the same 00691 * mother desktop window 00692 */ 00693 if (pTerm->dwTERMF_Flags & TERMF_NOIO) { 00694 00695 PWINDOWSTATION pwinstaW; 00696 00697 UserAssert(grpWinStaList != NULL); 00698 00699 pwinstaW = grpWinStaList->rpwinstaNext; 00700 00701 pdeskR = NULL; 00702 00703 while (pwinstaW != NULL) { 00704 if (pwinstaW->rpdeskList != NULL) { 00705 pdeskR = pwinstaW->rpdeskList; 00706 break; 00707 } 00708 pwinstaW = pwinstaW->rpwinstaNext; 00709 } 00710 } else { 00711 pdeskR = pwinsta->rpdeskList; 00712 } 00713 00714 if (pdeskR == NULL) { 00715 00716 PWND pwnd; 00717 00718 TRACE_DESKTOP(("DESTROYING THE MOTHER DESKTOP WINDOW %#p\n", 00719 pTerm->spwndDesktopOwner)); 00720 00721 pwnd = pTerm->spwndDesktopOwner; 00722 00723 /* 00724 * Hide it first 00725 */ 00726 SetVisible(pwnd, SV_UNSET); 00727 00728 Unlock(&(pTerm->spwndDesktopOwner)); 00729 00730 xxxDestroyWindow(pwnd); 00731 00732 } else { 00733 TRACE_DESKTOP(("MOVING THE MOTHER DESKTOP WINDOW %#p to pdesk %#p '%ws'\n", 00734 pTerm->spwndDesktopOwner, pdeskR, GetDesktopName(pdeskR))); 00735 00736 LockDesktop(&(pTerm->spwndDesktopOwner->head.rpdesk), 00737 pdeskR, LDL_MOTHERDESK_DESK1, (ULONG_PTR)(pTerm->spwndDesktopOwner)); 00738 } 00739 } 00740 00741 if (pdesk->pDeskInfo && (pdesk->pDeskInfo->spwnd != NULL)) { 00742 00743 UserAssert(!(pdesk->dwDTFlags & DF_DESKWNDDESTROYED)); 00744 00745 pwnd = pdesk->pDeskInfo->spwnd; 00746 00747 /* 00748 * Hide this window without activating anyone else. 00749 */ 00750 if (TestWF(pwnd, WFVISIBLE)) { 00751 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); 00752 xxxSetWindowPos(pwnd, 00753 NULL, 00754 0, 00755 0, 00756 0, 00757 0, 00758 SWP_HIDEWINDOW | SWP_NOACTIVATE | 00759 SWP_NOMOVE | SWP_NOSIZE | 00760 SWP_NOZORDER | SWP_NOREDRAW | 00761 SWP_NOSENDCHANGING); 00762 00763 ThreadUnlock(&tlpwnd); 00764 } 00765 00766 /* 00767 * A lot of pwnd related code assumes that we 00768 * always have a valid desktop window. So we call 00769 * xxxDestroyWindow first to clean up and then 00770 * we unlock it to free it (now or eventually). 00771 * However, if we're destroying the last destkop, then 00772 * we don't unlock the window since we're are forced 00773 * to continue running on that desktop. 00774 */ 00775 00776 TRACE_DESKTOP(("Destroying the desktop window\n")); 00777 00778 xxxDestroyWindow(pdesk->pDeskInfo->spwnd); 00779 if (pdesk != grpdeskRitInput) { 00780 Unlock(&pdesk->pDeskInfo->spwnd); 00781 } else { 00782 00783 /* 00784 * unlock the gspwndShouldBeForeground window 00785 */ 00786 if (ISTS() && gspwndShouldBeForeground != NULL) { 00787 Unlock(&gspwndShouldBeForeground); 00788 } 00789 00790 /* 00791 * This is hit in HYDRA when the last desktop does away 00792 */ 00793 RIPMSG1(RIP_WARNING, "xxxDesktopThread: Running on zombie desk:%#p", pdesk); 00794 } 00795 pdesk->dwDTFlags |= DF_DESKWNDDESTROYED; 00796 } 00797 00798 /* 00799 * Restore the previous desktop 00800 */ 00801 xxxSetThreadDesktop(hdeskTemp, pdeskTemp); 00802 00803 00804 ThreadUnlockDesktop(ptiCurrent, &tlpdeskTemp, LDUT_FN_DESKTOPTHREAD_DESKTEMP); 00805 ThreadUnlockWinSta(ptiCurrent, &tlpwinsta); 00806 ThreadUnlockDesktop(ptiCurrent, &tlpdesk, LDUT_FN_DESKTOPTHREAD_DESK); 00807 } 00808 00809 if (gbRemoteSession) { 00810 /* 00811 * Wakeup ntinput thread for exit processing 00812 */ 00813 TRACE_DESKTOP(("Wakeup ntinput thread for exit processing\n")); 00814 00815 UserAssert(gpevtDesktopDestroyed != NULL); 00816 00817 KeSetEvent(gpevtDesktopDestroyed, EVENT_INCREMENT, FALSE); 00818 } 00819 00820 } else if (result == idHungThread) { 00821 /* 00822 * By using gspwndMouseOwner this code relies on this event being 00823 * received before another click may occur. In the worst case we 00824 * may "lose" a click and only react to the latest one. 00825 */ 00826 PWND pwnd = gspwndMouseOwner; 00827 if (pwnd != NULL && FHungApp(GETPTI(pwnd), CMSHUNGAPPTIMEOUT)) { 00828 00829 int ht = FindNCHit(pwnd, POINTTOPOINTS(glinp.ptLastClick)); 00830 00831 if (ht == HTCLOSE) { 00832 /* 00833 * Note -- this is private, and does not go to the hook, 00834 * only the posted ones from the shell. 00835 */ 00836 00837 PostShellHookMessages(HSHELL_ENDTASK, (LPARAM)HWq(pwnd)); 00838 } else if (ht == HTMINBUTTON) { 00839 TL tlpwnd; 00840 00841 ThreadLockAlways(pwnd, &tlpwnd); 00842 xxxMinimizeHungWindow(pwnd); 00843 ThreadUnlock(&tlpwnd); 00844 } 00845 } 00846 00847 } else { 00848 RIPMSG0(RIP_WARNING, "Desktop woke up for what?"); 00849 } 00850 00851 #if DBG 00852 gDesktopsBusy--; // diagnostic 00853 #endif 00854 } 00855 }

LRESULT xxxDesktopWndProc PWND  pwnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam
 

Definition at line 883 of file desktop.c.

References _GetDC(), _ReleaseDC(), CheckLock, CMSHUNGAPPTIMEOUT, CreateProfileUserName(), DTF_NEEDSPALETTECHANGED, tagDESKTOP::dwDTFlags, FALSE, FHungApp(), FNID_DESKTOP, FreeProfileUserName(), GETPTI, GetTopLevelWindow(), gpDispInfo, grpdeskRitInput, gspwndAltTab, tagDISPLAYINFO::hdcScreen, HWq, IsWinEventNotifyDeferredOK, L, NULL, tagDESKTOP::pDeskInfo, PsGetCurrentThread, PtiCurrent, PWND_BROADCAST, RevalidateHwnd, tagDESKTOPINFO::spwnd, tagWND::spwndParent, ThreadLockAlways, ThreadLockAlwaysWithPti, ThreadLockWithPti, ThreadUnlock, TRUE, VALIDATECLASSANDSIZE, xxxBeginPaint(), xxxDefWindowProc(), xxxEndPaint(), xxxInternalPaintDesktop(), xxxMakeWindowForegroundWithState(), xxxRealizeDesktop(), xxxRedrawWindow(), xxxSendMessage(), xxxSendNotifyMessage(), xxxSetDeskPattern(), xxxSetThreadDesktop(), and xxxSetWindowLong().

Referenced by InitFunctionTables(), InitializeClientPfnArrays(), and LW_RegisterWindows().

00888 { 00889 PTHREADINFO ptiCurrent = PtiCurrent(); 00890 HDC hdcT; 00891 PAINTSTRUCT ps; 00892 PWINDOWPOS pwp; 00893 00894 00895 CheckLock(pwnd); 00896 UserAssert(IsWinEventNotifyDeferredOK()); 00897 00898 VALIDATECLASSANDSIZE(pwnd, message, wParam, lParam, FNID_DESKTOP, WM_CREATE); 00899 00900 00901 if (pwnd->spwndParent == NULL) { 00902 switch (message) { 00903 00904 case WM_SETICON: 00905 /* 00906 * cannot allow this as it will cause a callback to user mode from the 00907 * desktop system thread. 00908 */ 00909 RIPMSG0(RIP_WARNING, "WM_ICON sent to desktop window was discarded.\n") ; 00910 return 0L ; 00911 00912 default: 00913 break; 00914 } /* switch */ 00915 00916 return xxxDefWindowProc(pwnd, message, wParam, lParam); 00917 } 00918 00919 switch (message) { 00920 00921 case WM_WINDOWPOSCHANGING: 00922 00923 /* 00924 * We receive this when switch desktop is called. Just 00925 * to be consistent, set the rit desktop as this 00926 * thread's desktop. 00927 */ 00928 pwp = (PWINDOWPOS)lParam; 00929 if (!(pwp->flags & SWP_NOZORDER) && pwp->hwndInsertAfter == HWND_TOP) { 00930 00931 xxxSetThreadDesktop(NULL, grpdeskRitInput); 00932 00933 /* 00934 * If some app has taken over the system-palette, we should make 00935 * sure the system is restored. Otherwise, if this is the logon 00936 * desktop, we might not be able to view the dialog correctly. 00937 */ 00938 if (GreGetSystemPaletteUse(gpDispInfo->hdcScreen) != SYSPAL_STATIC) 00939 GreRealizeDefaultPalette(gpDispInfo->hdcScreen, TRUE); 00940 00941 /* 00942 * Let everyone know if the palette has changed 00943 */ 00944 if (grpdeskRitInput->dwDTFlags & DTF_NEEDSPALETTECHANGED) { 00945 xxxSendNotifyMessage(PWND_BROADCAST, 00946 WM_PALETTECHANGED, 00947 (WPARAM)HWq(pwnd), 00948 0); 00949 grpdeskRitInput->dwDTFlags &= ~DTF_NEEDSPALETTECHANGED; 00950 } 00951 } 00952 break; 00953 00954 case WM_FULLSCREEN: { 00955 TL tlpwndT; 00956 00957 ThreadLockWithPti(ptiCurrent, grpdeskRitInput->pDeskInfo->spwnd, &tlpwndT); 00958 xxxMakeWindowForegroundWithState( 00959 grpdeskRitInput->pDeskInfo->spwnd, GDIFULLSCREEN); 00960 ThreadUnlock(&tlpwndT); 00961 00962 /* 00963 * We have to tell the switch window to repaint if we switched 00964 * modes 00965 */ 00966 if (gspwndAltTab != NULL) { 00967 ThreadLockAlwaysWithPti(ptiCurrent, gspwndAltTab, &tlpwndT); 00968 xxxSendMessage(gspwndAltTab, WM_FULLSCREEN, 0, 0); 00969 ThreadUnlock(&tlpwndT); 00970 } 00971 00972 break; 00973 } 00974 00975 case WM_CLOSE: 00976 00977 /* 00978 * Make sure nobody sends this window a WM_CLOSE and causes it to 00979 * destroy itself. 00980 */ 00981 break; 00982 00983 case WM_SETICON: 00984 /* 00985 * cannot allow this as it will cause a callback to user mode from the 00986 * desktop system thread. 00987 */ 00988 RIPMSG0(RIP_WARNING, "WM_ICON sent to desktop window was discarded.\n") ; 00989 break; 00990 00991 case WM_CREATE: { 00992 TL tlName; 00993 PUNICODE_STRING pProfileUserName = CreateProfileUserName(&tlName); 00994 /* 00995 * Is there a desktop pattern, or bitmap name in WIN.INI? 00996 */ 00997 xxxSetDeskPattern(pProfileUserName, (LPWSTR)-1, TRUE); 00998 00999 FreeProfileUserName(pProfileUserName, &tlName); 01000 /* 01001 * Initialize the system colors before we show the desktop window. 01002 */ 01003 xxxSendNotifyMessage(pwnd, WM_SYSCOLORCHANGE, 0, 0L); 01004 01005 hdcT = _GetDC(pwnd); 01006 xxxInternalPaintDesktop(pwnd, hdcT, FALSE); // use "normal" HDC so SelectPalette() will work 01007 _ReleaseDC(hdcT); 01008 01009 /* 01010 * Save process and thread ids. 01011 */ 01012 xxxSetWindowLong(pwnd, 01013 0, 01014 HandleToUlong(PsGetCurrentThread()->Cid.UniqueProcess), 01015 FALSE); 01016 01017 xxxSetWindowLong(pwnd, 01018 4, 01019 HandleToUlong(PsGetCurrentThread()->Cid.UniqueThread), 01020 FALSE); 01021 break; 01022 } 01023 case WM_PALETTECHANGED: 01024 if (HWq(pwnd) == (HWND)wParam) 01025 break; 01026 01027 // FALL THROUGH 01028 01029 case WM_QUERYNEWPALETTE: 01030 xxxRealizeDesktop(pwnd); 01031 break; 01032 01033 case WM_SYSCOLORCHANGE: 01034 01035 /* 01036 * We do the redrawing if someone has changed the sys-colors from 01037 * another desktop and we need to redraw. This is appearent with 01038 * the MATROX card which requires OGL applications to take over 01039 * the entire sys-colors for drawing. When switching desktops, we 01040 * never broadcast the WM_SYSCOLORCHANGE event to tell us to redraw 01041 * This is only a DAYTONA related fix, and should be removed once 01042 * we move the SYSMETS to a per-desktop state. 01043 * 01044 * 05-03-95 : ChrisWil. 01045 */ 01046 xxxRedrawWindow(pwnd, 01047 NULL, 01048 NULL, 01049 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE); 01050 break; 01051 01052 case WM_ERASEBKGND: 01053 hdcT = (HDC)wParam; 01054 xxxInternalPaintDesktop(pwnd, hdcT, TRUE); 01055 return TRUE; 01056 01057 case WM_PAINT: 01058 xxxBeginPaint(pwnd, (LPPAINTSTRUCT)&ps); 01059 xxxEndPaint(pwnd, (LPPAINTSTRUCT)&ps); 01060 break; 01061 01062 #ifdef HUNGAPP_GHOSTING 01063 case WM_HUNGTHREAD: 01064 { 01065 PWND pwnd = RevalidateHwnd((HWND)lParam); 01066 01067 if (pwnd != NULL && FHungApp(GETPTI(pwnd), CMSHUNGAPPTIMEOUT)) { 01068 TL tlpwnd; 01069 01070 pwnd = GetTopLevelWindow(pwnd); 01071 01072 ThreadLockAlways(pwnd, &tlpwnd); 01073 xxxCreateGhost(pwnd); 01074 ThreadUnlock(&tlpwnd); 01075 } 01076 break; 01077 } 01078 #endif // HUNGAPP_GHOSTING 01079 01080 case WM_LBUTTONDBLCLK: 01081 message = WM_SYSCOMMAND; 01082 wParam = SC_TASKLIST; 01083 01084 /* 01085 *** FALL THRU ** 01086 */ 01087 01088 default: 01089 return xxxDefWindowProc(pwnd, message, wParam, lParam); 01090 } 01091 01092 return 0L; 01093 }

HDESK xxxGetInputDesktop VOID   ) 
 

Definition at line 4309 of file desktop.c.

References grpdeskRitInput, HF_PROTECTED, NULL, PsGetCurrentProcess, SetHandleFlag(), TRUE, and xxxUserFindHandleForObject().

04310 { 04311 HDESK hdesk; 04312 04313 if (xxxUserFindHandleForObject(PsGetCurrentProcess(), grpdeskRitInput, NULL, NULL, &hdesk)) { 04314 SetHandleFlag(hdesk, HF_PROTECTED, TRUE); 04315 return hdesk; 04316 } else { 04317 return NULL; 04318 } 04319 }

HDESK xxxGetThreadDesktop DWORD  dwThread,
HDESK  hdeskConsole,
KPROCESSOR_MODE  AccessMode
 

Definition at line 4211 of file desktop.c.

References ExDesktopObjectType, FALSE, gpepCSRSS, tagTHREADINFO::hdesk, HF_PROTECTED, KeAttachProcess(), KeDetachProcess(), LogDesktop, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), tagTHREADINFO::ppi, PpiCurrent, PpiFromProcess, PsGetCurrentProcess, PsGetCurrentThread, PtiCurrent, PtiFromThreadId(), SetHandleFlag(), Status, TRUE, and xxxUserFindHandleForObject().

Referenced by NtUserGetThreadDesktop().

04215 { 04216 PTHREADINFO pti = PtiFromThreadId(dwThread); 04217 PPROCESSINFO ppiThread; 04218 HDESK hdesk; 04219 NTSTATUS Status; 04220 04221 if (pti == NULL) { 04222 04223 /* 04224 * If the thread has a console use that desktop. If 04225 * not, then the thread is either invalid or not 04226 * a Win32 thread. 04227 */ 04228 if (hdeskConsole == NULL) { 04229 RIPERR1(ERROR_INVALID_PARAMETER, RIP_VERBOSE, 04230 "xxxGetThreadDesktop: invalid threadId 0x%x", 04231 dwThread); 04232 return NULL; 04233 } 04234 04235 hdesk = hdeskConsole; 04236 ppiThread = PpiFromProcess(gpepCSRSS); 04237 } else { 04238 hdesk = pti->hdesk; 04239 ppiThread = pti->ppi; 04240 } 04241 04242 /* 04243 * If there is no desktop, return NULL with no error 04244 */ 04245 if (hdesk != NULL) { 04246 04247 /* 04248 * If the thread belongs to this process, return the 04249 * handle. Otherwise, enumerate the handle table of 04250 * this process to find a handle with the same 04251 * attributes. 04252 */ 04253 if (ppiThread != PpiCurrent()) { 04254 PVOID pobj; 04255 OBJECT_HANDLE_INFORMATION ohi; 04256 04257 RIPMSG4(RIP_VERBOSE, "[%x.%x] %s called xxxGetThreadDesktop for pti %#p\n", 04258 PsGetCurrentThread()->Cid.UniqueProcess, 04259 PsGetCurrentThread()->Cid.UniqueThread, 04260 PsGetCurrentProcess()->ImageFileName, 04261 pti); 04262 04263 KeAttachProcess(&ppiThread->Process->Pcb); 04264 Status = ObReferenceObjectByHandle(hdesk, 04265 0, 04266 *ExDesktopObjectType, 04267 AccessMode, 04268 &pobj, 04269 &ohi); 04270 KeDetachProcess(); 04271 if (!NT_SUCCESS(Status) || 04272 !xxxUserFindHandleForObject(PsGetCurrentProcess(), pobj, NULL, &ohi, &hdesk)) { 04273 04274 RIPMSG0(RIP_VERBOSE, "Cannot find hdesk for current process"); 04275 04276 hdesk = NULL; 04277 04278 } else { 04279 LogDesktop(pobj, LD_REF_FN_GETTHREADDESKTOP, TRUE, (ULONG_PTR)PtiCurrent()); 04280 } 04281 if (NT_SUCCESS(Status)) { 04282 LogDesktop(pobj, LD_DEREF_FN_GETTHREADDESKTOP, FALSE, (ULONG_PTR)PtiCurrent()); 04283 ObDereferenceObject(pobj); 04284 } 04285 } 04286 04287 if (hdesk == NULL) { 04288 RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "xxxGetThreadDesktop: hdesk is null"); 04289 } else { 04290 SetHandleFlag(hdesk, HF_PROTECTED, TRUE); 04291 } 04292 } 04293 04294 return hdesk; 04295 }

HDESK xxxOpenDesktop POBJECT_ATTRIBUTES  ccxObjA,
KPROCESSOR_MODE  AccessMode,
DWORD  dwFlags,
DWORD  dwDesiredAccess,
BOOL *  pbShutDown
 

Definition at line 3265 of file desktop.c.

References CloseProtectedHandle(), dwFlags, tagDESKTOP::dwSessionId, Error, ExDesktopObjectType, FALSE, gSessionId, HF_PROTECTED, KernelMode, LogDesktop, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObOpenObjectByName(), ObReferenceObjectByHandle(), OpenDesktopCompletion(), PtiCurrent, SetHandleFlag(), Status, TRACE_INIT, and TRUE.

Referenced by NtUserOpenDesktop(), xxxResolveDesktop(), and xxxResolveDesktopForWOW().

03271 { 03272 HDESK hdesk; 03273 PDESKTOP pdesk; 03274 NTSTATUS Status; 03275 03276 /* 03277 * Require read/write access 03278 */ 03279 dwDesiredAccess |= DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS; 03280 03281 /* 03282 * Open the desktop -- Ob routines capture Obj attributes. 03283 */ 03284 Status = ObOpenObjectByName( 03285 ccxObjA, 03286 *ExDesktopObjectType, 03287 AccessMode, 03288 NULL, 03289 dwDesiredAccess, 03290 NULL, 03291 &hdesk); 03292 if (!NT_SUCCESS(Status)) { 03293 RIPNTERR0(Status, RIP_VERBOSE, ""); 03294 return NULL; 03295 } 03296 03297 /* 03298 * Reference the desktop 03299 */ 03300 ObReferenceObjectByHandle( 03301 hdesk, 03302 0, 03303 *ExDesktopObjectType, 03304 KernelMode, 03305 &pdesk, 03306 NULL); 03307 if (!NT_SUCCESS(Status)) { 03308 RIPNTERR0(Status, RIP_VERBOSE, ""); 03309 03310 Error: 03311 CloseProtectedHandle(hdesk); 03312 return NULL; 03313 } 03314 03315 if (pdesk->dwSessionId != gSessionId) { 03316 RIPNTERR1(STATUS_INVALID_HANDLE, RIP_WARNING, 03317 "xxxOpenDesktop pdesk %#p belongs to a different session", 03318 pdesk); 03319 ObDereferenceObject(pdesk); 03320 goto Error; 03321 } 03322 03323 LogDesktop(pdesk, LD_REF_FN_OPENDESKTOP, TRUE, (ULONG_PTR)PtiCurrent()); 03324 03325 /* 03326 * Complete the desktop open 03327 */ 03328 if (!OpenDesktopCompletion(pdesk, hdesk, dwFlags, pbShutDown)) { 03329 CloseProtectedHandle(hdesk); 03330 hdesk = NULL; 03331 } 03332 03333 TRACE_INIT(("xxxOpenDesktop: Leaving\n")); 03334 03335 LogDesktop(pdesk, LD_DEREF_FN_OPENDESKTOP, FALSE, (ULONG_PTR)PtiCurrent()); 03336 ObDereferenceObject(pdesk); 03337 03338 if (hdesk != NULL) { 03339 SetHandleFlag(hdesk, HF_PROTECTED, TRUE); 03340 } 03341 03342 return hdesk; 03343 }

VOID xxxRealizeDesktop PWND  pwnd  ) 
 

Definition at line 863 of file desktop.c.

References _GetDC(), _ReleaseDC(), CheckLock, FALSE, FNID_DESKTOP, GETFNID, ghpalWallpaper, VOID(), and xxxInternalPaintDesktop().

Referenced by xxxBroadcastPaletteChanged(), and xxxDesktopWndProc().

00864 { 00865 CheckLock(pwnd); 00866 UserAssert(GETFNID(pwnd) == FNID_DESKTOP); 00867 00868 if (ghpalWallpaper) { 00869 HDC hdc = _GetDC(pwnd); 00870 xxxInternalPaintDesktop(pwnd, hdc, FALSE); 00871 _ReleaseDC(hdc); 00872 } 00873 }

HDESK xxxResolveDesktop HANDLE  hProcess,
PUNICODE_STRING  pstrDesktop,
HWINSTA *  phwinsta,
BOOL  fInherit,
BOOL *  pbShutDown
 

Definition at line 4821 of file desktop.c.

References _OpenWindowStation(), _UserTestForWinStaAccess(), BOOL, CheckCritIn, CloseProtectedHandle(), tagWINDOWSTATION::dwWSF_Flags, ExDesktopObjectType, ExWindowStationObjectType, FALSE, gbRemoteSession, gbSecureDesktop, GetDesktopView(), GetProcessLuid(), grpWinStaList, tagPROCESSINFO::hdeskStartup, tagPROCESSINFO::hwinsta, KernelMode, KPROCESSOR_MODE, L, LogDesktop, MapDesktop(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObOpenHandle, ObOpenObjectByPointer(), ObReferenceObjectByHandle(), PBYTE, PpiFromProcess, PsGetCurrentProcess, PsProcessType, PtiCurrent, tagPROCESSINFO::rpdeskStartup, tagPROCESSINFO::rpwinsta, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlCopyUnicodeString(), RtlInitUnicodeString(), Status, szWindowStationDirectory, TRUE, UserMode, USHORT, WSF_NOIO, xxxConnectService(), xxxOpenDesktop(), xxxUserDuplicateObject(), and xxxUserFindHandleForObject().

Referenced by NtUserResolveDesktop(), and xxxCreateThreadInfo().

04827 { 04828 PEPROCESS Process; 04829 PPROCESSINFO ppi; 04830 HWINSTA hwinsta; 04831 HDESK hdesk; 04832 PDESKTOP pdesk; 04833 PWINDOWSTATION pwinsta; 04834 BOOL fInteractive; 04835 UNICODE_STRING strDesktop; 04836 UNICODE_STRING strWinSta, strStatic; 04837 OBJECT_ATTRIBUTES ObjA; 04838 PUNICODE_STRING pstrStatic; 04839 POBJECT_ATTRIBUTES pObjA = NULL; 04840 SIZE_T cbObjA; 04841 LPWSTR pszDesktop; 04842 WCHAR awchName[sizeof(L"Service-0x0000-0000$") / sizeof(WCHAR)]; 04843 BOOL fWinStaDefaulted; 04844 BOOL fDesktopDefaulted; 04845 LUID luidService; 04846 NTSTATUS Status; 04847 HWINSTA hwinstaDup; 04848 PTEB pteb = NtCurrentTeb(); 04849 04850 CheckCritIn(); 04851 04852 UserAssert(pteb); 04853 04854 Status = ObReferenceObjectByHandle(hProcess, 04855 PROCESS_QUERY_INFORMATION, 04856 *PsProcessType, 04857 UserMode, 04858 &Process, 04859 NULL); 04860 if (!NT_SUCCESS(Status)) { 04861 RIPMSG1(RIP_WARNING, "ResolveDesktop: Could not reference process handle (0x%X)", hProcess); 04862 return NULL; 04863 } 04864 04865 strStatic.Length = 0; 04866 strStatic.MaximumLength = STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR); 04867 04868 /* 04869 * Use the StaticUnicodeBuffer on the TEB as the buffer for the object name. 04870 * Even if this is client side and we pass KernelMode to the Ob call in 04871 * _OpenWindowStation this is safe because the TEB is not going to go away 04872 * during this call. The worst it can happen is to have the buffer in the TEB 04873 * trashed. 04874 */ 04875 strStatic.Buffer = pteb->StaticUnicodeBuffer; 04876 04877 UserAssert(pteb->StaticUnicodeBuffer == pteb->StaticUnicodeString.Buffer); 04878 UserAssert(pteb->StaticUnicodeString.MaximumLength ==STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR)); 04879 /* 04880 * The static unicode buffer in the teb 04881 /* 04882 * If the process already has a windowstation and a startup desktop, 04883 * return them. 04884 */ 04885 hwinsta = NULL; 04886 hwinstaDup = NULL; 04887 hdesk = NULL; 04888 ppi = PpiFromProcess(Process); 04889 04890 /* 04891 * Make sure the process has not been destroyed. Bug 214643 04892 */ 04893 if (ppi != NULL) { 04894 04895 if (ppi->W32PF_Flags & W32PF_TERMINATED) { 04896 04897 ObDereferenceObject(Process); 04898 04899 RIPMSG1(RIP_WARNING, "xxxResolveDesktop: ppi %#p has been destroyed", ppi); 04900 return NULL; 04901 } 04902 04903 if (ppi->hwinsta != NULL && ppi->hdeskStartup != NULL) { 04904 04905 /* 04906 * If the target process is the current process, simply 04907 * return the handles. Otherwise, open the objects. 04908 */ 04909 if (Process == PsGetCurrentProcess()) { 04910 hwinsta = ppi->hwinsta; 04911 hdesk = ppi->hdeskStartup; 04912 } else { 04913 Status = ObOpenObjectByPointer( 04914 ppi->rpwinsta, 04915 0, 04916 NULL, 04917 MAXIMUM_ALLOWED, 04918 *ExWindowStationObjectType, 04919 (KPROCESSOR_MODE)(gbSecureDesktop ? UserMode : KernelMode), 04920 &hwinsta); 04921 if (NT_SUCCESS(Status)) { 04922 Status = ObOpenObjectByPointer( 04923 ppi->rpdeskStartup, 04924 0, 04925 NULL, 04926 MAXIMUM_ALLOWED, 04927 *ExDesktopObjectType, 04928 (KPROCESSOR_MODE)(gbSecureDesktop ? UserMode : KernelMode), 04929 &hdesk); 04930 if (!NT_SUCCESS(Status)) { 04931 UserVerify(NT_SUCCESS(ZwClose(hwinsta))); 04932 hwinsta = NULL; 04933 } 04934 } 04935 if (!NT_SUCCESS(Status)) { 04936 RIPNTERR2( 04937 Status, 04938 RIP_WARNING, 04939 "ResolveDesktop: Could not reference winsta=%#p and/or desk=%#p", 04940 ppi->rpwinsta, ppi->rpdeskStartup); 04941 } 04942 } 04943 04944 RIPMSG2(RIP_VERBOSE, 04945 "ResolveDesktop: to hwinsta=%#p desktop=%#p", 04946 hwinsta, hdesk); 04947 04948 ObDereferenceObject(Process); 04949 *phwinsta = hwinsta; 04950 return hdesk; 04951 } 04952 } 04953 04954 /* 04955 * Determine windowstation and desktop names. 04956 */ 04957 if (pstrDesktop == NULL || pstrDesktop->Length == 0) { 04958 RtlInitUnicodeString(&strDesktop, TEXT("Default")); 04959 fWinStaDefaulted = fDesktopDefaulted = TRUE; 04960 } else { 04961 USHORT cch; 04962 /* 04963 * The name be of the form windowstation\desktop. Parse 04964 * the string to separate out the names. 04965 */ 04966 strWinSta = *pstrDesktop; 04967 cch = strWinSta.Length / sizeof(WCHAR); 04968 pszDesktop = strWinSta.Buffer; 04969 while (cch && *pszDesktop != L'\\') { 04970 cch--; 04971 pszDesktop++; 04972 } 04973 fDesktopDefaulted = FALSE; 04974 04975 if (cch == 0) { 04976 04977 /* 04978 * No windowstation name was specified, only the desktop. 04979 */ 04980 strDesktop = strWinSta; 04981 fWinStaDefaulted = TRUE; 04982 } else { 04983 /* 04984 * Both names were in the string. 04985 */ 04986 strDesktop.Buffer = pszDesktop + 1; 04987 strDesktop.Length = strDesktop.MaximumLength = (cch - 1) * sizeof(WCHAR); 04988 strWinSta.Length = (USHORT)(pszDesktop - strWinSta.Buffer) * sizeof(WCHAR); 04989 fWinStaDefaulted = FALSE; 04990 04991 RtlAppendUnicodeToString(&strStatic, (PWSTR)szWindowStationDirectory); 04992 RtlAppendUnicodeToString(&strStatic, L"\\"); 04993 RtlAppendUnicodeStringToString(&strStatic, &strWinSta); 04994 04995 if (!NT_SUCCESS(Status = _UserTestForWinStaAccess(&strStatic,TRUE))) { 04996 if (strStatic.MaximumLength > strStatic.Length) 04997 strStatic.Buffer[strStatic.Length/sizeof(WCHAR)] = 0; 04998 else 04999 strStatic.Buffer[(strStatic.Length - sizeof(WCHAR))/sizeof(WCHAR)] = 0; 05000 RIPMSG2(RIP_WARNING, 05001 "ResolveDesktop: Error (0x%X) resolving to WinSta='%ws'", 05002 Status, strStatic.Buffer); 05003 ObDereferenceObject(Process); 05004 *phwinsta = NULL; 05005 return NULL; 05006 } 05007 05008 } 05009 } 05010 05011 /* 05012 * If the desktop name is defaulted, make the handles 05013 * not inheritable. 05014 */ 05015 if (fDesktopDefaulted) 05016 fInherit = FALSE; 05017 05018 /* 05019 * If a windowstation has not been assigned to this process yet and 05020 * there are existing windowstations, attempt an open. 05021 */ 05022 if (hwinsta == NULL && grpWinStaList) { 05023 05024 /* 05025 * If the windowstation name was defaulted, create a name 05026 * based on the session. 05027 */ 05028 if (fWinStaDefaulted) { 05029 //Default Window Station 05030 RtlInitUnicodeString(&strWinSta, L"WinSta0"); 05031 05032 RtlAppendUnicodeToString(&strStatic, (PWSTR)szWindowStationDirectory); 05033 RtlAppendUnicodeToString(&strStatic, L"\\"); 05034 RtlAppendUnicodeStringToString(&strStatic, &strWinSta); 05035 05036 if (gbRemoteSession) { 05037 /* 05038 * Fake this out if it's an non-interactive winstation startup. 05039 * We don't want an extra winsta. 05040 */ 05041 fInteractive = NT_SUCCESS(_UserTestForWinStaAccess(&strStatic, TRUE)); 05042 } else { 05043 fInteractive = NT_SUCCESS(_UserTestForWinStaAccess(&strStatic,fInherit)); 05044 } 05045 05046 if (!fInteractive) { 05047 GetProcessLuid(NULL, &luidService); 05048 swprintf(awchName, L"Service-0x%x-%x$", 05049 luidService.HighPart, luidService.LowPart); 05050 RtlInitUnicodeString(&strWinSta, awchName); 05051 } 05052 } 05053 05054 /* 05055 * If no windowstation name was passed in and a windowstation 05056 * handle was inherited, assign it. 05057 */ 05058 if (fWinStaDefaulted) { 05059 if (xxxUserFindHandleForObject(Process, NULL, *ExWindowStationObjectType, 05060 NULL, &hwinsta)) { 05061 05062 /* 05063 * If the handle belongs to another process, 05064 * dup it into this one 05065 */ 05066 if (Process != PsGetCurrentProcess()) { 05067 05068 Status = xxxUserDuplicateObject( 05069 hProcess, 05070 hwinsta, 05071 NtCurrentProcess(), 05072 &hwinstaDup, 05073 0, 05074 0, 05075 DUPLICATE_SAME_ACCESS); 05076 if (!NT_SUCCESS(Status)) { 05077 hwinsta = NULL; 05078 } else { 05079 hwinsta = hwinstaDup; 05080 } 05081 } 05082 } 05083 } 05084 05085 /* 05086 * If we were assigned to a windowstation, make sure 05087 * it matches our fInteractive flag 05088 */ 05089 if (hwinsta != NULL) { 05090 Status = ObReferenceObjectByHandle(hwinsta, 05091 0, 05092 *ExWindowStationObjectType, 05093 KernelMode, 05094 &pwinsta, 05095 NULL); 05096 if (NT_SUCCESS(Status)) { 05097 BOOL fIO = (pwinsta->dwWSF_Flags & WSF_NOIO) ? FALSE : TRUE; 05098 if (fIO != fInteractive) { 05099 if (hwinstaDup) { 05100 CloseProtectedHandle(hwinsta); 05101 } 05102 hwinsta = NULL; 05103 } 05104 ObDereferenceObject(pwinsta); 05105 } 05106 } 05107 05108 /* 05109 * If not, open the computed windowstation. 05110 */ 05111 if (NT_SUCCESS(Status) && hwinsta == NULL) { 05112 05113 /* 05114 * Fill in the path to the windowstation 05115 */ 05116 strStatic.Length = 0; 05117 RtlAppendUnicodeToString(&strStatic, (PWSTR)szWindowStationDirectory); 05118 RtlAppendUnicodeToString(&strStatic, L"\\"); 05119 RtlAppendUnicodeStringToString(&strStatic, &strWinSta); 05120 05121 if (gbSecureDesktop) { 05122 /* 05123 * Allocate an object attributes structure in user address space. 05124 */ 05125 cbObjA = sizeof(*pObjA) + sizeof(*pstrStatic); 05126 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 05127 &pObjA, 0, &cbObjA, MEM_COMMIT, PAGE_READWRITE); 05128 pstrStatic = (PUNICODE_STRING)((PBYTE)pObjA + sizeof(*pObjA)); 05129 05130 if (NT_SUCCESS(Status)) { 05131 /* 05132 * Note -- the string must be in client-space or the 05133 * address validation in OpenWindowStation will fail. 05134 */ 05135 try { 05136 *pstrStatic = strStatic; 05137 InitializeObjectAttributes( pObjA, 05138 pstrStatic, 05139 OBJ_CASE_INSENSITIVE, 05140 NULL, 05141 NULL 05142 ); 05143 if (fInherit) 05144 pObjA->Attributes |= OBJ_INHERIT; 05145 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 05146 Status = GetExceptionCode(); 05147 } 05148 05149 if (NT_SUCCESS(Status)) { 05150 hwinsta = _OpenWindowStation(pObjA, MAXIMUM_ALLOWED, UserMode); 05151 } 05152 } 05153 } else { 05154 InitializeObjectAttributes( &ObjA, 05155 &strStatic, 05156 OBJ_CASE_INSENSITIVE, 05157 NULL, 05158 NULL 05159 ); 05160 if (fInherit) 05161 ObjA.Attributes |= OBJ_INHERIT; 05162 hwinsta = _OpenWindowStation(&ObjA, MAXIMUM_ALLOWED, KernelMode); 05163 } 05164 } 05165 05166 /* 05167 * Only allow service logons at the console. I don't think our 05168 * win32k exit routines cope with more than one windowstation. 05169 */ 05170 /* 05171 * If the open failed and the process is in a non-interactive 05172 * logon session, attempt to create a windowstation and 05173 * desktop for that session. Note that the desktop handle 05174 * will be closed after the desktop has been assigned. 05175 */ 05176 if (!gbRemoteSession && NT_SUCCESS(Status) && 05177 hwinsta == NULL && !fInteractive && fWinStaDefaulted) { 05178 05179 *phwinsta = xxxConnectService( 05180 &strStatic, 05181 &hdesk); 05182 05183 /* 05184 * Clean up and leave. 05185 */ 05186 if (pObjA != NULL) { 05187 ZwFreeVirtualMemory(NtCurrentProcess(), &pObjA, &cbObjA, 05188 MEM_RELEASE); 05189 } 05190 ObDereferenceObject(Process); 05191 05192 RIPMSG2(RIP_VERBOSE, 05193 "ResolveDesktop: xxxConnectService was called\n" 05194 "to hwinsta=%#p desktop=%#p", 05195 *phwinsta, hdesk); 05196 05197 return hdesk; 05198 } 05199 } 05200 05201 /* 05202 * Attempt to assign a desktop. 05203 */ 05204 if (hwinsta != NULL) { 05205 05206 /* 05207 * Every gui thread needs an associated desktop. We'll use the default 05208 * to start with and the application can override it if it wants. 05209 */ 05210 if (hdesk == NULL) { 05211 05212 /* 05213 * If no desktop name was passed in and a desktop 05214 * handle was inherited, assign it. 05215 */ 05216 if (fDesktopDefaulted) { 05217 if (xxxUserFindHandleForObject(Process, NULL, *ExDesktopObjectType, 05218 NULL, &hdesk)) { 05219 05220 /* 05221 * If the handle belongs to another process, 05222 * dup it into this one 05223 */ 05224 if (Process != PsGetCurrentProcess()) { 05225 HDESK hdeskDup; 05226 05227 Status = xxxUserDuplicateObject( 05228 hProcess, 05229 hdesk, 05230 NtCurrentProcess(), 05231 &hdeskDup, 05232 0, 05233 0, 05234 DUPLICATE_SAME_ACCESS); 05235 if (!NT_SUCCESS(Status)) { 05236 CloseProtectedHandle(hdesk); 05237 hdesk = NULL; 05238 } else { 05239 hdesk = hdeskDup; 05240 } 05241 } 05242 05243 /* 05244 * Map the desktop into the process. 05245 */ 05246 if (hdesk != NULL && ppi != NULL) { 05247 Status = ObReferenceObjectByHandle(hdesk, 05248 0, 05249 *ExDesktopObjectType, 05250 KernelMode, 05251 &pdesk, 05252 NULL); 05253 if (NT_SUCCESS(Status)) { 05254 05255 LogDesktop(pdesk, LD_REF_FN_RESOLVEDESKTOP, TRUE, (ULONG_PTR)PtiCurrent()); 05256 05257 try { 05258 MapDesktop(ObOpenHandle, Process, pdesk, 0, 1); 05259 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 05260 Status = STATUS_NO_MEMORY; 05261 CloseProtectedHandle(hdesk); 05262 hdesk = NULL; 05263 } 05264 #if DBG 05265 if (hdesk != NULL) { 05266 UserAssert(GetDesktopView(ppi, pdesk) != NULL); 05267 } 05268 #endif // DBG 05269 LogDesktop(pdesk, LD_DEREF_FN_RESOLVEDESKTOP, FALSE, (ULONG_PTR)PtiCurrent()); 05270 ObDereferenceObject(pdesk); 05271 } else { 05272 CloseProtectedHandle(hdesk); 05273 hdesk = NULL; 05274 } 05275 } 05276 } 05277 } 05278 05279 /* 05280 * If not, open the desktop. 05281 */ 05282 if (NT_SUCCESS(Status) && hdesk == NULL) { 05283 RtlCopyUnicodeString(&strStatic, &strDesktop); 05284 05285 if (gbSecureDesktop) { 05286 if (pObjA == NULL) { 05287 /* 05288 * Allocate an object attributes structure in user address space. 05289 */ 05290 cbObjA = sizeof(*pObjA) + sizeof(*pstrStatic); 05291 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 05292 &pObjA, 0, &cbObjA, MEM_COMMIT, PAGE_READWRITE); 05293 pstrStatic = (PUNICODE_STRING)((PBYTE)pObjA + sizeof(*pObjA)); 05294 } 05295 05296 if (NT_SUCCESS(Status)) { 05297 /* 05298 * Note -- the string must be in client-space or the 05299 * address validation in OpenDesktop will fail. 05300 */ 05301 try { 05302 *pstrStatic = strStatic; 05303 InitializeObjectAttributes( pObjA, 05304 pstrStatic, 05305 OBJ_CASE_INSENSITIVE, 05306 hwinsta, 05307 NULL 05308 ); 05309 if (fInherit) 05310 pObjA->Attributes |= OBJ_INHERIT; 05311 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 05312 Status = GetExceptionCode(); 05313 } 05314 05315 if (NT_SUCCESS(Status)) { 05316 hdesk = xxxOpenDesktop(pObjA, 05317 UserMode, 05318 0, 05319 MAXIMUM_ALLOWED, 05320 pbShutDown); 05321 } 05322 } 05323 } else { 05324 InitializeObjectAttributes( &ObjA, 05325 &strStatic, 05326 OBJ_CASE_INSENSITIVE, 05327 hwinsta, 05328 NULL 05329 ); 05330 if (fInherit) 05331 ObjA.Attributes |= OBJ_INHERIT; 05332 hdesk = xxxOpenDesktop(&ObjA, 05333 KernelMode, 05334 0, 05335 MAXIMUM_ALLOWED, 05336 pbShutDown); 05337 } 05338 } 05339 } 05340 if (hdesk == NULL) { 05341 UserVerify(NT_SUCCESS(ZwClose(hwinsta))); 05342 hwinsta = NULL; 05343 } 05344 } 05345 05346 ObDereferenceObject(Process); 05347 05348 if (pObjA != NULL) { 05349 ZwFreeVirtualMemory(NtCurrentProcess(), &pObjA, &cbObjA, 05350 MEM_RELEASE); 05351 } 05352 05353 *phwinsta = hwinsta; 05354 05355 RIPMSG2(RIP_VERBOSE, 05356 "ResolveDesktop: to hwinsta=%#p desktop=%#p", 05357 *phwinsta, hdesk); 05358 05359 return hdesk; 05360 }

NTSTATUS xxxResolveDesktopForWOW IN OUT PUNICODE_STRING  pstrDesktop  ) 
 

Definition at line 4588 of file desktop.c.

References _OpenWindowStation(), BOOL, CloseProtectedHandle(), FALSE, gbSecureDesktop, KernelMode, L, NT_SUCCESS, NTSTATUS(), NULL, PBYTE, RtlAppendUnicodeStringToString(), RtlAppendUnicodeToString(), RtlCopyUnicodeString(), RtlInitUnicodeString(), Status, szWindowStationDirectory, TRUE, UserMode, USHORT, and xxxOpenDesktop().

Referenced by NtUserResolveDesktopForWOW().

04590 { 04591 NTSTATUS Status; 04592 UNICODE_STRING strDesktop, strWinSta, strStatic; 04593 LPWSTR pszDesktop; 04594 BOOL fWinStaDefaulted; 04595 BOOL fDesktopDefaulted; 04596 HWINSTA hwinsta; 04597 HDESK hdesk; 04598 OBJECT_ATTRIBUTES ObjA; 04599 PUNICODE_STRING pstrStatic; 04600 POBJECT_ATTRIBUTES pObjA = NULL; 04601 SIZE_T cbObjA; 04602 BOOL bShutDown = FALSE; 04603 PTEB pteb = NtCurrentTeb(); 04604 04605 UserAssert(pteb); 04606 04607 /* 04608 * Determine windowstation and desktop names. 04609 */ 04610 04611 04612 if (pstrDesktop == NULL) { 04613 return STATUS_INVALID_PARAMETER; 04614 } 04615 04616 strStatic.Length = 0; 04617 strStatic.MaximumLength = STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR); 04618 04619 /* 04620 * Use the StaticUnicodeBuffer on the TEB as the buffer for the object name. 04621 * Even if this is client side and we pass KernelMode to the Ob call in 04622 * _OpenWindowStation this is safe because the TEB is not going to go away 04623 * during this call. The worst it can happen is to have the buffer in the TEB 04624 * trashed. 04625 */ 04626 strStatic.Buffer = pteb->StaticUnicodeBuffer; 04627 04628 UserAssert(pteb->StaticUnicodeBuffer == pteb->StaticUnicodeString.Buffer); 04629 UserAssert(pteb->StaticUnicodeString.MaximumLength ==STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR)); 04630 04631 if (pstrDesktop->Length == 0) { 04632 RtlInitUnicodeString(&strDesktop, TEXT("Default")); 04633 fWinStaDefaulted = fDesktopDefaulted = TRUE; 04634 } else { 04635 USHORT cch; 04636 /* 04637 * The name be of the form windowstation\desktop. Parse 04638 * the string to separate out the names. 04639 */ 04640 strWinSta = *pstrDesktop; 04641 cch = strWinSta.Length / sizeof(WCHAR); 04642 pszDesktop = strWinSta.Buffer; 04643 while (cch && *pszDesktop != L'\\') { 04644 cch--; 04645 pszDesktop++; 04646 } 04647 fDesktopDefaulted = FALSE; 04648 04649 if (cch == 0) { 04650 04651 /* 04652 * No windowstation name was specified, only the desktop. 04653 */ 04654 strDesktop = strWinSta; 04655 fWinStaDefaulted = TRUE; 04656 } else { 04657 /* 04658 * Both names were in the string. 04659 */ 04660 strDesktop.Buffer = pszDesktop + 1; 04661 strDesktop.Length = strDesktop.MaximumLength = (cch - 1) * sizeof(WCHAR); 04662 strWinSta.Length = (USHORT)(pszDesktop - strWinSta.Buffer) * sizeof(WCHAR); 04663 04664 /* 04665 * zero terminate the strWinSta buffer so the rebuild of the desktop 04666 * name at the end of the function works. 04667 */ 04668 *pszDesktop = (WCHAR)0; 04669 04670 fWinStaDefaulted = FALSE; 04671 04672 RtlAppendUnicodeToString(&strStatic, (PWSTR)szWindowStationDirectory); 04673 RtlAppendUnicodeToString(&strStatic, L"\\"); 04674 RtlAppendUnicodeStringToString(&strStatic, &strWinSta); 04675 04676 } 04677 } 04678 04679 if (fWinStaDefaulted) { 04680 04681 //Default Window Station 04682 RtlInitUnicodeString(&strWinSta, L"WinSta0"); 04683 04684 RtlAppendUnicodeToString(&strStatic, (PWSTR)szWindowStationDirectory); 04685 RtlAppendUnicodeToString(&strStatic, L"\\"); 04686 RtlAppendUnicodeStringToString(&strStatic, &strWinSta); 04687 04688 } 04689 04690 /* 04691 * Open the computed windowstation. This will also do an access check 04692 */ 04693 if (gbSecureDesktop) { 04694 /* 04695 * Allocate an object attributes structure in user address space. 04696 */ 04697 cbObjA = sizeof(*pObjA) + sizeof(*pstrStatic); 04698 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 04699 &pObjA, 0, &cbObjA, MEM_COMMIT, PAGE_READWRITE); 04700 pstrStatic = (PUNICODE_STRING)((PBYTE)pObjA + sizeof(*pObjA)); 04701 04702 if (NT_SUCCESS(Status)) { 04703 /* 04704 * Note -- the string must be in client-space or the 04705 * address validation in OpenWindowStation will fail. 04706 */ 04707 try { 04708 *pstrStatic = strStatic; 04709 InitializeObjectAttributes( pObjA, 04710 pstrStatic, 04711 OBJ_CASE_INSENSITIVE, 04712 NULL, 04713 NULL 04714 ); 04715 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 04716 Status = GetExceptionCode(); 04717 } 04718 04719 if (NT_SUCCESS(Status)) { 04720 hwinsta = _OpenWindowStation(pObjA, MAXIMUM_ALLOWED, UserMode); 04721 } else { 04722 hwinsta = NULL; 04723 } 04724 if (!hwinsta) { 04725 ZwFreeVirtualMemory(NtCurrentProcess(), &pObjA, &cbObjA, 04726 MEM_RELEASE); 04727 return STATUS_ACCESS_DENIED; 04728 } 04729 } else { 04730 return STATUS_NO_MEMORY; 04731 } 04732 } else { 04733 InitializeObjectAttributes( &ObjA, 04734 &strStatic, 04735 OBJ_CASE_INSENSITIVE, 04736 NULL, 04737 NULL 04738 ); 04739 hwinsta = _OpenWindowStation(&ObjA, MAXIMUM_ALLOWED, KernelMode); 04740 if (!hwinsta) { 04741 return STATUS_ACCESS_DENIED; 04742 } 04743 } 04744 04745 /* 04746 * Do an access check on the desktop by opening it 04747 */ 04748 04749 RtlCopyUnicodeString(&strStatic, &strDesktop); 04750 04751 if (gbSecureDesktop) { 04752 /* 04753 * Note -- the string must be in client-space or the 04754 * address validation in OpenDesktop will fail. 04755 */ 04756 try { 04757 *pstrStatic = strStatic; 04758 InitializeObjectAttributes( pObjA, 04759 pstrStatic, 04760 OBJ_CASE_INSENSITIVE, 04761 hwinsta, 04762 NULL 04763 ); 04764 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 04765 Status = GetExceptionCode(); 04766 } 04767 04768 if (NT_SUCCESS(Status)) { 04769 hdesk = xxxOpenDesktop(pObjA, 04770 UserMode, 04771 0, 04772 MAXIMUM_ALLOWED, 04773 &bShutDown); 04774 } else { 04775 hdesk = NULL; 04776 } 04777 04778 ZwFreeVirtualMemory(NtCurrentProcess(), &pObjA, &cbObjA, 04779 MEM_RELEASE); 04780 } else { 04781 InitializeObjectAttributes( &ObjA, 04782 &strStatic, 04783 OBJ_CASE_INSENSITIVE, 04784 hwinsta, 04785 NULL 04786 ); 04787 hdesk = xxxOpenDesktop(&ObjA, 04788 KernelMode, 04789 0, 04790 MAXIMUM_ALLOWED, 04791 &bShutDown); 04792 } 04793 04794 if (!hdesk) { 04795 UserVerify(NT_SUCCESS(ZwClose(hwinsta))); 04796 return STATUS_ACCESS_DENIED; 04797 } 04798 04799 CloseProtectedHandle(hdesk); 04800 UserVerify(NT_SUCCESS(ZwClose(hwinsta))); 04801 04802 /* 04803 * Copy the final Computed String 04804 */ 04805 RtlCopyUnicodeString(pstrDesktop, &strWinSta); 04806 RtlAppendUnicodeToString(pstrDesktop, L"\\"); 04807 RtlAppendUnicodeStringToString(pstrDesktop, &strDesktop); 04808 04809 return STATUS_SUCCESS; 04810 }

BOOL xxxSetDeskPattern PUNICODE_STRING  pProfileUserName,
LPWSTR  lpszPattern,
BOOL  fCreation
 

Definition at line 1105 of file desktop.c.

References BOOL, CheckCritIn, CXYDESKPATTERN, DESKTOP, FALSE, FastGetProfileStringFromIDW(), ghbmDesktop, hModuleWin, L, MAX_PATH, NULL, PMAP_DESKTOP, PWND_BROADCAST, RecolorDeskPattern(), ServerLoadString, SYSHBR, SYSRGB, TRUE, UINT, xxxRedrawScreen, and xxxSendNotifyMessage().

Referenced by xxxDesktopWndProc(), and xxxSystemParametersInfo().

01108 { 01109 LPWSTR p; 01110 int i; 01111 UINT val; 01112 WCHAR wszNone[20]; 01113 WCHAR wchValue[MAX_PATH]; 01114 WORD rgBits[CXYDESKPATTERN]; 01115 HBRUSH hBrushTemp; 01116 01117 CheckCritIn(); 01118 01119 /* 01120 * Get rid of the old bitmap (if any). 01121 */ 01122 if (ghbmDesktop != NULL) { 01123 GreDeleteObject(ghbmDesktop); 01124 ghbmDesktop = NULL; 01125 } 01126 01127 /* 01128 * Check if a pattern is passed via lpszPattern. 01129 */ 01130 if (lpszPattern != (LPWSTR)LongToPtr( (LONG)-1 )) { 01131 01132 /* 01133 * Yes! Then use that pattern; 01134 */ 01135 p = lpszPattern; 01136 goto GotThePattern; 01137 } 01138 01139 /* 01140 * Else, pickup the pattern selected in WIN.INI. 01141 * Get the "DeskPattern" string from WIN.INI's [Desktop] section. 01142 */ 01143 if (!FastGetProfileStringFromIDW(pProfileUserName, 01144 PMAP_DESKTOP, 01145 STR_DESKPATTERN, 01146 TEXT(""), 01147 wchValue, 01148 sizeof(wchValue)/sizeof(WCHAR) 01149 )) { 01150 return FALSE; 01151 } 01152 01153 ServerLoadString(hModuleWin, 01154 STR_NONE, 01155 wszNone, 01156 sizeof(wszNone)/sizeof(WCHAR)); 01157 01158 p = wchValue; 01159 01160 GotThePattern: 01161 01162 /* 01163 * Was a Desk Pattern selected? 01164 */ 01165 if (*p == TEXT('\0') || _wcsicmp(p, wszNone) == 0) { 01166 hBrushTemp = GreCreateSolidBrush(SYSRGB(DESKTOP)); 01167 if (hBrushTemp != NULL) { 01168 if (SYSHBR(DESKTOP)) { 01169 GreMarkDeletableBrush(SYSHBR(DESKTOP)); 01170 GreDeleteObject(SYSHBR(DESKTOP)); 01171 } 01172 GreMarkUndeletableBrush(hBrushTemp); 01173 SYSHBR(DESKTOP) = hBrushTemp; 01174 } 01175 GreSetBrushOwnerPublic(hBrushTemp); 01176 goto SDPExit; 01177 } 01178 01179 /* 01180 * Get eight groups of numbers seprated by non-numeric characters. 01181 */ 01182 for (i = 0; i < CXYDESKPATTERN; i++) { 01183 val = 0; 01184 01185 /* 01186 * Skip over any non-numeric characters, check for null EVERY time. 01187 */ 01188 while (*p && !(*p >= TEXT('0') && *p <= TEXT('9'))) 01189 p++; 01190 01191 /* 01192 * Get the next series of digits. 01193 */ 01194 while (*p >= TEXT('0') && *p <= TEXT('9')) 01195 val = val * (UINT)10 + (UINT)(*p++ - TEXT('0')); 01196 01197 rgBits[i] = (WORD)val; 01198 } 01199 01200 ghbmDesktop = GreCreateBitmap(CXYDESKPATTERN, 01201 CXYDESKPATTERN, 01202 1, 01203 1, 01204 (LPBYTE)rgBits); 01205 01206 if (ghbmDesktop == NULL) 01207 return FALSE; 01208 01209 GreSetBitmapOwner(ghbmDesktop, OBJECT_OWNER_PUBLIC); 01210 01211 RecolorDeskPattern(); 01212 01213 SDPExit: 01214 if (!fCreation) { 01215 01216 /* 01217 * Notify everyone that the colors have changed. 01218 */ 01219 xxxSendNotifyMessage(PWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0L); 01220 01221 /* 01222 * Update the entire screen. If this is creation, don't update: the 01223 * screen hasn't drawn, and also there are some things that aren't 01224 * initialized yet. 01225 */ 01226 xxxRedrawScreen(); 01227 } 01228 01229 return TRUE; 01230 }

BOOL xxxSetThreadDesktop HDESK  hdesk,
PDESKTOP  pdesk
 

Definition at line 4033 of file desktop.c.

References AllocQueue(), BOOL, tagQ::cThreads, tagTHREADINFO::cWindows, FALSE, tagTHREADINFO::fsHooks, GetDesktopView(), gpepCSRSS, gpqForeground, GTERMF_MOUSE, tagTHREADINFO::iCursorLevel, tagQ::iCursorLevel, LockDesktop, MapDesktop(), NULL, ObOpenHandle, tagTHREADINFO::ppi, tagTHREADINFO::pq, PtiCurrent, tagTHREADINFO::rpdesk, tagPROCESSINFO::rpdeskStartup, tagQ::spwndActive, tagQ::spwndActivePrev, tagQ::spwndCapture, tagQ::spwndFocus, TEST_GTERMF, TRUE, xxxSetForegroundWindow2(), zzzAttachToQueue(), and zzzSetDesktop().

Referenced by NtUserSetThreadDesktop(), xxxDesktopThread(), xxxDesktopWndProc(), xxxNextWindow(), xxxRestoreCsrssThreadDesktop(), and xxxSetCsrssThreadDesktop().

04036 { 04037 PTHREADINFO ptiCurrent; 04038 PPROCESSINFO ppiCurrent; 04039 PQ pqAttach; 04040 04041 ptiCurrent = PtiCurrent(); 04042 ppiCurrent = ptiCurrent->ppi; 04043 04044 04045 /* 04046 * If the handle has not been mapped in, do it now. 04047 */ 04048 if (pdesk != NULL) { 04049 try { 04050 MapDesktop(ObOpenHandle, ppiCurrent->Process, pdesk, 0, 1); 04051 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 04052 return FALSE; 04053 } 04054 04055 UserAssert(GetDesktopView(ppiCurrent, pdesk) != NULL); 04056 } 04057 04058 /* 04059 * Check non-system thread status 04060 */ 04061 if (ptiCurrent->pEThread->ThreadsProcess != gpepCSRSS) { 04062 04063 /* 04064 * Fail if the non-system thread has any windows or thread hooks. 04065 */ 04066 if (ptiCurrent->cWindows != 0 || ptiCurrent->fsHooks) { 04067 RIPERR0(ERROR_BUSY, RIP_WARNING, "Thread has windows or hooks"); 04068 return FALSE; 04069 } 04070 04071 /* 04072 * If this is the first desktop assigned to the process, 04073 * make it the startup desktop. 04074 */ 04075 if (ppiCurrent->rpdeskStartup == NULL && hdesk != NULL) { 04076 LockDesktop(&ppiCurrent->rpdeskStartup, pdesk, LDL_PPI_DESKSTARTUP1, (ULONG_PTR)ppiCurrent); 04077 ppiCurrent->hdeskStartup = hdesk; 04078 } 04079 } 04080 04081 04082 /* 04083 * If the desktop is changing and the thread is sharing a queue, 04084 * detach the thread. This will ensure that threads sharing 04085 * queues are all on the same desktop. This will prevent 04086 * zzzDestroyQueue from getting confused and setting ptiKeyboard 04087 * and ptiMouse to NULL when a thread detachs. 04088 */ 04089 if (ptiCurrent->rpdesk != pdesk) { 04090 if (ptiCurrent->pq->cThreads > 1) { 04091 pqAttach = AllocQueue(NULL, NULL); 04092 if (pqAttach != NULL) { 04093 pqAttach->cThreads++; 04094 zzzAttachToQueue(ptiCurrent, pqAttach, NULL, FALSE); 04095 } else { 04096 RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_WARNING, "Thread could not be detached"); 04097 return FALSE; 04098 } 04099 } else if (ptiCurrent->pq == gpqForeground) { 04100 /* 04101 * This thread doesn't own any windows, still it's attached to qpgForeground and 04102 * it's the only thread attached to it. 04103 * Since any threads attached to qpgForeground must be in grpdeskRitInput, 04104 * we must set qpgForeground to NULL here because this thread is going to another 04105 * desktop. 04106 */ 04107 UserAssert(ptiCurrent->pq->spwndActive == NULL); 04108 UserAssert(ptiCurrent->pq->spwndCapture == NULL); 04109 UserAssert(ptiCurrent->pq->spwndFocus == NULL); 04110 UserAssert(ptiCurrent->pq->spwndActivePrev == NULL); 04111 xxxSetForegroundWindow2(NULL, ptiCurrent, 0); 04112 } else if (ptiCurrent->rpdesk == NULL) { 04113 /* 04114 * We need to initialize iCursorLevel. 04115 */ 04116 ptiCurrent->iCursorLevel = TEST_GTERMF(GTERMF_MOUSE) ? 0 : -1; 04117 ptiCurrent->pq->iCursorLevel = ptiCurrent->iCursorLevel; 04118 } 04119 04120 UserAssert(ptiCurrent->pq != gpqForeground); 04121 04122 } 04123 04124 zzzSetDesktop(ptiCurrent, pdesk, hdesk); 04125 04126 return TRUE; 04127 }

BOOL xxxSwitchDesktop PWINDOWSTATION  pwinsta,
PDESKTOP  pdesk,
BOOL  bCreateNew
 

Definition at line 3358 of file desktop.c.

References tagQ::afKeyRecentDown, AllocQueue(), BOOL, CBKEYSTATERECENTDOWN, CheckCritIn, _ETHREAD::Cid, tagQ::cThreads, DF_DESKWNDDESTROYED, DF_DESTROYED, DF_DYING, DF_NEWDISPLAYSETTINGS, tagDESKTOP::dwDTFlags, DWORD, tagWINDOWSTATION::dwWSF_Flags, EVENT_INCREMENT, FALSE, FreeAllSpbs(), gbDesktopLocked, GetFullScreen, GETPTI, gHardErrorHandler, gpEventSwitchDesktop, gpidLogon, gpqCursor, gpqForeground, gpsi, gptiRit, grpdeskLogon, grpdeskRitInput, gspdeskDisconnect, gspdeskShouldBeForeground, gspwndAltTab, tagDISPLAYINFO::hDev, HMIsMarkDestroy, IPostQuitMessage(), IS_SYSTEM_THREAD, IsWinEventNotifyDeferredOK, KePulseEvent(), KernelMode, Lock, LockDesktop, NT_SUCCESS, NTSTATUS(), NULL, ObOpenObjectByPointer(), tagDESKTOP::pDeskInfo, tagDESKTOP::pDispInfo, tagDISPLAYINFO::pmdev, POBJECT_NAME, PostUpdateKeyStateEvent(), tagTHREADINFO::pq, tagTERMINAL::pqDesktop, PsGetCurrentThread, tagWINDOWSTATION::pTerm, tagHARDERRORHANDLER::pti, PtiCurrent, tagTERMINAL::ptiDesktop, tagDESKTOP::PtiList, tagQ::QF_flags, QF_KEYSTATERESET, QF_UPDATEKEYSTATE, tagTHREADINFO::rpdesk, tagDESKTOP::rpwinstaParent, SetFullScreen, SetPointer(), tagDESKTOPINFO::spwnd, tagQ::spwndActive, tagWND::spwndChild, tagDESKTOP::spwndForeground, tagWND::spwndNext, Status, TestWF, ThreadLockAlwaysWithPti, ThreadLockDesktopHandle, ThreadLockWithPti, ThreadUnlock, ThreadUnlockDesktopHandle, TRACE_DESKTOP, TRACE_INIT, TRUE, Unlock, WFVISIBLE, WSF_NOIO, WSF_SWITCHLOCK, xxxBroadcastDisplaySettingsChange(), xxxSendMessage(), xxxSetForegroundWindow2(), xxxSetWindowPos(), zzzAttachToQueue(), zzzCancelJournalling(), zzzInternalSetCursorPos(), and zzzSetDesktop().

Referenced by NtUserSwitchDesktop(), RawInputThread(), RemoteDisableScreen(), RemoteRedrawScreen(), xxxCreateDesktop(), xxxDesktopThread(), and xxxQueryInformationThread().

03362 { 03363 PETHREAD Thread; 03364 PWND pwndSetForeground; 03365 TL tlpwndChild; 03366 TL tlpwnd; 03367 TL tlhdesk; 03368 PQ pq; 03369 BOOL bUpdateCursor = FALSE; 03370 PLIST_ENTRY pHead, pEntry; 03371 PTHREADINFO pti; 03372 PTHREADINFO ptiCurrent = PtiCurrent(); 03373 PTERMINAL pTerm; 03374 NTSTATUS Status; 03375 HDESK hdesk; 03376 03377 CheckCritIn(); 03378 03379 UserAssert(IsWinEventNotifyDeferredOK()); 03380 03381 if (pdesk == NULL) { 03382 return FALSE; 03383 } 03384 03385 if (pdesk == grpdeskRitInput) { 03386 return TRUE; 03387 } 03388 03389 if (pdesk->dwDTFlags & DF_DESTROYED) { 03390 RIPMSG1(RIP_ERROR, "xxxSwitchDesktop: destroyed:%#p", pdesk); 03391 return FALSE; 03392 } 03393 03394 UserAssert(!(pdesk->dwDTFlags & (DF_DESKWNDDESTROYED | DF_DYING))); 03395 03396 if (pwinsta == NULL) 03397 pwinsta = pdesk->rpwinstaParent; 03398 03399 /* 03400 * Get the windowstation, and assert if this process doesn't have one. 03401 */ 03402 UserAssert(pwinsta); 03403 if (pwinsta == NULL) { 03404 RIPMSG1(RIP_WARNING, 03405 "xxxSwitchDesktop: failed for pwinsta NULL pdesk %#p", pdesk); 03406 return FALSE; 03407 } 03408 03409 /* 03410 * Don't allow invisible desktops to become active 03411 */ 03412 if (pwinsta->dwWSF_Flags & WSF_NOIO) { 03413 RIPMSG1(RIP_VERBOSE, 03414 "xxxSwitchDesktop: failed for NOIO pdesk %#p", pdesk); 03415 return FALSE; 03416 } 03417 03418 pTerm = pwinsta->pTerm; 03419 03420 UserAssert(grpdeskRitInput == pwinsta->pdeskCurrent); 03421 03422 /* 03423 * Do tracing only if compiled in. 03424 */ 03425 TRACE_INIT(("xxxSwitchDesktop: Entering, desktop = %ws, createdNew = %01lx\n", POBJECT_NAME(pdesk), (DWORD)bCreateNew)); 03426 if (grpdeskRitInput) { 03427 TRACE_INIT((" coming from desktop = %ws\n", POBJECT_NAME(grpdeskRitInput))); 03428 } 03429 03430 /* 03431 * Wait if the logon has the windowstation locked 03432 */ 03433 Thread = PsGetCurrentThread(); 03434 03435 /* 03436 * Allow switches to the disconnected desktop 03437 */ 03438 if (pdesk != gspdeskDisconnect) 03439 if (!IS_SYSTEM_THREAD(Thread) && pwinsta->dwWSF_Flags & WSF_SWITCHLOCK && 03440 pdesk != grpdeskLogon && 03441 Thread->Cid.UniqueProcess != gpidLogon) 03442 return FALSE; 03443 03444 /* 03445 * We don't allow switching away from the disconnect desktop. 03446 */ 03447 if (gbDesktopLocked && ((!gspdeskDisconnect) || (pdesk != gspdeskDisconnect))) { 03448 TRACE_DESKTOP(("Attempt to switch away from the disconnect desktop\n")); 03449 03450 /* 03451 * we should not lock this global !!! clupu 03452 */ 03453 LockDesktop(&gspdeskShouldBeForeground, pdesk, LDL_DESKSHOULDBEFOREGROUND1, 0); 03454 return TRUE; 03455 } 03456 03457 /* 03458 * HACKHACK LATER !!! 03459 * Where should we really switch the desktop ... 03460 * And we need to send repaint messages to everyone... 03461 * 03462 */ 03463 03464 UserAssert(grpdeskRitInput == pwinsta->pdeskCurrent); 03465 03466 if (!bCreateNew && grpdeskRitInput && 03467 (grpdeskRitInput->pDispInfo->hDev != pdesk->pDispInfo->hDev)) { 03468 03469 if (!DrvDisableMDEV(grpdeskRitInput->pDispInfo->pmdev, TRUE)) { 03470 RIPMSG1(RIP_WARNING, "xxxSwitchDesktop: DrvDisableMDEV failed for pdesk %#p", 03471 grpdeskRitInput); 03472 return FALSE; 03473 } 03474 DrvEnableMDEV(pdesk->pDispInfo->pmdev, TRUE); 03475 bUpdateCursor = TRUE; 03476 03477 } 03478 03479 /* 03480 * Grab a handle to the pdesk 03481 */ 03482 Status = ObOpenObjectByPointer(pdesk, 03483 0, 03484 NULL, 03485 EVENT_ALL_ACCESS, 03486 NULL, 03487 KernelMode, 03488 &hdesk); 03489 if (!NT_SUCCESS(Status)) { 03490 03491 RIPMSG2(RIP_ERROR, "Could not get a handle for pdesk %#p Status %x", 03492 pdesk, Status); 03493 return FALSE; 03494 } 03495 03496 ThreadLockDesktopHandle(ptiCurrent, &tlhdesk, hdesk); 03497 03498 #if DBG 03499 /* 03500 * The current desktop is now the new desktop. 03501 */ 03502 pwinsta->pdeskCurrent = pdesk; 03503 #endif // DBG 03504 03505 /* 03506 * Kill any journalling that is occuring. If an app is journaling to 03507 * the CoolSwitch window, zzzCancelJournalling() will kill the window. 03508 */ 03509 if (ptiCurrent->rpdesk != NULL) 03510 zzzCancelJournalling(); 03511 03512 /* 03513 * Remove the cool switch window if it's on the RIT. Sending the message 03514 * is OK because the destination is the RIT, which should never block. 03515 */ 03516 if (gspwndAltTab != NULL) { 03517 03518 TL tlpwndT; 03519 03520 ThreadLockWithPti(ptiCurrent, gspwndAltTab, &tlpwndT); 03521 xxxSendMessage(gspwndAltTab, WM_CLOSE, 0, 0); 03522 ThreadUnlock(&tlpwndT); 03523 } 03524 03525 /* 03526 * Remove all trace of previous active window. 03527 */ 03528 if (grpdeskRitInput != NULL) { 03529 03530 UserAssert(grpdeskRitInput->spwndForeground == NULL); 03531 03532 if (grpdeskRitInput->pDeskInfo->spwnd != NULL) { 03533 if (gpqForeground != NULL) { 03534 03535 Lock(&grpdeskRitInput->spwndForeground, 03536 gpqForeground->spwndActive); 03537 03538 /* 03539 * This is an API so ptiCurrent can pretty much be on any 03540 * state; it might not be in grpdeskRitInput (current) or 03541 * pdesk (the one we're switching to). It can be sharing its 03542 * queue with other threads from another desktop. 03543 * This is tricky because we're calling xxxSetForegroundWindow 03544 * and xxxSetWindowPos but PtiCurrent might be on whatever 03545 * desktop. We cannot cleanly switch ptiCurrent to the proper 03546 * desktop because it might be sharing its queue with other 03547 * threads, own windows, hooks, etc. So this is kind of broken. 03548 * 03549 * Old Comment: 03550 * Fixup the current-thread (system) desktop. This 03551 * could be needed in case the xxxSetForegroundWindow() 03552 * calls xxxDeactivate(). There is logic in their which 03553 * requires the desktop. This is only needed temporarily 03554 * for this case. 03555 * 03556 * We would only go into xxxDeactivate if 03557 * ptiCurrent->pq == qpqForeground; but if this is the case, 03558 * then ptiCurrent must be in grpdeskRitInput already. So 03559 * I don't think we need this at all. Let's find out. 03560 * Note that we might switch queues while processing the 03561 * xxxSetForegroundWindow call. That should be fine as long 03562 * as we don't switch desktops..... 03563 */ 03564 UserAssert((ptiCurrent->pq != gpqForeground) 03565 || (ptiCurrent->rpdesk == grpdeskRitInput)); 03566 03567 /* 03568 * The SetForegroundWindow call must succed here, so we call 03569 * xxxSetForegroundWindow2() directly 03570 */ 03571 xxxSetForegroundWindow2(NULL, ptiCurrent, 0); // WHAT KEEPS pdesk LOCKED - IANJA ??? 03572 03573 } 03574 } 03575 } 03576 03577 /* 03578 * Post update events to all queues sending input to the desktop 03579 * that is becoming inactive. This keeps the queues in sync up 03580 * to the desktop switch. 03581 */ 03582 if (grpdeskRitInput != NULL) { 03583 03584 pHead = &grpdeskRitInput->PtiList; 03585 03586 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 03587 03588 pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 03589 pq = pti->pq; 03590 03591 if (pq->QF_flags & QF_UPDATEKEYSTATE) 03592 PostUpdateKeyStateEvent(pq); 03593 03594 /* 03595 * Clear the reset bit to ensure that we can properly 03596 * reset the key state when this desktop again becomes 03597 * active. 03598 */ 03599 pq->QF_flags &= ~QF_KEYSTATERESET; 03600 } 03601 } 03602 03603 /* 03604 * Send the RIT input to the desktop. We do this before any window 03605 * management since DoPaint() uses grpdeskRitInput to go looking for 03606 * windows with update regions. 03607 */ 03608 LockDesktop(&grpdeskRitInput, pdesk, LDL_DESKRITINPUT, 0); 03609 03610 /* 03611 * Free any spbs that are only valid for the previous desktop. 03612 */ 03613 FreeAllSpbs(); 03614 03615 /* 03616 * Lock it into the RIT thread (we could use this desktop rather than 03617 * the global grpdeskRitInput to direct input!) 03618 */ 03619 zzzSetDesktop(gptiRit, pdesk, NULL); // DeferWinEventNotify() ?? IANJA ?? 03620 03621 /* 03622 * Lock the desktop into the desktop thread. Be sure 03623 * that the thread is using an unattached queue before 03624 * setting the desktop. This is needed to ensure that 03625 * the thread does not using a shared journal queue 03626 * for the old desktop. 03627 */ 03628 if (pTerm->ptiDesktop->pq != pTerm->pqDesktop) { 03629 UserAssert(pTerm->pqDesktop->cThreads == 0); 03630 AllocQueue(NULL, pTerm->pqDesktop); 03631 pTerm->pqDesktop->cThreads++; 03632 zzzAttachToQueue(pTerm->ptiDesktop, pTerm->pqDesktop, NULL, FALSE); 03633 } 03634 zzzSetDesktop(pTerm->ptiDesktop, pdesk, NULL); // DeferWinEventNotify() ?? IANJA ?? 03635 03636 /* 03637 * Bring the desktop window to the top and invalidate 03638 * everything. 03639 */ 03640 ThreadLockWithPti(ptiCurrent, pdesk->pDeskInfo->spwnd, &tlpwnd); 03641 03642 03643 /* 03644 * Suspend DirectDraw before we bring up the desktop window, so we make 03645 * sure that everything is repainted properly once DirectDraw is disabled. 03646 */ 03647 03648 GreSuspendDirectDraw(pdesk->pDispInfo->hDev, TRUE); 03649 03650 xxxSetWindowPos(pdesk->pDeskInfo->spwnd, // WHAT KEEPS pdesk LOCKED - IANJA ??? 03651 NULL, 03652 0, 03653 0, 03654 0, 03655 0, 03656 SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOCOPYBITS); 03657 03658 /* 03659 * At this point, my understanding is that the new desktop window has been 03660 * brought to the front, and therefore the vis-region of any app on any 03661 * other desktop is now NULL. 03662 * 03663 * So this is the appropriate time to resume DirectDraw, which will 03664 * ensure the DirectDraw app can not draw anything in the future. 03665 * 03666 * If this is not the case, then this code needs to be moved to a more 03667 * appropriate location. 03668 * 03669 * [andreva] 6-26-96 03670 */ 03671 03672 GreResumeDirectDraw(pdesk->pDispInfo->hDev, TRUE); 03673 03674 /* 03675 * Find the first visible top-level window. 03676 */ 03677 pwndSetForeground = pdesk->spwndForeground; 03678 if (pwndSetForeground == NULL || HMIsMarkDestroy(pwndSetForeground)) { 03679 03680 pwndSetForeground = pdesk->pDeskInfo->spwnd->spwndChild; 03681 03682 while ((pwndSetForeground != NULL) && 03683 !TestWF(pwndSetForeground, WFVISIBLE)) { 03684 03685 pwndSetForeground = pwndSetForeground->spwndNext; 03686 } 03687 } 03688 Unlock(&pdesk->spwndForeground); 03689 03690 /* 03691 * Now set it to the foreground. 03692 */ 03693 03694 if (pwndSetForeground == NULL) { 03695 xxxSetForegroundWindow2(NULL, NULL, 0); 03696 } else { 03697 03698 UserAssert(GETPTI(pwndSetForeground)->rpdesk == grpdeskRitInput); 03699 /* 03700 * If the new foreground window is a minimized fullscreen app, 03701 * make it fullscreen. 03702 */ 03703 if (GetFullScreen(pwndSetForeground) == FULLSCREENMIN) { 03704 SetFullScreen(pwndSetForeground, FULLSCREEN); 03705 } 03706 03707 ThreadLockAlwaysWithPti(ptiCurrent, pwndSetForeground, &tlpwndChild); 03708 /* 03709 * The SetForegroundWindow call must succed here, so we call 03710 * xxxSetForegroundWindow2() directly 03711 */ 03712 xxxSetForegroundWindow2(pwndSetForeground, ptiCurrent, 0); 03713 ThreadUnlock(&tlpwndChild); 03714 } 03715 03716 03717 ThreadUnlock(&tlpwnd); 03718 03719 /* 03720 * Overwrite key state of all queues sending input to the new 03721 * active desktop with the current async key state. This 03722 * prevents apps on inactive desktops from spying on active 03723 * desktops. This blows away anything set with SetKeyState, 03724 * but there is no way of preserving this without giving 03725 * away information about what keys were hit on other 03726 * desktops. 03727 */ 03728 pHead = &grpdeskRitInput->PtiList; 03729 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 03730 03731 pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 03732 pq = pti->pq; 03733 03734 if (!(pq->QF_flags & QF_KEYSTATERESET)) { 03735 pq->QF_flags |= QF_UPDATEKEYSTATE | QF_KEYSTATERESET; 03736 RtlFillMemory(pq->afKeyRecentDown, CBKEYSTATERECENTDOWN, 0xff); 03737 PostUpdateKeyStateEvent(pq); 03738 } 03739 } 03740 03741 /* 03742 * If there is a hard-error popup up, nuke it and notify the 03743 * hard error thread that it needs to pop it up again. 03744 */ 03745 if (gHardErrorHandler.pti) { 03746 IPostQuitMessage(gHardErrorHandler.pti, 0); 03747 } 03748 03749 /* 03750 * Notify anyone waiting for a desktop switch. 03751 */ 03752 UserAssert(!(pdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO)); 03753 03754 KePulseEvent(gpEventSwitchDesktop, EVENT_INCREMENT, FALSE); 03755 03756 /* 03757 * reset the cursor when we come back from another pdev 03758 */ 03759 if (bUpdateCursor == TRUE) { 03760 03761 gpqCursor = NULL; 03762 zzzInternalSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y); 03763 03764 SetPointer(TRUE); 03765 } 03766 03767 /* 03768 * Make sure we come back to the right mode when this is all done, because 03769 * the device may be left in an interesting state if we were running 03770 * DirectDraw. 03771 */ 03772 03773 { 03774 /* 03775 * Don't check the return code right now since there is nothing 03776 * we can do if we can not reset the mode ... 03777 */ 03778 03779 // BUGBUG 03780 // DONT_CHECKIN 03781 03782 //UserChangeDisplaySettings(pdesk->pDispInfo->hDevInfo, 03783 // pdesk->pDesktopDevmode, 03784 // _GetDesktopWindow(), 03785 // pdesk, 03786 // 0, 03787 // NULL, 03788 // TRUE); 03789 } 03790 03791 03792 /* 03793 * If this desktop was not active during last display settings change 03794 * let's now bradcast the settings change to its windows. This 03795 * code is copied from xxxResetDisplayDevice(). 03796 */ 03797 03798 03799 if ((pdesk->dwDTFlags & DF_NEWDISPLAYSETTINGS) && pdesk->pDeskInfo && pdesk->pDeskInfo->spwnd ){ 03800 03801 pdesk->dwDTFlags &= ~DF_NEWDISPLAYSETTINGS; 03802 xxxBroadcastDisplaySettingsChange(pdesk, TRUE); 03803 03804 03805 } 03806 03807 ThreadUnlockDesktopHandle(&tlhdesk); 03808 03809 TRACE_INIT(("xxxSwitchDesktop: Leaving\n")); 03810 03811 return TRUE; 03812 }

NTSTATUS xxxUserDuplicateObject IN HANDLE  SourceProcessHandle,
IN HANDLE  SourceHandle,
IN HANDLE TargetProcessHandle  OPTIONAL,
OUT PHANDLE TargetHandle  OPTIONAL,
IN ACCESS_MASK  DesiredAccess,
IN ULONG  HandleAttributes,
IN ULONG  Options
 

Definition at line 4137 of file desktop.c.

References CheckCritIn, EnterCrit, LeaveCrit, NTSTATUS(), and Status.

04147 { 04148 NTSTATUS Status; 04149 04150 CheckCritIn(); 04151 04152 LeaveCrit(); 04153 04154 Status = ZwDuplicateObject(SourceProcessHandle, SourceHandle, TargetProcessHandle, 04155 TargetHandle, DesiredAccess, HandleAttributes, Options); 04156 04157 EnterCrit(); 04158 04159 return Status; 04160 }

BOOLEAN xxxUserFindHandleForObject IN PEPROCESS  Process,
IN PVOID Object  OPTIONAL,
IN POBJECT_TYPE ObjectType  OPTIONAL,
IN POBJECT_HANDLE_INFORMATION HandleInformation  OPTIONAL,
OUT PHANDLE  Handle
 

Definition at line 4171 of file desktop.c.

References BOOL, EnterCrit, EnterSharedCrit(), ExIsResourceAcquiredExclusiveLite(), ExIsResourceAcquiredSharedLite(), gpresUser, Handle, LeaveCrit, ObFindHandleForObject(), and POBJECT_HANDLE_INFORMATION.

Referenced by xxxGetInputDesktop(), xxxGetThreadDesktop(), and xxxResolveDesktop().

04178 { 04179 BOOLEAN fRet; 04180 BOOL fExclusive, fShared; 04181 04182 fExclusive = ExIsResourceAcquiredExclusiveLite(gpresUser); 04183 if (!fExclusive) { 04184 fShared = ExIsResourceAcquiredSharedLite(gpresUser); 04185 } 04186 04187 if (fExclusive || fShared) { 04188 LeaveCrit(); 04189 } 04190 04191 fRet = ObFindHandleForObject(Process, Object, ObjectType, HandleInformation, Handle); 04192 04193 if (fExclusive) { 04194 EnterCrit(); 04195 } else if (fShared) { 04196 EnterSharedCrit(); 04197 } 04198 04199 return fRet; 04200 }

VOID xxxUserResetDisplayDevice  ) 
 

Definition at line 3136 of file desktop.c.

References BMSG_SENDNOTIFYMSG, gpqCursor, gpsi, grpdeskRitInput, NULL, tagDESKTOP::pDeskInfo, SetPointer(), tagDESKTOPINFO::spwnd, SYSMET, ThreadLock, ThreadUnlock, TRACE_INIT, TRUE, VOID(), xxxBroadcastMessage(), xxxRedrawWindow(), and zzzInternalSetCursorPos().

Referenced by NtUserEnumDisplayDevices(), VideoPortCalloutThread(), xxxCreateDesktop2(), xxxUserChangeDisplaySettings(), and xxxUserPowerEventCalloutWorker().

03137 { 03138 TL tlpwnd; 03139 TRACE_INIT(("xxxUserResetDisplayDevice: about to reset the device\n")); 03140 03141 /* 03142 * Handle early system initialization gracefully. 03143 */ 03144 if (grpdeskRitInput != NULL) { 03145 ThreadLock(grpdeskRitInput->pDeskInfo->spwnd, &tlpwnd); 03146 #if 0 03147 // what should we do here to notify the display applet ? 03148 // AndreVa 03149 03150 /* 03151 * Broadcast that the display has changed resolution. We are going 03152 * to specify the desktop for the changing-desktop. That way we 03153 * don't get confused as to what desktop to broadcast to. 03154 */ 03155 xxxBroadcastMessage(grpdeskRitInput->pDeskInfo->spwnd, 03156 WM_DISPLAYCHANGE, 03157 gpsi->BitCount, 03158 MAKELONG(SYSMET(CXSCREEN), SYSMET(CYSCREEN)), 03159 BMSG_SENDNOTIFYMSG, 03160 NULL); 03161 #endif 03162 xxxRedrawWindow(grpdeskRitInput->pDeskInfo->spwnd, 03163 NULL, 03164 NULL, 03165 RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW | 03166 RDW_ALLCHILDREN); 03167 gpqCursor = NULL; 03168 03169 /* 03170 * No need to DeferWinEventNotify() - we just made an xxx call above 03171 */ 03172 zzzInternalSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y); 03173 03174 SetPointer(TRUE); 03175 03176 ThreadUnlock(&tlpwnd); 03177 } 03178 03179 TRACE_INIT(("xxxUserResetDisplayDevice: complete\n")); 03180 03181 }

VOID zzzSetDesktop PTHREADINFO  pti,
PDESKTOP  pdesk,
HDESK  hdesk
 

Definition at line 3823 of file desktop.c.

References tagTHREADINFO::amdesk, CheckHandleFlag(), CLIENTTHREADINFO, tagQ::cThreads, tagTHREADINFO::cWindows, DesktopAllocAlways, DesktopFree, DF_DESKWNDDESTROYED, DF_DYING, diStatic, DTAG_CLIENTTHREADINFO, tagDESKTOP::dwConsoleThreadId, tagDESKTOP::dwDTFlags, tagDESKTOP::dwSessionId, ExDesktopObjectType, FALSE, GetDesktopView(), GetJournallingQueue(), _OBJECT_HANDLE_INFORMATION::GrantedAccess, gSessionId, GTERMF_MOUSE, tagTHREADINFO::hdesk, HF_DESKTOPHOOK, HF_PROTECTED, ISATOMICCHECK, KernelMode, LockDesktop, LogDesktop, NT_SUCCESS, NULL, ObDereferenceObject, OBJECT_HANDLE_INFORMATION, ObReferenceObjectByHandle(), PBYTE, tagTHREADINFO::pcti, tagDESKTOP::pDeskInfo, tagTHREADINFO::pq, PtiCurrent, tagTHREADINFO::PtiLink, tagDESKTOP::PtiList, tagTHREADINFO::rpdesk, SetHandleFlag(), TEST_GTERMF, ThreadLockDesktop, ThreadUnlockDesktop, TIDq, TIF_ALLOWOTHERACCOUNTHOOK, tagTHREADINFO::TIF_flags, TRUE, VOID(), and zzzAttachToQueue().

Referenced by xxxCreateDesktop(), xxxCreateThreadInfo(), xxxCreateWindowStation(), xxxSetThreadDesktop(), and xxxSwitchDesktop().

03827 { 03828 PTEB pteb; 03829 OBJECT_HANDLE_INFORMATION ohi; 03830 PDESKTOP pdeskRef; 03831 PDESKTOP pdeskOld; 03832 PCLIENTTHREADINFO pctiOld; 03833 TL tlpdesk; 03834 PTHREADINFO ptiCurrent = PtiCurrent(); 03835 03836 if (pti == NULL) { 03837 UserAssert(pti); 03838 return; 03839 } 03840 03841 /* 03842 * A handle without an object pointer is bad news. 03843 */ 03844 UserAssert(pdesk != NULL || hdesk == NULL); 03845 03846 /* 03847 * This desktop must not be destroyed 03848 */ 03849 if (pdesk != NULL && (pdesk->dwDTFlags & (DF_DESKWNDDESTROYED | DF_DYING)) && 03850 pdesk != pti->rpdesk) { 03851 RIPMSG2(RIP_ERROR, "Assigning pti %#p to a dying desktop %#p", 03852 pti, pdesk); 03853 return; 03854 } 03855 03856 #if DBG 03857 /* 03858 * Catch reset of important desktops 03859 */ 03860 if (pti->rpdesk && pti->rpdesk->dwConsoleThreadId == TIDq(pti) && 03861 pti->cWindows != 0) { 03862 RIPMSG0(RIP_ERROR, "Reset of console desktop"); 03863 } 03864 #endif 03865 03866 /* 03867 * Clear hook flag 03868 */ 03869 pti->TIF_flags &= ~TIF_ALLOWOTHERACCOUNTHOOK; 03870 03871 /* 03872 * Get granted access 03873 */ 03874 pti->hdesk = hdesk; 03875 if (hdesk != NULL) { 03876 if (NT_SUCCESS(ObReferenceObjectByHandle(hdesk, 03877 0, 03878 *ExDesktopObjectType, 03879 KernelMode, 03880 &pdeskRef, 03881 &ohi))) { 03882 03883 UserAssert(pdesk->dwSessionId == gSessionId); 03884 03885 LogDesktop(pdeskRef, LD_REF_FN_SETDESKTOP, TRUE, (ULONG_PTR)PtiCurrent()); 03886 03887 UserAssert(pdeskRef == pdesk); 03888 LogDesktop(pdesk, LD_DEREF_FN_SETDESKTOP, FALSE, (ULONG_PTR)PtiCurrent()); 03889 ObDereferenceObject(pdeskRef); 03890 pti->amdesk = ohi.GrantedAccess; 03891 if (CheckHandleFlag(hdesk, HF_DESKTOPHOOK)) 03892 pti->TIF_flags |= TIF_ALLOWOTHERACCOUNTHOOK; 03893 03894 SetHandleFlag(hdesk, HF_PROTECTED, TRUE); 03895 03896 } else { 03897 pti->amdesk = 0; 03898 } 03899 03900 } else { 03901 pti->amdesk = 0; 03902 } 03903 03904 /* 03905 * Do nothing else if the thread has initialized and the desktop 03906 * is not changing. 03907 */ 03908 if ((pdesk != NULL) && (pdesk == pti->rpdesk)) 03909 return; 03910 03911 /* 03912 * Save old pointers for later. Locking the old desktop ensures 03913 * that we will be able to free the CLIENTTHREADINFO structure. 03914 */ 03915 pdeskOld = pti->rpdesk; 03916 ThreadLockDesktop(ptiCurrent, pdeskOld, &tlpdesk, LDLT_FN_SETDESKTOP); 03917 pctiOld = pti->pcti; 03918 03919 /* 03920 * Remove the pti from the current desktop. 03921 */ 03922 if (pti->rpdesk) { 03923 UserAssert(ISATOMICCHECK() || pti->pq == NULL || pti->pq->cThreads == 1); 03924 RemoveEntryList(&pti->PtiLink); 03925 } 03926 03927 LockDesktop(&pti->rpdesk, pdesk, LDL_PTI_DESK, (ULONG_PTR)pti); 03928 03929 03930 /* 03931 * If there is no desktop, we need to fake a desktop info 03932 * structure so that the IsHooked() macro can test a "valid" 03933 * fsHooks value. Also link the pti to the desktop. 03934 */ 03935 if (pdesk != NULL) { 03936 pti->pDeskInfo = pdesk->pDeskInfo; 03937 InsertHeadList(&pdesk->PtiList, &pti->PtiLink); 03938 } else { 03939 pti->pDeskInfo = &diStatic; 03940 } 03941 03942 // UserAssert((pti->ppi != NULL) || (pti->ppi == PpiCurrent())); // can't access TEB/pClientInfo of other process 03943 03944 pteb = pti->pEThread->Tcb.Teb; 03945 if (pteb) { 03946 PDESKTOPVIEW pdv; 03947 if (pdesk && (pdv = GetDesktopView(pti->ppi, pdesk))) { 03948 03949 pti->pClientInfo->pDeskInfo = 03950 (PDESKTOPINFO)((PBYTE)pti->pDeskInfo - pdv->ulClientDelta); 03951 03952 pti->pClientInfo->ulClientDelta = pdv->ulClientDelta; 03953 03954 } else { 03955 03956 pti->pClientInfo->pDeskInfo = NULL; 03957 pti->pClientInfo->ulClientDelta = 0; 03958 03959 /* 03960 * Reset the cursor level to its orginal state. 03961 */ 03962 pti->iCursorLevel = TEST_GTERMF(GTERMF_MOUSE) ? 0 : -1; 03963 if (pti->pq) 03964 pti->pq->iCursorLevel = pti->iCursorLevel; 03965 } 03966 } 03967 03968 /* 03969 * Allocate thread information visible from client, then copy and free 03970 * any old info we have lying around. 03971 */ 03972 if (pdesk != NULL) { 03973 03974 /* 03975 * Do not use DesktopAlloc here because the desktop might 03976 * have DF_DESTROYED set. 03977 */ 03978 pti->pcti = DesktopAllocAlways(pdesk, 03979 sizeof(CLIENTTHREADINFO), 03980 DTAG_CLIENTTHREADINFO); 03981 } 03982 03983 if (pdesk == NULL || pti->pcti == NULL) { 03984 pti->pcti = &(pti->cti); 03985 pti->pClientInfo->pClientThreadInfo = NULL; 03986 } else { 03987 pti->pClientInfo->pClientThreadInfo = 03988 (PCLIENTTHREADINFO)((PBYTE)pti->pcti - pti->pClientInfo->ulClientDelta); 03989 } 03990 03991 if (pctiOld != NULL) { 03992 03993 if (pctiOld != pti->pcti) { 03994 RtlCopyMemory(pti->pcti, pctiOld, sizeof(CLIENTTHREADINFO)); 03995 } 03996 03997 if (pctiOld != &(pti->cti)) { 03998 DesktopFree(pdeskOld, pctiOld); 03999 } 04000 04001 } else { 04002 RtlZeroMemory(pti->pcti, sizeof(CLIENTTHREADINFO)); 04003 } 04004 04005 /* 04006 * If journalling is occuring on the new desktop, attach to 04007 * the journal queue. 04008 * Assert that the pti and the pdesk point to the same deskinfo 04009 * if not, we will check the wrong hooks. 04010 */ 04011 UserAssert((pdesk == NULL ) || (pti->pDeskInfo == pdesk->pDeskInfo)); 04012 UserAssert(pti->rpdesk == pdesk); 04013 if (pti->pq != NULL) { 04014 PQ pq = GetJournallingQueue(pti); 04015 if (pq != NULL) { 04016 pq->cThreads++; 04017 zzzAttachToQueue(pti, pq, NULL, FALSE); 04018 } 04019 } 04020 04021 ThreadUnlockDesktop(ptiCurrent, &tlpdesk, LDUT_FN_SETDESKTOP); 04022 }


Variable Documentation

BOOL fGdiEnabled
 

Definition at line 23 of file desktop.c.

Referenced by FullScreenCleanup(), xxxCreateDesktop(), xxxMakeWindowForegroundWithState(), and xxxUserPowerStateCalloutWorker().

HANDLE gHandleInUse
 

Definition at line 29 of file desktop.c.

Referenced by CheckHandleInUse(), and SetHandleInUse().

PEPROCESS gProcessInUse
 

Definition at line 28 of file desktop.c.

Referenced by CheckHandleInUse(), and SetHandleInUse().


Generated on Sat May 15 19:43:26 2004 for test by doxygen 1.3.7