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

queue.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define TraceDdeMsg(m, h1, h2, c)
#define DebugValidateMLIST(pml)
#define DebugValidateMLISTandQMSG(pml, pqmsg)
#define QUERY_VALUE_BUFFER   80
#define MODULESUFFIXSIZE   (8*sizeof(WCHAR))
#define MAXMODULENAMELEN   (sizeof(szKey) - MODULESUFFIXSIZE)
#define NORMAL_PRIORITY_TASK   10
#define QS_TEST_AND_CLEAR   (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_SENDMESSAGE)
#define QS_TEST   (QS_MOUSEBUTTON | QS_KEY)
#define INTERMEDIATE_TIMEOUT   (500)

Functions

VOID DestroyProcessesObjects (PPROCESSINFO ppi)
VOID DestroyThreadsMessages (PQ pq, PTHREADINFO pti)
void CheckProcessForeground (PTHREADINFO pti)
void ScreenSaverCheck (PTHREADINFO pti)
DWORD xxxPollAndWaitForSingleObject (PKEVENT pEvent, PVOID pExecObject, DWORD dwMilliseconds)
NTSTATUS InitiateShutdown (PETHREAD Thread, PULONG lpdwFlags)
NTSTATUS EndShutdown (PETHREAD Thread, NTSTATUS StatusShutdown)
void SetVDMCursorBounds (LPRECT lprc)
NTSTATUS InitQEntryLookaside (VOID)
void SetAppStarting (PPROCESSINFO ppi)
BOOL xxxSetProcessInitState (PEPROCESS Process, DWORD dwFlags)
BOOL CheckAllowForeground (PEPROCESS pep)
void xxxUserNotifyConsoleApplication (PCONSOLE_PROCESS_INFO pcpi)
void UserSetConsoleProcessWindowStation (DWORD idProcess, HWINSTA hwinsta)
BOOL xxxUserNotifyProcessCreate (DWORD idProcess, DWORD idParentThread, ULONG_PTR dwData, DWORD dwFlags)
void zzzCalcStartCursorHide (PW32PROCESS pwp, DWORD timeAdd)
BOOL SetAppImeCompatFlags (PTHREADINFO pti, PUNICODE_STRING pstrModName, PUNICODE_STRING pstrBaseFileName)
BOOL SetAppCompatFlags (PTHREADINFO pti)
DWORD GetAppCompatFlags (PTHREADINFO pti)
DWORD GetAppCompatFlags2 (WORD wVer)
DWORD GetAppImeCompatFlags (PTHREADINFO pti)
VOID CheckAppStarting (PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam)
void ClearAppStarting (PPROCESSINFO ppi)
NTSTATUS zzzInitTask (UINT dwExpWinVer, DWORD dwAppCompatFlags, PUNICODE_STRING pstrModName, PUNICODE_STRING pstrBaseFileName, DWORD hTaskWow, DWORD dwHotkey, DWORD idTask, DWORD dwX, DWORD dwY, DWORD dwXSize, DWORD dwYSize)
void zzzShowStartGlass (DWORD dwTimeout)
PQ GetJournallingQueue (PTHREADINFO pti)
void ClearQueueServerEvent (WORD wWakeMask)
ULONG ParseReserved (WCHAR *pchReserved, WCHAR *pchFind)
NTSTATUS xxxCreateThreadInfo (PETHREAD pEThread, BOOL IsSystemThread)
PQ AllocQueue (PTHREADINFO ptiKeyState, PQ pq)
VOID FreeQueue (PQ pq)
VOID FreeCachedQueues (VOID)
void zzzDestroyQueue (PQ pq, PTHREADINFO pti)
VOID UserDeleteW32Thread (PW32THREAD pW32Thread)
VOID UserDeleteW32Process (PW32PROCESS pW32Process)
__inline BOOL FLastGuiThread (PTHREADINFO pti)
VOID xxxDestroyThreadInfo (VOID)
void CleanEventMessage (PQMSG pqmsg)
VOID FreeMessageList (PMLIST pml)
NTSTATUS InitQEntryLookaside ()
PQMSG AllocQEntry (PMLIST pml)
void DelQEntry (PMLIST pml, PQMSG pqmsg)
void CheckRemoveHotkeyBit (PTHREADINFO pti, PMLIST pml)
PQMSG FindQMsg (PTHREADINFO pti, PMLIST pml, PWND pwndFilter, UINT msgMin, UINT msgMax, BOOL bProcessAck)
BOOL CheckQuitMessage (PTHREADINFO pti, LPMSG lpMsg, BOOL fRemoveMsg)
BOOL xxxReadPostMessage (PTHREADINFO pti, LPMSG lpMsg, PWND pwndFilter, UINT msgMin, UINT msgMax, BOOL fRemoveMsg)
void xxxProcessHungThreadEvent (PWND pwnd)
VOID xxxProcessEventMessage (PTHREADINFO ptiCurrent, PQMSG pqmsg)
BOOL _GetInputState (VOID)
DWORD _GetQueueStatus (UINT flags)
DWORD xxxMsgWaitForMultipleObjects (DWORD nCount, PVOID *apObjects, MSGWAITCALLBACK pfnNonMsg, PKWAIT_BLOCK WaitBlockArray)
BOOL xxxSleepThread (UINT fsWakeMask, DWORD Timeout, BOOL fInputIdle)
VOID SetWakeBit (PTHREADINFO pti, UINT wWakeBit)
void TransferWakeBit (PTHREADINFO pti, UINT message)
VOID ClearWakeBit (PTHREADINFO pti, UINT wWakeBit, BOOL fSysCheck)
PTHREADINFO PtiFromThreadId (DWORD dwThreadId)
void StoreMessage (LPMSG pmsg, PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, DWORD time)
void StoreQMessage (PQMSG pqmsg, PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, DWORD time, DWORD dwQEvent, ULONG_PTR dwExtraInfo)
NTSTATUS xxxInitProcessInfo (PW32PROCESS pwp)
BOOL DestroyProcessInfo (PW32PROCESS pwp)
VOID ClearWakeMask (VOID)
HANDLE xxxGetInputEvent (DWORD dwWakeMask)
DWORD xxxWaitForInputIdle (ULONG_PTR idProcess, DWORD dwMilliseconds, BOOL fSharedWow)
DWORD WaitOnPseudoEvent (HANDLE *phE, DWORD dwMilliseconds)
NTSTATUS xxxSetCsrssThreadDesktop (PDESKTOP pdesk, PDESKRESTOREDATA pdrdRestore)
NTSTATUS xxxRestoreCsrssThreadDesktop (PDESKRESTOREDATA pdrdRestore)
ULONG GetTaskName (PTHREADINFO pti, PWSTR Buffer, ULONG BufferLength)
NTSTATUS xxxQueryInformationThread (IN HANDLE hThread, IN USERTHREADINFOCLASS ThreadInfoClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
NTSTATUS xxxSetInformationThread (IN HANDLE hThread, IN USERTHREADINFOCLASS ThreadInfoClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
NTSTATUS SetInformationProcess (IN HANDLE hProcess, IN USERPROCESSINFOCLASS ProcessInfoClass, IN PVOID ProcessInformation, IN ULONG ProcessInformationLength)
VOID xxxSetConsoleCaretInfo (PCONSOLE_CARET_INFO pcci)
NTSTATUS xxxConsoleControl (IN CONSOLECONTROL ConsoleControl, IN PVOID ConsoleInformation, IN ULONG ConsoleInformationLength)

Variables

PW32PROCESS gpwpCalcFirst
PPAGED_LOOKASIDE_LIST QLookaside
PPAGED_LOOKASIDE_LIST QEntryLookaside
PUNICODE_STRING gpastrSetupExe
int giSetupExe
BEEPPROC pfnBP []


Define Documentation

#define DebugValidateMLIST pml   ) 
 

Definition at line 107 of file queue.c.

Referenced by AllocQEntry(), AllocQueue(), DelQEntry(), DestroyThreadsMessages(), FindQMsg(), FreeMessageList(), and zzzDestroyQueue().

#define DebugValidateMLISTandQMSG pml,
pqmsg   ) 
 

Definition at line 108 of file queue.c.

Referenced by AllocQEntry(), and DelQEntry().

#define INTERMEDIATE_TIMEOUT   (500)
 

Definition at line 5463 of file queue.c.

Referenced by xxxPollAndWaitForSingleObject().

#define MAXMODULENAMELEN   (sizeof(szKey) - MODULESUFFIXSIZE)
 

Referenced by SetAppCompatFlags().

#define MODULESUFFIXSIZE   (8*sizeof(WCHAR))
 

#define NORMAL_PRIORITY_TASK   10
 

Referenced by zzzInitTask().

#define QS_TEST   (QS_MOUSEBUTTON | QS_KEY)
 

Definition at line 4204 of file queue.c.

Referenced by _GetInputState().

#define QS_TEST_AND_CLEAR   (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_SENDMESSAGE)
 

Definition at line 4203 of file queue.c.

Referenced by _GetInputState().

#define QUERY_VALUE_BUFFER   80
 

Definition at line 677 of file queue.c.

Referenced by SetAppCompatFlags(), and SetAppImeCompatFlags().

#define TraceDdeMsg m,
h1,
h2,
c   ) 
 

Definition at line 40 of file queue.c.


Function Documentation

BOOL _GetInputState VOID   ) 
 

Definition at line 4206 of file queue.c.

References _GetQueueStatus(), BOOL, FALSE, QS_TEST, QS_TEST_AND_CLEAR, and TRUE.

Referenced by NtUserGetThreadState().

04207 { 04208 if (LOWORD(_GetQueueStatus(QS_TEST_AND_CLEAR)) & QS_TEST) { 04209 return TRUE; 04210 } else { 04211 return FALSE; 04212 } 04213 }

DWORD _GetQueueStatus UINT  flags  ) 
 

Definition at line 4228 of file queue.c.

References DWORD, tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeBits, tagCLIENTTHREADINFO::fsWakeBitsJournal, tagTHREADINFO::pcti, PtiCurrentShared, and UINT.

Referenced by _GetInputState().

04230 { 04231 PTHREADINFO ptiCurrent; 04232 UINT fsChangeBits; 04233 04234 ptiCurrent = PtiCurrentShared(); 04235 04236 flags &= (QS_ALLINPUT | QS_ALLPOSTMESSAGE | QS_TRANSFER); 04237 04238 fsChangeBits = ptiCurrent->pcti->fsChangeBits; 04239 04240 /* 04241 * Clear out the change bits the app is looking at 04242 * so it'll know what changed since it's last call 04243 * to GetQueueStatus(). 04244 */ 04245 ptiCurrent->pcti->fsChangeBits &= ~flags; 04246 04247 /* 04248 * Return the current change/wake-bits. 04249 */ 04250 return MAKELONG(fsChangeBits & flags, 04251 (ptiCurrent->pcti->fsWakeBits | ptiCurrent->pcti->fsWakeBitsJournal) & flags); 04252 }

PQMSG AllocQEntry PMLIST  pml  ) 
 

Definition at line 3208 of file queue.c.

References tagMLIST::cMsgs, DebugValidateMLIST, DebugValidateMLISTandQMSG, ExAllocateFromPagedLookasideList(), gUserPostMessageLimit, NULL, tagQMSG::pqmsgNext, tagQMSG::pqmsgPrev, tagMLIST::pqmsgRead, tagMLIST::pqmsgWriteLast, and QEntryLookaside.

Referenced by _PostMessage(), _PostThreadMessage(), DestroyProcessInfo(), DoTimer(), PostEventMessage(), PostInputMessage(), and xxxSetForegroundWindow2().

03210 { 03211 PQMSG pqmsg; 03212 03213 DebugValidateMLIST(pml); 03214 03215 if (pml->cMsgs >= gUserPostMessageLimit) { 03216 RIPMSG3(RIP_WARNING, "AllocQEntry: # of post messages exceeds the limit(%d) in pti=0x%p, pml=0x%p", 03217 gUserPostMessageLimit, W32GetCurrentThread(), pml); 03218 return NULL; 03219 } 03220 03221 /* 03222 * Allocate a Q message structure. 03223 */ 03224 if ((pqmsg = ExAllocateFromPagedLookasideList(QEntryLookaside)) == NULL) { 03225 return NULL; 03226 } 03227 03228 RtlZeroMemory(pqmsg, sizeof(*pqmsg)); 03229 03230 if (pml->pqmsgWriteLast != NULL) { 03231 pml->pqmsgWriteLast->pqmsgNext = pqmsg; 03232 pqmsg->pqmsgPrev = pml->pqmsgWriteLast; 03233 pml->pqmsgWriteLast = pqmsg; 03234 } else { 03235 pml->pqmsgWriteLast = pml->pqmsgRead = pqmsg; 03236 } 03237 03238 pml->cMsgs++; 03239 03240 DebugValidateMLISTandQMSG(pml, pqmsg); 03241 03242 return pqmsg; 03243 }

PQ AllocQueue PTHREADINFO  ptiKeyState,
PQ  pq
 

Definition at line 2102 of file queue.c.

References tagQ::afKeyState, CBKEYSTATE, tagQ::cLockCount, DebugValidateMLIST, ExAllocateFromPagedLookasideList(), gafAsyncKeyState, GTERMF_MOUSE, tagQ::iCursorLevel, LockQCursor, tagQ::mlInput, NULL, tagTHREADINFO::pq, QLookaside, SYSCUR, TEST_GTERMF, and USHORT.

Referenced by xxxCreateThreadInfo(), xxxHardErrorControl(), xxxSetThreadDesktop(), xxxSwitchDesktop(), zzzJournalAttach(), and zzzRecalcThreadAttachment().

02106 { 02107 USHORT cLockCount; 02108 02109 if (pq == NULL) { 02110 pq = ExAllocateFromPagedLookasideList(QLookaside); 02111 if (pq == NULL) { 02112 return NULL; 02113 } 02114 cLockCount = 0; 02115 } else { 02116 DebugValidateMLIST(&pq->mlInput); 02117 /* 02118 * Preserve lock count. 02119 */ 02120 cLockCount = pq->cLockCount; 02121 } 02122 RtlZeroMemory(pq, sizeof(Q)); 02123 pq->cLockCount = cLockCount; 02124 02125 /* 02126 * This is a new queue; we need to update its key state table before 02127 * the first input event is put in the queue. 02128 * We do this by copying the current keystate table and NULLing the recent 02129 * down state table. If a key is really down it will be updated when 02130 * we get it repeats. 02131 * 02132 * He is the old way that did not work because if the first key was say an 02133 * alt key the Async table would be updated, then the UpdateKeyState 02134 * message and it would look like the alt key was PREVIOUSLY down. 02135 * 02136 * The queue will get updated when it first reads input: to allow the 02137 * app to query the key state before it calls GetMessage, set its initial 02138 * key state to the asynchronous key state. 02139 */ 02140 if (ptiKeyState) { 02141 RtlCopyMemory(pq->afKeyState, ptiKeyState->pq->afKeyState, CBKEYSTATE); 02142 } else { 02143 RtlCopyMemory(pq->afKeyState, gafAsyncKeyState, CBKEYSTATE); 02144 } 02145 02146 /* 02147 * If there isn't a mouse set iCursorLevel to -1 so the 02148 * mouse cursor won't be visible on the screen. 02149 */ 02150 if ( 02151 !TEST_GTERMF(GTERMF_MOUSE)) { 02152 pq->iCursorLevel--; 02153 } 02154 /* 02155 * While the thread is starting up... it has the wait cursor. 02156 */ 02157 LockQCursor(pq, SYSCUR(WAIT)); 02158 02159 DebugValidateMLIST(&pq->mlInput); 02160 return pq; 02161 }

BOOL CheckAllowForeground PEPROCESS  pep  ) 
 

Definition at line 222 of file queue.c.

References BOOL, CanForceForeground(), tagWINDOWSTATION::dwWSF_Flags, EnterCrit, FALSE, GiveUpForeground(), HasForegroundActivateRight(), _EPROCESS::InheritedFromUniqueProcessId, IsShellProcess(), LeaveCrit, LockProcessByClientId(), luidSystem, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, pep, PpiFromProcess, PsReferencePrimaryToken(), tagPROCESSINFO::ptiList, tagPROCESSINFO::rpwinsta, RtlEqualLuid(), SeQueryAuthenticationIdToken(), Status, TIF_ALLOWFOREGROUNDACTIVATE, tagTHREADINFO::TIF_flags, TRUE, UINT, UnlockProcess, W32PF_ALLOWSETFOREGROUND, and WSF_NOIO.

Referenced by xxxInitProcessInfo(), and xxxUserNotifyConsoleApplication().

00224 { 00225 BOOL fCreator = TRUE; 00226 HANDLE hpid = (HANDLE)pep->InheritedFromUniqueProcessId; 00227 LUID luid; 00228 PACCESS_TOKEN pat; 00229 PEPROCESS pepParent; 00230 PPROCESSINFO ppiParent; 00231 UINT uAncestors = 0; 00232 BOOL fAllowForeground = FALSE; 00233 NTSTATUS Status; 00234 00235 do { 00236 /* 00237 * Get the ppi for the parent process. 00238 */ 00239 LeaveCrit(); 00240 Status = LockProcessByClientId(hpid, &pepParent); 00241 EnterCrit(); 00242 if (!NT_SUCCESS(Status)) { 00243 /* 00244 * Bug 294193 - joejo 00245 * 00246 * If this is a process that was created after it'a creator was 00247 * destroyed, then lets attempt to give it foreground. This is a 00248 * typical scenario when a stub exe trys to create another process 00249 * in it's place. 00250 */ 00251 if (HasForegroundActivateRight(pep->InheritedFromUniqueProcessId)) { 00252 fAllowForeground = TRUE; 00253 } 00254 break; 00255 } 00256 00257 ppiParent = PpiFromProcess(pepParent); 00258 if (ppiParent == NULL) { 00259 UnlockProcess(pepParent); 00260 break; 00261 } 00262 /* 00263 * If we're walking the parent chain, 00264 * stop when we get to the shell or to a process that 00265 * is not running on the IO winsta 00266 */ 00267 if (!fCreator 00268 && (IsShellProcess(ppiParent) 00269 || ((ppiParent->rpwinsta != NULL) 00270 && (ppiParent->rpwinsta->dwWSF_Flags & WSF_NOIO)))) { 00271 00272 UnlockProcess(pepParent); 00273 break; 00274 } 00275 fAllowForeground = CanForceForeground(ppiParent); 00276 if (!fAllowForeground) { 00277 /* 00278 * Bug 285639 - joejo 00279 * 00280 * If the first thread of the parent process has allow set foreground 00281 * than we allow the setting of the foreground. 00282 */ 00283 if (ppiParent->ptiList != NULL 00284 && (ppiParent->ptiList->TIF_flags & TIF_ALLOWFOREGROUNDACTIVATE)) { 00285 fAllowForeground = TRUE; 00286 } 00287 00288 if (!fAllowForeground){ 00289 /* 00290 * Let's try an ancestor (this might be a worker process). 00291 */ 00292 hpid = (HANDLE)pepParent->InheritedFromUniqueProcessId; 00293 /* 00294 * If this is launched by a system process, let it come to 00295 * the foreground (i.e. CSRSS launching an OLE server). 00296 */ 00297 if (fCreator) { 00298 fCreator = FALSE; 00299 pat = PsReferencePrimaryToken(pepParent); 00300 if (pat != NULL) { 00301 Status = SeQueryAuthenticationIdToken(pat, &luid); 00302 if (NT_SUCCESS(Status)) { 00303 fAllowForeground = RtlEqualLuid(&luid, &luidSystem); 00304 /* 00305 * If it is a system process, give it the 00306 * permanent right so we won't have to check 00307 * its luid again 00308 */ 00309 if (fAllowForeground) { 00310 ppiParent->W32PF_Flags |= W32PF_ALLOWSETFOREGROUND; 00311 } 00312 } 00313 ObDereferenceObject(pat); 00314 } 00315 } 00316 } 00317 } 00318 UnlockProcess(pepParent); 00319 /* 00320 * InheritedFromUniqueProcessId cannot be quite trusted because 00321 * process ids get reused very often. So we just check few levels up 00322 */ 00323 } while (!fAllowForeground && (uAncestors++ < 5)); 00324 00325 return fAllowForeground || GiveUpForeground(); 00326 }

VOID CheckAppStarting PWND  pwnd,
UINT  message,
UINT_PTR  nID,
LPARAM  lParam
 

Definition at line 1059 of file queue.c.

References CMSAPPSTARTINGTIMEOUT, ghCanActivateForegroundPIDs, gppiStarting, KeQuerySystemTime(), NULL, tagPROCESSINFO::ppiNext, and VOID().

Referenced by SetAppStarting().

01060 { 01061 LARGE_INTEGER liStartingTimeout; 01062 PPROCESSINFO *pppi = &gppiStarting; 01063 01064 KeQuerySystemTime(&liStartingTimeout); /* 1 unit == 100ns */ 01065 liStartingTimeout.QuadPart -= (LONGLONG)(CMSAPPSTARTINGTIMEOUT * 10000); 01066 while (*pppi != NULL) { 01067 if (liStartingTimeout.QuadPart > (*pppi)->Process->CreateTime.QuadPart) { 01068 (*pppi)->W32PF_Flags &= ~(W32PF_APPSTARTING | W32PF_ALLOWFOREGROUNDACTIVATE); 01069 TAGMSG1(DBGTAG_FOREGROUND, "CheckAppStarting clear W32PF %#p", *pppi); 01070 *pppi = (*pppi)->ppiNext; 01071 } else { 01072 pppi = &(*pppi)->ppiNext; 01073 } 01074 } 01075 01076 TAGMSG0(DBGTAG_FOREGROUND, "Removing all entries from ghCanActivateForegroundPIDs array"); 01077 RtlZeroMemory(ghCanActivateForegroundPIDs, sizeof(ghCanActivateForegroundPIDs)); 01078 return; 01079 UNREFERENCED_PARAMETER(pwnd); 01080 UNREFERENCED_PARAMETER(message); 01081 UNREFERENCED_PARAMETER(nID); 01082 UNREFERENCED_PARAMETER(lParam); 01083 }

void CheckProcessForeground PTHREADINFO  pti  ) 
 

Definition at line 155 of file ntuser/kernel/input.c.

References _CLIENTINFO::cSpins, _CLIENTINFO::dwTIFlags, gppiWantForegroundPriority, NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::ppi, tagPROCESSINFO::ptiList, tagTHREADINFO::ptiSibling, SetForegroundPriority(), tagTHREADINFO::TIF_flags, TIF_SPINNING, and TRUE.

Referenced by xxxGetInputEvent(), xxxMsgWaitForMultipleObjects(), xxxReadPostMessage(), xxxScanSysQueue(), and xxxSleepThread().

00157 { 00158 PTHREADINFO ptiT; 00159 00160 /* 00161 * Check to see if we need to move this process into foreground 00162 * priority. 00163 */ 00164 pti->pClientInfo->cSpins = 0; 00165 pti->TIF_flags &= ~TIF_SPINNING; 00166 pti->pClientInfo->dwTIFlags = pti->TIF_flags; 00167 00168 if (pti->ppi->W32PF_Flags & W32PF_FORCEBACKGROUNDPRIORITY) { 00169 /* 00170 * See if any thread of this process is spinning. If none 00171 * are, we can remove the force to background. 00172 */ 00173 for (ptiT = pti->ppi->ptiList; ptiT != NULL; ptiT = ptiT->ptiSibling) { 00174 if (ptiT->TIF_flags & TIF_SPINNING) 00175 return; 00176 } 00177 00178 pti->ppi->W32PF_Flags &= ~W32PF_FORCEBACKGROUNDPRIORITY; 00179 if (pti->ppi == gppiWantForegroundPriority) { 00180 SetForegroundPriority(pti, TRUE); 00181 } 00182 } 00183 }

BOOL CheckQuitMessage PTHREADINFO  pti,
LPMSG  lpMsg,
BOOL  fRemoveMsg
 

Definition at line 3466 of file queue.c.

References BOOL, tagMLIST::cMsgs, tagTHREADINFO::cQuit, DWORD, tagTHREADINFO::exitCode, FALSE, tagTHREADINFO::mlPost, NULL, StoreMessage(), and TRUE.

Referenced by xxxReadPostMessage().

03470 { 03471 /* 03472 * If there are no more posted messages in the queue and cQuit is != 03473 * 0, then generate a quit! 03474 */ 03475 if (pti->cQuit != 0 && pti->mlPost.cMsgs == 0) { 03476 /* 03477 * If we're "removing" the quit, set cQuit to 0 so another one isn't 03478 * generated. 03479 */ 03480 if (fRemoveMsg) 03481 pti->cQuit = 0; 03482 StoreMessage(lpMsg, NULL, WM_QUIT, (DWORD)pti->exitCode, 0, 0); 03483 return TRUE; 03484 } 03485 03486 return FALSE; 03487 }

void CheckRemoveHotkeyBit PTHREADINFO  pti,
PMLIST  pml
 

Definition at line 3301 of file queue.c.

References DWORD, tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeBits, tagQMSG::msg, NULL, tagTHREADINFO::pcti, tagQMSG::pqmsgNext, and tagMLIST::pqmsgRead.

Referenced by FindQMsg(), and xxxReadPostMessage().

03304 { 03305 PQMSG pqmsg; 03306 DWORD cHotkeys; 03307 03308 /* 03309 * Remove the QS_HOTKEY bit if there is only one WM_HOTKEY message 03310 * in this message list. 03311 */ 03312 cHotkeys = 0; 03313 for (pqmsg = pml->pqmsgRead; pqmsg != NULL; pqmsg = pqmsg->pqmsgNext) { 03314 if (pqmsg->msg.message == WM_HOTKEY) 03315 cHotkeys++; 03316 } 03317 03318 /* 03319 * If there is 1 or fewer hot keys, remove the hotkey bits. 03320 */ 03321 if (cHotkeys <= 1) { 03322 pti->pcti->fsWakeBits &= ~QS_HOTKEY; 03323 pti->pcti->fsChangeBits &= ~QS_HOTKEY; 03324 } 03325 }

void CleanEventMessage PQMSG  pqmsg  ) 
 

Definition at line 3068 of file queue.c.

References DestroyNotify(), tagQMSG::dwQEvent, tagASYNCSENDMSG::lParam, tagQMSG::msg, PASYNCSENDMSG, PBYTE, QEVENT_ASYNCSENDMSG, QEVENT_NOTIFYWINEVENT, QEVENT_SETWINDOWPOS, QEVENT_UPDATEKEYSTATE, and UserDeleteAtom().

Referenced by DestroyThreadsMessages(), FreeMessageList(), RedistributeInput(), xxxProcessEventMessage(), and xxxScanSysQueue().

03070 { 03071 PASYNCSENDMSG pmsg; 03072 03073 /* 03074 * Certain special messages on the INPUT queue have associated 03075 * bits of memory that need to be freed. 03076 */ 03077 switch (pqmsg->dwQEvent) { 03078 case QEVENT_SETWINDOWPOS: 03079 UserFreePool((PSMWP)pqmsg->msg.wParam); 03080 break; 03081 03082 case QEVENT_UPDATEKEYSTATE: 03083 UserFreePool((PBYTE)pqmsg->msg.wParam); 03084 break; 03085 03086 case QEVENT_NOTIFYWINEVENT: 03087 DestroyNotify((PNOTIFY)pqmsg->msg.lParam); 03088 break; 03089 03090 case QEVENT_ASYNCSENDMSG: 03091 pmsg = (PASYNCSENDMSG)pqmsg->msg.wParam; 03092 UserDeleteAtom((ATOM)pmsg->lParam); 03093 UserFreePool(pmsg); 03094 break; 03095 } 03096 }

void ClearAppStarting PPROCESSINFO  ppi  ) 
 

Definition at line 1131 of file queue.c.

References gppiStarting, PROCESSINFO, and REMOVE_FROM_LIST.

Referenced by DestroyProcessInfo(), FRemoveForegroundActivate(), and InitSystemThread().

01132 { 01133 REMOVE_FROM_LIST(PROCESSINFO, gppiStarting, ppi, ppiNext); 01134 ppi->W32PF_Flags &= ~W32PF_APPSTARTING; 01135 }

void ClearQueueServerEvent WORD  wWakeMask  ) 
 

Definition at line 1458 of file queue.c.

References tagCLIENTTHREADINFO::fsWakeMask, KeClearEvent, tagTHREADINFO::pcti, tagTHREADINFO::pEventQueueServer, and PtiCurrent.

Referenced by xxxGetInputEvent(), xxxMsgWaitForMultipleObjects(), xxxPollAndWaitForSingleObject(), and xxxSleepThread().

01459 { 01460 PTHREADINFO ptiCurrent = PtiCurrent(); 01461 UserAssert(wWakeMask != 0); 01462 ptiCurrent->pcti->fsWakeMask = wWakeMask; 01463 KeClearEvent(ptiCurrent->pEventQueueServer); 01464 }

VOID ClearWakeBit PTHREADINFO  pti,
UINT  wWakeBit,
BOOL  fSysCheck
 

Definition at line 4700 of file queue.c.

References tagMLIST::cMsgs, FJOURNALPLAYBACK, tagCLIENTTHREADINFO::fsWakeBits, tagQ::mlInput, tagTHREADINFO::pcti, tagTHREADINFO::pq, tagQ::QF_flags, QF_MOUSEMOVED, and VOID().

Referenced by xxxDesktopThread(), and xxxScanSysQueue().

04704 { 04705 04706 /* 04707 * If fSysCheck is TRUE, clear bits only if we are not doing journal 04708 * playback and there are no more messages in the queue. fSysCheck 04709 * is TRUE if clearing because of no more input. FALSE if just 04710 * transfering input ownership from one thread to another. 04711 */ 04712 if (fSysCheck) { 04713 if (pti->pq->mlInput.cMsgs != 0 || FJOURNALPLAYBACK()) 04714 return; 04715 if (pti->pq->QF_flags & QF_MOUSEMOVED) 04716 wWakeBit &= ~QS_MOUSEMOVE; 04717 } 04718 04719 /* 04720 * Only clear the wake bits, not the change bits as well! 04721 */ 04722 pti->pcti->fsWakeBits &= ~wWakeBit; 04723 }

VOID ClearWakeMask VOID   ) 
 

Definition at line 5223 of file queue.c.

References PtiCurrent, and VOID().

05224 { 05225 PtiCurrent()->pcti->fsWakeMask = 0; 05226 }

void DelQEntry PMLIST  pml,
PQMSG  pqmsg
 

Definition at line 3253 of file queue.c.

References tagMLIST::cMsgs, DebugValidateMLIST, DebugValidateMLISTandQMSG, ExFreeToPagedLookasideList(), NULL, tagQMSG::pqmsgNext, tagQMSG::pqmsgPrev, tagMLIST::pqmsgRead, tagMLIST::pqmsgWriteLast, and QEntryLookaside.

Referenced by AdjustForCoalescing(), DestroyThreadsMessages(), FindQMsg(), FreeMessageList(), PostInputMessage(), RemoveEventMessage(), xxxReadPostMessage(), xxxScanSysQueue(), and xxxSkipSysMsg().

03256 { 03257 DebugValidateMLISTandQMSG(pml, pqmsg); 03258 UserAssert((int)pml->cMsgs > 0); 03259 UserAssert(pml->pqmsgRead); 03260 UserAssert(pml->pqmsgWriteLast); 03261 03262 /* 03263 * Unlink this pqmsg from the message list. 03264 */ 03265 if (pqmsg->pqmsgPrev != NULL) 03266 pqmsg->pqmsgPrev->pqmsgNext = pqmsg->pqmsgNext; 03267 03268 if (pqmsg->pqmsgNext != NULL) 03269 pqmsg->pqmsgNext->pqmsgPrev = pqmsg->pqmsgPrev; 03270 03271 /* 03272 * Update the read/write pointers if necessary. 03273 */ 03274 if (pml->pqmsgRead == pqmsg) 03275 pml->pqmsgRead = pqmsg->pqmsgNext; 03276 03277 if (pml->pqmsgWriteLast == pqmsg) 03278 pml->pqmsgWriteLast = pqmsg->pqmsgPrev; 03279 03280 /* 03281 * Adjust the message count and free the message structure. 03282 */ 03283 pml->cMsgs--; 03284 03285 ExFreeToPagedLookasideList(QEntryLookaside, pqmsg); 03286 03287 DebugValidateMLIST(pml); 03288 }

VOID DestroyProcessesObjects PPROCESSINFO  ppi  ) 
 

Definition at line 2511 of file handtabl.c.

References tagSHAREDINFO::aheList, _HANDLEENTRY::bFlags, tagHANDLETYPEINFO::bObjectCreateFlags, BOOL, _HANDLEENTRY::bType, DBGValidateHandleQuota, FixupCursor(), gahti, giheLast, gpepCSRSS, gptiRit, gSharedInfo, HANDLEF_DESTROY, HMChangeOwnerPheProcess(), HMDestroyUnlockedObject(), ISTS, OCF_PROCESSOWNED, _HANDLEENTRY::phead, _HANDLEENTRY::pOwner, TYPE_CURSOR, TYPE_FREE, VOID(), and ZombieCursor().

Referenced by xxxDestroyThreadInfo().

02513 { 02514 PHE pheT, pheMax; 02515 BOOL bGlobal = (ISTS() && ppi->Process == gpepCSRSS); 02516 02517 /* 02518 * Loop through the table destroying all objects created by the current 02519 * process. All objects will get destroyed in their proper order simply 02520 * because of the object locking. 02521 */ 02522 DBGValidateHandleQuota(); 02523 pheMax = &gSharedInfo.aheList[giheLast]; 02524 02525 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 02526 02527 /* 02528 * Check against free before we look at ppi... because pq is stored 02529 * in the object itself, which won't be there if TYPE_FREE. 02530 */ 02531 if (pheT->bType == TYPE_FREE) 02532 continue; 02533 02534 /* 02535 * Destroy those objects created by this queue. 02536 */ 02537 if (!(gahti[pheT->bType].bObjectCreateFlags & OCF_PROCESSOWNED) || 02538 (PPROCESSINFO)pheT->pOwner != ppi) 02539 continue; 02540 02541 /* 02542 * Make sure this object isn't already marked to be destroyed - we'll 02543 * do no good if we try to destroy it now since it is locked. 02544 * Change the owner since the process is going away 02545 */ 02546 if (pheT->bFlags & HANDLEF_DESTROY) { 02547 HMChangeOwnerPheProcess(pheT, gptiRit); 02548 continue; 02549 } 02550 02551 if (bGlobal) { 02552 02553 /* 02554 * For global cursors set the ppi in the pcur 02555 * to be CSRSS 02556 */ 02557 if (pheT->bType == TYPE_CURSOR) { 02558 FixupCursor((PCURSOR)pheT->phead, ppi); 02559 } 02560 } 02561 02562 /* 02563 * Destroy this object. 02564 */ 02565 HMDestroyUnlockedObject(pheT); 02566 02567 /* 02568 * When the object is freed, the handle type is set to TYPE_FREE. 02569 * Zombie this object, since its process is going away and it couldn't 02570 * be freed. This may include unlinking it and resetting the owner. 02571 */ 02572 if (pheT->bType != TYPE_FREE) { 02573 if (pheT->bType == TYPE_CURSOR) { 02574 RIPMSG1(RIP_WARNING, "About to zombie pcur %#p\n", 02575 pheT->phead); 02576 02577 ZombieCursor((PCURSOR)pheT->phead); 02578 } else { 02579 HMChangeOwnerPheProcess(pheT, gptiRit); 02580 } 02581 } 02582 } /* for loop */ 02583 DBGValidateHandleQuota(); 02584 }

BOOL DestroyProcessInfo PW32PROCESS  pwp  ) 
 

Definition at line 4976 of file queue.c.

References tagSHAREDINFO::aheList, AllocQEntry(), BEGINATOMICCHECK, _HANDLEENTRY::bFlags, BOOL, _HANDLEENTRY::bType, CheckCritIn, ClearAppStarting(), CLOSE_PSEUDO_EVENT, CloseProtectedHandle(), tagPROCESSINFO::cThreads, DeferWinEventNotify, DelayedDestroyCacheDC(), tagWINDOWSTATION::dwWSF_Flags, ENDATOMICCHECK, EndDeferWinEventNotifyWithoutProcessing, FALSE, gahti, GETPTI, giheLast, GiveForegroundActivateRight(), gppiForegroundOld, gppiInputProvider, gppiList, gppiLockSFW, gppiScreenSaver, gpPublicObjectList, gpwpiFirstWow, gSharedInfo, gspwndLogonNotify, HANDLEF_DESTROY, IsShellProcess(), tagTHREADINFO::mlPost, tagPUBOBJ::next, NT_SUCCESS, NULL, ObDereferenceObject, OCF_PROCESSOWNED, tagDESKTOP::pDeskInfo, tagDESKTOPVIEW::pdvNext, tagWOWPROCESSINFO::pEventWowExec, tagPUBOBJ::pid, _HANDLEENTRY::pOwner, tagDESKTOPINFO::ppiShellProcess, PPUBOBJ, REMOVE_FROM_LIST, tagPROCESSINFO::rpdeskStartup, tagPROCESSINFO::rpwinsta, SetWakeBit(), StoreQMessage(), UnlockDesktop, UnlockWinSta, USER_SOUND_CLOSE, WOWPROCESSINFO, WSF_OPENLOCK, and zzzCalcStartCursorHide().

