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

syscmd.c

Go to the documentation of this file.
00001 /**************************** Module Header ********************************\ 00002 * Module Name: syscmd.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * System Command Routines 00007 * 00008 * History: 00009 * 01-25-91 IanJa Added handle revalidation 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 00016 /***************************************************************************\ 00017 * xxxHandleNCMouseGuys 00018 * 00019 * History: 00020 * 11-09-90 DavidPe Ported. 00021 \***************************************************************************/ 00022 00023 void xxxHandleNCMouseGuys( 00024 PWND pwnd, 00025 UINT message, 00026 int htArea, 00027 LPARAM lParam) 00028 { 00029 UINT syscmd; 00030 PWND pwndT; 00031 TL tlpwndT; 00032 00033 CheckLock(pwnd); 00034 00035 syscmd = 0xFFFF; 00036 00037 switch (htArea) { 00038 00039 case HTCAPTION: 00040 switch (message) { 00041 00042 case WM_NCLBUTTONDBLCLK: 00043 if (TestWF(pwnd, WFMINIMIZED) || TestWF(pwnd, WFMAXIMIZED)) { 00044 syscmd = SC_RESTORE; 00045 } else if (TestWF(pwnd, WFMAXBOX)) { 00046 syscmd = SC_MAXIMIZE; 00047 } 00048 break; 00049 00050 case WM_NCLBUTTONDOWN: 00051 pwndT = GetTopLevelWindow(pwnd); 00052 ThreadLock(pwndT, &tlpwndT); 00053 xxxActivateWindow(pwndT, AW_USE2); 00054 ThreadUnlock(&tlpwndT); 00055 syscmd = SC_MOVE; 00056 break; 00057 } 00058 break; 00059 00060 case HTSYSMENU: 00061 case HTMENU: 00062 case HTHSCROLL: 00063 case HTVSCROLL: 00064 if (message == WM_NCLBUTTONDOWN || message == WM_NCLBUTTONDBLCLK) { 00065 switch (htArea) { 00066 case HTSYSMENU: 00067 if (message == WM_NCLBUTTONDBLCLK) { 00068 syscmd = SC_CLOSE; 00069 break; 00070 } 00071 00072 /* 00073 *** FALL THRU ** 00074 */ 00075 00076 case HTMENU: 00077 syscmd = SC_MOUSEMENU; 00078 break; 00079 00080 case HTHSCROLL: 00081 syscmd = SC_HSCROLL; 00082 break; 00083 00084 case HTVSCROLL: 00085 syscmd = SC_VSCROLL; 00086 break; 00087 } 00088 } 00089 break; 00090 } 00091 00092 switch (syscmd) { 00093 00094 case SC_MINIMIZE: 00095 case SC_MAXIMIZE: 00096 case SC_CLOSE: 00097 00098 /* 00099 * Only do double click commands on an upclick. 00100 * This code is very sensitive to changes from this state. 00101 * Eat any mouse messages. 00102 */ 00103 00104 /* 00105 * Bug #152: WM_NCLBUTTONUP message missing from double click. 00106 * This code was broken in Windows 3.x and the test for whether 00107 * the mouse button was down always failed, so no mouse messages 00108 * were ever eaten. We'll emulate this by not even doing the test. 00109 * 00110 * 00111 * { 00112 * PQ pqCurrent; 00113 * MSG msg; 00114 * 00115 * pqCurrent = PtiCurrent()->pq; 00116 * if (TestKeyStateDown(pqCurrent, VK_LBUTTON)) { 00117 * xxxCapture(PtiCurrent(), pwnd, WINDOW_CAPTURE); 00118 * 00119 * while (TestKeyStateDown(pqCurrent, VK_LBUTTON)) { 00120 * if (!xxxPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, 00121 * PM_REMOVE)) { 00122 * if (!xxxSleepThread(QS_MOUSE, 0, TRUE)) 00123 * break; 00124 * } 00125 * } 00126 * 00127 * xxxReleaseCapture(); 00128 * 00129 * } 00130 * } 00131 * 00132 */ 00133 00134 /* 00135 ** FALL THRU ** 00136 */ 00137 case SC_SIZE: 00138 case SC_MOVE: 00139 /* 00140 * For SysCommands on system menu, don't do if menu item is 00141 * disabled. 00142 */ 00143 if (TestWF(pwnd, WFSYSMENU)) { 00144 xxxSetSysMenu(pwnd); 00145 if (_GetMenuState(xxxGetSysMenuHandle(pwnd), (syscmd & 0xFFF0), 00146 MF_BYCOMMAND) & MFS_GRAYED) { 00147 return; 00148 } 00149 } 00150 break; 00151 } 00152 00153 if (syscmd != 0xFFFF) { 00154 xxxSendMessage(pwnd, WM_SYSCOMMAND, syscmd | htArea, lParam); 00155 } 00156 } 00157 00158 /***************************************************************************\ 00159 * StartScreenSaver 00160 * 00161 * History: 00162 * 11-12-90 MikeHar ported. 00163 \***************************************************************************/ 00164 00165 void StartScreenSaver( 00166 BOOL bOnlyIfSecure) 00167 { 00168 /* 00169 * If a screen saver is already running or we're in the midst of powering 00170 * down the machine, ignore this request. 00171 */ 00172 if (gppiScreenSaver != NULL || gPowerState.fInProgress) 00173 return; 00174 00175 if (gspwndLogonNotify != NULL) { 00176 /* 00177 * Let the logon process take care of the screen saver 00178 */ 00179 _PostMessage(gspwndLogonNotify, 00180 WM_LOGONNOTIFY, LOGON_INPUT_TIMEOUT, bOnlyIfSecure); 00181 } 00182 } 00183 00184 00185 /***************************************************************************\ 00186 * xxxSysCommand 00187 * 00188 * History: 00189 * 11-12-90 MikeHar ported. 00190 * 02-07-91 DavidPe Added Win 3.1 WH_CBT support. 00191 \***************************************************************************/ 00192 00193 void xxxSysCommand( 00194 PWND pwnd, 00195 DWORD cmd, 00196 LPARAM lParam) 00197 { 00198 UINT htArea; 00199 PWND pwndSwitch; 00200 PMENUSTATE pMenuState; 00201 TL tlpwnd; 00202 POINT pt; 00203 DWORD dw; 00204 PWND pwndCapture; 00205 PTHREADINFO pti; 00206 00207 CheckLock(pwnd); 00208 00209 htArea = (UINT)(cmd & 0x0F); 00210 cmd -= htArea; 00211 00212 /* 00213 * Intense hack o' death. 00214 */ 00215 if (lParam == 0x00010000L) 00216 lParam = 0L; 00217 00218 /* 00219 * If the system doesn't have capture (ie CLENT_CAPTURE_INTERNAL) 00220 * do the sys command. Also, do the sys command for the special case 00221 * where the window receiving the sys command is a console window that 00222 * is in full screen mode. In this case we let the sys command through. 00223 * 00224 * Also if this a SC_SCREENSAVE then we handle it anyway and 00225 * switching desktops will do the cancel. SC_SCREENSAVER 00226 * is special so we can start the screen saver even if we are in 00227 * menu mode for security so NT bug 10975 Banker's Trust 00228 */ 00229 pti = GETPTI(pwnd); 00230 00231 /* 00232 * For 32bit apps (and apps on seperate queues), we need to check 00233 * the capture in the queue. Otherwise, on MDI child-destruction 00234 * we would get the restore when they shouldn't. This broke MSGOLF 00235 * who during the restore, AV'd because they assumed this wouldn't 00236 * happen. On 16bit shared apps, we want to check the internal 00237 * capture. Otherwise, when doing 16bit drag-and-drop, we would 00238 * not restore the minimized window if we had a queue-capture-window. 00239 */ 00240 00241 /* 00242 * But... it is too broad a change to just check internal capture for all WoW apps. Some 00243 * apps depend on bailing out when they have capture set. (Adobe Persuasion, NT bug 68794, 00244 * for SC_MOVE). So, let's restrict the hack to SC_RESTORE to keep Ole drag-and-drop working. 00245 * See NT bug 6109. FritzS 00246 */ 00247 00248 pwndCapture = ((pti->TIF_flags & TIF_16BIT) && (cmd == SC_RESTORE)) ? gspwndInternalCapture : 00249 pti->pq->spwndCapture; 00250 00251 if ((!pwndCapture && !TestWF(pwnd, WFDISABLED)) || 00252 (pwnd == gspwndFullScreen) || 00253 (cmd == SC_SCREENSAVE) || 00254 (cmd == SC_MONITORPOWER) || 00255 (cmd == SC_TASKLIST)) { 00256 00257 /* 00258 * Perform the sys command 00259 */ 00260 00261 #ifdef SYSMODALWINDOWS 00262 if (gspwndSysModal != NULL) { 00263 switch (cmd) { 00264 case SC_SIZE: 00265 case SC_MOVE: 00266 case SC_MINIMIZE: 00267 case SC_MAXIMIZE: 00268 case SC_NEXTWINDOW: 00269 case SC_PREVWINDOW: 00270 case SC_SCREENSAVE: 00271 return; 00272 } 00273 } 00274 #endif 00275 00276 /* 00277 * Call the CBT hook asking if it's okay to do this command. 00278 * If not, return from here. 00279 */ 00280 if (IsHooked(PtiCurrent(), WHF_CBT) && xxxCallHook(HCBT_SYSCOMMAND, 00281 (DWORD)cmd, (DWORD)lParam, WH_CBT)) { 00282 return; 00283 } 00284 00285 switch (cmd) { 00286 case SC_RESTORE: 00287 cmd = SW_RESTORE; 00288 if (TestWF(pwnd, WFMINIMIZED) || !TestWF(pwnd, WFMAXIMIZED)) 00289 PlayEventSound(USER_SOUND_RESTOREUP); 00290 else 00291 PlayEventSound(USER_SOUND_RESTOREDOWN); 00292 goto MinMax; 00293 00294 00295 case SC_MINIMIZE: 00296 cmd = SW_MINIMIZE; 00297 00298 /* 00299 * Are we already minimized? 00300 */ 00301 if (TestWF(pwnd, WFMINIMIZED)) 00302 break; 00303 00304 PlayEventSound(USER_SOUND_MINIMIZE); 00305 00306 goto MinMax; 00307 case SC_MAXIMIZE: 00308 cmd = SW_SHOWMAXIMIZED; 00309 00310 /* 00311 * Are we already maximized? 00312 */ 00313 if (TestWF(pwnd, WFMAXIMIZED)) 00314 break; 00315 00316 PlayEventSound(USER_SOUND_MAXIMIZE); 00317 MinMax: 00318 xxxShowWindow(pwnd, cmd | TEST_PUDF(PUDF_ANIMATE)); 00319 return; 00320 00321 case SC_SIZE: 00322 { 00323 xxxMoveSize(pwnd, htArea, _GetMessagePos()); 00324 } 00325 return; 00326 00327 case SC_MOVE: 00328 // 00329 // Don't enter movesize loop unless the user is actually 00330 // dragging from the caption. Otherwise, put up the system 00331 // menu on a minimized window. 00332 // 00333 00334 // 00335 // Are we dragging with the left mouse button? 00336 // 00337 dw = _GetMessagePos(); 00338 POINTSTOPOINT( pt, MAKEPOINTS(dw)); 00339 if ( !htArea || 00340 xxxIsDragging(pwnd, pt, WM_LBUTTONUP)) { 00341 00342 /* 00343 * We are moving. Enter move/size loop. 00344 */ 00345 { 00346 xxxMoveSize(pwnd, (htArea == 0) ? WMSZ_KEYMOVE : WMSZ_MOVE, dw); 00347 } 00348 } else { 00349 00350 /* 00351 * Activate our window, just like we would have in 00352 * MoveSize(). 00353 */ 00354 xxxSetWindowPos(pwnd, PWND_TOP, 0, 0, 0, 0, 00355 SWP_NOMOVE | SWP_NOSIZE); 00356 if (TestWF(pwnd, WFMINIMIZED)) { 00357 00358 /* 00359 * Try to popup the system menu 00360 */ 00361 xxxSendMessage(pwnd, WM_SYSCOMMAND, SC_KEYMENU, 00362 (DWORD) (TestWF(pwnd, WFCHILD) ? '-' : MENUSYSMENU)); 00363 } 00364 } 00365 return; 00366 00367 case SC_CLOSE: 00368 xxxSendMessage(pwnd, WM_CLOSE, 0L, 0L); 00369 return; 00370 00371 case SC_NEXTWINDOW: 00372 case SC_PREVWINDOW: 00373 xxxOldNextWindow((UINT)lParam); 00374 break; 00375 00376 case SC_CONTEXTHELP: 00377 xxxHelpLoop(pwnd); 00378 break; 00379 00380 case SC_KEYMENU: 00381 00382 /* 00383 * A menu was selected via keyboard 00384 */ 00385 pMenuState = xxxMNStartMenuState(pwnd, cmd, lParam); 00386 if (pMenuState != NULL) { 00387 UserAssert(PtiCurrent() == pMenuState->ptiMenuStateOwner); 00388 00389 /* 00390 * Make sure we are not fullscreen 00391 */ 00392 if (gspwndFullScreen == pwnd) { 00393 PWND pwndT; 00394 TL tlpwndT; 00395 00396 pwndT = _GetDesktopWindow(); 00397 ThreadLock(pwndT, &tlpwndT); 00398 xxxMakeWindowForegroundWithState(pwndT, GDIFULLSCREEN); 00399 ThreadUnlock(&tlpwndT); 00400 } 00401 00402 pMenuState->fUnderline = TRUE; 00403 xxxMNKeyFilter(pMenuState->pGlobalPopupMenu, pMenuState, (UINT)lParam); 00404 if (!pMenuState->fModelessMenu) { 00405 xxxMNEndMenuState (TRUE); 00406 } 00407 } 00408 /* 00409 * Capture must have been unlocked 00410 */ 00411 UserAssert(!(PtiCurrent()->pq->QF_flags & QF_CAPTURELOCKED)); 00412 return; 00413 00414 case SC_MOUSEMENU: 00415 case SC_DEFAULT: 00416 00417 /* 00418 * If the window is not foreground, eat the command to avoid 00419 * wasting time flashing the system menu. 00420 * 00421 * We used to check if the top level window was WFFRAMEON (so a 00422 * child window's system menu works like Win 3.1) but Excel's 00423 * (SDM) dialogs allow you to access their menus even though 00424 * the child and parent appear to be inactive. 00425 */ 00426 if (!(GETPTI(pwnd)->pq == gpqForeground)) 00427 return; 00428 00429 /* 00430 * A mouse click occurred on a toplevel menu. 00431 */ 00432 pMenuState = xxxMNStartMenuState(pwnd, cmd, lParam); 00433 if (pMenuState != NULL) { 00434 UserAssert(PtiCurrent() == pMenuState->ptiMenuStateOwner); 00435 xxxMNLoop(pMenuState->pGlobalPopupMenu, pMenuState, lParam, (cmd==SC_DEFAULT)); 00436 if (!pMenuState->fModelessMenu) { 00437 xxxMNEndMenuState (TRUE); 00438 } 00439 } 00440 /* 00441 * Capture must have been unlocked 00442 */ 00443 UserAssert(!(PtiCurrent()->pq->QF_flags & QF_CAPTURELOCKED)); 00444 return; 00445 00446 case SC_VSCROLL: 00447 case SC_HSCROLL: 00448 xxxSBTrackInit(pwnd, lParam, htArea, (_GetKeyState(VK_SHIFT) < 0) ? SCROLL_DIRECT : SCROLL_NORMAL); 00449 return; 00450 00451 case SC_TASKLIST: 00452 // _PostThreadMessage(gptiTasklist, WM_SYSCOMMAND, SC_TASKLIST, 0); 00453 // if (!FCallTray() || 00454 // !CallHook(HSHELL_TASKMAN, (WPARAM) HW16(hwnd), (LPARAM) 0, WH_SHELL)) 00455 00456 /* 00457 * Winlogon will set lParam to -1 to indicate that we really want a task list, 00458 * not just the start menu. We indicate this to the shell by passing a NULL 00459 * window ptr 00460 * This message is really intended for the SHELL, so give them the right 00461 * to set the foreground. 00462 */ 00463 if (FDoTray() && (FCallHookTray() || FPostTray(pwnd->head.rpdesk))) { 00464 PWND pwndTaskman = pwnd->head.rpdesk->pDeskInfo->spwndTaskman; 00465 if (FCallHookTray()) { 00466 xxxCallHook(HSHELL_TASKMAN, (WPARAM)HWq(pwnd), (LPARAM) 0, WH_SHELL); 00467 } 00468 if ((FPostTray(pwnd->head.rpdesk)) && (pwndTaskman != NULL)) { 00469 glinp.ptiLastWoken = GETPTI(pwndTaskman); 00470 _PostMessage(pwndTaskman, gpsi->uiShellMsg, HSHELL_TASKMAN, 00471 lParam == (ULONG)(-1) ? (LPARAM) -1 :(LPARAM)HWq(pwnd)); 00472 } 00473 } else if (gptiTasklist != NULL) { 00474 glinp.ptiLastWoken = gptiTasklist; 00475 _PostThreadMessage(gptiTasklist, WM_SYSCOMMAND, SC_TASKLIST, 0); 00476 // LATER -- FritzS 00477 // HCURSOR hCursorLast; 00478 // static char CODESEG szTask[] = " %d %d"; 00479 00480 // ShowCursor(TRUE); 00481 // hCursorLast = SetCursor32(hCursWait, TRUE); 00482 00483 // Try in the windows directory first. 00484 // GetWindowsDirectory(szBuff, sizeof(szBuff)); 00485 // if (szBuff[lstrlen(szBuff) - 1] != '\\') 00486 // lstrcatn(szBuff, "\\", sizeof(szBuff)); 00487 // lstrcatn(szBuff, (LPSTR)pTaskManName, sizeof(szBuff)); 00488 // wvsprintf(szBuff+lstrlen(szBuff), (LPSTR)szTask, (LPSTR)&lParam); 00489 00490 // if (WinExec((LPSTR)szBuff, SW_SHOWNORMAL) <= 32) 00491 // { 00492 // // If it wasn't in the windows directory then try 00493 // // searching the full path. 00494 // lstrcpyn(szBuff, pTaskManName, sizeof(szBuff)); 00495 // wvsprintf(szBuff+lstrlen(szBuff), (LPSTR)szTask, (LPSTR)&lParam); 00496 // WinExec((LPSTR)szBuff, SW_SHOWNORMAL); 00497 // } 00498 // 00499 // ShowCursor(FALSE); 00500 // SetCursor32(hCursorLast, TRUE); 00501 } 00502 00503 break; 00504 00505 case SC_MONITORPOWER: 00506 /* 00507 * If we're powering down the machine, ignore this request. 00508 */ 00509 if (gPowerState.fInProgress) { 00510 break; 00511 } 00512 00513 switch (lParam) { 00514 case POWERON_PHASE: 00515 if (glinp.dwFlags & LINP_POWERTIMEOUTS) { 00516 glinp.dwFlags &= ~LINP_POWERTIMEOUTS; 00517 DrvSetMonitorPowerState(gpDispInfo->pmdev, 00518 PowerDeviceD0); 00519 } 00520 break; 00521 case LOWPOWER_PHASE: 00522 if ((glinp.dwFlags & LINP_LOWPOWER) == 0) { 00523 glinp.dwFlags |= LINP_LOWPOWER; 00524 DrvSetMonitorPowerState(gpDispInfo->pmdev, 00525 PowerDeviceD1); 00526 } 00527 break; 00528 case POWEROFF_PHASE: 00529 if ((glinp.dwFlags & LINP_POWEROFF) == 0) { 00530 glinp.dwFlags |= LINP_POWEROFF; 00531 DrvSetMonitorPowerState(gpDispInfo->pmdev, 00532 PowerDeviceD3); 00533 } 00534 break; 00535 default: 00536 break; 00537 } 00538 break; 00539 00540 case SC_SCREENSAVE: 00541 pwndSwitch = RevalidateHwnd(ghwndSwitch); 00542 00543 // Lock out screen save until we get another input message. 00544 00545 if (pwndSwitch != NULL && pwnd != pwndSwitch) { 00546 _PostMessage(pwndSwitch, WM_SYSCOMMAND, SC_SCREENSAVE, 0L); 00547 } else { 00548 StartScreenSaver(FALSE); 00549 } 00550 break; 00551 00552 case SC_HOTKEY: 00553 00554 /* 00555 * Loword of the lparam is window to switch to 00556 */ 00557 pwnd = ValidateHwnd((HWND)lParam); 00558 if (pwnd != NULL) { 00559 pwndSwitch = _GetLastActivePopup(pwnd); 00560 00561 if (pwndSwitch != NULL) 00562 pwnd = pwndSwitch; 00563 00564 ThreadLockAlways(pwnd, &tlpwnd); 00565 xxxSetForegroundWindow(pwnd, FALSE); 00566 ThreadUnlock(&tlpwnd); 00567 00568 if (TestWF(pwnd, WFMINIMIZED)) 00569 _PostMessage(pwnd, WM_SYSCOMMAND, SC_RESTORE, 0); 00570 } 00571 break; 00572 } 00573 } 00574 } 00575 00576 /***************************************************************************\ 00577 * _RegisterTasklist (Private API) 00578 * 00579 * History: 00580 * 05-01-91 DavidPe Created. 00581 \***************************************************************************/ 00582 00583 BOOL _RegisterTasklist( 00584 PWND pwndTasklist) 00585 { 00586 #ifdef LATER 00587 // 00588 // JimA - ??? Why do this? 00589 // 00590 PETHREAD Thread; 00591 00592 Thread = PsGetCurrentThread(); 00593 pRitCSRThread->ThreadHandle = Thread->ThreadHandle; 00594 #endif 00595 00596 gptiTasklist = GETPTI(pwndTasklist); 00597 ghwndSwitch = HWq(pwndTasklist); 00598 00599 /* 00600 * Don't allow an app to call AttachThreadInput() on task man - 00601 * we want taskman to be unsynchronized at all times (so the user 00602 * can bring it up and kill other apps). 00603 */ 00604 GETPTI(pwndTasklist)->TIF_flags |= TIF_DONTATTACHQUEUE; 00605 00606 return TRUE; 00607 }

Generated on Sat May 15 19:41:55 2004 for test by doxygen 1.3.7