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