Referenced by xxxUserProcessCallout().

04978 { 04979 PPROCESSINFO ppi = (PPROCESSINFO)pwp; 04980 PDESKTOPVIEW pdv, pdvNext; 04981 BOOL fHadThreads; 04982 PPUBOBJ ppo; 04983 04984 CheckCritIn(); 04985 04986 /* 04987 * Free up input idle event if it exists - wake everyone waiting on it 04988 * first. This object will get created sometimes even for non-windows 04989 * processes (usually for WinExec(), which calls WaitForInputIdle()). 04990 */ 04991 CLOSE_PSEUDO_EVENT(&pwp->InputIdleEvent); 04992 04993 /* 04994 * Check to see if the startglass is on, and if so turn it off and update. 04995 * DeferWinEventNotify to because we cannot process notifications for this 04996 * thread now (we may have no PtiCurrent, see comment above) 04997 */ 04998 BEGINATOMICCHECK(); 04999 DeferWinEventNotify(); 05000 if (pwp->W32PF_Flags & W32PF_STARTGLASS) { 05001 pwp->W32PF_Flags &= ~W32PF_STARTGLASS; 05002 zzzCalcStartCursorHide(NULL, 0); 05003 } 05004 /* 05005 * This is bookkeeping - restore original notification deferral but without 05006 * attempting to process any deferred notifications because we have no pti. 05007 */ 05008 EndDeferWinEventNotifyWithoutProcessing(); 05009 ENDATOMICCHECK(); 05010 05011 /* 05012 * If the process never called Win32k, we're done. 05013 */ 05014 if (!(pwp->W32PF_Flags & W32PF_PROCESSCONNECTED)) { 05015 return FALSE; 05016 } 05017 05018 /* 05019 * Play the Process Close sound for non-console processes 05020 * running on the I/O windowstation. 05021 */ 05022 05023 if ((ppi->W32PF_Flags & W32PF_IOWINSTA) && 05024 !(ppi->W32PF_Flags & W32PF_CONSOLEAPPLICATION) && 05025 (gspwndLogonNotify != NULL) && 05026 !(ppi->rpwinsta->dwWSF_Flags & WSF_OPENLOCK)) { 05027 05028 PTHREADINFO pti = GETPTI(gspwndLogonNotify); 05029 PQMSG pqmsg; 05030 05031 if ((pqmsg = AllocQEntry(&pti->mlPost)) != NULL) { 05032 StoreQMessage(pqmsg, gspwndLogonNotify, WM_LOGONNOTIFY, 05033 LOGON_PLAYEVENTSOUND, USER_SOUND_CLOSE, 0, 0, 0); 05034 05035 SetWakeBit(pti, QS_POSTMESSAGE | QS_ALLPOSTMESSAGE); 05036 } 05037 05038 } 05039 05040 /* 05041 * Be like WIN95. 05042 * If this is the shell process, then send a LOGON_RESTARTSHELL 05043 * notification to the winlogon process (only if not logging off) 05044 */ 05045 if (IsShellProcess(ppi)) { 05046 05047 /* 05048 * The shell process will get killed and it's better to set this 05049 * in the desktop info. 05050 */ 05051 ppi->rpdeskStartup->pDeskInfo->ppiShellProcess = NULL; 05052 05053 /* 05054 * If we're not logging off, notify winlogon 05055 */ 05056 if ((gspwndLogonNotify != NULL) && 05057 !(ppi->rpwinsta->dwWSF_Flags & WSF_OPENLOCK)) { 05058 05059 PTHREADINFO pti = GETPTI(gspwndLogonNotify); 05060 PQMSG pqmsg; 05061 05062 if ((pqmsg = AllocQEntry(&pti->mlPost)) != NULL) { 05063 StoreQMessage(pqmsg, gspwndLogonNotify, WM_LOGONNOTIFY, 05064 LOGON_RESTARTSHELL, ppi->Process->ExitStatus, 0, 0, 0); 05065 SetWakeBit(pti, QS_POSTMESSAGE | QS_ALLPOSTMESSAGE); 05066 } 05067 } 05068 } 05069 05070 if (ppi->cThreads) 05071 RIPMSG1(RIP_ERROR, "Disconnect with %d threads remaining\n", ppi->cThreads); 05072 05073 /* 05074 * If the app is still starting, remove it from the startup list 05075 */ 05076 if (ppi->W32PF_Flags & W32PF_APPSTARTING) { 05077 /* 05078 * Bug 294193 - joejo 05079 * 05080 * Handle case when creator process exits before the child 05081 * process makes it to CheckAllowForeground code. This is typical with 05082 * stub EXEs that do nothing but create other processes. 05083 */ 05084 GiveForegroundActivateRight(ppi->Process->UniqueProcessId); 05085 ClearAppStarting(ppi); 05086 } 05087 05088 /* 05089 * remove it from the global list 05090 */ 05091 REMOVE_FROM_LIST(PROCESSINFO, gppiList, ppi, ppiNextRunning); 05092 05093 /* 05094 * If any threads ever connected, there may be DCs, classes, 05095 * cursors, etc. still lying around. If no threads connected 05096 * (which is the case for console apps), skip all of this cleanup. 05097 */ 05098 fHadThreads = ppi->W32PF_Flags & W32PF_THREADCONNECTED; 05099 if (fHadThreads) { 05100 05101 /* 05102 * When a process dies we need to make sure any DCE's it owns 05103 * and have not been deleted are cleanup up. The clean up 05104 * earlier may have failed if the DC was busy in GDI. 05105 */ 05106 if (ppi->W32PF_Flags & W32PF_OWNDCCLEANUP) { 05107 DelayedDestroyCacheDC(); 05108 } 05109 05110 #if DBG 05111 { 05112 PHE pheT, pheMax; 05113 05114 /* 05115 * Loop through the table destroying all objects created by the current 05116 * process. All objects will get destroyed in their proper order simply 05117 * because of the object locking. 05118 */ 05119 pheMax = &gSharedInfo.aheList[giheLast]; 05120 for (pheT = gSharedInfo.aheList; pheT <= pheMax; pheT++) { 05121 05122 /* 05123 * We should have no process objects left for this process. 05124 */ 05125 UserAssertMsg0( 05126 pheT->bFlags & HANDLEF_DESTROY || 05127 !(gahti[pheT->bType].bObjectCreateFlags & OCF_PROCESSOWNED) || 05128 (PPROCESSINFO)pheT->pOwner != ppi, 05129 "We should have no process objects left for this process!"); 05130 } 05131 } 05132 #endif 05133 } 05134 05135 if (pwp->UserHandleCount) 05136 RIPMSG1(RIP_ERROR, "Disconnect with %d User handle objects remaining\n", pwp->UserHandleCount); 05137 05138 /* 05139 * check if we need to zap PID's for DDE objects 05140 */ 05141 for (ppo = gpPublicObjectList; 05142 ppo != NULL; 05143 ppo = ppo->next) { 05144 if (ppo->pid == pwp->W32Pid) { 05145 ppo->pid = OBJECT_OWNER_PUBLIC; 05146 } 05147 } 05148 05149 05150 if (gppiScreenSaver == ppi) { 05151 UserAssert(ppi->W32PF_Flags & W32PF_SCREENSAVER); 05152 05153 gppiScreenSaver = NULL; 05154 } 05155 05156 if (gppiForegroundOld == ppi) { 05157 gppiForegroundOld = NULL; 05158 } 05159 05160 UnlockWinSta(&ppi->rpwinsta); 05161 UnlockDesktop(&ppi->rpdeskStartup, LDU_PPI_DESKSTARTUP3, (ULONG_PTR)ppi); 05162 05163 /* 05164 * Close the startup desktop handle now if it's still around. If we wait 05165 * until handle table cleanup time we could potentially deadlock. 05166 */ 05167 if (ppi->hdeskStartup) { 05168 UserVerify(NT_SUCCESS(CloseProtectedHandle(ppi->hdeskStartup))); 05169 ppi->hdeskStartup = NULL; 05170 } 05171 05172 /* 05173 * Mark the process as terminated so access checks will work. 05174 */ 05175 ppi->W32PF_Flags |= W32PF_TERMINATED; 05176 05177 /* 05178 * Cleanup wow process info struct, if any 05179 */ 05180 if (ppi->pwpi) { 05181 PWOWPROCESSINFO pwpi = ppi->pwpi; 05182 05183 ObDereferenceObject(pwpi->pEventWowExec); 05184 05185 REMOVE_FROM_LIST(WOWPROCESSINFO, gpwpiFirstWow, pwpi, pwpiNext); 05186 05187 UserFreePool(pwpi); 05188 ppi->pwpi = NULL; 05189 } 05190 05191 /* 05192 * Delete desktop views. System will do unmapping. 05193 */ 05194 pdv = ppi->pdvList; 05195 while (pdv) { 05196 pdvNext = pdv->pdvNext; 05197 UserFreePool(pdv); 05198 pdv = pdvNext; 05199 } 05200 ppi->pdvList = NULL; 05201 05202 /* 05203 * Clear the SendInput/Journalling hook caller ppi 05204 */ 05205 if (ppi == gppiInputProvider) { 05206 gppiInputProvider = NULL; 05207 } 05208 /* 05209 * If this ppi locked SetForegroundWindow, clean up 05210 */ 05211 if (ppi == gppiLockSFW) { 05212 gppiLockSFW = NULL; 05213 } 05214 05215 return fHadThreads; 05216 }

VOID DestroyThreadsMessages PQ  pq,
PTHREADINFO  pti
 

Definition at line 3128 of file queue.c.

References CheckPtiSysPeek, CleanEventMessage(), DebugValidateMLIST, DelQEntry(), tagQ::idSysPeek, tagQ::mlInput, NULL, tagQMSG::pqmsgNext, tagMLIST::pqmsgRead, tagQMSG::pti, and VOID().

Referenced by xxxDestroyThreadInfo().

03131 { 03132 PQMSG pqmsg; 03133 PQMSG pqmsgNext; 03134 03135 DebugValidateMLIST(&pq->mlInput); 03136 03137 pqmsg = pq->mlInput.pqmsgRead; 03138 while (pqmsg != NULL) { 03139 pqmsgNext = pqmsg->pqmsgNext; 03140 if (pqmsg->pti == pti) { 03141 /* 03142 * Make sure we don't leave any bogus references to this message 03143 * lying around. 03144 */ 03145 if (pq->idSysPeek == (ULONG_PTR)pqmsg) { 03146 CheckPtiSysPeek(8, pq, 0); 03147 pq->idSysPeek = 0; 03148 } 03149 CleanEventMessage(pqmsg); 03150 DelQEntry(&pq->mlInput, pqmsg); 03151 } 03152 pqmsg = pqmsgNext; 03153 } 03154 03155 DebugValidateMLIST(&pq->mlInput); 03156 }

NTSTATUS EndShutdown PETHREAD  Thread,
NTSTATUS  StatusShutdown
 

Definition at line 324 of file kernel/exitwin.c.

References _PostThreadMessage(), CLEAR_PUDF, tagWINDOWSTATION::dwWSF_Flags, EnterCrit, FALSE, ForceEmptyClipboard(), gdwLocks, gdwShutdownFlags, gdwThreadEndSession, GetProcessLuid(), gpidEndSession, gptiShutdownNotify, gpwinstaLogoff, LeaveCrit, tagWINDOWSTATION::luidUser, NotifyLogon(), NT_SUCCESS, NTSTATUS(), NULL, tagWINDOWSTATION::pGlobalAtomTable, tagDESKTOP::pheapDesktop, PUDF_FONTSARELOADED, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, RtlEmptyAtomTable(), RtlEqualLuid(), RtlZeroHeap(), TEST_PUDF, WSF_OPENLOCK, and WSF_SHUTDOWN.

Referenced by xxxSetInformationThread().

00327 { 00328 PWINDOWSTATION pwinsta = gpwinstaLogoff; 00329 PDESKTOP pdesk; 00330 LUID luidCaller; 00331 UserAssert(gpwinstaLogoff); 00332 00333 gpwinstaLogoff = NULL; 00334 gpidEndSession = NULL; 00335 gdwThreadEndSession = 0; 00336 pwinsta->dwWSF_Flags &= ~WSF_SHUTDOWN; 00337 00338 if (!NT_SUCCESS(GetProcessLuid(Thread, &luidCaller))) { 00339 luidCaller = RtlConvertUlongToLuid(0); // null luid 00340 } 00341 00342 if (!NT_SUCCESS(StatusShutdown)) { 00343 00344 /* 00345 * We need to notify the process that called ExitWindows that 00346 * the logoff was aborted. 00347 */ 00348 if (gptiShutdownNotify) { 00349 _PostThreadMessage(gptiShutdownNotify, WM_ENDSESSION, FALSE, 0); 00350 gptiShutdownNotify = NULL; 00351 } 00352 00353 /* 00354 * Reset the windowstation lock flags so apps can start 00355 * again. 00356 */ 00357 pwinsta->dwWSF_Flags = 00358 (pwinsta->dwWSF_Flags & ~WSF_OPENLOCK) | 00359 gdwLocks; 00360 00361 /* 00362 * Bug 294204 - joejo 00363 * Tell winlogon that we we cancelled shutdown/logoff. 00364 */ 00365 NotifyLogon(pwinsta, &luidCaller, gdwShutdownFlags | EWX_CANCELED, StatusShutdown); 00366 00367 return STATUS_SUCCESS; 00368 } 00369 00370 gptiShutdownNotify = NULL; 00371 00372 /* 00373 * If logoff is occuring for the user set by winlogon, perform 00374 * the normal logoff cleanup. Otherwise, clear the open lock 00375 * and continue. 00376 */ 00377 if (((pwinsta->luidUser.LowPart != 0) || (pwinsta->luidUser.HighPart != 0)) && 00378 RtlEqualLuid(&pwinsta->luidUser, &luidCaller)) { 00379 00380 /* 00381 * Zero out the free blocks in all desktop heaps. 00382 */ 00383 for (pdesk = pwinsta->rpdeskList; pdesk != NULL; pdesk = pdesk->rpdeskNext) { 00384 RtlZeroHeap(Win32HeapGetHandle(pdesk->pheapDesktop), 0); 00385 } 00386 00387 /* 00388 * Logoff/shutdown was successful. In case this is a logoff, remove 00389 * everything from the clipboard so the next logged on user can't get 00390 * at this stuff. 00391 */ 00392 ForceEmptyClipboard(pwinsta); 00393 00394 /* 00395 * Destroy all non-pinned atoms in the global atom table. User can't 00396 * create pinned atoms. Currently only the OLE atoms are pinned. 00397 */ 00398 RtlEmptyAtomTable(pwinsta->pGlobalAtomTable, FALSE); 00399 00400 // this code path is hit only on logoff and also on shutdown 00401 // We do not want to unload fonts twice when we attempt shutdown 00402 // so we mark that the fonts have been unloaded at a logoff time 00403 00404 if (TEST_PUDF(PUDF_FONTSARELOADED)) { 00405 LeaveCrit(); 00406 GreRemoveAllButPermanentFonts(); 00407 EnterCrit(); 00408 CLEAR_PUDF(PUDF_FONTSARELOADED); 00409 } 00410 } else { 00411 pwinsta->dwWSF_Flags &= ~WSF_OPENLOCK; 00412 } 00413 00414 /* 00415 * Tell winlogon that we successfully shutdown/logged off. 00416 */ 00417 NotifyLogon(pwinsta, &luidCaller, gdwShutdownFlags, STATUS_SUCCESS); 00418 00419 return STATUS_SUCCESS; 00420 }

PQMSG FindQMsg PTHREADINFO  pti,
PMLIST  pml,
PWND  pwndFilter,
UINT  msgMin,
UINT  msgMax,
BOOL  bProcessAck
 

Definition at line 3336 of file queue.c.

References CheckMsgFilter, CheckPwndFilter(), CheckRemoveHotkeyBit(), DebugValidateMLIST, DelQEntry(), tagXSTATE::flags, FreeDdeXact(), HMValidateHandleNoRip(), tagQ::idSysLock, tagQMSG::msg, MSGFLAG_DDE_MID_THUNK, NULL, tagTHREADINFO::pq, tagQMSG::pqmsgNext, tagMLIST::pqmsgRead, tagQ::ptiSysLock, PtoH, PXSTATE, RevalidateHwnd, TYPE_DDEXACT, UINT, and XS_FREEPXS.

Referenced by xxxFreeWindow(), and xxxReadPostMessage().

03343 { 03344 PWND pwnd; 03345 PQMSG pqmsgRead; 03346 PQMSG pqmsgRet = NULL; 03347 UINT message; 03348 03349 DebugValidateMLIST(pml); 03350 03351 pqmsgRead = pml->pqmsgRead; 03352 03353 while (pqmsgRead != NULL) { 03354 03355 /* 03356 * Make sure this window is valid and doesn't have the destroy 03357 * bit set (don't want to send it to any client side window procs 03358 * if destroy window has been called on it). 03359 */ 03360 pwnd = RevalidateHwnd(pqmsgRead->msg.hwnd); 03361 03362 if (pwnd == NULL && pqmsgRead->msg.hwnd != NULL) { 03363 /* 03364 * If we're removing a WM_HOTKEY message, we may need to 03365 * clear the QS_HOTKEY bit, since we have a special bit 03366 * for that message. 03367 */ 03368 if (pqmsgRead->msg.message == WM_HOTKEY) { 03369 CheckRemoveHotkeyBit(pti, pml); 03370 } 03371 /* 03372 * If the current thread's queue is locked waiting for this message, 03373 * we have to unlock it because we're eating the message. If there's 03374 * no more input/messages for this thread, the thread is going to 03375 * sleep; hence there might not be a next Get/PeekMessage call to 03376 * unlock the queue (ie, updating pti->idLast is not enough); 03377 * so we must unlock it now. 03378 * Win95 doesn't have this problem because their FindQMsg doesn't 03379 * eat messages; they call ReadPostMessage from FreeWindow 03380 * to take care of this scenario (== message for a destroyed window). 03381 * We could also do this if we have some problems with this fix. 03382 */ 03383 if ((pti->pq->idSysLock == (ULONG_PTR)pqmsgRead) 03384 && (pti->pq->ptiSysLock == pti)) { 03385 /* CheckSysLock(What number?, pti->pq, NULL); */ 03386 RIPMSG2(RIP_VERBOSE, "FindQMsg: Unlocking queue:%#p. Msg:%#lx", 03387 pti->pq, pqmsgRead->msg.message); 03388 pti->pq->ptiSysLock = NULL; 03389 } 03390 03391 DelQEntry(pml, pqmsgRead); 03392 goto nextMsgFromPml; 03393 } 03394 03395 /* 03396 * Process the WM_DDE_ACK messages if bProcessAck is set. 03397 */ 03398 if (bProcessAck && (PtoH(pwndFilter) == pqmsgRead->msg.hwnd) && 03399 (pqmsgRead->msg.message == (WM_DDE_ACK | MSGFLAG_DDE_MID_THUNK))) { 03400 03401 PXSTATE pxs; 03402 03403 pxs = (PXSTATE)HMValidateHandleNoRip((HANDLE)pqmsgRead->msg.lParam, TYPE_DDEXACT); 03404 03405 if (pxs != NULL && (pxs->flags & XS_FREEPXS)) { 03406 FreeDdeXact(pxs); 03407 DelQEntry(pml, pqmsgRead); 03408 goto nextMsgFromPml; 03409 } 03410 } 03411 03412 /* 03413 * Make sure this message fits both window handle and message 03414 * filters. 03415 */ 03416 if (!CheckPwndFilter(pwnd, pwndFilter)) 03417 goto nextMsg; 03418 03419 /* 03420 * If this is a fixed up dde message, then turn it into a normal 03421 * dde message for the sake of message filtering. 03422 */ 03423 message = pqmsgRead->msg.message; 03424 if (CheckMsgFilter(message, 03425 (WM_DDE_FIRST + 1) | MSGFLAG_DDE_MID_THUNK, 03426 WM_DDE_LAST | MSGFLAG_DDE_MID_THUNK)) { 03427 message = message & ~MSGFLAG_DDE_MID_THUNK; 03428 } 03429 03430 if (!CheckMsgFilter(message, msgMin, msgMax)) 03431 goto nextMsg; 03432 03433 /* 03434 * Found it. If bProcessAck is set, remember this pointer and go on 03435 * till we finish walking the list to process all WM_DDE_ACK messages. 03436 */ 03437 if (!bProcessAck) { 03438 DebugValidateMLIST(pml); 03439 return pqmsgRead; 03440 } 03441 03442 if (pqmsgRet == NULL) { 03443 pqmsgRet = pqmsgRead; 03444 } 03445 nextMsg: 03446 pqmsgRead = pqmsgRead->pqmsgNext; 03447 continue; 03448 03449 nextMsgFromPml: 03450 pqmsgRead = pml->pqmsgRead; 03451 continue; 03452 } 03453 03454 DebugValidateMLIST(pml); 03455 return pqmsgRet; 03456 }

__inline BOOL FLastGuiThread PTHREADINFO  pti  ) 
 

Definition at line 2521 of file queue.c.

References BOOL, NULL, tagTHREADINFO::ppi, tagPROCESSINFO::ptiList, and tagTHREADINFO::ptiSibling.

Referenced by xxxDestroyThreadInfo().

02522 { 02523 return (pti->ppi && 02524 pti->ppi->ptiList == pti && 02525 pti->ptiSibling == NULL); 02526 }

VOID FreeCachedQueues VOID   ) 
 

Definition at line 2193 of file queue.c.

References ExDeletePagedLookasideList(), NULL, QLookaside, and VOID().

Referenced by Win32kNtUserCleanup().

02195 { 02196 if (QLookaside != NULL) { 02197 ExDeletePagedLookasideList(QLookaside); 02198 UserFreePool(QLookaside); 02199 QLookaside = NULL; 02200 } 02201 }

VOID FreeMessageList PMLIST  pml  ) 
 

Definition at line 3106 of file queue.c.

References CleanEventMessage(), DebugValidateMLIST, DelQEntry(), NULL, tagMLIST::pqmsgRead, and VOID().

Referenced by xxxDestroyThreadInfo(), and zzzDestroyQueue().

03108 { 03109 PQMSG pqmsg; 03110 03111 DebugValidateMLIST(pml); 03112 03113 while ((pqmsg = pml->pqmsgRead) != NULL) { 03114 CleanEventMessage(pqmsg); 03115 DelQEntry(pml, pqmsg); 03116 } 03117 03118 DebugValidateMLIST(pml); 03119 }

VOID FreeQueue PQ  pq  ) 
 

Definition at line 2168 of file queue.c.

References ExFreeToPagedLookasideList(), gpqCursor, gpqForeground, gpqForegroundPrev, tagQ::QF_flags, QF_INDESTROY, QLookaside, and VOID().

Referenced by RtlpDphFreeDelayedBlocksFromHeap(), RtlpDphTrimDelayedFreeQueue(), UserDeleteW32Thread(), Win32kNtUserCleanup(), and zzzDestroyQueue().

02170 { 02171 #if DBG 02172 /* 02173 * Turn off the flag indicating that this queue is in destruction. 02174 * We do this in either case that we are putting this into the free 02175 * list, or truly destroying the handle. We use this to try and 02176 * track cases where someone tries to lock elements into the queue 02177 * structure while it's going through destuction. 02178 */ 02179 pq->QF_flags &= ~QF_INDESTROY; 02180 #endif 02181 02182 UserAssertMsg0(pq != gpqForeground, "FreeQueue(gpqForeground) !"); 02183 UserAssertMsg0(pq != gpqForegroundPrev, "FreeQueue(gpqForegroundPrev) !"); 02184 UserAssertMsg0(pq != gpqCursor, "FreeQueue(gpqCursor) !"); 02185 ExFreeToPagedLookasideList(QLookaside, pq); 02186 }

DWORD GetAppCompatFlags PTHREADINFO  pti  ) 
 

Definition at line 1014 of file queue.c.

References ConnectIfNecessary, tagTHREADINFO::dwCompatFlags, DWORD, GetClientInfo, NULL, and PtiCurrentShared.

Referenced by _GetWindow(), InternalInvalidate2(), LBGetScrollFlags(), xxxCalcValidRects(), xxxCreateWindowEx(), and xxxDoScrollMenu().

01016 { 01017 // From GRE with pti = NULL 01018 // We got to use PtiCurrentShared() 01019 if (pti == NULL) 01020 pti = PtiCurrentShared(); 01021 01022 return pti->dwCompatFlags; 01023 }

DWORD GetAppCompatFlags2 WORD  wVer  ) 
 

Definition at line 1033 of file queue.c.

References ConnectIfNecessary, DWORD, GetAppCompatFlags2ForPti(), GETAPPVER, GetClientInfo, and PtiCurrentShared.

Referenced by DispatchMessageWorker(), NtUserCreateWindowEx(), UnlinkConvFromOthers(), xxxCBShowListBoxWindow(), xxxDDETrackGetMessageHook(), xxxDDETrackWindowDying(), xxxDrawMenuBarUnderlines(), xxxDrawMenuItemText(), xxxInternalToUnicode(), xxxMenuBarDraw(), xxxMenuWindowProc(), xxxSetWindowStyle(), and zzzHideCursorNoCapture().

01035 { 01036 return GetAppCompatFlags2ForPti(PtiCurrentShared(), wVer); 01037 }

DWORD GetAppImeCompatFlags PTHREADINFO  pti  ) 
 

Definition at line 1039 of file queue.c.

References tagPROCESSINFO::dwImeCompatFlags, DWORD, NULL, tagTHREADINFO::ppi, and PtiCurrentShared.

Referenced by NlsKbdSendIMEProc(), xxxButtonEvent(), xxxImmProcessKey(), and xxxScanSysQueue().

01041 { 01042 if (pti == NULL) { 01043 pti = PtiCurrentShared(); 01044 } 01045 01046 UserAssert(pti->ppi); 01047 return pti->ppi->dwImeCompatFlags; 01048 }

PQ GetJournallingQueue PTHREADINFO  pti  ) 
 

Definition at line 1416 of file queue.c.

References GETPTI, IsHooked, NULL, PhkFirstGlobalValid(), tagTHREADINFO::rpdesk, TIF_DONTJOURNALATTACH, tagTHREADINFO::TIF_flags, and WHF_FROM_WH.

Referenced by xxxCreateThreadInfo(), and zzzSetDesktop().

01417 { 01418 PHOOK phook; 01419 /* 01420 * fail if we cannot journal this thread 01421 */ 01422 if ((pti->TIF_flags & TIF_DONTJOURNALATTACH) 01423 || (pti->rpdesk == NULL)) { 01424 01425 return NULL; 01426 } 01427 /* 01428 * Get the journalling hook if any. 01429 */ 01430 phook = PhkFirstGlobalValid(pti, WH_JOURNALPLAYBACK); 01431 if (phook == NULL) { 01432 phook = PhkFirstGlobalValid(pti, WH_JOURNALRECORD); 01433 } 01434 /* 01435 * Validate fsHooks bits. 01436 */ 01437 UserAssert((phook == NULL) 01438 ^ IsHooked(pti, (WHF_FROM_WH(WH_JOURNALPLAYBACK) | WHF_FROM_WH(WH_JOURNALRECORD)))); 01439 01440 /* 01441 * return the queue if we found a journalling hook 01442 */ 01443 return ((phook == NULL) ? NULL : GETPTI(phook)->pq); 01444 }

ULONG GetTaskName PTHREADINFO  pti,
PWSTR  Buffer,
ULONG  BufferLength
 

Definition at line 5857 of file queue.c.

References Buffer, FALSE, min, NT_SUCCESS, NTSTATUS(), NULL, tagTHREADINFO::pstrAppName, RtlAnsiStringToUnicodeString(), RtlInitAnsiString(), SHORT, and Status.

Referenced by xxxQueryInformationThread(), and xxxSendBSMtoDesktop().

05861 { 05862 ANSI_STRING strAppName; 05863 UNICODE_STRING strAppNameU; 05864 NTSTATUS Status; 05865 ULONG NameLength = 0; 05866 05867 if (pti == NULL) { 05868 *Buffer = 0; 05869 return 0; 05870 } 05871 if (pti->pstrAppName != NULL) { 05872 NameLength = min(pti->pstrAppName->Length + sizeof(WCHAR), BufferLength); 05873 RtlCopyMemory(Buffer, pti->pstrAppName->Buffer, NameLength); 05874 } else { 05875 RtlInitAnsiString(&strAppName, pti->pEThread->ThreadsProcess->ImageFileName); 05876 if (BufferLength < sizeof(WCHAR)) 05877 NameLength = (strAppName.Length + 1) * sizeof(WCHAR); 05878 else { 05879 strAppNameU.Buffer = Buffer; 05880 strAppNameU.MaximumLength = (SHORT)BufferLength - sizeof(WCHAR); 05881 Status = RtlAnsiStringToUnicodeString(&strAppNameU, &strAppName, 05882 FALSE); 05883 if (NT_SUCCESS(Status)) 05884 NameLength = strAppNameU.Length + sizeof(WCHAR); 05885 } 05886 } 05887 Buffer[(NameLength / sizeof(WCHAR)) - 1] = 0; 05888 05889 return NameLength; 05890 }

NTSTATUS InitiateShutdown PETHREAD  Thread,
PULONG  lpdwFlags
 

Definition at line 119 of file kernel/exitwin.c.

References tagPROCESSINFO::amwinsta, _ETHREAD::Cid, tagTHREADINFO::cWindows, dwFlags, DWORD, tagWINDOWSTATION::dwWSF_Flags, gdwLocks, gdwShutdownFlags, gdwThreadEndSession, GetProcessLuid(), gpidEndSession, gpidLogon, gptiShutdownNotify, gpwinstaLogoff, tagPROCESSINFO::hwinsta, IsPrivileged(), tagWINDOWSTATION::luidEndSession, luidSystem, NotifyLogon(), NT_SUCCESS, NTSTATUS(), NULL, OPTIONMASK, PpiFromProcess, PsGetCurrentThread, PtiFromThread, tagPROCESSINFO::rpwinsta, RtlAreAllAccessesGranted(), RtlEqualLuid(), Status, THREAD_TO_PROCESS, TIF_16BIT, tagTHREADINFO::TIF_flags, WSF_NOIO, WSF_OPENLOCK, WSF_REALSHUTDOWN, WSF_SHUTDOWN, and WSF_SWITCHLOCK.

Referenced by xxxSetInformationThread().

00122 { 00123 static PRIVILEGE_SET psShutdown = { 00124 1, PRIVILEGE_SET_ALL_NECESSARY, { SE_SHUTDOWN_PRIVILEGE, 0 } 00125 }; 00126 PEPROCESS Process; 00127 LUID luidCaller; 00128 PPROCESSINFO ppi; 00129 PWINDOWSTATION pwinsta; 00130 HWINSTA hwinsta; 00131 PTHREADINFO ptiClient; 00132 NTSTATUS Status; 00133 DWORD dwFlags; 00134 00135 /* 00136 * Find out the callers sid. Only want to shutdown processes in the 00137 * callers sid. 00138 */ 00139 Process = THREAD_TO_PROCESS(Thread); 00140 ptiClient = PtiFromThread(Thread); 00141 Status = GetProcessLuid(Thread, &luidCaller); 00142 00143 if (!NT_SUCCESS(Status)) { 00144 return Status; 00145 } 00146 00147 /* 00148 * Set the system flag if the caller is a system process. 00149 * Winlogon uses this to determine in which context to perform 00150 * a shutdown operation. 00151 */ 00152 dwFlags = *lpdwFlags; 00153 if (RtlEqualLuid(&luidCaller, &luidSystem)) { 00154 dwFlags |= EWX_SYSTEM_CALLER; 00155 } else { 00156 dwFlags &= ~EWX_SYSTEM_CALLER; 00157 } 00158 00159 /* 00160 * Find a windowstation. If the process does not have one 00161 * assigned, use the standard one. 00162 */ 00163 ppi = PpiFromProcess(Process); 00164 if (ppi == NULL) { 00165 /* 00166 * We ran into a case where the thread was terminated and had already 00167 * been cleaned up by USER. Thus, the ppi and ptiClient was NULL. 00168 */ 00169 return STATUS_INVALID_HANDLE; 00170 } 00171 pwinsta = ppi->rpwinsta; 00172 hwinsta = ppi->hwinsta; 00173 /* 00174 * If we're not being called by Winlogon, validate the call and 00175 * notify the logon process to do the actual shutdown. 00176 */ 00177 if (Thread->Cid.UniqueProcess != gpidLogon) { 00178 dwFlags &= ~EWX_WINLOGON_CALLER; 00179 *lpdwFlags = dwFlags; 00180 00181 if (pwinsta == NULL) { 00182 #ifndef LATER 00183 return STATUS_INVALID_HANDLE; 00184 #else 00185 hwinsta = ppi->pOpenObjectTable[HI_WINDOWSTATION].h; 00186 if (hwinsta == NULL) { 00187 return STATUS_INVALID_HANDLE; 00188 } 00189 pwinsta = (PWINDOWSTATION)ppi->pOpenObjectTable[HI_WINDOWSTATION].phead; 00190 #endif 00191 } 00192 00193 /* 00194 * Check security first - does this thread have access? 00195 */ 00196 if (!RtlAreAllAccessesGranted(ppi->amwinsta, WINSTA_EXITWINDOWS)) { 00197 return STATUS_ACCESS_DENIED; 00198 } 00199 00200 /* 00201 * If the client requested shutdown, reboot, or poweroff they must have 00202 * the shutdown privilege. 00203 */ 00204 if (dwFlags & EWX_SHUTDOWN) { 00205 if (!IsPrivileged(&psShutdown) ) { 00206 return STATUS_PRIVILEGE_NOT_HELD; 00207 } 00208 } else { 00209 00210 /* 00211 * If this is a non-IO windowstation and we are not shutting down, 00212 * fail the call. 00213 */ 00214 if (pwinsta->dwWSF_Flags & WSF_NOIO) { 00215 return STATUS_INVALID_DEVICE_REQUEST; 00216 } 00217 } 00218 } 00219 00220 /* 00221 * Is there a shutdown already in progress? 00222 */ 00223 if (gdwThreadEndSession != 0) { 00224 DWORD dwNew; 00225 00226 /* 00227 * If the current shutdown in another sid and is not being done by 00228 * winlogon, override it. 00229 */ 00230 if (!RtlEqualLuid(&luidCaller, &gpwinstaLogoff->luidEndSession) && 00231 (gpidEndSession != gpidLogon)) { 00232 return STATUS_RETRY; 00233 } 00234 00235 /* 00236 * Calculate new flags 00237 */ 00238 dwNew = dwFlags & OPTIONMASK & (~gdwShutdownFlags); 00239 00240 /* 00241 * Should we override the other shutdown? Make sure 00242 * winlogon does not recurse. 00243 */ 00244 if (dwNew && HandleToUlong(PsGetCurrentThread()->Cid.UniqueThread) != 00245 gdwThreadEndSession) { 00246 /* 00247 * Only one windowstation can be logged off at a time. 00248 */ 00249 if (!(dwFlags & EWX_SHUTDOWN) && 00250 pwinsta != gpwinstaLogoff) { 00251 return STATUS_DEVICE_BUSY; 00252 } 00253 00254 /* 00255 * Set the new flags 00256 */ 00257 gdwShutdownFlags = dwFlags; 00258 00259 if (dwNew & EWX_FORCE) { 00260 return STATUS_RETRY; 00261 } else { 00262 return STATUS_PENDING; 00263 } 00264 } else { 00265 /* 00266 * Don't override 00267 */ 00268 return STATUS_PENDING; 00269 } 00270 } 00271 00272 /* 00273 * If the caller is not winlogon, signal winlogon to start 00274 * the real shutdown. 00275 */ 00276 if (Thread->Cid.UniqueProcess != gpidLogon) { 00277 if (dwFlags & EWX_NOTIFY) { 00278 if (ptiClient && ptiClient->TIF_flags & TIF_16BIT) 00279 gptiShutdownNotify = ptiClient; 00280 dwFlags &= ~EWX_NOTIFY; 00281 *lpdwFlags = dwFlags; 00282 } 00283 00284 if (NotifyLogon(pwinsta, &luidCaller, dwFlags, STATUS_SUCCESS)) 00285 return STATUS_PENDING; 00286 else if (ptiClient && ptiClient->cWindows) 00287 return STATUS_CANT_WAIT; 00288 } 00289 00290 /* 00291 * Mark this thread as the one that is currently processing 00292 * exit windows, and set the global saying someone is exiting 00293 */ 00294 dwFlags |= EWX_WINLOGON_CALLER; 00295 *lpdwFlags = dwFlags; 00296 gdwShutdownFlags = dwFlags; 00297 00298 gdwThreadEndSession = HandleToUlong(PsGetCurrentThread()->Cid.UniqueThread); 00299 gpidEndSession = PsGetCurrentThread()->Cid.UniqueProcess; 00300 gpwinstaLogoff = pwinsta; 00301 pwinsta->luidEndSession = luidCaller; 00302 00303 /* 00304 * Lock the windowstation to prevent apps from starting 00305 * while we're doing shutdown processing. 00306 */ 00307 gdwLocks = pwinsta->dwWSF_Flags & (WSF_SWITCHLOCK | WSF_OPENLOCK); 00308 pwinsta->dwWSF_Flags |= (WSF_OPENLOCK | WSF_SHUTDOWN); 00309 00310 /* 00311 * Set the flag WSF_REALSHUTDOWN if we are not doing just a 00312 * logoff 00313 */ 00314 if (dwFlags & 00315 (EWX_WINLOGON_OLD_SHUTDOWN | EWX_WINLOGON_OLD_REBOOT | 00316 EWX_SHUTDOWN | EWX_REBOOT)) { 00317 00318 pwinsta->dwWSF_Flags |= WSF_REALSHUTDOWN; 00319 } 00320 00321 return STATUS_SUCCESS; 00322 }

NTSTATUS InitQEntryLookaside  ) 
 

Definition at line 3169 of file queue.c.

References ExInitializePagedLookasideList(), NULL, PAGED_LOOKASIDE_LIST, QEntryLookaside, QLookaside, and SESSION_POOL_MASK.

Referenced by Win32UserInitialize().

03170 { 03171 QEntryLookaside = UserAllocPoolNonPaged(sizeof(PAGED_LOOKASIDE_LIST), TAG_LOOKASIDE); 03172 if (QEntryLookaside == NULL) { 03173 return STATUS_NO_MEMORY; 03174 } 03175 03176 ExInitializePagedLookasideList(QEntryLookaside, 03177 NULL, 03178 NULL, 03179 SESSION_POOL_MASK, 03180 sizeof(QMSG), 03181 TAG_QMSG, 03182 16); 03183 03184 QLookaside = UserAllocPoolNonPaged(sizeof(PAGED_LOOKASIDE_LIST), TAG_LOOKASIDE); 03185 if (QLookaside == NULL) { 03186 return STATUS_NO_MEMORY; 03187 } 03188 03189 ExInitializePagedLookasideList(QLookaside, 03190 NULL, 03191 NULL, 03192 SESSION_POOL_MASK, 03193 sizeof(Q), 03194 TAG_Q, 03195 16); 03196 return STATUS_SUCCESS; 03197 }

NTSTATUS InitQEntryLookaside VOID   ) 
 

ULONG ParseReserved WCHAR *  pchReserved,
WCHAR *  pchFind
 

Definition at line 1474 of file queue.c.

References NULL, RtlInitUnicodeString(), and RtlUnicodeStringToInteger().

Referenced by SetUpConsoleInfo(), and xxxCreateThreadInfo().

01477 { 01478 ULONG dw; 01479 WCHAR *pch, *pchT, ch; 01480 UNICODE_STRING uString; 01481 01482 dw = 0; 01483 if (pchReserved != NULL && (pch = wcsstr(pchReserved, pchFind)) != NULL) { 01484 pch += wcslen(pchFind); 01485 01486 pchT = pch; 01487 while (*pchT >= '0' && *pchT <= '9') 01488 pchT++; 01489 01490 ch = *pchT; 01491 *pchT = 0; 01492 RtlInitUnicodeString(&uString, pch); 01493 *pchT = ch; 01494 01495 RtlUnicodeStringToInteger(&uString, 0, &dw); 01496 } 01497 01498 return dw; 01499 }

PTHREADINFO PtiFromThreadId DWORD  dwThreadId  ) 
 

