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

random.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: random.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains a random collection of support routines for the User 00007 * API functions. Many of these functions will be moved to more appropriate 00008 * files once we get our act together. 00009 * 00010 * History: 00011 * 10-17-90 DarrinM Created. 00012 * 02-06-91 IanJa HWND revalidation added (none required) 00013 \***************************************************************************/ 00014 00015 #include "precomp.h" 00016 #pragma hdrstop 00017 00018 00019 /***************************************************************************\ 00020 * xxxUpdateWindows 00021 * 00022 * User mode wrapper 00023 \***************************************************************************/ 00024 00025 BOOL xxxUpdateWindows(PWND pwnd, HRGN hrgn) 00026 { 00027 CheckLock(pwnd); 00028 00029 xxxUpdateThreadsWindows(PtiCurrent(), pwnd, hrgn); 00030 00031 /* 00032 * This function needs to return a value, since it is 00033 * called through NtUserCallHwndParam. 00034 */ 00035 return TRUE; 00036 } 00037 00038 /***************************************************************************\ 00039 * ValidateState 00040 * 00041 * States allowed to be set/cleared by Set/ClearWindowState. If you're 00042 * allowing a new flag here, you must make sure it won't cause an AV 00043 * in the kernel if someone sets it maliciously. 00044 \***************************************************************************/ 00045 00046 #define NUM_BYTES 16 // Window state bytes are 0 to F, explanation in user.h 00047 00048 CONST BYTE abValidateState[NUM_BYTES] = { 00049 0, // 0 00050 0, // 1 00051 0, // 2 00052 0, // 3 00053 0, // 4 00054 LOBYTE(WFWIN40COMPAT), 00055 0, // 6 00056 LOBYTE(WFNOANIMATE), 00057 0, // 8 00058 LOBYTE(WEFEDGEMASK), 00059 LOBYTE(WEFSTATICEDGE), 00060 0, // B 00061 LOBYTE(EFPASSWORD), 00062 LOBYTE(CBFHASSTRINGS | EFREADONLY), 00063 LOBYTE(WFTABSTOP | WFSYSMENU | WFVSCROLL | WFHSCROLL | WFBORDER), 00064 LOBYTE(WFCLIPCHILDREN) 00065 }; 00066 00067 BOOL ValidateState(DWORD dwFlags) 00068 { 00069 BYTE bOffset = HIBYTE(dwFlags), bState = LOBYTE(dwFlags); 00070 00071 if (bOffset > NUM_BYTES - 1) 00072 return FALSE; 00073 00074 return ((bState & abValidateState[bOffset]) == bState); 00075 } 00076 00077 /***************************************************************************\ 00078 * Set/ClearWindowState 00079 * 00080 * Wrapper functions for User mode to be able to set state fags 00081 \***************************************************************************/ 00082 00083 void SetWindowState( 00084 PWND pwnd, 00085 DWORD dwFlags) 00086 { 00087 /* 00088 * Don't let anyone mess with someone else's window 00089 */ 00090 if (GETPTI(pwnd)->ppi == PtiCurrent()->ppi) { 00091 if (ValidateState(dwFlags)) { 00092 SetWF(pwnd, dwFlags); 00093 } else { 00094 RIPMSG1(RIP_ERROR, "SetWindowState: invalid flag %x", dwFlags); 00095 } 00096 } else { 00097 RIPMSG1(RIP_WARNING, "SetWindowState: current ppi doesn't own pwnd %#p", pwnd); 00098 } 00099 00100 } 00101 00102 void ClearWindowState( 00103 PWND pwnd, 00104 DWORD dwFlags) 00105 { 00106 /* 00107 * Don't let anyone mess with someone else's window 00108 */ 00109 if (GETPTI(pwnd)->ppi == PtiCurrent()->ppi) { 00110 if (ValidateState(dwFlags)) { 00111 ClrWF(pwnd, dwFlags); 00112 } else { 00113 RIPMSG1(RIP_ERROR, "SetWindowState: invalid flag %x", dwFlags); 00114 } 00115 } else { 00116 RIPMSG1(RIP_WARNING, "ClearWindowState: current ppi doesn't own pwnd %#p", pwnd); 00117 } 00118 00119 } 00120 00121 00122 /***************************************************************************\ 00123 * CheckPwndFilter 00124 * 00125 * 00126 * 00127 * History: 00128 * 11-07-90 DarrinM Translated Win 3.0 ASM code. 00129 \***************************************************************************/ 00130 00131 BOOL CheckPwndFilter( 00132 PWND pwnd, 00133 PWND pwndFilter) 00134 { 00135 if ((pwndFilter == NULL) || (pwndFilter == pwnd) || 00136 ((pwndFilter == (PWND)1) && (pwnd == NULL))) { 00137 return TRUE; 00138 } 00139 00140 return _IsChild(pwndFilter, pwnd); 00141 } 00142 00143 00144 /***************************************************************************\ 00145 * AllocateUnicodeString 00146 * 00147 * History: 00148 * 10-25-90 MikeHar Wrote. 00149 * 11-09-90 DarrinM Fixed. 00150 * 01-13-92 GregoryW Neutralized. 00151 * 03-05-98 FritzS Only allocate Length+1 00152 \***************************************************************************/ 00153 00154 BOOL 00155 AllocateUnicodeString( 00156 PUNICODE_STRING pstrDst, 00157 PUNICODE_STRING cczpstrSrc) 00158 { 00159 if (cczpstrSrc == NULL) { 00160 RtlInitUnicodeString(pstrDst, NULL); 00161 return TRUE; 00162 } 00163 00164 pstrDst->Buffer = UserAllocPoolWithQuota(cczpstrSrc->Length+sizeof(UNICODE_NULL), TAG_TEXT); 00165 if (pstrDst->Buffer == NULL) { 00166 return FALSE; 00167 } 00168 00169 try { 00170 RtlCopyMemory(pstrDst->Buffer, cczpstrSrc->Buffer, cczpstrSrc->Length); 00171 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00172 UserFreePool(pstrDst->Buffer); 00173 pstrDst->Buffer = NULL; 00174 return FALSE; 00175 } 00176 pstrDst->MaximumLength = cczpstrSrc->Length+sizeof(UNICODE_NULL); 00177 pstrDst->Length = cczpstrSrc->Length; 00178 pstrDst->Buffer[pstrDst->Length / sizeof(WCHAR)] = 0; 00179 00180 return TRUE; 00181 } 00182 00183 00184 /***************************************************************************\ 00185 * xxxGetControlColor 00186 * 00187 * <brief description> 00188 * 00189 * History: 00190 * 02-12-92 JimA Ported from Win31 sources 00191 \***************************************************************************/ 00192 00193 HBRUSH xxxGetControlColor( 00194 PWND pwndParent, 00195 PWND pwndCtl, 00196 HDC hdc, 00197 UINT message) 00198 { 00199 HBRUSH hbrush; 00200 00201 /* 00202 * If we're sending to a window of another thread, don't send this message 00203 * but instead call DefWindowProc(). New rule about the CTLCOLOR messages. 00204 * Need to do this so that we don't send an hdc owned by one thread to 00205 * another thread. It is also a harmless change. 00206 */ 00207 if (PpiCurrent() != GETPTI(pwndParent)->ppi) { 00208 return (HBRUSH)xxxDefWindowProc(pwndParent, message, (WPARAM)hdc, (LPARAM)HW(pwndCtl)); 00209 } 00210 00211 hbrush = (HBRUSH)xxxSendMessage(pwndParent, message, (WPARAM)hdc, (LPARAM)HW(pwndCtl)); 00212 00213 /* 00214 * If the brush returned from the parent is invalid, get a valid brush from 00215 * xxxDefWindowProc. 00216 */ 00217 if ((hbrush == 0) || !GreValidateServerHandle(hbrush, BRUSH_TYPE)) { 00218 #if DBG 00219 if (hbrush != 0) 00220 RIPMSG2(RIP_WARNING, 00221 "Invalid HBRUSH from WM_CTLCOLOR*** msg %lX brush %lX", message, hbrush); 00222 #endif 00223 hbrush = (HBRUSH)xxxDefWindowProc(pwndParent, message, 00224 (WPARAM)hdc, (LPARAM)pwndCtl); 00225 } 00226 00227 return hbrush; 00228 } 00229 00230 00231 /***************************************************************************\ 00232 * xxxGetControlBrush 00233 * 00234 * <brief description> 00235 * 00236 * History: 00237 * 12-10-90 IanJa type replaced with new 32-bit message 00238 * 01-21-91 IanJa Prefix '_' denoting exported function (although not API) 00239 \***************************************************************************/ 00240 00241 HBRUSH xxxGetControlBrush( 00242 PWND pwnd, 00243 HDC hdc, 00244 UINT message) 00245 { 00246 HBRUSH hbr; 00247 PWND pwndSend; 00248 TL tlpwndSend; 00249 00250 CheckLock(pwnd); 00251 00252 if ((pwndSend = (TestwndPopup(pwnd) ? pwnd->spwndOwner : pwnd->spwndParent)) 00253 == NULL) 00254 pwndSend = pwnd; 00255 00256 ThreadLock(pwndSend, &tlpwndSend); 00257 00258 /* 00259 * Last parameter changes the message into a ctlcolor id. 00260 */ 00261 hbr = xxxGetControlColor(pwndSend, pwnd, hdc, message); 00262 ThreadUnlock(&tlpwndSend); 00263 00264 return hbr; 00265 } 00266 00267 /***************************************************************************\ 00268 * xxxHardErrorControl 00269 * 00270 * Performs kernel-mode hard error support functions. 00271 * 00272 * History: 00273 * 02-08-95 JimA Created. 00274 \***************************************************************************/ 00275 00276 UINT xxxHardErrorControl( 00277 DWORD dwCmd, 00278 HANDLE handle, 00279 PDESKRESTOREDATA pdrdRestore) 00280 { 00281 PTHREADINFO ptiClient, ptiCurrent = PtiCurrent(); 00282 PDESKTOP pdesk; 00283 PUNICODE_STRING pstrName; 00284 NTSTATUS Status; 00285 PETHREAD Thread; 00286 BOOL fAllowForeground; 00287 00288 /* 00289 * turn off BlockInput so the user can respond to the hard error popup 00290 */ 00291 gptiBlockInput = NULL; 00292 00293 UserAssert(ISCSRSS()); 00294 switch (dwCmd) { 00295 case HardErrorSetup: 00296 00297 /* 00298 * Don't do it if the system has not been initialized. 00299 */ 00300 if (grpdeskRitInput == NULL) { 00301 RIPMSG0(RIP_WARNING, "HardErrorControl: System not initialized"); 00302 return HEC_ERROR; 00303 } 00304 00305 /* 00306 * Setup caller as the hard error handler. 00307 */ 00308 if (gHardErrorHandler.pti != NULL) { 00309 RIPMSG1(RIP_WARNING, "HardErrorControl: pti not NULL %#p", gHardErrorHandler.pti); 00310 return HEC_ERROR; 00311 } 00312 00313 /* 00314 * Mark the handler as active. 00315 */ 00316 gHardErrorHandler.pti = ptiCurrent; 00317 00318 /* 00319 * Clear any pending quits. 00320 */ 00321 ptiCurrent->cQuit = 0; 00322 00323 break; 00324 00325 case HardErrorCleanup: 00326 00327 /* 00328 * Remove caller as the hard error handler. 00329 */ 00330 if (gHardErrorHandler.pti != ptiCurrent) { 00331 return HEC_ERROR; 00332 } 00333 00334 gHardErrorHandler.pti = NULL; 00335 break; 00336 00337 case HardErrorAttachUser: 00338 case HardErrorInDefDesktop: 00339 /* 00340 * Check for exit conditions. We do not allow attaches to the 00341 * disconnect desktop. 00342 */ 00343 if (ISTS()) { 00344 if ((grpdeskRitInput == NULL) || 00345 00346 ((grpdeskRitInput == gspdeskDisconnect) && 00347 (gspdeskShouldBeForeground == NULL)) || 00348 00349 ((grpdeskRitInput == gspdeskDisconnect) && 00350 (gspdeskShouldBeForeground == gspdeskDisconnect))) { 00351 return HEC_ERROR; 00352 } 00353 } 00354 00355 /* 00356 * Only attach to a user desktop. 00357 */ 00358 if (ISTS() && grpdeskRitInput == gspdeskDisconnect) { 00359 pstrName = POBJECT_NAME(gspdeskShouldBeForeground); 00360 } else { 00361 pstrName = POBJECT_NAME(grpdeskRitInput); 00362 } 00363 00364 if (pstrName && (!_wcsicmp(TEXT("Winlogon"), pstrName->Buffer) || 00365 !_wcsicmp(TEXT("Disconnect"), pstrName->Buffer) || 00366 !_wcsicmp(TEXT("Screen-saver"), pstrName->Buffer))) { 00367 RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, ""); 00368 return HEC_WRONGDESKTOP; 00369 } 00370 if (dwCmd == HardErrorInDefDesktop) { 00371 /* 00372 * Clear any pending quits. 00373 */ 00374 ptiCurrent->cQuit = 0; 00375 return HEC_SUCCESS; 00376 } 00377 00378 00379 /* 00380 * Fall through. 00381 */ 00382 00383 case HardErrorAttach: 00384 00385 /* 00386 * Save a pointer to and prevent destruction of the 00387 * current queue. This will give us a queue to return 00388 * to if journalling is occuring when we tear down the 00389 * hard error popup. 00390 */ 00391 gHardErrorHandler.pqAttach = ptiCurrent->pq; 00392 (ptiCurrent->pq->cLockCount)++; 00393 00394 /* 00395 * Fall through. 00396 */ 00397 00398 case HardErrorAttachNoQueue: 00399 00400 /* 00401 * Check for exit conditions. We do not allow attaches to the 00402 * disconnect desktop. 00403 */ 00404 if (ISTS()) { 00405 if ((grpdeskRitInput == NULL) || 00406 00407 ((grpdeskRitInput == gspdeskDisconnect) && 00408 (gspdeskShouldBeForeground == NULL)) || 00409 00410 ((grpdeskRitInput == gspdeskDisconnect) && 00411 (gspdeskShouldBeForeground == gspdeskDisconnect))) { 00412 return HEC_ERROR; 00413 } 00414 } 00415 00416 /* 00417 * Attach the handler to the current desktop. 00418 */ 00419 /* 00420 * Don't allow an attach to the disconnected desktop, but 00421 * remember this for later when we detach. 00422 */ 00423 gbDisconnectHardErrorAttach = FALSE; 00424 00425 if (ISTS() && grpdeskRitInput == gspdeskDisconnect) { 00426 pdesk = gspdeskShouldBeForeground; 00427 gbDisconnectHardErrorAttach = TRUE; 00428 } else { 00429 pdesk = grpdeskRitInput; 00430 } 00431 00432 UserAssert(pdesk != NULL); 00433 00434 Status = xxxSetCsrssThreadDesktop(pdesk, pdrdRestore); 00435 00436 if (!NT_SUCCESS(Status)) { 00437 RIPMSG1(RIP_WARNING, "HardErrorControl: HardErrorAttachNoQueue failed:%#lx", Status); 00438 if (dwCmd != HardErrorAttachNoQueue) { 00439 gHardErrorHandler.pqAttach = NULL; 00440 UserAssert(ptiCurrent->pq->cLockCount); 00441 (ptiCurrent->pq->cLockCount)--; 00442 } 00443 return HEC_ERROR; 00444 } 00445 00446 /* 00447 * Make sure we actually set the pdesk in the current thread 00448 */ 00449 UserAssert(ptiCurrent->rpdesk != NULL); 00450 00451 /* 00452 * Determine if this box can come to the foreground. 00453 * Let it come to the foreground if it doesn't have a pti 00454 * (it might have just failed to load). 00455 */ 00456 fAllowForeground = FALSE; 00457 if (handle != NULL) { 00458 Status = ObReferenceObjectByHandle(handle, 00459 THREAD_QUERY_INFORMATION, 00460 *PsThreadType, 00461 UserMode, 00462 &Thread, 00463 NULL); 00464 if (NT_SUCCESS(Status)) { 00465 ptiClient = PtiFromThread(Thread); 00466 if ((ptiClient == NULL) || CanForceForeground(ptiClient->ppi)) { 00467 fAllowForeground = TRUE; 00468 } 00469 00470 UnlockThread(Thread); 00471 00472 } else { 00473 RIPMSG2(RIP_WARNING, "HardErrorControl: HardErrorAttach failed to get thread (%#lx) pointer:%#lx", handle, Status); 00474 } 00475 } 00476 00477 if (fAllowForeground) { 00478 ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 00479 TAGMSG1(DBGTAG_FOREGROUND, "xxxHardErrorControl set TIF %#lx", ptiCurrent); 00480 } else { 00481 ptiCurrent->TIF_flags &= ~TIF_ALLOWFOREGROUNDACTIVATE; 00482 TAGMSG1(DBGTAG_FOREGROUND, "xxxHardErrorControl clear TIF %#lx", ptiCurrent); 00483 } 00484 00485 break; 00486 00487 case HardErrorDetach: 00488 00489 /* 00490 * xxxSwitchDesktop may have sent WM_QUIT to the msgbox, so 00491 * ensure that the quit flag is reset. 00492 */ 00493 ptiCurrent->cQuit = 0; 00494 00495 /* 00496 * We will reset the hard-error queue to the pre-allocated 00497 * one so if we end up looping back (i.e. from a desktop 00498 * switch), we will have a valid queue in case the desktop 00499 * was deleted. 00500 */ 00501 UserAssert(gHardErrorHandler.pqAttach->cLockCount); 00502 (gHardErrorHandler.pqAttach->cLockCount)--; 00503 00504 DeferWinEventNotify(); 00505 00506 BEGINATOMICCHECK(); 00507 00508 if (ptiCurrent->pq != gHardErrorHandler.pqAttach) { 00509 UserAssert(gHardErrorHandler.pqAttach->cThreads == 0); 00510 AllocQueue(NULL, gHardErrorHandler.pqAttach); 00511 gHardErrorHandler.pqAttach->cThreads++; 00512 zzzAttachToQueue(ptiCurrent, gHardErrorHandler.pqAttach, NULL, FALSE); 00513 } 00514 00515 gHardErrorHandler.pqAttach = NULL; 00516 00517 ENDATOMICCHECK(); 00518 00519 zzzEndDeferWinEventNotify(); 00520 00521 /* 00522 * Fall through. 00523 */ 00524 00525 case HardErrorDetachNoQueue: 00526 /* 00527 * Detach the handler from the desktop and return 00528 * status to indicate if a switch has occured. 00529 */ 00530 pdesk = ptiCurrent->rpdesk; 00531 xxxRestoreCsrssThreadDesktop(pdrdRestore); 00532 00533 if (ISTS()) { 00534 /* 00535 * The hard error message box gets a desktop switch notification, 00536 * so remember that we lied to him and lie (or unlie) to him again. 00537 * A desktop switch did occur. 00538 */ 00539 if (gbDisconnectHardErrorAttach) { 00540 gbDisconnectHardErrorAttach = FALSE; 00541 return HEC_DESKTOPSWITCH; 00542 } 00543 #ifdef WAY_LATER 00544 /* 00545 * This happened once and caused a trap when a KeyEvent() came in and we 00546 * directed it to this queue. I think this is a MS window that we caught 00547 * since we use this so much for license popup's. 00548 */ 00549 if (gHardErrorHandler.pqAttach == gpqForeground) { 00550 gpqForeground = NULL; 00551 } 00552 #endif 00553 } 00554 00555 return (pdesk != grpdeskRitInput ? HEC_DESKTOPSWITCH : HEC_SUCCESS); 00556 } 00557 return HEC_SUCCESS; 00558 } 00559 00560 #if 0 // not used anywhere (IanJa) 00561 /***************************************************************************\ 00562 * VersionFromWindowFlag 00563 * 00564 * Returns the version of a window from its window state flags. 00565 * 00566 * History: 00567 * 04-Apr-1997 adams Created. 00568 \***************************************************************************/ 00569 00570 WORD 00571 VersionFromWindowFlag(PWND pwnd) 00572 { 00573 BYTE bFlags = TestWF(pwnd, WFWINCOMPATMASK); 00574 if (bFlags == LOBYTE(WFWIN50COMPAT | WFWIN40COMPAT | WFWIN31COMPAT)) { 00575 return VER50; 00576 } else if (bFlags == LOBYTE(WFWIN40COMPAT | WFWIN31COMPAT)) { 00577 return VER40; 00578 } else if (bFlags == LOBYTE(WFWIN31COMPAT)) { 00579 return VER31; 00580 } else { 00581 return VER30; 00582 } 00583 } 00584 #endif // not used anywhere (IanJa)

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