HRESULT Library_spot_native_Microsoft_SPOT_Hardware_Utility::CombineArrays( CLR_RT_StackFrame& stack, CLR_RT_HeapBlock& ref1, int offset1, int count1, CLR_RT_HeapBlock& ref2, int offset2, int count2 )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* array1;
    CLR_RT_HeapBlock_Array* array2;

    array1 = ref1.DereferenceArray(); FAULT_ON_NULL(array1);
    array2 = ref2.DereferenceArray(); FAULT_ON_NULL(array2);

    if(array1->SameHeader( *array2 ) == false)
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
    }

    if(count1 < 0) count1 = array1->m_numOfElements;
    if(count2 < 0) count2 = array2->m_numOfElements;

    {
        CLR_RT_HeapBlock& ref = stack.PushValue();

        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, count1 + count2, array1->ReflectionDataConst() ));

        TINYCLR_CHECK_HRESULT(Library_corlib_native_System_Array::Copy( stack, ref1, offset1, ref,      0, count1 ));
        TINYCLR_CHECK_HRESULT(Library_corlib_native_System_Array::Copy( stack, ref2, offset2, ref, count1, count2 ));
    }

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Decryptor::TransformFinalBlockInternal___SZARRAY_U1__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis     = stack.This();
    CLR_RT_HeapBlock_Array* pData     = stack.Arg1().DereferenceArray(); 
    CLR_INT32               offset    = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len       = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession  = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CLR_UINT32              decrSize  = 0;
    CK_SESSION_HANDLE       hSession;
    CLR_RT_HeapBlock        hbRef;
    CLR_RT_HeapBlock*       pRet;
    CLR_UINT32              maxOut;

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL_ARG(pSession);

    if((offset + len) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession  = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    CRYPTOKI_CHECK_RESULT(stack, C_Decrypt(hSession, pData->GetElement(offset), len, NULL, (CK_ULONG_PTR)&decrSize));

    maxOut = decrSize;

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(hbRef, decrSize, g_CLR_RT_WellKnownTypes.m_UInt8));

    CRYPTOKI_CHECK_RESULT(stack, C_Decrypt(hSession, pData->GetElement(offset), len, hbRef.DereferenceArray()->GetFirstElement(), (CK_ULONG_PTR)&decrSize));

    if(decrSize < maxOut)
    {
        CLR_RT_HeapBlock refSmall;
        
        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(refSmall, decrSize, g_CLR_RT_WellKnownTypes.m_UInt8));

        memcpy(refSmall.DereferenceArray()->GetFirstElement(), hbRef.DereferenceArray()->GetFirstElement(), decrSize);

        pRet = refSmall.Dereference();
    }
    else
    {
        pRet = hbRef.Dereference();
    }

    stack.SetResult_Object(pRet);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::MarshalSockAddress( struct SOCK_sockaddr* addrDst, CLR_UINT32& addrLen, const CLR_RT_HeapBlock& blkSockAddress )
{        
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* ptrSockAddress;
    SOCK_sockaddr_in* dst = (SOCK_sockaddr_in*)addrDst;
    SOCK_sockaddr_in* src;    

    ptrSockAddress = blkSockAddress.DereferenceArray();                    
    FAULT_ON_NULL(ptrSockAddress);

    if(ptrSockAddress->m_numOfElements > addrLen) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    src = (SOCK_sockaddr_in*)ptrSockAddress->GetFirstElement();

    dst->sin_family           = SwapEndianIfBEc16(src->sin_family);
    dst->sin_port             = src->sin_port;
    dst->sin_addr.S_un.S_addr = src->sin_addr.S_un.S_addr; //already in network byte order

    memcpy(dst->sin_zero, src->sin_zero, sizeof(dst->sin_zero));

    addrLen = ptrSockAddress->m_numOfElements;

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::MarshalSockAddress( CLR_RT_HeapBlock& blkDst, const struct SOCK_sockaddr* addrSrc, CLR_UINT32 addrLenSrc )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* arr = NULL;

    CLR_RT_HeapBlock blkArr; blkArr.SetObjectReference( NULL );
    CLR_RT_ProtectFromGC gc( blkArr );
    SOCK_sockaddr_in* dst;
    SOCK_sockaddr_in* src = (SOCK_sockaddr_in*)addrSrc;
        
    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( blkArr, addrLenSrc, g_CLR_RT_WellKnownTypes.m_UInt8 ));
    
    arr = blkArr.DereferenceArray();

    _ASSERTE(arr);

    dst = (SOCK_sockaddr_in*)arr->GetFirstElement();

    dst->sin_family           = SwapEndianIfBEc16(src->sin_family);
    dst->sin_port             = src->sin_port;
    dst->sin_addr.S_un.S_addr = src->sin_addr.S_un.S_addr;

    memcpy(dst->sin_zero, src->sin_zero, sizeof(dst->sin_zero));

    _ASSERTE(blkDst.DataType() == DATATYPE_BYREF || blkDst.DataType() == DATATYPE_ARRAY_BYREF);

    TINYCLR_CHECK_HRESULT(blkArr.StoreToReference( blkDst, 0 ));

    TINYCLR_NOCLEANUP();
}
Ejemplo n.º 5
0
HRESULT CLR_RT_HeapBlock_MemoryStream::ToArray( CLR_RT_HeapBlock& ref )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_UINT32              tot;
    CLR_RT_HeapBlock_Array* array;
    CLR_UINT8*              buf;

    tot = 0;
    TINYCLR_FOREACH_NODE(Buffer,node,m_buffers)
    {
        tot += node->m_length;
    }
    TINYCLR_FOREACH_NODE_END();

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, tot, g_CLR_RT_WellKnownTypes.m_UInt8 ));

    array = ref.DereferenceArray();
    buf   = array->GetFirstElement();

    TINYCLR_FOREACH_NODE(Buffer,node,m_buffers)
    {
        memcpy( buf, node->m_payload, node->m_length ); buf += node->m_length;
    }
