[Win32SS]
[reactos.git] / reactos / win32ss / user / ntuser / object.c
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 = (((unsigned int)handle & 0xffff) - 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 = (unsigned int)handle >> 16;
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)(((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 ((unsigned int)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 }