Definition at line 4737 of file queue.c.

References FALSE, LockThreadByClientId(), NT_SUCCESS, NULL, PsIsThreadTerminating, PtiFromThread, tagTHREADINFO::TIF_flags, TIF_GUITHREADINITIALIZED, TIF_INCLEANUP, and UnlockThread.

Referenced by _SetWinEventHook(), NtUserAttachThreadInput(), NtUserBuildHimcList(), NtUserBuildHwndList(), NtUserDisableThreadIme(), NtUserGetGUIThreadInfo(), NtUserGetThreadState(), NtUserPostThreadMessage(), NtUserSetWindowsHookEx(), UT_CaretSet(), xxxConsoleControl(), xxxDirectedYield(), xxxGetThreadDesktop(), and zzzAttachThreadInput().

04739 { 04740 PETHREAD pEThread; 04741 PTHREADINFO pti; 04742 04743 /* 04744 * BUG BUG: Pretty much every place else we do call LockThreadByClientId 04745 * while outside the user critical section so we don't cause any 04746 * potential deadlock in the kernel. 04747 * It's too late to change it now. 2/17/99 04748 */ 04749 04750 if (!NT_SUCCESS(LockThreadByClientId((HANDLE)LongToHandle( dwThreadId ), &pEThread))) 04751 return NULL; 04752 04753 /* 04754 * If the thread is not terminating, look up the pti. This is 04755 * needed because the value returned by PtiFromThread() is 04756 * undefined if the thread is terminating. See PspExitThread in 04757 * ntos\ps\psdelete.c. 04758 */ 04759 if (!PsIsThreadTerminating(pEThread)) { 04760 pti = PtiFromThread(pEThread); 04761 } else { 04762 pti = NULL; 04763 } 04764 04765 /* 04766 * Do a sanity check on the pti to make sure it's really valid. 04767 */ 04768 if (pti != NULL) { 04769 try { 04770 if (pti->pEThread->Cid.UniqueThread != (HANDLE)LongToHandle( dwThreadId )) { 04771 pti = NULL; 04772 } else if (!(pti->TIF_flags & TIF_GUITHREADINITIALIZED)) { 04773 RIPMSG1(RIP_WARNING, "PtiFromThreadId: pti %#p not initialized", pti); 04774 pti = NULL; 04775 } else if (pti->TIF_flags & TIF_INCLEANUP) { 04776 RIPMSG1(RIP_WARNING, "PtiFromThreadId: pti %#p in cleanup", pti); 04777 pti = NULL; 04778 } 04779 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 04780 pti = NULL; 04781 } 04782 } 04783 04784 UnlockThread(pEThread); 04785 04786 return pti; 04787 }

void ScreenSaverCheck PTHREADINFO  pti  ) 
 

BOOL SetAppCompatFlags PTHREADINFO  pti  ) 
 

Definition at line 814 of file queue.c.

References BOOL, BYTE, tagTHREADINFO::dwCompatFlags, _CLIENTINFO::dwCompatFlags, tagTHREADINFO::dwCompatFlags2, _CLIENTINFO::dwCompatFlags2, dwFlags, DWORD, FALSE, FastGetProfileStringW(), FastGetProfileValue(), L, MAXMODULENAMELEN, NULL, tagTHREADINFO::pClientInfo, PMAP_COMPAT2, PMAP_COMPAT32, tagTHREADINFO::ppi, PpiCurrent, ProbeAndReadUnicodeString, ProbeForRead, ProbeForReadUnicodeStringBuffer, tagTHREADINFO::pstrAppName, tagPROCESSINFO::ptiList, tagTHREADINFO::ptiSibling, QUERY_VALUE_BUFFER, RtlImageNtHeader(), RtlInitUnicodeString(), RtlUnicodeStringToInteger(), SetAppImeCompatFlags(), TIF_16BIT, tagTHREADINFO::TIF_flags, TRUE, and USHORT.

Referenced by xxxCreateThreadInfo().

00816 { 00817 DWORD dwFlags = 0; 00818 DWORD dwFlags2 = 0; 00819 WCHAR szHex[QUERY_VALUE_BUFFER]; 00820 WCHAR szKey[90]; 00821 WCHAR *pchStart, *pchEnd; 00822 DWORD cb; 00823 PUNICODE_STRING pstrAppName; 00824 UNICODE_STRING strKey; 00825 UNICODE_STRING strImageName; 00826 ULONG cbSize; 00827 typedef struct tagCompat2Key { 00828 DWORD dwCompatFlags2; 00829 DWORD dwMajorVersion; 00830 DWORD dwMinorVersion; 00831 DWORD dwBuildNumber; 00832 DWORD dwPlatformId; 00833 } COMPAT2KEY, *PCOMPAT2KEY; 00834 COMPAT2KEY Compat2Key; 00835 00836 /* 00837 * Because can't access pClientInfo of another process 00838 */ 00839 UserAssert(pti->ppi == PpiCurrent()); 00840 00841 UserAssert(pti->ppi->ptiList); 00842 00843 UserAssert(!(pti->TIF_flags & TIF_16BIT)); 00844 00845 /* 00846 * We assume here that pti was just inserted in at the head of ptiList 00847 */ 00848 UserAssert(pti == pti->ppi->ptiList); 00849 00850 if (pti->ptiSibling) { 00851 pti->pClientInfo->dwCompatFlags = pti->dwCompatFlags = pti->ptiSibling->dwCompatFlags; 00852 pti->pClientInfo->dwCompatFlags2 = pti->dwCompatFlags2 = pti->ptiSibling->dwCompatFlags2; 00853 return FALSE; 00854 } 00855 00856 try { 00857 /* 00858 * PEB can be trashed from the client side, so we need to probe pointers in it 00859 * MCostea 317180 00860 */ 00861 /* 00862 * Find end of app name 00863 */ 00864 if (pti->pstrAppName != NULL) 00865 pstrAppName = pti->pstrAppName; 00866 else { 00867 struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters = pti->pEThread->ThreadsProcess->Peb->ProcessParameters; 00868 00869 ProbeForRead(ProcessParameters, sizeof(*ProcessParameters), sizeof(BYTE)); 00870 strImageName = ProbeAndReadUnicodeString(&ProcessParameters->ImagePathName); 00871 ProbeForReadUnicodeStringBuffer(strImageName); 00872 pstrAppName = &strImageName; 00873 } 00874 pchStart = pchEnd = pstrAppName->Buffer + 00875 (pstrAppName->Length / sizeof(WCHAR)); 00876 00877 /* 00878 * Locate start of extension 00879 */ 00880 while (TRUE) { 00881 if (pchEnd == pstrAppName->Buffer) { 00882 pchEnd = pchStart; 00883 break; 00884 } 00885 00886 if (*pchEnd == TEXT('.')) 00887 break; 00888 00889 pchEnd--; 00890 } 00891 00892 /* 00893 * Locate start of filename 00894 */ 00895 pchStart = pchEnd; 00896 00897 while (pchStart != pstrAppName->Buffer) { 00898 if (*pchStart == TEXT('\\') || *pchStart == TEXT(':')) { 00899 pchStart++; 00900 break; 00901 } 00902 00903 pchStart--; 00904 } 00905 00906 #define MODULESUFFIXSIZE (8*sizeof(WCHAR)) 00907 #define MAXMODULENAMELEN (sizeof(szKey) - MODULESUFFIXSIZE) 00908 /* 00909 * Get a copy of the filename 00910 * Allow extra spaces for the 'ImageSubsystemMajorVersionMinorVersion' 00911 * i.e. 3.5 that will get appended at the end of the module name 00912 */ 00913 cb = (DWORD)(pchEnd - pchStart) * sizeof(WCHAR); 00914 if (cb >= MAXMODULENAMELEN) 00915 cb = MAXMODULENAMELEN - sizeof(WCHAR); 00916 RtlCopyMemory(szKey, pchStart, cb); 00917 } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { 00918 return FALSE; 00919 } 00920 00921 szKey[(cb / sizeof(WCHAR))] = 0; 00922 #undef MAXMODULENAMELEN 00923 00924 if (FastGetProfileStringW( 00925 NULL, 00926 PMAP_COMPAT32, 00927 szKey, 00928 NULL, 00929 szHex, 00930 sizeof(szHex) 00931 )) { 00932 00933 UNICODE_STRING strHex; 00934 00935 /* 00936 * Found some flags. Attempt to convert the hex string 00937 * into numeric value. Specify base 0, so 00938 * RtlUnicodeStringToInteger will handle the 0x format 00939 */ 00940 RtlInitUnicodeString(&strHex, szHex); 00941 RtlUnicodeStringToInteger(&strHex, 0, (PULONG)&dwFlags); 00942 } 00943 00944 pti->dwCompatFlags = dwFlags; 00945 pti->pClientInfo->dwCompatFlags = dwFlags; 00946 00947 /* 00948 * Retrieve the image version 00949 */ 00950 { 00951 PIMAGE_NT_HEADERS pnthdr; 00952 USHORT uMinorImage, uMajorImage; 00953 PWCHAR pWritePtr = szKey + cb/sizeof(WCHAR); 00954 00955 try { 00956 pnthdr = RtlImageNtHeader(pti->pEThread->ThreadsProcess->SectionBaseAddress); 00957 if (pnthdr != NULL) { 00958 uMinorImage = pnthdr->OptionalHeader.MinorImageVersion & 0xFF; 00959 uMajorImage = pnthdr->OptionalHeader.MajorImageVersion & 0xFF; 00960 } else { 00961 uMinorImage = uMajorImage = 0; 00962 } 00963 } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { 00964 goto Compat2Failed; 00965 } 00966 swprintf(pWritePtr, L"%u.%u", uMajorImage, uMinorImage); 00967 } 00968 cbSize = FastGetProfileValue( 00969 NULL, 00970 PMAP_COMPAT2, 00971 szKey, 00972 NULL, 00973 (LPBYTE)&Compat2Key, 00974 sizeof(Compat2Key)); 00975 /* 00976 * The first DWORD in Compat2 is the CompatFlags. There might be or not 00977 * version information but dwCompatFlags2 is always there if the key exist. 00978 * We will be able to include extra data in these keys by setting the 00979 * MajorVersion to zero and thus the version information will not be changed 00980 */ 00981 if (cbSize >= sizeof(DWORD)) { 00982 pti->dwCompatFlags2 = pti->pClientInfo->dwCompatFlags2 = Compat2Key.dwCompatFlags2; 00983 00984 if (cbSize >= sizeof(COMPAT2KEY) && Compat2Key.dwMajorVersion != 0) { 00985 PPEB Peb = pti->pEThread->ThreadsProcess->Peb; 00986 00987 Peb->OSMajorVersion = Compat2Key.dwMajorVersion; 00988 Peb->OSMinorVersion = Compat2Key.dwMinorVersion; 00989 Peb->OSBuildNumber = (USHORT)(Compat2Key.dwBuildNumber); 00990 Peb->OSPlatformId = Compat2Key.dwPlatformId; 00991 } 00992 } 00993 00994 Compat2Failed: 00995 /* 00996 * Restore the string 00997 */ 00998 szKey[(cb / sizeof(WCHAR))] = 0; 00999 RtlInitUnicodeString(&strKey, szKey); 01000 01001 return SetAppImeCompatFlags(pti, &strKey, NULL); 01002 }

BOOL SetAppImeCompatFlags PTHREADINFO  pti,
PUNICODE_STRING  pstrModName,
PUNICODE_STRING  pstrBaseFileName
 

Definition at line 702 of file queue.c.

References BOOL, tagTHREADINFO::dwExpWinVer, tagPROCESSINFO::dwImeCompatFlags, DWORD, FALSE, FastGetProfileStringW(), giSetupExe, gpastrSetupExe, NULL, PMAP_IMECOMPAT, tagTHREADINFO::ppi, PpiCurrent, QUERY_VALUE_BUFFER, RtlCompareUnicodeString(), RtlInitUnicodeString(), RtlUnicodeStringToInteger(), TRUE, and VER31.

Referenced by SetAppCompatFlags(), and zzzInitTask().

00706 { 00707 DWORD dwImeFlags = 0; 00708 WCHAR szHex[QUERY_VALUE_BUFFER]; 00709 WORD wPrimaryLangID; 00710 LCID lcid; 00711 int iSetup; 00712 BOOL fSetup = FALSE; 00713 int iAppName; 00714 int cAppNames; 00715 PUNICODE_STRING rgpstrAppNames[2]; 00716 UNICODE_STRING strHex; 00717 00718 /* 00719 * Because can't access pClientInfo of another process 00720 */ 00721 UserAssert(pti->ppi == PpiCurrent()); 00722 00723 /* 00724 * Because it is used as a zero-terminated profile key name. 00725 */ 00726 UserAssert(0 == pstrModName->Buffer[ pstrModName->Length / sizeof(WCHAR) ]); 00727 00728 if (FastGetProfileStringW( 00729 NULL, 00730 PMAP_IMECOMPAT, 00731 pstrModName->Buffer, 00732 NULL, 00733 szHex, 00734 sizeof(szHex) 00735 )) { 00736 00737 /* 00738 * Found some flags. Attempt to convert the hex string 00739 * into numeric value. Specify base 0, so 00740 * RtlUnicodeStringToInteger will handle the 0x format 00741 */ 00742 RtlInitUnicodeString(&strHex, szHex); 00743 RtlUnicodeStringToInteger(&strHex, 0, (PULONG)&dwImeFlags); 00744 } 00745 00746 /* 00747 * if current layout is not IME layout, Actually, we don't need to 00748 * get compatible flags for IME. But now, we don't have any scheme 00749 * to get this flags when the keyboard layout is switched. then 00750 * we get it here, even this flags are not nessesary for non-IME 00751 * keyboard layouts. 00752 */ 00753 ZwQueryDefaultLocale(FALSE, &lcid); 00754 wPrimaryLangID = PRIMARYLANGID(lcid); 00755 00756 if ((wPrimaryLangID == LANG_KOREAN || wPrimaryLangID == LANG_JAPANESE) && 00757 (LOWORD(pti->dwExpWinVer) <= VER31)) { 00758 /* 00759 * IME compatibility flags are needed even it's a 32 bit app 00760 */ 00761 pti->ppi->dwImeCompatFlags = dwImeFlags; 00762 } else { 00763 pti->ppi->dwImeCompatFlags = dwImeFlags & (IMECOMPAT_NOFINALIZECOMPSTR | IMECOMPAT_HYDRACLIENT); 00764 if (dwImeFlags & IMECOMPAT_NOFINALIZECOMPSTR) { 00765 RIPMSG1(RIP_WARNING, "IMECOMPAT_NOFINALIZECOMPSTR is set to ppi=0x%p", pti->ppi); 00766 } 00767 if (dwImeFlags & IMECOMPAT_HYDRACLIENT) { 00768 RIPMSG1(RIP_WARNING, "IMECOMPAT_HYDRACLIENT is set to ppi=0x%p", pti->ppi); 00769 } 00770 } 00771 00772 00773 if (gpastrSetupExe == NULL) { 00774 return fSetup; 00775 } 00776 00777 rgpstrAppNames[0] = pstrModName; 00778 cAppNames = 1; 00779 if (pstrBaseFileName) { 00780 rgpstrAppNames[1] = pstrBaseFileName; 00781 cAppNames = 2; 00782 } 00783 00784 for (iAppName = 0; 00785 iAppName < cAppNames && !fSetup; 00786 iAppName++) { 00787 00788 iSetup = 0; 00789 while (iSetup < giSetupExe) { 00790 int i; 00791 if ((i = RtlCompareUnicodeString(rgpstrAppNames[iAppName], &(gpastrSetupExe[iSetup]), TRUE)) == 0) { 00792 fSetup = TRUE; 00793 break; 00794 } 00795 iSetup++; 00796 } 00797 } 00798 00799 return fSetup; 00800 }

void SetAppStarting PPROCESSINFO  ppi  ) 
 

Definition at line 1094 of file queue.c.

References CheckAppStarting(), CMSAPPSTARTINGTIMEOUT, CMSHUNGAPPTIMEOUT, gppiStarting, gptmrMaster, InternalSetTimer(), NULL, and tagPROCESSINFO::ppiNext.

Referenced by xxxInitProcessInfo(), xxxUserNotifyConsoleApplication(), and zzzInitTask().

01095 { 01096 static UINT_PTR guAppStartingId = 0; 01097 01098 // This ppi had better not be in the list already, or we will be creating 01099 // a loop (as seen in stress) 01100 UserAssert((ppi->W32PF_Flags & W32PF_APPSTARTING) == 0); 01101 01102 /* 01103 * if we add this to the gppiStartingList without this bit set, we will 01104 * skip removing it from the list in DestroyProcessInfo(), but continue 01105 * to free it in FreeW32Process called by W32pProcessCallout 01106 */ 01107 UserAssert((ppi->W32PF_Flags & W32PF_PROCESSCONNECTED)); 01108 01109 ppi->W32PF_Flags |= W32PF_APPSTARTING; 01110 ppi->ppiNext = gppiStarting; 01111 gppiStarting = ppi; 01112 /* 01113 * Some system processes are initialized before the RIT has setup the master 01114 * timer; so check for it 01115 */ 01116 if (gptmrMaster != NULL) { 01117 guAppStartingId = InternalSetTimer(NULL, guAppStartingId, 01118 CMSAPPSTARTINGTIMEOUT + CMSHUNGAPPTIMEOUT, 01119 CheckAppStarting, TMRF_RIT | TMRF_ONESHOT); 01120 } 01121 }

NTSTATUS SetInformationProcess IN HANDLE  hProcess,
IN USERPROCESSINFOCLASS  ProcessInfoClass,
IN PVOID  ProcessInformation,
IN ULONG  ProcessInformationLength
 

Definition at line 6357 of file queue.c.

References DWORD, FALSE, ISCSRSS, NT_SUCCESS, NTSTATUS(), NULL, ObReferenceObjectByHandle(), PpiFromProcess, PsProcessType, Status, UnlockProcess, and UserMode.

Referenced by NtUserSetInformationProcess().

06362 { 06363 PUSERPROCESS_FLAGS pFlags; 06364 DWORD dwOldFlags; 06365 NTSTATUS Status = STATUS_SUCCESS; 06366 PEPROCESS Process; 06367 PPROCESSINFO ppi; 06368 06369 UNREFERENCED_PARAMETER(ProcessInformationLength); 06370 06371 UserAssert(ISCSRSS()); 06372 06373 Status = ObReferenceObjectByHandle(hProcess, 06374 PROCESS_SET_INFORMATION, 06375 *PsProcessType, 06376 UserMode, 06377 &Process, 06378 NULL); 06379 if (!NT_SUCCESS(Status)) { 06380 return Status; 06381 } 06382 06383 ppi = PpiFromProcess(Process); 06384 06385 switch (ProcessInfoClass) { 06386 case UserProcessFlags: 06387 if (ppi == NULL) { 06388 Status = STATUS_INVALID_HANDLE; 06389 } else { 06390 UserAssert(ProcessInformationLength == sizeof(USERPROCESS_FLAGS)); 06391 pFlags = ProcessInformation; 06392 dwOldFlags = ppi->W32PF_Flags; 06393 ppi->W32PF_Flags ^= ((dwOldFlags ^ pFlags->dwFlags) & pFlags->dwMask); 06394 } 06395 break; 06396 06397 default: 06398 Status = STATUS_INVALID_INFO_CLASS; 06399 UserAssert(FALSE); 06400 break; 06401 } 06402 06403 UnlockProcess(Process); 06404 06405 return Status; 06406 }

void SetVDMCursorBounds LPRECT  lprc  ) 
 

Definition at line 351 of file ntuser/kernel/cursor.c.

References CLEAR_PUDF, grcVDMCursorBounds, NULL, PUDF_VDMBOUNDSACTIVE, SET_PUDF, and VOID().

Referenced by xxxConsoleControl(), and xxxMakeWindowForegroundWithState().

00353 { 00354 if (lprc != NULL) { 00355 00356 /* 00357 * Set grcVDMCursorBounds before TEST_PUDF(PUDF_VDMBOUNDSACTIVE), because 00358 * MoveEvent() calls BoundCursor() from outside the USER CritSect! 00359 */ 00360 grcVDMCursorBounds = *lprc; 00361 SET_PUDF(PUDF_VDMBOUNDSACTIVE); 00362 00363 } else { 00364 00365 /* 00366 * Turn vdm bounds off. 00367 */ 00368 CLEAR_PUDF(PUDF_VDMBOUNDSACTIVE); 00369 } 00370 }

VOID SetWakeBit PTHREADINFO  pti,
UINT  wWakeBit
 

Definition at line 4578 of file queue.c.

References CheckCritIn, FALSE, tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeBits, tagCLIENTTHREADINFO::fsWakeMask, gpsi, gptSSCursor, KeSetEvent(), tagTDB::nEvents, tagTHREADINFO::pcti, tagTHREADINFO::pEventQueueServer, tagTHREADINFO::ppi, tagTHREADINFO::pq, tagTHREADINFO::ptdb, tagQ::ptiKeyboard, tagQ::ptiMouse, SetForegroundPriority(), TIF_16BIT, tagTHREADINFO::TIF_flags, TRUE, VOID(), and WakeWowTask().

Referenced by _PostMessage(), _PostThreadMessage(), _ReplyMessage(), DestroyProcessInfo(), DoTimer(), IncPaintCount(), IPostQuitMessage(), PostEventMessage(), PostUpdateKeyStateEvent(), ReceiverDied(), RedistributeInput(), TimersProc(), WakeSomeone(), xxxCancelTrackingForThread(), xxxDeactivate(), xxxInterSendMsgEx(), xxxProcessEventMessage(), xxxReceiveMessage(), xxxScanSysQueue(), xxxSetForegroundWindow2(), xxxSystemTimerProc(), zzzDestroyQueue(), and zzzSetFMouseMoved().

04581 { 04582 CheckCritIn(); 04583 04584 UserAssert(pti); 04585 04586 /* 04587 * Win3.1 changes ptiKeyboard and ptiMouse accordingly if we're setting 04588 * those bits. 04589 */ 04590 if (wWakeBit & QS_MOUSE) 04591 pti->pq->ptiMouse = pti; 04592 04593 if (wWakeBit & QS_KEY) 04594 pti->pq->ptiKeyboard = pti; 04595 04596 /* 04597 * OR in these bits - these bits represent what input this app has 04598 * (fsWakeBits), or what input has arrived since that last look 04599 * (fsChangeBits). 04600 */ 04601 pti->pcti->fsWakeBits |= wWakeBit; 04602 pti->pcti->fsChangeBits |= wWakeBit; 04603 04604 /* 04605 * Before waking, do screen saver check to see if it should 04606 * go away. 04607 */ 04608 if ((wWakeBit & QS_INPUT) 04609 && (pti->ppi->W32PF_Flags & W32PF_IDLESCREENSAVER)) { 04610 if ((wWakeBit & QS_MOUSEMOVE) 04611 && (gpsi->ptCursor.x == gptSSCursor.x) 04612 && (gpsi->ptCursor.y == gptSSCursor.y)) { 04613 goto SkipScreenSaverStuff; 04614 } 04615 04616 /* 04617 * Our idle screen saver needs to be given a priority boost so that it 04618 * can process input. 04619 */ 04620 pti->ppi->W32PF_Flags &= ~W32PF_IDLESCREENSAVER; 04621 SetForegroundPriority(pti, TRUE); 04622 } 04623 04624 SkipScreenSaverStuff: 04625 if (wWakeBit & pti->pcti->fsWakeMask) { 04626 /* 04627 * Wake the Thread 04628 */ 04629 if (pti->TIF_flags & TIF_16BIT) { 04630 pti->ptdb->nEvents++; 04631 gpsi->nEvents++; 04632 WakeWowTask(pti); 04633 } else { 04634 KeSetEvent(pti->pEventQueueServer, 2, FALSE); 04635 } 04636 } 04637 }

void StoreMessage LPMSG  pmsg,
PWND  pwnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam,
DWORD  time
 

Definition at line 4799 of file queue.c.

References CheckCritIn, gpsi, HW, and NtGetTickCount().

Referenced by CheckQuitMessage(), and DoPaint().

04806 { 04807 CheckCritIn(); 04808 04809 pmsg->hwnd = HW(pwnd); 04810 pmsg->message = message; 04811 pmsg->wParam = wParam; 04812 pmsg->lParam = lParam; 04813 pmsg->time = (time != 0 ? time : NtGetTickCount()); 04814 04815 pmsg->pt = gpsi->ptCursor; 04816 }

void StoreQMessage PQMSG  pqmsg,
PWND  pwnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam,
DWORD  time,
DWORD  dwQEvent,
ULONG_PTR  dwExtraInfo
 

Definition at line 4831 of file queue.c.

References CheckCritIn, tagQMSG::dwQEvent, tagQMSG::ExtraInfo, gpsi, HW, tagQMSG::msg, and NtGetTickCount().

Referenced by _PostMessage(), _PostThreadMessage(), DestroyProcessInfo(), DoTimer(), PostEventMessage(), PostInputMessage(), xxxCallJournalPlaybackHook(), and xxxSetForegroundWindow2().

04840 { 04841 CheckCritIn(); 04842 04843 pqmsg->msg.hwnd = HW(pwnd); 04844 pqmsg->msg.message = message; 04845 pqmsg->msg.wParam = wParam; 04846 pqmsg->msg.lParam = lParam; 04847 pqmsg->msg.time = (time == 0) ? NtGetTickCount() : time; 04848 04849 #ifdef REDIRECTION 04850 if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) { 04851 pqmsg->msg.pt.x = LOWORD(lParam); 04852 pqmsg->msg.pt.y = HIWORD(lParam); 04853 } else { 04854 pqmsg->msg.pt = gpsi->ptCursor; 04855 } 04856 #else 04857 pqmsg->msg.pt = gpsi->ptCursor; 04858 #endif 04859 pqmsg->dwQEvent = dwQEvent; 04860 pqmsg->ExtraInfo = dwExtraInfo; 04861 }

void TransferWakeBit PTHREADINFO  pti,
UINT  message
 

Definition at line 4649 of file queue.c.

References CalcWakeMask(), tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeBits, tagTHREADINFO::pcti, tagTHREADINFO::pq, tagQ::ptiKeyboard, tagQ::ptiMouse, and UINT.

Referenced by xxxScanSysQueue().

04652 { 04653 PTHREADINFO ptiT; 04654 UINT fsMask; 04655 04656 /* 04657 * Calculate the mask from the message range. Only interested 04658 * in hardware input here: mouse and keys. 04659 */ 04660 fsMask = CalcWakeMask(message, message, 0) & (QS_MOUSE | QS_KEY); 04661 04662 /* 04663 * If it is set in this thread's wakebits, nothing to do. 04664 * Otherwise transfer them from the owner to this thread. 04665 */ 04666 if (!(pti->pcti->fsWakeBits & fsMask)) { 04667 /* 04668 * Either mouse or key is set (not both). Remove this bit 04669 * from the thread that currently owns it, and change mouse / 04670 * key ownership to this thread. 04671 */ 04672 if (fsMask & QS_KEY) { 04673 ptiT = pti->pq->ptiKeyboard; 04674 pti->pq->ptiKeyboard = pti; 04675 } else { 04676 ptiT = pti->pq->ptiMouse; 04677 pti->pq->ptiMouse = pti; 04678 } 04679 ptiT->pcti->fsWakeBits &= ~fsMask; 04680 04681 /* 04682 * Transfer them to this thread (certainly this may be the 04683 * same thread for win32 threads not sharing queues). 04684 */ 04685 pti->pcti->fsWakeBits |= fsMask; 04686 pti->pcti->fsChangeBits |= fsMask; 04687 } 04688 }

VOID UserDeleteW32Process PW32PROCESS  pW32Process  ) 
 

Definition at line 2475 of file queue.c.

References tagPROCESSINFO::bmHandleFlags, EnterHandleFlagsCrit(), LeaveHandleFlagsCrit(), NULL, RtlInitializeBitMap(), and VOID().

02476 { 02477 PPROCESSINFO ppi = (PPROCESSINFO)pW32Process; 02478 02479 BEGIN_REENTERCRIT(); 02480 02481 /* 02482 * Make sure the ref count didn't get bumped up while we were waiting. 02483 */ 02484 if (pW32Process->RefCount == 0) { 02485 02486 /* 02487 * Grab the handle flags lock. We can't call into the object manager when 02488 * we have this or we might deadlock. 02489 */ 02490 EnterHandleFlagsCrit(); 02491 02492 /* 02493 * Delete handle flags attribute bitmap 02494 */ 02495 if (ppi->bmHandleFlags.Buffer) { 02496 UserFreePool(ppi->bmHandleFlags.Buffer); 02497 RtlInitializeBitMap(&ppi->bmHandleFlags, NULL, 0); 02498 } 02499 02500 /* 02501 * Remove the pointer to this W32Process and free the associated memory. 02502 */ 02503 InterlockedCompareExchangePointer(&pW32Process->Process->Win32Process, NULL, pW32Process); 02504 Win32FreePool(pW32Process); 02505 02506 /* 02507 * Release the handle flags lock. 02508 */ 02509 LeaveHandleFlagsCrit(); 02510 } 02511 02512 END_REENTERCRIT(); 02513 }

VOID UserDeleteW32Thread PW32THREAD  pW32Thread  ) 
 

Definition at line 2385 of file queue.c.

References tagTHREADINFO::apEvent, tagQ::cLockCount, tagQ::cThreads, FreeQueue(), NULL, ObDereferenceObject, tagTHREADINFO::pEventQueueServer, tagTHREADINFO::pq, tagTHREADINFO::pqAttach, tagTHREADINFO::pstrAppName, tagTHREADINFO::rpdesk, UnlockDesktop, and VOID().

