test: desktop.c File Reference

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_CONTEXT * | PDESKTOP_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().