Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengdiobj.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS win32 kernel mode subsystem 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: subsystems/win32/win32k/objects/gdiobj.c 00005 * PURPOSE: General GDI object manipulation routines 00006 * PROGRAMMERS: Timo Kreuzer 00007 */ 00008 00009 /* 00010 * If you want to understand this code, you need to start thinking in portals. 00011 * - gpaulRefCount is a global pointer to an allocated array of ULONG values, 00012 * one for each handle. Bits 0 - 22 contain a reference count for the handle. 00013 * It gets increased for each handle lock / reference. Bit 23 contains a valid 00014 * bit. If this bit is 0, the handle got deleted and will be pushed to the free 00015 * list, once all references are gone. Bits 24 - 31 contain the reuse value of 00016 * the handle, which allows to check if the entry was changed before atomically 00017 * exchanging the reference count. 00018 * - Objects can exist with or without a handle 00019 * - Objects with a handle can be locked either exclusively or shared. 00020 * Both locks increase the handle reference count in gpaulRefCount. 00021 * Exclusive locks also increase the BASEOBJECT's cExclusiveLock field 00022 * and the first lock (can be acquired recursively) acquires a pushlock 00023 * that is also stored in the BASEOBJECT. 00024 * - Objects without a handle cannot have exclusive locks. Their reference 00025 * count is tracked in the BASEOBJECT's ulShareCount field. 00026 * - An object that is inserted in the handle table automatically has an 00027 * exclusive lock. For objects that are "shared objects" (BRUSH, PALETTE, ...) 00028 * this is the only way it can ever be exclusively locked. It prevents the 00029 * object from being locked by another thread. A shared lock will simply fail, 00030 * while an exclusive lock will succeed after the object was unlocked. 00031 * 00032 */ 00033 00034 /* INCLUDES ******************************************************************/ 00035 00036 #include <win32k.h> 00037 #define NDEBUG 00038 #include <debug.h> 00039 00040 // Move to gdidbg.h 00041 #if DBG 00042 #define DBG_INCREASE_LOCK_COUNT(pti, hobj) \ 00043 if (pti) ((PTHREADINFO)pti)->acExclusiveLockCount[((ULONG_PTR)hobj >> 16) & 0x1f]++; 00044 #define DBG_DECREASE_LOCK_COUNT(pti, hobj) \ 00045 if (pti) ((PTHREADINFO)pti)->acExclusiveLockCount[((ULONG_PTR)hobj >> 16) & 0x1f]--; 00046 #define ASSERT_SHARED_OBJECT_TYPE(objt) \ 00047 ASSERT((objt) == GDIObjType_SURF_TYPE || \ 00048 (objt) == GDIObjType_PAL_TYPE || \ 00049 (objt) == GDIObjType_LFONT_TYPE || \ 00050 (objt) == GDIObjType_PATH_TYPE || \ 00051 (objt) == GDIObjType_BRUSH_TYPE) 00052 #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) \ 00053 ASSERT((objt) == GDIObjType_DC_TYPE || \ 00054 (objt) == GDIObjType_RGN_TYPE || \ 00055 (objt) == GDIObjType_LFONT_TYPE) 00056 #else 00057 #define DBG_INCREASE_LOCK_COUNT(ppi, hobj) 00058 #define DBG_DECREASE_LOCK_COUNT(x, y) 00059 #define ASSERT_SHARED_OBJECT_TYPE(objt) 00060 #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) 00061 #endif 00062 00063 #define MmMapViewInSessionSpace MmMapViewInSystemSpace 00064 00065 #if defined(_M_IX86) || defined(_M_AMD64) 00066 #define InterlockedOr16 _InterlockedOr16 00067 #endif 00068 00069 #define GDIOBJ_POOL_TAG(type) ('00hG' + ((objt & 0x1f) << 24)) 00070 00071 enum 00072 { 00073 REF_MASK_REUSE = 0xff000000, 00074 REF_INC_REUSE = 0x01000000, 00075 REF_MASK_VALID = 0x00800000, 00076 REF_MASK_COUNT = 0x007fffff, 00077 REF_MASK_INUSE = 0x00ffffff, 00078 }; 00079 00080 /* GLOBALS *******************************************************************/ 00081 00082 /* Per session handle table globals */ 00083 static PVOID gpvGdiHdlTblSection = NULL; 00084 static PENTRY gpentHmgr; 00085 static PULONG gpaulRefCount; 00086 ULONG gulFirstFree; 00087 ULONG gulFirstUnused; 00088 static PPAGED_LOOKASIDE_LIST gpaLookasideList; 00089 00090 static BOOL NTAPI GDIOBJ_Cleanup(PVOID ObjectBody); 00091 00092 static const 00093 GDICLEANUPPROC 00094 apfnCleanup[] = 00095 { 00096 NULL, /* 00 GDIObjType_DEF_TYPE */ 00097 DC_Cleanup, /* 01 GDIObjType_DC_TYPE */ 00098 NULL, /* 02 GDIObjType_UNUSED1_TYPE */ 00099 NULL, /* 03 GDIObjType_UNUSED2_TYPE */ 00100 REGION_Cleanup, /* 04 GDIObjType_RGN_TYPE */ 00101 SURFACE_Cleanup, /* 05 GDIObjType_SURF_TYPE */ 00102 GDIOBJ_Cleanup, /* 06 GDIObjType_CLIENTOBJ_TYPE */ 00103 GDIOBJ_Cleanup, /* 07 GDIObjType_PATH_TYPE */ 00104 PALETTE_Cleanup, /* 08 GDIObjType_PAL_TYPE */ 00105 GDIOBJ_Cleanup, /* 09 GDIObjType_ICMLCS_TYPE */ 00106 GDIOBJ_Cleanup, /* 0a GDIObjType_LFONT_TYPE */ 00107 NULL, /* 0b GDIObjType_RFONT_TYPE, unused */ 00108 NULL, /* 0c GDIObjType_PFE_TYPE, unused */ 00109 NULL, /* 0d GDIObjType_PFT_TYPE, unused */ 00110 GDIOBJ_Cleanup, /* 0e GDIObjType_ICMCXF_TYPE */ 00111 NULL, /* 0f GDIObjType_SPRITE_TYPE, unused */ 00112 BRUSH_Cleanup, /* 10 GDIObjType_BRUSH_TYPE, BRUSH, PEN, EXTPEN */ 00113 NULL, /* 11 GDIObjType_UMPD_TYPE, unused */ 00114 NULL, /* 12 GDIObjType_UNUSED4_TYPE */ 00115 NULL, /* 13 GDIObjType_SPACE_TYPE, unused */ 00116 NULL, /* 14 GDIObjType_UNUSED5_TYPE */ 00117 NULL, /* 15 GDIObjType_META_TYPE, unused */ 00118 NULL, /* 16 GDIObjType_EFSTATE_TYPE, unused */ 00119 NULL, /* 17 GDIObjType_BMFD_TYPE, unused */ 00120 NULL, /* 18 GDIObjType_VTFD_TYPE, unused */ 00121 NULL, /* 19 GDIObjType_TTFD_TYPE, unused */ 00122 NULL, /* 1a GDIObjType_RC_TYPE, unused */ 00123 NULL, /* 1b GDIObjType_TEMP_TYPE, unused */ 00124 DRIVEROBJ_Cleanup,/* 1c GDIObjType_DRVOBJ_TYPE */ 00125 NULL, /* 1d GDIObjType_DCIOBJ_TYPE, unused */ 00126 NULL, /* 1e GDIObjType_SPOOL_TYPE, unused */ 00127 NULL, /* 1f reserved entry */ 00128 }; 00129 00130 /* INTERNAL FUNCTIONS ********************************************************/ 00131 00132 static 00133 BOOL NTAPI 00134 GDIOBJ_Cleanup(PVOID ObjectBody) 00135 { 00136 return TRUE; 00137 } 00138 00139 static 00140 VOID 00141 InitLookasideList(UCHAR objt, ULONG cjSize) 00142 { 00143 ExInitializePagedLookasideList(&gpaLookasideList[objt], 00144 NULL, 00145 NULL, 00146 0, 00147 cjSize, 00148 GDITAG_HMGR_LOOKASIDE_START + (objt << 24), 00149 0); 00150 } 00151 00152 INIT_FUNCTION 00153 NTSTATUS 00154 NTAPI 00155 InitGdiHandleTable(void) 00156 { 00157 NTSTATUS status; 00158 LARGE_INTEGER liSize; 00159 PVOID pvSection; 00160 SIZE_T cjViewSize = 0; 00161 00162 /* Create a section for the shared handle table */ 00163 liSize.QuadPart = sizeof(GDI_HANDLE_TABLE); // GDI_HANDLE_COUNT * sizeof(ENTRY); 00164 status = MmCreateSection(&gpvGdiHdlTblSection, 00165 SECTION_ALL_ACCESS, 00166 NULL, 00167 &liSize, 00168 PAGE_READWRITE, 00169 SEC_COMMIT, 00170 NULL, 00171 NULL); 00172 if (!NT_SUCCESS(status)) 00173 { 00174 DPRINT1("INITGDI: Could not allocate a GDI handle table.\n"); 00175 return status; 00176 } 00177 00178 /* Map the section in session space */ 00179 status = MmMapViewInSessionSpace(gpvGdiHdlTblSection, 00180 (PVOID*)&gpentHmgr, 00181 &cjViewSize); 00182 if (!NT_SUCCESS(status)) 00183 { 00184 DPRINT1("INITGDI: Failed to map handle table section\n"); 00185 ObDereferenceObject(gpvGdiHdlTblSection); 00186 return status; 00187 } 00188 00189 /* Allocate memory for the reference counter table */ 00190 gpaulRefCount = EngAllocSectionMem(&pvSection, 00191 FL_ZERO_MEMORY, 00192 GDI_HANDLE_COUNT * sizeof(ULONG), 00193 'frHG'); 00194 if (!gpaulRefCount) 00195 { 00196 DPRINT1("INITGDI: Failed to allocate reference table.\n"); 00197 ObDereferenceObject(gpvGdiHdlTblSection); 00198 return STATUS_INSUFFICIENT_RESOURCES; 00199 } 00200 00201 gulFirstFree = 0; 00202 gulFirstUnused = RESERVE_ENTRIES_COUNT; 00203 00204 GdiHandleTable = (PVOID)gpentHmgr; 00205 00206 /* Initialize the lookaside lists */ 00207 gpaLookasideList = ExAllocatePoolWithTag(NonPagedPool, 00208 GDIObjTypeTotal * sizeof(PAGED_LOOKASIDE_LIST), 00209 TAG_GDIHNDTBLE); 00210 if(!gpaLookasideList) 00211 return STATUS_NO_MEMORY; 00212 00213 InitLookasideList(GDIObjType_DC_TYPE, sizeof(DC)); 00214 InitLookasideList(GDIObjType_RGN_TYPE, sizeof(REGION)); 00215 InitLookasideList(GDIObjType_SURF_TYPE, sizeof(SURFACE)); 00216 InitLookasideList(GDIObjType_CLIENTOBJ_TYPE, sizeof(CLIENTOBJ)); 00217 InitLookasideList(GDIObjType_PATH_TYPE, sizeof(PATH)); 00218 InitLookasideList(GDIObjType_PAL_TYPE, sizeof(PALETTE)); 00219 InitLookasideList(GDIObjType_ICMLCS_TYPE, sizeof(COLORSPACE)); 00220 InitLookasideList(GDIObjType_LFONT_TYPE, sizeof(TEXTOBJ)); 00221 InitLookasideList(GDIObjType_BRUSH_TYPE, sizeof(BRUSH)); 00222 00223 return STATUS_SUCCESS; 00224 } 00225 00226 FORCEINLINE 00227 VOID 00228 IncrementGdiHandleCount(void) 00229 { 00230 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); 00231 if (ppi) InterlockedIncrement((LONG*)&ppi->GDIHandleCount); 00232 } 00233 00234 FORCEINLINE 00235 VOID 00236 DecrementGdiHandleCount(void) 00237 { 00238 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); 00239 if (ppi) InterlockedDecrement((LONG*)&ppi->GDIHandleCount); 00240 } 00241 00242 static 00243 PENTRY 00244 ENTRY_pentPopFreeEntry(VOID) 00245 { 00246 ULONG iFirst, iNext, iPrev; 00247 PENTRY pentFree; 00248 00249 DPRINT("Enter InterLockedPopFreeEntry\n"); 00250 00251 do 00252 { 00253 /* Get the index and sequence number of the first free entry */ 00254 iFirst = gulFirstFree; 00255 00256 /* Check if we have a free entry */ 00257 if (!(iFirst & GDI_HANDLE_INDEX_MASK)) 00258 { 00259 /* Increment FirstUnused and get the new index */ 00260 iFirst = InterlockedIncrement((LONG*)&gulFirstUnused) - 1; 00261 00262 /* Check if we have unused entries left */ 00263 if (iFirst >= GDI_HANDLE_COUNT) 00264 { 00265 DPRINT1("No more GDI handles left!\n"); 00266 return 0; 00267 } 00268 00269 /* Return the old entry */ 00270 return &gpentHmgr[iFirst]; 00271 } 00272 00273 /* Get a pointer to the first free entry */ 00274 pentFree = &gpentHmgr[iFirst & GDI_HANDLE_INDEX_MASK]; 00275 00276 /* Create a new value with an increased sequence number */ 00277 iNext = (USHORT)(ULONG_PTR)pentFree->einfo.pobj; 00278 iNext |= (iFirst & ~GDI_HANDLE_INDEX_MASK) + 0x10000; 00279 00280 /* Try to exchange the FirstFree value */ 00281 iPrev = InterlockedCompareExchange((LONG*)&gulFirstFree, 00282 iNext, 00283 iFirst); 00284 } 00285 while (iPrev != iFirst); 00286 00287 /* Sanity check: is entry really free? */ 00288 ASSERT(((ULONG_PTR)pentFree->einfo.pobj & ~GDI_HANDLE_INDEX_MASK) == 0); 00289 00290 return pentFree; 00291 } 00292 00293 /* Pushes an entry of the handle table to the free list, 00294 The entry must not have any references left */ 00295 static 00296 VOID 00297 ENTRY_vPushFreeEntry(PENTRY pentFree) 00298 { 00299 ULONG iToFree, iFirst, iPrev, idxToFree; 00300 00301 DPRINT("Enter ENTRY_vPushFreeEntry\n"); 00302 00303 idxToFree = pentFree - gpentHmgr; 00304 ASSERT((gpaulRefCount[idxToFree] & REF_MASK_INUSE) == 0); 00305 00306 /* Initialize entry */ 00307 pentFree->Objt = GDIObjType_DEF_TYPE; 00308 pentFree->ObjectOwner.ulObj = 0; 00309 pentFree->pUser = NULL; 00310 00311 /* Increase reuse counter in entry and reference counter */ 00312 InterlockedExchangeAdd((LONG*)&gpaulRefCount[idxToFree], REF_INC_REUSE); 00313 pentFree->FullUnique += 0x0100; 00314 00315 do 00316 { 00317 /* Get the current first free index and sequence number */ 00318 iFirst = gulFirstFree; 00319 00320 /* Set the einfo.pobj member to the index of the first free entry */ 00321 pentFree->einfo.pobj = UlongToPtr(iFirst & GDI_HANDLE_INDEX_MASK); 00322 00323 /* Combine new index and increased sequence number in iToFree */ 00324 iToFree = idxToFree | ((iFirst & ~GDI_HANDLE_INDEX_MASK) + 0x10000); 00325 00326 /* Try to atomically update the first free entry */ 00327 iPrev = InterlockedCompareExchange((LONG*)&gulFirstFree, 00328 iToFree, 00329 iFirst); 00330 } 00331 while (iPrev != iFirst); 00332 } 00333 00334 static 00335 PENTRY 00336 ENTRY_ReferenceEntryByHandle(HGDIOBJ hobj, FLONG fl) 00337 { 00338 ULONG ulIndex, cNewRefs, cOldRefs; 00339 PENTRY pentry; 00340 00341 /* Get the handle index and check if its too big */ 00342 ulIndex = GDI_HANDLE_GET_INDEX(hobj); 00343 if (ulIndex >= GDI_HANDLE_COUNT) return NULL; 00344 00345 /* Get pointer to the entry */ 00346 pentry = &gpentHmgr[ulIndex]; 00347 00348 /* Get the current reference count */ 00349 cOldRefs = gpaulRefCount[ulIndex]; 00350 00351 do 00352 { 00353 /* Check if the slot is deleted */ 00354 if ((cOldRefs & REF_MASK_VALID) == 0) 00355 { 00356 DPRINT("GDIOBJ: Slot is not valid: 0x%lx, hobh=%p\n", cOldRefs, hobj); 00357 return NULL; 00358 } 00359 00360 /* Check if the unique value matches */ 00361 if (pentry->FullUnique != (USHORT)((ULONG_PTR)hobj >> 16)) 00362 { 00363 DPRINT("GDIOBJ: Wrong unique value. Handle: 0x%4x, entry: 0x%4x\n", 00364 (USHORT)((ULONG_PTR)hobj >> 16, pentry->FullUnique)); 00365 return NULL; 00366 } 00367 00368 /* Check if the object owner is this process or public */ 00369 if (!(fl & GDIOBJFLAG_IGNOREPID) && 00370 pentry->ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC && 00371 pentry->ObjectOwner.ulObj != PtrToUlong(PsGetCurrentProcessId())) 00372 { 00373 DPRINT("GDIOBJ: Cannot reference foreign handle %p, pentry=%p:%lx.\n", 00374 hobj, pentry, pentry->ObjectOwner.ulObj); 00375 return NULL; 00376 } 00377 00378 /* Try to atomically increment the reference count */ 00379 cNewRefs = cOldRefs + 1; 00380 cOldRefs = InterlockedCompareExchange((PLONG)&gpaulRefCount[ulIndex], 00381 cNewRefs, 00382 cOldRefs); 00383 } 00384 while (cNewRefs != cOldRefs + 1); 00385 00386 /* Integrity checks */ 00387 ASSERT((pentry->FullUnique & 0x1f) == pentry->Objt); 00388 ASSERT(pentry->einfo.pobj && pentry->einfo.pobj->hHmgr == hobj); 00389 00390 return pentry; 00391 } 00392 00393 static 00394 HGDIOBJ 00395 ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner) 00396 { 00397 ULONG ulIndex; 00398 00399 /* Calculate the handle index */ 00400 ulIndex = pentry - gpentHmgr; 00401 00402 /* Update the fields in the ENTRY */ 00403 pentry->einfo.pobj = pobj; 00404 pentry->Objt = objt & 0x1f; 00405 pentry->FullUnique = (pentry->FullUnique & 0xff00) | objt; 00406 pentry->ObjectOwner.ulObj = ulOwner; 00407 00408 /* Make the handle valid with 1 reference */ 00409 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_INUSE) == 0); 00410 InterlockedOr((LONG*)&gpaulRefCount[ulIndex], REF_MASK_VALID | 1); 00411 00412 /* Return the handle */ 00413 return (HGDIOBJ)(((ULONG_PTR)pentry->FullUnique << 16) | ulIndex); 00414 } 00415 00416 POBJ 00417 NTAPI 00418 GDIOBJ_AllocateObject(UCHAR objt, ULONG cjSize, FLONG fl) 00419 { 00420 POBJ pobj; 00421 00422 if (fl & BASEFLAG_LOOKASIDE) 00423 { 00424 /* Allocate the object from a lookaside list */ 00425 pobj = ExAllocateFromPagedLookasideList(&gpaLookasideList[objt & 0x1f]); 00426 } 00427 else 00428 { 00429 /* Allocate the object from paged pool */ 00430 pobj = ExAllocatePoolWithTag(PagedPool, cjSize, GDIOBJ_POOL_TAG(objt)); 00431 } 00432 00433 if (!pobj) return NULL; 00434 00435 /* Initialize the object */ 00436 RtlZeroMemory(pobj, cjSize); 00437 pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)objt << 16); 00438 pobj->cExclusiveLock = 0; 00439 pobj->ulShareCount = 1; 00440 pobj->BaseFlags = fl & 0xffff; 00441 DBG_INITLOG(&pobj->slhLog); 00442 DBG_LOGEVENT(&pobj->slhLog, EVENT_ALLOCATE, 0); 00443 00444 return pobj; 00445 } 00446 00447 VOID 00448 NTAPI 00449 GDIOBJ_vFreeObject(POBJ pobj) 00450 { 00451 UCHAR objt; 00452 00453 DBG_CLEANUP_EVENT_LIST(&pobj->slhLog); 00454 00455 /* Get the object type */ 00456 objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0x1f; 00457 00458 /* Call the cleanup procedure */ 00459 ASSERT(apfnCleanup[objt]); 00460 apfnCleanup[objt](pobj); 00461 00462 /* Check if the object is allocated from a lookaside list */ 00463 if (pobj->BaseFlags & BASEFLAG_LOOKASIDE) 00464 { 00465 ExFreeToPagedLookasideList(&gpaLookasideList[objt], pobj); 00466 } 00467 else 00468 { 00469 ExFreePoolWithTag(pobj, GDIOBJ_POOL_TAG(objt)); 00470 } 00471 } 00472 00473 VOID 00474 NTAPI 00475 GDIOBJ_vDereferenceObject(POBJ pobj) 00476 { 00477 ULONG cRefs, ulIndex; 00478 00479 /* Calculate the index */ 00480 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr); 00481 00482 /* Check if the object has a handle */ 00483 if (ulIndex) 00484 { 00485 /* Decrement reference count */ 00486 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0); 00487 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]); 00488 DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs); 00489 00490 /* Check if we reached 0 and handle bit is not set */ 00491 if ((cRefs & REF_MASK_INUSE) == 0) 00492 { 00493 /* Make sure it's ok to delete the object */ 00494 ASSERT(pobj->BaseFlags & BASEFLAG_READY_TO_DIE); 00495 00496 /* Check if the handle was process owned */ 00497 if (gpentHmgr[ulIndex].ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC && 00498 gpentHmgr[ulIndex].ObjectOwner.ulObj != GDI_OBJ_HMGR_NONE) 00499 { 00500 /* Decrement the process handle count */ 00501 ASSERT(gpentHmgr[ulIndex].ObjectOwner.ulObj == 00502 HandleToUlong(PsGetCurrentProcessId())); 00503 DecrementGdiHandleCount(); 00504 } 00505 00506 /* Push entry to the free list */ 00507 ENTRY_vPushFreeEntry(&gpentHmgr[ulIndex]); 00508 00509 /* Free the object */ 00510 GDIOBJ_vFreeObject(pobj); 00511 } 00512 } 00513 else 00514 { 00515 /* Decrement the objects reference count */ 00516 ASSERT(pobj->ulShareCount > 0); 00517 cRefs = InterlockedDecrement((LONG*)&pobj->ulShareCount); 00518 DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs); 00519 00520 /* Check if we reached 0 */ 00521 if (cRefs == 0) 00522 { 00523 /* Free the object */ 00524 GDIOBJ_vFreeObject(pobj); 00525 } 00526 } 00527 } 00528 00529 POBJ 00530 NTAPI 00531 GDIOBJ_ReferenceObjectByHandle( 00532 HGDIOBJ hobj, 00533 UCHAR objt) 00534 { 00535 PENTRY pentry; 00536 POBJ pobj; 00537 00538 /* Check if the handle type matches */ 00539 ASSERT_SHARED_OBJECT_TYPE(objt); 00540 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt) 00541 { 00542 DPRINT("GDIOBJ: Wrong type. handle=%p, type=%x\n", hobj, objt); 00543 return NULL; 00544 } 00545 00546 /* Reference the handle entry */ 00547 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0); 00548 if (!pentry) 00549 { 00550 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj); 00551 return NULL; 00552 } 00553 00554 /* Get the pointer to the BASEOBJECT */ 00555 pobj = pentry->einfo.pobj; 00556 00557 /* Check if the object is exclusively locked */ 00558 if (pobj->cExclusiveLock != 0) 00559 { 00560 DPRINT1("GDIOBJ: Cannot reference oject %p with exclusive lock.\n", hobj); 00561 GDIOBJ_vDereferenceObject(pobj); 00562 DBG_DUMP_EVENT_LIST(&pobj->slhLog); 00563 return NULL; 00564 } 00565 00566 DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, gpaulRefCount[pentry - gpentHmgr]); 00567 00568 /* All is well, return the object */ 00569 return pobj; 00570 } 00571 00572 VOID 00573 NTAPI 00574 GDIOBJ_vReferenceObjectByPointer(POBJ pobj) 00575 { 00576 ULONG cRefs; 00577 00578 /* Check if the object has a handle */ 00579 if (GDI_HANDLE_GET_INDEX(pobj->hHmgr)) 00580 { 00581 /* Increase the handle's reference count */ 00582 ULONG ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr); 00583 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0); 00584 cRefs = InterlockedIncrement((LONG*)&gpaulRefCount[ulIndex]); 00585 } 00586 else 00587 { 00588 /* Increase the object's reference count */ 00589 cRefs = InterlockedIncrement((LONG*)&pobj->ulShareCount); 00590 } 00591 00592 DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, cRefs); 00593 } 00594 00595 PGDIOBJ 00596 NTAPI 00597 GDIOBJ_LockObject( 00598 HGDIOBJ hobj, 00599 UCHAR objt) 00600 { 00601 PENTRY pentry; 00602 POBJ pobj; 00603 DWORD dwThreadId; 00604 00605 /* Check if the handle type matches */ 00606 ASSERT_EXCLUSIVE_OBJECT_TYPE(objt); 00607 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt) 00608 { 00609 DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt); 00610 return NULL; 00611 } 00612 00613 /* Reference the handle entry */ 00614 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0); 00615 if (!pentry) 00616 { 00617 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj); 00618 return NULL; 00619 } 00620 00621 /* Get the pointer to the BASEOBJECT */ 00622 pobj = pentry->einfo.pobj; 00623 00624 /* Check if we already own the lock */ 00625 dwThreadId = PtrToUlong(PsGetCurrentThreadId()); 00626 if (pobj->dwThreadId != dwThreadId) 00627 { 00628 /* Disable APCs and acquire the push lock */ 00629 KeEnterCriticalRegion(); 00630 ExAcquirePushLockExclusive(&pobj->pushlock); 00631 00632 /* Set us as lock owner */ 00633 ASSERT(pobj->dwThreadId == 0); 00634 pobj->dwThreadId = dwThreadId; 00635 } 00636 00637 /* Increase lock count */ 00638 pobj->cExclusiveLock++; 00639 DBG_INCREASE_LOCK_COUNT(PsGetCurrentProcessWin32Process(), hobj); 00640 DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0); 00641 00642 /* Return the object */ 00643 return pobj; 00644 } 00645 00646 VOID 00647 NTAPI 00648 GDIOBJ_vUnlockObject(POBJ pobj) 00649 { 00650 ULONG cRefs, ulIndex; 00651 ASSERT(pobj->cExclusiveLock > 0); 00652 00653 /* Decrease lock count */ 00654 pobj->cExclusiveLock--; 00655 DBG_DECREASE_LOCK_COUNT(PsGetCurrentProcessWin32Process(), pobj->hHmgr); 00656 DBG_LOGEVENT(&pobj->slhLog, EVENT_UNLOCK, 0); 00657 00658 /* Check if this was the last lock */ 00659 if (pobj->cExclusiveLock == 0) 00660 { 00661 /* Reset lock owner */ 00662 pobj->dwThreadId = 0; 00663 00664 /* Release the pushlock and reenable APCs */ 00665 ExReleasePushLockExclusive(&pobj->pushlock); 00666 KeLeaveCriticalRegion(); 00667 } 00668 00669 /* Calculate the index */ 00670 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr); 00671 00672 /* Decrement reference count */ 00673 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0); 00674 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]); 00675 ASSERT(cRefs & REF_MASK_VALID); 00676 } 00677 00678 HGDIOBJ 00679 NTAPI 00680 GDIOBJ_hInsertObject( 00681 POBJ pobj, 00682 ULONG ulOwner) 00683 { 00684 PENTRY pentry; 00685 UCHAR objt; 00686 00687 /* Must have no handle and only one reference */ 00688 ASSERT(GDI_HANDLE_GET_INDEX(pobj->hHmgr) == 0); 00689 ASSERT(pobj->cExclusiveLock == 0); 00690 ASSERT(pobj->ulShareCount == 1); 00691 00692 /* Get a free handle entry */ 00693 pentry = ENTRY_pentPopFreeEntry(); 00694 if (!pentry) 00695 { 00696 DPRINT1("GDIOBJ: Could not get a free entry.\n"); 00697 return NULL; 00698 } 00699 00700 /* Make the object exclusively locked */ 00701 ExInitializePushLock(&pobj->pushlock); 00702 KeEnterCriticalRegion(); 00703 ExAcquirePushLockExclusive(&pobj->pushlock); 00704 pobj->cExclusiveLock = 1; 00705 pobj->dwThreadId = PtrToUlong(PsGetCurrentThreadId()); 00706 DBG_INCREASE_LOCK_COUNT(PsGetCurrentProcessWin32Process(), pobj->hHmgr); 00707 00708 /* Get object type from the hHmgr field */ 00709 objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0xff; 00710 ASSERT(objt != GDIObjType_DEF_TYPE); 00711 00712 /* Check if current process is requested owner */ 00713 if (ulOwner == GDI_OBJ_HMGR_POWNED) 00714 { 00715 /* Increment the process handle count */ 00716 IncrementGdiHandleCount(); 00717 00718 /* Use Process id */ 00719 ulOwner = HandleToUlong(PsGetCurrentProcessId()); 00720 } 00721 00722 /* Insert the object into the handle table */ 00723 pobj->hHmgr = ENTRY_hInsertObject(pentry, pobj, objt, ulOwner); 00724 00725 /* Return the handle */ 00726 DPRINT("GDIOBJ: Created handle: %p\n", pobj->hHmgr); 00727 DBG_LOGEVENT(&pobj->slhLog, EVENT_CREATE_HANDLE, 0); 00728 return pobj->hHmgr; 00729 } 00730 00731 VOID 00732 NTAPI 00733 GDIOBJ_vSetObjectOwner( 00734 POBJ pobj, 00735 ULONG ulOwner) 00736 { 00737 PENTRY pentry; 00738 00739 /* This is a ugly HACK, needed to fix IntGdiSetDCOwnerEx */ 00740 if (GDI_HANDLE_IS_STOCKOBJ(pobj->hHmgr)) 00741 { 00742 DPRINT("Trying to set ownership of stock object %p to %lx\n", pobj->hHmgr, ulOwner); 00743 return; 00744 } 00745 00746 /* Get the handle entry */ 00747 ASSERT(GDI_HANDLE_GET_INDEX(pobj->hHmgr)); 00748 pentry = &gpentHmgr[GDI_HANDLE_GET_INDEX(pobj->hHmgr)]; 00749 00750 /* Is the current process requested? */ 00751 if (ulOwner == GDI_OBJ_HMGR_POWNED) 00752 { 00753 /* Use process id */ 00754 ulOwner = HandleToUlong(PsGetCurrentProcessId()); 00755 if (pentry->ObjectOwner.ulObj != ulOwner) 00756 { 00757 IncrementGdiHandleCount(); 00758 } 00759 } 00760 00761 // HACK 00762 if (ulOwner == GDI_OBJ_HMGR_NONE) 00763 ulOwner = GDI_OBJ_HMGR_PUBLIC; 00764 00765 if (ulOwner == GDI_OBJ_HMGR_PUBLIC || 00766 ulOwner == GDI_OBJ_HMGR_NONE) 00767 { 00768 /* Make sure we don't leak user mode memory */ 00769 ASSERT(pentry->pUser == NULL); 00770 if (pentry->ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC && 00771 pentry->ObjectOwner.ulObj != GDI_OBJ_HMGR_NONE) 00772 { 00773 DecrementGdiHandleCount(); 00774 } 00775 } 00776 00777 /* Set new owner */ 00778 pentry->ObjectOwner.ulObj = ulOwner; 00779 DBG_LOGEVENT(&pobj->slhLog, EVENT_SET_OWNER, 0); 00780 } 00781 00782 /* Locks 2 or 3 objects at a time */ 00783 BOOL 00784 NTAPI 00785 GDIOBJ_bLockMultipleObjects( 00786 IN ULONG ulCount, 00787 IN HGDIOBJ* ahObj, 00788 OUT PGDIOBJ* apObj, 00789 IN UCHAR objt) 00790 { 00791 UINT auiIndices[3] = {0, 1, 2}; 00792 UINT i, j, tmp; 00793 00794 ASSERT(ulCount <= 3); 00795 00796 /* Sort the handles */ 00797 for (i = 0; i < ulCount - 1; i++) 00798 { 00799 for (j = i + 1; j < ulCount; j++) 00800 { 00801 if ((ULONG_PTR)ahObj[auiIndices[i]] < 00802 (ULONG_PTR)ahObj[auiIndices[j]]) 00803 { 00804 tmp = auiIndices[i]; 00805 auiIndices[i] = auiIndices[j]; 00806 auiIndices[j] = tmp; 00807 } 00808 } 00809 } 00810 00811 /* Lock the objects in safe order */ 00812 for (i = 0; i < ulCount; i++) 00813 { 00814 /* Skip NULL handles */ 00815 if (ahObj[auiIndices[i]] == NULL) 00816 { 00817 apObj[auiIndices[i]] = NULL; 00818 continue; 00819 } 00820 00821 /* Lock the object */ 00822 apObj[auiIndices[i]] = GDIOBJ_LockObject(ahObj[auiIndices[i]], objt); 00823 00824 /* Check for failure */ 00825 if (apObj[auiIndices[i]] == NULL) 00826 { 00827 /* Cleanup */ 00828 while (i--) 00829 { 00830 if (apObj[auiIndices[i]]) 00831 GDIOBJ_vUnlockObject(apObj[auiIndices[i]]); 00832 } 00833 return FALSE; 00834 } 00835 } 00836 00837 return TRUE; 00838 } 00839 00840 PVOID 00841 NTAPI 00842 GDIOBJ_pvGetObjectAttr(POBJ pobj) 00843 { 00844 ULONG ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr); 00845 return gpentHmgr[ulIndex].pUser; 00846 } 00847 00848 VOID 00849 NTAPI 00850 GDIOBJ_vSetObjectAttr(POBJ pobj, PVOID pvObjAttr) 00851 { 00852 ULONG ulIndex; 00853 00854 ASSERT(pobj->hHmgr); 00855 00856 /* Get the handle index */ 00857 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr); 00858 00859 /* Set pointer to the usermode attribute */ 00860 gpentHmgr[ulIndex].pUser = pvObjAttr; 00861 } 00862 00863 VOID 00864 NTAPI 00865 GDIOBJ_vDeleteObject(POBJ pobj) 00866 { 00867 ULONG ulIndex; 00868 00869 /* Set the object's delete flag */ 00870 InterlockedOr16((SHORT*)&pobj->BaseFlags, BASEFLAG_READY_TO_DIE); 00871 DBG_LOGEVENT(&pobj->slhLog, EVENT_DELETE, 0); 00872 00873 /* Get the handle index */ 00874 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr); 00875 if (ulIndex) 00876 { 00877 /* Reset the handle valid bit */ 00878 InterlockedAnd((LONG*)&gpaulRefCount[ulIndex], ~REF_MASK_VALID); 00879 00880 /* Check if the object is exclusively locked */ 00881 if (pobj->cExclusiveLock != 0) 00882 { 00883 /* Reset lock owner and lock count */ 00884 pobj->dwThreadId = 0; 00885 pobj->cExclusiveLock = 0; 00886 00887 /* Release the pushlock and reenable APCs */ 00888 ExReleasePushLockExclusive(&pobj->pushlock); 00889 KeLeaveCriticalRegion(); 00890 DBG_DECREASE_LOCK_COUNT(PsGetCurrentProcessWin32Process(), pobj->hHmgr); 00891 } 00892 } 00893 00894 /* Dereference the object (will take care of deletion) */ 00895 GDIOBJ_vDereferenceObject(pobj); 00896 } 00897 00898 BOOL 00899 NTAPI 00900 GreIsHandleValid(HGDIOBJ hobj) 00901 { 00902 PENTRY pentry; 00903 00904 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0); 00905 if (!pentry) return FALSE; 00906 GDIOBJ_vDereferenceObject(pentry->einfo.pobj); 00907 return TRUE; 00908 } 00909 00910 BOOL 00911 NTAPI 00912 GreDeleteObject(HGDIOBJ hobj) 00913 { 00914 PENTRY pentry; 00915 00916 /* Check for stock objects */ 00917 if (GDI_HANDLE_IS_STOCKOBJ(hobj)) 00918 { 00919 DPRINT1("GreDeleteObject: Cannot delete stock object %p.\n", hobj); 00920 return FALSE; 00921 } 00922 00923 /* Reference the handle entry */ 00924 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0); 00925 if (!pentry) 00926 { 00927 DPRINT1("GreDeleteObject: Trying to delete invalid object %p\n", hobj); 00928 return FALSE; 00929 } 00930 00931 /* Check for public owner */ 00932 if (pentry->ObjectOwner.ulObj == GDI_OBJ_HMGR_PUBLIC) 00933 { 00934 DPRINT1("GreDeleteObject: Trying to delete global object %p\n", hobj); 00935 GDIOBJ_vDereferenceObject(pentry->einfo.pobj); 00936 return FALSE; 00937 } 00938 00939 /* Delete the object */ 00940 GDIOBJ_vDeleteObject(pentry->einfo.pobj); 00941 return TRUE; 00942 } 00943 00944 ULONG 00945 NTAPI 00946 GreGetObjectOwner(HGDIOBJ hobj) 00947 { 00948 ULONG ulIndex, ulOwner; 00949 00950 /* Get the handle index */ 00951 ulIndex = GDI_HANDLE_GET_INDEX(hobj); 00952 00953 /* Check if the handle is valid */ 00954 if (ulIndex >= GDI_HANDLE_COUNT || 00955 gpentHmgr[ulIndex].Objt == GDIObjType_DEF_TYPE || 00956 ((ULONG_PTR)hobj >> 16) != gpentHmgr[ulIndex].FullUnique) 00957 { 00958 DPRINT1("GreGetObjectOwner: invalid handle 0x%p.\n", hobj); 00959 return GDI_OBJ_HMGR_RESTRICTED; 00960 } 00961 00962 /* Get the object owner */ 00963 ulOwner = gpentHmgr[ulIndex].ObjectOwner.ulObj; 00964 00965 if (ulOwner == HandleToUlong(PsGetCurrentProcessId())) 00966 return GDI_OBJ_HMGR_POWNED; 00967 00968 if (ulOwner == GDI_OBJ_HMGR_PUBLIC) 00969 return GDI_OBJ_HMGR_PUBLIC; 00970 00971 return GDI_OBJ_HMGR_RESTRICTED; 00972 } 00973 00974 BOOL 00975 NTAPI 00976 GreSetObjectOwner( 00977 HGDIOBJ hobj, 00978 ULONG ulOwner) 00979 { 00980 PENTRY pentry; 00981 00982 /* Check for stock objects */ 00983 if (GDI_HANDLE_IS_STOCKOBJ(hobj)) 00984 { 00985 DPRINT("GreSetObjectOwner: Got stock object %p\n", hobj); 00986 return FALSE; 00987 } 00988 00989 /* Reference the handle entry */ 00990 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0); 00991 if (!pentry) 00992 { 00993 DPRINT("GreSetObjectOwner: Invalid handle 0x%p.\n", hobj); 00994 return FALSE; 00995 } 00996 00997 /* Call internal function */ 00998 GDIOBJ_vSetObjectOwner(pentry->einfo.pobj, ulOwner); 00999 01000 /* Dereference the object */ 01001 GDIOBJ_vDereferenceObject(pentry->einfo.pobj); 01002 01003 return TRUE; 01004 } 01005 01006 INT 01007 NTAPI 01008 GreGetObject( 01009 IN HGDIOBJ hobj, 01010 IN INT cbCount, 01011 IN PVOID pvBuffer) 01012 { 01013 PVOID pvObj; 01014 UCHAR objt; 01015 INT iResult = 0; 01016 01017 /* Verify object type */ 01018 objt = ((ULONG_PTR)hobj >> 16) & 0x1f; 01019 if (objt != GDIObjType_BRUSH_TYPE && 01020 objt != GDIObjType_SURF_TYPE && 01021 objt != GDIObjType_LFONT_TYPE && 01022 objt != GDIObjType_PAL_TYPE) 01023 { 01024 DPRINT1("GreGetObject: Invalid object type\n"); 01025 return 0; 01026 } 01027 01028 pvObj = GDIOBJ_ReferenceObjectByHandle(hobj, objt); 01029 if (!pvObj) 01030 { 01031 DPRINT("GreGetObject: Could not lock object\n"); 01032 return 0; 01033 } 01034 01035 switch (GDI_HANDLE_GET_TYPE(hobj)) 01036 { 01037 case GDILoObjType_LO_PEN_TYPE: 01038 case GDILoObjType_LO_EXTPEN_TYPE: 01039 iResult = PEN_GetObject(pvObj, cbCount, pvBuffer); 01040 break; 01041 01042 case GDILoObjType_LO_BRUSH_TYPE: 01043 iResult = BRUSH_GetObject(pvObj, cbCount, pvBuffer); 01044 break; 01045 01046 case GDILoObjType_LO_BITMAP_TYPE: 01047 iResult = BITMAP_GetObject(pvObj, cbCount, pvBuffer); 01048 break; 01049 01050 case GDILoObjType_LO_FONT_TYPE: 01051 iResult = FontGetObject(pvObj, cbCount, pvBuffer); 01052 break; 01053 01054 case GDILoObjType_LO_PALETTE_TYPE: 01055 iResult = PALETTE_GetObject(pvObj, cbCount, pvBuffer); 01056 break; 01057 01058 default: 01059 DPRINT1("GDI object type of 0x%p not implemented\n", hobj); 01060 break; 01061 } 01062 01063 GDIOBJ_vDereferenceObject(pvObj); 01064 return iResult; 01065 } 01066 01067 W32KAPI 01068 INT 01069 APIENTRY 01070 NtGdiExtGetObjectW( 01071 IN HANDLE hobj, 01072 IN INT cbCount, 01073 OUT LPVOID lpBuffer) 01074 { 01075 INT iRetCount = 0; 01076 INT cbCopyCount; 01077 union 01078 { 01079 BITMAP bitmap; 01080 DIBSECTION dibsection; 01081 LOGPEN logpen; 01082 LOGBRUSH logbrush; 01083 LOGFONTW logfontw; 01084 EXTLOGFONTW extlogfontw; 01085 ENUMLOGFONTEXDVW enumlogfontexdvw; 01086 } object; 01087 01088 /* Normalize to the largest supported object size */ 01089 cbCount = min((UINT)cbCount, sizeof(object)); 01090 01091 /* Now do the actual call */ 01092 iRetCount = GreGetObject(hobj, cbCount, lpBuffer ? &object : NULL); 01093 cbCopyCount = min((UINT)cbCount, (UINT)iRetCount); 01094 01095 /* Make sure we have a buffer and a copy size */ 01096 if ((cbCopyCount) && (lpBuffer)) 01097 { 01098 /* Enter SEH for buffer transfer */ 01099 _SEH2_TRY 01100 { 01101 /* Probe the buffer and copy it */ 01102 ProbeForWrite(lpBuffer, cbCopyCount, sizeof(WORD)); 01103 RtlCopyMemory(lpBuffer, &object, cbCopyCount); 01104 } 01105 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01106 { 01107 /* Clear the return value. 01108 * Do *NOT* set last error here! */ 01109 iRetCount = 0; 01110 } 01111 _SEH2_END; 01112 } 01113 01114 /* Return the count */ 01115 return iRetCount; 01116 } 01117 01118 W32KAPI 01119 HANDLE 01120 APIENTRY 01121 NtGdiCreateClientObj( 01122 IN ULONG ulType) 01123 { 01124 POBJ pObject; 01125 HANDLE handle; 01126 01127 /* Allocate a new object */ 01128 pObject = GDIOBJ_AllocateObject(GDIObjType_CLIENTOBJ_TYPE, 01129 sizeof(CLIENTOBJ), 01130 BASEFLAG_LOOKASIDE); 01131 if (!pObject) 01132 { 01133 DPRINT1("NtGdiCreateClientObj: Could not allocate a clientobj.\n"); 01134 return NULL; 01135 } 01136 01137 /* Mask out everything that would change the type in a wrong manner */ 01138 ulType &= (GDI_HANDLE_TYPE_MASK & ~GDI_HANDLE_BASETYPE_MASK); 01139 01140 /* Set the real object type */ 01141 pObject->hHmgr = UlongToHandle(ulType | GDILoObjType_LO_CLIENTOBJ_TYPE); 01142 01143 /* Create a handle */ 01144 handle = GDIOBJ_hInsertObject(pObject, GDI_OBJ_HMGR_POWNED); 01145 if (!handle) 01146 { 01147 DPRINT1("NtGdiCreateClientObj: Could not create a handle.\n"); 01148 GDIOBJ_vFreeObject(pObject); 01149 return NULL; 01150 } 01151 01152 /* Unlock it */ 01153 GDIOBJ_vUnlockObject(pObject); 01154 01155 return handle; 01156 } 01157 01158 W32KAPI 01159 BOOL 01160 APIENTRY 01161 NtGdiDeleteClientObj( 01162 IN HANDLE hobj) 01163 { 01164 /* We first need to get the real type from the handle */ 01165 ULONG ulType = GDI_HANDLE_GET_TYPE(hobj); 01166 01167 /* Check if it's really a CLIENTOBJ */ 01168 if ((ulType & GDI_HANDLE_BASETYPE_MASK) != GDILoObjType_LO_CLIENTOBJ_TYPE) 01169 { 01170 /* FIXME: SetLastError? */ 01171 return FALSE; 01172 } 01173 01174 return GreDeleteObject(hobj); 01175 } 01176 01177 01178 01179 PGDI_HANDLE_TABLE GdiHandleTable = NULL; 01180 01181 PGDIOBJ NTAPI 01182 GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType) 01183 { 01184 if (ExpectedType == GDI_OBJECT_TYPE_DONTCARE) 01185 ExpectedType = GDI_HANDLE_GET_TYPE(hObj); 01186 return GDIOBJ_ReferenceObjectByHandle(hObj, (ExpectedType >> 16) & 0x1f); 01187 } 01188 01189 // This function is not safe to use with concurrent deleting attempts 01190 // That shouldn't be a problem, since we don't have any processes yet, 01191 // that could delete the handle 01192 BOOL 01193 NTAPI 01194 GDIOBJ_ConvertToStockObj(HGDIOBJ *phObj) 01195 { 01196 PENTRY pentry; 01197 POBJ pobj; 01198 01199 /* Reference the handle entry */ 01200 pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0); 01201 if (!pentry) 01202 { 01203 DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj); 01204 return FALSE; 01205 } 01206 01207 /* Update the entry */ 01208 pentry->FullUnique |= GDI_ENTRY_STOCK_MASK; 01209 pentry->ObjectOwner.ulObj = 0; 01210 01211 /* Get the pointer to the BASEOBJECT */ 01212 pobj = pentry->einfo.pobj; 01213 01214 /* Calculate the new handle */ 01215 pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)pobj->hHmgr | GDI_HANDLE_STOCK_MASK); 01216 01217 /* Return the new handle */ 01218 *phObj = pobj->hHmgr; 01219 01220 /* Dereference the handle */ 01221 GDIOBJ_vDereferenceObject(pobj); 01222 01223 return TRUE; 01224 } 01225 01226 POBJ NTAPI 01227 GDIOBJ_AllocObjWithHandle(ULONG ObjectType, ULONG cjSize) 01228 { 01229 POBJ pobj; 01230 FLONG fl = 0; 01231 UCHAR objt = (ObjectType >> 16) & 0xFF; 01232 01233 if ((objt == GDIObjType_DC_TYPE && cjSize == sizeof(DC)) || 01234 (objt == GDIObjType_PAL_TYPE && cjSize == sizeof(PALETTE)) || 01235 (objt == GDIObjType_RGN_TYPE && cjSize == sizeof(REGION)) || 01236 (objt == GDIObjType_SURF_TYPE && cjSize == sizeof(SURFACE)) || 01237 (objt == GDIObjType_PATH_TYPE && cjSize == sizeof(PATH))) 01238 { 01239 fl |= BASEFLAG_LOOKASIDE; 01240 } 01241 01242 pobj = GDIOBJ_AllocateObject(objt, cjSize, fl); 01243 if (!GDIOBJ_hInsertObject(pobj, GDI_OBJ_HMGR_POWNED)) 01244 { 01245 GDIOBJ_vFreeObject(pobj); 01246 return NULL; 01247 } 01248 return pobj; 01249 } 01250 01251 PVOID NTAPI 01252 GDI_MapHandleTable(PEPROCESS pProcess) 01253 { 01254 PVOID pvMappedView = NULL; 01255 NTSTATUS Status; 01256 LARGE_INTEGER liOffset; 01257 ULONG cjViewSize = sizeof(GDI_HANDLE_TABLE); 01258 01259 liOffset.QuadPart = 0; 01260 01261 ASSERT(gpvGdiHdlTblSection != NULL); 01262 ASSERT(pProcess != NULL); 01263 01264 Status = MmMapViewOfSection(gpvGdiHdlTblSection, 01265 pProcess, 01266 &pvMappedView, 01267 0, 01268 0, 01269 &liOffset, 01270 &cjViewSize, 01271 ViewUnmap, 01272 SEC_NO_CHANGE, 01273 PAGE_READONLY); 01274 01275 if (!NT_SUCCESS(Status)) 01276 return NULL; 01277 01278 return pvMappedView; 01279 } 01280 01281 BOOL NTAPI 01282 GDI_CleanupForProcess(struct _EPROCESS *Process) 01283 { 01284 PENTRY pentry; 01285 ULONG ulIndex; 01286 DWORD dwProcessId; 01287 PPROCESSINFO ppi; 01288 01289 DPRINT("CleanupForProcess prochandle %x Pid %d\n", 01290 Process, Process->UniqueProcessId); 01291 01292 ASSERT(Process == PsGetCurrentProcess()); 01293 01294 /* Get the current process Id */ 01295 dwProcessId = PtrToUlong(PsGetCurrentProcessId()); 01296 01297 /* Loop all handles in the handle table */ 01298 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++) 01299 { 01300 pentry = &gpentHmgr[ulIndex]; 01301 01302 /* Check if the object is owned by the process */ 01303 if (pentry->ObjectOwner.ulObj == dwProcessId) 01304 { 01305 ASSERT(pentry->einfo.pobj->cExclusiveLock == 0); 01306 01307 /* Reference the object and delete it */ 01308 InterlockedIncrement((LONG*)&gpaulRefCount[ulIndex]); 01309 GDIOBJ_vDeleteObject(pentry->einfo.pobj); 01310 } 01311 } 01312 01313 #if DBG 01314 //#ifdef GDI_DEBUG 01315 DbgGdiHTIntegrityCheck(); 01316 //#endif 01317 #endif 01318 01319 ppi = PsGetCurrentProcessWin32Process(); 01320 DPRINT("Completed cleanup for process %d\n", Process->UniqueProcessId); 01321 if (ppi->GDIHandleCount != 0) 01322 { 01323 DPRINT1("Leaking %d handles!\n", ppi->GDIHandleCount); 01324 ASSERT(FALSE); 01325 } 01326 01327 /* Loop all handles in the handle table */ 01328 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++) 01329 { 01330 pentry = &gpentHmgr[ulIndex]; 01331 01332 /* Check if the object is owned by the process */ 01333 if (pentry->ObjectOwner.ulObj == dwProcessId) 01334 { 01335 DPRINT1("Leaking object. Index=%lx, type=0x%x, refcount=%lx\n", 01336 ulIndex, pentry->Objt, gpaulRefCount[ulIndex]); 01337 DBG_DUMP_EVENT_LIST(&pentry->einfo.pobj->slhLog); 01338 //DBG_CLEANUP_EVENT_LIST(&pentry->einfo.pobj->slhLog); 01339 ASSERT(FALSE); 01340 } 01341 } 01342 01343 return TRUE; 01344 } 01345 01346 /* EOF */ Generated on Fri May 25 2012 04:36:38 for ReactOS by
1.7.6.1
|