02386 { 02387 PTHREADINFO pti = (PTHREADINFO)pW32Thread; 02388 02389 BEGIN_REENTERCRIT(); 02390 02391 /* 02392 * Make sure the ref count didn't get bumped up while we were waiting. 02393 */ 02394 if (pW32Thread->RefCount == 0) { 02395 02396 /* 02397 * Events 02398 */ 02399 if (pti->pEventQueueServer != NULL) { 02400 ObDereferenceObject(pti->pEventQueueServer); 02401 } 02402 if (pti->apEvent != NULL) { 02403 UserFreePool(pti->apEvent); 02404 } 02405 02406 /* 02407 * App name. 02408 */ 02409 if (pti->pstrAppName != NULL) { 02410 UserFreePool(pti->pstrAppName); 02411 } 02412 02413 /* 02414 * Unlock the queues and free them if no one is using them 02415 * (the queues were already destroyed in DestroyThreadInfo) 02416 */ 02417 if (pti->pq != NULL) { 02418 02419 UserAssert(pti->pq->cLockCount); 02420 --(pti->pq->cLockCount); 02421 02422 if ((pti->pq->cLockCount == 0) 02423 && (pti->pq->cThreads == 0)) { 02424 FreeQueue(pti->pq); 02425 } 02426 02427 } 02428 /* 02429 * zzzReattachThreads shouldn't call back while using pqAttach 02430 */ 02431 UserAssert(pti->pqAttach == NULL); 02432 #if 0 02433 if (pti->pqAttach != NULL) { 02434 02435 UserAssert(pti->pqAttach->cLockCount); 02436 --(pti->pqAttach->cLockCount); 02437 02438 if ((pti->pqAttach->cLockCount == 0) 02439 && (pti->pqAttach->cThreads == 0)) { 02440 FreeQueue(pti->pqAttach); 02441 } 02442 02443 } 02444 #endif 02445 /* 02446 * Unlock the desktop (pti already unlinked from ptiList) 02447 */ 02448 if (pti->rpdesk != NULL) { 02449 UnlockDesktop(&pti->rpdesk, LDU_PTI_DESK, (ULONG_PTR)pti); 02450 } 02451 02452 /* 02453 * Remove the pointer to this W32Thread and free the associated memory. 02454 */ 02455 InterlockedCompareExchangePointer(&pW32Thread->pEThread->Tcb.Win32Thread, NULL, pW32Thread); 02456 Win32FreePool(pW32Thread); 02457 } 02458 02459 END_REENTERCRIT(); 02460 }

void UserSetConsoleProcessWindowStation DWORD  idProcess,
HWINSTA  hwinsta
 

Definition at line 404 of file queue.c.

References EnterCrit, LeaveCrit, LockProcessByClientId(), NT_SUCCESS, NTSTATUS(), Status, UnlockProcess, and _EPROCESS::Win32WindowStation.

Referenced by xxxConsoleControl().

00408 { 00409 NTSTATUS Status; 00410 PEPROCESS Process; 00411 00412 /* 00413 * First search for this process in our process information list. 00414 */ 00415 LeaveCrit(); 00416 Status = LockProcessByClientId((HANDLE)LongToHandle( idProcess ), &Process); 00417 EnterCrit(); 00418 00419 if (!NT_SUCCESS(Status)) { 00420 RIPMSG2(RIP_WARNING, "UserSetConsoleProcessWindowStation: Failed with Process ID == %X, Status = %x\n", 00421 idProcess, Status); 00422 return; 00423 } 00424 00425 Process->Win32WindowStation = hwinsta; 00426 00427 UnlockProcess(Process); 00428 }

DWORD WaitOnPseudoEvent HANDLE *  phE,
DWORD  dwMilliseconds
 

Definition at line 5671 of file queue.c.

References CheckCritIn, DWORD, ExEventObjectType, FALSE, KernelMode, NT_SUCCESS, NTSTATUS(), NULL, ObReferenceObjectByHandle(), PSEUDO_EVENT_OFF, PSEUDO_EVENT_ON, and Status.

Referenced by xxxWaitForInputIdle().

05674 { 05675 HANDLE hEvent; 05676 NTSTATUS Status; 05677 05678 CheckCritIn(); 05679 if (*phE == PSEUDO_EVENT_OFF) { 05680 if (!NT_SUCCESS(ZwCreateEvent(&hEvent, EVENT_ALL_ACCESS, NULL, 05681 NotificationEvent, FALSE))) { 05682 UserAssert(!"Could not create event on the fly."); 05683 if (dwMilliseconds != INFINITE) { 05684 return STATUS_TIMEOUT; 05685 } else { 05686 return (DWORD)-1; 05687 } 05688 } 05689 Status = ObReferenceObjectByHandle(hEvent, EVENT_ALL_ACCESS, *ExEventObjectType, 05690 KernelMode, phE, NULL); 05691 ZwClose(hEvent); 05692 if (!NT_SUCCESS(Status)) 05693 return (DWORD)-1; 05694 } else if (*phE == PSEUDO_EVENT_ON) { 05695 return STATUS_WAIT_0; 05696 } 05697 return(STATUS_ABANDONED); 05698 }

NTSTATUS xxxConsoleControl IN CONSOLECONTROL  ConsoleControl,
IN PVOID  ConsoleInformation,
IN ULONG  ConsoleInformationLength
 

Definition at line 6445 of file queue.c.

References tagDESKTOP::dwConsoleIMEThreadId, tagDESKTOP::dwConsoleThreadId, DWORD, ExDesktopObjectType, FALSE, gatomConsoleClass, ISCSRSS, LogDesktop, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PtiCurrent, PtiFromThreadId(), SetVDMCursorBounds(), Status, TIF_DONTATTACHQUEUE, tagTHREADINFO::TIF_flags, TRUE, UserMode, UserSetConsoleProcessWindowStation(), xxxbFullscreenSwitch(), xxxSetConsoleCaretInfo(), and xxxUserNotifyConsoleApplication().

Referenced by NtUserConsoleControl().

06449 { 06450 PCONSOLEDESKTOPCONSOLETHREAD pDesktopConsole; 06451 PCONSOLEWINDOWSTATIONPROCESS pConsoleWindowStationInfo; 06452 PDESKTOP pdesk; 06453 DWORD dwThreadIdOld; 06454 NTSTATUS Status = STATUS_SUCCESS; 06455 06456 UNREFERENCED_PARAMETER(ConsoleInformationLength); 06457 UserAssert(ISCSRSS()); 06458 06459 switch (ConsoleControl) { 06460 case ConsoleDesktopConsoleThread: 06461 UserAssert(ConsoleInformationLength == sizeof(CONSOLEDESKTOPCONSOLETHREAD)); 06462 pDesktopConsole = (PCONSOLEDESKTOPCONSOLETHREAD)ConsoleInformation; 06463 06464 Status = ObReferenceObjectByHandle( 06465 pDesktopConsole->hdesk, 06466 0, 06467 *ExDesktopObjectType, 06468 UserMode, 06469 &pdesk, 06470 NULL); 06471 if (!NT_SUCCESS(Status)) 06472 return Status; 06473 06474 LogDesktop(pdesk, LD_REF_FN_CONSOLECONTROL1, TRUE, (ULONG_PTR)PtiCurrent()); 06475 06476 dwThreadIdOld = pdesk->dwConsoleThreadId; 06477 06478 if (pDesktopConsole->dwThreadId != (DWORD)-1) { 06479 pdesk->dwConsoleThreadId = 06480 pDesktopConsole->dwThreadId; 06481 } 06482 06483 pDesktopConsole->dwThreadId = dwThreadIdOld; 06484 LogDesktop(pdesk, LD_DEREF_FN_CONSOLECONTROL1, FALSE, (ULONG_PTR)PtiCurrent()); 06485 ObDereferenceObject(pdesk); 06486 break; 06487 06488 case ConsoleClassAtom: 06489 UserAssert(ConsoleInformationLength == sizeof(ATOM)); 06490 gatomConsoleClass = *(ATOM *)ConsoleInformation; 06491 break; 06492 06493 case ConsoleNotifyConsoleApplication: 06494 /* 06495 * Bug 273518 - joejo 06496 * 06497 * Adding optimization to bug fix 06498 */ 06499 UserAssert(ConsoleInformationLength == sizeof(CONSOLE_PROCESS_INFO)); 06500 xxxUserNotifyConsoleApplication((PCONSOLE_PROCESS_INFO)ConsoleInformation); 06501 break; 06502 06503 case ConsoleSetVDMCursorBounds: 06504 UserAssert((ConsoleInformation == NULL) || 06505 (ConsoleInformationLength == sizeof(RECT))); 06506 SetVDMCursorBounds(ConsoleInformation); 06507 break; 06508 06509 case ConsolePublicPalette: 06510 UserAssert(ConsoleInformationLength == sizeof(HPALETTE)); 06511 GreSetPaletteOwner(*(HPALETTE *)ConsoleInformation, OBJECT_OWNER_PUBLIC); 06512 break; 06513 06514 case ConsoleWindowStationProcess: 06515 UserAssert(ConsoleInformationLength == sizeof(CONSOLEWINDOWSTATIONPROCESS)); 06516 06517 pConsoleWindowStationInfo = (PCONSOLEWINDOWSTATIONPROCESS)ConsoleInformation; 06518 UserSetConsoleProcessWindowStation(pConsoleWindowStationInfo->dwProcessId, 06519 pConsoleWindowStationInfo->hwinsta); 06520 break; 06521 06522 #if defined(FE_IME) 06523 /* 06524 * For console IME issue 06525 * 06526 * Console IME do register thread ID in DESKTOP info. 06527 * So should be per desktop. 06528 */ 06529 case ConsoleRegisterConsoleIME: 06530 { 06531 PCONSOLE_REGISTER_CONSOLEIME RegConIMEInfo; 06532 DWORD dwConsoleIMEThreadIdOld; 06533 06534 UserAssert(ConsoleInformationLength == sizeof(CONSOLE_REGISTER_CONSOLEIME)); 06535 06536 RegConIMEInfo = (PCONSOLE_REGISTER_CONSOLEIME)ConsoleInformation; 06537 RegConIMEInfo->dwConsoleInputThreadId = 0; 06538 06539 Status = ObReferenceObjectByHandle( 06540 RegConIMEInfo->hdesk, 06541 0, 06542 *ExDesktopObjectType, 06543 UserMode, 06544 &pdesk, 06545 NULL); 06546 if (!NT_SUCCESS(Status)) 06547 return Status; 06548 06549 LogDesktop(pdesk, LD_REF_FN_CONSOLECONTROL2, TRUE, (ULONG_PTR)PtiCurrent()); 06550 06551 Status = STATUS_SUCCESS; 06552 if (pdesk->dwConsoleThreadId) 06553 { 06554 /* 06555 * Exists console input thread 06556 */ 06557 RegConIMEInfo->dwConsoleInputThreadId = pdesk->dwConsoleThreadId; 06558 06559 dwConsoleIMEThreadIdOld = pdesk->dwConsoleIMEThreadId; 06560 06561 if (RegConIMEInfo->dwAction != REGCONIME_QUERY) { 06562 PTHREADINFO ptiConsoleIME; 06563 06564 if ((ptiConsoleIME = PtiFromThreadId(RegConIMEInfo->dwThreadId)) != NULL) 06565 { 06566 if ( (RegConIMEInfo->dwAction == REGCONIME_REGISTER) && 06567 !(ptiConsoleIME->TIF_flags & TIF_DONTATTACHQUEUE) ) 06568 { 06569 /* 06570 * Register 06571 */ 06572 ptiConsoleIME->TIF_flags |= TIF_DONTATTACHQUEUE; 06573 pdesk->dwConsoleIMEThreadId = RegConIMEInfo->dwThreadId; 06574 } 06575 else if ( (RegConIMEInfo->dwAction == REGCONIME_UNREGISTER) && 06576 (ptiConsoleIME->TIF_flags & TIF_DONTATTACHQUEUE) ) 06577 { 06578 /* 06579 * Unregister 06580 */ 06581 ptiConsoleIME->TIF_flags &= ~TIF_DONTATTACHQUEUE; 06582 pdesk->dwConsoleIMEThreadId = 0; 06583 } 06584 else if (RegConIMEInfo->dwAction == REGCONIME_TERMINATE) 06585 { 06586 /* 06587 * Terminate console IME (Logoff/Shutdown) 06588 */ 06589 pdesk->dwConsoleIMEThreadId = 0; 06590 } 06591 } 06592 else if (RegConIMEInfo->dwAction == REGCONIME_TERMINATE) 06593 { 06594 /* 06595 * Abnormal end console IME 06596 */ 06597 pdesk->dwConsoleIMEThreadId = 0; 06598 } 06599 else 06600 Status = STATUS_ACCESS_DENIED; 06601 } 06602 RegConIMEInfo->dwThreadId = dwConsoleIMEThreadIdOld; 06603 } 06604 LogDesktop(pdesk, LD_DEREF_FN_CONSOLECONTROL2, FALSE, (ULONG_PTR)PtiCurrent()); 06605 ObDereferenceObject(pdesk); 06606 return Status; 06607 } 06608 break; 06609 #endif 06610 06611 case ConsoleFullscreenSwitch: 06612 UserAssert(ConsoleInformationLength == sizeof(CONSOLE_FULLSCREEN_SWITCH)); 06613 xxxbFullscreenSwitch(((PCONSOLE_FULLSCREEN_SWITCH)ConsoleInformation)->bFullscreenSwitch, 06614 ((PCONSOLE_FULLSCREEN_SWITCH)ConsoleInformation)->hwnd); 06615 break; 06616 06617 case ConsoleSetCaretInfo: 06618 UserAssert(ConsoleInformationLength == sizeof(CONSOLE_CARET_INFO)); 06619 xxxSetConsoleCaretInfo((PCONSOLE_CARET_INFO)ConsoleInformation); 06620 break; 06621 06622 default: 06623 RIPMSG0(RIP_ERROR, "xxxConsoleControl - invalid control class\n"); 06624 UserAssert(FALSE); 06625 return STATUS_INVALID_INFO_CLASS; 06626 } 06627 return STATUS_SUCCESS; 06628 }

NTSTATUS xxxCreateThreadInfo PETHREAD  pEThread,
BOOL  IsSystemThread
 

Definition at line 1501 of file queue.c.

References AllocQueue(), ARRAY_SIZE, BEGINATOMICCHECK, BOOL, tagUSERSTARTUPINFO::cb, CheckCritIn, _CLIENTINFO::CI_flags, CI_REGISTERCLASSES, _ETHREAD::Cid, CLIENTINFO, ClientThreadSetup(), _CLIENTINFO::CodePage, tagKL::CodePage, CreateInputContext(), tagPROCESSINFO::cThreads, tagQ::cThreads, tagTHREADINFO::cti, DeferWinEventNotify, DF_DESTROYED, tagDESKTOP::dwDTFlags, tagTHREADINFO::dwExpWinVer, _CLIENTINFO::dwExpWinVer, tagUSERSTARTUPINFO::dwFlags, tagPROCESSINFO::dwHotkey, DWORD, _CLIENTINFO::dwTIFlags, tagUSERSTARTUPINFO::dwX, tagUSERSTARTUPINFO::dwXSize, tagUSERSTARTUPINFO::dwY, tagUSERSTARTUPINFO::dwYSize, ENDATOMICCHECK, EndDeferWinEventNotifyWithoutProcessing, EnterCrit, ExDesktopObjectType, ExEventObjectType, ExRaiseHardError(), FALSE, gbCleanedUpResources, gdwGuiThreads, GetJournallingQueue(), glinp, gpepCSRSS, gpidLogon, gppiScreenSaver, gpsi, gptiForeground, gptSSCursor, grpdeskRitInput, grpWinStaList, gspklBaseLayout, tagPROCESSINFO::hdeskStartup, tagTHREADINFO::hEventQueueClient, _CLIENTINFO::hKL, tagKL::hkl, tagPROCESSINFO::hMonitor, _EPROCESS::InheritedFromUniqueProcessId, IS_IME_ENABLED, IsWinEventNotifyDeferredOK, KernelMode, L, LeaveCrit, Lock, LockDesktop, LW_RegisterWindows(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), ParseReserved(), tagTHREADINFO::pClientInfo, tagTHREADINFO::pcti, tagTHREADINFO::pDeskInfo, tagDESKTOP::pDeskInfo, _EPROCESS::Peb, tagTHREADINFO::pEventQueueServer, PlayEventSound(), tagTHREADINFO::ppi, PpiCurrent, tagTHREADINFO::pq, ProtectHandle(), tagQ::ptiKeyboard, tagLASTINPUT::ptiLastWoken, tagPROCESSINFO::ptiList, tagQ::ptiMouse, tagTHREADINFO::ptiSibling, PUSERSTARTUPINFO, tagTHREADINFO::rpdesk, tagPROCESSINFO::rpdeskStartup, tagPROCESSINFO::rpwinsta, RtlGetExpWinVer(), _EPROCESS::SectionBaseAddress, SET_TIME_LAST_READ, SetAppCompatFlags(), SetForegroundPriority(), tagTHREADINFO::spklActive, Status, SYSCUR, _ETHREAD::Tcb, ThreadLockDesktop, _ETHREAD::ThreadsProcess, ThreadUnlockDesktop, TIF_ALLOWFOREGROUNDACTIVATE, TIF_CSRSSTHREAD, TIF_DISABLEIME, TIF_DONTATTACHQUEUE, tagTHREADINFO::TIF_flags, TIF_GUITHREADINITIALIZED, TIF_RESTRICTED, TIF_SYSTEMTHREAD, TIF_WAITFORINPUTIDLE, TIF_WOW64, TRUE, _EPROCESS::UniqueProcessId, USER_SOUND_OPEN, UserMode, tagPROCESSINFO::usi, ValidateHmonitor(), ValidateProcessSessionId, VER40, _EPROCESS::Win32Process, _KTHREAD::Win32Thread, tagUSERSTARTUPINFO::wShowWindow, xxxDestroyThreadInfo(), xxxResolveDesktop(), xxxSetProcessWindowStation(), zzzCalcStartCursorHide(), and zzzSetDesktop().

Referenced by InitSystemThread(), UserInitialize(), and UserThreadCallout().

01504 { 01505 DWORD dwTIFlags = 0; 01506 PPROCESSINFO ppi; 01507 PTHREADINFO ptiCurrent; 01508 PEPROCESS pEProcess = pEThread->ThreadsProcess; 01509 PUSERSTARTUPINFO pusi; 01510 PRTL_USER_PROCESS_PARAMETERS ProcessParams; 01511 PDESKTOP pdesk = NULL; 01512 HDESK hdesk = NULL; 01513 HWINSTA hwinsta; 01514 PQ pq; 01515 NTSTATUS Status; 01516 BOOL fFirstThread; 01517 PTEB pteb = NtCurrentTeb(); 01518 TL tlpdesk; 01519 01520 CheckCritIn(); 01521 UserAssert(IsWinEventNotifyDeferredOK()); 01522 01523 ValidateProcessSessionId(pEProcess); 01524 01525 /* 01526 * If CleanupResources was called for the last GUI thread then 01527 * we should not allow any more GUI threads 01528 */ 01529 if (gbCleanedUpResources) { 01530 RIPMSG0(RIP_ERROR, "No more GUI threads should be created"); 01531 return STATUS_PROCESS_IS_TERMINATING; 01532 } 01533 01534 /* 01535 * Increment the number of GUI threads in the session 01536 */ 01537 gdwGuiThreads++; 01538 01539 /* 01540 * Although all threads now have a ETHREAD structure, server-side 01541 * threads (RIT, Console, etc) don't have a client-server eventpair 01542 * handle. We use this to distinguish the two cases. 01543 */ 01544 01545 if (IsSystemThread) { 01546 dwTIFlags = TIF_SYSTEMTHREAD | TIF_DONTATTACHQUEUE | TIF_DISABLEIME; 01547 } 01548 01549 if (!(dwTIFlags & TIF_SYSTEMTHREAD) && pEProcess == gpepCSRSS) { 01550 dwTIFlags = TIF_CSRSSTHREAD | TIF_DONTATTACHQUEUE | TIF_DISABLEIME; 01551 } 01552 01553 ProcessParams = (pEProcess->Peb ? pEProcess->Peb->ProcessParameters : NULL); 01554 01555 /* 01556 * Locate the processinfo structure for the new thread. 01557 */ 01558 ppi = PpiCurrent(); 01559 01560 #if defined(_WIN64) 01561 /* 01562 * If the process is marked as an emulated 32bit app thus, 01563 * mark the thread as an emulated 32bit thread. 01564 * This is to be consistent with the way WOW16 marks threads. 01565 */ 01566 if (ppi->W32PF_Flags & W32PF_WOW64) { 01567 dwTIFlags |= TIF_WOW64; 01568 } 01569 #endif //defined(_WIN64) 01570 01571 /* 01572 * For Winlogon, only the first thread can have IME processing. 01573 */ 01574 if (gpidLogon == pEThread->Cid.UniqueProcess) { 01575 if (ppi->ptiList != NULL) { 01576 dwTIFlags |= TIF_DISABLEIME; 01577 RIPMSG1(RIP_VERBOSE, "WinLogon, second or other thread. pti=%x", pEThread->Tcb.Win32Thread); 01578 } 01579 } 01580 01581 /* 01582 * Allocate the thread-info structure. If it's a SYSTEMTHREAD, then 01583 * make sure we have enough space for the (pwinsta) pointer. This 01584 * is referenced in (paint.c: DoPaint) to assure desktop/input can 01585 * have a winsta to view. 01586 */ 01587 ptiCurrent = (PTHREADINFO)pEThread->Tcb.Win32Thread; 01588 01589 ptiCurrent->TIF_flags = dwTIFlags; 01590 Lock(&ptiCurrent->spklActive, gspklBaseLayout); 01591 ptiCurrent->pcti = &(ptiCurrent->cti); 01592 01593 /* 01594 * Check if no IME processing for all threads 01595 * in the same process. 01596 */ 01597 if (ppi->W32PF_Flags & W32PF_DISABLEIME) 01598 ptiCurrent->TIF_flags |= TIF_DISABLEIME; 01599 01600 /* 01601 * Hook up this queue to this process info structure, increment 01602 * the count of threads using this process info structure. Set up 01603 * the ppi before calling SetForegroundPriority(). 01604 */ 01605 UserAssert(ppi != NULL); 01606 01607 ptiCurrent->ppi = ppi; 01608 ptiCurrent->ptiSibling = ppi->ptiList; 01609 ppi->ptiList = ptiCurrent; 01610 ppi->cThreads++; 01611 01612 01613 if (pteb != NULL) 01614 pteb->Win32ThreadInfo = ptiCurrent; 01615 01616 /* 01617 * Point to the client info. 01618 */ 01619 if (dwTIFlags & TIF_SYSTEMTHREAD) { 01620 ptiCurrent->pClientInfo = UserAllocPoolWithQuota(sizeof(CLIENTINFO), 01621 TAG_CLIENTTHREADINFO); 01622 if (ptiCurrent->pClientInfo == NULL) { 01623 Status = STATUS_NO_MEMORY; 01624 goto CreateThreadInfoFailed; 01625 } 01626 } else { 01627 /* 01628 * If this is not a system thread then grab the user mode client info 01629 * elsewhere we use the GetClientInfo macro which looks here 01630 */ 01631 UserAssert(NtCurrentTeb() != NULL); 01632 ptiCurrent->pClientInfo = ((PCLIENTINFO)((NtCurrentTeb())->Win32ClientInfo)); 01633 01634 /* 01635 * set the SECURE flag in the thread flags if this is a secure process 01636 */ 01637 if (((PW32PROCESS)ppi)->W32PF_Flags & W32PF_RESTRICTED) { 01638 ptiCurrent->TIF_flags |= TIF_RESTRICTED; 01639 } 01640 } 01641 01642 01643 /* 01644 * Create the input event. 01645 */ 01646 Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, 01647 EVENT_ALL_ACCESS, 01648 NULL, 01649 SynchronizationEvent, 01650 FALSE); 01651 01652 if (NT_SUCCESS(Status)) { 01653 Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 01654 EVENT_ALL_ACCESS, 01655 *ExEventObjectType, 01656 UserMode, 01657 &ptiCurrent->pEventQueueServer, 01658 NULL); 01659 if (NT_SUCCESS(Status)) { 01660 Status = ProtectHandle(ptiCurrent->hEventQueueClient, TRUE); 01661 } else if (Status == STATUS_INVALID_HANDLE) { 01662 ptiCurrent->hEventQueueClient = NULL; 01663 } 01664 } 01665 if (!NT_SUCCESS(Status)) { 01666 goto CreateThreadInfoFailed; 01667 } 01668 01669 /* 01670 * Mark the process as having threads that need cleanup. See 01671 * DestroyProcessesObjects(). 01672 */ 01673 fFirstThread = !(ppi->W32PF_Flags & W32PF_THREADCONNECTED); 01674 ppi->W32PF_Flags |= W32PF_THREADCONNECTED; 01675 01676 /* 01677 * If we haven't copied over our startup info yet, do it now. 01678 * Don't bother copying the info if we aren't going to use it. 01679 */ 01680 if (ProcessParams) { 01681 01682 pusi = &ppi->usi; 01683 01684 if ((pusi->cb == 0) && (ProcessParams->WindowFlags != 0)) { 01685 pusi->cb = sizeof(USERSTARTUPINFO); 01686 pusi->dwX = ProcessParams->StartingX; 01687 pusi->dwY = ProcessParams->StartingY; 01688 pusi->dwXSize = ProcessParams->CountX; 01689 pusi->dwYSize = ProcessParams->CountY; 01690 pusi->dwFlags = ProcessParams->WindowFlags; 01691 pusi->wShowWindow = (WORD)ProcessParams->ShowWindowFlags; 01692 } 01693 01694 if (fFirstThread) { 01695 01696 /* 01697 * Set up the hot key, if there is one. 01698 * 01699 * If the STARTF_USEHOTKEY flag is given in the startup info, then 01700 * the hStdInput is the hotkey (new from Chicago). Otherwise, parse 01701 * it out in string format from the lpReserved string. 01702 */ 01703 if (ProcessParams->WindowFlags & STARTF_USEHOTKEY) { 01704 ppi->dwHotkey = HandleToUlong(ProcessParams->StandardInput); 01705 } else { 01706 ppi->dwHotkey = ParseReserved(ProcessParams->ShellInfo.Buffer, 01707 L"hotkey."); 01708 } 01709 01710 /* 01711 * Copy the monitor handle, if there is one. 01712 */ 01713 UserAssert(!ppi->hMonitor); 01714 if (ProcessParams->WindowFlags & STARTF_HASSHELLDATA) { 01715 HMONITOR hMonitor; 01716 01717 hMonitor = (HMONITOR)(ProcessParams->StandardOutput); 01718 if (ValidateHmonitor(hMonitor)) { 01719 ppi->hMonitor = hMonitor; 01720 } 01721 } 01722 } 01723 } 01724 01725 /* 01726 * Open the windowstation and desktop. If this is a system 01727 * thread only use the desktop that might be stored in the teb. 01728 */ 01729 UserAssert(ptiCurrent->rpdesk == NULL); 01730 if (!(ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) && 01731 grpWinStaList) { 01732 01733 BOOL bShutDown = FALSE; 01734 01735 hdesk = xxxResolveDesktop( 01736 NtCurrentProcess(), 01737 &ProcessParams->DesktopInfo, 01738 &hwinsta, (ProcessParams->WindowFlags & STARTF_DESKTOPINHERIT), 01739 &bShutDown); 01740 01741 if (hdesk == NULL) { 01742 01743 if (bShutDown) { 01744 /* 01745 * Trying to create a new process during logoff 01746 */ 01747 ULONG_PTR adwParameters[5] = {0, 0, 0, 0, MB_DEFAULT_DESKTOP_ONLY}; 01748 ULONG ErrorResponse; 01749 01750 LeaveCrit(); 01751 01752 ExRaiseHardError((NTSTATUS)STATUS_DLL_INIT_FAILED_LOGOFF, 01753 ARRAY_SIZE(adwParameters), 01754 0, 01755 adwParameters, 01756 OptionOkNoWait, 01757 &ErrorResponse); 01758 01759 ZwTerminateProcess(NtCurrentProcess(), STATUS_DLL_INIT_FAILED); 01760 01761 EnterCrit(); 01762 } 01763 01764 Status = STATUS_DLL_INIT_FAILED; 01765 goto CreateThreadInfoFailed; 01766 01767 } else { 01768 01769 xxxSetProcessWindowStation(hwinsta, KernelMode); 01770 01771 /* 01772 * Reference the desktop handle 01773 */ 01774 Status = ObReferenceObjectByHandle( 01775 hdesk, 01776 0, 01777 *ExDesktopObjectType, 01778 KernelMode, 01779 &pdesk, 01780 NULL); 01781 01782 if (!NT_SUCCESS(Status)) { 01783 UserAssert(pdesk == NULL); 01784 goto CreateThreadInfoFailed; 01785 } 01786 01787 ThreadLockDesktop(ptiCurrent, pdesk, &tlpdesk, LDLT_FN_CREATETHREADINFO); 01788 01789 ObDereferenceObject(pdesk); 01790 01791 /* 01792 * The first desktop is the default for all succeeding threads. 01793 */ 01794 if ((ppi->hdeskStartup == NULL) && 01795 (pEProcess->UniqueProcessId != gpidLogon)) { 01796 01797 LockDesktop(&ppi->rpdeskStartup, pdesk, LDL_PPI_DESKSTARTUP2, (ULONG_PTR)ppi); 01798 ppi->hdeskStartup = hdesk; 01799 } 01800 } 01801 } 01802 01803 /* 01804 * Remember dwExpWinVer. This is used to return GetAppVer() (and 01805 * GetExpWinVer(NULL). 01806 */ 01807 if (pEProcess->Peb != NULL) 01808 ptiCurrent->dwExpWinVer = RtlGetExpWinVer(pEProcess->SectionBaseAddress); 01809 else 01810 ptiCurrent->dwExpWinVer = VER40; 01811 01812 ptiCurrent->pClientInfo->dwExpWinVer = ptiCurrent->dwExpWinVer; 01813 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; 01814 01815 if (ptiCurrent->spklActive) { 01816 ptiCurrent->pClientInfo->CodePage = ptiCurrent->spklActive->CodePage; 01817 ptiCurrent->pClientInfo->hKL = ptiCurrent->spklActive->hkl; 01818 } else { 01819 ptiCurrent->pClientInfo->CodePage = CP_ACP; 01820 ptiCurrent->pClientInfo->hKL = 0; 01821 } 01822 01823 /* 01824 * Set the desktop even if it is NULL to ensure that ptiCurrent->pDeskInfo 01825 * is set. 01826 * NOTE: This adds the pti to the desktop's PtiList, but we don't yet have 01827 * a pti->pq. zzzRecalcThreadAttachment loops through this PtiList expects 01828 * a pq, so we must not leave the critsect until we have a queue. 01829 * zzzSetDesktop only zzz leaves the critsect if there is a pti->pq, so we 01830 * can BEGINATOMICCHECK to ensure this, and make sure we allocate the queue 01831 * before we leave the critical section. 01832 */ 01833 BEGINATOMICCHECK(); 01834 zzzSetDesktop(ptiCurrent, pdesk, hdesk); 01835 ENDATOMICCHECK(); 01836 01837 /* 01838 * If we have a desktop and are journalling on that desktop, use 01839 * the journal queue, otherwise create a new queue. 01840 */ 01841 if (pdesk == grpdeskRitInput) { 01842 PQ pq; 01843 UserAssert((pdesk == NULL) || (ptiCurrent->pDeskInfo == pdesk->pDeskInfo)); 01844 UserAssert(ptiCurrent->rpdesk == pdesk); 01845 pq = GetJournallingQueue(ptiCurrent); 01846 if (pq != NULL) { 01847 ptiCurrent->pq = pq; 01848 pq->cThreads++; 01849 } 01850 } 01851 01852 /* 01853 * If not journalling, give this thread its own queue 01854 */ 01855 if (ptiCurrent->pq == NULL) { 01856 if ((pq = AllocQueue(NULL, NULL)) == NULL) { 01857 Status = STATUS_NO_MEMORY; 01858 goto CreateThreadInfoFailed; 01859 } 01860 /* 01861 * Attach the Q to the THREADINFO. 01862 */ 01863 ptiCurrent->pq = pq; 01864 pq->ptiMouse = pq->ptiKeyboard = ptiCurrent; 01865 pq->cThreads++; 01866 } 01867 01868 /* 01869 * Remember that this is a screen saver. That way we can set its 01870 * priority appropriately when it is idle or when it needs to go 01871 * away. At first we set it to normal priority, then we set the 01872 * TIF_IDLESCREENSAVER bit so that when it activates it will get 01873 * lowered in priority. 01874 */ 01875 if (ProcessParams && ProcessParams->WindowFlags & STARTF_SCREENSAVER) { 01876 01877 if (fFirstThread) { 01878 UserAssert(gppiScreenSaver == NULL); 01879 01880 /* 01881 * Make sure the parent's process is WinLogon, since only WinLogon is allowed to 01882 * use the STARTF_SCREENSAVER flag. 01883 */ 01884 if (gpidLogon == 0 || pEProcess->InheritedFromUniqueProcessId != gpidLogon) { 01885 RIPMSG0(RIP_WARNING,"Only the Logon process can launch a screen saver."); 01886 ProcessParams->WindowFlags &= ~STARTF_SCREENSAVER; 01887 goto NotAScreenSaver; 01888 } 01889 01890 gppiScreenSaver = ppi; 01891 gptSSCursor = gpsi->ptCursor; 01892 ppi->W32PF_Flags |= W32PF_SCREENSAVER; 01893 } 01894 #if DBG 01895 else { 01896 UserAssert(ppi->W32PF_Flags & W32PF_SCREENSAVER); 01897 } 01898 #endif 01899 01900 SetForegroundPriority(ptiCurrent, TRUE); 01901 01902 if (fFirstThread) { 01903 ppi->W32PF_Flags |= W32PF_IDLESCREENSAVER; 01904 } 01905 01906 /* 01907 * Screen saver doesn't need any IME processing. 01908 */ 01909 ptiCurrent->TIF_flags |= TIF_DISABLEIME; 01910 } 01911 01912 NotAScreenSaver: 01913 01914 /* 01915 * Do special processing for the first thread of a process. 01916 */ 01917 if (!(ptiCurrent->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD))) { 01918 01919 /* 01920 * I changed the code a while ago to unregister classes when the last 01921 * GUI thread is destroyed. Simply, there was too much stuff getting 01922 * unlocked and destroyed to guarantee that it would work on a non-GUI 01923 * thread. So if a process destroys its last GUI thread and then makes 01924 * a thread GUI later, we need to re-register the classes. 01925 */ 01926 01927 if (!(ppi->W32PF_Flags & W32PF_CLASSESREGISTERED)) { 01928 if (!LW_RegisterWindows(FALSE)) { 01929 RIPMSG0(RIP_WARNING, "xxxCreateThreadInfo: LW_RegisterWindows failed"); 01930 Status = STATUS_UNSUCCESSFUL; 01931 goto CreateThreadInfoFailed; 01932 } 01933 ppi->W32PF_Flags |= W32PF_CLASSESREGISTERED; 01934 if (ptiCurrent->pClientInfo) { 01935 ptiCurrent->pClientInfo->CI_flags |= CI_REGISTERCLASSES; 01936 } 01937 } 01938 01939 if (fFirstThread) { 01940 01941 /* 01942 * If this is an application starting (ie. not some thread of 01943 * the server context), enable the app-starting cursor. 01944 */ 01945 DeferWinEventNotify(); 01946 zzzCalcStartCursorHide((PW32PROCESS)pEProcess->Win32Process, 5000); 01947 EndDeferWinEventNotifyWithoutProcessing(); 01948 01949 /* 01950 * Open the windowstation 01951 */ 01952 if (grpWinStaList && ppi->rpwinsta == NULL) { 01953 RIPERR0(ERROR_CAN_NOT_COMPLETE, RIP_WARNING, "System is not initialized\n"); 01954 Status = STATUS_UNSUCCESSFUL; 01955 goto CreateThreadInfoFailed; 01956 } 01957 } 01958 } else { 01959 01960 /* 01961 * Don't register system windows until cursors and icons 01962 * have been loaded. 01963 */ 01964 if ((SYSCUR(ARROW) != NULL) && 01965 !(ppi->W32PF_Flags & W32PF_CLASSESREGISTERED)) { 01966 01967 ppi->W32PF_Flags |= W32PF_CLASSESREGISTERED; 01968 if (!LW_RegisterWindows(ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD)) { 01969 RIPMSG0(RIP_WARNING, "xxxCreateThreadInfo: LW_RegisterWindows failed"); 01970 Status = STATUS_UNSUCCESSFUL; 01971 goto CreateThreadInfoFailed; 01972 } 01973 } 01974 } 01975 01976 01977 /* 01978 * Initialize hung timer value 01979 */ 01980 01981 SET_TIME_LAST_READ(ptiCurrent); 01982 01983 /* 01984 * If someone is waiting on this process propagate that info into 01985 * the thread info 01986 */ 01987 if (ppi->W32PF_Flags & W32PF_WAITFORINPUTIDLE) 01988 ptiCurrent->TIF_flags |= TIF_WAITFORINPUTIDLE; 01989 01990 /* 01991 * Mark the thread as initialized. 01992 */ 01993 ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED; 01994 01995 /* 01996 * Allow the thread to come to foreground when it is created 01997 * if the current process is the foreground process or the last input owner 01998 * This Flag is a hack to fix Bug 28502. When we click on 01999 * "Map Network Drive" button on the toolbar, the explorer (Bobday) 02000 * creates another thread to create the dialog box. This will create 02001 * the dialog in the background. We are adding this fix at the request 02002 * of the Shell team so that this dialog comes up as foreground. 02003 * 02004 * If the process already has the foreground right, we don't give it 02005 * to this thread (it doesn't need it). We do this to narrow the number 02006 * of ways this process can force the foreground. 02007 * Also, if the process is starting, it already has the right unless 02008 * the user has canceled it -- in which case we don't want to give it back. 02009 * 02010 */ 02011 if (!(ppi->W32PF_Flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING))) { 02012 if (((gptiForeground != NULL) && (ppi == gptiForeground->ppi)) 02013 || ((glinp.ptiLastWoken != NULL) && (ppi == glinp.ptiLastWoken->ppi))) { 02014 02015 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 02016 TAGMSG1(DBGTAG_FOREGROUND, "xxxCreateThreadInfo set TIF %#p", ptiCurrent); 02017 } 02018 } 02019 02020 if (IS_IME_ENABLED()) { 02021 /* 02022 * Create per-thread default input context 02023 */ 02024 CreateInputContext(0); 02025 } 02026 02027 /* 02028 * Call back to the client to finish initialization. 02029 */ 02030 if (!(dwTIFlags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD))) { 02031 02032 if (SetAppCompatFlags(ptiCurrent)) { 02033 /* 02034 * Flag this process as a setup app. 02035 */ 02036 ppi->W32PF_Flags |= W32PF_SETUPAPP; 02037 } 02038 02039 Status = ClientThreadSetup(); 02040 if (!NT_SUCCESS(Status)) { 02041 RIPMSG1(RIP_WARNING, "ClientThreadSetup failed with NTSTATUS %lx", Status); 02042 goto CreateThreadInfoFailed; 02043 } 02044 } 02045 02046 if ((NT_SUCCESS(Status) && fFirstThread) && 02047 !(ppi->W32PF_Flags & W32PF_CONSOLEAPPLICATION)) { 02048 02049 /* 02050 * Don't play the sound for console processes 02051 * since we will play it when the console window 02052 * will be created 02053 */ 02054 PlayEventSound(USER_SOUND_OPEN); 02055 } 02056 02057 /* 02058 * Release desktop. 02059 * Some other thread might have been waiting to destroy this desktop 02060 * when xxxResolveDestktop got a handle to it. So let's double 02061 * check this now that we have called back several times after getting 02062 * the handle back. 02063 */ 02064 if (pdesk != NULL) { 02065 if (pdesk->dwDTFlags & DF_DESTROYED) { 02066 RIPMSG1(RIP_WARNING, "xxxCreateThreadInfo: pdesk destroyed:%#p", pdesk); 02067 Status = STATUS_UNSUCCESSFUL; 02068 goto CreateThreadInfoFailed; 02069 } 02070 ThreadUnlockDesktop(ptiCurrent, &tlpdesk, LDUT_FN_CREATETHREADINFO1); 02071 } 02072 02073 // We must return a success here. If the failure status is returned 02074 // W32Thread will be freed without us going thru xxxDestroyProcessInfo. 02075 UserAssert(NT_SUCCESS(Status)); 02076 02077 return Status; 02078 02079 CreateThreadInfoFailed: 02080 02081 RIPMSG2(RIP_WARNING, "xxxCreateThreadInfo: failed: pti %#p pdesk %#p", 02082 ptiCurrent, pdesk); 02083 02084 if (pdesk != NULL) { 02085 ThreadUnlockDesktop(ptiCurrent, &tlpdesk, LDUT_FN_CREATETHREADINFO2); 02086 } 02087 xxxDestroyThreadInfo(); 02088 return Status; 02089 }

VOID xxxDestroyThreadInfo VOID   ) 
 

Definition at line 2552 of file queue.c.

References _GetProcessWindowStation(), _PostMessage(), _WOWCleanup(), tagTHREADINFO::cEnterCount, CleanupResources(), tagQ::cLockCount, tagQ::cThreads, tagPROCESSINFO::cThreads, tagTHREADINFO::cti, DesktopFree, DestroyProcessesClasses(), DestroyProcessesObjects(), DestroyTask(), DestroyThreadsHotKeys(), DestroyThreadsMessages(), DestroyThreadsObjects(), DestroyThreadsTimers(), DTM_SETUPAPPRAN, tagMENUSTATE::dwLockCount, FALSE, tagPOPUPMENU::fDestroyed, tagMENUSTATE::fInsideMenuLoop, tagPOPUPMENU::fIsMenuBar, FLastGuiThread(), tagMENUSTATE::fModelessMenu, FreeHwndList(), FreeMessageList(), FreeThreadsWindowHooks(), FreeThreadsWinEvents(), FWINABLE, gbExitInProgress, gdwGuiThreads, GETDESKINFO, GETPTI, gHardErrorHandler, glinp, gpai, gpbwlList, gpdeskRecalcQueueAttach, gppiFullscreen, gptiBlockInput, gptiForeground, gptiShutdownNotify, gptiTasklist, gspwndInternalCapture, guiActivateShellWindow, tagTHREADINFO::hEventQueueClient, tagTDB::hTaskWow, tagQ::iCursorLevel, tagTHREADINFO::iCursorLevel, IsWinEventNotifyDeferredOK, KernelMode, KeSetKernelStackSwapEnable(), LockDesktop, MarkThreadsObjects(), tagTHREADINFO::mlPost, NULL, tagATTACHINFO::paiNext, PatchThreadWindows(), tagBWL::pbwlNext, tagTHREADINFO::pClientInfo, tagTHREADINFO::pcti, tagDESKTOP::pDeskInfo, tagMENUSTATE::pGlobalPopupMenu, tagTHREADINFO::pMenuState, tagMENUSTATE::pmnsPrev, tagTHREADINFO::pmsd, tagTHREADINFO::ppi, PpiCurrent, tagTHREADINFO::pq, tagTHREADINFO::pqAttach, ProtectHandle(), tagTHREADINFO::pSBTrack, tagTHREADINFO::psiiList, tagTHREADINFO::ptdb, tagHARDERRORHANDLER::pti, tagWINDOWSTATION::ptiClipLock, PtiCurrent, tagWINDOWSTATION::ptiDrawingClipboard, tagLASTINPUT::ptiLastWoken, tagTHREADINFO::PtiLink, tagPROCESSINFO::ptiList, tagPROCESSINFO::ptiMainThread, tagMENUSTATE::ptiMenuStateOwner, tagBWL::ptiOwner, tagTHREADINFO::ptiSibling, QF_CAPTURELOCKED, tagQ::QF_flags, tagTHREADINFO::rpdesk, SendMsgCleanup(), SetForegroundThread(), tagTHREADINFO::spDefaultImc, tagTHREADINFO::spklActive, _MOVESIZEDATA::spwnd, tagDESKTOPINFO::spwnd, tagDESKTOP::spwndMenu, tagPOPUPMENU::spwndNotify, tagDESKTOPINFO::spwndProgman, tagSBTRACK::spwndSB, tagSBTRACK::spwndSBNotify, tagDESKTOPINFO::spwndShell, tagSBTRACK::spwndTrack, ThreadLock, ThreadUnlock, TIF_16BIT, TIF_DONTATTACHQUEUE, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, TIF_PALETTEAWARE, TIF_SYSTEMTHREAD, TRUE, Unlock, UnlockDesktop, VOID(), WEF_ASYNC, xxxCancelTrackingForThread(), xxxCloseClipboard(), xxxDestroyThreadDDEObject(), xxxEndMenuLoop(), xxxFlushPalette(), xxxMNCloseHierarchy(), xxxMNEndMenuState(), xxxUserChangeDisplaySettings(), xxxWindowEvent(), zzzDestroyQueue(), and zzzSetFMouseMoved().

Referenced by UserThreadCallout(), and xxxCreateThreadInfo().

02553 { 02554 PTHREADINFO ptiCurrent; 02555 PTHREADINFO *ppti; 02556 02557 ptiCurrent = PtiCurrent(); 02558 UserAssert (ptiCurrent != NULL); 02559 UserAssert(IsWinEventNotifyDeferredOK()); 02560 02561 /* 02562 * If this thread is blocking input, stop it 02563 */ 02564 if (gptiBlockInput == ptiCurrent) { 02565 gptiBlockInput = NULL; 02566 } 02567 02568 /* 02569 * Don't mess with this ptiCurrent anymore. 02570 */ 02571 ptiCurrent->TIF_flags |= (TIF_DONTATTACHQUEUE | TIF_INCLEANUP); 02572 02573 /* 02574 * First do any preparation work: windows need to be "patched" so that 02575 * their window procs point to server only windowprocs, for example. 02576 */ 02577 PatchThreadWindows(ptiCurrent); 02578 02579 /* 02580 * If this thread terminated abnormally and was tracking tell 02581 * GDI to hide the trackrect. 02582 */ 02583 if (ptiCurrent->pmsd != NULL) { 02584 xxxCancelTrackingForThread(ptiCurrent); 02585 } 02586 02587 /* 02588 * Unlock the pmsd window. 02589 */ 02590 if (ptiCurrent->pmsd != NULL) { 02591 Unlock(&ptiCurrent->pmsd->spwnd); 02592 UserFreePool(ptiCurrent->pmsd); 02593 ptiCurrent->pmsd = NULL; 02594 } 02595 02596 /* 02597 * Free the clipboard if owned by this thread 02598 */ 02599 { 02600 PWINDOWSTATION pwinsta; 02601 pwinsta = _GetProcessWindowStation(NULL); 02602 if (pwinsta != NULL) { 02603 if (pwinsta->ptiClipLock == ptiCurrent) { 02604 xxxCloseClipboard(pwinsta); 02605 } 02606 if (pwinsta->ptiDrawingClipboard == ptiCurrent) { 02607 pwinsta->ptiDrawingClipboard = NULL; 02608 } 02609 } 02610 } 02611 02612 /* 02613 * Unlock all the objects stored in the menustate structure 02614 */ 02615 while (ptiCurrent->pMenuState != NULL) { 02616 PMENUSTATE pMenuState; 02617 PPOPUPMENU ppopupmenuRoot; 02618 02619 pMenuState = ptiCurrent->pMenuState; 02620 ppopupmenuRoot = pMenuState->pGlobalPopupMenu; 02621 02622 /* 02623 * If menu mode was running on this thread 02624 */ 02625 if (ptiCurrent == pMenuState->ptiMenuStateOwner) { 02626 /* 02627 * The menu's going away, so anyone who's locked it 02628 * is SOL anyway. Bug #375467. 02629 */ 02630 pMenuState->dwLockCount = 0; 02631 02632 /* 02633 * Close this menu. 02634 */ 02635 if (pMenuState->fModelessMenu) { 02636 xxxEndMenuLoop(pMenuState, ppopupmenuRoot); 02637 xxxMNEndMenuState(TRUE); 02638 } else { 02639 pMenuState->fInsideMenuLoop = FALSE; 02640 ptiCurrent->pq->QF_flags &= ~QF_CAPTURELOCKED; 02641 xxxMNCloseHierarchy(ppopupmenuRoot, pMenuState); 02642 xxxMNEndMenuState(ppopupmenuRoot->fIsMenuBar || ppopupmenuRoot->fDestroyed); 02643 } 02644 } else { 02645 /* 02646 * Menu mode is running on another thread. This thread 02647 * must own spwndNotify which is going away soon. 02648 * When spwndNotify is destroyed, we will clean up pMenuState 02649 * from this pti. So do nothing now as we'll need this 02650 * pMenuState at that time. 02651 */ 02652 UserAssert((ppopupmenuRoot->spwndNotify != NULL) 02653 && (GETPTI(ppopupmenuRoot->spwndNotify) == ptiCurrent)); 02654 02655 /* 02656 * Nested menus are not supposed to involve multiple threads 02657 */ 02658 UserAssert(pMenuState->pmnsPrev == NULL); 02659 break; 02660 } 02661 02662 } /* while (ptiCurrent->pMenuState != NULL) */ 02663 02664 #if DBG 02665 /* 02666 * This thread must not be using the desktop menu 02667 */ 02668 if ((ptiCurrent->rpdesk != NULL) && (ptiCurrent->rpdesk->spwndMenu != NULL)) { 02669 UserAssert(ptiCurrent != GETPTI(ptiCurrent->rpdesk->spwndMenu)); 02670 } 02671 #endif 02672 02673 /* 02674 * Unlock all the objects stored in the sbstate structure. 02675 */ 02676 if (ptiCurrent->pSBTrack) { 02677 Unlock(&ptiCurrent->pSBTrack->spwndSB); 02678 Unlock(&ptiCurrent->pSBTrack->spwndSBNotify); 02679 Unlock(&ptiCurrent->pSBTrack->spwndTrack); 02680 UserFreePool(ptiCurrent->pSBTrack); 02681 ptiCurrent->pSBTrack = NULL; 02682 } 02683 02684 /* 02685 * If this is the main input thread of this application, zero out 02686 * that field. 02687 */ 02688 if (ptiCurrent->ppi != NULL && ptiCurrent->ppi->ptiMainThread == ptiCurrent) 02689 ptiCurrent->ppi->ptiMainThread = NULL; 02690 02691 while (ptiCurrent->psiiList != NULL) { 02692 xxxDestroyThreadDDEObject(ptiCurrent, ptiCurrent->psiiList); 02693 } 02694 02695 if (ptiCurrent->TIF_flags & TIF_PALETTEAWARE) { 02696 PWND pwnd; 02697 TL tlpwnd; 02698 02699 UserAssert(ptiCurrent->rpdesk != NULL); 02700 02701 pwnd = ptiCurrent->rpdesk->pDeskInfo->spwnd; 02702 02703 ThreadLock(pwnd, &tlpwnd); 02704 xxxFlushPalette(pwnd); 02705 ThreadUnlock(&tlpwnd); 02706 } 02707 02708 /* 02709 * If this is the last GUI thread for the process that made a temporary 02710 * (fullscreen) mode change, restore the mode to what's in the registry. 02711 */ 02712 if (FLastGuiThread(ptiCurrent) && (gppiFullscreen == ptiCurrent->ppi)) { 02713 xxxUserChangeDisplaySettings(NULL, NULL, NULL, NULL, 0, 0, KernelMode); 02714 02715 UserAssert(gppiFullscreen != ptiCurrent->ppi); 02716 } 02717 02718 /*******************************************************************************************\ 02719 * * 02720 * CLEANING THREAD OBJECTS. AVOID CALLING BACK AFTER THIS POINT * 02721 * New objects might be created while calling back and won't be cleaned up * 02722 * * 02723 \*******************************************************************************************/ 02724 02725 /* 02726 * This thread might have some outstanding timers. Destroy them 02727 */ 02728 DestroyThreadsTimers(ptiCurrent); 02729 02730 /* 02731 * Free any windows hooks this thread has created. 02732 */ 02733 FreeThreadsWindowHooks(); 02734 02735 /* 02736 * Free any hwnd lists the thread was using 02737 */ 02738 { 02739 PBWL pbwl, pbwlNext; 02740 for (pbwl = gpbwlList; pbwl != NULL; ) { 02741 pbwlNext = pbwl->pbwlNext; 02742 if (pbwl->ptiOwner == ptiCurrent) { 02743 FreeHwndList(pbwl); 02744 } 02745 pbwl = pbwlNext; 02746 } 02747 } 02748 02749 /* 02750 * Destroy all the public objects created by this thread. 02751 */ 02752 DestroyThreadsHotKeys(); 02753 02754 DestroyThreadsObjects(); 02755 02756 /* 02757 * Free any synchronous Notifies pending for this thread and 02758 * free any Win Event Hooks this thread created. 02759 */ 02760 FreeThreadsWinEvents(ptiCurrent); 02761 02762 /* 02763 * Unlock the keyboard layouts here 02764 */ 02765 Unlock(&ptiCurrent->spklActive); 02766 02767 /* 02768 * Cleanup the global resources if this is the last GUI 02769 * thread for this session 02770 */ 02771 if (gdwGuiThreads == 1) { 02772 CleanupResources(); 02773 } 02774 02775 02776 if (FLastGuiThread(ptiCurrent)) { 02777 02778 /* 02779 * Check if this was a setup app. 02780 */ 02781 if (ptiCurrent->ppi->W32PF_Flags & W32PF_SETUPAPP) { 02782 PDESKTOPINFO pdeskinfo = GETDESKINFO(ptiCurrent); 02783 if (pdeskinfo->spwndShell) { 02784 _PostMessage(pdeskinfo->spwndShell, DTM_SETUPAPPRAN, 0, 0); 02785 } 02786 } 02787 02788 DestroyProcessesClasses(ptiCurrent->ppi); 02789 ptiCurrent->ppi->W32PF_Flags &= ~(W32PF_CLASSESREGISTERED); 02790 02791 02792 DestroyProcessesObjects(ptiCurrent->ppi); 02793 } 02794 02795 #ifdef FE_IME 02796 /* 02797 * Unlock default input context. 02798 */ 02799 Unlock(&ptiCurrent->spDefaultImc); 02800 #endif 02801 02802 if (ptiCurrent->pq != NULL) { 02803 /* 02804 * Remove this thread's cursor count from the queue. 02805 */ 02806 ptiCurrent->pq->iCursorLevel -= ptiCurrent->iCursorLevel; 02807 02808 /* 02809 * Have to recalc queue ownership after this thread 02810 * leaves if it is a member of a shared input queue. 02811 */ 02812 if (ptiCurrent->pq->cThreads != 1) 02813 { 02814 gpdeskRecalcQueueAttach = ptiCurrent->rpdesk; 02815 /* 02816 * Because we are in thread cleanup, we won't callback due 02817 * to WinEvents (zzzSetFMouseMoved calls zzzUpdateCursorImage) 02818 */ 02819 UserAssert(ptiCurrent->TIF_flags & TIF_INCLEANUP); 02820 UserAssert(gbExitInProgress == FALSE); 02821 zzzSetFMouseMoved(); 02822 } 02823 } 02824 02825 /* 02826 * Remove from the process' list, also. 02827 */ 02828 ppti = &PpiCurrent()->ptiList; 02829 if (*ppti != NULL) { 02830 while (*ppti != ptiCurrent && (*ppti)->ptiSibling != NULL) { 02831 ppti = &((*ppti)->ptiSibling); 02832 } 02833 if (*ppti == ptiCurrent) { 02834 *ppti = ptiCurrent->ptiSibling; 02835 ptiCurrent->ptiSibling = NULL; 02836 } 02837 } 02838 02839 { 02840 PDESKTOP rpdesk; 02841 PATTACHINFO *ppai; 02842 02843 /* 02844 * Temporarily lock the desktop until the THREADINFO structure is 02845 * freed. Note that locking a NULL ptiCurrent->rpdesk is OK. Use a 02846 * normal lock instead of a thread lock because the lock must 02847 * exist past the freeing of the ptiCurrent. 02848 */ 02849 rpdesk = NULL; 02850 LockDesktop(&rpdesk, ptiCurrent->rpdesk, LDL_FN_DESTROYTHREADINFO, (ULONG_PTR)PtiCurrent()); 02851 02852 /* 02853 * Cleanup SMS structures attached to this thread. Handles both 02854 * pending send and receive messages. MUST make sure we do SendMsgCleanup 02855 * AFTER window cleanup. 02856 */ 02857 SendMsgCleanup(ptiCurrent); 02858 02859 02860 /* 02861 * Allow this thread to be swapped 02862 */ 02863 if (ptiCurrent->cEnterCount) { 02864 BOOLEAN bool; 02865 02866 RIPMSG1(RIP_WARNING, "Thread exiting with stack locked. pti:%#p\n", ptiCurrent); 02867 bool = KeSetKernelStackSwapEnable(TRUE); 02868 ptiCurrent->cEnterCount = 0; 02869 UserAssert(!bool); 02870 } 02871 02872 if (ptiCurrent->ppi != NULL) { 02873 ptiCurrent->ppi->cThreads--; 02874 UserAssert(ptiCurrent->ppi->cThreads >= 0); 02875 } 02876 02877 /* 02878 * If this thread is a win16 task, remove it from the scheduler. 02879 */ 02880 if (ptiCurrent->TIF_flags & TIF_16BIT) { 02881 if ((ptiCurrent->ptdb) && (ptiCurrent->ptdb->hTaskWow != 0)) { 02882 _WOWCleanup(NULL, ptiCurrent->ptdb->hTaskWow); 02883 } 02884 DestroyTask(ptiCurrent->ppi, ptiCurrent); 02885 } 02886 02887 if (ptiCurrent->hEventQueueClient != NULL) { 02888 ProtectHandle(ptiCurrent->hEventQueueClient, FALSE); 02889 ZwClose(ptiCurrent->hEventQueueClient); 02890 ptiCurrent->hEventQueueClient = NULL; 02891 } 02892 02893 02894 if (gspwndInternalCapture != NULL) { 02895 if (GETPTI(gspwndInternalCapture) == ptiCurrent) { 02896 Unlock(&gspwndInternalCapture); 02897 } 02898 } 02899 02900 /* 02901 * Set gptiForeground to NULL if equal to this pti before exiting 02902 * this routine. 02903 */ 02904 if (gptiForeground == ptiCurrent) { 02905 if (FWINABLE()) { 02906 /* 02907 * Post these (WEF_ASYNC), since we can't make callbacks from here. 02908 */ 02909 xxxWindowEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, INDEXID_CONTAINER, WEF_ASYNC); 02910 xxxWindowEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, INDEXID_CONTAINER, WEF_ASYNC); 02911 } 02912 02913 /* 02914 * Call the Shell to ask it to activate its main window. 02915 * This will be accomplished with a PostMessage() to itself, 02916 * so the actual activation will take place later. 02917 */ 02918 UserAssert(rpdesk != NULL); 02919 02920 if (rpdesk->pDeskInfo->spwndProgman) 02921 _PostMessage(rpdesk->pDeskInfo->spwndProgman, guiActivateShellWindow, 0, 0); 02922 02923 /* 02924 * Set gptiForeground to NULL because we're destroying it. 02925 */ 02926 SetForegroundThread(NULL); 02927 02928 /* 02929 * If this thread is attached to gpqForeground AND it's the 02930 * last thread in the queue, then zzzDestroyQueue will NULL out 02931 * qpqForeground. Due to journalling attaching, gptiForegrouund 02932 * is not always attached to gpqForeground. This is one reason 02933 * why we no longer NULL out gpqForeground as stated in the old 02934 * comment. The other reason is that there might be other threads 02935 * in the foreground queue so there is no need to zap it. This was 02936 * messing up MsTest (now called VisualTest) 02937 * This is the old comment: 02938 * "Since gpqForeground is derived from the foreground thread 02939 * structure, set it to NULL as well, since there now is no 02940 * foreground thread structure" 02941 * 02942 * qpqForeground = NULL; 02943 */ 02944 } 02945 02946 02947 /* 02948 * If this thread got the last input event, pass ownership to another 02949 * thread in this process or to the foreground thread. 02950 */ 02951 if (ptiCurrent == glinp.ptiLastWoken) { 02952 UserAssert(PpiCurrent() == ptiCurrent->ppi); 02953 if (ptiCurrent->ppi->ptiList != NULL) { 02954 UserAssert (ptiCurrent != ptiCurrent->ppi->ptiList); 02955 glinp.ptiLastWoken = ptiCurrent->ppi->ptiList; 02956 } else { 02957 glinp.ptiLastWoken = gptiForeground; 02958 } 02959 } 02960 02961 /* 02962 * Make sure none of the other global thread pointers are pointing to us. 02963 */ 02964 if (gptiShutdownNotify == ptiCurrent) { 02965 gptiShutdownNotify = NULL; 02966 } 02967 if (gptiTasklist == ptiCurrent) { 02968 gptiTasklist = NULL; 02969 } 02970 if (gHardErrorHandler.pti == ptiCurrent) { 02971 gHardErrorHandler.pti = NULL; 02972 } 02973 02974 /* 02975 * May be called from xxxCreateThreadInfo before the queue is created 02976 * so check for NULL queue. 02977 * Lock the queues since this pti might be locked. They will be unlocked 02978 * in UserDeleteW32Thread 02979 */ 02980 if (ptiCurrent->pq != NULL) { 02981 UserAssert(ptiCurrent->pq != ptiCurrent->pqAttach); 02982 DestroyThreadsMessages(ptiCurrent->pq, ptiCurrent); 02983 (ptiCurrent->pq->cLockCount)++; 02984 zzzDestroyQueue(ptiCurrent->pq, ptiCurrent); 02985 } 02986 02987 /* 02988 * zzzReattachThreads shouldn't call back while using pqAttach 02989 */ 02990 UserAssert(ptiCurrent->pqAttach == NULL); 02991 #if 0 02992 if (ptiCurrent->pqAttach != NULL) { 02993 DestroyThreadsMessages(ptiCurrent->pqAttach, ptiCurrent); 02994 (ptiCurrent->pqAttach->cLockCount)++; 02995 zzzDestroyQueue(ptiCurrent->pqAttach, ptiCurrent); 02996 } 02997 #endif 02998 02999 /* 03000 * Remove the pti from its pti list and reset the pointers. 03001 */ 03002 if (ptiCurrent->rpdesk != NULL) { 03003 RemoveEntryList(&ptiCurrent->PtiLink); 03004 InitializeListHead(&ptiCurrent->PtiLink); 03005 } 03006 03007 FreeMessageList(&ptiCurrent->mlPost); 03008 03009 /* 03010 * Free any attachinfo structures pointing to this thread 03011 */ 03012 ppai = &gpai; 03013 while ((*ppai) != NULL) { 03014 if ((*ppai)->pti1 == ptiCurrent || (*ppai)->pti2 == ptiCurrent) { 03015 PATTACHINFO paiKill = *ppai; 03016 *ppai = (*ppai)->paiNext; 03017 UserFreePool((HLOCAL)paiKill); 03018 } else { 03019 ppai = &(*ppai)->paiNext; 03020 } 03021 } 03022 03023 /* 03024 * Change ownership of any objects that didn't get freed (because they 03025 * are locked or we have a bug and the object didn't get destroyed). 03026 */ 03027 MarkThreadsObjects(ptiCurrent); 03028 03029 /* 03030 * Free thread information visible from client 03031 */ 03032 if (rpdesk && ptiCurrent->pcti != NULL && ptiCurrent->pcti != &(ptiCurrent->cti)) { 03033 DesktopFree(rpdesk, ptiCurrent->pcti); 03034 ptiCurrent->pcti = &(ptiCurrent->cti); 03035 } 03036 03037 /* 03038 * Free the client info for system threads 03039 */ 03040 if (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD && ptiCurrent->pClientInfo != NULL) { 03041 UserFreePool(ptiCurrent->pClientInfo); 03042 ptiCurrent->pClientInfo = NULL; 03043 } 03044 03045 /* 03046 * Unlock the temporary desktop lock. ptiCurrent->rpdesk is still locked 03047 * and will be unlocked in UserDeleteW32Thread. 03048 */ 03049 UnlockDesktop(&rpdesk, LDU_FN_DESTROYTHREADINFO, (ULONG_PTR)PtiCurrent()); 03050 } 03051 03052 /* 03053 * One more thread died. 03054 */ 03055 gdwGuiThreads--; 03056 }

HANDLE xxxGetInputEvent DWORD  dwWakeMask  ) 
 

Definition at line 5238 of file queue.c.

References CheckForClientDeath, CheckProcessForeground(), ClearQueueServerEvent(), _CLIENTINFO::cSpins, FALSE, tagCLIENTTHREADINFO::fsWakeMask, GetInputBits(), gptiForeground, tagTHREADINFO::hEventQueueClient, IsHooked, IsWinEventNotifyDeferredOK, KeSetEvent(), tagTHREADINFO::pClientInfo, tagTHREADINFO::pcti, tagTHREADINFO::pEventQueueServer, tagTHREADINFO::ppi, PtiCurrent, tagPROCESSINFO::ptiMainThread, tagTHREADINFO::TIF_flags, TIF_SPINNING, WHF_FOREGROUNDIDLE, xxxCallHook(), and zzzWakeInputIdle().

05240 { 05241 PTHREADINFO ptiCurrent; 05242 WORD wFlags = HIWORD(dwWakeMask); 05243 UserAssert(IsWinEventNotifyDeferredOK()); 05244 05245 ptiCurrent = PtiCurrent(); 05246 05247 /* 05248 * If our wait condition is satisfied, signal the event and return. 05249 * (Since the wake mask could have been anything at the time the input 05250 * arrived, the event might not be signaled) 05251 */ 05252 if (GetInputBits(ptiCurrent->pcti, LOWORD(dwWakeMask), (wFlags & MWMO_INPUTAVAILABLE))) { 05253 KeSetEvent(ptiCurrent->pEventQueueServer, 2, FALSE); 05254 return ptiCurrent->hEventQueueClient; 05255 } 05256 05257 /* 05258 * If an idle hook is set, call it. 05259 */ 05260 if (ptiCurrent == gptiForeground && 05261 IsHooked(ptiCurrent, WHF_FOREGROUNDIDLE)) { 05262 xxxCallHook(HC_ACTION, 0, 0, WH_FOREGROUNDIDLE); 05263 } 05264 05265 CheckForClientDeath(); 05266 05267 /* 05268 * What is the criteria for an "idle process"? 05269 * Answer: The first thread that calls zzzWakeInputIdle, or SleepInputIdle or... 05270 * Any thread that calls xxxGetInputEvent with any of the following 05271 * bits set in its wakemask: (sanfords) 05272 */ 05273 if (dwWakeMask & (QS_POSTMESSAGE | QS_INPUT)) { 05274 ptiCurrent->ppi->ptiMainThread = ptiCurrent; 05275 } 05276 05277 /* 05278 * When we return, this app is going to sleep. Since it is in its 05279 * idle mode when it goes to sleep, wake any apps waiting for this 05280 * app to go idle. 05281 */ 05282 zzzWakeInputIdle(ptiCurrent); 05283 /* 05284 * Setup the wake mask for this thread. Wait for QS_EVENT or the app won't 05285 * get event messages like deactivate. 05286 */ 05287 ClearQueueServerEvent((WORD)(dwWakeMask | QS_EVENT)); 05288 /* 05289 * This app is going idle. Clear the spin count check to see 05290 * if we need to make this process foreground again. 05291 */ 05292 ptiCurrent->pClientInfo->cSpins = 0; 05293 if (ptiCurrent->TIF_flags & TIF_SPINNING) { 05294 CheckProcessForeground(ptiCurrent); 05295 } 05296 05297 UserAssert(ptiCurrent->pcti->fsWakeMask != 0); 05298 return ptiCurrent->hEventQueueClient; 05299 }

NTSTATUS xxxInitProcessInfo PW32PROCESS  pwp  ) 
 

Definition at line 4874 of file queue.c.

References CheckAllowForeground(), CheckCritIn, gcSysExpunge, GetProcessLuid(), gppiList, NT_SUCCESS, NTSTATUS(), NULL, tagPROCESSINFO::ppiNextRunning, PUDF_ALLOWFOREGROUNDACTIVATE, SetAppStarting(), Status, TEST_PUDF, and xxxSetProcessInitState().

Referenced by xxxUserProcessCallout().

04876 { 04877 PPROCESSINFO ppi = (PPROCESSINFO)pwp; 04878 NTSTATUS Status; 04879 04880 CheckCritIn(); 04881 04882 /* 04883 * Check if we need to initialize the process. 04884 */ 04885 if (pwp->W32PF_Flags & W32PF_PROCESSCONNECTED) { 04886 return STATUS_ALREADY_WIN32; 04887 } 04888 pwp->W32PF_Flags |= W32PF_PROCESSCONNECTED; 04889 04890 #if defined(_WIN64) 04891 /* Tag as emulated 32bit. Flag is copied to be consistent with 04892 * the way WOW16 apps are tagged for win32k. 04893 */ 04894 if (pwp->Process->Wow64Process) { 04895 pwp->W32PF_Flags |= W32PF_WOW64; 04896 } 04897 #endif 04898 04899 /* 04900 * Mark this app as "starting" - it will be starting until its first 04901 * window activates. 04902 */ 04903 UserVerify(xxxSetProcessInitState(pwp->Process, STARTF_FORCEOFFFEEDBACK)); 04904 04905 /* 04906 * link it into the starting processes list 04907 */ 04908 SetAppStarting(ppi); 04909 /* 04910 * link it into the global processes list 04911 */ 04912 ppi->ppiNextRunning = gppiList; 04913 gppiList = ppi; 04914 /* 04915 * If foreground activation has not been canceled and the parent process 04916 * (or an ancestor) can force a foreground change, then allow this process 04917 * to come to the foreground when it does its first activation. 04918 * 04919 * Bug 273518 - joejo 04920 * 04921 * This will allow console windows to set foreground correctly on new 04922 * process' it launches, as opposed it just forcing foreground. 04923 */ 04924 if (TEST_PUDF(PUDF_ALLOWFOREGROUNDACTIVATE) && CheckAllowForeground(pwp->Process)) { 04925 ppi->W32PF_Flags |= W32PF_ALLOWFOREGROUNDACTIVATE; 04926 } 04927 TAGMSG2(DBGTAG_FOREGROUND, "xxxInitProcessInfo %s W32PF %#p", 04928 ((ppi->W32PF_Flags & W32PF_ALLOWFOREGROUNDACTIVATE) ? "set" : "NOT"), 04929 ppi); 04930 04931 /* 04932 * Get the logon session id. This is used to determine which 04933 * windowstation to connect to and to identify attempts to 04934 * call hooks across security contexts. 04935 */ 04936 Status = GetProcessLuid(NULL, &ppi->luidSession); 04937 UserAssert(NT_SUCCESS(Status)); 04938 04939 /* 04940 * Ensure that we're in sync with the expunge count 04941 */ 04942 ppi->cSysExpunge = gcSysExpunge; 04943 04944 /* 04945 * Don't perform any LPK callbacks until GDI notifies 04946 * us that the LPK(s) are loaded and initialized. 04947 */ 04948 ppi->dwLpkEntryPoints = 0; 04949 04950 return STATUS_SUCCESS; 04951 }

DWORD xxxMsgWaitForMultipleObjects DWORD  nCount,
PVOID *  apObjects,
MSGWAITCALLBACK  pfnNonMsg,
PKWAIT_BLOCK  WaitBlockArray
 

Definition at line 4271 of file queue.c.

References apObjects, CheckForClientDeath, CheckProcessForeground(), ClearQueueServerEvent(), _CLIENTINFO::cSpins, DEVICE_TYPE_MOUSE, DWORD, EnterCrit, FALSE, tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeMask, gptiForeground, IsHooked, IsWinEventNotifyDeferredOK, KeWaitForMultipleObjects(), LeaveCrit, MSGWAITCALLBACK, NT_SUCCESS, NTSTATUS(), NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::pcti, tagTHREADINFO::pEventQueueServer, PtiCurrent, SleepInputIdle(), Status, tagTHREADINFO::TIF_flags, TIF_SPINNING, UserMode, WHF_FOREGROUNDIDLE, WrUserRequest, xxxCallHook(), and zzzWakeInputIdle().

Referenced by xxxDesktopThread().

04276 { 04277 PTHREADINFO ptiCurrent = PtiCurrent(); 04278 NTSTATUS Status; 04279 04280 ptiCurrent = PtiCurrent(); 04281 UserAssert(IsWinEventNotifyDeferredOK()); 04282 04283 /* 04284 * Setup the wake mask for this thread. Wait for QS_EVENT or the app won't 04285 * get event messages like deactivate. 04286 */ 04287 ClearQueueServerEvent(QS_ALLINPUT | QS_EVENT); 04288 04289 /* 04290 * Stuff the event handle for the current queue at the end. 04291 */ 04292 apObjects[nCount] = ptiCurrent->pEventQueueServer; 04293 04294 /* 04295 * Check to see if any input came inbetween when we 04296 * last checked and the NtClearEvent() call. 04297 */ 04298 if (!(ptiCurrent->pcti->fsChangeBits & QS_ALLINPUT)) { 04299 04300 /* 04301 * This app is going idle. Clear the spin count check to see 04302 * if we need to make this process foreground again. 04303 */ 04304 if (ptiCurrent->TIF_flags & TIF_SPINNING) { 04305 CheckProcessForeground(ptiCurrent); 04306 } 04307 ptiCurrent->pClientInfo->cSpins = 0; 04308 04309 if (ptiCurrent == gptiForeground && 04310 IsHooked(ptiCurrent, WHF_FOREGROUNDIDLE)) { 04311 xxxCallHook(HC_ACTION, 0, 0, WH_FOREGROUNDIDLE); 04312 } 04313 04314 CheckForClientDeath(); 04315 04316 /* 04317 * Set the input idle event to wake up any threads waiting 04318 * for this thread to go into idle state. 04319 */ 04320 zzzWakeInputIdle(ptiCurrent); 04321 04322 Again: 04323 LeaveCrit(); 04324 04325 Status = KeWaitForMultipleObjects(nCount + 1, apObjects, 04326 WaitAny, WrUserRequest, 04327 UserMode, FALSE, 04328 NULL, WaitBlockArray); 04329 04330 EnterCrit(); 04331 04332 CheckForClientDeath(); 04333 04334 UserAssert(NT_SUCCESS(Status)); 04335 04336 04337 if ((Status == STATUS_WAIT_0) && (pfnNonMsg != NULL)) { 04338 /* 04339 * Call pfnNonMsg for the first event 04340 */ 04341 pfnNonMsg(DEVICE_TYPE_MOUSE); 04342 04343 /* 04344 * Setup again the wake mask for this thread. 04345 * Wait for QS_EVENT or the app won't 04346 * get event messages like deactivate. 04347 */ 04348 ptiCurrent->pcti->fsWakeMask = QS_ALLINPUT | QS_EVENT; 04349 goto Again; 04350 } 04351 04352 if (Status == (NTSTATUS)(STATUS_WAIT_0 + nCount)) { 04353 04354 /* 04355 * Reset the input idle event to block and threads waiting 04356 * for this thread to go into idle state. 04357 */ 04358 SleepInputIdle(ptiCurrent); 04359 } 04360 } else { 04361 Status = nCount; 04362 } 04363 04364 /* 04365 * Clear fsWakeMask since we're no longer waiting on the queue. 04366 */ 04367 ptiCurrent->pcti->fsWakeMask = 0; 04368 04369 return (DWORD)Status; 04370 }

DWORD xxxPollAndWaitForSingleObject PKEVENT  pEvent,
PVOID  pExecObject,
DWORD  dwMilliseconds
 

Definition at line 5481 of file queue.c.

References tagTHREADINFO::apEvent, ClearQueueServerEvent(), ClientDeliverUserApc(), ComputePastTickDelta(), DWORD, EnterCrit, FALSE, tagCLIENTTHREADINFO::fsChangeBits, HEVENT_REMOVEME, IEV_EXEC, IEV_IDLE, IEV_INPUT, INTERMEDIATE_TIMEOUT, KeWaitForMultipleObjects(), LeaveCrit, NT_SUCCESS, NtGetTickCount(), NTSTATUS(), NULL, tagTHREADINFO::pcti, tagTHREADINFO::pEventQueueServer, POLL_EVENT_CNT, PtiCurrent, Status, ThreadLockObject, ThreadUnlockObject, TIF_16BIT, tagTHREADINFO::TIF_flags, TRUE, UINT, UserMode, WrUserRequest, xxxDirectedYield(), xxxReceiveMessages, and xxxSleepTask().

Referenced by xxxWaitForInputIdle().

05485 { 05486 DWORD dwIntermediateMilliseconds, dwStartTickCount; 05487 PTHREADINFO ptiCurrent; 05488 UINT cEvent = 2; 05489 NTSTATUS Status = -1; 05490 LARGE_INTEGER li; 05491 TL tlEvent; 05492 05493 ptiCurrent = PtiCurrent(); 05494 05495 if (ptiCurrent->apEvent == NULL) { 05496 ptiCurrent->apEvent = UserAllocPoolNonPaged(POLL_EVENT_CNT * sizeof(PKEVENT), TAG_EVENT); 05497 if (ptiCurrent->apEvent == NULL) 05498 return (DWORD)-1; 05499 } 05500 05501 /* 05502 * Refcount the event to ensure that it won't go 05503 * away during the wait. By using a thread lock, the 05504 * event will be dereferenced if the thread exits 05505 * during a callback. The process pointer has already been 05506 * locked. 05507 */ 05508 ThreadLockObject(pEvent, &tlEvent); 05509 05510 /* 05511 * If a process was passed in, wait on it too. No need 05512 * to reference this because the caller has it referenced. 05513 */ 05514 if (pExecObject) { 05515 cEvent++; 05516 } 05517 05518 /* 05519 * We want to wake if there're sent messages pending 05520 */ 05521 ClearQueueServerEvent(QS_SENDMESSAGE); 05522 05523 /* 05524 * Wow Tasks MUST be descheduled while in the wait to allow 05525 * other tasks in the same wow scheduler to run. 05526 * 05527 * For example, 16 bit app A calls WaitForInputIdle on 32 bit app B. 05528 * App B starts up and tries to send a message to 16 bit app C. App C 05529 * will never be able to process the message unless app A yields 05530 * control to it, so app B will never go idle. 05531 */ 05532 05533 if (ptiCurrent->TIF_flags & TIF_16BIT) { 05534 xxxSleepTask(FALSE, HEVENT_REMOVEME); 05535 // caution: the wow task is no longer scheduled. 05536 } 05537 05538 dwStartTickCount = NtGetTickCount(); 05539 while (TRUE) { 05540 if (dwMilliseconds > INTERMEDIATE_TIMEOUT) { 05541 dwIntermediateMilliseconds = INTERMEDIATE_TIMEOUT; 05542 05543 /* 05544 * If we are not waiting an infinite amount of time then subtract 05545 * the last loop duration from time left to wait. 05546 */ 05547 if (dwMilliseconds != INFINITE) { 05548 DWORD dwNewTickCount = NtGetTickCount(); 05549 DWORD dwDelta = ComputePastTickDelta(dwNewTickCount, dwStartTickCount); 05550 dwStartTickCount = dwNewTickCount; 05551 if (dwDelta < dwMilliseconds) { 05552 dwMilliseconds -= dwDelta; 05553 } else { 05554 dwMilliseconds = 0; 05555 } 05556 } 05557 } else { 05558 dwIntermediateMilliseconds = dwMilliseconds; 05559 dwMilliseconds = 0; 05560 } 05561 05562 /* 05563 * Convert dwMilliseconds to a relative-time(i.e. negative) LARGE_INTEGER. 05564 * NT Base calls take time values in 100 nanosecond units. 05565 */ 05566 if (dwIntermediateMilliseconds != INFINITE) 05567 li.QuadPart = Int32x32To64(-10000, dwIntermediateMilliseconds); 05568 05569 /* 05570 * Load events into the wait array. Do this every time 05571 * through the loop in case of recursion. 05572 */ 05573 ptiCurrent->apEvent[IEV_IDLE] = pEvent; 05574 ptiCurrent->apEvent[IEV_INPUT] = ptiCurrent->pEventQueueServer; 05575 ptiCurrent->apEvent[IEV_EXEC] = pExecObject; 05576 05577 LeaveCrit(); 05578 05579 Status = KeWaitForMultipleObjects(cEvent, 05580 &ptiCurrent->apEvent[IEV_IDLE], 05581 WaitAny, 05582 WrUserRequest, 05583 UserMode, 05584 FALSE, 05585 (dwIntermediateMilliseconds == INFINITE ? 05586 NULL : &li), 05587 NULL); 05588 05589 EnterCrit(); 05590 05591 if (!NT_SUCCESS(Status)) { 05592 Status = -1; 05593 } else { 05594 05595 /* 05596 * Because we do a non-alertable wait, we know that a status 05597 * of STATUS_USER_APC means that the thread was terminated. 05598 * If we have terminated, get back to user mode 05599 */ 05600 if (Status == STATUS_USER_APC) { 05601 ClientDeliverUserApc(); 05602 Status = -1; 05603 } 05604 } 05605 05606 if (ptiCurrent->pcti->fsChangeBits & QS_SENDMESSAGE) { 05607 /* 05608 * Wow Tasks MUST wait to be rescheduled in the wow non-premptive 05609 * scheduler before doing anything which might invoke client code. 05610 */ 05611 if (ptiCurrent->TIF_flags & TIF_16BIT) { 05612 xxxDirectedYield(DY_OLDYIELD); 05613 } 05614 05615 xxxReceiveMessages(ptiCurrent); 05616 05617 if (ptiCurrent->TIF_flags & TIF_16BIT) { 05618 xxxSleepTask(FALSE, HEVENT_REMOVEME); 05619 // caution: the wow task is no longer scheduled. 05620 } 05621 } 05622 05623 /* 05624 * If we returned from the wait for some other reason than a timeout 05625 * or to receive messages we are done. If it is a timeout we are 05626 * only done waiting if the overall time is zero. 05627 */ 05628 if (Status != STATUS_TIMEOUT && Status != 1) 05629 break; 05630 05631 if (dwMilliseconds == 0) { 05632 /* 05633 * Fix up the return if the last poll was interupted by a message 05634 */ 05635 if (Status == 1) 05636 Status = WAIT_TIMEOUT; 05637 break; 05638 } 05639 05640 } 05641 05642 /* 05643 * reschedule the 16 bit app 05644 */ 05645 if (ptiCurrent->TIF_flags & TIF_16BIT) { 05646 xxxDirectedYield(DY_OLDYIELD); 05647 } 05648 05649 /* 05650 * Unlock the events. 05651 */ 05652 ThreadUnlockObject(&tlEvent); 05653 05654 return Status; 05655 }

VOID xxxProcessEventMessage PTHREADINFO  ptiCurrent,
PQMSG  pqmsg
 

Definition at line 3772 of file queue.c.

References _PostMessage(), ATW_ASYNC, ATW_NOZORDER, ATW_SETFOCUS, BOOL, CBKEYSTATE, CleanEventMessage(), DF_MOUSEMOVETRK, DF_TOOLTIP, DF_TOOLTIPACTIVE, DF_TOOLTIPSHOWING, DF_TRACKMOUSELEAVE, DoBeep(), tagDESKTOP::dwDTFlags, DWORD, tagQMSG::dwQEvent, GetMouseKeyFlags(), GETPTI, gpqForeground, tagDESKTOP::htEx, IsHooked, IsWinEventNotifyDeferredOK, LockWindowUpdate2(), tagQMSG::msg, NULL, PBYTE, PEM_ACTIVATE_NOZORDER, PEM_ACTIVATE_RESTORE, pfnBP, PostEventMessage(), PostShellHookMessages(), tagTHREADINFO::ppi, tagTHREADINFO::pq, ProcessUpdateKeyStateEvent(), PtiCurrent, PtoHq, PTOOLTIPWND, PWND_TOP, QEVENT_ACTIVATE, QEVENT_APPCOMMAND, QEVENT_ASYNCSENDMSG, QEVENT_CANCELMODE, QEVENT_CANCELMOUSEMOVETRK, QEVENT_DEACTIVATE, QEVENT_DESTROYWINDOW, QEVENT_HUNGTHREAD, QEVENT_NOTIFYWINEVENT, QEVENT_POSTMESSAGE, QEVENT_RITACCESSIBILITY, QEVENT_RITSOUND, QEVENT_SETWINDOWPOS, QEVENT_SHOWWINDOW, QEVENT_UPDATEKEYSTATE, RevalidateHwnd, RITSOUND_DOBEEP, RITSOUND_DOWNSIREN, RITSOUND_HIGHBEEP, RITSOUND_KEYCLICK, RITSOUND_LOWBEEP, RITSOUND_UPSIREN, tagTHREADINFO::rpdesk, SetWakeBit(), tagQ::spwndActive, tagQ::spwndCapture, tagQ::spwndFocus, tagDESKTOP::spwndTooltip, tagDESKTOP::spwndTrack, TestUP, TestWF, ThreadLockAlwaysWithPti, ThreadLockPoolCleanup, ThreadUnlock, ThreadUnlockPoolCleanup, TIF_ALLOWFOREGROUNDACTIVATE, tagTHREADINFO::TIF_flags, TRUE, UINT, VOID(), WEF_ASYNC, WEF_POSTED, WFCHILD, WFINDESTROY, WFMINIMIZED, WHF_SHELL, WPUpdateCheckPointSettings(), xxxActivateThisWindow(), xxxCallHook(), xxxCancelMouseMoveTracking(), xxxCancelTracking(), xxxDeactivate(), xxxDestroyWindow(), xxxFreeWindow(), xxxProcessAsyncSendMessage(), xxxProcessHungThreadEvent(), xxxProcessNotifyWinEvent(), xxxProcessSetWindowPosEvent(), xxxResetTooltip(), xxxSendMessage(), xxxSetForegroundWindow2(), xxxSetWindowPos(), xxxShowWindow(), xxxUpdateTray(), zzzActiveCursorTracking(), and zzzClipCursor().

Referenced by xxxScanSysQueue().

03775 { 03776 PWND pwnd; 03777 TL tlpwndT; 03778 TL tlMsg; 03779 PQ pq; 03780 03781 UserAssert(IsWinEventNotifyDeferredOK()); 03782 UserAssert(ptiCurrent == PtiCurrent()); 03783 03784 ThreadLockPoolCleanup(ptiCurrent, pqmsg, &tlMsg, CleanEventMessage); 03785 03786 pq = ptiCurrent->pq; 03787 switch (pqmsg->dwQEvent) { 03788 case QEVENT_DESTROYWINDOW: 03789 /* 03790 * These events are posted from xxxDW_DestroyOwnedWindows 03791 * for owned windows that are not owned by the owner 03792 * window thread. 03793 */ 03794 pwnd = RevalidateHwnd((HWND)pqmsg->msg.wParam); 03795 if (pwnd != NULL) { 03796 if (!TestWF(pwnd, WFCHILD)) 03797 xxxDestroyWindow(pwnd); 03798 else { 03799 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwndT); 03800 xxxFreeWindow(pwnd, &tlpwndT); 03801 } 03802 } 03803 break; 03804 03805 case QEVENT_SHOWWINDOW: 03806 /* 03807 * These events are mainly used from within CascadeChildWindows() 03808 * and TileChildWindows() so that taskmgr doesn't hang while calling 03809 * these apis if it is trying to tile or cascade a hung application. 03810 */ 03811 /* The HIWORD of lParam now has the preserved state of gfAnimate at the 03812 * time of the call. 03813 */ 03814 pwnd = RevalidateHwnd((HWND)pqmsg->msg.wParam); 03815 if (pwnd != NULL && !TestWF(pwnd, WFINDESTROY)) { 03816 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwndT); 03817 xxxShowWindow(pwnd, (DWORD)pqmsg->msg.lParam); 03818 /* 03819 * If this is coming from an async SetWindowPlacement, update the 03820 * check point settings if the window is minimized. 03821 */ 03822 if ((pqmsg->msg.message & WPF_ASYNCWINDOWPLACEMENT) 03823 && TestWF(pwnd, WFMINIMIZED)) { 03824 03825 WPUpdateCheckPointSettings(pwnd, (UINT)pqmsg->msg.message); 03826 } 03827 ThreadUnlock(&tlpwndT); 03828 } 03829 break; 03830 03831 case QEVENT_NOTIFYWINEVENT: 03832 UserAssert(((PNOTIFY)pqmsg->msg.lParam)->dwWEFlags & WEF_POSTED); 03833 UserAssert(((PNOTIFY)pqmsg->msg.lParam)->dwWEFlags & WEF_ASYNC); 03834 xxxProcessNotifyWinEvent((PNOTIFY)pqmsg->msg.lParam); 03835 break; 03836 03837 case QEVENT_SETWINDOWPOS: 03838 /* 03839 * QEVENT_SETWINDOWPOS events are generated when a thread calls 03840 * SetWindowPos with a list of windows owned by threads other than 03841 * itself. This way all WINDOWPOSing on a window is done the thread 03842 * that owns (created) the window and we don't have any of those 03843 * nasty inter-thread synchronization problems. 03844 */ 03845 xxxProcessSetWindowPosEvent((PSMWP)pqmsg->msg.wParam); 03846 break; 03847 03848 case QEVENT_UPDATEKEYSTATE: 03849 /* 03850 * Update the local key state with the state from those 03851 * keys that have changed since the last time key state 03852 * was synchronized. 03853 */ 03854 ProcessUpdateKeyStateEvent(pq, (PBYTE)pqmsg->msg.wParam, (PBYTE)pqmsg->msg.wParam + CBKEYSTATE); 03855 break; 03856 03857 case QEVENT_ACTIVATE: 03858 { 03859 if (pqmsg->msg.lParam == 0) { 03860 03861 /* 03862 * Clear any visible tracking going on in system. We 03863 * only bother to do this if lParam == 0 since 03864 * xxxSetForegroundWindow2() deals with this in the 03865 * other case. 03866 */ 03867 xxxCancelTracking(); 03868 03869 /* 03870 * Remove the clip cursor rectangle - it is a global mode that 03871 * gets removed when switching. Also remove any LockWindowUpdate() 03872 * that's still around. 03873 */ 03874 zzzClipCursor(NULL); 03875 LockWindowUpdate2(NULL, TRUE); 03876 03877 /* 03878 * Reload pq because it may have changed. 03879 */ 03880 pq = ptiCurrent->pq; 03881 03882 /* 03883 * If this event didn't originate from an initializing app 03884 * coming to the foreground [wParam == 0] then go ahead 03885 * and check if there's already an active window and if so make 03886 * it visually active. Also make sure we're still the foreground 03887 * queue. 03888 */ 03889 if ((pqmsg->msg.wParam != 0) && (pq->spwndActive != NULL) && 03890 (pq == gpqForeground)) { 03891 PWND pwndActive; 03892 03893 ThreadLockAlwaysWithPti(ptiCurrent, pwndActive = pq->spwndActive, &tlpwndT); 03894 xxxSendMessage(pwndActive, WM_NCACTIVATE, TRUE, 0); 03895 xxxUpdateTray(pwndActive); 03896 xxxSetWindowPos(pwndActive, PWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 03897 ThreadUnlock(&tlpwndT); 03898 } else if (pq != gpqForeground) { 03899 03900 /* 03901 * If we're not being activated, make sure we don't become foreground. 03902 */ 03903 ptiCurrent->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; 03904 TAGMSG1(DBGTAG_FOREGROUND, "xxxProcessEventMessage clear TIF %#p", ptiCurrent); 03905 ptiCurrent->ppi->W32PF_Flags &= ~W32PF_ALLOWFOREGROUNDACTIVATE; 03906 TAGMSG1(DBGTAG_FOREGROUND, "xxxProcessEventMessage clear W32PF %#p", ptiCurrent->ppi); 03907 } 03908 03909 } else { 03910 03911 pwnd = RevalidateHwnd((HWND)pqmsg->msg.lParam); 03912 if (pwnd == NULL) 03913 break; 03914 03915 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwndT); 03916 03917 /* 03918 * If nobody is foreground, allow this app to become foreground. 03919 */ 03920 if (gpqForeground == NULL) { 03921 xxxSetForegroundWindow2(pwnd, ptiCurrent, 0); 03922 } else { 03923 if (pwnd != pq->spwndActive) { 03924 if (xxxActivateThisWindow(pwnd, (UINT)pqmsg->msg.wParam, 03925 (ATW_SETFOCUS | ATW_ASYNC) | 03926 ((pqmsg->msg.message & PEM_ACTIVATE_NOZORDER) ? ATW_NOZORDER : 0))) { 03927 03928 /* 03929 * This event was posted by SetForegroundWindow2 03930 * (i.e. pqmsg->msg.lParam != 0) so make sure 03931 * mouse is on this window. 03932 */ 03933 if (TestUP(ACTIVEWINDOWTRACKING)) { 03934 zzzActiveCursorTracking(pwnd); 03935 } 03936 } 03937 } else { 03938 BOOL fActive = (GETPTI(pwnd)->pq == gpqForeground); 03939 03940 xxxSendMessage(pwnd, WM_NCACTIVATE, 03941 (DWORD)(fActive), 0); 03942 if (fActive) { 03943 xxxUpdateTray(pwnd); 03944 } 03945 03946 /* 03947 * Only bring the window to the top if it is becoming active. 03948 */ 03949 if (fActive && !(pqmsg->msg.message & PEM_ACTIVATE_NOZORDER)) 03950 xxxSetWindowPos(pwnd, PWND_TOP, 0, 0, 0, 0, 03951 SWP_NOSIZE | SWP_NOMOVE); 03952 } 03953 } 03954 03955 /* 03956 * Check here to see if the window needs to be restored. This is a 03957 * hack so that we're compatible with what msmail expects out of 03958 * win3.1 alt-tab. msmail expects to always be active when it gets 03959 * asked to be restored. This will ensure that during alt-tab 03960 * activate. 03961 */ 03962 if (pqmsg->msg.message & PEM_ACTIVATE_RESTORE) { 03963 if (TestWF(pwnd, WFMINIMIZED)) { 03964 _PostMessage(pwnd, WM_SYSCOMMAND, SC_RESTORE, 0); 03965 } 03966 } 03967 03968 ThreadUnlock(&tlpwndT); 03969 } 03970 03971 } 03972 break; 03973 03974 case QEVENT_DEACTIVATE: 03975 xxxDeactivate(ptiCurrent, (DWORD)pqmsg->msg.wParam); 03976 break; 03977 03978 case QEVENT_CANCELMODE: 03979 if (pq->spwndCapture != NULL) { 03980 ThreadLockAlwaysWithPti(ptiCurrent, pq->spwndCapture, &tlpwndT); 03981 xxxSendMessage(pq->spwndCapture, WM_CANCELMODE, 0, 0); 03982 ThreadUnlock(&tlpwndT); 03983 03984 /* 03985 * Set QS_MOUSEMOVE so any sleeping modal loops, 03986 * like the move/size code, will wake up and figure 03987 * out that it should abort. 03988 */ 03989 SetWakeBit(ptiCurrent, QS_MOUSEMOVE); 03990 } 03991 break; 03992 03993 03994 case QEVENT_POSTMESSAGE: 03995 /* 03996 * This event is used in situations where we need to ensure that posted 03997 * messages are processed after previous QEVENT's. Normally, posting a 03998 * queue event and then calling postmessage will result in the posted 03999 * message being seen first by the app (because posted messages are 04000 * processed before input.) Instead we will post a QEVENT_POSTMESSAGE 04001 * instead of doing a postmessage directly, which will result in the 04002 * correct ordering of messages. 04003 * 04004 */ 04005 04006 if (pwnd = RevalidateHwnd((HWND)pqmsg->msg.hwnd)) { 04007 04008 _PostMessage(pwnd,pqmsg->msg.message,pqmsg->msg.wParam,pqmsg->msg.lParam); 04009 } 04010 break; 04011 04012 04013 case QEVENT_ASYNCSENDMSG: 04014 xxxProcessAsyncSendMessage((PASYNCSENDMSG)pqmsg->msg.wParam); 04015 break; 04016 04017 case QEVENT_HUNGTHREAD: 04018 pwnd = RevalidateHwnd((HWND)pqmsg->msg.hwnd); 04019 if (pwnd != NULL) { 04020 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwndT); 04021 xxxProcessHungThreadEvent(pwnd); 04022 ThreadUnlock(&tlpwndT); 04023 } 04024 break; 04025 04026 case QEVENT_CANCELMOUSEMOVETRK: { 04027 /* 04028 * hwnd: hwndTrack. message: dwDTFlags. 04029 * wParam: htEx. lParam: dwDTCancel 04030 */ 04031 PDESKTOP pdesk = ptiCurrent->rpdesk; 04032 pwnd = RevalidateHwnd((HWND)pqmsg->msg.hwnd); 04033 /* 04034 * Let's check that the app didn't manage to restart mouse leave 04035 * tracking before we had a chance to cancel it. 04036 */ 04037 UserAssert(!(pqmsg->msg.message & DF_TRACKMOUSELEAVE) 04038 || !(pdesk->dwDTFlags & DF_TRACKMOUSELEAVE) 04039 || (PtoHq(pdesk->spwndTrack) != pqmsg->msg.hwnd) 04040 || !((pdesk->htEx == HTCLIENT) ^ ((int)pqmsg->msg.wParam == HTCLIENT))); 04041 /* 04042 * If we're back tracking at the same spot, bail 04043 */ 04044 if ((pdesk->dwDTFlags & DF_MOUSEMOVETRK) 04045 && (PtoHq(pdesk->spwndTrack) == pqmsg->msg.hwnd) 04046 && (pdesk->htEx == (int)pqmsg->msg.wParam)) { 04047 /* 04048 * If we're tracking mouse leave, 04049 */ 04050 break; 04051 } 04052 /* 04053 * Don't nuke the tooltip if it has been reactivated. 04054 */ 04055 if (pdesk->dwDTFlags & DF_TOOLTIPACTIVE) { 04056 pqmsg->msg.lParam &= ~DF_TOOLTIP; 04057 } 04058 /* 04059 * Cancel tracking if the window is still around 04060 */ 04061 if (pwnd != NULL) { 04062 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwndT); 04063 xxxCancelMouseMoveTracking(pqmsg->msg.message, pwnd, 04064 (int)pqmsg->msg.wParam, 04065 (DWORD)pqmsg->msg.lParam); 04066 ThreadUnlock(&tlpwndT); 04067 } else if ((pqmsg->msg.lParam & DF_TOOLTIP) 04068 && (pqmsg->msg.message & DF_TOOLTIPSHOWING)) { 04069 /* 04070 * The window is gone and so must be tracking. 04071 * Just take care of the tooltip which is still showing. 04072 */ 04073 pwnd = pdesk->spwndTooltip; 04074 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwndT); 04075 xxxResetTooltip((PTOOLTIPWND)pwnd); 04076 ThreadUnlock(&tlpwndT); 04077 } 04078 } 04079 break; 04080 04081 case QEVENT_RITACCESSIBILITY: 04082 if (IsHooked(ptiCurrent, WHF_SHELL)) { 04083 xxxCallHook((UINT)pqmsg->msg.wParam, 04084 (WPARAM)pqmsg->msg.lParam, 04085 (LPARAM)0, 04086 WH_SHELL); 04087 } 04088 04089 PostShellHookMessages((UINT)pqmsg->msg.wParam, pqmsg->msg.lParam); 04090 break; 04091 04092 case QEVENT_RITSOUND: 04093 /* 04094 * This should only happen on the desktop thread. 04095 */ 04096 switch(pqmsg->msg.message) { 04097 case RITSOUND_UPSIREN: 04098 case RITSOUND_DOWNSIREN: 04099 case RITSOUND_LOWBEEP: 04100 case RITSOUND_HIGHBEEP: 04101 case RITSOUND_KEYCLICK: 04102 (pfnBP[pqmsg->msg.message])(); 04103 break; 04104 04105 case RITSOUND_DOBEEP: 04106 switch(pqmsg->msg.wParam) { 04107 case RITSOUND_UPSIREN: 04108 case RITSOUND_DOWNSIREN: 04109 case RITSOUND_LOWBEEP: 04110 case RITSOUND_HIGHBEEP: 04111 case RITSOUND_KEYCLICK: 04112 DoBeep(pfnBP[pqmsg->msg.wParam], (DWORD)pqmsg->msg.lParam); 04113 } 04114 break; 04115 } 04116 break; 04117 04118 case QEVENT_APPCOMMAND: { 04119 /* 04120 * qevent app commands so we can post a wm_appcommand to the queue 04121 */ 04122 THREADINFO *ptiWindowOwner; 04123 int cmd; 04124 UINT keystate; 04125 04126 /* 04127 * check the appcommand's are within reasonable ranges 04128 * if they aren't then we have an internal consistency error since xxxKeyEvent should 04129 * have generated correct ones for us 04130 */ 04131 UserAssert( pqmsg->msg.lParam >= VK_APPCOMMAND_FIRST && 04132 pqmsg->msg.lParam <= VK_APPCOMMAND_LAST ); 04133 04134 /* 04135 * We need to work out which window to send to here. Using the same 04136 * rules as from xxxScanSysQueue: 04137 * Assign the input to the focus window. If there is no focus 04138 * window, assign it to the active window as a SYS message. 04139 */ 04140 pwnd = ptiCurrent->pq->spwndFocus; 04141 if (!pwnd) { 04142 pwnd = ptiCurrent->pq->spwndActive; 04143 if (!pwnd ) { 04144 /* 04145 * At the moment we will just eat the message since we can't find a foreground q 04146 * This follows the method that any other app (eg hidserv) would mimic to 04147 * find the window to send to. 04148 */ 04149 break; 04150 } 04151 } 04152 04153 /* 04154 * We don't want to block on another thread since the xxxSendMessage is a synchronous call 04155 * so we post the message to the queue of the window owner thread 04156 */ 04157 ptiWindowOwner = GETPTI(pwnd); 04158 if (ptiCurrent != ptiWindowOwner) { 04159 /* 04160 * Post the event message to the window who should get it 04161 */ 04162 PostEventMessage(ptiWindowOwner, ptiWindowOwner->pq, QEVENT_APPCOMMAND, 04163 NULL, 0, (WPARAM)0, pqmsg->msg.lParam); 04164 04165 /* 04166 * break out of this since we've now posted the message to a different q - we 04167 * don't want to deal with it here 04168 */ 04169 break; 04170 } 04171 04172 cmd = APPCOMMAND_FIRST + ((UINT)pqmsg->msg.lParam - VK_APPCOMMAND_FIRST); 04173 keystate = GetMouseKeyFlags(ptiWindowOwner->pq); 04174 pqmsg->msg.lParam = MAKELPARAM(keystate, cmd); 04175 04176 04177 /* 04178 * Generate a WM_APPCOMMAND message from the keyboard keys 04179 */ 04180 ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwndT); 04181 xxxSendMessage(pwnd, WM_APPCOMMAND, (WPARAM)pwnd, pqmsg->msg.lParam); 04182 ThreadUnlock(&tlpwndT); 04183 04184 break; 04185 } 04186 default: 04187 RIPMSG1(RIP_ERROR, "xxxProcessEventMessage Bad pqmsg->dwQEvent:%#lx", pqmsg->dwQEvent); 04188 break; 04189 } 04190 04191 ThreadUnlockPoolCleanup(ptiCurrent, &tlMsg); 04192 }

