NTSTATUS NTAPI NtOpenProcessToken( HANDLE Process, ACCESS_MASK DesiredAccess, PHANDLE Token ) { NTSTATUS r; TRACE("%p %08lx %p\n", Process, DesiredAccess, Token); r = VerifyForWrite( Token, sizeof *Token ); if (r < STATUS_SUCCESS) return r; PROCESS *p = 0; r = ObjectFromHandle( p, Process, 0 ); if (r < STATUS_SUCCESS) return r; TOKEN *token = new TOKEN_IMPL; if (!token) return STATUS_NO_MEMORY; r = AllocUserHandle( token, DesiredAccess, Token ); Release( token ); return r; }
NTSTATUS NtCancelTimer( HANDLE TimerHandle, PBOOLEAN PreviousState) { NTSTATUS r; NTTIMER* timer = 0; r = ObjectFromHandle( timer, TimerHandle, TIMER_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (PreviousState) { r = VerifyForWrite( PreviousState, sizeof *PreviousState ); if (r < STATUS_SUCCESS) return r; } BOOLEAN prev = 0; timer->Cancel(prev); if (PreviousState) CopyToUser( PreviousState, &prev, sizeof prev ); return STATUS_SUCCESS; }
NTSTATUS NTAPI NtOpenThreadToken( HANDLE Thread, ACCESS_MASK DesiredAccess, BOOLEAN OpenAsSelf, PHANDLE TokenHandle ) { NTSTATUS r; TRACE("%p %08lx %u %p\n", Thread, DesiredAccess, OpenAsSelf, TokenHandle); r = VerifyForWrite( TokenHandle, sizeof *TokenHandle ); if (r < STATUS_SUCCESS) return r; THREAD *t = 0; r = ObjectFromHandle( t, Thread, DesiredAccess ); if (r < STATUS_SUCCESS) return r; TOKEN *tok = t->GetToken(); if (tok == 0) return STATUS_NO_TOKEN; r = AllocUserHandle( tok, DesiredAccess, TokenHandle ); return r; }
NTSTATUS NTAPI NtQueryTimer( HANDLE TimerHandle, TIMER_INFORMATION_CLASS TimerInformationClass, PVOID TimerInformation, ULONG TimerInformationLength, PULONG ResultLength) { NTSTATUS r; NTTIMER* timer = 0; r = ObjectFromHandle( timer, TimerHandle, TIMER_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; union { TIMER_BASIC_INFORMATION basic; } info; ULONG sz = 0; switch (TimerInformationClass) { case TimerBasicInformation: sz = sizeof info.basic; break; default: return STATUS_INVALID_INFO_CLASS; } // this seems like the wrong order, but agrees with what tests show r = VerifyForWrite( TimerInformation, sz ); if (r < STATUS_SUCCESS) return r; if (sz != TimerInformationLength) return STATUS_INFO_LENGTH_MISMATCH; switch (TimerInformationClass) { case TimerBasicInformation: info.basic.SignalState = timer->IsSignalled(); timer->TimeRemaining( info.basic.TimeRemaining ); break; default: assert(0); } r = CopyToUser( TimerInformation, &info, sz ); if (r < STATUS_SUCCESS) return r; if (ResultLength) CopyToUser( ResultLength, &sz, sizeof sz ); return r; }
OBJECTREF ComCallWrapper::GetObjectRefFromComIP(IUnknown* pUnk) { ComCallWrapper *pWrapper; THROWSCOMPLUSEXCEPTION(); _ASSERTE(pUnk != NULL); // check whether the IUnknown* is comming from our wrapper if (*(PVOID*)pUnk != GetComCallWrapperVPtr()) COMPlusThrow(kInvalidCastException); pWrapper = GetWrapperFromIP(pUnk); return ObjectFromHandle(pWrapper->m_hThis); }
static OBJECTREF GetOleAutBinder() { THROWSCOMPLUSEXCEPTION(); // If we have already create the instance of the OleAutBinder then simply return it. if (s_hndOleAutBinder) return ObjectFromHandle(s_hndOleAutBinder); MethodTable *pOleAutBinderClass = g_Mscorlib.GetClass(CLASS__OLE_AUT_BINDER); // Allocate an instance of the OleAutBinder class. OBJECTREF OleAutBinder = AllocateObject(pOleAutBinderClass); // Keep a handle to the OleAutBinder instance. s_hndOleAutBinder = CreateGlobalHandle(OleAutBinder); return OleAutBinder; }
NTSTATUS NTAPI NtSetInformationToken( IN HANDLE TokenHandle, IN TOKEN_INFORMATION_CLASS TokenInformationClass, IN PVOID TokenInformation, IN ULONG TokenInformationLength) { TOKEN *Token; //ULONG Len; NTSTATUS Status; FIXME("UNIMPLEMENTED: %08lx %08lx\n", TokenHandle, TokenInformationClass); Status = ObjectFromHandle(Token, TokenHandle, TOKEN_QUERY); if (Status < STATUS_SUCCESS) return Status; return STATUS_SUCCESS; }
// nonblocking NTSTATUS NTAPI NtSetIoCompletion( HANDLE IoCompletionHandle, ULONG IoCompletionKey, ULONG IoCompletionValue, NTSTATUS Status, ULONG Information) { NTSTATUS r; TRACE("%p %08lx %08lx %08lx %08lx\n", IoCompletionHandle, IoCompletionKey, IoCompletionValue, Status, Information); COMPLETION_PORT_IMPL *port = 0; r = ObjectFromHandle( port, IoCompletionHandle, IO_COMPLETION_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; port->Set( IoCompletionKey, IoCompletionValue, Status, Information ); return STATUS_SUCCESS; }
//NtPrivilegeCheck(00000154,0006fdc0,0006fe34) ret=77fa7082 NTSTATUS NtPrivilegeCheck( HANDLE TokenHandle, PPRIVILEGE_SET RequiredPrivileges, PBOOLEAN Result) { TOKEN *token = 0; NTSTATUS r = ObjectFromHandle( token, TokenHandle, TOKEN_QUERY ); if (r < STATUS_SUCCESS) return r; PRIVILEGES_SET ps; r = ps.CopyFromUser( RequiredPrivileges ); if (r < STATUS_SUCCESS) return r; BOOLEAN ok = TRUE; r = CopyToUser( Result, &ok, sizeof ok ); FIXME("\n"); return r; }
NTSTATUS NTAPI NtDuplicateToken( HANDLE ExistingToken, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, BOOLEAN EffectiveOnly, TOKEN_TYPE TokenType, PHANDLE TokenHandle) { TOKEN *existing = 0; NTSTATUS r = ObjectFromHandle( existing, ExistingToken, TOKEN_QUERY ); if (r < STATUS_SUCCESS) return r; TOKEN *token = new TOKEN_IMPL; if (!token) return STATUS_NO_MEMORY; r = AllocUserHandle( token, DesiredAccess, TokenHandle ); Release( token ); return r; }
HRESULT AssemblySpecBindingCache::Lookup(AssemblySpec *pSpec, PEFile **ppFile, IAssembly** ppIAssembly, OBJECTREF *pThrowable) { DWORD key = pSpec->Hash(); AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); if (entry == (AssemblyBinding *) INVALIDENTRY) return S_FALSE; else { if (ppFile) { if (entry->file == NULL) *ppFile = NULL; else PEFile::Clone(entry->file, ppFile); } if (ppIAssembly) { *ppIAssembly = entry->pIAssembly; if (*ppIAssembly != NULL) (*ppIAssembly)->AddRef(); } if (pThrowable) { if (entry->hThrowable == NULL) *pThrowable = NULL; else *pThrowable = ObjectFromHandle(entry->hThrowable); } return entry->hr; } }
NTSTATUS NtSetTimer( HANDLE TimerHandle, PLARGE_INTEGER DueTime, PTIMER_APC_ROUTINE TimerApcRoutine, PVOID TimerContext, BOOLEAN Resume, LONG Period, PBOOLEAN PreviousState) { LARGE_INTEGER due; NTSTATUS r = CopyFromUser( &due, DueTime, sizeof due ); if (r < STATUS_SUCCESS) return r; TRACE("due = %llx\n", due.QuadPart); NTTIMER* timer = 0; r = ObjectFromHandle( timer, TimerHandle, TIMER_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (PreviousState) { r = VerifyForWrite( PreviousState, sizeof *PreviousState ); if (r < STATUS_SUCCESS) return r; } BOOLEAN prev = FALSE; r = timer->Set( due, (PKNORMAL_ROUTINE)TimerApcRoutine, TimerContext, Resume, Period, prev ); if (r == STATUS_SUCCESS && PreviousState ) CopyToUser( PreviousState, &prev, sizeof prev ); return r; }
NTSTATUS NTAPI NtQueryInformationToken( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, PVOID TokenInformation, ULONG TokenInformationLength, PULONG ReturnLength ) { TOKEN *token; ULONG len; NTSTATUS r; TOKEN_STATISTICS stats; TRACE("%p %u %p %lu %p\n", TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength ); r = ObjectFromHandle( token, TokenHandle, TOKEN_QUERY ); if (r < STATUS_SUCCESS) return r; switch( TokenInformationClass ) { case TokenOwner: TRACE("TokenOwner\n"); r = CopyPtrToUser( token->GetOwner(), TokenInformation, TokenInformationLength, len ); break; case TokenPrimaryGroup: TRACE("TokenPrimaryGroup\n"); r = CopyPtrToUser( token->GetPrimaryGroup(), TokenInformation, TokenInformationLength, len ); break; case TokenDefaultDacl: TRACE("TokenDefaultDacl\n"); r = CopyPtrToUser( token->GetDefaultDacl(), TokenInformation, TokenInformationLength, len ); break; case TokenUser: TRACE("TokenUser\n"); len = token->GetUser().GetLength(); if (len > TokenInformationLength) { r = STATUS_BUFFER_TOO_SMALL; break; } r = token->GetUser().CopyToUser( (SID_AND_ATTRIBUTES*) TokenInformation ); break; case TokenImpersonationLevel: FIXME("UNIMPLEMENTED: TokenImpersonationLevel\n"); return STATUS_INVALID_INFO_CLASS; case TokenStatistics: TRACE("TokenStatistics\n"); len = sizeof stats; if (len != TokenInformationLength) return STATUS_INFO_LENGTH_MISMATCH; memset( &stats, 0, sizeof stats ); r = CopyToUser( TokenInformation, &stats, sizeof stats ); if (r < STATUS_SUCCESS) return r; break; case TokenGroups: TRACE("TokenGroups\n"); len = token->GetGroups().GetLength(); if (len > TokenInformationLength) { r = STATUS_BUFFER_TOO_SMALL; break; } r = token->GetGroups().CopyToUser( (TOKEN_GROUPS*) TokenInformation ); break; case TokenRestrictedSids: TRACE("TokenRestrictedSids\n"); len = token->GetRestrictedSids().GetLength(); if (len > TokenInformationLength) { r = STATUS_BUFFER_TOO_SMALL; break; } r = token->GetGroups().CopyToUser((TOKEN_GROUPS*)TokenInformation); break; default: FIXME("UNIMPLEMENTED: info class %d\n", TokenInformationClass); return STATUS_INVALID_INFO_CLASS; } if (ReturnLength) CopyToUser( ReturnLength, &len, sizeof len ); return r; }
NTSTATUS NTAPI NtAdjustPrivilegesToken( HANDLE TokenHandle, BOOLEAN DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, ULONG BufferLength, PTOKEN_PRIVILEGES PreviousState, PULONG ReturnLength ) { NTSTATUS r; TRACE("%p %u %p %lu %p %p\n", TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength ); if (ReturnLength) { r = VerifyForWrite( ReturnLength, sizeof *ReturnLength ); if (r < STATUS_SUCCESS) return r; } if (!NewState) return STATUS_INVALID_PARAMETER; // getting the old state requires query rights ACCESS_MASK mask = TOKEN_ADJUST_PRIVILEGES; if (PreviousState) mask |= TOKEN_QUERY; TOKEN *token = 0; r = ObjectFromHandle( token, TokenHandle, mask ); if (r < STATUS_SUCCESS) return r; CTOKEN_PRIVILEGES privs; r = privs.CopyFromUser( NewState ); if (r < STATUS_SUCCESS) return r; // return previous state information if required if (PreviousState) { CTOKEN_PRIVILEGES& prev_state = token->GetPrivs(); ULONG len = prev_state.GetLength(); TRACE("old privs %ld bytes\n", len); prev_state.Dump(); if (len > BufferLength) return STATUS_BUFFER_TOO_SMALL; r = prev_state.CopyToUser( PreviousState ); if (r < STATUS_SUCCESS) return r; r = CopyToUser( ReturnLength, &len, sizeof len ); assert( r == STATUS_SUCCESS ); } r = token->Adjust( privs ); TRACE("new privs\n"); privs.Dump(); return r; }
MonoObject* mono_gc_weak_link_get (void **link_addr) { return ObjectFromHandle((OBJECTHANDLE)*link_addr); }
VOID ComCallWrapper::InvokeByNameCallback(LPVOID ptr) { InvokeByNameArgs* args = (InvokeByNameArgs*)ptr; INT32 NumByrefArgs = 0; INT32 *aByrefArgMngVariantIndex = NULL; INT32 iArg; struct __gc { OBJECTREF Target; STRINGREF MemberName; PTRARRAYREF ParamArray; OBJECTREF TmpObj; OBJECTREF RetVal; } gc; ZeroMemory(&gc, sizeof(gc)); GCPROTECT_BEGIN(gc); gc.MemberName = COMString::NewString(args->MemberName); gc.ParamArray = (PTRARRAYREF)AllocateObjectArray(args->ArgCount, g_pObjectClass); // // Fill in the arguments. // for (iArg = 0; iArg < args->ArgCount; iArg++) { // Convert the variant. VARIANT *pSrcOleVariant = &args->ArgList[iArg]; OleVariant::MarshalObjectForOleVariant(pSrcOleVariant, &gc.TmpObj); gc.ParamArray->SetAt(iArg, gc.TmpObj); // If the argument is byref then add it to the array of byref arguments. if (V_VT(pSrcOleVariant) & VT_BYREF) { if (aByrefArgMngVariantIndex == NULL) { aByrefArgMngVariantIndex = (INT32 *)_alloca(sizeof(INT32) * args->ArgCount); } aByrefArgMngVariantIndex[NumByrefArgs] = iArg; NumByrefArgs++; } } gc.Target = ObjectFromHandle(args->pThis->m_hThis); // // Invoke using IReflect::InvokeMember // EEClass *pClass = gc.Target->GetClass(); // Retrieve the method descriptor that will be called on. MethodDesc *pMD = GetInvokeMemberMD(); // Prepare the arguments that will be passed to Invoke. ARG_SLOT Args[] = { ObjToArgSlot(GetReflectionObject(pClass)), // IReflect ObjToArgSlot(gc.MemberName), // name (ARG_SLOT) args->BindingFlags, // invokeAttr ObjToArgSlot(GetOleAutBinder()),// binder ObjToArgSlot(gc.Target), // target ObjToArgSlot(gc.ParamArray), // args ObjToArgSlot(NULL), // modifiers ObjToArgSlot(NULL), // culture ObjToArgSlot(NULL) // namedParameters }; // Do the actual method invocation. MetaSig metaSig(pMD->GetSig(),pMD->GetModule()); gc.RetVal = ArgSlotToObj(pMD->Call(Args, &metaSig)); // // Convert the return value and the byref arguments. // // Convert all the ByRef arguments back. for (iArg = 0; iArg < NumByrefArgs; iArg++) { INT32 i = aByrefArgMngVariantIndex[iArg]; gc.TmpObj = gc.ParamArray->GetAt(i); OleVariant::MarshalOleRefVariantForObject(&gc.TmpObj, &args->ArgList[i]); } // Convert the return COM+ object to an OLE variant. if (args->pRetVal) OleVariant::MarshalOleVariantForObject(&gc.RetVal, args->pRetVal); GCPROTECT_END(); }
int main(int argc, char* argv[]) { // // Initialize system info // InitializeSystemInfo(); // // Initialize free object methodtable. The GC uses a special array-like methodtable as placeholder // for collected free space. // static MethodTable freeObjectMT; freeObjectMT.InitializeFreeObject(); g_pFreeObjectMethodTable = &freeObjectMT; // // Initialize handle table // if (!Ref_Initialize()) return -1; // // Initialize GC heap // GCHeap *pGCHeap = GCHeap::CreateGCHeap(); if (!pGCHeap) return -1; if (FAILED(pGCHeap->Initialize())) return -1; // // Initialize current thread // ThreadStore::AttachCurrentThread(false); // // Create a Methodtable with GCDesc // class My : Object { public: Object * m_pOther1; int dummy_inbetween; Object * m_pOther2; }; static struct My_MethodTable { // GCDesc CGCDescSeries m_series[2]; size_t m_numSeries; // The actual methodtable MethodTable m_MT; } My_MethodTable; // 'My' contains the MethodTable* size_t baseSize = sizeof(My); // GC expects the size of ObjHeader (extra void*) to be included in the size. baseSize = baseSize + sizeof(ObjHeader); // Add padding as necessary. GC requires the object size to be at least MIN_OBJECT_SIZE. My_MethodTable.m_MT.m_baseSize = max(baseSize, MIN_OBJECT_SIZE); My_MethodTable.m_MT.m_componentSize = 0; // Array component size My_MethodTable.m_MT.m_flags = MTFlag_ContainsPointers; My_MethodTable.m_numSeries = 2; // The GC walks the series backwards. It expects the offsets to be sorted in descending order. My_MethodTable.m_series[0].SetSeriesOffset(offsetof(My, m_pOther2)); My_MethodTable.m_series[0].SetSeriesCount(1); My_MethodTable.m_series[0].seriessize -= My_MethodTable.m_MT.m_baseSize; My_MethodTable.m_series[1].SetSeriesOffset(offsetof(My, m_pOther1)); My_MethodTable.m_series[1].SetSeriesCount(1); My_MethodTable.m_series[1].seriessize -= My_MethodTable.m_MT.m_baseSize; MethodTable * pMyMethodTable = &My_MethodTable.m_MT; // Allocate instance of MyObject Object * pObj = AllocateObject(pMyMethodTable); if (pObj == NULL) return -1; // Create strong handle and store the object into it OBJECTHANDLE oh = CreateGlobalHandle(pObj); if (oh == NULL) return -1; for (int i = 0; i < 1000000; i++) { Object * pBefore = ((My *)ObjectFromHandle(oh))->m_pOther1; // Allocate more instances of the same object Object * p = AllocateObject(pMyMethodTable); if (p == NULL) return -1; Object * pAfter = ((My *)ObjectFromHandle(oh))->m_pOther1; // Uncomment this assert to see how GC triggered inside AllocateObject moved objects around // assert(pBefore == pAfter); // Store the newly allocated object into a field using WriteBarrier WriteBarrier(&(((My *)ObjectFromHandle(oh))->m_pOther1), p); } // Create weak handle that points to our object OBJECTHANDLE ohWeak = CreateGlobalWeakHandle(ObjectFromHandle(oh)); if (ohWeak == NULL) return -1; // Destroy the strong handle so that nothing will be keeping out object alive DestroyGlobalHandle(oh); // Explicitly trigger full GC pGCHeap->GarbageCollect(); // Verify that the weak handle got cleared by the GC assert(ObjectFromHandle(ohWeak) == NULL); printf("Done\n"); return 0; }
// blocking NTSTATUS NTAPI NtRemoveIoCompletion( HANDLE IoCompletionHandle, PULONG IoCompletionKey, PULONG IoCompletionValue, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER TimeOut) { NTSTATUS r; TRACE("%p %p %p %p %p\n", IoCompletionHandle, IoCompletionKey, IoCompletionValue, IoStatusBlock, TimeOut); COMPLETION_PORT_IMPL *port = 0; r = ObjectFromHandle( port, IoCompletionHandle, IO_COMPLETION_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (IoCompletionKey) { r = VerifyForWrite( IoCompletionKey, sizeof *IoCompletionKey ); if (r < STATUS_SUCCESS) return r; } if (IoCompletionValue) { r = VerifyForWrite( IoCompletionValue, sizeof *IoCompletionValue ); if (r < STATUS_SUCCESS) return r; } if (IoStatusBlock) { r = VerifyForWrite( IoStatusBlock, sizeof *IoStatusBlock ); if (r < STATUS_SUCCESS) return r; } LARGE_INTEGER t; t.QuadPart = 0LL; if (TimeOut) { r = CopyFromUser( &t, TimeOut, sizeof t ); if (r < STATUS_SUCCESS) return r; TimeOut = &t; } ULONG key = 0, val = 0; IO_STATUS_BLOCK iosb; iosb.Status = 0; iosb.Information = 0; port->Remove( key, val, iosb.Status, iosb.Information, TimeOut ); if (IoCompletionKey) CopyToUser( IoCompletionKey, &key, sizeof key ); if (IoCompletionValue) CopyToUser( IoCompletionValue, &val, sizeof val ); if (IoStatusBlock) CopyToUser( IoStatusBlock, &iosb, sizeof iosb ); return r; }