mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 22:02:57 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
803
win32ss/user/ntuser/object.c
Normal file
803
win32ss/user/ntuser/object.c
Normal file
|
@ -0,0 +1,803 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: User handle manager
|
||||
* FILE: win32ss/user/ntuser/object.c
|
||||
* PROGRAMER: Copyright (C) 2001 Alexandre Julliard
|
||||
*/
|
||||
|
||||
#include <win32k.h>
|
||||
DBG_DEFAULT_CHANNEL(UserObj);
|
||||
|
||||
//int usedHandles=0;
|
||||
PUSER_HANDLE_TABLE gHandleTable = NULL;
|
||||
|
||||
/* Forward declarations */
|
||||
_Success_(return!=NULL)
|
||||
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);
|
||||
}
|
||||
|
||||
_Success_(return!=NULL)
|
||||
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);
|
||||
}
|
||||
|
||||
_Success_(return!=NULL)
|
||||
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);
|
||||
}
|
||||
|
||||
_Success_(return!=NULL)
|
||||
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;
|
||||
}
|
||||
|
||||
void FreeProcMarkObject(
|
||||
_In_ PVOID Object)
|
||||
{
|
||||
PPROCESSINFO ppi = ((PPROCMARKHEAD)Object)->ppi;
|
||||
|
||||
UserHeapFree(Object);
|
||||
|
||||
ppi->UserHandleCount--;
|
||||
IntDereferenceProcessInfo(ppi);
|
||||
}
|
||||
|
||||
_Success_(return!=NULL)
|
||||
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, IntDestroyCurIconObject, FreeCurIconObject }, /* 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(VOID)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
unsigned short generation;
|
||||
int index = (((unsigned int)handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
|
||||
if (index < 0 || index >= ht->nb_handles)
|
||||
return NULL;
|
||||
if (!ht->handles[index].type)
|
||||
return NULL;
|
||||
generation = (unsigned int)handle >> 16;
|
||||
if (generation == ht->handles[index].generation || !generation || generation == 0xffff)
|
||||
return &ht->handles[index];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__inline static HANDLE entry_to_handle(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY ptr )
|
||||
{
|
||||
int index = ptr - ht->handles;
|
||||
return (HANDLE)(((index << 1) + FIRST_USER_HANDLE) + (ptr->generation << 16));
|
||||
}
|
||||
|
||||
__inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht)
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
TRACE("handles used %lu\n", gpsi->cHandleEntries);
|
||||
|
||||
if (ht->freelist)
|
||||
{
|
||||
entry = ht->freelist;
|
||||
ht->freelist = entry->ptr;
|
||||
|
||||
gpsi->cHandleEntries++;
|
||||
return entry;
|
||||
}
|
||||
|
||||
if (ht->nb_handles >= ht->allocated_handles) /* Need to grow the array */
|
||||
{
|
||||
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;
|
||||
/* Grow array by 50% (but at minimum 32 entries) */
|
||||
int growth = max( 32, ht->allocated_handles / 2 );
|
||||
int new_size = min( ht->allocated_handles + growth, (LAST_USER_HANDLE-FIRST_USER_HANDLE+1) >> 1 );
|
||||
if (new_size <= ht->allocated_handles)
|
||||
return NULL;
|
||||
if (!(new_handles = UserHeapReAlloc( ht->handles, new_size * sizeof(*ht->handles) )))
|
||||
return NULL;
|
||||
ht->handles = new_handles;
|
||||
ht->allocated_handles = new_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
entry = &ht->handles[ht->nb_handles++];
|
||||
|
||||
entry->generation = 1;
|
||||
|
||||
gpsi->cHandleEntries++;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
VOID UserInitHandleTable(PUSER_HANDLE_TABLE ht, PVOID mem, ULONG bytes)
|
||||
{
|
||||
ht->freelist = NULL;
|
||||
ht->handles = mem;
|
||||
|
||||
ht->nb_handles = 0;
|
||||
ht->allocated_handles = bytes / sizeof(USER_HANDLE_ENTRY);
|
||||
}
|
||||
|
||||
|
||||
__inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY entry)
|
||||
{
|
||||
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;
|
||||
entry->flags = 0;
|
||||
entry->pi = NULL;
|
||||
ht->freelist = entry;
|
||||
|
||||
gpsi->cHandleEntries--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* allocate a user handle for a given object */
|
||||
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)
|
||||
return 0;
|
||||
entry->ptr = object;
|
||||
entry->type = type;
|
||||
entry->flags = 0;
|
||||
entry->pi = HandleOwner;
|
||||
if (++entry->generation >= 0xffff)
|
||||
entry->generation = 1;
|
||||
|
||||
/* We have created a handle, which is a reference! */
|
||||
UserReferenceObject(object);
|
||||
|
||||
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, HANDLE_TYPE type )
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
|
||||
ASSERT(ht);
|
||||
|
||||
if (!(entry = handle_to_entry(ht, handle )) || entry->type != type)
|
||||
{
|
||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
return entry->ptr;
|
||||
}
|
||||
|
||||
|
||||
/* Get the full handle (32bit) for a possibly truncated (16bit) handle */
|
||||
HANDLE get_user_full_handle(PUSER_HANDLE_TABLE ht, HANDLE handle )
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
|
||||
if ((unsigned int)handle >> 16)
|
||||
return handle;
|
||||
if (!(entry = handle_to_entry(ht, handle )))
|
||||
return handle;
|
||||
return entry_to_handle( ht, 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, HANDLE_TYPE type )
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
|
||||
if (!(entry = handle_to_entry(ht, *handle )) || entry->type != type)
|
||||
return NULL;
|
||||
*handle = entry_to_handle( ht, entry );
|
||||
return entry->ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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) * HandleCount);
|
||||
if (!mem)
|
||||
{
|
||||
ERR("Failed creating handle table\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gHandleTable = UserHeapAlloc(sizeof(USER_HANDLE_TABLE));
|
||||
if (gHandleTable == NULL)
|
||||
{
|
||||
UserHeapFree(mem);
|
||||
ERR("Failed creating handle table\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FIXME: Make auto growable
|
||||
UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * HandleCount);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// New
|
||||
//
|
||||
PVOID
|
||||
FASTCALL
|
||||
UserCreateObject( PUSER_HANDLE_TABLE ht,
|
||||
PDESKTOP pDesktop,
|
||||
PTHREADINFO pti,
|
||||
HANDLE* h,
|
||||
HANDLE_TYPE type,
|
||||
ULONG size)
|
||||
{
|
||||
HANDLE hi;
|
||||
PVOID Object;
|
||||
PVOID ObjectOwner;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
ERR("User object allocation failed. Out of memory!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hi = UserAllocHandle(ht, Object, type, ObjectOwner);
|
||||
if (hi == NULL)
|
||||
{
|
||||
ERR("Out of user handles!\n");
|
||||
ObjectCallbacks[type].ObjectFree(Object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if DBG
|
||||
if (pti)
|
||||
pti->ppi->DbgHandleCount[type]++;
|
||||
#endif
|
||||
|
||||
/* Give this object its identity. */
|
||||
((PHEAD)Object)->h = hi;
|
||||
|
||||
/* The caller will get a locked object.
|
||||
* Note: with the reference from the handle, that makes two */
|
||||
UserReferenceObject(Object);
|
||||
|
||||
if (h)
|
||||
*h = hi;
|
||||
return Object;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserMarkObjectDestroy(PVOID Object)
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
PHEAD ObjHead = Object;
|
||||
|
||||
entry = handle_to_entry(gHandleTable, ObjHead->h);
|
||||
|
||||
ASSERT(entry != NULL);
|
||||
|
||||
entry->flags |= HANDLEENTRY_DESTROY;
|
||||
|
||||
if (ObjHead->cLockObj > 1)
|
||||
{
|
||||
entry->flags &= ~HANDLEENTRY_INDESTROY;
|
||||
TRACE("Count %d\n",ObjHead->cLockObj);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserDereferenceObject(PVOID Object)
|
||||
{
|
||||
PHEAD ObjHead = Object;
|
||||
|
||||
ASSERT(ObjHead->cLockObj >= 1);
|
||||
ASSERT(ObjHead->cLockObj < 0x10000);
|
||||
|
||||
if (--ObjHead->cLockObj == 0)
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
HANDLE_TYPE type;
|
||||
|
||||
entry = handle_to_entry(gHandleTable, ObjHead->h);
|
||||
|
||||
ASSERT(entry != NULL);
|
||||
/* The entry should be marked as in deletion */
|
||||
ASSERT(entry->flags & HANDLEENTRY_INDESTROY);
|
||||
|
||||
type = entry->type;
|
||||
ASSERT(type != TYPE_FREE);
|
||||
ASSERT(type < TYPE_CTYPES);
|
||||
|
||||
/* We can now get rid of everything */
|
||||
free_user_entry(gHandleTable, entry );
|
||||
|
||||
#if 0
|
||||
/* Call the object destructor */
|
||||
ASSERT(ObjectCallbacks[type].ObjectCleanup != NULL);
|
||||
ObjectCallbacks[type].ObjectCleanup(Object);
|
||||
#endif
|
||||
|
||||
/* And free it */
|
||||
ASSERT(ObjectCallbacks[type].ObjectFree != NULL);
|
||||
ObjectCallbacks[type].ObjectFree(Object);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserFreeHandle(PUSER_HANDLE_TABLE ht, HANDLE handle )
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
|
||||
if (!(entry = handle_to_entry( ht, handle )))
|
||||
{
|
||||
SetLastNtError( STATUS_INVALID_HANDLE );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
entry->flags = HANDLEENTRY_INDESTROY;
|
||||
|
||||
return UserDereferenceObject(entry->ptr);
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserObjectInDestroy(HANDLE h)
|
||||
{
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
|
||||
if (!(entry = handle_to_entry( gHandleTable, h )))
|
||||
{
|
||||
SetLastNtError( STATUS_INVALID_HANDLE );
|
||||
return TRUE;
|
||||
}
|
||||
return (entry->flags & HANDLEENTRY_INDESTROY);
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
UserDeleteObject(HANDLE h, HANDLE_TYPE type )
|
||||
{
|
||||
PVOID body = UserGetObject(gHandleTable, h, type);
|
||||
|
||||
if (!body) return FALSE;
|
||||
|
||||
ASSERT( ((PHEAD)body)->cLockObj >= 1);
|
||||
ASSERT( ((PHEAD)body)->cLockObj < 0x10000);
|
||||
|
||||
return UserFreeHandle(gHandleTable, h);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
UserReferenceObject(PVOID obj)
|
||||
{
|
||||
PHEAD ObjHead = obj;
|
||||
ASSERT(ObjHead->cLockObj < 0x10000);
|
||||
|
||||
ObjHead->cLockObj++;
|
||||
}
|
||||
|
||||
PVOID
|
||||
FASTCALL
|
||||
UserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type)
|
||||
{
|
||||
PVOID object;
|
||||
|
||||
object = UserGetObject(gHandleTable, handle, type);
|
||||
if (object)
|
||||
{
|
||||
UserReferenceObject(object);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Status
|
||||
* @implemented
|
||||
*/
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtUserValidateHandleSecure(
|
||||
HANDLE handle)
|
||||
{
|
||||
UINT uType;
|
||||
PPROCESSINFO ppi;
|
||||
PUSER_HANDLE_ENTRY entry;
|
||||
|
||||
DECLARE_RETURN(BOOL);
|
||||
UserEnterExclusive();
|
||||
|
||||
if (!(entry = handle_to_entry(gHandleTable, handle )))
|
||||
{
|
||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||
RETURN( FALSE);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (!ppi) RETURN( FALSE);
|
||||
|
||||
// Same process job returns TRUE.
|
||||
if (gptiCurrent->ppi->pW32Job == ppi->pW32Job) RETURN( TRUE);
|
||||
|
||||
RETURN( FALSE);
|
||||
|
||||
CLEANUP:
|
||||
UserLeave();
|
||||
END_CLEANUP;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue