/*++ BUILD Version: 0001 // Increment this if a change has global effects Copyright (c) 1985 - 1999, Microsoft Corporation Module Name: usergdi.h Abstract: This module contains private USER functions used by GDI. All of these function are named Userxxx. Author: Chris Williams (chriswil) 25-May-1995 Revision History: --*/ #ifndef _USERGDI_ZWAPI_INC_ #define _USERGDI_ZWAPI_INC_ #include #endif extern PDRIVER_OBJECT gpWin32kDriverObject; VOID VideoPortCallout( IN PVOID Params ); BOOL FASTCALL UserScreenAccessCheck( VOID ); HDC UserGetDesktopDC( ULONG type, BOOL bAltType, BOOL bValidate ); BOOL UserReleaseDC( HDC hdc ); HDEV UserGetHDEV( VOID ); VOID UserAssociateHwnd( HWND hwnd, PVOID pwo ); HRGN UserGetClientRgn( HWND hwnd, LPRECT lprc, BOOL bWindowInsteadOfClient ); BOOL UserGetHwnd( HDC hdc, HWND *phwnd, PVOID *ppwo, BOOL bCheckStyle ); VOID UserEnterUserCritSec( VOID ); VOID UserLeaveUserCritSec( VOID ); BOOL UserGetCurrentDesktopId( DWORD* pdwDesktopId ); VOID UserRedrawDesktop( VOID ); UINT_PTR UserSetTimer( UINT dwElapse, PVOID pTimerFunc ); BOOL UserVisrgnFromHwnd( HRGN *phrgn, HWND hwnd ); VOID UserKillTimer( UINT_PTR nID ); #if DBG VOID UserAssertUserCritSecIn( VOID ); VOID UserAssertUserCritSecOut( VOID ); #endif VOID UserGetDisconnectDeviceResolutionHint( PDEVMODEW ); NTSTATUS UserSessionSwitchEnterCrit( VOID ); VOID UserSessionSwitchLeaveCrit( VOID ); BOOL UserIsUserCritSecIn( VOID ); DWORD GetAppCompatFlags2( WORD wVersion ); BOOL UserGetRedirectedWindowOrigin( HDC hdc, LPPOINT ppt ); HBITMAP UserGetRedirectionBitmap( HWND hwnd ); // // User-mode printer driver kernel-to-client callback mechanism. // DWORD ClientPrinterThunk( PVOID pvIn, ULONG cjIn, PVOID pvOut, ULONG cjOut ); // // Gdi fonts stuff // VOID GdiMultiUserFontCleanup(); #define BEGIN_REENTERCRIT() \ { \ BOOL fAlreadyHadCrit; \ \ /* \ * If we're not in the user crit then acquire it. \ */ \ fAlreadyHadCrit = ExIsResourceAcquiredExclusiveLite(gpresUser); \ if (fAlreadyHadCrit == FALSE) { \ EnterCrit(); \ } #define END_REENTERCRIT() \ if (fAlreadyHadCrit == FALSE) { \ LeaveCrit(); \ } \ } /* * Pool memory allocation functions used in win32k */ /* * From ntos\inc\pool.h */ #define SESSION_POOL_MASK 32 #if DBG #define TRACE_MAP_VIEWS #define MAP_VIEW_STACK_TRACE #else #if defined(PRERELEASE) || defined(USER_INSTRUMENTATION) #define TRACE_MAP_VIEWS #define MAP_VIEW_STACK_TRACE #endif #endif #define TAG_SECTION_SHARED 101 #define TAG_SECTION_DESKTOP 102 #define TAG_SECTION_GDI 103 #define TAG_SECTION_FONT 104 #define TAG_SECTION_REMOTEFONT 105 #define TAG_SECTION_CREATESECTION 106 #define TAG_SECTION_DIB 107 #define TAG_SECTION_HMGR 108 struct tagWin32MapView; #define MAP_VIEW_STACK_TRACE_SIZE 6 typedef struct tagWin32Section { struct tagWin32Section* pNext; struct tagWin32Section* pPrev; struct tagWin32MapView* pFirstView; PVOID SectionObject; LARGE_INTEGER SectionSize; DWORD SectionTag; #ifdef MAP_VIEW_STACK_TRACE PVOID trace[MAP_VIEW_STACK_TRACE_SIZE]; #endif // MAP_VIEW_STACK_TRACE } Win32Section, *PWin32Section; typedef struct tagWin32MapView { struct tagWin32MapView* pNext; struct tagWin32MapView* pPrev; PWin32Section pSection; PVOID pViewBase; SIZE_T ViewSize; #ifdef MAP_VIEW_STACK_TRACE PVOID trace[MAP_VIEW_STACK_TRACE_SIZE]; #endif // MAP_VIEW_STACK_TRACE } Win32MapView, *PWin32MapView; #ifndef TRACE_MAP_VIEWS NTSTATUS __inline Win32CreateSection( PVOID *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER InputMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle, PFILE_OBJECT FileObject, DWORD SectionTag) { NTSTATUS Status; Status = MmCreateSection( SectionObject, DesiredAccess, ObjectAttributes, InputMaximumSize, SectionPageProtection, AllocationAttributes, FileHandle, FileObject); if (NT_SUCCESS(Status)) { ObDeleteCapturedInsertInfo (*SectionObject); } return Status; } NTSTATUS __inline ZwWin32CreateSection( PVOID *SectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER InputMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle, PFILE_OBJECT FileObject, DWORD SectionTag) { HANDLE SectionHandle; NTSTATUS Status; Status = ZwCreateSection( &SectionHandle, DesiredAccess, ObjectAttributes, InputMaximumSize, SectionPageProtection, AllocationAttributes, FileHandle); if (!NT_SUCCESS(Status)) { return Status; } Status = ObReferenceObjectByHandle( SectionHandle, DesiredAccess, *(POBJECT_TYPE *)MmSectionObjectType, KernelMode, SectionObject, NULL); ZwClose(SectionHandle); return Status; } NTSTATUS __inline Win32MapViewInSessionSpace( PVOID Section, PVOID *MappedBase, PSIZE_T ViewSize) { return MmMapViewInSessionSpace(Section, MappedBase, ViewSize); } NTSTATUS __inline Win32UnmapViewInSessionSpace( PVOID MappedBase) { return MmUnmapViewInSessionSpace(MappedBase); } VOID __inline Win32DestroySection(PVOID Section) { ObDereferenceObject(Section); } #else NTSTATUS _Win32CreateSection( PVOID* pSectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER pInputMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle, PFILE_OBJECT FileObject, DWORD SectionTag); NTSTATUS _ZwWin32CreateSection( PVOID* pSectionObject, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER pInputMaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle, PFILE_OBJECT FileObject, DWORD SectionTag); NTSTATUS _Win32MapViewInSessionSpace( PVOID Section, PVOID* pMappedBase, PSIZE_T pViewSize); NTSTATUS _Win32UnmapViewInSessionSpace( PVOID MappedBase); VOID _Win32DestroySection( PVOID Section); #define Win32CreateSection _Win32CreateSection #define ZwWin32CreateSection _ZwWin32CreateSection #define Win32MapViewInSessionSpace _Win32MapViewInSessionSpace #define Win32UnmapViewInSessionSpace _Win32UnmapViewInSessionSpace #define Win32DestroySection _Win32DestroySection #endif // TRACE_MAP_VIEWS #if DBG #define POOL_INSTR #define POOL_INSTR_API #else #define POOL_INSTR #endif // DBG /*++ How the registry controls pool instrumentation in win32k.sys: -------------------------------------------------------------- If pool instrumentation is turned on (this can be done for free builds as well as checked) then there are several levels of tracing controlled from the registry under the following key: HKLM\System\CurrentControlSet\Control\Session Manager\SubSystems\Pool if this key doesn't exist default settings are used for each of the following key. 1. HeavyRemoteSession REG_DWORD default: 1 if this is non zero or the key doesn't exist then pool tracing is on for remote sessions of win32k.sys. 2. HeavyConsoleSession REG_DWORD default: 0 if this is non zero then pool tracing is on for console sessions of win32k.sys. it the key doesn't exist then pool tracing is off for the main session. 3. StackTraces REG_DWORD default: - 1 for remote sessions - 0 for the main session if non zero then a stack trace record will be saved for every pool allocation made. 4. KeepFailRecords REG_DWORD default: 32 if non zero then win32k.sys will keep a list of the last x allocations that failed (tag + stack trace). Use !dpa -f to dump the stack traces of the failed allocations 4. UseTailString REG_DWORD default: 0 if non zero for every pool allocation there will be a string attached to the end of the allocation to catch some specific type of memory corruption. 5. KeepFreeRecords REG_DWORD default: 0 not implemented yet. the number will specify how many free pointers will be kept in a list so we can differentiate when we call ExFreePool between a totally bogus value and a pointer that was already freed. 6. AllocationIndex REG_DWORD 7. AllocationsToFail REG_DWORD If AllocationIndex is non zero then win32k counts the pool allocations made and will start failing from allocation AllocationIndex a number of AllocationsToFail allocations. This is useful during boot time when a user mode test cannot call Win32PoolAllocationStats to fail pool allocations. 8. BreakForPoolLeaks REG_DWORD default: 0 Breaks in the debugger (if started with /debug in boot.ini) if pool leaks are detected in win32k.sys for remote sessions. --*/ #ifdef POOL_INSTR PVOID HeavyAllocPool(SIZE_T uBytes, ULONG iTag, DWORD dwFlags, EX_POOL_PRIORITY priority); VOID HeavyFreePool(PVOID p); #define Win32AllocPool(uBytes, iTag) \ HeavyAllocPool(uBytes, iTag, 0, (EX_POOL_PRIORITY)0) #define Win32AllocPoolWithPriority(uBytes, iTag, priority) \ HeavyAllocPool(uBytes, iTag, DAP_PRIORITY, priority) #define Win32AllocPoolZInit(uBytes, iTag) \ HeavyAllocPool(uBytes, iTag, DAP_ZEROINIT, (EX_POOL_PRIORITY)0) #define Win32AllocPoolZInitWithPriority(uBytes, iTag, priority) \ HeavyAllocPool(uBytes, iTag, DAP_ZEROINIT | DAP_PRIORITY, priority) #define Win32AllocPoolWithQuota(uBytes, iTag) \ HeavyAllocPool(uBytes, iTag, DAP_USEQUOTA, (EX_POOL_PRIORITY)0) #define Win32AllocPoolWithQuotaZInit(uBytes, iTag) \ HeavyAllocPool(uBytes, iTag, DAP_USEQUOTA | DAP_ZEROINIT, (EX_POOL_PRIORITY)0) #define Win32AllocPoolNonPaged(uBytes, iTag) \ HeavyAllocPool(uBytes, iTag, DAP_NONPAGEDPOOL, (EX_POOL_PRIORITY)0); #define Win32AllocPoolNonPagedWithPriority(uBytes, iTag, priority) \ HeavyAllocPool(uBytes, iTag, DAP_NONPAGEDPOOL | DAP_PRIORITY, priority); #define Win32AllocPoolWithQuotaNonPaged(uBytes, iTag) \ HeavyAllocPool(uBytes, iTag, DAP_USEQUOTA | DAP_NONPAGEDPOOL, (EX_POOL_PRIORITY)0); #define Win32AllocPoolNonPagedNS(uBytes, iTag) \ HeavyAllocPool(uBytes, iTag, DAP_NONPAGEDPOOL | DAP_NONSESSION, (EX_POOL_PRIORITY)0); #define Win32AllocPoolNonPagedNSWithPriority(uBytes, iTag, priority) \ HeavyAllocPool(uBytes, iTag, DAP_NONPAGEDPOOL | DAP_NONSESSION | DAP_PRIORITY, priority); #define Win32FreePool HeavyFreePool #else PVOID __inline Win32AllocPool(SIZE_T uBytes, ULONG uTag) { return ExAllocatePoolWithTag( (POOL_TYPE)(SESSION_POOL_MASK | PagedPool), uBytes, uTag); } PVOID __inline Win32AllocPoolWithPriority(SIZE_T uBytes, ULONG uTag, EX_POOL_PRIORITY priority) { return ExAllocatePoolWithTagPriority( (POOL_TYPE)(SESSION_POOL_MASK | PagedPool), uBytes, uTag, priority); } PVOID __inline Win32AllocPoolWithQuota(SIZE_T uBytes, ULONG uTag) { return ExAllocatePoolWithQuotaTag( (POOL_TYPE)(SESSION_POOL_MASK | PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE), uBytes, uTag); } PVOID __inline Win32AllocPoolNonPaged(SIZE_T uBytes, ULONG uTag) { return ExAllocatePoolWithTag( (POOL_TYPE)(SESSION_POOL_MASK | NonPagedPool), uBytes, uTag); } PVOID __inline Win32AllocPoolNonPagedWithPriority(SIZE_T uBytes, ULONG uTag, EX_POOL_PRIORITY priority) { return ExAllocatePoolWithTagPriority( (POOL_TYPE)(SESSION_POOL_MASK | NonPagedPool), uBytes, uTag, priority); } PVOID __inline Win32AllocPoolNonPagedNS(SIZE_T uBytes, ULONG uTag) { return ExAllocatePoolWithTag( (POOL_TYPE)NonPagedPool, uBytes, uTag); } PVOID __inline Win32AllocPoolNonPagedNSWithPriority(SIZE_T uBytes, ULONG uTag, EX_POOL_PRIORITY priority) { return ExAllocatePoolWithTagPriority( (POOL_TYPE)NonPagedPool, uBytes, uTag, priority); } PVOID __inline Win32AllocPoolWithQuotaNonPaged(SIZE_T uBytes, ULONG uTag) { return ExAllocatePoolWithQuotaTag( (POOL_TYPE)(SESSION_POOL_MASK | NonPagedPool), uBytes, uTag); } PVOID Win32AllocPoolWithTagZInit(SIZE_T uBytes, ULONG uTag); PVOID Win32AllocPoolWithTagZInitWithPriority(SIZE_T uBytes, ULONG uTag, EX_POOL_PRIORITY priority); PVOID Win32AllocPoolWithQuotaTagZInit(SIZE_T uBytes, ULONG uTag); PVOID __inline Win32AllocPoolZInit(SIZE_T uBytes, ULONG uTag) { return Win32AllocPoolWithTagZInit(uBytes, uTag); } PVOID __inline Win32AllocPoolZInitWithPriority(SIZE_T uBytes, ULONG uTag, EX_POOL_PRIORITY priority) { return Win32AllocPoolWithTagZInitWithPriority(uBytes, uTag, priority); } PVOID __inline Win32AllocPoolWithQuotaZInit(SIZE_T uBytes, ULONG uTag) { return Win32AllocPoolWithQuotaTagZInit(uBytes, uTag); } #define Win32FreePool ExFreePool #endif // POOL_INSTR /* * All the User* allocation functions are defined to be Win32* */ #define UserAllocPool Win32AllocPool #define UserAllocPoolZInit Win32AllocPoolZInit #define UserAllocPoolWithQuota Win32AllocPoolWithQuota #define UserAllocPoolWithQuotaZInit Win32AllocPoolWithQuotaZInit #define UserAllocPoolNonPaged Win32AllocPoolNonPaged #define UserAllocPoolNonPagedNS Win32AllocPoolNonPagedNS #define UserAllocPoolWithQuotaNonPaged Win32AllocPoolWithQuotaNonPaged #define UserFreePool Win32FreePool SIZE_T Win32QueryPoolSize( PVOID p); PVOID UserReAllocPoolWithTag( PVOID pSrc, SIZE_T uBytesSrc, SIZE_T uBytes, ULONG uTag); PVOID UserReAllocPoolWithQuotaTag( PVOID pSrc, SIZE_T uBytesSrc, SIZE_T uBytes, ULONG uTag); PVOID __inline UserReAllocPool(PVOID p, SIZE_T uBytesSrc, SIZE_T uBytes, ULONG uTag) { return UserReAllocPoolWithTag(p, uBytesSrc, uBytes, uTag); } PVOID __inline UserReAllocPoolWithQuota(PVOID p, SIZE_T uBytesSrc, SIZE_T uBytes, ULONG uTag) { return UserReAllocPoolWithQuotaTag(p, uBytesSrc, uBytes, uTag); } /* * Since the ReAllocPoolZInit functions are not yet used, they are * made inline to save code space. Consider making them non-inline * if they get a few uses. */ PVOID __inline UserReAllocPoolZInit(PVOID p, SIZE_T uBytesSrc, SIZE_T uBytes, ULONG uTag) { PVOID pv; pv = UserReAllocPoolWithTag(p, uBytesSrc, uBytes, uTag); if (pv && uBytes > uBytesSrc) { RtlZeroMemory((BYTE *)pv + uBytesSrc, uBytes - uBytesSrc); } return pv; } PVOID __inline UserReAllocPoolWithQuotaZInit(PVOID p, SIZE_T uBytesSrc, SIZE_T uBytes, ULONG uTag) { PVOID pv; pv = UserReAllocPoolWithQuotaTag(p, uBytesSrc, uBytes, uTag); if (pv && uBytes > uBytesSrc) { RtlZeroMemory((BYTE *)pv + uBytesSrc, uBytes - uBytesSrc); } return pv; } #define DAP_USEQUOTA 0x01 #define DAP_ZEROINIT 0x02 #define DAP_NONPAGEDPOOL 0x04 #define DAP_NONSESSION 0x08 #define DAP_PRIORITY 0x10 //!!!dbug -- there has to be a better one somewhere... /* * Memory manager (ExAllocate..., etc.) pool header size. */ #define MM_POOL_HEADER_SIZE 8 #define POOL_ALLOC_TRACE_SIZE 8 typedef struct tagWin32PoolHead { SIZE_T size; // the size of the allocation (doesn't include // this structure struct tagWin32PoolHead* pPrev; // pointer to the previous allocation of this tag struct tagWin32PoolHead* pNext; // pointer to the next allocation of this tag PVOID* pTrace; // pointer to the stack trace } Win32PoolHead, *PWin32PoolHead; /* * Memory barrier * This macro ensures the pending write-back instructions retire before the next * code, settles the multi-proc rare problems (see KeMemoryBarrier macros). * RISC chips could reorder the retirement of the instructions, so when it's * critical to ensure the order of the write operation, those macros should be * used. */ #if defined(_X86_) #define Win32MemoryBarrier() #elif defined(_IA64_) #if defined(NT_UP) #define Win32MemoryBarrier() #else #define WIN32_MEMORY_BARRIER_REQUIRED #define Win32MemoryBarrier() __mf() #endif #elif defined(_AMD64_) #define Win32MemoryBarrier() #else #error unknown CPU type. #endif