void xxxProcessHungThreadEvent PWND  pwnd  ) 
 

Definition at line 3736 of file queue.c.

References CheckLock, MINMAX_KEEPHIDDEN, SetVisible(), SV_SET, TestWF, WFMINIMIZED, WFVISIBLE, and xxxMinMaximize().

Referenced by xxxProcessEventMessage().

03737 { 03738 CheckLock(pwnd); 03739 03740 if (TestWF(pwnd, WFVISIBLE)) { 03741 RIPMSG0(RIP_WARNING, "xxxProcessHungThreadEvent: window is already visible"); 03742 } else { 03743 SetVisible(pwnd, SV_SET); 03744 03745 if (TestWF(pwnd, WFMINIMIZED)) { 03746 RIPMSG0(RIP_WARNING, "xxxProcessHungThreadEvent: window is already minmized"); 03747 } else { 03748 xxxMinMaximize(pwnd, SW_SHOWMINNOACTIVE, MINMAX_KEEPHIDDEN); 03749 } 03750 } 03751 }

NTSTATUS xxxQueryInformationThread IN HANDLE  hThread,
IN USERTHREADINFOCLASS  ThreadInfoClass,
OUT PVOID  ThreadInformation,
IN ULONG  ThreadInformationLength,
OUT PULONG ReturnLength  OPTIONAL
 

