test: validate.c Source File

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

# validate.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: validate.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * This module contains functions for validating windows, menus, cursors, etc.
    00007 *
    00008 * History:
    00009 * 01-02-91 DarrinM      Created.
    00010 \***************************************************************************/
    00011
    00012 #include "precomp.h"
    00013 #pragma hdrstop
    00014 #include <ntsdexts.h>
    00015
    00016 /*
    00017  * these defines are used for using the validation macros
    00018  * StartValidateHandleMacro and EndValidateHandleMacro
    00019  */
    00020 #define ClientSharedInfo()  (&gSharedInfo)
    00021 #define ServerInfo()  (gpsi)
    00022
    00023 #include "wow.h"
    00024
    00025 #if DBG
    00026 #if defined(_X86_)
    00027     CRITSTACK  gCritStack;
    00028 #endif // defined(_X86_)
    00029 #endif // DBG
    00030
    00031 /*
    00032  * Globals used only in his file.
    00033  */
    00034 __int64   gCSTimeExclusiveWhenEntering;
    00035
    00036 /***************************************************************************\
    00037 * ValidateHwinsta
    00038 *
    00039 * Validate windowstation handle
    00040 *
    00041 * History:
    00042 * 03-29-91 JimA             Created.
    00043 * 06-20-95 JimA             Kernel-mode objects.
    00044 \***************************************************************************/
    00045
    00046 NTSTATUS ValidateHwinsta(
    00047     HWINSTA         hwinsta,
    00048     KPROCESSOR_MODE AccessMode,
    00049     ACCESS_MASK     amDesired,
    00050     PWINDOWSTATION* ppwinsta)
    00051 {
    00052     NTSTATUS Status;
    00053
    00054     Status = ObReferenceObjectByHandle(
    00055             hwinsta,
    00056             amDesired,
    00057             *ExWindowStationObjectType,
    00058             AccessMode,
    00059             ppwinsta,
    00060             NULL);
    00061
    00062     if (!NT_SUCCESS(Status)) {
    00063         RIPNTERR1(Status, RIP_VERBOSE, "ValidateHwinsta failed for %#p", hwinsta);
    00064
    00065     } else if ((*ppwinsta)->dwSessionId != gSessionId) {
    00066
    00067         RIPNTERR3(STATUS_INVALID_HANDLE, RIP_WARNING,
    00068                   "SessionId %d. Wrong session id %d for pwinsta %#p",
    00069                   gSessionId, (*ppwinsta)->dwSessionId, *ppwinsta);
    00070
    00071         ObDereferenceObject(*ppwinsta);
    00072 #if DBG
    00073         *ppwinsta = NULL;
    00074 #endif // DBG
    00075
    00076         return STATUS_INVALID_HANDLE;
    00077     }
    00078
    00079     return Status;
    00080 }
    00081
    00082 /***************************************************************************\
    00083 * ValidateHdesk
    00084 *
    00085 * Validate desktop handle
    00086 *
    00087 * History:
    00088 * 03-29-91 JimA             Created.
    00089 * 06-20-95 JimA             Kernel-mode objects.
    00090 \***************************************************************************/
    00091
    00092 NTSTATUS ValidateHdesk(
    00093     HDESK           hdesk,
    00094     KPROCESSOR_MODE AccessMode,
    00095     ACCESS_MASK     amDesired,
    00096     PDESKTOP*       ppdesk)
    00097 {
    00098     NTSTATUS Status;
    00099
    00100     Status = ObReferenceObjectByHandle(
    00101             hdesk,
    00102             amDesired,
    00103             *ExDesktopObjectType,
    00104             AccessMode,
    00105             ppdesk,
    00106             NULL);
    00107
    00108     if (NT_SUCCESS(Status)) {
    00109
    00110         if ((*ppdesk)->dwSessionId != gSessionId) {
    00111
    00112             RIPNTERR3(STATUS_INVALID_HANDLE, RIP_WARNING,
    00113                       "SessionId %d. Wrong session id %d for pdesk %#p",
    00114                       gSessionId, (*ppdesk)->dwSessionId, *ppdesk);
    00115
    00116             goto Error;
    00117         }
    00118
    00119         LogDesktop(*ppdesk, LDL_VALIDATE_HDESK, TRUE, (ULONG_PTR)PtiCurrent());
    00120
    00121         if ((*ppdesk)->dwDTFlags & (DF_DESTROYED | DF_DESKWNDDESTROYED | DF_DYING)) {
    00122             RIPNTERR1(STATUS_INVALID_HANDLE, RIP_ERROR,
    00123                       "ValidateHdesk: destroyed desktop %#p",
    00124                       *ppdesk);
    00125 Error:
    00126             ObDereferenceObject(*ppdesk);
    00127 #if DBG
    00128             *ppdesk = NULL;
    00129 #endif // DBG
    00130
    00131             return STATUS_INVALID_HANDLE;
    00132         }
    00133     } else {
    00134         RIPNTERR1(Status, RIP_VERBOSE, "ValidateHdesk failed for %#p", hdesk);
    00135     }
    00136
    00137     return Status;
    00138 }
    00139
    00140 /***************************************************************************\
    00141 * UserValidateCopyRgn
    00142 *
    00143 * Validates a region-handle.  This essentially tries to copy the region
    00144 * in order to verify the region is valid.  If hrgn isn't a valid region,
    00145 * then the combine will fail.  We return a copy of the region.
    00146 *
    00147 * History:
    00148 * 24=Jan-1996   ChrisWil    Created.
    00149 \***************************************************************************/
    00150
    00151 HRGN UserValidateCopyRgn(
    00152     HRGN hrgn)
    00153 {
    00154     HRGN hrgnCopy = NULL;
    00155
    00156
    00157     if (hrgn && (GreValidateServerHandle(hrgn, RGN_TYPE))) {
    00158
    00159         hrgnCopy = CreateEmptyRgn();
    00160
    00161         if (CopyRgn(hrgnCopy, hrgn) == ERROR) {
    00162
    00163             GreDeleteObject(hrgnCopy);
    00164
    00165             hrgnCopy = NULL;
    00166         }
    00167     }
    00168
    00169     return hrgnCopy;
    00170 }
    00171
    00172 /***************************************************************************\
    00173 * ValidateHmenu
    00174 *
    00175 * Validate menu handle and open it
    00176 *
    00177 * History:
    00178 * 03-29-91 JimA             Created.
    00179 \***************************************************************************/
    00180
    00181 PMENU ValidateHmenu(
    00182     HMENU hmenu)
    00183 {
    00184     PTHREADINFO pti = PtiCurrentShared();
    00185     PMENU pmenuRet;
    00186
    00187     pmenuRet = (PMENU)HMValidateHandle(hmenu, TYPE_MENU);
    00188
    00189     if (pmenuRet != NULL &&
    00190             ((pti->rpdesk != NULL &&  // hack so console initialization works.
    00191             pmenuRet->head.rpdesk != pti->rpdesk))) {
    00192         RIPERR1(ERROR_INVALID_MENU_HANDLE, RIP_WARNING, "Invalid menu handle (%#p)", hmenu);
    00193         return NULL;
    00194     }
    00195
    00196     return pmenuRet;
    00197 }
    00198
    00199
    00200
    00201 /***************************************************************************\
    00202 * ValidateHmonitor
    00203 *
    00204 * Validate monitor handle and open it.
    00205 *
    00206 * History:
    00207 * 03-29-91 JimA             Created.
    00208 \***************************************************************************/
    00209
    00210 PMONITOR ValidateHmonitor(
    00211         HMONITOR hmonitor)
    00212 {
    00213     return (PMONITOR)HMValidateSharedHandle(hmonitor, TYPE_MONITOR);
    00214 }
    00215
    00216 /*
    00217  * The handle validation routines should be optimized for time, not size,
    00218  * since they get called so often.
    00219  */
    00220 #pragma optimize("t", on)
    00221
    00222 /***************************************************************************\
    00223 * IsHandleEntrySecure
    00224 *
    00225 * Validate a user handle for a restricted process bypassing the routine to
    00226 * get the handle entry.
    00227 *
    00228 * History:
    00229 * August 22, 97   CLupu      Created.
    00230 \***************************************************************************/
    00231
    00232 BOOL IsHandleEntrySecure(
    00233     HANDLE h,
    00234     PHE    phe)
    00235 {
    00236     DWORD        bCreateFlags;
    00237     PPROCESSINFO ppiOwner;
    00238     PPROCESSINFO ppiCurrent;
    00239     PW32JOB      pW32Job;
    00240     DWORD        ind;
    00241     PULONG_PTR    pgh;
    00242
    00243     /*
    00244      * get the current process
    00245      */
    00246     ppiCurrent = PpiCurrent();
    00247
    00248     if (ppiCurrent == NULL)
    00249         return TRUE;
    00250
    00251     UserAssert(ppiCurrent->pW32Job != NULL);
    00252
    00253     UserAssert(ppiCurrent->W32PF_Flags & W32PF_RESTRICTED);
    00254
    00255     /*
    00256      * get the process that owns the handle
    00257      */
    00258
    00259     bCreateFlags = gahti[phe->bType].bObjectCreateFlags;
    00260
    00261     ppiOwner = NULL;
    00262
    00263     if (bCreateFlags & OCF_PROCESSOWNED) {
    00264         ppiOwner = (PPROCESSINFO)phe->pOwner;
    00265     } else if (bCreateFlags & OCF_THREADOWNED) {
    00266
    00267         PTHREADINFO pti;
    00268
    00269         pti = (PTHREADINFO)phe->pOwner;
    00270
    00271         if (pti != NULL) {
    00272             ppiOwner = pti->ppi;
    00273         }
    00274     }
    00275
    00276     /*
    00277      * if the owner is NULL then consider the handle secure
    00278      */
    00279     if (ppiOwner == NULL)
    00280         return FALSE;
    00281
    00282
    00283     /*
    00284      * if the handle is owned by a process in the same job, then it's secure
    00285      */
    00286     if (ppiOwner->pW32Job == ppiCurrent->pW32Job)
    00287         return TRUE;
    00288
    00289     /*
    00290      * the handle is not owned by the current process
    00291      */
    00292
    00293     pW32Job = ppiCurrent->pW32Job;
    00294
    00295     if (pW32Job->pgh == NULL)
    00296         return FALSE;
    00297
    00298     pgh = pW32Job->pgh;
    00299
    00300     UserAssert(pW32Job->ughCrt <= pW32Job->ughMax);
    00301
    00302     for (ind = 0; ind < pW32Job->ughCrt; ind++) {
    00303         if (*(pgh + ind) == (ULONG_PTR)h) {
    00304             return TRUE;
    00305         }
    00306     }
    00307
    00308     return FALSE;
    00309 }
    00310
    00311
    00312 /***************************************************************************\
    00313 * ValidateHandleSecure
    00314 *
    00315 * Validate a user handle for a restricted process.
    00316 *
    00317 * History:
    00318 * July 29, 97   CLupu      Created.
    00319 \***************************************************************************/
    00320
    00321 BOOL ValidateHandleSecure(
    00322     HANDLE h)
    00323 {
    00324     PVOID pobj;
    00325
    00326     CheckCritInShared();
    00327
    00328     StartValidateHandleMacro(h)
    00329     BeginTypeValidateHandleMacro(pobj, TYPE_GENERIC)
    00330
    00331         if (IsHandleEntrySecure(h, phe)) {
    00332             return TRUE;
    00333         }
    00334
    00335     EndTypeValidateHandleMacro
    00336     EndValidateHandleMacro
    00337
    00338     return FALSE;
    00339 }
    00340
    00341 /***************************************************************************\
    00342 * ValidateHwnd
    00343 *
    00344 * History:
    00345 * 08-Feb-1991 mikeke
    00346 \***************************************************************************/
    00347
    00348 PWND FASTCALL ValidateHwnd(
    00349     HWND hwnd)
    00350 {
    00351     StartValidateHandleMacro(hwnd)
    00352
    00353         /*
    00354          * Now make sure the app is
    00355          * passing the right handle
    00356          * type for this api. If the
    00357          * handle is TYPE_FREE, this'll
    00358          * catch it.
    00359          */
    00360         if (phe->bType == TYPE_WINDOW) {
    00361
    00362             PTHREADINFO pti = PtiCurrentShared();
    00363
    00364             /*
    00365              * This is called from thunks for routines in the shared critsec.
    00366              */
    00367             PWND pwndRet = (PWND)phe->phead;
    00368
    00369             /*
    00370              * This test establishes that the window belongs to the current
    00371              * 'desktop'.. The two exceptions are for the desktop-window of
    00372              * the current desktop, which ends up belonging to another desktop,
    00373              * and when pti->rpdesk is NULL.  This last case happens for
    00374              * initialization of TIF_SYSTEMTHREAD threads (ie. console windows).
    00375              * IanJa doesn't know if we should be test TIF_CSRSSTHREAD here, but
    00376              * JohnC thinks the whole test below is no longer required ??? LATER
    00377              */
    00378
    00379             if (pwndRet != NULL) {
    00380                 if (phe->bFlags & HANDLEF_DESTROY) {
    00381                     RIPERR2(ERROR_INVALID_WINDOW_HANDLE,
    00382                         RIP_WARNING,"ValidateHwnd, hwnd %#p, pwnd %#p already destroyed\n",
    00383                             hwnd, pwndRet);
    00384                     return NULL;
    00385                 }
    00386                 if (GETPTI(pwndRet) == pti ||
    00387                        (
    00388                         (pwndRet->head.rpdesk == pti->rpdesk ||
    00389                          (pti->TIF_flags & TIF_SYSTEMTHREAD) ||  // | TIF_CSRSSTHREAD I think
    00390                          GetDesktopView(pti->ppi, pwndRet->head.rpdesk) !=
    00391                                 NULL))) {
    00392
    00393                     if (IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_HANDLES)) {
    00394
    00395                         /*
    00396                          * make sure this window belongs to this process
    00397                          */
    00398                         if (!IsHandleEntrySecure(hwnd, phe)) {
    00399                             RIPERR1(ERROR_INVALID_WINDOW_HANDLE,
    00400                                     RIP_WARNING,
    00401                                     "ValidateHwnd: Invalid hwnd (%#p) for restricted process\n",
    00402                                     hwnd);
    00403                             pwndRet = NULL;
    00404                         }
    00405                     }
    00406                     return pwndRet;
    00407                 }
    00408             }
    00409         }
    00410
    00411     EndValidateHandleMacro
    00412
    00413     RIPERR1(ERROR_INVALID_WINDOW_HANDLE,
    00414             RIP_WARNING,
    00415             "ValidateHwnd: Invalid hwnd (%#p)",
    00416             hwnd);
    00417     return NULL;
    00418 }
    00419
    00420 /*
    00421  * Switch back to default optimization.
    00422  */
    00423 #pragma optimize("", on)
    00424
    00425 /******************************Public*Routine******************************\
    00426 *
    00427 * UserCritSec routines
    00428 *
    00429 * Exposes an opaque interface to the user critical section for
    00430 * the WNDOBJ code in GRE
    00431 *
    00432 * Exposed as functions because they aren't time critical and it
    00433 * insulates GRE from rebuilding if the definitions of Enter/LeaveCrit change
    00434 *
    00435 * History:
    00436 *  Wed Sep 20 11:19:14 1995 -by-    Drew Bliss [drewb]
    00437 *   Created
    00438 *
    00439 \**************************************************************************/
    00440
    00441 #if DBG
    00442
    00443 #if defined(_X86_)
    00444
    00445     #define GetCallStack()  \
    00446     {                                                               \
    00447         ULONG Hash;                                                 \
    00448                                                                     \
    00449         gCritStack.thread  = PsGetCurrentThread();                  \
    00450         gCritStack.nFrames = GetStackTrace(1,                       \
    00451                                            MAX_STACK_CALLS,         \
    00452                                            gCritStack.trace,        \
    00453                                            &Hash);                  \
    00454     }
    00455
    00456     #define FlushCallStack()    \
    00457     {                                                               \
    00458         gCritStack.thread  = NULL;                                  \
    00459         gCritStack.nFrames = 0;                                     \
    00460     }
    00461
    00462 #else // defined(_X86_)
    00463
    00464     #define GetCallStack()
    00465     #define FlushCallStack()
    00466
    00467 #endif // defined(_X86_)
    00468
    00469
    00470 #endif // DBG
    00471
    00472 VOID UserEnterUserCritSec(VOID)
    00473 {
    00474     EnterCrit();
    00475 }
    00476
    00477 VOID UserLeaveUserCritSec(VOID)
    00478 {
    00479     LeaveCrit();
    00480 }
    00481
    00482 #if DBG
    00483 VOID UserAssertUserCritSecIn(VOID)
    00484 {
    00485     _AssertCritInShared();
    00486 }
    00487
    00488 VOID UserAssertUserCritSecOut(VOID)
    00489 {
    00490     _AssertCritOut();
    00491 }
    00492 #endif // DBG
    00493
    00494 BOOL UserGetCurrentDesktopId(DWORD* pdwDesktopId)
    00495 {
    00496     PDESKTOP pdesktop;
    00497
    00498     CheckCritIn();
    00499
    00500     /*
    00501      * PtiCurrent()->rpdesk can be NULL !!! (in the case of thread shutdown).
    00502      */
    00503
    00504     pdesktop = PtiCurrent()->rpdesk;
    00505
    00506     if (pdesktop != grpdeskRitInput) {
    00507         RIPMSG0(RIP_WARNING, "UserGetCurrentDesktopId on wrong desktop pdesk\n");
    00508         return FALSE;
    00509     }
    00510
    00511     *pdwDesktopId = pdesktop->dwDesktopId;
    00512
    00513     return TRUE;
    00514 }
    00515
    00516 #if 0
    00517
    00518 //
    00519 // Temporary arrays used to track critsec frees
    00520 //
    00521
    00522 #define ARRAY_SIZE 20
    00523 #define LEAVE_TYPE 0xf00d0000
    00524 #define ENTER_TYPE 0x0000dead
    00525
    00526 typedef struct _DEBUG_STASHCS {
    00527     RTL_CRITICAL_SECTION Lock;
    00528     DWORD Type;
    00529 } DEBUG_STASHCS, *PDEBUG_STASHCS;
    00530
    00531 DEBUG_STASHCS UserSrvArray[ARRAY_SIZE];
    00532
    00533 ULONG UserSrvIndex;
    00534
    00535 VOID
    00536 DumpArray(
    00537     HANDLE hCurrentProcess,
    00538     HANDLE hCurrentThread,
    00539     DWORD dwCurrentPc,
    00540     PNTSD_EXTENSION_APIS lpExtensionApis,
    00541     LPSTR lpArgumentString,
    00542     LPDWORD IndexAddress,
    00543     LPDWORD ArrayAddress
    00544     )
    00545 {
    00546     PNTSD_OUTPUT_ROUTINE Print;
    00547     PNTSD_GET_EXPRESSION EvalExpression;
    00548     PNTSD_GET_SYMBOL GetSymbol;
    00549
    00550     DWORD History;
    00551     int InitialIndex;
    00552     PDEBUG_STASHCS Array;
    00553     BOOL b;
    00554     PRTL_CRITICAL_SECTION CriticalSection;
    00555     CHAR Symbol[64], Symbol2[64];
    00556     DWORD Displacement, Displacement2;
    00557     int Position;
    00558     LPSTR p;
    00559
    00560     DBG_UNREFERENCED_PARAMETER(hCurrentThread);
    00561     DBG_UNREFERENCED_PARAMETER(dwCurrentPc);
    00562
    00563     Print = lpExtensionApis->lpOutputRoutine;
    00564     EvalExpression = lpExtensionApis->lpGetExpressionRoutine;
    00565     GetSymbol = lpExtensionApis->lpGetSymbolRoutine;
    00566
    00567     p = lpArgumentString;
    00568
    00569     History = 0;
    00570
    00571     if ( *p ) {
    00572         History = EvalExpression(p);
    00573         }
    00574     if ( History == 0 || History >= ARRAY_SIZE ) {
    00575         History = 10;
    00576         }
    00577
    00578     //
    00579     // Get the Current Index and the array.
    00580     //
    00581
    00582     b = ReadProcessMemory(
    00583             hCurrentProcess,
    00584             (LPVOID)IndexAddress,
    00585             &InitialIndex,
    00586             sizeof(InitialIndex),
    00587             NULL
    00588             );
    00589     if ( !b ) {
    00590         return;
    00591         }
    00592
    00593     Array = RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(UserSrvArray));
    00594     if ( !Array ) {
    00595         return;
    00596         }
    00597
    00598     b = ReadProcessMemory(
    00599             hCurrentProcess,
    00600             (LPVOID)ArrayAddress,
    00601             Array,
    00602             sizeof(UserSrvArray),
    00603             NULL
    00604             );
    00605     if ( !b ) {
    00606         RtlFreeHeap(RtlProcessHeap(), 0, Array);
    00607         return;
    00608         }
    00609
    00610     Position = 0;
    00611     while ( History ) {
    00612         InitialIndex--;
    00613         if ( InitialIndex < 0 ) {
    00614             InitialIndex = ARRAY_SIZE-1;
    00615             }
    00616
    00617         if (Array[InitialIndex].Type == LEAVE_TYPE ) {
    00618             (Print)("\n(%d) LEAVING Critical Section \n", Position);
    00619             } else {
    00620             (Print)("\n(%d) ENTERING Critical Section \n", Position);
    00621             }
    00622
    00623         CriticalSection = &Array[InitialIndex].Lock;
    00624
    00625         if ( CriticalSection->LockCount == -1) {
    00626             (Print)("\tLockCount NOT LOCKED\n");
    00627             } else {
    00628             (Print)("\tLockCount %ld\n", CriticalSection->LockCount);
    00629             }
    00630         (Print)("\tRecursionCount %ld\n", CriticalSection->RecursionCount);
    00631         (Print)("\tOwningThread %lx\n", CriticalSection->OwningThread );
    00632 #if DBG
    00633         (GetSymbol)(CriticalSection->OwnerBackTrace[ 0 ], Symbol, &Displacement);
    00634         (GetSymbol)(CriticalSection->OwnerBackTrace[ 1 ], Symbol2, &Displacement2);
    00635         (Print)("\tCalling Address %s+%lx\n", Symbol, Displacement);
    00636         (Print)("\tCallers Caller %s+%lx\n", Symbol2, Displacement2);
    00637 #endif // DBG
    00638         Position--;
    00639         History--;
    00640         }
    00641     RtlFreeHeap(RtlProcessHeap(), 0, Array);
    00642 }
    00643
    00644
    00645 VOID
    00646 dsrv(
    00647     HANDLE hCurrentProcess,
    00648     HANDLE hCurrentThread,
    00649     DWORD dwCurrentPc,
    00650     PNTSD_EXTENSION_APIS lpExtensionApis,
    00651     LPSTR lpArgumentString
    00652     )
    00653 {
    00654     DumpArray(
    00655         hCurrentProcess,
    00656         hCurrentThread,
    00657         dwCurrentPc,
    00658         lpExtensionApis,
    00659         lpArgumentString,
    00660         &UserSrvIndex,
    00661         (LPDWORD)&UserSrvArray[0]
    00662         );
    00663 }
    00664
    00665 #endif // if 0
    00666
    00667 #if DBG
    00668
    00669 #ifdef EXTRAHEAPCHECKING
    00670
    00671 VOID ValidateUserHeaps( VOID )
    00672 {
    00673     PWINDOWSTATION  pwinsta;
    00674     PDESKTOP        pdesk;
    00675
    00676     for (pwinsta = grpwinstaList; pwinsta; pwinsta = pwinsta->rpwinstaNext) {
    00677         for (pdesk = pwinsta->rpdeskList; pdesk; pdesk = pdesk->rpdeskNext) {
    00678             if (!wcscmp(pdesk->lpszDeskName, L"Default")) {
    00679                 RtlValidateHeap(Win32HeapGetHandle(pdesk->pheapDesktop), 0, NULL);  // desktop heaps
    00680             }
    00681         }
    00682     }
    00683 }
    00684
    00685 #endif // EXTRAHEAPCHECKING
    00686
    00687 /***************************************************************************\
    00688 * _EnterCrit
    00689 * _LeaveCrit
    00690 *
    00691 * These are temporary routines that are used by USER.DLL until the critsect,
    00692 * validation, mapping code is moved to the server-side stubs generated by
    00693 * SMeans' Thank compiler.
    00694 *
    00695 * History:
    00696 * 01-02-91 DarrinM      Created.
    00697 \***************************************************************************/
    00698
    00699 void _AssertCritIn()
    00700 {
    00701     UserAssert(gpresUser != NULL);
    00702     UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE);
    00703 }
    00704
    00705 void _AssertDeviceInfoListCritIn()
    00706 {
    00707     UserAssert(gpresDeviceInfoList != NULL);
    00708     UserAssert(ExIsResourceAcquiredExclusiveLite(gpresDeviceInfoList) == TRUE);
    00709 }
    00710
    00711 void _AssertCritInShared()
    00712 {
    00713     UserAssert(gpresUser != NULL);
    00714     UserAssert( (ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE) ||
    00715             (ExIsResourceAcquiredSharedLite(gpresUser) == TRUE));
    00716 }
    00717
    00718
    00719 void _AssertCritOut()
    00720 {
    00721     UserAssert(gpresUser != NULL);
    00722     UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == FALSE);
    00723 }
    00724
    00725 void _AssertDeviceInfoListCritOut()
    00726 {
    00727     UserAssert(gpresDeviceInfoList != NULL);
    00728     UserAssert(ExIsResourceAcquiredExclusiveLite(gpresDeviceInfoList) == FALSE);
    00729 }
    00730
    00731 /***************************************************************************\
    00732 * BeginAtomicCheck()
    00733 * EndAtomicCheck()
    00734 *
    00735 * Routine that verify we never leave the critical section and that an
    00736 * operation is truely atomic with the possiblity of other code being run
    00737 * because we left the critical section
    00738 *
    00739 \***************************************************************************/
    00740
    00741 void BeginAtomicCheck()
    00742 {
    00743     gdwInAtomicOperation++;
    00744 }
    00745
    00746 void EndAtomicCheck()
    00747 {
    00748     UserAssert(gdwInAtomicOperation > 0);
    00749     gdwInAtomicOperation--;
    00750 }
    00751
    00752 void BeginAtomicDeviceInfoListCheck()
    00753 {
    00754     gdwInAtomicDeviceInfoListOperation++;
    00755 }
    00756
    00757 void EndAtomicDeviceInfoListCheck()
    00758 {
    00759     UserAssert(gdwInAtomicDeviceInfoListOperation > 0);
    00760     gdwInAtomicDeviceInfoListOperation--;
    00761 }
    00762
    00763 #define INCCRITSECCOUNT (gdwCritSecUseCount++)
    00764 #define INCDEVICEINFOLISTCRITSECCOUNT (gdwDeviceInfoListCritSecUseCount++)
    00765
    00766 #else // else DBG
    00767
    00768 #define INCCRITSECCOUNT
    00769 #define INCDEVICEINFOLISTCRITSECCOUNT
    00770
    00771 #endif // endif DBG
    00772
    00773 BOOL UserIsUserCritSecIn()
    00774 {
    00775     UserAssert(gpresUser != NULL);
    00776     return( (ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE) ||
    00777             (ExIsResourceAcquiredSharedLite(gpresUser) == TRUE));
    00778
    00779     return(TRUE);
    00780 }
    00781
    00782 #if DBG
    00783 void CheckDevLockOut()
    00784 {
    00785     /*
    00786      * gpDispInfo can be NULL if Win32UserInitialize fails before allocationg it.
    00787      * hDev is initialized later in InitVideo, after the critical section has been
    00788      *  released at least once; so we better check it too.
    00789      */
    00790     if ((gpDispInfo != NULL) && (gpDispInfo->hDev != NULL)) {
    00791         UserAssert(!GreIsDisplayLocked(gpDispInfo->hDev));
    00792     }
    00793 }
    00794 #else
    00795 #define CheckDevLockOut()
    00796 #endif
    00797
    00798 void EnterCrit(void)
    00799 {
    00800     CheckCritOut();
    00801     CheckDeviceInfoListCritOut();
    00802     KeEnterCriticalRegion();
    00803     ExAcquireResourceExclusiveLite(gpresUser, TRUE);
    00804     CheckDevLockOut();
    00805     UserAssert(!ISATOMICCHECK());
    00806     UserAssert(gptiCurrent == NULL);
    00807     gptiCurrent = ((PTHREADINFO)(W32GetCurrentThread()));
    00808     INCCRITSECCOUNT;
    00809 #if defined (USER_PERFORMANCE)
    00810     {
    00811         __int64 i64Frecv;
    00812         *(LARGE_INTEGER*)(&gCSTimeExclusiveWhenEntering) = KeQueryPerformanceCounter((LARGE_INTEGER*)&i64Frecv);
    00813         InterlockedIncrement(&gCSStatistics.cExclusive);
    00814     }
    00815 #endif // (USER_PERFORMANCE)
    00816
    00817 #if DBG
    00818     GetCallStack();
    00819 #endif // DBG
    00820 }
    00821
    00822 #if DBG
    00823 void EnterDeviceInfoListCrit(void)
    00824 {
    00825     CheckDeviceInfoListCritOut();
    00826     KeEnterCriticalRegion();
    00827     ExAcquireResourceExclusiveLite(gpresDeviceInfoList, TRUE);
    00828     UserAssert(!ISATOMICDEVICEINFOLISTCHECK());
    00829     INCDEVICEINFOLISTCRITSECCOUNT;
    00830 }
    00831 #endif // DBG
    00832
    00833 void EnterSharedCrit(void)
    00834 {
    00835     KeEnterCriticalRegion();
    00836     ExAcquireResourceSharedLite(gpresUser, TRUE);
    00837     CheckDevLockOut();
    00838     UserAssert(!ISATOMICCHECK());
    00839 #if defined (USER_PERFORMANCE)
    00840     InterlockedIncrement(&gCSStatistics.cShared);
    00841 #endif // (USER_PERFORMANCE)
    00842
    00843     INCCRITSECCOUNT;
    00844 }
    00845
    00846 void LeaveCrit(void)
    00847 {
    00848     INCCRITSECCOUNT;
    00849 #if DBG
    00850     UserAssert(!ISATOMICCHECK());
    00851     UserAssert(IsWinEventNotifyDeferredOK());
    00852     CheckDevLockOut();
    00853     FlushCallStack();
    00854     gptiCurrent = NULL;
    00855 #endif // DBG
    00856
    00857 #if defined (USER_PERFORMANCE)
    00858     /*
    00859      * A non null gCSTimeExclusiveWhenEntering means the
    00860      * critical section is owned exclusive
    00861      */
    00862     if (gCSTimeExclusiveWhenEntering) {
    00863         __int64 i64Temp, i64Frecv;
    00864
    00865         *(LARGE_INTEGER*)(&i64Temp) = KeQueryPerformanceCounter((LARGE_INTEGER*)&i64Frecv);
    00866         gCSStatistics.i64TimeExclusive += i64Temp - gCSTimeExclusiveWhenEntering;
    00867         gCSTimeExclusiveWhenEntering = 0;
    00868     }
    00869 #endif // (USER_PERFORMANCE)
    00870     ExReleaseResource(gpresUser);
    00871     KeLeaveCriticalRegion();
    00872     CheckCritOut();
    00873 }
    00874
    00875 #if DBG
    00876 void _LeaveDeviceInfoListCrit(void)
    00877 {
    00878     INCDEVICEINFOLISTCRITSECCOUNT;
    00879     UserAssert(!ISATOMICDEVICEINFOLISTCHECK());
    00880
    00881     ExReleaseResource(gpresDeviceInfoList);
    00882     KeLeaveCriticalRegion();
    00883     CheckDeviceInfoListCritOut();
    00884 }
    00885 #endif // DBG
    00886
    00887 VOID ChangeAcquireResourceType(
    00888     VOID)
    00889 {
    00890 #if DBG
    00891     FlushCallStack();
    00892     CheckDevLockOut();
    00893     UserAssert(!ISATOMICCHECK());
    00894 #endif // DBG
    00895     ExReleaseResource(gpresUser);
    00896     ExAcquireResourceExclusiveLite(gpresUser, TRUE);
    00897     gptiCurrent = ((PTHREADINFO)(W32GetCurrentThread()));
    00898 #if DBG
    00899     GetCallStack();
    00900 #endif // DBG
    00901 }
    00902
    00903
    00904 #if DBG
    00905
    00906 PTHREADINFO _ptiCrit(void)
    00907 {
    00908     UserAssert(gpresUser);
    00909     UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE);
    00910     UserAssert(gptiCurrent);
    00911     UserAssert(gptiCurrent == ((PTHREADINFO)(W32GetCurrentThread())));
    00912     UserAssert(gptiCurrent);
    00913     return gptiCurrent;
    00914 }
    00915
    00916 PTHREADINFO _ptiCritShared(void)
    00917 {
    00918     UserAssert(W32GetCurrentThread());
    00919     return ((PTHREADINFO)(W32GetCurrentThread()));
    00920 }
    00921
    00922 #undef KeUserModeCallback
    00923
    00924 NTSTATUS
    00925 _KeUserModeCallback (
    00926     IN ULONG ApiNumber,
    00927     IN PVOID InputBuffer,
    00928     IN ULONG InputLength,
    00929     OUT PVOID *OutputBuffer,
    00930     OUT PULONG OutputLength
    00931     )
    00932 {
    00933
    00934     UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == FALSE);
    00935
    00936     /*
    00937      * Added this so we can detect an erroneous user mode callback
    00938      * with a checked win32k on top of a free system.
    00939      */
    00940     ASSERT(KeGetPreviousMode() == UserMode);
    00941
    00942     return KeUserModeCallback( ApiNumber, InputBuffer, InputLength,
    00943             OutputBuffer, OutputLength);
    00944 }
    00945
    00946 #endif