Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

902 lines
24 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: validate.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains functions for validating windows, menus, cursors, etc.
  7. *
  8. * History:
  9. * 01-02-91 DarrinM Created.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /*
  14. * These defines are used for using the validation macros
  15. * StartValidateHandleMacro and EndValidateHandleMacro.
  16. */
  17. #define ClientSharedInfo() (&gSharedInfo)
  18. #define ServerInfo() (gpsi)
  19. #include "wow.h"
  20. #if DBG
  21. CRITSTACK gCritStack;
  22. #endif
  23. #ifdef USER_PERFORMANCE
  24. __int64 gCSTimeExclusiveWhenEntering;
  25. #endif
  26. /***************************************************************************\
  27. * ValidateHwinsta
  28. *
  29. * Validate windowstation handle
  30. *
  31. * History:
  32. * 03-29-91 JimA Created.
  33. * 06-20-95 JimA Kernel-mode objects.
  34. \***************************************************************************/
  35. NTSTATUS ValidateHwinsta(
  36. HWINSTA hwinsta,
  37. KPROCESSOR_MODE AccessMode,
  38. ACCESS_MASK amDesired,
  39. PWINDOWSTATION *ppwinsta)
  40. {
  41. NTSTATUS Status;
  42. Status = ObReferenceObjectByHandle(hwinsta,
  43. amDesired,
  44. *ExWindowStationObjectType,
  45. AccessMode,
  46. ppwinsta,
  47. NULL);
  48. if (!NT_SUCCESS(Status)) {
  49. RIPNTERR1(Status,
  50. RIP_WARNING,
  51. "ValidateHwinsta failed for 0x%p",
  52. hwinsta);
  53. } else if ((*ppwinsta)->dwSessionId != gSessionId) {
  54. RIPNTERR3(STATUS_INVALID_HANDLE,
  55. RIP_WARNING,
  56. "SessionId %d does not match id %d for pwinsta 0x%p",
  57. gSessionId,
  58. (*ppwinsta)->dwSessionId,
  59. *ppwinsta);
  60. ObDereferenceObject(*ppwinsta);
  61. return STATUS_INVALID_HANDLE;
  62. }
  63. return Status;
  64. }
  65. /***************************************************************************\
  66. * ValidateHdesk
  67. *
  68. * Validate desktop handle
  69. *
  70. * History:
  71. * 03-29-91 JimA Created.
  72. * 06-20-95 JimA Kernel-mode objects.
  73. \***************************************************************************/
  74. NTSTATUS ValidateHdesk(
  75. HDESK hdesk,
  76. KPROCESSOR_MODE AccessMode,
  77. ACCESS_MASK amDesired,
  78. PDESKTOP* ppdesk)
  79. {
  80. NTSTATUS Status;
  81. Status = ObReferenceObjectByHandle(hdesk,
  82. amDesired,
  83. *ExDesktopObjectType,
  84. AccessMode,
  85. ppdesk,
  86. NULL);
  87. if (NT_SUCCESS(Status)) {
  88. if ((*ppdesk)->dwSessionId != gSessionId) {
  89. RIPNTERR3(STATUS_INVALID_HANDLE,
  90. RIP_WARNING,
  91. "SessionId %d does not match id %d for pdesk 0x%p",
  92. gSessionId,
  93. (*ppdesk)->dwSessionId,
  94. *ppdesk);
  95. goto Error;
  96. }
  97. LogDesktop(*ppdesk, LDL_VALIDATE_HDESK, TRUE, (ULONG_PTR)PtiCurrent());
  98. if ((*ppdesk)->dwDTFlags & (DF_DESTROYED | DF_DESKWNDDESTROYED | DF_DYING)) {
  99. RIPNTERR1(STATUS_INVALID_HANDLE,
  100. RIP_WARNING,
  101. "ValidateHdesk: destroyed desktop 0x%p",
  102. *ppdesk);
  103. Error:
  104. ObDereferenceObject(*ppdesk);
  105. return STATUS_INVALID_HANDLE;
  106. }
  107. } else {
  108. RIPNTERR1(Status,
  109. RIP_WARNING,
  110. "ValidateHdesk failed for 0x%p",
  111. hdesk);
  112. }
  113. return Status;
  114. }
  115. /***************************************************************************\
  116. * UserValidateCopyRgn
  117. *
  118. * Validates a region-handle. This essentially tries to copy the region
  119. * in order to verify the region is valid. If hrgn isn't a valid region,
  120. * then the combine will fail. We return a copy of the region.
  121. *
  122. * History:
  123. * 24=Jan-1996 ChrisWil Created.
  124. \***************************************************************************/
  125. HRGN UserValidateCopyRgn(
  126. HRGN hrgn)
  127. {
  128. HRGN hrgnCopy = NULL;
  129. if (hrgn && (GreValidateServerHandle(hrgn, RGN_TYPE))) {
  130. hrgnCopy = CreateEmptyRgn();
  131. if (CopyRgn(hrgnCopy, hrgn) == ERROR) {
  132. GreDeleteObject(hrgnCopy);
  133. hrgnCopy = NULL;
  134. }
  135. }
  136. return hrgnCopy;
  137. }
  138. /***************************************************************************\
  139. * ValidateHmenu
  140. *
  141. * Validate menu handle and open it.
  142. *
  143. * History:
  144. * 03-29-91 JimA Created.
  145. \***************************************************************************/
  146. PMENU ValidateHmenu(
  147. HMENU hmenu)
  148. {
  149. PTHREADINFO pti = PtiCurrentShared();
  150. PMENU pmenuRet;
  151. pmenuRet = (PMENU)HMValidateHandle(hmenu, TYPE_MENU);
  152. if (pmenuRet != NULL && pmenuRet->head.rpdesk != pti->rpdesk) {
  153. RIPERR1(ERROR_INVALID_MENU_HANDLE,
  154. RIP_WARNING,
  155. "Invalid menu handle 0x%p",
  156. hmenu);
  157. return NULL;
  158. }
  159. return pmenuRet;
  160. }
  161. /***************************************************************************\
  162. * ValidateHmonitor
  163. *
  164. * Validate monitor handle and open it.
  165. *
  166. * History:
  167. * 03-29-91 JimA Created.
  168. \***************************************************************************/
  169. PMONITOR ValidateHmonitor(
  170. HMONITOR hmonitor)
  171. {
  172. return (PMONITOR)HMValidateSharedHandle(hmonitor, TYPE_MONITOR);
  173. }
  174. /*
  175. * The handle validation routines should be optimized for time, not size,
  176. * since they get called so often.
  177. */
  178. #pragma optimize("t", on)
  179. /***************************************************************************\
  180. * IsHandleEntrySecure
  181. *
  182. * Validate a user handle for a restricted process bypassing the routine to
  183. * get the handle entry.
  184. *
  185. * History:
  186. * August 22, 97 CLupu Created.
  187. \***************************************************************************/
  188. BOOL IsHandleEntrySecure(
  189. HANDLE h,
  190. PHE phe)
  191. {
  192. DWORD bCreateFlags;
  193. PPROCESSINFO ppiOwner;
  194. PPROCESSINFO ppiCurrent;
  195. PW32JOB pW32Job;
  196. DWORD ind;
  197. PULONG_PTR pgh;
  198. ppiCurrent = PpiCurrent();
  199. if (ppiCurrent == NULL) {
  200. return TRUE;
  201. }
  202. UserAssert(ppiCurrent->pW32Job != NULL);
  203. UserAssert(ppiCurrent->W32PF_Flags & W32PF_RESTRICTED);
  204. /*
  205. * Get the process that owns the handle.
  206. */
  207. bCreateFlags = gahti[phe->bType].bObjectCreateFlags;
  208. ppiOwner = NULL;
  209. if (bCreateFlags & OCF_PROCESSOWNED) {
  210. ppiOwner = (PPROCESSINFO)phe->pOwner;
  211. } else if (bCreateFlags & OCF_THREADOWNED) {
  212. PTHREADINFO pti = (PTHREADINFO)phe->pOwner;
  213. if (pti != NULL) {
  214. ppiOwner = pti->ppi;
  215. }
  216. }
  217. /*
  218. * If the owner is NULL then consider the handle secure.
  219. */
  220. if (ppiOwner == NULL) {
  221. return FALSE;
  222. }
  223. /*
  224. * If the handle is owned by a process in the same job, then it's secure.
  225. */
  226. if (ppiOwner->pW32Job == ppiCurrent->pW32Job) {
  227. return TRUE;
  228. }
  229. /*
  230. * The handle is not owned by the current process.
  231. */
  232. pW32Job = ppiCurrent->pW32Job;
  233. if (pW32Job->pgh == NULL) {
  234. return FALSE;
  235. }
  236. pgh = pW32Job->pgh;
  237. UserAssert(pW32Job->ughCrt <= pW32Job->ughMax);
  238. for (ind = 0; ind < pW32Job->ughCrt; ind++) {
  239. if (*(pgh + ind) == (ULONG_PTR)h) {
  240. return TRUE;
  241. }
  242. }
  243. return FALSE;
  244. }
  245. /***************************************************************************\
  246. * ValidateHandleSecure
  247. *
  248. * Validate a user handle for a restricted process.
  249. *
  250. * History:
  251. * July 29, 97 CLupu Created.
  252. \***************************************************************************/
  253. BOOL ValidateHandleSecure(
  254. HANDLE h)
  255. {
  256. PVOID pobj;
  257. CheckCritInShared();
  258. StartValidateHandleMacro(h)
  259. BeginTypeValidateHandleMacro(pobj, TYPE_GENERIC)
  260. if (IsHandleEntrySecure(h, phe)) {
  261. return TRUE;
  262. }
  263. EndTypeValidateHandleMacro
  264. EndValidateHandleMacro
  265. return FALSE;
  266. }
  267. /***************************************************************************\
  268. * ValidateHwnd
  269. *
  270. * History:
  271. * 08-Feb-1991 mikeke
  272. \***************************************************************************/
  273. PWND FASTCALL ValidateHwnd(
  274. HWND hwnd)
  275. {
  276. StartValidateHandleMacro(hwnd)
  277. /*
  278. * Now make sure the app is passing the right handle type for this
  279. * api. If the handle is TYPE_FREE, this'll catch it.
  280. */
  281. if (phe->bType == TYPE_WINDOW) {
  282. PTHREADINFO pti = PtiCurrentShared();
  283. PWND pwndRet = (PWND)phe->phead;
  284. /*
  285. * This test establishes that the window belongs to the current
  286. * 'desktop'.. The two exceptions are for the desktop-window of
  287. * the current desktop, which ends up belonging to another desktop,
  288. * and when pti->rpdesk is NULL. This last case happens for
  289. * initialization of TIF_SYSTEMTHREAD threads (ie. console windows).
  290. * IanJa doesn't know if we should be test TIF_CSRSSTHREAD here, but
  291. * JohnC thinks the whole test below is no longer required ??? LATER
  292. */
  293. if (pwndRet != NULL) {
  294. if (phe->bFlags & HANDLEF_DESTROY) {
  295. RIPERR2(ERROR_INVALID_WINDOW_HANDLE,
  296. RIP_WARNING,"ValidateHwnd, hwnd %#p, pwnd %#p already destroyed\n",
  297. hwnd, pwndRet);
  298. return NULL;
  299. }
  300. if (GETPTI(pwndRet) == pti ||
  301. (
  302. (pwndRet->head.rpdesk == pti->rpdesk ||
  303. (pti->TIF_flags & TIF_SYSTEMTHREAD) || // | TIF_CSRSSTHREAD I think
  304. GetDesktopView(pti->ppi, pwndRet->head.rpdesk) !=
  305. NULL))) {
  306. if (IS_THREAD_RESTRICTED(pti, JOB_OBJECT_UILIMIT_HANDLES)) {
  307. /*
  308. * make sure this window belongs to this process
  309. */
  310. if (!IsHandleEntrySecure(hwnd, phe)) {
  311. RIPERR1(ERROR_INVALID_WINDOW_HANDLE,
  312. RIP_WARNING,
  313. "ValidateHwnd: Invalid hwnd (%#p) for restricted process\n",
  314. hwnd);
  315. pwndRet = NULL;
  316. }
  317. }
  318. return pwndRet;
  319. }
  320. }
  321. }
  322. EndValidateHandleMacro
  323. RIPERR1(ERROR_INVALID_WINDOW_HANDLE,
  324. RIP_WARNING,
  325. "ValidateHwnd: Invalid hwnd (%#p)",
  326. hwnd);
  327. return NULL;
  328. }
  329. /*
  330. * Switch back to default optimization.
  331. */
  332. #pragma optimize("", on)
  333. /******************************Public*Routine******************************\
  334. *
  335. * UserCritSec routines
  336. *
  337. * Exposes an opaque interface to the user critical section for
  338. * the WNDOBJ code in GRE
  339. *
  340. * Exposed as functions because they aren't time critical and it
  341. * insulates GRE from rebuilding if the definitions of Enter/LeaveCrit change
  342. *
  343. * History:
  344. * Wed Sep 20 11:19:14 1995 -by- Drew Bliss [drewb]
  345. * Created
  346. *
  347. \**************************************************************************/
  348. #if DBG
  349. #define GetCallStack() \
  350. { \
  351. gCritStack.thread = PsGetCurrentThread(); \
  352. gCritStack.nFrames = RtlWalkFrameChain(gCritStack.trace, \
  353. MAX_STACK_CALLS, \
  354. 0); \
  355. }
  356. #define FlushCallStack() \
  357. { \
  358. gCritStack.thread = NULL; \
  359. gCritStack.nFrames = 0; \
  360. }
  361. #else
  362. #define GetCallStack()
  363. #define FlushCallStack()
  364. #endif // DBG
  365. VOID UserEnterUserCritSec(
  366. VOID)
  367. {
  368. EnterCrit();
  369. }
  370. VOID UserLeaveUserCritSec(
  371. VOID)
  372. {
  373. LeaveCrit();
  374. }
  375. #if DBG
  376. VOID UserAssertUserCritSecIn(
  377. VOID)
  378. {
  379. _AssertCritInShared();
  380. }
  381. VOID UserAssertUserCritSecOut(
  382. VOID)
  383. {
  384. _AssertCritOut();
  385. }
  386. #endif // DBG
  387. BOOL UserGetCurrentDesktopId(
  388. DWORD* pdwDesktopId)
  389. {
  390. PDESKTOP pdesktop;
  391. CheckCritIn();
  392. /*
  393. * PtiCurrent()->rpdesk can be NULL (in the case of thread shutdown).
  394. */
  395. pdesktop = PtiCurrent()->rpdesk;
  396. if (pdesktop != grpdeskRitInput) {
  397. RIPMSG0(RIP_WARNING, "UserGetCurrentDesktopId on wrong desktop pdesk\n");
  398. return FALSE;
  399. }
  400. *pdwDesktopId = pdesktop->dwDesktopId;
  401. return TRUE;
  402. }
  403. #if 0
  404. //
  405. // Temporary arrays used to track critsec frees
  406. //
  407. #define ARRAY_SIZE 20
  408. #define LEAVE_TYPE 0xf00d0000
  409. #define ENTER_TYPE 0x0000dead
  410. typedef struct _DEBUG_STASHCS {
  411. RTL_CRITICAL_SECTION Lock;
  412. DWORD Type;
  413. } DEBUG_STASHCS, *PDEBUG_STASHCS;
  414. DEBUG_STASHCS UserSrvArray[ARRAY_SIZE];
  415. ULONG UserSrvIndex;
  416. VOID
  417. DumpArray(
  418. HANDLE hCurrentProcess,
  419. HANDLE hCurrentThread,
  420. DWORD dwCurrentPc,
  421. PNTSD_EXTENSION_APIS lpExtensionApis,
  422. LPSTR lpArgumentString,
  423. LPDWORD IndexAddress,
  424. LPDWORD ArrayAddress
  425. )
  426. {
  427. PNTSD_OUTPUT_ROUTINE Print;
  428. PNTSD_GET_EXPRESSION EvalExpression;
  429. PNTSD_GET_SYMBOL GetSymbol;
  430. DWORD History;
  431. int InitialIndex;
  432. PDEBUG_STASHCS Array;
  433. BOOL b;
  434. PRTL_CRITICAL_SECTION CriticalSection;
  435. CHAR Symbol[64], Symbol2[64];
  436. DWORD Displacement, Displacement2;
  437. int Position;
  438. LPSTR p;
  439. DBG_UNREFERENCED_PARAMETER(hCurrentThread);
  440. DBG_UNREFERENCED_PARAMETER(dwCurrentPc);
  441. Print = lpExtensionApis->lpOutputRoutine;
  442. EvalExpression = lpExtensionApis->lpGetExpressionRoutine;
  443. GetSymbol = lpExtensionApis->lpGetSymbolRoutine;
  444. p = lpArgumentString;
  445. History = 0;
  446. if (*p) {
  447. History = EvalExpression(p);
  448. }
  449. if (History == 0 || History >= ARRAY_SIZE) {
  450. History = 10;
  451. }
  452. //
  453. // Get the Current Index and the array.
  454. //
  455. b = ReadProcessMemory(
  456. hCurrentProcess,
  457. (LPVOID)IndexAddress,
  458. &InitialIndex,
  459. sizeof(InitialIndex),
  460. NULL
  461. );
  462. if (!b) {
  463. return;
  464. }
  465. Array = RtlAllocateHeap(RtlProcessHeap(), 0, sizeof(UserSrvArray));
  466. if (!Array) {
  467. return;
  468. }
  469. b = ReadProcessMemory(
  470. hCurrentProcess,
  471. (LPVOID)ArrayAddress,
  472. Array,
  473. sizeof(UserSrvArray),
  474. NULL
  475. );
  476. if (!b) {
  477. RtlFreeHeap(RtlProcessHeap(), 0, Array);
  478. return;
  479. }
  480. Position = 0;
  481. while (History) {
  482. InitialIndex--;
  483. if (InitialIndex < 0) {
  484. InitialIndex = ARRAY_SIZE - 1;
  485. }
  486. if (Array[InitialIndex].Type == LEAVE_TYPE) {
  487. (Print)("\n(%d) LEAVING Critical Section \n", Position);
  488. } else {
  489. (Print)("\n(%d) ENTERING Critical Section \n", Position);
  490. }
  491. CriticalSection = &Array[InitialIndex].Lock;
  492. if (CriticalSection->LockCount == -1) {
  493. (Print)("\tLockCount NOT LOCKED\n");
  494. } else {
  495. (Print)("\tLockCount %ld\n", CriticalSection->LockCount);
  496. }
  497. (Print)("\tRecursionCount %ld\n", CriticalSection->RecursionCount);
  498. (Print)("\tOwningThread %lx\n", CriticalSection->OwningThread );
  499. #if DBG
  500. (GetSymbol)(CriticalSection->OwnerBackTrace[0], Symbol, &Displacement);
  501. (GetSymbol)(CriticalSection->OwnerBackTrace[1], Symbol2, &Displacement2);
  502. (Print)("\tCalling Address %s+%lx\n", Symbol, Displacement);
  503. (Print)("\tCallers Caller %s+%lx\n", Symbol2, Displacement2);
  504. #endif // DBG
  505. Position--;
  506. History--;
  507. }
  508. RtlFreeHeap(RtlProcessHeap(), 0, Array);
  509. }
  510. VOID
  511. dsrv(
  512. HANDLE hCurrentProcess,
  513. HANDLE hCurrentThread,
  514. DWORD dwCurrentPc,
  515. PNTSD_EXTENSION_APIS lpExtensionApis,
  516. LPSTR lpArgumentString
  517. )
  518. {
  519. DumpArray(
  520. hCurrentProcess,
  521. hCurrentThread,
  522. dwCurrentPc,
  523. lpExtensionApis,
  524. lpArgumentString,
  525. &UserSrvIndex,
  526. (LPDWORD)&UserSrvArray[0]
  527. );
  528. }
  529. #endif // if 0
  530. #if DBG
  531. /***************************************************************************\
  532. * _EnterCrit
  533. * _LeaveCrit
  534. *
  535. * These are temporary routines that are used by USER.DLL until the critsect,
  536. * validation, mapping code is moved to the server-side stubs generated by
  537. * SMeans' Thank compiler.
  538. *
  539. * History:
  540. * 01-02-91 DarrinM Created.
  541. \***************************************************************************/
  542. VOID _AssertCritIn(
  543. VOID)
  544. {
  545. UserAssert(gpresUser != NULL);
  546. UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE);
  547. }
  548. VOID _AssertDeviceInfoListCritIn(
  549. VOID)
  550. {
  551. UserAssert(gpresDeviceInfoList != NULL);
  552. UserAssert(ExIsResourceAcquiredExclusiveLite(gpresDeviceInfoList) == TRUE);
  553. }
  554. VOID _AssertCritInShared(
  555. VOID)
  556. {
  557. UserAssert(gpresUser != NULL);
  558. UserAssert( (ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE) ||
  559. (ExIsResourceAcquiredSharedLite(gpresUser) == TRUE));
  560. }
  561. VOID _AssertCritOut(
  562. VOID)
  563. {
  564. UserAssert(gpresUser != NULL);
  565. UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == FALSE);
  566. }
  567. VOID _AssertDeviceInfoListCritOut(
  568. VOID)
  569. {
  570. UserAssert(gpresDeviceInfoList != NULL);
  571. UserAssert(ExIsResourceAcquiredExclusiveLite(gpresDeviceInfoList) == FALSE);
  572. }
  573. /***************************************************************************\
  574. * BeginAtomicCheck()
  575. * EndAtomicCheck()
  576. *
  577. * Routine that verify we never leave the critical section and that an
  578. * operation is truely atomic with the possiblity of other code being run
  579. * because we left the critical section
  580. *
  581. \***************************************************************************/
  582. VOID BeginAtomicCheck(
  583. VOID)
  584. {
  585. gdwInAtomicOperation++;
  586. }
  587. VOID EndAtomicCheck(
  588. VOID)
  589. {
  590. UserAssert(gdwInAtomicOperation > 0);
  591. gdwInAtomicOperation--;
  592. }
  593. VOID BeginAtomicDeviceInfoListCheck(
  594. VOID)
  595. {
  596. gdwInAtomicDeviceInfoListOperation++;
  597. }
  598. VOID EndAtomicDeviceInfoListCheck(
  599. VOID)
  600. {
  601. UserAssert(gdwInAtomicDeviceInfoListOperation > 0);
  602. gdwInAtomicDeviceInfoListOperation--;
  603. }
  604. #define INCCRITSECCOUNT (gdwCritSecUseCount++)
  605. #define INCDEVICEINFOLISTCRITSECCOUNT (gdwDeviceInfoListCritSecUseCount++)
  606. #else // else DBG
  607. #define INCCRITSECCOUNT
  608. #define INCDEVICEINFOLISTCRITSECCOUNT
  609. #endif // endif DBG
  610. BOOL UserIsUserCritSecIn(
  611. VOID)
  612. {
  613. UserAssert(gpresUser != NULL);
  614. return ((ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE) ||
  615. (ExIsResourceAcquiredSharedLite(gpresUser) == TRUE));
  616. }
  617. #if DBG
  618. VOID CheckDevLockOut(
  619. VOID)
  620. {
  621. /*
  622. * gpDispInfo can be NULL if Win32UserInitialize fails before allocating
  623. * it. hDev is initialized later in InitVideo, after the critical
  624. * section has been released at least once, so we better check it too.
  625. */
  626. if (gpDispInfo != NULL && gpDispInfo->hDev != NULL) {
  627. UserAssert(!GreIsDisplayLocked(gpDispInfo->hDev));
  628. }
  629. }
  630. #else
  631. #define CheckDevLockOut()
  632. #endif
  633. VOID EnterCrit(
  634. VOID)
  635. {
  636. CheckCritOut();
  637. CheckDeviceInfoListCritOut();
  638. KeEnterCriticalRegion();
  639. ExAcquireResourceExclusiveLite(gpresUser, TRUE);
  640. CheckDevLockOut();
  641. UserAssert(!ISATOMICCHECK());
  642. UserAssert(gptiCurrent == NULL);
  643. gptiCurrent = ((PTHREADINFO)(W32GetCurrentThread()));
  644. INCCRITSECCOUNT;
  645. #if defined (USER_PERFORMANCE)
  646. {
  647. __int64 i64Frecv;
  648. *(LARGE_INTEGER*)(&gCSTimeExclusiveWhenEntering) = KeQueryPerformanceCounter((LARGE_INTEGER*)&i64Frecv);
  649. InterlockedIncrement(&gCSStatistics.cExclusive);
  650. }
  651. #endif // (USER_PERFORMANCE)
  652. GetCallStack();
  653. }
  654. #if DBG
  655. VOID EnterDeviceInfoListCrit(
  656. VOID)
  657. {
  658. CheckDeviceInfoListCritOut();
  659. KeEnterCriticalRegion();
  660. ExAcquireResourceExclusiveLite(gpresDeviceInfoList, TRUE);
  661. UserAssert(!ISATOMICDEVICEINFOLISTCHECK());
  662. INCDEVICEINFOLISTCRITSECCOUNT;
  663. }
  664. #endif // DBG
  665. VOID EnterSharedCrit(
  666. VOID)
  667. {
  668. KeEnterCriticalRegion();
  669. ExAcquireResourceSharedLite(gpresUser, TRUE);
  670. CheckDevLockOut();
  671. UserAssert(!ISATOMICCHECK());
  672. #if defined (USER_PERFORMANCE)
  673. InterlockedIncrement(&gCSStatistics.cShared);
  674. #endif // (USER_PERFORMANCE)
  675. INCCRITSECCOUNT;
  676. }
  677. VOID LeaveCrit(
  678. VOID)
  679. {
  680. INCCRITSECCOUNT;
  681. #if DBG
  682. UserAssert(!ISATOMICCHECK());
  683. UserAssert(IsWinEventNotifyDeferredOK());
  684. CheckDevLockOut();
  685. FlushCallStack();
  686. gptiCurrent = NULL;
  687. #endif // DBG
  688. #ifdef USER_PERFORMANCE
  689. /*
  690. * A non null gCSTimeExclusiveWhenEntering means the
  691. * critical section is owned exclusive
  692. */
  693. if (gCSTimeExclusiveWhenEntering) {
  694. __int64 i64Temp, i64Frecv;
  695. *(LARGE_INTEGER*)(&i64Temp) = KeQueryPerformanceCounter((LARGE_INTEGER*)&i64Frecv);
  696. gCSStatistics.i64TimeExclusive += i64Temp - gCSTimeExclusiveWhenEntering;
  697. gCSTimeExclusiveWhenEntering = 0;
  698. }
  699. #endif // USER_PERFORMANCE
  700. ExReleaseResourceLite(gpresUser);
  701. KeLeaveCriticalRegion();
  702. CheckCritOut();
  703. }
  704. #if DBG
  705. VOID _LeaveDeviceInfoListCrit(
  706. VOID)
  707. {
  708. INCDEVICEINFOLISTCRITSECCOUNT;
  709. UserAssert(!ISATOMICDEVICEINFOLISTCHECK());
  710. ExReleaseResourceLite(gpresDeviceInfoList);
  711. KeLeaveCriticalRegion();
  712. CheckDeviceInfoListCritOut();
  713. }
  714. #endif // DBG
  715. VOID ChangeAcquireResourceType(
  716. VOID)
  717. {
  718. #if DBG
  719. FlushCallStack();
  720. CheckDevLockOut();
  721. UserAssert(!ISATOMICCHECK());
  722. #endif // DBG
  723. ExReleaseResourceLite(gpresUser);
  724. ExAcquireResourceExclusiveLite(gpresUser, TRUE);
  725. gptiCurrent = ((PTHREADINFO)(W32GetCurrentThread()));
  726. GetCallStack();
  727. }
  728. #if DBG
  729. PTHREADINFO _ptiCrit(
  730. VOID)
  731. {
  732. UserAssert(gpresUser);
  733. UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == TRUE);
  734. UserAssert(gptiCurrent);
  735. UserAssert(gptiCurrent == ((PTHREADINFO)(W32GetCurrentThread())));
  736. UserAssert(gptiCurrent);
  737. return gptiCurrent;
  738. }
  739. PTHREADINFO _ptiCritShared(
  740. VOID)
  741. {
  742. UserAssert(W32GetCurrentThread());
  743. return ((PTHREADINFO)(W32GetCurrentThread()));
  744. }
  745. #undef KeUserModeCallback
  746. NTSTATUS
  747. _KeUserModeCallback (
  748. IN ULONG ApiNumber,
  749. IN PVOID InputBuffer,
  750. IN ULONG InputLength,
  751. OUT PVOID *OutputBuffer,
  752. OUT PULONG OutputLength)
  753. {
  754. UserAssert(ExIsResourceAcquiredExclusiveLite(gpresUser) == FALSE);
  755. /*
  756. * Added this so we can detect an erroneous user mode callback
  757. * with a checked win32k on top of a free system.
  758. */
  759. UserAssert(PsGetCurrentThreadPreviousMode() == UserMode);
  760. return KeUserModeCallback(ApiNumber, InputBuffer, InputLength,
  761. OutputBuffer, OutputLength);
  762. }
  763. #endif // DBG