Definition at line 5901 of file queue.c.

References BOOL, _ETHREAD::Cid, tagTHREADINFO::cWindows, DWORD, tagWINDOWSTATION::dwWSF_Flags, FALSE, FHungApp(), GetTaskName(), gpidLogon, tagTDB::hTaskWow, HW, ISCSRSS, tagWOWPROCESSINFO::lpfnWowExitTask, NT_SUCCESS, NTSTATUS(), NULL, ObReferenceObjectByHandle(), tagDESKTOP::pDeskInfo, tagTHREADINFO::ppi, PsThreadType, tagTHREADINFO::ptdb, PtiCurrent, PtiFromThread, tagPROCESSINFO::pwpi, tagTHREADINFO::rpdesk, tagDESKTOP::rpwinstaParent, SHUTDOWN_KNOWN_PROCESS, SHUTDOWN_UNKNOWN_PROCESS, tagDESKTOPINFO::spwnd, Status, TIF_16BIT, tagTHREADINFO::TIF_flags, UnlockThread, UserMode, WMCS_NORETRY, WSF_NOIO, WSF_REALSHUTDOWN, xxxRestoreCsrssThreadDesktop(), xxxSetCsrssThreadDesktop(), and xxxSwitchDesktop().

Referenced by NtUserQueryInformationThread().

