test: random.c Source File

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)