分析的时windows 10 21h2
CreateBitmap 在3环会先调用gdi32.dll 同名函数接着调用 gdi32full.dll 的同名函数->再接着w32u.dll 的NtGdiCreateBitmap 让后进入内核
__int64 __fastcall NtGdiCreateBitmap(unsigned int a1, unsigned int a2, unsigned int a3, unsigned int a4, char *Address) { __int64 Bitmap; // rbx HANDLE v10; // rdi unsigned __int64 v12; // r8 unsigned __int64 v13; // r8 char *v14; // rcx Bitmap = 1i64; v10 = 0i64; if ( Address ) { v12 = ((a1 * (unsigned __int16)a3 * (unsigned __int64)(unsigned __int16)a4 + 15) >> 3) & 0x1FFFFFFFFFFFFFFEi64; if ( v12 <= 0xFFFFFFFF && (v13 = a2 * v12, v13 <= 0xFFFFFFFF) && (_DWORD)v13 ) { v14 = &Address[(int)v13]; if ( (unsigned __int64)v14 > MmUserProbeAddress || v14 < Address ) *(_BYTE *)MmUserProbeAddress = 0; v10 = MmSecureVirtualMemory(Address, (int)v13, 2u); Bitmap = -(__int64)(v10 != 0i64) & 1; } else { Bitmap = 0i64; } } if ( Bitmap ) Bitmap = GreCreateBitmap(a1, a2, a3, a4, Address); if ( v10 ) MmUnsecureVirtualMemory(v10); return Bitmap; }
会调用 win32kbase.sys 的
GreCreateBitmap(a1, a2, a3, a4, Address); 进行bitmap 结构申请·和变量赋值
__int64 __fastcall GreCreateBitmap(int a1, int a2, unsigned int a3, unsigned int a4, __int64 a5) { __int64 v5; // rdi unsigned int v6; // r10d unsigned __int64 v7; // r14 int v8; // ebx __int64 v9; // rdx __int64 v10; // rsi __int64 v11; // r14 __int64 v12; // rbx __int64 v13; // r8 __int64 v15; // [rsp+50h] [rbp-30h] BYREF char v16; // [rsp+58h] [rbp-28h] int v17[4]; // [rsp+60h] [rbp-20h] BYREF _QWORD v18[2]; // [rsp+70h] [rbp-10h] int v19; // [rsp+A0h] [rbp+20h] BYREF v5 = 0i64; v6 = a4 * a3; if ( a1 <= 0 || (unsigned int)a1 > 0x7FFFFFF || a2 <= 0 || a3 > 0x20 || a4 > 0x20 || v6 > 0x20 || (v7 = a2 * (unsigned __int64)(((a1 * v6 + 15) >> 3) & 0x1FFFFFFE), v7 > 0xFFFFFFFF) ) { EngSetLastError(0x57u); return 0i64; } else { v17[3] = 0; v18[1] = 1i64; v17[1] = a1; v17[2] = a2; v18[0] = 0i64; if ( v6 > 1 ) { v8 = 4; if ( v6 <= 4 ) { v8 = 2; } else if ( v6 <= 8 ) { v8 = 3; } else if ( v6 > 0x10 ) { v8 = (v6 > 0x18) + 5; } } else { v8 = 1; v18[0] = WPP_MAIN_CB.Dpc.DeferredRoutine; } v17[0] = v8; v15 = 0i64; v16 = 0; SURFMEM::bCreateDIB((SURFMEM *)&v15, (struct _DEVBITMAPINFO *)v17, 0i64, 0i64, 0, 0i64, 0i64, 0, 1, 0); v10 = v15; if ( v15 ) { *(_DWORD *)(v15 + 112) |= 0x4000000u; if ( a5 ) { v19 = 0; if ( (int)IsGreSetBitmapBitsSupported_0() >= 0 ) GreSetBitmapBits_0(*(_QWORD *)(v10 + 32), (unsigned int)v7, a5, &v19); } if ( v8 != 1 ) *(_DWORD *)(v10 + 112) |= 0x800200u; v11 = *(_QWORD *)(v10 + 32); LOBYTE(v9) = 5; v16 |= 1u; v12 = HmgShareLockCheck(v11, v9); if ( v12 ) { if ( (v11 & 0x800000) == 0 ) { LOBYTE(v13) = 5; HmgSetOwner(v11, 2147483650i64, v13); } HmgDecrementShareReferenceCount(v12); } v5 = *(_QWORD *)(v10 + 32); } SURFMEM::~SURFMEM((SURFMEM *)&v15); return v5; } }
接着调用
SURFMEM::bCreateDIB 申请gib 对象 就结束了
这里还涉及 对象大小计算 当nPlanes*nBitCount 不同结果导致不同的计算规则。
当nPlanes*nBitCount=8时 有
(nWidth+3)*nHeight+(对齐字节满足8字节对齐)+handle(0x10)+0x2b8 就是CreateBitmap 在内存的真正大小
假定创建代码
HGDIOBJ bitmap = CreateBitmap(1024, 2, 1, 8, NULL);
这里我们用windbg 看是否是按这样计算的
1: kd> !process 0 0 cs.exe PROCESS ffffbd0f9aacb300 SessionId: 1 Cid: 1938 Peb: 0039d000 ParentCid: 0db0 DirBase: 03f45000 ObjectTable: ffffe5030f923300 HandleCount: 51. Image: cs.exe
1: kd> r $peb $peb=000000000039d000
找GdiSharedHandleTable
1: kd> dt nt!_peb 000000000039d000 GdiSharedHandleTable +0x0f8 GdiSharedHandleTable : 0x00000000`009d0000 Void
1: kd> dq 0x00000000`009d0000+c02*18 L3 00000000`009e2030 ffffffff`ff250c02 00052505`00001938 00000000`009e2040 00000000`00000000
GdiSharedHandleTable+ (返回句柄&0xffff)*18
!pool ffffffff`ff250c02
0xac8
bCreateDIB
__int64 __fastcall SURFMEM::bCreateDIB( SURFMEM *this, struct _DEVBITMAPINFO *a2, void *a3, __int64 a4, unsigned int a5, void *a6, unsigned __int64 a7, int a8, int a9, int a10) { struct _DEVBITMAPINFO *v10; // r13 int v11; // eax int v13; // r10d unsigned int v14; // edi unsigned int v15; // edi unsigned int v17; // edi unsigned int v18; // edi unsigned int v19; // edi unsigned int v20; // eax unsigned int v21; // edi bool v22; // cf unsigned int v23; // esi int v24; // r15d unsigned __int64 v25; // rcx __int64 v26; // rbx int v27; // eax int v28; // eax int v29; // eax PVOID v30; // rcx PVOID v31; // rax int v32; // r8d unsigned __int64 v33; // rcx int v34; // r15d int v35; // r12d __int64 v36; // rbx _QWORD *v37; // rax __int64 v38; // rbx void *v39; // rax __int64 v40; // r15 __int64 v41; // r13 __int64 v42; // r12 __int64 v43; // rbx __int64 *CurrentThreadWin32ThreadAndEnterCriticalRegion; // rax __int64 v45; // rax signed __int32 v46; // eax unsigned int v47; // edx void *v48; // r12 int v49; // r13d __int64 *ThreadWin32Thread; // rax __int64 v51; // rax _QWORD *v52; // rax __int64 CurrentProcess; // rax int v54; // edx __int64 v55; // r8 __int64 v56; // r15 __int64 v57; // rsi __int64 ProcessWin32Process; // rax __int64 v59; // rbx struct _ERESOURCE *v60; // rbx _QWORD *v61; // rax __int64 v62; // rax __int64 v63; // rax __int64 v64; // rax __int64 v65; // rax char v66; // si unsigned __int64 v67; // r12 unsigned __int64 v68; // rbx __int64 *v69; // rax int v70; // edx __int64 v71; // rcx __int64 v72; // r8 __int64 v73; // rax __int64 v74; // rax struct _ERESOURCE *v75; // rdi int v76; // r15d int v77; // esi struct _ERESOURCE *v78; // rdi __int64 CurrentProcessWin32Process; // rax __int64 v80; // rcx __int64 v81; // rdx unsigned int v82; // eax __int64 v83; // rax __int64 v84; // rdx int v85; // ecx unsigned int v86; // ecx unsigned int v87; // eax __int64 v88; // rdx int v89; // eax __int64 v90; // rdi __int64 *v91; // rax char v92; // r15 __int64 v93; // rax __int64 v94; // r13 unsigned int v95; // ebx bool v96; // zf signed __int32 v97; // eax struct _BASEOBJECT *v98; // rax __int64 v99; // r15 struct _BASEOBJECT *v100; // rdx unsigned int v101; // r8d int v102; // ebx unsigned int v103; // ebx unsigned int CurrentProcessId; // eax struct _KTHREAD *CurrentThread; // rax __int128 v106; // xmm0 __int64 v107; // rax __int128 v108; // xmm1 __int128 v109; // xmm0 PVOID v110; // rcx int v111; // eax __int64 v112; // rdi PVOID v113; // rbx __int64 v114; // rax PVOID v115; // rcx PVOID Object; // [rsp+50h] [rbp-B0h] BYREF int v117; // [rsp+58h] [rbp-A8h] int v118; // [rsp+5Ch] [rbp-A4h] int v119; // [rsp+60h] [rbp-A0h] unsigned int v120; // [rsp+64h] [rbp-9Ch] struct _BASEOBJECT *v121; // [rsp+68h] [rbp-98h] void *v122; // [rsp+70h] [rbp-90h] BYREF int v123[2]; // [rsp+78h] [rbp-88h] BYREF PEPROCESS v124; // [rsp+80h] [rbp-80h] BYREF PEPROCESS Process; // [rsp+88h] [rbp-78h] BYREF __int32 v126; // [rsp+9Ch] [rbp-64h] int v127; // [rsp+A0h] [rbp-60h] unsigned int v128; // [rsp+A4h] [rbp-5Ch] _OWORD v129[3]; // [rsp+A8h] [rbp-58h] BYREF __int64 v130; // [rsp+D8h] [rbp-28h] BYREF int v131[5]; // [rsp+E0h] [rbp-20h] BYREF __int32 v132; // [rsp+F4h] [rbp-Ch] int v133; // [rsp+F8h] [rbp-8h] char v134[24]; // [rsp+100h] [rbp+0h] BYREF __int32 v135; // [rsp+160h] [rbp+60h] unsigned int v136; // [rsp+160h] [rbp+60h] PVOID pv; // [rsp+170h] [rbp+70h] BYREF __int64 v139; // [rsp+178h] [rbp+78h] v139 = a4; pv = a3; *((_BYTE *)this + 8) = 8; *(_QWORD *)this = 0i64; v10 = a2; v11 = *(_DWORD *)a2 - 1; v120 = 1; v118 = 0; v13 = 0; v14 = 0; switch ( v11 ) { case 0: v15 = *((_DWORD *)a2 + 1); if ( v15 >= 0xFFFFFFE0 ) return 0i64; v14 = ((v15 + 31) >> 3) & 0x1FFFFFFC; goto LABEL_17; case 1: v17 = *((_DWORD *)a2 + 1); if ( v17 >= 0xFFFFFFF8 ) return 0i64; v14 = ((v17 + 7) >> 1) & 0x7FFFFFFC; goto LABEL_17; case 2: v18 = *((_DWORD *)a2 + 1); if ( v18 >= 0xFFFFFFFC ) return 0i64; v14 = (v18 + 3) & 0xFFFFFFFC; goto LABEL_17; case 3: v19 = *((_DWORD *)a2 + 1); if ( v19 >= 0xFFFFFFFE || v19 + 1 >= 0x7FFFFFFF ) return 0i64; v14 = (2 * v19 + 2) & 0xFFFFFFFC; goto LABEL_17; case 4: v20 = *((_DWORD *)a2 + 1); if ( v20 >= 0x55555554 ) return 0i64; v14 = (3 * (v20 + 1)) & 0xFFFFFFFC; goto LABEL_17; case 5: v21 = *((_DWORD *)a2 + 1); if ( v21 >= 0x3FFFFFFF ) return 0i64; v14 = 4 * v21; LABEL_17: v22 = a8 != 0; a8 = -a8; v23 = SURFACE::tSize; Object = 0i64; memset(v129, 0, sizeof(v129)); v24 = (v22 ? 8 : 0) | 6; v117 = v24; v119 = 0; v122 = 0i64; if ( a3 ) { if ( !a9 || (!v13 ? (v33 = v14 * (unsigned __int64)*((unsigned int *)a2 + 2)) : (v33 = *((unsigned int *)a2 + 3)), v33 <= 0x7FFFFFFF) ) { if ( (*((_DWORD *)a2 + 6) & 0x800) == 0 ) goto LABEL_54; W32PIDLOCK::vInit((W32PIDLOCK *)v129); if ( *((_QWORD *)&v129[2] + 1) ) { v118 = 2048; v119 = 1; goto LABEL_54; } } return 0i64; } if ( v13 ) v25 = *((unsigned int *)a2 + 3); else v25 = v14 * (unsigned __int64)*((unsigned int *)a2 + 2); v26 = v25 + (unsigned int)SURFACE::tSize; if ( v26 < v25 || (unsigned __int64)v26 > 0x7FFFFFFF ) return 0i64; v27 = *((_DWORD *)a2 + 6); if ( (v27 & 0x40000) != 0 && v26 > 4096 ) *((_DWORD *)a2 + 6) = v27 | 8; v28 = *((_DWORD *)a2 + 6); if ( (v28 & 8) != 0 ) { if ( (v28 & 0x80u) == 0 ) v29 = EngAllocUserMemEx((int)v26, 0x1C0000000ui64, &pv); else v29 = AllocateSharedSection(v26, 0xC0000000, &Object, &v122, &pv); if ( v29 >= 0 ) { v30 = pv; v31 = Object; LABEL_42: if ( v30 || v31 ) goto LABEL_54; goto LABEL_44; } return 0i64; } if ( (v28 & 0x810) != 0 ) { if ( (v28 & 0x800) != 0 ) { W32PIDLOCK::vInit((W32PIDLOCK *)v129); if ( !*((_QWORD *)&v129[2] + 1) ) return 0i64; Object = 0i64; v123[1] = 0; v123[0] = v26 - v23; Win32CreateSection((unsigned int)&Object, 6, v32, (unsigned int)v123); v31 = Object; if ( !Object ) { W32PIDLOCK::vCleanUp((W32PIDLOCK *)v129); return 0i64; } } else { AllocateKernelSection(v26, 0xC0000000, &pv); v31 = Object; } v30 = pv; if ( pv || v31 ) { v118 = *((_DWORD *)v10 + 6) & 0x800 | 0x10; goto LABEL_42; } } LABEL_44: v23 = v26; if ( (*((_DWORD *)v10 + 6) & 2) == 0 ) { LOWORD(v24) = v24 & 0xFFFB; v117 = v24; } LABEL_54: v34 = ((unsigned __int8)~(_BYTE)v24 >> 2) & 1; if ( gulGdiHmgrTraceObjectType == 5 ) { v35 = 1; v23 += 160; } else { v35 = 0; } if ( dword_1C0104624 >= v23 ) { v36 = qword_1C01046E8; if ( (int)IsWin32AllocateFromPagedLookasideListImplSupported_0() >= 0 ) { v37 = (_QWORD *)Win32AllocateFromPagedLookasideListImpl_0(v36); v38 = (__int64)v37; if ( v37 ) { if ( v34 ) { memset(v37, 0, v23); } else { *v37 = 0i64; v37[1] = 0i64; v37[2] = 0i64; } if ( v35 ) RtlCaptureStackBackTrace(0, 0x14u, (PVOID *)(v23 + v38 - 160), 0i64); LOWORD(v135) = *(_WORD *)(v38 + 12); HIWORD(v135) = *(_WORD *)(v38 + 14) | 0x8000; _InterlockedExchange((volatile __int32 *)(v38 + 12), v135); goto LABEL_76; } } } if ( v34 ) { v38 = 0i64; if ( v23 ) { if ( (int)IsWin32AllocPoolImplSupported_0() >= 0 ) { v39 = (void *)Win32AllocPoolImpl_0(33i64, v23, 892364871i64); v38 = (__int64)v39; if ( v39 ) memset(v39, 0, v23); } } } else { v38 = PALLOCMEM2(v23); if ( !v38 ) { LABEL_236: EngSetLastError(8u); goto LABEL_237; } *(_QWORD *)v38 = 0i64; *(_QWORD *)(v38 + 8) = 0i64; *(_QWORD *)(v38 + 16) = 0i64; } if ( !v38 ) goto LABEL_236; if ( v35 ) RtlCaptureStackBackTrace(0, 0x14u, (PVOID *)(v23 + v38 - 160), 0i64); LABEL_76: *(_QWORD *)this = v38; v40 = 0i64; *(_QWORD *)(v38 + 56) = *(_QWORD *)((char *)v10 + 4); *(_WORD *)(*(_QWORD *)this + 100i64) = 0; *(_QWORD *)(*(_QWORD *)this + 136i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 216i64) = 0i64; v41 = *((_QWORD *)v10 + 2); if ( !v41 ) goto LABEL_101; v42 = 0i64; if ( (unsigned __int16)v41 >= (unsigned int)gcMaxHmgr ) goto LABEL_101; v43 = gpentHmgr + 24i64 * (unsigned __int16)v41; CurrentThreadWin32ThreadAndEnterCriticalRegion = (__int64 *)PsGetCurrentThreadWin32ThreadAndEnterCriticalRegion(v131); if ( CurrentThreadWin32ThreadAndEnterCriticalRegion ) { v45 = *CurrentThreadWin32ThreadAndEnterCriticalRegion; if ( v45 ) v40 = *(_QWORD *)(v45 + 72); } LABEL_81: _m_prefetchw((const void *)(v43 + 8)); v46 = *(_DWORD *)(v43 + 8); v47 = v46 & 0xFFFFFFFE; v132 = v46; if ( (v46 & 0xFFFFFFFE) != (v131[0] & 0xFFFFFFFC) && v47 && (!v40 || v47 != *(_DWORD *)(v40 + 8)) || (*(_BYTE *)(v43 + 15) & 0x20) != 0 ) { KeLeaveCriticalRegion(); LABEL_101: *(_QWORD *)(*(_QWORD *)this + 120i64) = 0i64; goto LABEL_102; } while ( (*(_BYTE *)(v43 + 15) & 0x40) == 0 ) { if ( (v46 & 1) != 0 ) { KeDelayExecutionThread(0, 0, gpLockShortDelay); goto LABEL_81; } v133 = v46 | 1; if ( v46 != _InterlockedCompareExchange((volatile signed __int32 *)(v43 + 8), v46 | 1, v46) || (*(_BYTE *)(v43 + 15) & 0x40) != 0 ) { goto LABEL_81; } *((_QWORD *)gpentPushLock + (unsigned __int16)v41) = 0i64; *(_BYTE *)(v43 + 15) |= 0x40u; _m_prefetchw((const void *)(v43 + 8)); v132 = *(_DWORD *)(v43 + 8) & 0xFFFFFFFE; _InterlockedExchange((volatile __int32 *)(v43 + 8), v132); v46 = v132; } ExAcquirePushLockExclusiveEx((char *)gpentPushLock + 8 * (unsigned __int16)v41, 0i64); if ( *(_BYTE *)(v43 + 14) == 8 && *(_WORD *)(v43 + 12) == WORD1(v41) ) { v42 = *(_QWORD *)v43; ++*(_DWORD *)(*(_QWORD *)v43 + 8i64); } if ( (*(_BYTE *)(v43 + 15) & 0x40) != 0 ) { ExReleasePushLockExclusiveEx((char *)gpentPushLock + 8 * (unsigned __int16)v41, 0i64); } else { _m_prefetchw((const void *)(v43 + 8)); v132 = *(_DWORD *)(v43 + 8) & 0xFFFFFFFE; _InterlockedExchange((volatile __int32 *)(v43 + 8), v132); } KeLeaveCriticalRegion(); if ( !v42 ) goto LABEL_101; *(_QWORD *)(*(_QWORD *)this + 120i64) = v42; LABEL_102: v48 = a6; v49 = a10; *(_DWORD *)(*(_QWORD *)this + 96i64) = *(_DWORD *)a2; *(_WORD *)(*(_QWORD *)this + 102i64) = v118 | *((_WORD *)a2 + 12) & 0x89; *(_QWORD *)(*(_QWORD *)this + 176i64) = v139; *(_DWORD *)(*(_QWORD *)this + 192i64) = a5; *(_QWORD *)(*(_QWORD *)this + 184i64) = v48; *(_QWORD *)(*(_QWORD *)this + 200i64) = a7; *(_DWORD *)(*(_QWORD *)this + 208i64) = v49; *(_QWORD *)(*(_QWORD *)this + 24i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 40i64) = 0i64; *(_DWORD *)(*(_QWORD *)this + 112i64) = *((_DWORD *)a2 + 6) & 0x40000; *(_QWORD *)(*(_QWORD *)this + 128i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 144i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 152i64) = 0i64; *(_DWORD *)(*(_QWORD *)this + 160i64) = 0; *(_QWORD *)(*(_QWORD *)this + 168i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 48i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 104i64) = 0i64; ThreadWin32Thread = (__int64 *)PsGetThreadWin32Thread(KeGetCurrentThread()); if ( ThreadWin32Thread ) { v51 = *ThreadWin32Thread; if ( v51 ) *(_QWORD *)(v51 + 304) = 0i64; } *(_QWORD *)(*(_QWORD *)this + 240i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 248i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 256i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 584i64) = 0i64; *(_DWORD *)(*(_QWORD *)this + 592i64) = 0; *(_DWORD *)(*(_QWORD *)this + 116i64) = 0; *(_QWORD *)(*(_QWORD *)this + 496i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 488i64) = 0i64; v52 = (_QWORD *)(*(_QWORD *)this + 224i64); v52[1] = v52; *v52 = v52; *(_DWORD *)(*(_QWORD *)this + 312i64) = 0; *(_DWORD *)(*(_QWORD *)this + 316i64) = 0; *(_QWORD *)(*(_QWORD *)this + 568i64) = 0i64; CurrentProcess = PsGetCurrentProcess(); v56 = *(_QWORD *)this; v57 = CurrentProcess; if ( CurrentProcess ) { ProcessWin32Process = PsGetProcessWin32Process(CurrentProcess); v59 = ProcessWin32Process; if ( !ProcessWin32Process || !*(_DWORD *)(ProcessWin32Process + 836) || !(unsigned int)IsImmersiveAppRestricted(ProcessWin32Process) || (*(_DWORD *)(v59 + 776) & 0x200) != 0 ) { v57 = 0i64; } } v60 = ghsemHmgr; if ( ghsemHmgr ) { PsEnterPriorityRegion(); ExEnterCriticalRegionAndAcquireResourceExclusive(v60); LODWORD(v60) = (_DWORD)ghsemHmgr; } if ( gbLockEtw && (Microsoft_Windows_Win32kEnableBits & 0x10) != 0 ) Template_pqz((unsigned int)L"ghsemHmgr", v54, v55, (_DWORD)v60, 16, (__int64)L"ghsemHmgr"); *(_QWORD *)(v56 + 576) = v57; if ( gbLockEtw && (Microsoft_Windows_Win32kEnableBits & 0x10) != 0 ) Template_pz(L"ghsemHmgr", &LockRelease, v55, ghsemHmgr, L"ghsemHmgr"); if ( ghsemHmgr ) { ExReleaseResourceAndLeaveCriticalRegion(ghsemHmgr); PsLeavePriorityRegion(); } v61 = (_QWORD *)(*(_QWORD *)this + 440i64); v61[1] = v61; *v61 = v61; *(_QWORD *)(*(_QWORD *)this + 560i64) = 0i64; if ( v119 ) *(_DWORD *)(*(_QWORD *)this + 116i64) |= 1u; if ( v48 && !v49 ) *(_WORD *)(*(_QWORD *)this + 102i64) |= 4u; if ( pv || Object ) *(_QWORD *)(*(_QWORD *)this + 72i64) = pv; else *(_QWORD *)(*(_QWORD *)this + 72i64) = *(_QWORD *)this + SURFACE::tSize; v10 = a2; v62 = *(_QWORD *)this; if ( (unsigned int)(*(_DWORD *)a2 - 7) <= 3 ) { *(_WORD *)(v62 + 102) &= ~0x800u; *(_DWORD *)(*(_QWORD *)this + 88i64) = 0; *(_DWORD *)(*(_QWORD *)this + 64i64) = *((_DWORD *)a2 + 3); if ( (unsigned int)(*(_DWORD *)a2 - 9) <= 1 ) *(_QWORD *)(*(_QWORD *)this + 80i64) = 0i64; else *(_QWORD *)(*(_QWORD *)this + 80i64) = *(_QWORD *)(*(_QWORD *)this + 72i64); } else { *(_DWORD *)(v62 + 64) = v14 * *((_DWORD *)a2 + 2); v63 = *(_QWORD *)this; if ( (*((_DWORD *)a2 + 6) & 1) != 0 ) { *(_DWORD *)(v63 + 88) = v14; *(_QWORD *)(*(_QWORD *)this + 80i64) = *(_QWORD *)(*(_QWORD *)this + 72i64); } else { *(_DWORD *)(v63 + 88) = -v14; *(_QWORD *)(*(_QWORD *)this + 80i64) = *(_QWORD *)(*(_QWORD *)this + 72i64) + *(_DWORD *)(*(_QWORD *)this + 64i64) - v14; } } if ( *(char *)(*(_QWORD *)this + 102i64) < 0 ) { *(_QWORD *)(*(_QWORD *)this + 520i64) = Object; *(_QWORD *)(*(_QWORD *)this + 528i64) = v122; *(_QWORD *)(*(_QWORD *)this + 536i64) = (char *)v122 + *(_QWORD *)(*(_QWORD *)this + 80i64) - *(_QWORD *)(*(_QWORD *)this + 72i64); *(_DWORD *)(*(_QWORD *)this + 544i64) = 1; v64 = W32GetThreadWin32Thread(KeGetCurrentThread()); if ( v64 && (v65 = *(_QWORD *)(v64 + 72)) != 0 ) { *(_DWORD *)(*(_QWORD *)this + 548i64) = *(_DWORD *)(v65 + 8); *(_DWORD *)(*(_QWORD *)this + 552i64) = 1; } else { *(_DWORD *)(*(_QWORD *)this + 548i64) = 0; *(_DWORD *)(*(_QWORD *)this + 552i64) = 0; } } v66 = v117; v67 = 0i64; v136 = (unsigned __int16)v117; *(_DWORD *)(*(_QWORD *)this + 92i64) = _InterlockedIncrement((volatile signed __int32 *)&_ulGlobalSurfaceUnique); v121 = *(struct _BASEOBJECT **)this; v68 = (unsigned __int64)PsGetCurrentProcessId() & 0xFFFFFFFC; v69 = (__int64 *)PsGetThreadWin32Thread(KeGetCurrentThread()); if ( v69 ) { v73 = *v69; if ( v73 ) { v74 = *(_QWORD *)(v73 + 72); if ( v74 ) LODWORD(v68) = *(_DWORD *)(v74 + 8); } } v75 = ghsemHmgr; if ( ghsemHmgr ) { PsEnterPriorityRegion(); ExEnterCriticalRegionAndAcquireResourceExclusive(v75); } if ( gbLockEtw && (Microsoft_Windows_Win32kEnableBits & 0x10) != 0 ) Template_pqz(v71, v70, v72, (_DWORD)ghsemHmgr, 16, (__int64)L"ghsemHmgr"); v76 = v66 & 8; if ( (v66 & 8) == 0 ) { v77 = v76 + 1; if ( (_DWORD)v68 ) { if ( (_DWORD)v68 != -2147483630 ) { v78 = ghsemHmgr; if ( ghsemHmgr ) { PsEnterPriorityRegion(); ExEnterCriticalRegionAndAcquireResourceExclusive(v78); } if ( gbLockEtw && (Microsoft_Windows_Win32kEnableBits & 0x10) != 0 ) Template_pqz(v71, v70, v72, (_DWORD)ghsemHmgr, 16, (__int64)L"ghsemHmgr"); if ( (_DWORD)v68 == ((unsigned int)PsGetCurrentProcessId() & 0xFFFFFFFC) ) { CurrentProcessWin32Process = PsGetCurrentProcessWin32Process(); v81 = CurrentProcessWin32Process; if ( CurrentProcessWin32Process ) { v80 = *(unsigned int *)(CurrentProcessWin32Process + 60); if ( (int)v80 < gProcessHandleQuota ) { v80 = (unsigned int)(v80 + 1); *(_DWORD *)(CurrentProcessWin32Process + 60) = v80; v82 = *(_DWORD *)(CurrentProcessWin32Process + 64); if ( (unsigned int)v80 > v82 ) v82 = v80; *(_DWORD *)(v81 + 64) = v82; } else { v77 = 0; } } } else if ( PsLookupProcessByProcessId((HANDLE)(int)v68, &Process) >= 0 ) { v83 = PsGetProcessWin32Process(Process); v84 = v83; if ( v83 ) { v85 = *(_DWORD *)(v83 + 60); if ( v85 < gProcessHandleQuota ) { v86 = v85 + 1; *(_DWORD *)(v83 + 60) = v86; v87 = *(_DWORD *)(v83 + 64); if ( v86 > v87 ) v87 = v86; *(_DWORD *)(v84 + 64) = v87; } else { v77 = 0; } } ObfDereferenceObject(Process); } if ( gbLockEtw && (Microsoft_Windows_Win32kEnableBits & 0x10) != 0 ) Template_pz(v80, &LockRelease, v72, ghsemHmgr, L"ghsemHmgr"); v71 = (__int64)ghsemHmgr; if ( ghsemHmgr ) { ExReleaseResourceAndLeaveCriticalRegion(ghsemHmgr); PsLeavePriorityRegion(); } if ( !v77 ) goto LABEL_185; } } } if ( ghFreeHmgr ) { v72 = (unsigned __int16)ghFreeHmgr; v88 = gpentHmgr + 24i64 * (unsigned __int16)ghFreeHmgr; v71 = 65285i64; ghFreeHmgr = *(_QWORD *)v88; v89 = *(_WORD *)(v88 + 12) & 0xFF00 | 5; *(_WORD *)(v88 + 12) = v89; v67 = (int)v72 | (unsigned __int64)(v89 << 16); } else { if ( gcMaxHmgr >= (unsigned int)gMaxGdiHandleCount ) goto LABEL_183; v71 = 3i64 * (unsigned int)gcMaxHmgr; *(_WORD *)(gpentHmgr + 24i64 * (unsigned int)gcMaxHmgr + 12) = 261; v67 = gcMaxHmgr++ | 0x1050000i64; } if ( !v67 ) { LABEL_183: if ( !v76 ) HmgDecProcessHandleCount((unsigned int)v68); goto LABEL_185; } v90 = gpentHmgr; v91 = (__int64 *)PsGetThreadWin32Thread(KeGetCurrentThread()); v92 = v136; if ( v91 && (v93 = *v91) != 0 && (v136 & 0x10) == 0 ) v94 = *(_QWORD *)(v93 + 72); else v94 = 0i64; PsGetCurrentThreadWin32ThreadAndEnterCriticalRegion(v134); v95 = (unsigned __int16)v67; v117 = (unsigned __int16)v67; v128 = (unsigned __int16)v67; _m_prefetchw((const void *)(v90 + 24i64 * (unsigned __int16)v67 + 8)); v96 = (*(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 15) & 0x20) == 0; v97 = *(_DWORD *)(v90 + 24i64 * (unsigned __int16)v67 + 8); v126 = v97; if ( !v96 ) { LABEL_209: KeLeaveCriticalRegion(); goto LABEL_210; } while ( (*(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 15) & 0x40) == 0 ) { if ( (v97 & 1) != 0 ) { KeDelayExecutionThread(0, 0, gpLockShortDelay); LABEL_208: _m_prefetchw((const void *)(v90 + 24i64 * (unsigned __int16)v67 + 8)); v96 = (*(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 15) & 0x20) == 0; v97 = *(_DWORD *)(v90 + 24i64 * (unsigned __int16)v67 + 8); v126 = v97; if ( !v96 ) goto LABEL_209; } else { v127 = v97 | 1; if ( v97 != _InterlockedCompareExchange( (volatile signed __int32 *)(v90 + 24i64 * (unsigned __int16)v67 + 8), v97 | 1, v97) || (*(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 15) & 0x40) != 0 ) { goto LABEL_208; } *((_QWORD *)gpentPushLock + v128) = 0i64; *(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 15) |= 0x40u; _m_prefetchw((const void *)(v90 + 24i64 * (unsigned __int16)v67 + 8)); v126 = *(_DWORD *)(v90 + 24i64 * (unsigned __int16)v67 + 8) & 0xFFFFFFFE; _InterlockedExchange((volatile __int32 *)(v90 + 24i64 * (unsigned __int16)v67 + 8), v126); v97 = v126; } } v99 = 8i64 * v128; ExAcquirePushLockExclusiveEx((char *)gpentPushLock + v99, 0i64); *(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 15) &= 0x40u; v100 = v121; v101 = v136; v102 = *(_DWORD *)(v90 + 24i64 * (unsigned __int16)v67 + 8); *(_QWORD *)(v90 + 24i64 * (unsigned __int16)v67) = v121; *(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 14) = 5; *(_QWORD *)(v90 + 24i64 * (unsigned __int16)v67 + 16) = 0i64; if ( (v136 & 8) != 0 ) { v103 = v102 & 1; } else if ( v94 ) { v103 = *(_DWORD *)(v94 + 8) ^ (*(_DWORD *)(v94 + 8) ^ v102) & 1; } else { CurrentProcessId = (unsigned int)PsGetCurrentProcessId(); v100 = v121; v101 = v136; v103 = v102 & 1 | CurrentProcessId & 0xFFFFFFFC; } if ( (v101 & 1) != 0 ) { if ( v94 ) CurrentThread = *(struct _KTHREAD **)v94; else CurrentThread = KeGetCurrentThread(); *((_QWORD *)v100 + 2) = CurrentThread; } ++gcCurHmgr; *((_WORD *)v100 + 6) = v101 & 1; *((_DWORD *)v100 + 2) = (v101 >> 1) & 1; *(_QWORD *)(v90 + 24i64 * (unsigned __int16)v67 + 16) = 0i64; *(_DWORD *)(v90 + 24i64 * (unsigned __int16)v67 + 8) = v103; if ( (*(_BYTE *)(v90 + 24i64 * (unsigned __int16)v67 + 15) & 0x40) != 0 ) { ExReleasePushLockExclusiveEx((char *)gpentPushLock + v99, 0i64); } else { _m_prefetchw((const void *)(v90 + 24i64 * (unsigned __int16)v67 + 8)); v126 = v103 & 0xFFFFFFFE; _InterlockedExchange((volatile __int32 *)(v90 + 24i64 * (unsigned __int16)v67 + 8), v103 & 0xFFFFFFFE); } KeLeaveCriticalRegion(); v95 = v117; v92 = v136; LABEL_210: v96 = gbGdiHmgrStacks == 0; v98 = v121; *(_QWORD *)v121 = v67; if ( !v96 && gpentHmgrStacks ) { RECSTACKBACKTRACE(v95); v98 = v121; } if ( (v92 & 2) != 0 && gbGdiHmgrAltStacks && gpentHmgrAltStacks ) RECALTLOCKSTACKBACKTRACE(v95, v98); v10 = a2; LABEL_185: if ( gbLockEtw && (Microsoft_Windows_Win32kEnableBits & 0x10) != 0 ) Template_pz(v71, &LockRelease, v72, ghsemHmgr, L"ghsemHmgr"); if ( ghsemHmgr ) { ExReleaseResourceAndLeaveCriticalRegion(ghsemHmgr); PsLeavePriorityRegion(); } if ( v67 ) { *(_QWORD *)(*(_QWORD *)this + 32i64) = **(_QWORD **)this; if ( (*(_WORD *)(*(_QWORD *)this + 102i64) & 0x800) != 0 && *((_QWORD *)&v129[2] + 1) ) { v106 = v129[0]; *(_QWORD *)(*(_QWORD *)this + 240i64) = Object; v107 = *(_QWORD *)this; v108 = v129[1]; *(_OWORD *)(v107 + 264) = v106; v109 = v129[2]; *(_OWORD *)(v107 + 280) = v108; *(_OWORD *)(v107 + 296) = v109; *(_QWORD *)(*(_QWORD *)this + 72i64) = 0i64; *(_QWORD *)(*(_QWORD *)this + 80i64) = 0i64; *(_DWORD *)(*(_QWORD *)this + 112i64) |= 0x200u; } } else { if ( *(_QWORD *)(*(_QWORD *)this + 120i64) ) { v130 = *(_QWORD *)(*(_QWORD *)this + 120i64); XEPALOBJ::vUnrefPalette((XEPALOBJ *)&v130, 1); *(_QWORD *)(*(_QWORD *)this + 120i64) = 0i64; } FreeObject(*(_QWORD *)this, 5i64); LABEL_237: v110 = pv; v120 = 0; *(_QWORD *)this = 0i64; if ( v110 || Object ) { v111 = *((_DWORD *)v10 + 6); if ( (v111 & 8) != 0 ) { if ( (v111 & 0x80u) == 0 ) { EngFreeUserMem(v110); } else { v112 = W32GetThreadWin32Thread(KeGetCurrentThread()); if ( *(_QWORD *)(v112 + 72) ) { v113 = pv; v114 = PsGetCurrentProcess(); MmUnmapViewOfSection(v114, v113); if ( PsLookupProcessByProcessId((HANDLE)*(int *)(*(_QWORD *)(v112 + 72) + 8i64), &v124) >= 0 ) { MmUnmapViewOfSection(v124, v122); ObfDereferenceObject(v124); } v115 = Object; if ( !Object ) KeBugCheckEx(0x50u, 0i64, 0i64, 0x6D626B47ui64, 0i64); goto LABEL_251; } } } else if ( (v118 & 0x800) != 0 ) { W32PIDLOCK::vCleanUp((W32PIDLOCK *)v129); if ( !v119 ) { v115 = Object; if ( !Object ) KeBugCheckEx(0x50u, 0i64, 0i64, 0x6D626B47ui64, 0i64); LABEL_251: ObfDereferenceObject(v115); } } else if ( (v118 & 0x10) != 0 ) { vFreeKernelSection(v110); } } } return v120; case 6: case 7: case 8: case 9: v13 = 1; goto LABEL_17; default: return 0i64; } }