05907 { 05908 PUSERTHREAD_SHUTDOWN_INFORMATION pShutdown; 05909 PUSERTHREAD_WOW_INFORMATION pWow; 05910 PETHREAD Thread; 05911 PTHREADINFO pti; 05912 NTSTATUS Status = STATUS_SUCCESS; 05913 ULONG LocalReturnLength = 0; 05914 DWORD dwClientFlags; 05915 05916 UNREFERENCED_PARAMETER(ThreadInformationLength); 05917 /* 05918 * Only allow CSRSS to make this call 05919 */ 05920 UserAssert(ISCSRSS()); 05921 05922 Status = ObReferenceObjectByHandle(hThread, 05923 THREAD_QUERY_INFORMATION, 05924 *PsThreadType, 05925 UserMode, 05926 &Thread, 05927 NULL); 05928 if (!NT_SUCCESS(Status)) 05929 return Status; 05930 05931 pti = PtiFromThread(Thread); 05932 05933 switch (ThreadInfoClass) { 05934 case UserThreadShutdownInformation: 05935 LocalReturnLength = sizeof(USERTHREAD_SHUTDOWN_INFORMATION); 05936 UserAssert(ThreadInformationLength == sizeof(USERTHREAD_SHUTDOWN_INFORMATION)); 05937 pShutdown = ThreadInformation; 05938 /* 05939 * Read the client flags and zero out the structure, 05940 * except for pdeskRestore (which is supposed 05941 * to be the last field) 05942 */ 05943 dwClientFlags = pShutdown->dwFlags; 05944 UserAssert(FIELD_OFFSET(USERTHREAD_SHUTDOWN_INFORMATION, drdRestore) 05945 == (sizeof(USERTHREAD_SHUTDOWN_INFORMATION) - sizeof(DESKRESTOREDATA))); 05946 RtlZeroMemory(pShutdown, 05947 sizeof(USERTHREAD_SHUTDOWN_INFORMATION) - sizeof(DESKRESTOREDATA)); 05948 05949 /* 05950 * Return the desktop window handle if the thread 05951 * has a desktop and the desktop is on a visible 05952 * windowstation. 05953 */ 05954 if (pti != NULL && pti->rpdesk != NULL && 05955 !(pti->rpdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO)) 05956 pShutdown->hwndDesktop = HW(pti->rpdesk->pDeskInfo->spwnd); 05957 05958 /* 05959 * Return shutdown status. Zero indicates that the thread 05960 * has windows and can be shut down in the normal manner. 05961 */ 05962 if (Thread->Cid.UniqueProcess == gpidLogon) { 05963 /* 05964 * Do not shutdown the logon process. 05965 */ 05966 pShutdown->StatusShutdown = SHUTDOWN_KNOWN_PROCESS; 05967 } else if (pti == NULL || pti->rpdesk == NULL) { 05968 05969 /* 05970 * The thread either is not a gui thread or it doesn't 05971 * have a desktop. Make console do the shutdown. 05972 */ 05973 pShutdown->StatusShutdown = SHUTDOWN_UNKNOWN_PROCESS; 05974 } 05975 05976 /* 05977 * Return flags 05978 */ 05979 if (pti != NULL && pti->cWindows != 0) 05980 pShutdown->dwFlags |= USER_THREAD_GUI; 05981 05982 /* 05983 * If we return the desktop window handle and the 05984 * app should be shut down, switch to the desktop 05985 * and assign it to the shutdown worker thread. 05986 */ 05987 if ((pShutdown->dwFlags & USER_THREAD_GUI) && 05988 pShutdown->StatusShutdown == 0) { 05989 /* 05990 * The current csrss thread is going to 05991 * make activation calls, send messages, 05992 * switch video modes, etc so we need to 05993 * assign it to a dekstop 05994 */ 05995 PTHREADINFO ptiCurrent = PtiCurrent(); 05996 UserAssert(pti->rpdesk != NULL); 05997 05998 if (ptiCurrent->rpdesk != pti->rpdesk) { 05999 /* 06000 * If this thread already has a desktop, 06001 * restore the old one first. 06002 * This might happen when threads of the same 06003 * process are attached to different desktops. 06004 */ 06005 if (ptiCurrent->rpdesk != NULL) { 06006 Status = xxxRestoreCsrssThreadDesktop(&pShutdown->drdRestore); 06007 UserAssert(pti == PtiFromThread(Thread)); 06008 } 06009 if (NT_SUCCESS(Status)) { 06010 Status = xxxSetCsrssThreadDesktop(pti->rpdesk, &pShutdown->drdRestore); 06011 UserAssert(pti == PtiFromThread(Thread)); 06012 } 06013 } 06014 /* 06015 * If we're forcing a shutdown, then there is no need to switch 06016 * since we won't send any messages or bring up the EndTask dialog 06017 * (We still want to have a proper rpdesk since BoostHardError might 06018 * call PostThreadMessage) 06019 */ 06020 if (!(dwClientFlags & WMCS_NORETRY)) { 06021 if (NT_SUCCESS(Status)) { 06022 #if DBG 06023 BOOL fSwitch = 06024 #endif 06025 xxxSwitchDesktop(pti->rpdesk->rpwinstaParent, pti->rpdesk, FALSE); 06026 #if DBG 06027 UserAssert(pti == PtiFromThread(Thread)); 06028 if (!fSwitch) { 06029 if ((pti->rpdesk->rpwinstaParent == NULL) 06030 || !(pti->rpdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO)) { 06031 06032 if (!(pti->rpdesk->rpwinstaParent->dwWSF_Flags & WSF_REALSHUTDOWN)) 06033 RIPMSG1(RIP_ERROR, "UserThreadShutdownInformation: xxxSwitchDesktop failed. pti:%#p", pti); 06034 06035 } 06036 } 06037 #endif 06038 } 06039 } 06040 } 06041 break; 06042 06043 case UserThreadFlags: 06044 LocalReturnLength = sizeof(DWORD); 06045 if (pti == NULL) 06046 Status = STATUS_INVALID_HANDLE; 06047 else { 06048 UserAssert(ThreadInformationLength == sizeof(DWORD)); 06049 *(LPDWORD)ThreadInformation = pti->TIF_flags; 06050 } 06051 break; 06052 06053 case UserThreadTaskName: 06054 LocalReturnLength = GetTaskName(pti, ThreadInformation, ThreadInformationLength); 06055 break; 06056 06057 case UserThreadWOWInformation: 06058 LocalReturnLength = sizeof(USERTHREAD_WOW_INFORMATION); 06059 UserAssert(ThreadInformationLength == sizeof(USERTHREAD_WOW_INFORMATION)); 06060 pWow = ThreadInformation; 06061 RtlZeroMemory(pWow, sizeof(USERTHREAD_WOW_INFORMATION)); 06062 06063 /* 06064 * If the thread is 16-bit, Status = the exit task function 06065 * and task id. 06066 */ 06067 if (pti && pti->TIF_flags & TIF_16BIT) { 06068 pWow->lpfnWowExitTask = pti->ppi->pwpi->lpfnWowExitTask; 06069 if (pti->ptdb) 06070 pWow->hTaskWow = pti->ptdb->hTaskWow; 06071 else 06072 pWow->hTaskWow = 0; 06073 } 06074 break; 06075 06076 case UserThreadHungStatus: 06077 LocalReturnLength = sizeof(DWORD); 06078 UserAssert(ThreadInformationLength >= sizeof(DWORD)); 06079 06080 /* 06081 * Return hung status. 06082 */ 06083 if (pti) 06084 *(PDWORD)ThreadInformation = 06085 (DWORD) FHungApp(pti, (DWORD)*(PDWORD)ThreadInformation); 06086 else 06087 *(PDWORD)ThreadInformation = FALSE; 06088 break; 06089 06090 default: 06091 Status = STATUS_INVALID_INFO_CLASS; 06092 UserAssert(FALSE); 06093 break; 06094 } 06095 06096 if (ARGUMENT_PRESENT(ReturnLength) ) { 06097 *ReturnLength = LocalReturnLength; 06098 } 06099 06100 UnlockThread(Thread); 06101 06102 return Status; 06103 }

BOOL xxxReadPostMessage PTHREADINFO  pti,
LPMSG  lpMsg,
PWND  pwndFilter,
UINT  msgMin,
UINT  msgMax,
BOOL  fRemoveMsg
 

Definition at line 3499 of file queue.c.

References BOOL, CheckMsgFilter, CheckProcessForeground(), CheckQuitMessage(), CheckRemoveHotkeyBit(), tagMLIST::cMsgs, tagTHREADINFO::cQuit, DelQEntry(), tagQMSG::ExtraInfo, tagQ::ExtraInfo, FALSE, FindQMsg(), tagCLIENTTHREADINFO::fsChangeBits, tagCLIENTTHREADINFO::fsWakeBits, tagTHREADINFO::idLast, tagTHREADINFO::mlPost, tagQMSG::msg, MSGFLAG_DDE_MID_THUNK, NULL, tagTHREADINFO::pcti, tagTHREADINFO::pq, tagMLIST::pqmsgRead, tagTHREADINFO::ptLast, tagTHREADINFO::TIF_flags, TIF_MSGPOSCHANGED, TIF_SPINNING, tagTHREADINFO::timeLast, TraceDdeMsg, TRUE, UINT, and xxxDDETrackGetMessageHook().

Referenced by xxxInternalGetMessage().

03506 { 03507 PQMSG pqmsg; 03508 PMLIST pmlPost; 03509 03510 /* 03511 * Check to see if it is time to generate a quit message. 03512 */ 03513 if (CheckQuitMessage(pti, lpMsg, fRemoveMsg)) 03514 return TRUE; 03515 03516 /* 03517 * Loop through the messages in this list looking for the one that 03518 * fits the passed in filters. 03519 */ 03520 pmlPost = &pti->mlPost; 03521 pqmsg = FindQMsg(pti, pmlPost, pwndFilter, msgMin, msgMax, FALSE); 03522 if (pqmsg == NULL) { 03523 /* 03524 * Check again for quit... FindQMsg deletes some messages 03525 * in some instances, so we may match the conditions 03526 * for quit generation here. 03527 */ 03528 if (CheckQuitMessage(pti, lpMsg, fRemoveMsg)) 03529 return TRUE; 03530 } else { 03531 /* 03532 * Update the thread info fields with the info from this qmsg. 03533 */ 03534 pti->timeLast = pqmsg->msg.time; 03535 if (!RtlEqualMemory(&pti->ptLast, &pqmsg->msg.pt, sizeof(POINT))) { 03536 pti->TIF_flags |= TIF_MSGPOSCHANGED; 03537 } 03538 pti->ptLast = pqmsg->msg.pt; 03539 03540 pti->idLast = (ULONG_PTR)pqmsg; 03541 pti->pq->ExtraInfo = pqmsg->ExtraInfo; 03542 03543 /* 03544 * Are we supposed to yank out the message? If not, stick some 03545 * random id into idLast so we don't unlock the input queue until we 03546 * pull this message from the queue. 03547 */ 03548 *lpMsg = pqmsg->msg; 03549 if (!fRemoveMsg) { 03550 pti->idLast = 1; 03551 } else { 03552 /* 03553 * If we're removing a WM_HOTKEY message, we may need to 03554 * clear the QS_HOTKEY bit, since we have a special bit 03555 * for that message. 03556 */ 03557 if (pmlPost->pqmsgRead->msg.message == WM_HOTKEY) { 03558 CheckRemoveHotkeyBit(pti, pmlPost); 03559 } 03560 03561 03562 /* 03563 * Since we're removing an event from the queue, we 03564 * need to check priority. This resets the TIF_SPINNING 03565 * since we're no longer spinning. 03566 */ 03567 // We disable all MS badapp code and do it our way 03568 if (pti->TIF_flags & TIF_SPINNING) 03569 CheckProcessForeground(pti); 03570 03571 DelQEntry(pmlPost, pqmsg); 03572 } 03573 03574 /* 03575 * See if this is a dde message that needs to be fixed up. 03576 */ 03577 if (CheckMsgFilter(lpMsg->message, 03578 (WM_DDE_FIRST + 1) | MSGFLAG_DDE_MID_THUNK, 03579 WM_DDE_LAST | MSGFLAG_DDE_MID_THUNK)) { 03580 /* 03581 * Fixup the message value. 03582 */ 03583 lpMsg->message &= (UINT)~MSGFLAG_DDE_MID_THUNK; 03584 03585 /* 03586 * Call back the client to allocate the dde data for this message. 03587 */ 03588 xxxDDETrackGetMessageHook(lpMsg); 03589 03590 /* 03591 * Copy these values back into the queue if this message hasn't 03592 * been removed from the queue. Need to search through the 03593 * queue again because the pqmsg may have been removed when 03594 * we left the critical section above. 03595 */ 03596 if (!fRemoveMsg) { 03597 if (pqmsg == FindQMsg(pti, pmlPost, pwndFilter, msgMin, msgMax, FALSE)) { 03598 pqmsg->msg = *lpMsg; 03599 } 03600 } 03601 } 03602 #if DBG 03603 else if (CheckMsgFilter(lpMsg->message, WM_DDE_FIRST, WM_DDE_LAST)) { 03604 if (fRemoveMsg) { 03605 TraceDdeMsg(lpMsg->message, (HWND)lpMsg->wParam, lpMsg->hwnd, MSG_RECV); 03606 } else { 03607 TraceDdeMsg(lpMsg->message, (HWND)lpMsg->wParam, lpMsg->hwnd, MSG_PEEK); 03608 } 03609 } 03610 #endif 03611 } 03612 03613 /* 03614 * If there are no posted messages available, clear the post message 03615 * bit so we don't go looking for them again. 03616 */ 03617 if (pmlPost->cMsgs == 0 && pti->cQuit == 0) { 03618 pti->pcti->fsWakeBits &= ~(QS_POSTMESSAGE | QS_ALLPOSTMESSAGE); 03619 pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE; 03620 } 03621 03622 return pqmsg != NULL; 03623 }

NTSTATUS xxxRestoreCsrssThreadDesktop PDESKRESTOREDATA  pdrdRestore  ) 
 

Definition at line 5804 of file queue.c.

References CloseProtectedHandle(), FALSE, ISCSRSS, LogDesktop, msg, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PtiCurrent, tagTHREADINFO::rpdesk, Status, xxxDispatchMessage(), xxxPeekMessage, and xxxSetThreadDesktop().

Referenced by VideoPortCalloutThread(), xxxHardErrorControl(), xxxQueryInformationThread(), xxxSetInformationThread(), and xxxUserPowerEventCalloutWorker().

05805 { 05806 PTHREADINFO ptiCurrent = PtiCurrent(); 05807 NTSTATUS Status = STATUS_SUCCESS; 05808 MSG msg; 05809 05810 /* 05811 * Only csr should come here 05812 */ 05813 UserAssert(ISCSRSS()); 05814 UserAssert(pdrdRestore); 05815 05816 /* 05817 * Set the new desktop, if switching 05818 */ 05819 if (pdrdRestore->pdeskRestore != ptiCurrent->rpdesk) { 05820 /* 05821 * Process any remaining messages before we leave the desktop 05822 */ 05823 if (ptiCurrent->rpdesk) { 05824 while (xxxPeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) 05825 xxxDispatchMessage(&msg); 05826 } 05827 05828 if (!xxxSetThreadDesktop(NULL, pdrdRestore->pdeskRestore)) { 05829 RIPMSG1(RIP_WARNING, "xxxRestoreCsrssThreadDesktop: xxxRestoreThreadDesktop(%#p) failed", pdrdRestore->pdeskRestore); 05830 Status = STATUS_INVALID_HANDLE; 05831 } 05832 } 05833 05834 /* 05835 * Dereference the desktop, 05836 * even if failing the call. 05837 */ 05838 if (pdrdRestore->pdeskRestore != NULL) { 05839 LogDesktop(pdrdRestore->pdeskRestore, LD_DEREF_FN_SETCSRSSTHREADDESKTOP2, FALSE, 0); 05840 ObDereferenceObject(pdrdRestore->pdeskRestore); 05841 pdrdRestore->pdeskRestore = NULL; 05842 } 05843 05844 if(pdrdRestore->hdeskNew) { 05845 CloseProtectedHandle(pdrdRestore->hdeskNew); 05846 UserAssert(NT_SUCCESS(Status)); 05847 pdrdRestore->hdeskNew = NULL; 05848 } 05849 return Status; 05850 }

VOID xxxSetConsoleCaretInfo PCONSOLE_CARET_INFO  pcci  ) 
 

Definition at line 6419 of file queue.c.

References FWINABLE, tagWND::head, ThreadLock, ThreadUnlock, ValidateHwnd, VOID(), WEF_ASYNC, and xxxWindowEvent().

Referenced by xxxConsoleControl().

06421 { 06422 PWND pwnd; 06423 TL tlpwnd; 06424 06425 if (FWINABLE()) { 06426 pwnd = ValidateHwnd(pcci->hwnd); 06427 if (pwnd && pwnd->head.rpdesk) { 06428 pwnd->head.rpdesk->cciConsole = *pcci; 06429 ThreadLock(pwnd, &tlpwnd); 06430 xxxWindowEvent(EVENT_OBJECT_LOCATIONCHANGE, pwnd, OBJID_CARET, INDEXID_CONTAINER, WEF_ASYNC); 06431 ThreadUnlock(&tlpwnd); 06432 } 06433 } 06434 }

NTSTATUS xxxSetCsrssThreadDesktop PDESKTOP  pdesk,
PDESKRESTOREDATA  pdrdRestore
 

Definition at line 5713 of file queue.c.

References CloseProtectedHandle(), DF_DESTROYED, tagDESKTOP::dwDTFlags, ExDesktopObjectType, FALSE, ISCSRSS, KernelMode, LogDesktop, msg, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObOpenObjectByPointer(), ObReferenceObjectByPointer(), PtiCurrent, tagTHREADINFO::rpdesk, Status, TRUE, xxxDispatchMessage(), xxxPeekMessage, and xxxSetThreadDesktop().

Referenced by VideoPortCalloutThread(), xxxHardErrorControl(), xxxQueryInformationThread(), xxxSetInformationThread(), and xxxUserPowerEventCalloutWorker().

05714 { 05715 PTHREADINFO ptiCurrent = PtiCurrent(); 05716 NTSTATUS Status = STATUS_SUCCESS; 05717 MSG msg; 05718 05719 /* 05720 * Only csr should come here 05721 */ 05722 UserAssert(ISCSRSS()); 05723 UserAssert(pdrdRestore); 05724 UserAssert(pdrdRestore->pdeskRestore == NULL); 05725 05726 if (pdesk->dwDTFlags & DF_DESTROYED) { 05727 RIPMSG1(RIP_WARNING, "xxxSetCsrssThreadDesktop: pdesk 0x%x destroyed", 05728 pdesk); 05729 return STATUS_UNSUCCESSFUL; 05730 } 05731 05732 /* 05733 * Lock the current desktop (set operation). Also, create and save a 05734 * handle to the new desktop. 05735 */ 05736 pdrdRestore->pdeskRestore = ptiCurrent->rpdesk; 05737 05738 if (pdrdRestore->pdeskRestore != NULL) { 05739 Status = ObReferenceObjectByPointer(pdrdRestore->pdeskRestore, 05740 MAXIMUM_ALLOWED, 05741 *ExDesktopObjectType, 05742 KernelMode); 05743 05744 if (!NT_SUCCESS(Status)) { 05745 pdrdRestore->pdeskRestore = NULL; 05746 pdrdRestore->hdeskNew = NULL; 05747 return Status; 05748 } 05749 LogDesktop(pdrdRestore->pdeskRestore, LD_REF_FN_SETCSRSSTHREADDESKTOP, TRUE, (ULONG_PTR)PtiCurrent()); 05750 } 05751 05752 Status = ObOpenObjectByPointer( 05753 pdesk, 05754 0, 05755 NULL, 05756 EVENT_ALL_ACCESS, 05757 NULL, 05758 KernelMode, 05759 &(pdrdRestore->hdeskNew)); 05760 05761 05762 if (!NT_SUCCESS(Status)) { 05763 RIPNTERR2(Status, RIP_WARNING, "SetCsrssThreadDesktop, can't open handle, pdesk %#p. Status: %#x", pdesk, Status); 05764 if (pdrdRestore->pdeskRestore) { 05765 LogDesktop(pdrdRestore->pdeskRestore, LD_DEREF_FN_SETCSRSSTHREADDESKTOP1, FALSE, (ULONG_PTR)PtiCurrent()); 05766 ObDereferenceObject(pdrdRestore->pdeskRestore); 05767 pdrdRestore->pdeskRestore = NULL; 05768 } 05769 pdrdRestore->hdeskNew = NULL; 05770 return Status; 05771 } 05772 /* 05773 * Set the new desktop, if switching 05774 */ 05775 if (pdesk != ptiCurrent->rpdesk) { 05776 /* 05777 * Process any remaining messages before we leave the desktop 05778 */ 05779 if (ptiCurrent->rpdesk) { 05780 while (xxxPeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) 05781 xxxDispatchMessage(&msg); 05782 } 05783 05784 if (!xxxSetThreadDesktop(NULL, pdesk)) { 05785 RIPMSG1(RIP_WARNING, "xxxSetCsrssThreadDesktop: xxxSetThreadDesktop(%#p) failed", pdesk); 05786 Status = STATUS_INVALID_HANDLE; 05787 /* 05788 * We're failing so deref if needed. 05789 */ 05790 if (pdrdRestore->pdeskRestore != NULL) { 05791 LogDesktop(pdrdRestore->pdeskRestore, LD_DEREF_FN_SETCSRSSTHREADDESKTOP1, FALSE, (ULONG_PTR)PtiCurrent()); 05792 ObDereferenceObject(pdrdRestore->pdeskRestore); 05793 pdrdRestore->pdeskRestore = NULL; 05794 } 05795 CloseProtectedHandle(pdrdRestore->hdeskNew); 05796 pdrdRestore->hdeskNew = NULL; 05797 } 05798 } 05799 05800 UserAssert(NT_SUCCESS(Status)); 05801 return Status; 05802 }

NTSTATUS xxxSetInformationThread IN HANDLE  hThread,
IN USERTHREADINFOCLASS  ThreadInfoClass,
IN PVOID  ThreadInformation,
IN ULONG  ThreadInformationLength
 

Definition at line 6114 of file queue.c.

References CsrApiPort, CsrPortHandle, DWORD, EndShutdown(), FALSE, gpepCSRSS, grpdeskRitInput, InitiateShutdown(), ISCSRSS, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PsThreadType, PtiFromThread, tagTHREADINFO::rpdesk, SET_TIME_LAST_READ, Status, _ETHREAD::ThreadsProcess, tagTHREADINFO::TIF_flags, UnlockThread, UserMode, xxxRestoreCsrssThreadDesktop(), and xxxSetCsrssThreadDesktop().

Referenced by NtUserSetInformationThread().

06119 { 06120 PUSERTHREAD_FLAGS pFlags; 06121 HANDLE hClientThread; 06122 DWORD dwOldFlags; 06123 PTHREADINFO ptiT; 06124 NTSTATUS Status = STATUS_SUCCESS; 06125 PETHREAD Thread; 06126 PETHREAD ThreadClient; 06127 PTHREADINFO pti; 06128 HANDLE CsrPortHandle; 06129 06130 UNREFERENCED_PARAMETER(ThreadInformationLength); 06131 06132 /* 06133 * Only allow CSRSS to make this call 06134 */ 06135 UserAssert(ISCSRSS()); 06136 06137 Status = ObReferenceObjectByHandle(hThread, 06138 THREAD_SET_INFORMATION, 06139 *PsThreadType, 06140 UserMode, 06141 &Thread, 06142 NULL); 06143 if (!NT_SUCCESS(Status)) 06144 return Status; 06145 06146 pti = PtiFromThread(Thread); 06147 06148 switch (ThreadInfoClass) { 06149 case UserThreadFlags: 06150 if (pti == NULL) 06151 Status = STATUS_INVALID_HANDLE; 06152 else { 06153 UserAssert(ThreadInformationLength == sizeof(USERTHREAD_FLAGS)); 06154 pFlags = ThreadInformation; 06155 dwOldFlags = pti->TIF_flags; 06156 pti->TIF_flags ^= ((dwOldFlags ^ pFlags->dwFlags) & pFlags->dwMask); 06157 } 06158 break; 06159 06160 case UserThreadHungStatus: 06161 if (pti == NULL) 06162 Status = STATUS_INVALID_HANDLE; 06163 else { 06164 06165 /* 06166 * No arguments, simple set the last time read. 06167 */ 06168 SET_TIME_LAST_READ(pti); 06169 } 06170 break; 06171 06172 case UserThreadInitiateShutdown: 06173 UserAssert(ThreadInformationLength == sizeof(ULONG)); 06174 Status = InitiateShutdown(Thread, (PULONG)ThreadInformation); 06175 break; 06176 06177 case UserThreadEndShutdown: 06178 UserAssert(ThreadInformationLength == sizeof(NTSTATUS)); 06179 Status = EndShutdown(Thread, *(NTSTATUS *)ThreadInformation); 06180 break; 06181 06182 case UserThreadUseDesktop: 06183 UserAssert(ThreadInformationLength == sizeof(USERTHREAD_USEDESKTOPINFO)); 06184 if (pti == NULL) { 06185 Status = STATUS_INVALID_HANDLE; 06186 break; 06187 } 06188 06189 /* 06190 * If the caller provides a thread handle, then we use that 06191 * thread's pdesk and return the pdesk currently used 06192 * by the caller (set operation). Otherwise, 06193 * we use the pdesk provided by the caller (restore operation). 06194 */ 06195 hClientThread = ((PUSERTHREAD_USEDESKTOPINFO)ThreadInformation)->hThread; 06196 if (hClientThread != NULL) { 06197 Status = ObReferenceObjectByHandle(hClientThread, 06198 THREAD_QUERY_INFORMATION, 06199 *PsThreadType, 06200 UserMode, 06201 &ThreadClient, 06202 NULL); 06203 if (!NT_SUCCESS(Status)) 06204 break; 06205 06206 ptiT = PtiFromThread(ThreadClient); 06207 if ((ptiT == NULL) || (ptiT->rpdesk == NULL)) { 06208 Status = STATUS_INVALID_HANDLE; 06209 goto DerefClientThread; 06210 } 06211 Status = xxxSetCsrssThreadDesktop(ptiT->rpdesk, &((PUSERTHREAD_USEDESKTOPINFO)ThreadInformation)->drdRestore); 06212 } else { 06213 Status = xxxRestoreCsrssThreadDesktop(&((PUSERTHREAD_USEDESKTOPINFO)ThreadInformation)->drdRestore); 06214 } 06215 06216 06217 if (hClientThread != NULL) { 06218 DerefClientThread: 06219 ObDereferenceObject(ThreadClient); 06220 } 06221 break; 06222 06223 case UserThreadUseActiveDesktop: 06224 { 06225 UserAssert(ThreadInformationLength == sizeof(USERTHREAD_USEDESKTOPINFO)); 06226 if (pti == NULL || grpdeskRitInput == NULL) { 06227 Status = STATUS_INVALID_HANDLE; 06228 break; 06229 } 06230 Status = xxxSetCsrssThreadDesktop(grpdeskRitInput, 06231 &((PUSERTHREAD_USEDESKTOPINFO)ThreadInformation)->drdRestore); 06232 break; 06233 } 06234 case UserThreadCsrApiPort: 06235 06236 /* 06237 * Only CSR can call this 06238 */ 06239 if (Thread->ThreadsProcess != gpepCSRSS) { 06240 Status = STATUS_ACCESS_DENIED; 06241 break; 06242 } 06243 06244 UserAssert(ThreadInformationLength == sizeof(HANDLE)); 06245 06246 /* 06247 * Only set it once. 06248 */ 06249 if (CsrApiPort != NULL) 06250 break; 06251 06252 CsrPortHandle = *(PHANDLE)ThreadInformation; 06253 Status = ObReferenceObjectByHandle( 06254 CsrPortHandle, 06255 0, 06256 NULL, //*LpcPortObjectType, 06257 UserMode, 06258 &CsrApiPort, 06259 NULL); 06260 if (!NT_SUCCESS(Status)) { 06261 CsrApiPort = NULL; 06262 RIPMSG1(RIP_WARNING, 06263 "CSR port reference failed, Status=%#lx", 06264 Status); 06265 } 06266 06267 break; 06268 06269 default: 06270 Status = STATUS_INVALID_INFO_CLASS; 06271 UserAssert(FALSE); 06272 break; 06273 } 06274 06275 UnlockThread(Thread); 06276 06277 return Status; 06278 }

BOOL xxxSetProcessInitState PEPROCESS  Process,
DWORD  dwFlags
 

Definition at line 120 of file queue.c.

References BOOL, CheckCritIn, DeferWinEventNotify, dwFlags, EndDeferWinEventNotifyWithoutProcessing, FALSE, gpepCSRSS, IsWinEventNotifyDeferredOK, NT_SUCCESS, NTSTATUS(), NULL, PUDF_ALLOWFOREGROUNDACTIVATE, SET_PSEUDO_EVENT, SET_PUDF, Status, TRUE, _EPROCESS::Win32Process, and zzzCalcStartCursorHide().

Referenced by xxxInitProcessInfo(), xxxUserNotifyConsoleApplication(), and xxxUserNotifyProcessCreate().

00123 { 00124 PW32PROCESS W32Process; 00125 NTSTATUS Status; 00126 00127 CheckCritIn(); 00128 UserAssert(IsWinEventNotifyDeferredOK()); 00129 00130 /* 00131 * If the W32Process structure has not been allocated, do it now. 00132 */ 00133 W32Process = (PW32PROCESS)Process->Win32Process; 00134 if (W32Process == NULL) { 00135 Status = AllocateW32Process(Process); 00136 if (!NT_SUCCESS(Status)) { 00137 return FALSE; 00138 } 00139 W32Process = (PW32PROCESS)Process->Win32Process; 00140 #if DBG 00141 /* 00142 * The above AllocateW32Process(Process, FALSE) won't set the 00143 * W32PF_PROCESSCONNECTED flag (and if it wasn't previously set), 00144 * make sure we're not on the gppiStarting list, because if we are, 00145 * we will not be removed without the W32PF_PROCESSCONNECTED bit. 00146 */ 00147 if ((W32Process->W32PF_Flags & W32PF_PROCESSCONNECTED) == 0) { 00148 UserAssert((W32Process->W32PF_Flags & W32PF_APPSTARTING) == 0); 00149 } 00150 #endif 00151 } 00152 00153 /* 00154 * Defer WinEvent notifications, because the thread isn't initialized yet. 00155 */ 00156 DeferWinEventNotify(); 00157 if (dwFlags == 0) { 00158 if (!(W32Process->W32PF_Flags & W32PF_WOW)) { 00159 00160 /* 00161 * Check to see if the startglass is on, and if so turn it off and update. 00162 */ 00163 if (W32Process->W32PF_Flags & W32PF_STARTGLASS) { 00164 W32Process->W32PF_Flags &= ~W32PF_STARTGLASS; 00165 zzzCalcStartCursorHide(NULL, 0); 00166 } 00167 00168 /* 00169 * Found it. Set the console bit and reset the wait event so any sleepers 00170 * wake up. 00171 */ 00172 W32Process->W32PF_Flags |= W32PF_CONSOLEAPPLICATION; 00173 SET_PSEUDO_EVENT(&W32Process->InputIdleEvent); 00174 } 00175 } else if (!(W32Process->W32PF_Flags & W32PF_INITIALIZED)) { 00176 W32Process->W32PF_Flags |= W32PF_INITIALIZED; 00177 00178 /* 00179 * Set global state to allow the new process to become 00180 * foreground. xxxInitProcessInfo() will set 00181 * W32PF_ALLOWFOREGROUNDACTIVATE when the process initializes. 00182 */ 00183 SET_PUDF(PUDF_ALLOWFOREGROUNDACTIVATE); 00184 TAGMSG1(DBGTAG_FOREGROUND, "xxxSetProcessInitState set PUDF. %#p", W32Process); 00185 00186 00187 /* 00188 * If this is the win32 server process, force off start glass feedback 00189 */ 00190 if (Process == gpepCSRSS) { 00191 dwFlags |= STARTF_FORCEOFFFEEDBACK; 00192 } 00193 00194 /* 00195 * Show the app start cursor for 2 seconds if it was requested from 00196 * the application. 00197 */ 00198 if (dwFlags & STARTF_FORCEOFFFEEDBACK) { 00199 W32Process->W32PF_Flags |= W32PF_FORCEOFFFEEDBACK; 00200 zzzCalcStartCursorHide(NULL, 0); 00201 } else if (dwFlags & STARTF_FORCEONFEEDBACK) { 00202 zzzCalcStartCursorHide(W32Process, 2000); 00203 } 00204 } 00205 /* 00206 * Have to defer without processing, because we don't have a ptiCurrent yet 00207 */ 00208 EndDeferWinEventNotifyWithoutProcessing(); 00209 return TRUE; 00210 }

BOOL xxxSleepThread UINT  fsWakeMask,
DWORD  Timeout,
BOOL  fInputIdle
 

Definition at line 4382 of file queue.c.

References BOOL, CheckCritIn, CheckForClientDeath, CheckProcessForeground(), ClearQueueServerEvent(), ClientDeliverUserApc(), _CLIENTINFO::cSpins, tagPROCESSINFO::cSysExpunge, tagPROCESSINFO::dwhmodLibLoadedMask, EnterCrit, FALSE, tagPOWERSTATE::fCritical, tagCLIENTTHREADINFO::fsChangeBits, tagTHREADINFO::fsChangeBitsRemoved, tagCLIENTTHREADINFO::fsWakeBits, tagCLIENTTHREADINFO::fsWakeMask, gcSysExpunge, gdwSysExpungeMask, gPowerState, gptiForeground, IsHooked, IsWinEventNotifyDeferredOK, KeWaitForSingleObject(), LeaveCrit, NTSTATUS(), NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::pcti, tagPOWERSTATE::pEvent, tagTHREADINFO::pEventQueueServer, tagTHREADINFO::ppi, PtiCurrent, SET_TIME_LAST_READ, SleepInputIdle(), TIF_16BIT, tagTHREADINFO::TIF_flags, TIF_SPINNING, TRUE, UserMode, WHF_FOREGROUNDIDLE, WrUserRequest, xxxCallHook(), xxxDoSysExpunge(), xxxReceiveMessages, xxxSleepTask(), and zzzWakeInputIdle().

Referenced by xxxbFullscreenSwitch(), xxxDefWindowProc(), xxxDragObject(), xxxInternalGetMessage(), xxxInterSendMsgEx(), xxxIsDragging(), xxxMNLoop(), xxxTrackCaptionButton(), and xxxWaitMessage().

04386 { 04387 PTHREADINFO ptiCurrent; 04388 LARGE_INTEGER li, *pli; 04389 NTSTATUS status = STATUS_SUCCESS; 04390 BOOL fExclusive = fsWakeMask & QS_EXCLUSIVE; 04391 WORD fsWakeMaskSaved; 04392 04393 UserAssert(IsWinEventNotifyDeferredOK()); 04394 04395 if (fExclusive) { 04396 /* 04397 * the exclusive bit is a 'dummy' arg, turn it off to 04398 * avoid any possible conflictions 04399 */ 04400 fsWakeMask = fsWakeMask & ~QS_EXCLUSIVE; 04401 } 04402 04403 if (Timeout) { 04404 /* 04405 * Convert dwMilliseconds to a relative-time(i.e. negative) 04406 * LARGE_INTEGER. NT Base calls take time values in 100 nanosecond 04407 * units. 04408 */ 04409 li.QuadPart = Int32x32To64(-10000, Timeout); 04410 pli = &li; 04411 } else 04412 pli = NULL; 04413 04414 CheckCritIn(); 04415 04416 ptiCurrent = PtiCurrent(); 04417 04418 fsWakeMaskSaved = ptiCurrent->pcti->fsWakeMask; 04419 04420 while (TRUE) { 04421 04422 /* 04423 * First check if the input has arrived. 04424 */ 04425 if (ptiCurrent->pcti->fsChangeBits & fsWakeMask) { 04426 /* 04427 * Restore the wake mask to what it was before we went to sleep 04428 * to allow possible callbacks before KeWait... but after the mask 04429 * has been set and also APCs from KeWait... to still be able to 04430 * wake up. Simply clearing the mask here if we're in such a 04431 * callback or in an APC means that the thread will never wake up. 04432 */ 04433 ptiCurrent->pcti->fsWakeMask = fsWakeMaskSaved; 04434 04435 /* 04436 * Update timeLastRead - it is used for hung app calculations. 04437 * If the thread is waking up to process input, it isn't hung! 04438 */ 04439 SET_TIME_LAST_READ(ptiCurrent); 04440 return TRUE; 04441 } 04442 04443 /* 04444 * Next check for SendMessages 04445 */ 04446 if (!fExclusive && ptiCurrent->pcti->fsWakeBits & QS_SENDMESSAGE) { 04447 xxxReceiveMessages(ptiCurrent); 04448 04449 /* 04450 * Restore the change bits we took out in PeekMessage() 04451 */ 04452 ptiCurrent->pcti->fsChangeBits |= (ptiCurrent->pcti->fsWakeBits & ptiCurrent->fsChangeBitsRemoved); 04453 ptiCurrent->fsChangeBitsRemoved = 0; 04454 } 04455 04456 /* 04457 * Check to see if some resources need expunging. 04458 * This will unload Hook DLLs, including WinEvent ones 04459 */ 04460 if (ptiCurrent->ppi->cSysExpunge != gcSysExpunge) { 04461 ptiCurrent->ppi->cSysExpunge = gcSysExpunge; 04462 if (ptiCurrent->ppi->dwhmodLibLoadedMask & gdwSysExpungeMask) 04463 xxxDoSysExpunge(ptiCurrent); 04464 } 04465 04466 /* 04467 * OR QS_SENDMESSAGE in since ReceiveMessage() will end up 04468 * trashing pq->fsWakeMask. Do the same for QS_SYSEXPUNGE. 04469 */ 04470 ClearQueueServerEvent((WORD)(fsWakeMask | (fExclusive ? 0 : QS_SENDMESSAGE))); 04471 04472 /* 04473 * If we have timed out then return our error to the caller. 04474 */ 04475 if (status == STATUS_TIMEOUT) { 04476 RIPERR1(ERROR_TIMEOUT, RIP_VERBOSE, "SleepThread: The timeout has expired %lX", Timeout); 04477 return FALSE; 04478 } 04479 04480 /* 04481 * Because we do a non-alertable wait, we know that a status 04482 * of STATUS_USER_APC means that the thread was terminated. 04483 * If we have terminated, get back to user mode. 04484 */ 04485 if (status == STATUS_USER_APC) { 04486 ClientDeliverUserApc(); 04487 return FALSE; 04488 } 04489 04490 /* 04491 * If this is the power state callout thread, we might need to bail 04492 * out early. 04493 */ 04494 if (gPowerState.pEvent == ptiCurrent->pEventQueueServer) { 04495 if (gPowerState.fCritical) { 04496 return FALSE; 04497 } 04498 } 04499 04500 UserAssert(status == STATUS_SUCCESS); 04501 /* 04502 * Check to see if any input came inbetween when we 04503 * last checked and the NtClearEvent() call. 04504 * 04505 * We call NtWaitForSingleObject() rather than 04506 * WaitForSingleObject() so we can set fAlertable 04507 * to TRUE and thus allow timer APCs to be processed. 04508 */ 04509 if (!(ptiCurrent->pcti->fsChangeBits & ptiCurrent->pcti->fsWakeMask)) { 04510 /* 04511 * This app is going idle. Clear the spin count check to see 04512 * if we need to make this process foreground again. 04513 */ 04514 if (fInputIdle) { 04515 if (ptiCurrent->TIF_flags & TIF_SPINNING) { 04516 CheckProcessForeground(ptiCurrent); 04517 } 04518 ptiCurrent->pClientInfo->cSpins = 0; 04519 } 04520 04521 04522 if (!(ptiCurrent->TIF_flags & TIF_16BIT)) { 04523 if (fInputIdle && ptiCurrent == gptiForeground && 04524 IsHooked(ptiCurrent, WHF_FOREGROUNDIDLE)) { 04525 xxxCallHook(HC_ACTION, 0, 0, WH_FOREGROUNDIDLE); 04526 } 04527 04528 CheckForClientDeath(); 04529 04530 /* 04531 * Set the input idle event to wake up any threads waiting 04532 * for this thread to go into idle state. 04533 */ 04534 if (fInputIdle) 04535 zzzWakeInputIdle(ptiCurrent); 04536 04537 xxxSleepTask(fInputIdle, NULL); 04538 04539 LeaveCrit(); 04540 status = KeWaitForSingleObject(ptiCurrent->pEventQueueServer, 04541 WrUserRequest, UserMode, FALSE, pli); 04542 CheckForClientDeath(); 04543 EnterCrit(); 04544 04545 /* 04546 * Reset the input idle event to block and threads waiting 04547 * for this thread to go into idle state. 04548 */ 04549 SleepInputIdle(ptiCurrent); 04550 04551 /* 04552 * ptiCurrent is 16bit! 04553 */ 04554 } else { 04555 if (fInputIdle) 04556 zzzWakeInputIdle(ptiCurrent); 04557 04558 xxxSleepTask(fInputIdle, NULL); 04559 } 04560 } 04561 } 04562 }

void xxxUserNotifyConsoleApplication PCONSOLE_PROCESS_INFO  pcpi  ) 
 

Definition at line 341 of file queue.c.

References BOOL, CheckAllowForeground(), EnterCrit, LeaveCrit, LockProcessByClientId(), NT_SUCCESS, NTSTATUS(), PpiCurrent, PpiFromProcess, PUDF_ALLOWFOREGROUNDACTIVATE, SET_PUDF, SetAppStarting(), Status, UnlockProcess, and xxxSetProcessInitState().

Referenced by xxxConsoleControl().

00343 { 00344 NTSTATUS Status; 00345 PEPROCESS Process; 00346 BOOL retval; 00347 00348 /* 00349 * First search for this process in our process information list. 00350 */ 00351 LeaveCrit(); 00352 Status = LockProcessByClientId((HANDLE)LongToHandle( pcpi->dwProcessID ), &Process); 00353 EnterCrit(); 00354 00355 if (!NT_SUCCESS(Status)) { 00356 RIPMSG2(RIP_WARNING, "xxxUserNotifyConsoleApplication: Failed with Process ID == %X, Status = %x\n", 00357 pcpi->dwProcessID, Status); 00358 return; 00359 } 00360 00361 retval = xxxSetProcessInitState(Process, 0); 00362 /* 00363 * Bug 273518 - joejo 00364 * 00365 * This will allow console windows to set foreground correctly on new 00366 * process' it launches, as opposed it just forcing foreground. 00367 */ 00368 if (retval) { 00369 if (pcpi->dwFlags & CPI_NEWPROCESSWINDOW) { 00370 PPROCESSINFO ppiCurrent = PpiCurrent(); 00371 if (CheckAllowForeground(Process)) { 00372 if (!(ppiCurrent->W32PF_Flags & W32PF_APPSTARTING)) { 00373 SetAppStarting(ppiCurrent); 00374 } 00375 SET_PUDF(PUDF_ALLOWFOREGROUNDACTIVATE); 00376 TAGMSG0(DBGTAG_FOREGROUND, "xxxUserNotifyConsoleApplication set PUDF"); 00377 ppiCurrent->W32PF_Flags |= W32PF_ALLOWFOREGROUNDACTIVATE; 00378 } 00379 00380 TAGMSG3(DBGTAG_FOREGROUND, "xxxUserNotifyConsoleApplication %s W32PF %#p-%#p", 00381 ((ppiCurrent->W32PF_Flags & W32PF_ALLOWFOREGROUNDACTIVATE) ? "set" : "NOT"), 00382 ppiCurrent, PpiFromProcess(Process)); 00383 } 00384 } else { 00385 RIPMSG1(RIP_WARNING, "xxxUserNotifyConsoleApplication - SetProcessInitState failed on %#p", Process); 00386 } 00387 00388 00389 00390 UnlockProcess(Process); 00391 }

BOOL xxxUserNotifyProcessCreate DWORD  idProcess,
DWORD  idParentThread,
ULONG_PTR  dwData,
DWORD  dwFlags
 

Definition at line 445 of file queue.c.

References BOOL, CheckCritIn, _ETHREAD::Cid, dwFlags, EnterCrit, FALSE, GiveForegroundActivateRight(), gpwtiFirst, tagWOWTHREADINFO::idParentProcess, tagWOWTHREADINFO::idTask, tagWOWTHREADINFO::idWaitObject, INIT_PSEUDO_EVENT, LeaveCrit, LockProcessByClientId(), LockThreadByClientId(), NT_SUCCESS, NTSTATUS(), NULL, tagWOWTHREADINFO::pIdleEvent, PtiFromThread, tagWOWTHREADINFO::pwtiNext, RESET_PSEUDO_EVENT, Status, TIF_16BIT, TIF_ALLOWFOREGROUNDACTIVATE, tagTHREADINFO::TIF_flags, TRUE, UnlockProcess, UnlockThread, _EPROCESS::Win32Process, WOWTHREADINFO, and xxxSetProcessInitState().

Referenced by NtUserNotifyProcessCreate().

00450 { 00451 PEPROCESS Process; 00452 PETHREAD Thread; 00453 PTHREADINFO pti; 00454 NTSTATUS Status; 00455 BOOL retval; 00456 00457 CheckCritIn(); 00458 00459 00460 GiveForegroundActivateRight((HANDLE)idProcess); 00461 00462 /* 00463 * 0x1 bit means give feedback (app start cursor). 00464 * 0x2 bit means this is a gui app (meaning, call CreateProcessInfo() 00465 * so we get app start synchronization (WaitForInputIdle()). 00466 * 0x8 bit means this process is a WOW process, set W32PF_WOW. 0x1 00467 * and 0x2 bits will also be set. 00468 * 0x4 value means this is really a shared WOW task starting 00469 */ 00470 00471 /* 00472 * If we want feedback, we need to create a process info structure, 00473 * so do it: it will be properly cleaned up. 00474 */ 00475 if ((dwFlags & 0xb) != 0) { 00476 LeaveCrit(); 00477 Status = LockProcessByClientId((HANDLE)LongToHandle( idProcess ), &Process); 00478 EnterCrit(); 00479 00480 if (!NT_SUCCESS(Status)) { 00481 RIPMSG2(RIP_WARNING, "xxxUserNotifyProcessCreate: Failed with Process ID == %X, Status = %x\n", 00482 idProcess, Status); 00483 return FALSE; 00484 } 00485 00486 retval = xxxSetProcessInitState(Process, ((dwFlags & 1) ? STARTF_FORCEONFEEDBACK : STARTF_FORCEOFFFEEDBACK)); 00487 if (!retval) { 00488 RIPMSG1(RIP_WARNING, "xxxUserNotifyProcessCreate - SetProcessInitState failed on %#p", Process); 00489 } 00490 if (dwFlags & 0x8) { 00491 if (Process->Win32Process) 00492 ((PW32PROCESS)Process->Win32Process)->W32PF_Flags |= W32PF_WOW; 00493 } 00494 00495 UnlockProcess(Process); 00496 00497 /* 00498 * Find out who is starting this app. If it is a 16 bit app, allow 00499 * it to bring itself back to the foreground if it calls 00500 * SetActiveWindow() or SetFocus(). This is because this could be 00501 * related to OLE to DDE activation. Notes has a case where after it 00502 * lauches pbrush to edit an embedded bitmap, it brings up a message 00503 * box on top if the bitmap is read only. This message box won't appear 00504 * foreground unless we allow it to. This usually isn't a problem 00505 * because most apps don't bring up windows on top of editors 00506 * like this. 32 bit apps will call SetForegroundWindow(). 00507 */ 00508 00509 LeaveCrit(); 00510 Status = LockThreadByClientId((HANDLE)LongToHandle( idParentThread ), &Thread); 00511 EnterCrit(); 00512 00513 if (!NT_SUCCESS(Status)) { 00514 RIPMSG2(RIP_WARNING, "xxxUserNotifyProcessCreate: Failed with Thread ID == %X, Status = %x\n", 00515 idParentThread, Status); 00516 return FALSE; 00517 } 00518 00519 pti = PtiFromThread(Thread); 00520 if (pti && (pti->TIF_flags & TIF_16BIT)) { 00521 pti->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 00522 TAGMSG1(DBGTAG_FOREGROUND, "xxxUserNotifyProcessCreate set TIF %#p", pti); 00523 } 00524 00525 UnlockThread(Thread); 00526 00527 } else if (dwFlags == 4) { 00528 /* 00529 * A WOW task is starting up. Create the WOW per thread info 00530 * structure here in case someone calls WaitForInputIdle 00531 * before the thread is created. 00532 */ 00533 PWOWTHREADINFO pwti; 00534 00535 /* 00536 * Look for a matching thread in the WOW thread info list. 00537 */ 00538 for (pwti = gpwtiFirst; pwti != NULL; pwti = pwti->pwtiNext) { 00539 if (pwti->idTask == idProcess) { 00540 break; 00541 } 00542 } 00543 00544 /* 00545 * If we didn't find one, allocate a new one and add it to 00546 * the head of the list. 00547 */ 00548 if (pwti == NULL) { 00549 pwti = (PWOWTHREADINFO)UserAllocPoolWithQuota( 00550 sizeof(WOWTHREADINFO), TAG_WOWTHREADINFO); 00551 if (pwti == NULL) { 00552 return FALSE; 00553 } 00554 INIT_PSEUDO_EVENT(&pwti->pIdleEvent); 00555 pwti->idTask = idProcess; 00556 pwti->pwtiNext = gpwtiFirst; 00557 gpwtiFirst = pwti; 00558 } else { 00559 RESET_PSEUDO_EVENT(&pwti->pIdleEvent); 00560 } 00561 00562 pwti->idWaitObject = dwData; 00563 LeaveCrit(); 00564 Status = LockThreadByClientId((HANDLE)LongToHandle( idParentThread ), &Thread); 00565 EnterCrit(); 00566 if (!NT_SUCCESS(Status)) 00567 return FALSE; 00568 00569 if (!NT_SUCCESS(Status)) { 00570 RIPMSG2(RIP_WARNING, "xxxUserNotifyProcessCreate: Failed with Thread ID == %X, Status = %x\n", 00571 idParentThread, Status); 00572 return FALSE; 00573 } 00574 00575 pwti->idParentProcess = HandleToUlong(Thread->Cid.UniqueProcess); 00576 UnlockThread(Thread); 00577 } 00578 00579 return TRUE; 00580 }

DWORD xxxWaitForInputIdle ULONG_PTR  idProcess,
DWORD  dwMilliseconds,
BOOL  fSharedWow
 

Definition at line 5310 of file queue.c.

References CheckForClientDeath, DWORD, EnterCrit, _EPROCESS::ExitProcessCalled, gpwtiFirst, tagWOWTHREADINFO::idParentProcess, tagWOWTHREADINFO::idWaitObject, LeaveCrit, LockProcessByClientId(), NT_SUCCESS, NTSTATUS(), NULL, tagWOWTHREADINFO::pIdleEvent, tagTHREADINFO::ppi, PtiCurrent, tagPROCESSINFO::ptiList, tagPROCESSINFO::ptiMainThread, tagTHREADINFO::ptiSibling, tagWOWTHREADINFO::pwtiNext, Status, tagTHREADINFO::TIF_flags, TIF_SYSTEMTHREAD, TIF_WAITFORINPUTIDLE, UnlockProcess, WaitOnPseudoEvent(), _EPROCESS::Win32Process, and xxxPollAndWaitForSingleObject().

Referenced by NtUserWaitForInputIdle().

05314 { 05315 PTHREADINFO ptiCurrent; 05316 PTHREADINFO pti; 05317 PEPROCESS Process; 05318 PW32PROCESS W32Process; 05319 PPROCESSINFO ppi; 05320 DWORD dwResult; 05321 NTSTATUS Status; 05322 TL tlProcess; 05323 05324 ptiCurrent = PtiCurrent(); 05325 05326 /* 05327 * If fSharedWow is set, the client passed in a fake process 05328 * handle which CreateProcess returns for Win16 apps started 05329 * in the shared WOW VDM. 05330 * 05331 * CreateProcess returns a real process handle when you start 05332 * a Win16 app in a separate WOW VDM. 05333 */ 05334 05335 if (fSharedWow) { // Waiting for a WOW task to go idle. 05336 PWOWTHREADINFO pwti; 05337 05338 05339 /* 05340 * Look for a matching thread in the WOW thread info list. 05341 */ 05342 for (pwti = gpwtiFirst; pwti != NULL; pwti = pwti->pwtiNext) { 05343 if (pwti->idParentProcess == HandleToUlong(ptiCurrent->pEThread->Cid.UniqueProcess) && 05344 pwti->idWaitObject == idProcess) { 05345 break; 05346 } 05347 } 05348 05349 /* 05350 * If we couldn't find the right thread, bail out. 05351 */ 05352 if (pwti == NULL) { 05353 RIPMSG0(RIP_WARNING, "WaitForInputIdle couldn't find 16-bit task\n"); 05354 return (DWORD)-1; 05355 } 05356 05357 /* 05358 * Now wait for it to go idle and return. 05359 */ 05360 dwResult = WaitOnPseudoEvent(&pwti->pIdleEvent, dwMilliseconds); 05361 if (dwResult == STATUS_ABANDONED) { 05362 dwResult = xxxPollAndWaitForSingleObject(pwti->pIdleEvent, 05363 NULL, 05364 dwMilliseconds); 05365 } 05366 return dwResult; 05367 05368 } 05369 05370 /* 05371 * We shouldn't get here for system threads. 05372 */ 05373 UserAssert(!(ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD)); 05374 05375 /* 05376 * If the app is waiting for itself to go idle, error. 05377 */ 05378 if (ptiCurrent->pEThread->Cid.UniqueProcess == (HANDLE)idProcess && 05379 ptiCurrent == ptiCurrent->ppi->ptiMainThread) { 05380 RIPMSG0(RIP_WARNING, "WaitForInputIdle waiting on self\n"); 05381 return (DWORD)-1; 05382 } 05383 05384 /* 05385 * Now find the ppi structure for this process. 05386 */ 05387 LeaveCrit(); 05388 Status = LockProcessByClientId((HANDLE)idProcess, &Process); 05389 EnterCrit(); 05390 05391 if (!NT_SUCCESS(Status)) 05392 return (DWORD)-1; 05393 05394 if (Process->ExitProcessCalled) { 05395 UnlockProcess(Process); 05396 return (DWORD)-1; 05397 } 05398 05399 W32Process = (PW32PROCESS)Process->Win32Process; 05400 05401 /* 05402 * Couldn't find that process info structure.... return error. 05403 */ 05404 if (W32Process == NULL) { 05405 RIPMSG0(RIP_WARNING, "WaitForInputIdle process not GUI process\n"); 05406 UnlockProcess(Process); 05407 return (DWORD)-1; 05408 } 05409 05410 05411 ppi = (PPROCESSINFO)W32Process; 05412 05413 /* 05414 * If this is a console application, don't wait on it. 05415 */ 05416 if (W32Process->W32PF_Flags & W32PF_CONSOLEAPPLICATION) { 05417 RIPMSG0(RIP_WARNING, "WaitForInputIdle process is console process\n"); 05418 UnlockProcess(Process); 05419 return (DWORD)-1; 05420 } 05421 05422 /* 05423 * Wait on this event for the passed in time limit. 05424 */ 05425 CheckForClientDeath(); 05426 05427 /* 05428 * We have to wait mark the Process as one which others are waiting on 05429 */ 05430 ppi->W32PF_Flags |= W32PF_WAITFORINPUTIDLE; 05431 for (pti = ppi->ptiList; pti != NULL; pti = pti->ptiSibling) { 05432 pti->TIF_flags |= TIF_WAITFORINPUTIDLE; 05433 } 05434 05435 /* 05436 * Thread lock the process to ensure that it will be dereferenced 05437 * if the thread exits. 05438 */ 05439 LockW32Process(W32Process, &tlProcess); 05440 UnlockProcess(Process); 05441 05442 dwResult = WaitOnPseudoEvent(&W32Process->InputIdleEvent, dwMilliseconds); 05443 if (dwResult == STATUS_ABANDONED) { 05444 dwResult = xxxPollAndWaitForSingleObject(W32Process->InputIdleEvent, 05445 Process, 05446 dwMilliseconds); 05447 } 05448 05449 /* 05450 * Clear all thread TIF_WAIT bits from the process. 05451 */ 05452 ppi->W32PF_Flags &= ~W32PF_WAITFORINPUTIDLE; 05453 for (pti = ppi->ptiList; pti != NULL; pti = pti->ptiSibling) { 05454 pti->TIF_flags &= ~TIF_WAITFORINPUTIDLE; 05455 } 05456 05457 UnlockW32Process(&tlProcess); 05458 05459 return dwResult; 05460 }

void zzzCalcStartCursorHide PW32PROCESS  pwp,
DWORD  timeAdd
 

Definition at line 591 of file queue.c.

References ComputeTickDelta(), DWORD, gpwpCalcFirst, gtimeStartCursorHide, NtGetTickCount(), NULL, and zzzUpdateCursorImage().

Referenced by DestroyProcessInfo(), xxxCreateThreadInfo(), xxxHungAppDemon(), xxxInternalGetMessage(), xxxSetProcessInitState(), zzzChangeStates(), zzzInitTask(), zzzShowStartGlass(), and zzzWakeInputIdle().

00594 { 00595 DWORD timeNow; 00596 PW32PROCESS pwpT; 00597 PW32PROCESS *ppwpT; 00598 00599 00600 timeNow = NtGetTickCount(); 00601 00602 if (pwp != NULL) { 00603 00604 /* 00605 * We were passed in a timeout. Recalculate when we timeout 00606 * and add the pwp to the starting list. 00607 */ 00608 if (!(pwp->W32PF_Flags & W32PF_STARTGLASS)) { 00609 00610 /* 00611 * Add it to the list only if it is not already in the list 00612 */ 00613 for (pwpT = gpwpCalcFirst; pwpT != NULL; pwpT = pwpT->NextStart) { 00614 if (pwpT == pwp) 00615 break; 00616 } 00617 00618 if (pwpT != pwp) { 00619 pwp->NextStart = gpwpCalcFirst; 00620 gpwpCalcFirst = pwp; 00621 } 00622 } 00623 pwp->StartCursorHideTime = timeAdd + timeNow; 00624 pwp->W32PF_Flags |= W32PF_STARTGLASS; 00625 } 00626 00627 gtimeStartCursorHide = 0; 00628 for (ppwpT = &gpwpCalcFirst; (pwpT = *ppwpT) != NULL; ) { 00629 00630 /* 00631 * If the app isn't starting or feedback is forced off, remove 00632 * it from the list so we don't look at it again. 00633 */ 00634 if (!(pwpT->W32PF_Flags & W32PF_STARTGLASS) || 00635 (pwpT->W32PF_Flags & W32PF_FORCEOFFFEEDBACK)) { 00636 *ppwpT = pwpT->NextStart; 00637 continue; 00638 } 00639 00640 /* 00641 * Find the greatest hide cursor timeout value. 00642 */ 00643 if (gtimeStartCursorHide < pwpT->StartCursorHideTime) 00644 gtimeStartCursorHide = pwpT->StartCursorHideTime; 00645 00646 /* 00647 * If this app has timed out, it isn't starting anymore! 00648 * Remove it from the list. 00649 */ 00650 if (ComputeTickDelta(timeNow, pwpT->StartCursorHideTime) > 0) { 00651 pwpT->W32PF_Flags &= ~W32PF_STARTGLASS; 00652 *ppwpT = pwpT->NextStart; 00653 continue; 00654 } 00655 00656 /* 00657 * Step to the next pwp in the list. 00658 */ 00659 ppwpT = &pwpT->NextStart; 00660 } 00661 00662 /* 00663 * If the hide time is still less than the current time, then turn off 00664 * the app starting cursor. 00665 */ 00666 if (gtimeStartCursorHide <= timeNow) 00667 gtimeStartCursorHide = 0; 00668 00669 /* 00670 * Update the cursor image with the new info (doesn't do anything unless 00671 * the cursor is really changing). 00672 */ 00673 zzzUpdateCursorImage(); 00674 }

void zzzDestroyQueue PQ  pq,
PTHREADINFO  pti
 

Definition at line 2211 of file queue.c.

References BOOL, tagQ::caret, CheckSysLock, tagQ::cLockCount, tagQ::cThreads, DebugValidateMLIST, FALSE, FreeMessageList(), FreeQueue(), tagCLIENTTHREADINFO::fsWakeBits, gpqCursor, gpqForeground, gpqForegroundPrev, LockQCursor, tagQ::mlInput, NULL, tagTHREADINFO::pcti, tagTHREADINFO::pq, tagQ::ptiKeyboard, tagDESKTOP::PtiList, tagQ::ptiMouse, tagQ::ptiSysLock, tagQ::QF_flags, QF_INDESTROY, tagTHREADINFO::rpdesk, SetWakeBit(), tagCARET::spwnd, tagQ::spwndActive, tagQ::spwndActivePrev, tagQ::spwndFocus, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, TRUE, Unlock, UnlockCaptureWindow(), USHORT, and zzzSetFMouseMoved().

Referenced by xxxDesktopThread(), xxxDestroyThreadInfo(), zzzAddAttachment(), zzzAttachToQueue(), and zzzReattachThreads().

02214 { 02215 PTHREADINFO ptiT; 02216 PTHREADINFO ptiAny, ptiBestMouse, ptiBestKey; 02217 PLIST_ENTRY pHead, pEntry; 02218 02219 #if DBG 02220 USHORT cDying = 0; 02221 #endif 02222 02223 BOOL fSetFMouseMoved = FALSE; 02224 02225 DebugValidateMLIST(&pq->mlInput); 02226 02227 UserAssert(pq->cThreads); 02228 pq->cThreads--; 02229 02230 if (pq->cThreads != 0) { 02231 02232 /* 02233 * Since we aren't going to destroy this queue, make sure 02234 * it isn't pointing to the THREADINFO that's going away. 02235 */ 02236 if (pq->ptiSysLock == pti) { 02237 CheckSysLock(6, pq, NULL); 02238 pq->ptiSysLock = NULL; 02239 } 02240 02241 if ((pq->ptiKeyboard == pti) || (pq->ptiMouse == pti)) { 02242 02243 /* 02244 * Run through THREADINFOs looking for one pointing to pq. 02245 */ 02246 ptiAny = NULL; 02247 ptiBestMouse = NULL; 02248 ptiBestKey = NULL; 02249 02250 pHead = &pti->rpdesk->PtiList; 02251 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 02252 ptiT = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 02253 02254 /* 02255 * Skip threads that are going away or belong to a 02256 * different queue. 02257 */ 02258 if ((ptiT->TIF_flags & TIF_INCLEANUP) || (ptiT->pq != pq)) { 02259 #if DBG 02260 if (ptiT->pq == pq && (ptiT->TIF_flags & TIF_INCLEANUP)) 02261 cDying++; 02262 #endif 02263 continue; 02264 } 02265 02266 ptiAny = ptiT; 02267 02268 if (pti->pcti->fsWakeBits & QS_MOUSE) { 02269 if (ptiT->pcti->fsWakeMask & QS_MOUSE) 02270 ptiBestMouse = ptiT; 02271 } 02272 02273 if (pti->pcti->fsWakeBits & QS_KEY) { 02274 if (ptiT->pcti->fsWakeMask & QS_KEY) 02275 ptiBestKey = ptiT; 02276 } 02277 } 02278 02279 if (ptiBestMouse == NULL) 02280 ptiBestMouse = ptiAny; 02281 if (ptiBestKey == NULL) 02282 ptiBestKey = ptiAny; 02283 02284 /* 02285 * Transfer any wake-bits to this new queue. This 02286 * is a common problem for QS_MOUSEMOVE which doesn't 02287 * get set on coalesced WM_MOUSEMOVE events, so we 02288 * need to make sure the new thread tries to process 02289 * any input waiting in the queue. 02290 */ 02291 if (ptiBestMouse != NULL) 02292 SetWakeBit(ptiBestMouse, pti->pcti->fsWakeBits & QS_MOUSE); 02293 if (ptiBestKey != NULL) 02294 SetWakeBit(ptiBestKey, pti->pcti->fsWakeBits & QS_KEY); 02295 02296 if (pq->ptiKeyboard == pti) 02297 pq->ptiKeyboard = ptiBestKey; 02298 02299 if (pq->ptiMouse == pti) 02300 pq->ptiMouse = ptiBestMouse; 02301 02302 #if DBG 02303 /* 02304 * Bad things happen if ptiKeyboard or ptiMouse are NULL 02305 */ 02306 if (pq->cThreads != cDying && (pq->ptiKeyboard == NULL || pq->ptiMouse == NULL)) { 02307 RIPMSG6(RIP_ERROR, 02308 "pq %#p pq->cThreads %x cDying %x pti %#p ptiK %#p ptiM %#p", 02309 pq, pq->cThreads, cDying, pti, pq->ptiKeyboard, pq->ptiMouse); 02310 } 02311 #endif 02312 } 02313 02314 return; 02315 } 02316 02317 /* 02318 * Unlock any potentially locked globals now that we know absolutely 02319 * that this queue is going away. 02320 */ 02321 UnlockCaptureWindow(pq); 02322 Unlock(&pq->spwndFocus); 02323 Unlock(&pq->spwndActive); 02324 Unlock(&pq->spwndActivePrev); 02325 Unlock(&pq->caret.spwnd); 02326 LockQCursor(pq, NULL); 02327 02328 #if DBG 02329 /* 02330 * Mark this queue as being in the destruction process. This is 02331 * cleared in FreeQueue() once we have determined it's safe to 02332 * place in the free-list, or destroy the handle. We use this 02333 * to track cases where someone will lock a cursor into the queue 02334 * while it's in the middle of being destroyed. 02335 */ 02336 pq->QF_flags |= QF_INDESTROY; 02337 #endif 02338 02339 /* 02340 * Free everything else that was allocated/created by AllocQueue. 02341 */ 02342 FreeMessageList(&pq->mlInput); 02343 02344 /* 02345 * If this queue is in the foreground, set gpqForeground 02346 * to NULL so no input is routed. At some point we'll want 02347 * to do slightly more clever assignment of gpqForeground here. 02348 */ 02349 if (gpqForeground == pq) { 02350 gpqForeground = NULL; 02351 } 02352 02353 if (gpqForegroundPrev == pq) { 02354 gpqForegroundPrev = NULL; 02355 } 02356 02357 if (gpqCursor == pq) { 02358 gpqCursor = NULL; 02359 fSetFMouseMoved = TRUE; 02360 } 02361 02362 if (pq->cLockCount == 0) { 02363 FreeQueue(pq); 02364 } 02365 02366 if (fSetFMouseMoved) { 02367 zzzSetFMouseMoved(); 02368 } 02369 02370 }

NTSTATUS zzzInitTask UINT  dwExpWinVer,
DWORD  dwAppCompatFlags,
PUNICODE_STRING  pstrModName,
PUNICODE_STRING  pstrBaseFileName,
DWORD  hTaskWow,
DWORD  dwHotkey,
DWORD  idTask,
DWORD  dwX,
DWORD  dwY,
DWORD  dwXSize,
DWORD  dwYSize
 

Definition at line 1147 of file queue.c.

References tagUSERSTARTUPINFO::cb, CW2_USEDEFAULT, DeferWinEventNotify, tagTHREADINFO::dwCompatFlags, _CLIENTINFO::dwCompatFlags, tagTHREADINFO::dwExpWinVer, _CLIENTINFO::dwExpWinVer, tagUSERSTARTUPINFO::dwFlags, tagPROCESSINFO::dwHotkey, DWORD, _CLIENTINFO::dwTIFlags, tagUSERSTARTUPINFO::dwX, tagUSERSTARTUPINFO::dwXSize, tagUSERSTARTUPINFO::dwY, tagUSERSTARTUPINFO::dwYSize, EnterWowCritSect(), FALSE, FJOURNALPLAYBACK, FJOURNALRECORD, gpwtiFirst, tagTDB::hTaskWow, tagWOWTHREADINFO::idTask, InsertTask(), tagTDB::nEvents, NORMAL_PRIORITY_TASK, tagTDB::nPriority, NTSTATUS(), NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::ppi, tagTHREADINFO::pstrAppName, tagTHREADINFO::ptdb, tagTDB::ptdbNext, tagTDB::pti, PtiCurrent, tagPROCESSINFO::ptiList, tagTDB::pwti, tagWOWTHREADINFO::pwtiNext, SetAppImeCompatFlags(), SetAppStarting(), TDB, tagTDB::TDB_Flags, TDBF_SETUP, TIF_16BIT, TIF_FIRSTIDLE, tagTHREADINFO::TIF_flags, TIF_SHAREDWOW, tagPROCESSINFO::usi, zzzCalcStartCursorHide(), zzzEndDeferWinEventNotify, zzzReattachThreads(), and zzzShowStartGlass().

Referenced by NtUserInitTask().

01159 { 01160 PTHREADINFO ptiCurrent; 01161 PTDB ptdb; 01162 PPROCESSINFO ppi; 01163 PWOWTHREADINFO pwti; 01164 01165 ptiCurrent = PtiCurrent(); 01166 ppi = ptiCurrent->ppi; 01167 01168 /* 01169 * Set the real name of the module. (Instead of 'NTVDM') 01170 * We've already probed pstrModName->Buffer for Length+sizeof(WCHAR) so 01171 * we can copy the UNICODE_NULL terminator as well. 01172 */ 01173 if (ptiCurrent->pstrAppName != NULL) 01174 UserFreePool(ptiCurrent->pstrAppName); 01175 ptiCurrent->pstrAppName = UserAllocPoolWithQuota(sizeof(UNICODE_STRING) + 01176 pstrModName->Length + sizeof(WCHAR), TAG_TEXT); 01177 if (ptiCurrent->pstrAppName != NULL) { 01178 ptiCurrent->pstrAppName->Buffer = (PWCHAR)(ptiCurrent->pstrAppName + 1); 01179 try { 01180 RtlCopyMemory(ptiCurrent->pstrAppName->Buffer, pstrModName->Buffer, 01181 pstrModName->Length); 01182 ptiCurrent->pstrAppName->Buffer[pstrModName->Length / sizeof(WCHAR)] = 0; 01183 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 01184 UserFreePool(ptiCurrent->pstrAppName); 01185 ptiCurrent->pstrAppName = NULL; 01186 return STATUS_OBJECT_NAME_INVALID; 01187 } 01188 ptiCurrent->pstrAppName->MaximumLength = pstrModName->Length + sizeof(WCHAR); 01189 ptiCurrent->pstrAppName->Length = pstrModName->Length; 01190 } else 01191 return STATUS_OBJECT_NAME_INVALID; 01192 01193 /* 01194 * An app is starting! 01195 */ 01196 if (!(ppi->W32PF_Flags & W32PF_APPSTARTING)) { 01197 SetAppStarting(ppi); 01198 } 01199 01200 /* 01201 * We never want to use the ShowWindow defaulting mechanism for WOW 01202 * apps. If STARTF_USESHOWWINDOW was set in the client-side 01203 * STARTUPINFO structure, WOW has already picked it up and used 01204 * it for the first (command-line) app. 01205 */ 01206 ppi->usi.dwFlags &= ~STARTF_USESHOWWINDOW; 01207 01208 /* 01209 * If WOW passed us a hotkey for this app, save it for CreateWindow's use. 01210 */ 01211 if (dwHotkey != 0) { 01212 ppi->dwHotkey = dwHotkey; 01213 } 01214 01215 /* 01216 * If WOW passed us a non-default window position use it, otherwise clear it. 01217 */ 01218 ppi->usi.cb = sizeof(ppi->usi); 01219 01220 if (dwX == CW_USEDEFAULT || dwX == CW2_USEDEFAULT) { 01221 ppi->usi.dwFlags &= ~STARTF_USEPOSITION; 01222 } else { 01223 ppi->usi.dwFlags |= STARTF_USEPOSITION; 01224 ppi->usi.dwX = dwX; 01225 ppi->usi.dwY = dwY; 01226 } 01227 01228 /* 01229 * If WOW passed us a non-default window size use it, otherwise clear it. 01230 */ 01231 if (dwXSize == CW_USEDEFAULT || dwXSize == CW2_USEDEFAULT) { 01232 ppi->usi.dwFlags &= ~STARTF_USESIZE; 01233 } else { 01234 ppi->usi.dwFlags |= STARTF_USESIZE; 01235 ppi->usi.dwXSize = dwXSize; 01236 ppi->usi.dwYSize = dwYSize; 01237 } 01238 01239 /* 01240 * Alloc and Link in new task into the task list 01241 */ 01242 if ((ptdb = (PTDB)UserAllocPoolWithQuota(sizeof(TDB), TAG_WOWTDB)) == NULL) 01243 return STATUS_NO_MEMORY; 01244 ptiCurrent->ptdb = ptdb; 01245 01246 /* 01247 * Set the flags to say this is a 16-bit thread - before attaching 01248 * queues! 01249 */ 01250 ptiCurrent->TIF_flags |= TIF_16BIT | TIF_FIRSTIDLE; 01251 01252 /* 01253 * If this task is running in the shared WOW VDM, we handle 01254 * WaitForInputIdle a little differently than separate WOW 01255 * VDMs. This is because CreateProcess returns a real process 01256 * handle when you start a separate WOW VDM, so the "normal" 01257 * WaitForInputIdle works. For the shared WOW VDM, CreateProcess 01258 * returns an event handle. 01259 */ 01260 ptdb->pwti = NULL; 01261 if (idTask) { 01262 ptiCurrent->TIF_flags |= TIF_SHAREDWOW; 01263 01264 /* 01265 * Look for a matching thread in the WOW thread info list. 01266 */ 01267 if (idTask != (DWORD)-1) { 01268 for (pwti = gpwtiFirst; pwti != NULL; pwti = pwti->pwtiNext) { 01269 if (pwti->idTask == idTask) { 01270 ptdb->pwti = pwti; 01271 break; 01272 } 01273 } 01274 #if DBG 01275 if (pwti == NULL) { 01276 RIPMSG0(RIP_WARNING, "InitTask couldn't find WOW struct\n"); 01277 } 01278 #endif 01279 } 01280 } 01281 ptiCurrent->pClientInfo->dwTIFlags |= ptiCurrent->TIF_flags; 01282 01283 /* 01284 * We need this thread to share the queue of other win16 apps. 01285 * If we're journalling, all apps are sharing a queue, so we wouldn't 01286 * want to interrupt that - so only cause queue recalculation 01287 * if we aren't journalling. 01288 * ptdb may be freed by DestroyTask during a callback, so defer WinEvent 01289 * notifications until we don't need ptdb any more. 01290 */ 01291 DeferWinEventNotify(); 01292 if (!FJOURNALRECORD() && !FJOURNALPLAYBACK()) 01293 zzzReattachThreads(FALSE); 01294 01295 /* 01296 * Save away the 16 bit task handle: we use this later when calling 01297 * wow back to close a WOW task. 01298 */ 01299 ptdb->hTaskWow = LOWORD(hTaskWow); 01300 01301 /* 01302 * Setup the app start cursor for 5 second timeout. 01303 */ 01304 zzzCalcStartCursorHide((PW32PROCESS)ppi, 5000); 01305 01306 /* 01307 * HIWORD: != 0 if wants proportional font 01308 * LOWORD: Expected windows version (3.00 [300], 3.10 [30A], etc) 01309 */ 01310 ptiCurrent->dwExpWinVer = dwExpWinVer; 01311 ptiCurrent->pClientInfo->dwExpWinVer = dwExpWinVer; 01312 01313 /* 01314 * Mark this guy and add him to the global task list so he can run. 01315 */ 01316 #define NORMAL_PRIORITY_TASK 10 01317 01318 /* 01319 * To be Compatible it super important that the new task run immediately 01320 * Set its priority accordingly. No other task should ever be set to 01321 * CREATION priority 01322 */ 01323 ptdb->nPriority = NORMAL_PRIORITY_TASK; 01324 ptdb->nEvents = 0; 01325 ptdb->pti = ptiCurrent; 01326 ptdb->ptdbNext = NULL; 01327 ptdb->TDB_Flags = 0; 01328 01329 InsertTask(ppi, ptdb); 01330 zzzEndDeferWinEventNotify(); 01331 01332 ptiCurrent->dwCompatFlags = dwAppCompatFlags; 01333 ptiCurrent->pClientInfo->dwCompatFlags = dwAppCompatFlags; 01334 01335 UserAssert(ptiCurrent->ppi->ptiList); 01336 /* 01337 * We haven't captured pstrBaseFileName's buffer, we 01338 * may fault touching it in SetAppImeCompatFlags. If 01339 * so the IME flags have been set already and we 01340 * can safely assume it's not a setup app. 01341 */ 01342 01343 try { 01344 if (SetAppImeCompatFlags(ptiCurrent, ptiCurrent->pstrAppName, 01345 pstrBaseFileName)) { 01346 /* 01347 * Flag task as a setup app. 01348 */ 01349 ptdb->TDB_Flags = TDBF_SETUP; 01350 ppi->W32PF_Flags |= W32PF_SETUPAPP; 01351 } 01352 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 01353 } 01354 01355 /* 01356 * Force this new task to be the active task (WOW will ensure the 01357 * currently running task does a Yield which will put it into the 01358 * non preemptive scheduler. 01359 */ 01360 ppi->pwpi->ptiScheduled = ptiCurrent; 01361 ppi->pwpi->CSLockCount = -1; 01362 01363 EnterWowCritSect(ptiCurrent, ppi->pwpi); 01364 01365 /* 01366 * ensure app gets focus 01367 */ 01368 zzzShowStartGlass(10000); 01369 01370 return STATUS_SUCCESS; 01371 }

void zzzShowStartGlass DWORD  dwTimeout  ) 
 

Definition at line 1382 of file queue.c.

References PpiCurrent, PUDF_ALLOWFOREGROUNDACTIVATE, SET_PUDF, and zzzCalcStartCursorHide().

Referenced by zzzInitTask().

01384 { 01385 PPROCESSINFO ppi; 01386 01387 /* 01388 * If this is the first call to zzzShowStartGlass(), then the 01389 * W32PF_ALLOWFOREGROUNDACTIVATE bit has already been set in the process 01390 * info - we don't want to set it again because it may have been 01391 * purposefully cleared when the user hit a key or mouse clicked. 01392 */ 01393 ppi = PpiCurrent(); 01394 if (ppi->W32PF_Flags & W32PF_SHOWSTARTGLASSCALLED) { 01395 /* 01396 * Allow this wow app to come to the foreground. This'll be cancelled 01397 * if the user mouse clicks or hits any keys. 01398 */ 01399 SET_PUDF(PUDF_ALLOWFOREGROUNDACTIVATE); 01400 TAGMSG0(DBGTAG_FOREGROUND, "zzzShowStartGlass set PUDF"); 01401 ppi->W32PF_Flags |= W32PF_ALLOWFOREGROUNDACTIVATE; 01402 TAGMSG1(DBGTAG_FOREGROUND, "zzzShowStartGlass set W32PF %#p", ppi); 01403 } 01404 ppi->W32PF_Flags |= W32PF_SHOWSTARTGLASSCALLED; 01405 01406 /* 01407 * Show the start glass cursor for this much longer. 01408 */ 01409 zzzCalcStartCursorHide((PW32PROCESS)ppi, dwTimeout); 01410 }


Variable Documentation

int giSetupExe
 

Definition at line 688 of file queue.c.

Referenced by CreateSetupNameArray(), and SetAppImeCompatFlags().

PUNICODE_STRING gpastrSetupExe
 

Definition at line 687 of file queue.c.

PW32PROCESS gpwpCalcFirst
 

Definition at line 31 of file queue.c.

Referenced by zzzCalcStartCursorHide().

BEEPPROC pfnBP[]
 

Initial value:

Definition at line 3755 of file queue.c.

Referenced by xxxProcessEventMessage().

PPAGED_LOOKASIDE_LIST QEntryLookaside
 

Definition at line 44 of file queue.c.

Referenced by AllocQEntry(), DelQEntry(), FreeQEntry(), InitQEntryLookaside(), and Win32kNtUserCleanup().

PPAGED_LOOKASIDE_LIST QLookaside
 

Definition at line 43 of file queue.c.

Referenced by AllocQueue(), FreeCachedQueues(), FreeQueue(), and InitQEntryLookaside().


Generated on Sat May 15 19:45:25 2004 for test by doxygen 1.3.7