Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873/* * 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;}
_Success_(return!=NULL)static PVOID AllocSysObjectCB( _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));
/* Allocate the clipboard data */ // FIXME: This allocation should be done on the current session pool; // however ReactOS' MM doesn't support session pool yet. Object = ExAllocatePoolZero(/* SESSION_POOL_MASK | */ PagedPool, Size, USERTAG_CLIPBOARD); if (!Object) { ERR("ExAllocatePoolZero failed. No object created.\n"); return NULL; }
*ObjectOwner = NULL; return Object;}
static void FreeSysObject( _In_ PVOID Object){ UserHeapFree(Object);}
static void FreeSysObjectCB( _In_ PVOID Object){ ExFreePoolWithTag(Object, USERTAG_CLIPBOARD);}
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 */ { AllocSysObjectCB, /*UserClipDataCleanup*/NULL,FreeSysObjectCB }, /* 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 */ { AllocInputContextObject, UserDestroyInputContext, UserFreeInputContext }, /* 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 = (LOWORD(handle) - FIRST_USER_HANDLE) >> 1; if (index < 0 || index >= ht->nb_handles) return NULL; if (!ht->handles[index].type) return NULL; generation = HIWORD(handle); 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)((((INT_PTR)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 ((ULONG_PTR)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//PVOIDFASTCALLUserCreateObject( 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;}
// Win: HMMarkObjectDestroyBOOLFASTCALLUserMarkObjectDestroy(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;}
BOOLFASTCALLUserDereferenceObject(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;}
BOOLFASTCALLUserFreeHandle(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);}
BOOLFASTCALLUserObjectInDestroy(HANDLE h){ PUSER_HANDLE_ENTRY entry;
if (!(entry = handle_to_entry( gHandleTable, h ))) { SetLastNtError( STATUS_INVALID_HANDLE ); return TRUE; } return (entry->flags & HANDLEENTRY_INDESTROY);}
BOOLFASTCALLUserDeleteObject(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);}
VOIDFASTCALLUserReferenceObject(PVOID obj){ PHEAD ObjHead = obj; ASSERT(ObjHead->cLockObj < 0x10000);
ObjHead->cLockObj++;}
PVOIDFASTCALLUserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type){ PVOID object;
object = UserGetObject(gHandleTable, handle, type); if (object) { UserReferenceObject(object); } return object;}
BOOLEANUserDestroyObjectsForOwner(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 */
BOOLAPIENTRYNtUserValidateHandleSecure( HANDLE handle){ UINT uType; PPROCESSINFO ppi; PUSER_HANDLE_ENTRY entry; BOOL Ret = FALSE;
UserEnterExclusive();
if (!(entry = handle_to_entry(gHandleTable, handle ))) { EngSetLastError(ERROR_INVALID_HANDLE); goto Exit; // 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) goto Exit; // Return FALSE
// Same process job returns TRUE. if (gptiCurrent->ppi->pW32Job == ppi->pW32Job) Ret = TRUE;
Exit: UserLeave(); return Ret;}
// Win: HMAssignmentLockPVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew){ PVOID pvOld = *ppvObj; *ppvObj = pvNew;
if (pvOld && pvOld == pvNew) return pvOld;
if (pvNew) UserReferenceObject(pvNew);
if (pvOld) { if (UserDereferenceObject(pvOld)) pvOld = NULL; }
return pvOld;}
// Win: HMAssignmentUnlockPVOID FASTCALL UserAssignmentUnlock(PVOID *ppvObj){ PVOID pvOld = *ppvObj; *ppvObj = NULL;
if (pvOld) { if (UserDereferenceObject(pvOld)) pvOld = NULL; }
return pvOld;}