//int usedHandles=0;
PUSER_HANDLE_TABLE gHandleTable = NULL;
+/* Forward declarations */
+static PVOID AllocThreadObject(
+ _In_ PDESKTOP pDesk,
+ _In_ PTHREADINFO pti,
+ _In_ SIZE_T Size,
+ _Out_ PVOID* HandleOwner)
+{
+ PTHROBJHEAD ObjHead;
+
+ UNREFERENCED_PARAMETER(pDesk);
+
+ ASSERT(Size > sizeof(*ObjHead));
+ ASSERT(pti != NULL);
+
+ ObjHead = UserHeapAlloc(Size);
+ if (!ObjHead)
+ return NULL;
+
+ RtlZeroMemory(ObjHead, Size);
+
+ ObjHead->pti = pti;
+ IntReferenceThreadInfo(pti);
+ *HandleOwner = pti;
+ /* It's a thread object, but it still count as one for the process */
+ pti->ppi->UserHandleCount++;
+
+ return ObjHead;
+}
+
+static void FreeThreadObject(
+ _In_ PVOID Object)
+{
+ PTHROBJHEAD ObjHead = (PTHROBJHEAD)Object;
+ PTHREADINFO pti = ObjHead->pti;
+
+ UserHeapFree(ObjHead);
+
+ pti->ppi->UserHandleCount--;
+ IntDereferenceThreadInfo(pti);
+}
+
+static PVOID AllocDeskThreadObject(
+ _In_ PDESKTOP pDesk,
+ _In_ PTHREADINFO pti,
+ _In_ SIZE_T Size,
+ _Out_ PVOID* HandleOwner)
+{
+ PTHRDESKHEAD ObjHead;
+
+ ASSERT(Size > sizeof(*ObjHead));
+ ASSERT(pti != NULL);
+
+ if (!pDesk)
+ pDesk = pti->rpdesk;
+
+ ObjHead = DesktopHeapAlloc(pDesk, Size);
+ if (!ObjHead)
+ return NULL;
+
+ RtlZeroMemory(ObjHead, Size);
+
+ ObjHead->pSelf = ObjHead;
+ ObjHead->rpdesk = pDesk;
+ ObjHead->pti = pti;
+ IntReferenceThreadInfo(pti);
+ *HandleOwner = pti;
+ /* It's a thread object, but it still count as one for the process */
+ pti->ppi->UserHandleCount++;
+
+ return ObjHead;
+}
+
+static void FreeDeskThreadObject(
+ _In_ PVOID Object)
+{
+ PTHRDESKHEAD ObjHead = (PTHRDESKHEAD)Object;
+ PDESKTOP pDesk = ObjHead->rpdesk;
+ PTHREADINFO pti = ObjHead->pti;
+
+ DesktopHeapFree(pDesk, Object);
+
+ pti->ppi->UserHandleCount--;
+ IntDereferenceThreadInfo(pti);
+}
+
+static PVOID AllocDeskProcObject(
+ _In_ PDESKTOP pDesk,
+ _In_ PTHREADINFO pti,
+ _In_ SIZE_T Size,
+ _Out_ PVOID* HandleOwner)
+{
+ PPROCDESKHEAD ObjHead;
+ PPROCESSINFO ppi;
+
+ ASSERT(Size > sizeof(*ObjHead));
+ ASSERT(pDesk != NULL);
+ ASSERT(pti != NULL);
+
+ ObjHead = DesktopHeapAlloc(pDesk, Size);
+ if (!ObjHead)
+ return NULL;
+
+ RtlZeroMemory(ObjHead, Size);
+
+ ppi = pti->ppi;
+
+ ObjHead->pSelf = ObjHead;
+ ObjHead->rpdesk = pDesk;
+ ObjHead->hTaskWow = (DWORD_PTR)ppi;
+ ppi->UserHandleCount++;
+ IntReferenceProcessInfo(ppi);
+ *HandleOwner = ppi;
+
+ return ObjHead;
+}
+
+static void FreeDeskProcObject(
+ _In_ PVOID Object)
+{
+ PPROCDESKHEAD ObjHead = (PPROCDESKHEAD)Object;
+ PDESKTOP pDesk = ObjHead->rpdesk;
+ PPROCESSINFO ppi = (PPROCESSINFO)ObjHead->hTaskWow;
+
+ ppi->UserHandleCount--;
+ IntDereferenceProcessInfo(ppi);
+
+ DesktopHeapFree(pDesk, Object);
+}
+
+static PVOID AllocProcMarkObject(
+ _In_ PDESKTOP pDesk,
+ _In_ PTHREADINFO pti,
+ _In_ SIZE_T Size,
+ _Out_ PVOID* HandleOwner)
+{
+ PPROCMARKHEAD ObjHead;
+ PPROCESSINFO ppi = pti->ppi;
+
+ UNREFERENCED_PARAMETER(pDesk);
+
+ ASSERT(Size > sizeof(*ObjHead));
+
+ ObjHead = UserHeapAlloc(Size);
+ if (!ObjHead)
+ return NULL;
+
+ RtlZeroMemory(ObjHead, Size);
+
+ ObjHead->ppi = ppi;
+ IntReferenceProcessInfo(ppi);
+ *HandleOwner = ppi;
+ ppi->UserHandleCount++;
+
+ return ObjHead;
+}
+
+static void FreeProcMarkObject(
+ _In_ PVOID Object)
+{
+ PPROCESSINFO ppi = ((PPROCMARKHEAD)Object)->ppi;
+
+ UserHeapFree(Object);
+
+ ppi->UserHandleCount--;
+ IntDereferenceProcessInfo(ppi);
+}
+
+static PVOID AllocSysObject(
+ _In_ PDESKTOP pDesk,
+ _In_ PTHREADINFO pti,
+ _In_ SIZE_T Size,
+ _Out_ PVOID* ObjectOwner)
+{
+ PVOID Object;
+
+ UNREFERENCED_PARAMETER(pDesk);
+ UNREFERENCED_PARAMETER(pti);
+
+ ASSERT(Size > sizeof(HEAD));
+
+ Object = UserHeapAlloc(Size);
+ if (!Object)
+ return NULL;
+
+ *ObjectOwner = NULL;
+
+ RtlZeroMemory(Object, Size);
+ return Object;
+}
+
+static void FreeSysObject(
+ _In_ PVOID Object)
+{
+ UserHeapFree(Object);
+}
+
+static const struct
+{
+ PVOID (*ObjectAlloc)(PDESKTOP, PTHREADINFO, SIZE_T, PVOID*);
+ BOOLEAN (*ObjectDestroy)(PVOID);
+ void (*ObjectFree)(PVOID);
+} ObjectCallbacks[TYPE_CTYPES] =
+{
+ { NULL, NULL, NULL }, /* TYPE_FREE */
+ { AllocDeskThreadObject, co_UserDestroyWindow, FreeDeskThreadObject }, /* TYPE_WINDOW */
+ { AllocDeskProcObject, UserDestroyMenuObject, FreeDeskProcObject }, /* TYPE_MENU */
+ { AllocProcMarkObject, /*UserCursorCleanup*/NULL, FreeProcMarkObject }, /* TYPE_CURSOR */
+ { AllocSysObject, /*UserSetWindowPosCleanup*/NULL, FreeSysObject }, /* TYPE_SETWINDOWPOS */
+ { AllocDeskThreadObject, IntRemoveHook, FreeDeskThreadObject }, /* TYPE_HOOK */
+ { AllocSysObject, /*UserClipDataCleanup*/NULL,FreeSysObject }, /* TYPE_CLIPDATA */
+ { AllocDeskProcObject, DestroyCallProc, FreeDeskProcObject }, /* TYPE_CALLPROC */
+ { AllocProcMarkObject, UserDestroyAccelTable, FreeProcMarkObject }, /* TYPE_ACCELTABLE */
+ { NULL, NULL, NULL }, /* TYPE_DDEACCESS */
+ { NULL, NULL, NULL }, /* TYPE_DDECONV */
+ { NULL, NULL, NULL }, /* TYPE_DDEXACT */
+ { AllocSysObject, /*UserMonitorCleanup*/NULL, FreeSysObject }, /* TYPE_MONITOR */
+ { AllocSysObject, /*UserKbdLayoutCleanup*/NULL,FreeSysObject }, /* TYPE_KBDLAYOUT */
+ { AllocSysObject, /*UserKbdFileCleanup*/NULL, FreeSysObject }, /* TYPE_KBDFILE */
+ { AllocThreadObject, IntRemoveEvent, FreeThreadObject }, /* TYPE_WINEVENTHOOK */
+ { AllocSysObject, /*UserTimerCleanup*/NULL, FreeSysObject }, /* TYPE_TIMER */
+ { NULL, NULL, NULL }, /* TYPE_INPUTCONTEXT */
+ { NULL, NULL, NULL }, /* TYPE_HIDDATA */
+ { NULL, NULL, NULL }, /* TYPE_DEVICEINFO */
+ { NULL, NULL, NULL }, /* TYPE_TOUCHINPUTINFO */
+ { NULL, NULL, NULL }, /* TYPE_GESTUREINFOOBJ */
+};
+
+#if DBG
+
+void DbgUserDumpHandleTable()
+{
+ int HandleCounts[TYPE_CTYPES];
+ PPROCESSINFO ppiList;
+ int i;
+ PWCHAR TypeNames[] = {L"Free",L"Window",L"Menu", L"CursorIcon", L"SMWP", L"Hook", L"ClipBoardData", L"CallProc",
+ L"Accel", L"DDEaccess", L"DDEconv", L"DDExact", L"Monitor", L"KBDlayout", L"KBDfile",
+ L"Event", L"Timer", L"InputContext", L"HidData", L"DeviceInfo", L"TouchInput",L"GestureInfo"};
+
+ ERR("Total handles count: %lu\n", gpsi->cHandleEntries);
+
+ memset(HandleCounts, 0, sizeof(HandleCounts));
+
+ /* First of all count the number of handles per type */
+ ppiList = gppiList;
+ while (ppiList)
+ {
+ ERR("Process %s (%p) handles count: %d\n\t", ppiList->peProcess->ImageFileName, ppiList->peProcess->UniqueProcessId, ppiList->UserHandleCount);
+
+ for (i = 1 ;i < TYPE_CTYPES; i++)
+ {
+ HandleCounts[i] += ppiList->DbgHandleCount[i];
+
+ DbgPrint("%S: %lu, ", TypeNames[i], ppiList->DbgHandleCount[i]);
+ if (i % 6 == 0)
+ DbgPrint("\n\t");
+ }
+ DbgPrint("\n");
+
+ ppiList = ppiList->ppiNext;
+ }
+
+ /* Print total type counts */
+ ERR("Total handles of the running processes: \n\t");
+ for (i = 1 ;i < TYPE_CTYPES; i++)
+ {
+ DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]);
+ if (i % 6 == 0)
+ DbgPrint("\n\t");
+ }
+ DbgPrint("\n");
+
+ /* Now count the handle counts that are allocated from the handle table */
+ memset(HandleCounts, 0, sizeof(HandleCounts));
+ for (i = 0; i < gHandleTable->nb_handles; i++)
+ HandleCounts[gHandleTable->handles[i].type]++;
+
+ ERR("Total handles count allocated: \n\t");
+ for (i = 1 ;i < TYPE_CTYPES; i++)
+ {
+ DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]);
+ if (i % 6 == 0)
+ DbgPrint("\n\t");
+ }
+ DbgPrint("\n");
+}
+
+#endif
PUSER_HANDLE_ENTRY handle_to_entry(PUSER_HANDLE_TABLE ht, HANDLE handle )
{
__inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht)
{
PUSER_HANDLE_ENTRY entry;
- PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
- TRACE("handles used %i\n",gpsi->cHandleEntries);
+ TRACE("handles used %lu\n", gpsi->cHandleEntries);
if (ht->freelist)
{
ht->freelist = entry->ptr;
gpsi->cHandleEntries++;
- ppi->UserHandleCount++;
return entry;
}
if (ht->nb_handles >= ht->allocated_handles) /* Need to grow the array */
{
-/**/
- int i, iFree = 0, iWindow = 0, iMenu = 0, iCursorIcon = 0,
- iHook = 0, iCallProc = 0, iAccel = 0, iMonitor = 0, iTimer = 0, iEvent = 0, iSMWP = 0;
- /**/
- ERR("Out of user handles! Used -> %i, NM_Handle -> %d\n", gpsi->cHandleEntries, ht->nb_handles);
-//#if 0
- for(i = 0; i < ht->nb_handles; i++)
- {
- switch (ht->handles[i].type)
- {
- case otFree: // Should be zero.
- iFree++;
- break;
- case otWindow:
- iWindow++;
- break;
- case otMenu:
- iMenu++;
- break;
- case otCursorIcon:
- iCursorIcon++;
- break;
- case otHook:
- iHook++;
- break;
- case otCallProc:
- iCallProc++;
- break;
- case otAccel:
- iAccel++;
- break;
- case otMonitor:
- iMonitor++;
- break;
- case otTimer:
- iTimer++;
- break;
- case otEvent:
- iEvent++;
- break;
- case otSMWP:
- iSMWP++;
- default:
- break;
- }
- }
- ERR("Handle Count by Type:\n Free = %d Window = %d Menu = %d CursorIcon = %d Hook = %d\n CallProc = %d Accel = %d Monitor = %d Timer = %d Event = %d SMWP = %d\n",
- iFree, iWindow, iMenu, iCursorIcon, iHook, iCallProc, iAccel, iMonitor, iTimer, iEvent, iSMWP );
-//#endif
+ ERR("Out of user handles! Used -> %lu, NM_Handle -> %d\n", gpsi->cHandleEntries, ht->nb_handles);
+
+#if DBG
+ DbgUserDumpHandleTable();
+#endif
+
return NULL;
#if 0
PUSER_HANDLE_ENTRY new_handles;
entry->generation = 1;
gpsi->cHandleEntries++;
- ppi->UserHandleCount++;
return entry;
}
ht->allocated_handles = bytes / sizeof(USER_HANDLE_ENTRY);
}
+
__inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY entry)
{
- PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
void *ret;
+
+#if DBG
+ {
+ PPROCESSINFO ppi;
+ switch (entry->type)
+ {
+ case TYPE_WINDOW:
+ case TYPE_HOOK:
+ case TYPE_WINEVENTHOOK:
+ ppi = ((PTHREADINFO)entry->pi)->ppi;
+ break;
+ case TYPE_MENU:
+ case TYPE_CURSOR:
+ case TYPE_CALLPROC:
+ case TYPE_ACCELTABLE:
+ ppi = entry->pi;
+ break;
+ default:
+ ppi = NULL;
+ }
+ if (ppi)
+ ppi->DbgHandleCount[entry->type]--;
+ }
+#endif
+
ret = entry->ptr;
entry->ptr = ht->freelist;
entry->type = 0;
ht->freelist = entry;
gpsi->cHandleEntries--;
- ppi->UserHandleCount--;
return ret;
}
-static __inline PVOID
-UserHandleOwnerByType(USER_OBJECT_TYPE type)
-{
- PVOID pi;
-
- switch (type)
- {
- case otWindow:
- case otInputContext:
- pi = GetW32ThreadInfo();
- break;
-
- case otMenu:
- case otCursorIcon:
- case otHook:
- case otCallProc:
- case otAccel:
- case otSMWP:
- pi = GetW32ProcessInfo();
- break;
-
- case otMonitor:
- pi = NULL; /* System */
- break;
-
- default:
- pi = NULL;
- break;
- }
-
- return pi;
-}
-
/* allocate a user handle for a given object */
-HANDLE UserAllocHandle(PUSER_HANDLE_TABLE ht, PVOID object, USER_OBJECT_TYPE type )
+HANDLE UserAllocHandle(
+ _Inout_ PUSER_HANDLE_TABLE ht,
+ _In_ PVOID object,
+ _In_ HANDLE_TYPE type,
+ _In_ PVOID HandleOwner)
{
PUSER_HANDLE_ENTRY entry = alloc_user_entry(ht);
if (!entry)
entry->ptr = object;
entry->type = type;
entry->flags = 0;
- entry->pi = UserHandleOwnerByType(type);
+ entry->pi = HandleOwner;
if (++entry->generation >= 0xffff)
entry->generation = 1;
return entry_to_handle(ht, entry );
}
+/* return a pointer to a user object from its handle without setting an error */
+PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type )
+{
+ PUSER_HANDLE_ENTRY entry;
+
+ ASSERT(ht);
+
+ if (!(entry = handle_to_entry(ht, handle )) || entry->type != type)
+ {
+ return NULL;
+ }
+ return entry->ptr;
+}
+
/* return a pointer to a user object from its handle */
-PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type )
+PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type )
{
PUSER_HANDLE_ENTRY entry;
/* Same as get_user_object plus set the handle to the full 32-bit value */
-void *get_user_object_handle(PUSER_HANDLE_TABLE ht, HANDLE* handle, USER_OBJECT_TYPE type )
+void *get_user_object_handle(PUSER_HANDLE_TABLE ht, HANDLE* handle, HANDLE_TYPE type )
{
PUSER_HANDLE_ENTRY entry;
BOOL FASTCALL UserCreateHandleTable(VOID)
{
-
PVOID mem;
+ INT HandleCount = 1024 * 4;
// FIXME: Don't alloc all at once! Must be mapped into umode also...
- mem = UserHeapAlloc(sizeof(USER_HANDLE_ENTRY) * 1024*2);
+ mem = UserHeapAlloc(sizeof(USER_HANDLE_ENTRY) * HandleCount);
if (!mem)
{
ERR("Failed creating handle table\n");
}
// FIXME: Make auto growable
- UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * 1024*2);
+ UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * HandleCount);
return TRUE;
}
FASTCALL
UserCreateObject( PUSER_HANDLE_TABLE ht,
PDESKTOP pDesktop,
+ PTHREADINFO pti,
HANDLE* h,
- USER_OBJECT_TYPE type,
+ HANDLE_TYPE type,
ULONG size)
{
HANDLE hi;
PVOID Object;
- PTHREADINFO pti;
- PPROCESSINFO ppi;
- BOOL dt;
- PDESKTOP rpdesk = pDesktop;
+ PVOID ObjectOwner;
- pti = GetW32ThreadInfo();
- ppi = pti->ppi;
- if (!pDesktop) rpdesk = pti->rpdesk;
-
- switch (type)
- {
- case otWindow:
-// case otMenu:
- case otHook:
- case otCallProc:
- case otInputContext:
- Object = DesktopHeapAlloc(rpdesk, size);
- dt = TRUE;
- break;
-
- default:
- Object = UserHeapAlloc(size);
- dt = FALSE;
- break;
- }
+ /* Some sanity checks. Other checks will be made in the allocator */
+ ASSERT(type < TYPE_CTYPES);
+ ASSERT(type != TYPE_FREE);
+ ASSERT(ht != NULL);
+ /* Allocate the object */
+ ASSERT(ObjectCallbacks[type].ObjectAlloc != NULL);
+ Object = ObjectCallbacks[type].ObjectAlloc(pDesktop, pti, size, &ObjectOwner);
if (!Object)
- return NULL;
-
-
- hi = UserAllocHandle(ht, Object, type );
- if (!hi)
{
- if (dt)
- DesktopHeapFree(rpdesk, Object);
- else
- UserHeapFree(Object);
- return NULL;
+ ERR("User object allocation failed. Out of memory!\n");
+ return NULL;
}
- RtlZeroMemory(Object, size);
-
- switch (type)
+ hi = UserAllocHandle(ht, Object, type, ObjectOwner);
+ if (hi == NULL)
{
- case otWindow:
- case otHook:
- case otInputContext:
- ((PTHRDESKHEAD)Object)->rpdesk = rpdesk;
- ((PTHRDESKHEAD)Object)->pSelf = Object;
- case otEvent:
- ((PTHROBJHEAD)Object)->pti = pti;
- break;
-
- case otMenu:
- case otCallProc:
- ((PPROCDESKHEAD)Object)->rpdesk = rpdesk;
- ((PPROCDESKHEAD)Object)->pSelf = Object;
- break;
+ ERR("Out of user handles!\n");
+ ObjectCallbacks[type].ObjectFree(Object);
+ return NULL;
+ }
- case otCursorIcon:
- ((PPROCMARKHEAD)Object)->ppi = ppi;
- break;
+#if DBG
+ if (pti)
+ pti->ppi->DbgHandleCount[type]++;
+#endif
- default:
- break;
- }
- /* Now set default headers. */
+ /* Give this object its identity. */
((PHEAD)Object)->h = hi;
- ((PHEAD)Object)->cLockObj = 2; // We need this, because we create 2 refs: handle and pointer!
+
+ /* The caller will get a locked object.
+ * Note: with the reference from the handle, that makes two */
+ UserReferenceObject(Object);
if (h)
*h = hi;
BOOL
FASTCALL
-UserDereferenceObject(PVOID object)
+UserDereferenceObject(PVOID Object)
{
- PUSER_HANDLE_ENTRY entry;
- USER_OBJECT_TYPE type;
+ PHEAD ObjHead = (PHEAD)Object;
- ASSERT(((PHEAD)object)->cLockObj >= 1);
+ ASSERT(ObjHead->cLockObj >= 1);
- if ((INT)--((PHEAD)object)->cLockObj <= 0)
- {
- entry = handle_to_entry(gHandleTable, ((PHEAD)object)->h );
+ if (--ObjHead->cLockObj == 0)
+ {
+ PUSER_HANDLE_ENTRY entry;
+ HANDLE_TYPE type;
- if (!entry)
- {
- ERR("Warning! Dereference Object without ENTRY! Obj -> 0x%x\n", object);
- return FALSE;
- }
- TRACE("Warning! Dereference to zero! Obj -> 0x%x\n", object);
+ entry = handle_to_entry(gHandleTable, ObjHead->h);
- ((PHEAD)object)->cLockObj = 0;
+ ASSERT(entry != NULL);
+ /* The entry should be marked as in deletion */
+ ASSERT(entry->flags & HANDLEENTRY_INDESTROY);
- if (!(entry->flags & HANDLEENTRY_INDESTROY))
- return TRUE;
+ type = entry->type;
+ ASSERT(type != TYPE_FREE);
+ ASSERT(type < TYPE_CTYPES);
- type = entry->type;
- free_user_entry(gHandleTable, entry );
+ /* We can now get rid of everything */
+ free_user_entry(gHandleTable, entry );
- switch (type)
- {
- case otWindow:
-// case otMenu:
- case otHook:
- case otCallProc:
- case otInputContext:
- return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object);
+#if 0
+ /* Call the object destructor */
+ ASSERT(ObjectCallbacks[type].ObjectCleanup != NULL);
+ ObjectCallbacks[type].ObjectCleanup(Object);
+#endif
- default:
- return UserHeapFree(object);
- }
- }
- return FALSE;
+ /* And free it */
+ ASSERT(ObjectCallbacks[type].ObjectFree != NULL);
+ ObjectCallbacks[type].ObjectFree(Object);
+
+ return TRUE;
+ }
+ return FALSE;
}
BOOL
if (!(entry = handle_to_entry( gHandleTable, h )))
{
SetLastNtError( STATUS_INVALID_HANDLE );
- return FALSE;
+ return TRUE;
}
return (entry->flags & HANDLEENTRY_INDESTROY);
}
BOOL
FASTCALL
-UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type )
+UserDeleteObject(HANDLE h, HANDLE_TYPE type )
{
PVOID body = UserGetObject(gHandleTable, h, type);
PVOID
FASTCALL
-UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type)
+UserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type)
{
PVOID object;
return object;
}
+VOID
+FASTCALL
+UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner)
+{
+ PUSER_HANDLE_ENTRY entry = handle_to_entry(gHandleTable, ((PHEAD)obj)->h );
+ PPROCESSINFO ppi, oldppi;
+
+ /* This must be called with a valid object */
+ ASSERT(entry);
+
+ /* For now, only supported for CursorIcon object */
+ switch(type)
+ {
+ case TYPE_CURSOR:
+ ppi = (PPROCESSINFO)owner;
+ entry->pi = ppi;
+ oldppi = ((PPROCMARKHEAD)obj)->ppi;
+ ((PPROCMARKHEAD)obj)->ppi = ppi;
+ break;
+ default:
+ ASSERT(FALSE);
+ return;
+ }
+
+#if DBG
+ oldppi->DbgHandleCount[type]--;
+ ppi->DbgHandleCount[type]++;
+#endif
+
+ oldppi->UserHandleCount--;
+ IntDereferenceProcessInfo(oldppi);
+ ppi->UserHandleCount++;
+ IntReferenceProcessInfo(ppi);
+}
+
+BOOLEAN
+UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner)
+{
+ int i;
+ PUSER_HANDLE_ENTRY Entry;
+ BOOLEAN Ret = TRUE;
+
+ /* Sweep the whole handle table */
+ for (i = 0; i < Table->allocated_handles; i++)
+ {
+ Entry = &Table->handles[i];
+
+ if (Entry->pi != Owner)
+ continue;
+
+ /* Do not destroy if it's already been done */
+ if (Entry->flags & HANDLEENTRY_INDESTROY)
+ continue;
+
+ /* Spcial case for cursors until cursoricon_new is there */
+ if (Entry->type == TYPE_CURSOR)
+ {
+ UserReferenceObject(Entry->ptr);
+ if (!IntDestroyCurIconObject(Entry->ptr, Owner))
+ {
+ Ret = FALSE;
+ }
+ continue;
+ }
+
+ /* Call destructor */
+ if (!ObjectCallbacks[Entry->type].ObjectDestroy(Entry->ptr))
+ {
+ ERR("Failed destructing object %p, type %u.\n", Entry->ptr, Entry->type);
+ /* Don't return immediately, we must continue destroying the other objects */
+ Ret = FALSE;
+ }
+ }
+
+ return Ret;
+}
+
/*
- * NtUserValidateHandleSecure
+ * NtUserValidateHandleSecure W2k3 has one argument.
*
* Status
* @implemented
HANDLE handle,
BOOL Restricted)
{
- if(!Restricted)
+ UINT uType;
+ PPROCESSINFO ppi;
+ PUSER_HANDLE_ENTRY entry;
+
+ DECLARE_RETURN(BOOL);
+ UserEnterExclusive();
+
+ if (!(entry = handle_to_entry(gHandleTable, handle )))
{
- UINT uType;
- {
- PUSER_HANDLE_ENTRY entry;
- if (!(entry = handle_to_entry(gHandleTable, handle )))
- {
- EngSetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
- uType = entry->type;
- }
- switch (uType)
- {
- case otWindow:
- {
- if (UserGetWindowObject((HWND) handle)) return TRUE;
- return FALSE;
- }
- case otMenu:
- {
- if (UserGetMenuObject((HMENU) handle)) return TRUE;
- return FALSE;
- }
- case otAccel:
- {
- if (UserGetAccelObject((HACCEL) handle)) return TRUE;
- return FALSE;
- }
- case otCursorIcon:
- {
- if (UserGetCurIconObject((HCURSOR) handle)) return TRUE;
- return FALSE;
- }
- case otHook:
- {
- if (IntGetHookObject((HHOOK) handle)) return TRUE;
- return FALSE;
- }
- case otMonitor:
- {
- if (UserGetMonitorObject((HMONITOR) handle)) return TRUE;
- return FALSE;
- }
- case otCallProc:
- {
- WNDPROC_INFO Proc;
- return UserGetCallProcInfo( handle, &Proc );
- }
- default:
- EngSetLastError(ERROR_INVALID_HANDLE);
- }
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ RETURN( FALSE);
}
- else
- { /* Is handle entry restricted? */
- STUB
+ uType = entry->type;
+ switch (uType)
+ {
+ case TYPE_WINDOW:
+ case TYPE_INPUTCONTEXT:
+ ppi = ((PTHREADINFO)entry->pi)->ppi;
+ break;
+ case TYPE_MENU:
+ case TYPE_ACCELTABLE:
+ case TYPE_CURSOR:
+ case TYPE_HOOK:
+ case TYPE_CALLPROC:
+ case TYPE_SETWINDOWPOS:
+ ppi = entry->pi;
+ break;
+ default:
+ ppi = NULL;
+ break;
}
- return FALSE;
+
+ if (!ppi) RETURN( FALSE);
+
+ // Same process job returns TRUE.
+ if (gptiCurrent->ppi->pW32Job == ppi->pW32Job) RETURN( TRUE);
+
+ RETURN( FALSE);
+
+CLEANUP:
+ UserLeave();
+ END_CLEANUP;
}