1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: User handle manager 5 * FILE: win32ss/user/ntuser/object.c 6 * PROGRAMER: Copyright (C) 2001 Alexandre Julliard 7 */ 8 9 #include <win32k.h> 10 DBG_DEFAULT_CHANNEL(UserObj); 11 12 //int usedHandles=0; 13 PUSER_HANDLE_TABLE gHandleTable = NULL; 14 15 /* Forward declarations */ 16 _Success_(return!=NULL) 17 static PVOID AllocThreadObject( 18 _In_ PDESKTOP pDesk, 19 _In_ PTHREADINFO pti, 20 _In_ SIZE_T Size, 21 _Out_ PVOID* HandleOwner) 22 { 23 PTHROBJHEAD ObjHead; 24 25 UNREFERENCED_PARAMETER(pDesk); 26 27 ASSERT(Size > sizeof(*ObjHead)); 28 ASSERT(pti != NULL); 29 30 ObjHead = UserHeapAlloc(Size); 31 if (!ObjHead) 32 return NULL; 33 34 RtlZeroMemory(ObjHead, Size); 35 36 ObjHead->pti = pti; 37 IntReferenceThreadInfo(pti); 38 *HandleOwner = pti; 39 /* It's a thread object, but it still count as one for the process */ 40 pti->ppi->UserHandleCount++; 41 42 return ObjHead; 43 } 44 45 static void FreeThreadObject( 46 _In_ PVOID Object) 47 { 48 PTHROBJHEAD ObjHead = (PTHROBJHEAD)Object; 49 PTHREADINFO pti = ObjHead->pti; 50 51 UserHeapFree(ObjHead); 52 53 pti->ppi->UserHandleCount--; 54 IntDereferenceThreadInfo(pti); 55 } 56 57 _Success_(return!=NULL) 58 static PVOID AllocDeskThreadObject( 59 _In_ PDESKTOP pDesk, 60 _In_ PTHREADINFO pti, 61 _In_ SIZE_T Size, 62 _Out_ PVOID* HandleOwner) 63 { 64 PTHRDESKHEAD ObjHead; 65 66 ASSERT(Size > sizeof(*ObjHead)); 67 ASSERT(pti != NULL); 68 69 if (!pDesk) 70 pDesk = pti->rpdesk; 71 72 ObjHead = DesktopHeapAlloc(pDesk, Size); 73 if (!ObjHead) 74 return NULL; 75 76 RtlZeroMemory(ObjHead, Size); 77 78 ObjHead->pSelf = ObjHead; 79 ObjHead->rpdesk = pDesk; 80 ObjHead->pti = pti; 81 IntReferenceThreadInfo(pti); 82 *HandleOwner = pti; 83 /* It's a thread object, but it still count as one for the process */ 84 pti->ppi->UserHandleCount++; 85 86 return ObjHead; 87 } 88 89 static void FreeDeskThreadObject( 90 _In_ PVOID Object) 91 { 92 PTHRDESKHEAD ObjHead = (PTHRDESKHEAD)Object; 93 PDESKTOP pDesk = ObjHead->rpdesk; 94 PTHREADINFO pti = ObjHead->pti; 95 96 DesktopHeapFree(pDesk, Object); 97 98 pti->ppi->UserHandleCount--; 99 IntDereferenceThreadInfo(pti); 100 } 101 102 _Success_(return!=NULL) 103 static PVOID AllocDeskProcObject( 104 _In_ PDESKTOP pDesk, 105 _In_ PTHREADINFO pti, 106 _In_ SIZE_T Size, 107 _Out_ PVOID* HandleOwner) 108 { 109 PPROCDESKHEAD ObjHead; 110 PPROCESSINFO ppi; 111 112 ASSERT(Size > sizeof(*ObjHead)); 113 ASSERT(pDesk != NULL); 114 ASSERT(pti != NULL); 115 116 ObjHead = DesktopHeapAlloc(pDesk, Size); 117 if (!ObjHead) 118 return NULL; 119 120 RtlZeroMemory(ObjHead, Size); 121 122 ppi = pti->ppi; 123 124 ObjHead->pSelf = ObjHead; 125 ObjHead->rpdesk = pDesk; 126 ObjHead->hTaskWow = (DWORD_PTR)ppi; 127 ppi->UserHandleCount++; 128 IntReferenceProcessInfo(ppi); 129 *HandleOwner = ppi; 130 131 return ObjHead; 132 } 133 134 static void FreeDeskProcObject( 135 _In_ PVOID Object) 136 { 137 PPROCDESKHEAD ObjHead = (PPROCDESKHEAD)Object; 138 PDESKTOP pDesk = ObjHead->rpdesk; 139 PPROCESSINFO ppi = (PPROCESSINFO)ObjHead->hTaskWow; 140 141 ppi->UserHandleCount--; 142 IntDereferenceProcessInfo(ppi); 143 144 DesktopHeapFree(pDesk, Object); 145 } 146 147 _Success_(return!=NULL) 148 static PVOID AllocProcMarkObject( 149 _In_ PDESKTOP pDesk, 150 _In_ PTHREADINFO pti, 151 _In_ SIZE_T Size, 152 _Out_ PVOID* HandleOwner) 153 { 154 PPROCMARKHEAD ObjHead; 155 PPROCESSINFO ppi = pti->ppi; 156 157 UNREFERENCED_PARAMETER(pDesk); 158 159 ASSERT(Size > sizeof(*ObjHead)); 160 161 ObjHead = UserHeapAlloc(Size); 162 if (!ObjHead) 163 return NULL; 164 165 RtlZeroMemory(ObjHead, Size); 166 167 ObjHead->ppi = ppi; 168 IntReferenceProcessInfo(ppi); 169 *HandleOwner = ppi; 170 ppi->UserHandleCount++; 171 172 return ObjHead; 173 } 174 175 void FreeProcMarkObject( 176 _In_ PVOID Object) 177 { 178 PPROCESSINFO ppi = ((PPROCMARKHEAD)Object)->ppi; 179 180 UserHeapFree(Object); 181 182 ppi->UserHandleCount--; 183 IntDereferenceProcessInfo(ppi); 184 } 185 186 _Success_(return!=NULL) 187 static PVOID AllocSysObject( 188 _In_ PDESKTOP pDesk, 189 _In_ PTHREADINFO pti, 190 _In_ SIZE_T Size, 191 _Out_ PVOID* ObjectOwner) 192 { 193 PVOID Object; 194 195 UNREFERENCED_PARAMETER(pDesk); 196 UNREFERENCED_PARAMETER(pti); 197 198 ASSERT(Size > sizeof(HEAD)); 199 200 Object = UserHeapAlloc(Size); 201 if (!Object) 202 return NULL; 203 204 *ObjectOwner = NULL; 205 206 RtlZeroMemory(Object, Size); 207 return Object; 208 } 209 210 static void FreeSysObject( 211 _In_ PVOID Object) 212 { 213 UserHeapFree(Object); 214 } 215 216 static const struct 217 { 218 PVOID (*ObjectAlloc)(PDESKTOP, PTHREADINFO, SIZE_T, PVOID*); 219 BOOLEAN (*ObjectDestroy)(PVOID); 220 void (*ObjectFree)(PVOID); 221 } ObjectCallbacks[TYPE_CTYPES] = 222 { 223 { NULL, NULL, NULL }, /* TYPE_FREE */ 224 { AllocDeskThreadObject, co_UserDestroyWindow, FreeDeskThreadObject }, /* TYPE_WINDOW */ 225 { AllocDeskProcObject, UserDestroyMenuObject, FreeDeskProcObject }, /* TYPE_MENU */ 226 { AllocProcMarkObject, IntDestroyCurIconObject, FreeCurIconObject }, /* TYPE_CURSOR */ 227 { AllocSysObject, /*UserSetWindowPosCleanup*/NULL, FreeSysObject }, /* TYPE_SETWINDOWPOS */ 228 { AllocDeskThreadObject, IntRemoveHook, FreeDeskThreadObject }, /* TYPE_HOOK */ 229 { AllocSysObject, /*UserClipDataCleanup*/NULL,FreeSysObject }, /* TYPE_CLIPDATA */ 230 { AllocDeskProcObject, DestroyCallProc, FreeDeskProcObject }, /* TYPE_CALLPROC */ 231 { AllocProcMarkObject, UserDestroyAccelTable, FreeProcMarkObject }, /* TYPE_ACCELTABLE */ 232 { NULL, NULL, NULL }, /* TYPE_DDEACCESS */ 233 { NULL, NULL, NULL }, /* TYPE_DDECONV */ 234 { NULL, NULL, NULL }, /* TYPE_DDEXACT */ 235 { AllocSysObject, /*UserMonitorCleanup*/NULL, FreeSysObject }, /* TYPE_MONITOR */ 236 { AllocSysObject, /*UserKbdLayoutCleanup*/NULL,FreeSysObject }, /* TYPE_KBDLAYOUT */ 237 { AllocSysObject, /*UserKbdFileCleanup*/NULL, FreeSysObject }, /* TYPE_KBDFILE */ 238 { AllocThreadObject, IntRemoveEvent, FreeThreadObject }, /* TYPE_WINEVENTHOOK */ 239 { AllocSysObject, /*UserTimerCleanup*/NULL, FreeSysObject }, /* TYPE_TIMER */ 240 { NULL, NULL, NULL }, /* TYPE_INPUTCONTEXT */ 241 { NULL, NULL, NULL }, /* TYPE_HIDDATA */ 242 { NULL, NULL, NULL }, /* TYPE_DEVICEINFO */ 243 { NULL, NULL, NULL }, /* TYPE_TOUCHINPUTINFO */ 244 { NULL, NULL, NULL }, /* TYPE_GESTUREINFOOBJ */ 245 }; 246 247 #if DBG 248 249 void DbgUserDumpHandleTable(VOID) 250 { 251 int HandleCounts[TYPE_CTYPES]; 252 PPROCESSINFO ppiList; 253 int i; 254 PWCHAR TypeNames[] = {L"Free",L"Window",L"Menu", L"CursorIcon", L"SMWP", L"Hook", L"ClipBoardData", L"CallProc", 255 L"Accel", L"DDEaccess", L"DDEconv", L"DDExact", L"Monitor", L"KBDlayout", L"KBDfile", 256 L"Event", L"Timer", L"InputContext", L"HidData", L"DeviceInfo", L"TouchInput",L"GestureInfo"}; 257 258 ERR("Total handles count: %lu\n", gpsi->cHandleEntries); 259 260 memset(HandleCounts, 0, sizeof(HandleCounts)); 261 262 /* First of all count the number of handles per type */ 263 ppiList = gppiList; 264 while (ppiList) 265 { 266 ERR("Process %s (%p) handles count: %d\n\t", ppiList->peProcess->ImageFileName, ppiList->peProcess->UniqueProcessId, ppiList->UserHandleCount); 267 268 for (i = 1 ;i < TYPE_CTYPES; i++) 269 { 270 HandleCounts[i] += ppiList->DbgHandleCount[i]; 271 272 DbgPrint("%S: %lu, ", TypeNames[i], ppiList->DbgHandleCount[i]); 273 if (i % 6 == 0) 274 DbgPrint("\n\t"); 275 } 276 DbgPrint("\n"); 277 278 ppiList = ppiList->ppiNext; 279 } 280 281 /* Print total type counts */ 282 ERR("Total handles of the running processes: \n\t"); 283 for (i = 1 ;i < TYPE_CTYPES; i++) 284 { 285 DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]); 286 if (i % 6 == 0) 287 DbgPrint("\n\t"); 288 } 289 DbgPrint("\n"); 290 291 /* Now count the handle counts that are allocated from the handle table */ 292 memset(HandleCounts, 0, sizeof(HandleCounts)); 293 for (i = 0; i < gHandleTable->nb_handles; i++) 294 HandleCounts[gHandleTable->handles[i].type]++; 295 296 ERR("Total handles count allocated: \n\t"); 297 for (i = 1 ;i < TYPE_CTYPES; i++) 298 { 299 DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]); 300 if (i % 6 == 0) 301 DbgPrint("\n\t"); 302 } 303 DbgPrint("\n"); 304 } 305 306 #endif 307 308 PUSER_HANDLE_ENTRY handle_to_entry(PUSER_HANDLE_TABLE ht, HANDLE handle ) 309 { 310 unsigned short generation; 311 int index = (LOWORD(handle) - FIRST_USER_HANDLE) >> 1; 312 if (index < 0 || index >= ht->nb_handles) 313 return NULL; 314 if (!ht->handles[index].type) 315 return NULL; 316 generation = HIWORD(handle); 317 if (generation == ht->handles[index].generation || !generation || generation == 0xffff) 318 return &ht->handles[index]; 319 return NULL; 320 } 321 322 __inline static HANDLE entry_to_handle(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY ptr ) 323 { 324 int index = ptr - ht->handles; 325 return (HANDLE)((((INT_PTR)index << 1) + FIRST_USER_HANDLE) + (ptr->generation << 16)); 326 } 327 328 __inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht) 329 { 330 PUSER_HANDLE_ENTRY entry; 331 TRACE("handles used %lu\n", gpsi->cHandleEntries); 332 333 if (ht->freelist) 334 { 335 entry = ht->freelist; 336 ht->freelist = entry->ptr; 337 338 gpsi->cHandleEntries++; 339 return entry; 340 } 341 342 if (ht->nb_handles >= ht->allocated_handles) /* Need to grow the array */ 343 { 344 ERR("Out of user handles! Used -> %lu, NM_Handle -> %d\n", gpsi->cHandleEntries, ht->nb_handles); 345 346 #if DBG 347 DbgUserDumpHandleTable(); 348 #endif 349 350 return NULL; 351 #if 0 352 PUSER_HANDLE_ENTRY new_handles; 353 /* Grow array by 50% (but at minimum 32 entries) */ 354 int growth = max( 32, ht->allocated_handles / 2 ); 355 int new_size = min( ht->allocated_handles + growth, (LAST_USER_HANDLE-FIRST_USER_HANDLE+1) >> 1 ); 356 if (new_size <= ht->allocated_handles) 357 return NULL; 358 if (!(new_handles = UserHeapReAlloc( ht->handles, new_size * sizeof(*ht->handles) ))) 359 return NULL; 360 ht->handles = new_handles; 361 ht->allocated_handles = new_size; 362 #endif 363 } 364 365 entry = &ht->handles[ht->nb_handles++]; 366 367 entry->generation = 1; 368 369 gpsi->cHandleEntries++; 370 371 return entry; 372 } 373 374 VOID UserInitHandleTable(PUSER_HANDLE_TABLE ht, PVOID mem, ULONG bytes) 375 { 376 ht->freelist = NULL; 377 ht->handles = mem; 378 379 ht->nb_handles = 0; 380 ht->allocated_handles = bytes / sizeof(USER_HANDLE_ENTRY); 381 } 382 383 384 __inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY entry) 385 { 386 void *ret; 387 388 #if DBG 389 { 390 PPROCESSINFO ppi; 391 switch (entry->type) 392 { 393 case TYPE_WINDOW: 394 case TYPE_HOOK: 395 case TYPE_WINEVENTHOOK: 396 ppi = ((PTHREADINFO)entry->pi)->ppi; 397 break; 398 case TYPE_MENU: 399 case TYPE_CURSOR: 400 case TYPE_CALLPROC: 401 case TYPE_ACCELTABLE: 402 ppi = entry->pi; 403 break; 404 default: 405 ppi = NULL; 406 } 407 if (ppi) 408 ppi->DbgHandleCount[entry->type]--; 409 } 410 #endif 411 412 ret = entry->ptr; 413 entry->ptr = ht->freelist; 414 entry->type = 0; 415 entry->flags = 0; 416 entry->pi = NULL; 417 ht->freelist = entry; 418 419 gpsi->cHandleEntries--; 420 421 return ret; 422 } 423 424 /* allocate a user handle for a given object */ 425 HANDLE UserAllocHandle( 426 _Inout_ PUSER_HANDLE_TABLE ht, 427 _In_ PVOID object, 428 _In_ HANDLE_TYPE type, 429 _In_ PVOID HandleOwner) 430 { 431 PUSER_HANDLE_ENTRY entry = alloc_user_entry(ht); 432 if (!entry) 433 return 0; 434 entry->ptr = object; 435 entry->type = type; 436 entry->flags = 0; 437 entry->pi = HandleOwner; 438 if (++entry->generation >= 0xffff) 439 entry->generation = 1; 440 441 /* We have created a handle, which is a reference! */ 442 UserReferenceObject(object); 443 444 return entry_to_handle(ht, entry ); 445 } 446 447 /* return a pointer to a user object from its handle without setting an error */ 448 PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type ) 449 { 450 PUSER_HANDLE_ENTRY entry; 451 452 ASSERT(ht); 453 454 if (!(entry = handle_to_entry(ht, handle )) || entry->type != type) 455 { 456 return NULL; 457 } 458 return entry->ptr; 459 } 460 461 /* return a pointer to a user object from its handle */ 462 PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type ) 463 { 464 PUSER_HANDLE_ENTRY entry; 465 466 ASSERT(ht); 467 468 if (!(entry = handle_to_entry(ht, handle )) || entry->type != type) 469 { 470 EngSetLastError(ERROR_INVALID_HANDLE); 471 return NULL; 472 } 473 return entry->ptr; 474 } 475 476 477 /* Get the full handle (32bit) for a possibly truncated (16bit) handle */ 478 HANDLE get_user_full_handle(PUSER_HANDLE_TABLE ht, HANDLE handle ) 479 { 480 PUSER_HANDLE_ENTRY entry; 481 482 if ((ULONG_PTR)handle >> 16) 483 return handle; 484 if (!(entry = handle_to_entry(ht, handle ))) 485 return handle; 486 return entry_to_handle( ht, entry ); 487 } 488 489 490 /* Same as get_user_object plus set the handle to the full 32-bit value */ 491 void *get_user_object_handle(PUSER_HANDLE_TABLE ht, HANDLE* handle, HANDLE_TYPE type ) 492 { 493 PUSER_HANDLE_ENTRY entry; 494 495 if (!(entry = handle_to_entry(ht, *handle )) || entry->type != type) 496 return NULL; 497 *handle = entry_to_handle( ht, entry ); 498 return entry->ptr; 499 } 500 501 502 503 BOOL FASTCALL UserCreateHandleTable(VOID) 504 { 505 PVOID mem; 506 INT HandleCount = 1024 * 4; 507 508 // FIXME: Don't alloc all at once! Must be mapped into umode also... 509 mem = UserHeapAlloc(sizeof(USER_HANDLE_ENTRY) * HandleCount); 510 if (!mem) 511 { 512 ERR("Failed creating handle table\n"); 513 return FALSE; 514 } 515 516 gHandleTable = UserHeapAlloc(sizeof(USER_HANDLE_TABLE)); 517 if (gHandleTable == NULL) 518 { 519 UserHeapFree(mem); 520 ERR("Failed creating handle table\n"); 521 return FALSE; 522 } 523 524 // FIXME: Make auto growable 525 UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * HandleCount); 526 527 return TRUE; 528 } 529 530 // 531 // New 532 // 533 PVOID 534 FASTCALL 535 UserCreateObject( PUSER_HANDLE_TABLE ht, 536 PDESKTOP pDesktop, 537 PTHREADINFO pti, 538 HANDLE* h, 539 HANDLE_TYPE type, 540 ULONG size) 541 { 542 HANDLE hi; 543 PVOID Object; 544 PVOID ObjectOwner; 545 546 /* Some sanity checks. Other checks will be made in the allocator */ 547 ASSERT(type < TYPE_CTYPES); 548 ASSERT(type != TYPE_FREE); 549 ASSERT(ht != NULL); 550 551 /* Allocate the object */ 552 ASSERT(ObjectCallbacks[type].ObjectAlloc != NULL); 553 Object = ObjectCallbacks[type].ObjectAlloc(pDesktop, pti, size, &ObjectOwner); 554 if (!Object) 555 { 556 ERR("User object allocation failed. Out of memory!\n"); 557 return NULL; 558 } 559 560 hi = UserAllocHandle(ht, Object, type, ObjectOwner); 561 if (hi == NULL) 562 { 563 ERR("Out of user handles!\n"); 564 ObjectCallbacks[type].ObjectFree(Object); 565 return NULL; 566 } 567 568 #if DBG 569 if (pti) 570 pti->ppi->DbgHandleCount[type]++; 571 #endif 572 573 /* Give this object its identity. */ 574 ((PHEAD)Object)->h = hi; 575 576 /* The caller will get a locked object. 577 * Note: with the reference from the handle, that makes two */ 578 UserReferenceObject(Object); 579 580 if (h) 581 *h = hi; 582 return Object; 583 } 584 585 BOOL 586 FASTCALL 587 UserMarkObjectDestroy(PVOID Object) 588 { 589 PUSER_HANDLE_ENTRY entry; 590 PHEAD ObjHead = Object; 591 592 entry = handle_to_entry(gHandleTable, ObjHead->h); 593 594 ASSERT(entry != NULL); 595 596 entry->flags |= HANDLEENTRY_DESTROY; 597 598 if (ObjHead->cLockObj > 1) 599 { 600 entry->flags &= ~HANDLEENTRY_INDESTROY; 601 TRACE("Count %d\n",ObjHead->cLockObj); 602 return FALSE; 603 } 604 605 return TRUE; 606 } 607 608 BOOL 609 FASTCALL 610 UserDereferenceObject(PVOID Object) 611 { 612 PHEAD ObjHead = Object; 613 614 ASSERT(ObjHead->cLockObj >= 1); 615 ASSERT(ObjHead->cLockObj < 0x10000); 616 617 if (--ObjHead->cLockObj == 0) 618 { 619 PUSER_HANDLE_ENTRY entry; 620 HANDLE_TYPE type; 621 622 entry = handle_to_entry(gHandleTable, ObjHead->h); 623 624 ASSERT(entry != NULL); 625 /* The entry should be marked as in deletion */ 626 ASSERT(entry->flags & HANDLEENTRY_INDESTROY); 627 628 type = entry->type; 629 ASSERT(type != TYPE_FREE); 630 ASSERT(type < TYPE_CTYPES); 631 632 /* We can now get rid of everything */ 633 free_user_entry(gHandleTable, entry ); 634 635 #if 0 636 /* Call the object destructor */ 637 ASSERT(ObjectCallbacks[type].ObjectCleanup != NULL); 638 ObjectCallbacks[type].ObjectCleanup(Object); 639 #endif 640 641 /* And free it */ 642 ASSERT(ObjectCallbacks[type].ObjectFree != NULL); 643 ObjectCallbacks[type].ObjectFree(Object); 644 645 return TRUE; 646 } 647 return FALSE; 648 } 649 650 BOOL 651 FASTCALL 652 UserFreeHandle(PUSER_HANDLE_TABLE ht, HANDLE handle ) 653 { 654 PUSER_HANDLE_ENTRY entry; 655 656 if (!(entry = handle_to_entry( ht, handle ))) 657 { 658 SetLastNtError( STATUS_INVALID_HANDLE ); 659 return FALSE; 660 } 661 662 entry->flags = HANDLEENTRY_INDESTROY; 663 664 return UserDereferenceObject(entry->ptr); 665 } 666 667 BOOL 668 FASTCALL 669 UserObjectInDestroy(HANDLE h) 670 { 671 PUSER_HANDLE_ENTRY entry; 672 673 if (!(entry = handle_to_entry( gHandleTable, h ))) 674 { 675 SetLastNtError( STATUS_INVALID_HANDLE ); 676 return TRUE; 677 } 678 return (entry->flags & HANDLEENTRY_INDESTROY); 679 } 680 681 BOOL 682 FASTCALL 683 UserDeleteObject(HANDLE h, HANDLE_TYPE type ) 684 { 685 PVOID body = UserGetObject(gHandleTable, h, type); 686 687 if (!body) return FALSE; 688 689 ASSERT( ((PHEAD)body)->cLockObj >= 1); 690 ASSERT( ((PHEAD)body)->cLockObj < 0x10000); 691 692 return UserFreeHandle(gHandleTable, h); 693 } 694 695 VOID 696 FASTCALL 697 UserReferenceObject(PVOID obj) 698 { 699 PHEAD ObjHead = obj; 700 ASSERT(ObjHead->cLockObj < 0x10000); 701 702 ObjHead->cLockObj++; 703 } 704 705 PVOID 706 FASTCALL 707 UserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type) 708 { 709 PVOID object; 710 711 object = UserGetObject(gHandleTable, handle, type); 712 if (object) 713 { 714 UserReferenceObject(object); 715 } 716 return object; 717 } 718 719 BOOLEAN 720 UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner) 721 { 722 int i; 723 PUSER_HANDLE_ENTRY Entry; 724 BOOLEAN Ret = TRUE; 725 726 /* Sweep the whole handle table */ 727 for (i = 0; i < Table->allocated_handles; i++) 728 { 729 Entry = &Table->handles[i]; 730 731 if (Entry->pi != Owner) 732 continue; 733 734 /* Do not destroy if it's already been done */ 735 if (Entry->flags & HANDLEENTRY_INDESTROY) 736 continue; 737 738 /* Call destructor */ 739 if (!ObjectCallbacks[Entry->type].ObjectDestroy(Entry->ptr)) 740 { 741 ERR("Failed destructing object %p, type %u.\n", Entry->ptr, Entry->type); 742 /* Don't return immediately, we must continue destroying the other objects */ 743 Ret = FALSE; 744 } 745 } 746 747 return Ret; 748 } 749 750 /* 751 * 752 * Status 753 * @implemented 754 */ 755 756 BOOL 757 APIENTRY 758 NtUserValidateHandleSecure( 759 HANDLE handle) 760 { 761 UINT uType; 762 PPROCESSINFO ppi; 763 PUSER_HANDLE_ENTRY entry; 764 765 DECLARE_RETURN(BOOL); 766 UserEnterExclusive(); 767 768 if (!(entry = handle_to_entry(gHandleTable, handle ))) 769 { 770 EngSetLastError(ERROR_INVALID_HANDLE); 771 RETURN( FALSE); 772 } 773 uType = entry->type; 774 switch (uType) 775 { 776 case TYPE_WINDOW: 777 case TYPE_INPUTCONTEXT: 778 ppi = ((PTHREADINFO)entry->pi)->ppi; 779 break; 780 case TYPE_MENU: 781 case TYPE_ACCELTABLE: 782 case TYPE_CURSOR: 783 case TYPE_HOOK: 784 case TYPE_CALLPROC: 785 case TYPE_SETWINDOWPOS: 786 ppi = entry->pi; 787 break; 788 default: 789 ppi = NULL; 790 break; 791 } 792 793 if (!ppi) RETURN( FALSE); 794 795 // Same process job returns TRUE. 796 if (gptiCurrent->ppi->pW32Job == ppi->pW32Job) RETURN( TRUE); 797 798 RETURN( FALSE); 799 800 CLEANUP: 801 UserLeave(); 802 END_CLEANUP; 803 } 804