Ejemplo n.º 6
0
HRESULT CLR_RT_HeapBlock_XmlNameTable::Grow()
{
    TINYCLR_HEADER();
    
    CLR_RT_HeapBlock_Array*              oldEntries;
    CLR_RT_HeapBlock                     newEntriesHB;
    CLR_RT_HeapBlock_Array*              newEntries;
    CLR_RT_HeapBlock_XmlNameTable_Entry* entry;
    CLR_RT_HeapBlock_XmlNameTable_Entry* next;
    CLR_RT_HeapBlock*                    newEntryHB;

    CLR_UINT32                           i;
    CLR_INT32                            newIndex;
    CLR_INT32                            newMask;

    newMask = GetMask() * 2 + 1;

    // allocate a new instance of Entry array
    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( newEntriesHB, newMask + 1, g_CLR_RT_WellKnownTypes.m_XmlNameTable_Entry ));

    newEntries = newEntriesHB.DereferenceArray();
    oldEntries = GetEntries();

    // Go through the old buckets, and resort them
    for(i = 0; i < oldEntries->m_numOfElements; i++)
    {
        entry = (CLR_RT_HeapBlock_XmlNameTable_Entry*)((CLR_RT_HeapBlock*)oldEntries->GetElement( i ))->Dereference();
    
        while(entry != NULL)
        {
            newIndex = entry->GetHashCode() & newMask;
            next = entry->GetNext();
    
            newEntryHB = (CLR_RT_HeapBlock*)newEntries->GetElement( newIndex );
    
            entry->SetNext( (CLR_RT_HeapBlock_XmlNameTable_Entry*)newEntryHB->Dereference() );
    
            newEntryHB->SetObjectReference( entry );
    
            entry = next;
        }
    }

    SetEntries( newEntries );
    SetMask   ( newMask    );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiSign::SignInternal___SZARRAY_U1__SZARRAY_U1__I4__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis    = stack.This();
    CLR_RT_HeapBlock_Array* pData    = stack.Arg1().DereferenceArray();
    CLR_RT_HeapBlock_Array* pRes;
    CLR_INT32               offset   = stack.Arg2().NumericByRef().s4;
    CLR_INT32               len      = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    CK_ULONG                sigLen   = 0;
    CLR_RT_HeapBlock        hbRef;

    FAULT_ON_NULL(pSession);
    FAULT_ON_NULL_ARG(pData);

    if((offset + len) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4;

    if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);

    CRYPTOKI_CHECK_RESULT(stack, C_Sign(hSession, pData->GetElement(offset), len, NULL, (CK_ULONG_PTR)&sigLen));

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(hbRef, sigLen, g_CLR_RT_WellKnownTypes.m_UInt8));

    pRes = hbRef.DereferenceArray();

    CRYPTOKI_CHECK_RESULT(stack, C_Sign(hSession, pData->GetElement(offset), len, pRes->GetFirstElement(), (CK_ULONG_PTR)&sigLen));

    if(sigLen < pRes->m_numOfElements)
    {
        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValue(), sigLen, g_CLR_RT_WellKnownTypes.m_UInt8));

        memcpy(stack.TopValue().DereferenceArray()->GetFirstElement(), pRes->GetFirstElement(), sigLen);
    }
    else
    {
        stack.SetResult_Object(pRes);
    }

    TINYCLR_NOCLEANUP();
}
// May Trigger GC, but parameter value will be protected
HRESULT CLR_RT_HeapBlock_Queue::Enqueue( CLR_RT_HeapBlock* value )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* array    = GetArray();
    CLR_INT32               size     = GetSize();
    CLR_INT32               tail     = GetTail();
    CLR_INT32               capacity = array->m_numOfElements;

    if(size == capacity)
    {
        // Set new capacity
        CLR_RT_HeapBlock newArrayHB;
        
        // Protect value from GC, in case CreateInstance triggers one
        CLR_RT_HeapBlock valueHB; valueHB.SetObjectReference( value );
        CLR_RT_ProtectFromGC gc( valueHB );

        capacity *= 2;

        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( newArrayHB, capacity, g_CLR_RT_WellKnownTypes.m_Object ));

        array = newArrayHB.DereferenceArray();

        CopyTo( array, 0 );

        tail = size;

        SetArray( array );
        SetHead ( 0     );
        SetTail ( tail  );
    }

    ((CLR_RT_HeapBlock*)array->GetElement( tail ))->SetObjectReference( value );

    SetTail( (tail + 1) % capacity );

    SetSize( size + 1 );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::MarshalSockAddress( struct SOCK_sockaddr* addrDst, CLR_UINT32& addrLen, const CLR_RT_HeapBlock& blkSockAddress )
{        
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* ptrSockAddress;

    ptrSockAddress = blkSockAddress.DereferenceArray();                    
    FAULT_ON_NULL(ptrSockAddress);

    if(ptrSockAddress->m_numOfElements > addrLen) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    memcpy( addrDst, ptrSockAddress->GetFirstElement(), ptrSockAddress->m_numOfElements );

    addrLen = ptrSockAddress->m_numOfElements;

    _ASSERTE(addrDst->sa_family == SOCK_AF_INET);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_update_native_Microsoft_SPOT_MFUpdate_MFNativeUpdate::GetUpdateProperty___STATIC__BOOLEAN__I4__STRING__BYREF_SZARRAY_U1( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_INT32  handle = stack.Arg0().NumericByRef().s4;
    LPCSTR szProperty = stack.Arg1().StringText(); 
    CLR_RT_HeapBlock* pRef;
    CLR_RT_HeapBlock_Array* pData;
    int dataLen;

    FAULT_ON_NULL(szProperty);

    pRef    = stack.Arg2().Dereference();  FAULT_ON_NULL_ARG(pRef);
    pData   = pRef->DereferenceArray();    FAULT_ON_NULL_ARG(pData);
    dataLen = pData->m_numOfElements;

    stack.SetResult_Boolean(TRUE == MFUpdate_GetProperty(handle, szProperty, pData->GetFirstElement(), &dataLen));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_native_Microsoft_SPOT_CryptoState::Buffer::Allocate( CLR_RT_HeapBlock& ref, int size )
{
    TINYCLR_HEADER();

    ref.SetObjectReference( NULL );

    if(size)
    {
        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ref, size, g_CLR_RT_WellKnownTypes.m_UInt8 ));

        m_array = ref.DereferenceArray();
    }
    else
    {
        m_array = NULL;
    }

    m_offset = 0;
    m_count  = size;

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Cryptoki::GetSlotsInternal___STATIC__SZARRAY_MicrosoftSPOTCryptokiSlot( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CK_ULONG                i;
    CK_SLOT_ID              slots[NETMF_CRYPTOKI_MAX_SLOTS];
    CK_ULONG                count = NETMF_CRYPTOKI_MAX_SLOTS;
    CLR_RT_HeapBlock_Array* pSlots;
    CLR_RT_HeapBlock        ref;
    CLR_RT_HeapBlock*       pSlotRef;

    CRYPTOKI_CHECK_RESULT(stack, C_GetSlotList(CK_FALSE, slots, &count));

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(ref, (CLR_UINT32)count, g_CLR_RT_WellKnownTypes.m_CryptokiSlot));

    pSlots = ref.DereferenceArray();

    pSlotRef = (CLR_RT_HeapBlock*)pSlots->GetFirstElement();
            
    for(i=0; i<count; i++)
    {
        CLR_RT_HeapBlock* pSlot;
        
        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( pSlotRef[i], g_CLR_RT_WellKnownTypes.m_CryptokiSlot ));

        pSlot = pSlotRef[i].Dereference();
      
        pSlot[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Slot::FIELD__m_slotIndex    ].SetInteger        ((CLR_INT32)slots[i]);
        pSlot[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Slot::FIELD__m_disposed     ].SetBoolean        (false              );
        pSlot[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Slot::FIELD__m_evtDispatcher].SetObjectReference(NULL               );
        pSlot[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Slot::FIELD__m_slotEvent    ].SetObjectReference(NULL               );
        pSlot[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Slot::FIELD__m_slotInfo     ].SetObjectReference(NULL               );
    }

    stack.SetResult_Object(pSlots);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_corlib_native_System_Text_UTF8Encoding::Helper__GetChars(CLR_RT_StackFrame& stack, bool fIndexed)
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    LPSTR szText;
    CLR_RT_HeapBlock ref;
    ref.SetObjectReference( NULL );
    CLR_RT_ProtectFromGC gc( ref );
    CLR_RT_HeapBlock_Array* pArrayBytes = stack.Arg1().DereferenceArray();
    CLR_INT32               byteIdx     = fIndexed ? stack.Arg2().NumericByRef().s4 : 0;
    CLR_INT32               byteCnt     = fIndexed ? stack.Arg3().NumericByRef().s4 : pArrayBytes->m_numOfElements;
    CLR_RT_HeapBlock_Array* pArrayBytesCopy;
    CLR_RT_HeapBlock_Array* arrTmp;
    int cBytesCopy;

    FAULT_ON_NULL(pArrayBytes);

    _ASSERTE(pArrayBytes->m_typeOfElement == DATATYPE_U1);

    if((byteIdx + byteCnt) > (CLR_INT32)pArrayBytes->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    cBytesCopy = byteCnt+1;

    /* Copy the array to a temporary buffer to create a zero-terminated string */
    TINYCLR_CHECK_HRESULT( CLR_RT_HeapBlock_Array::CreateInstance( ref, cBytesCopy, g_CLR_RT_WellKnownTypes.m_UInt8 ));

    pArrayBytesCopy = ref.DereferenceArray();
    szText = (LPSTR)pArrayBytesCopy->GetFirstElement();

    hal_strncpy_s( szText, cBytesCopy, (LPSTR)pArrayBytes->GetElement(byteIdx), byteCnt );

    TINYCLR_CHECK_HRESULT(Library_corlib_native_System_String::ConvertToCharArray( szText, stack.PushValueAndClear(), arrTmp, 0, -1 ));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::MarshalSockAddress( CLR_RT_HeapBlock& blkDst, const struct SOCK_sockaddr* addrSrc, CLR_UINT32 addrLenSrc )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* arr = NULL;

    CLR_RT_HeapBlock blkArr; blkArr.SetObjectReference( NULL );
    CLR_RT_ProtectFromGC gc( blkArr );
        
    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( blkArr, addrLenSrc, g_CLR_RT_WellKnownTypes.m_UInt8 ));
    
    arr = blkArr.DereferenceArray();

    _ASSERTE(arr);

    memcpy( arr->GetFirstElement(), addrSrc, addrLenSrc );

    _ASSERTE(blkDst.DataType() == DATATYPE_BYREF || blkDst.DataType() == DATATYPE_ARRAY_BYREF);

    TINYCLR_CHECK_HRESULT(blkArr.StoreToReference( blkDst, 0 ));

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::getaddrinfo___STATIC__VOID__STRING__BYREF_STRING__BYREF_SZARRAY_SZARRAY_U1( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    LPCSTR szName = stack.Arg0().RecoverString();
    struct SOCK_addrinfo hints;
    struct SOCK_addrinfo* addr = NULL;
    struct SOCK_addrinfo* addrT;
    CLR_UINT32        cAddresses = 0;
    CLR_RT_HeapBlock* pAddress;
    CLR_INT32         timeout_ms = 30000;
    CLR_RT_HeapBlock  hbTimeout;
    CLR_INT32         ret;
    bool              fRes = true;
    CLR_INT64*        timeout;

    hbTimeout.SetInteger( timeout_ms );

    TINYCLR_CHECK_HRESULT(stack.SetupTimeout( hbTimeout, timeout ));

    do
    {
        memset( &hints, 0, sizeof(hints) );

        ret = SOCK_getaddrinfo( szName, NULL, &hints, &addr );

        if(ret == SOCK_SOCKET_ERROR)
        {
            if(SOCK_getlasterror() == SOCK_EWOULDBLOCK)
            {
                // non-blocking - allow other threads to run while we wait for handle activity
                TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.WaitEvents( stack.m_owningThread, *timeout, CLR_RT_ExecutionEngine::c_Event_Socket, fRes ));
            }
            else
            {
                break;
            }
        }
        else
        {
            break;
        }
    }
    while(fRes);
    
    // timeout expired
    if(!fRes)
    {
        ret = SOCK_SOCKET_ERROR;
        
        ThrowError( stack, SOCK_ETIMEDOUT );
    
        TINYCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION );
    }

    // getaddrinfo returns a winsock error code rather than SOCK_SOCKET_ERROR, so pass this on to the exception handling
    if(ret != 0)
    {
        ThrowError( stack, ret );
        TINYCLR_SET_AND_LEAVE(CLR_E_PROCESS_EXCEPTION);
    }

    {
        CLR_RT_HeapBlock  hbCanonicalName;
        CLR_RT_HeapBlock  hbAddresses;
        
        hbCanonicalName.SetObjectReference( NULL );
        CLR_RT_ProtectFromGC gc( hbCanonicalName );

        hbAddresses.SetObjectReference( NULL );
        CLR_RT_ProtectFromGC gc2( hbAddresses );

        for(int pass = 0; pass < 2; pass++)
        {                                    
            cAddresses = 0;

            for(addrT = addr; addrT != NULL; addrT = addrT->ai_next)
            {
                if(pass == 1)
                {
                    if(addrT->ai_canonname && addrT->ai_canonname[ 0 ])
                    {
                        //allocate return string
                        TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbCanonicalName, addrT->ai_canonname ));
                        TINYCLR_CHECK_HRESULT(hbCanonicalName.StoreToReference( stack.Arg1(), 0 ));
                    }

                    //allocate address and store into array
                    pAddress = (CLR_RT_HeapBlock*)hbAddresses.DereferenceArray()->GetElement( cAddresses );

                    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( *pAddress, (CLR_UINT32)addrT->ai_addrlen, g_CLR_RT_WellKnownTypes.m_UInt8 ));

                    //copy address.
                    memcpy( pAddress->DereferenceArray()->GetFirstElement(), addrT->ai_addr, addrT->ai_addrlen );
                }
                                
                cAddresses++;
            }
                            
            if(pass == 0)
            {
                //allocate array of byte arrays
                CLR_RT_ReflectionDef_Index idx;

                idx.m_kind               = REFLECTION_TYPE;
                idx.m_levels             = 2;
                idx.m_data.m_type.m_data = g_CLR_RT_WellKnownTypes.m_UInt8.m_data;

                TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( hbAddresses, cAddresses, idx ));

                TINYCLR_CHECK_HRESULT(hbAddresses.StoreToReference( stack.Arg2(), 0 ));                
            }
        }    
    }

    stack.PopValue();       // Timeout
    
    TINYCLR_CLEANUP();

    if( addr ) SOCK_freeaddrinfo( addr );

    TINYCLR_CLEANUP_END();
}