HRESULT Interop_Marshal_double( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, double &param )         
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_R8);
    param = stackFrame.ArgN( paramIndex ).NumericByRef().r8;
    TINYCLR_INTEROP_NOCLEANUP();
}
HRESULT Interop_Marshal_StoreRef( CLR_RT_StackFrame &stackFrame, void *pVoidHeapBlock, UINT32 paramIndex )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();
    CLR_RT_HeapBlock *pHeapBlock = (CLR_RT_HeapBlock *)pVoidHeapBlock;
    TINYCLR_CHECK_HRESULT(pHeapBlock->StoreToReference( stackFrame.ArgN(paramIndex), 0 ));
    TINYCLR_NOCLEANUP();
}
HRESULT Interop_Marshal_UNSUPPORTED_TYPE_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UNSUPPORTED_TYPE *&pParam )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();
    TINYCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) ));
    pParam = NULL;
    TINYCLR_NOCLEANUP();
}
HRESULT Interop_Marshal_bool( const CLR_RT_StackFrame &stackFrame, UINT32 paramIndex, bool &param )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_INTEROP_CHECK_ARG_TYPE(DATATYPE_I4);
// The comparison with 0 converts numeric type "u1" to boolean type.
    param = stackFrame.ArgN( paramIndex ).NumericByRef().u1 != 0;
    TINYCLR_INTEROP_NOCLEANUP();
}
HRESULT Interop_Marshal_double_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT64* &pParam )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();
    TINYCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) ));
    TINYCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_R8)
    pParam = (INT64 *)&((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().r8;
    TINYCLR_NOCLEANUP();
}
HRESULT Interop_Marshal_INT8_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, INT8 *&pParam )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();
    TINYCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) ));
    // INT8 servers for both boolean and sbyte types. So we check for either of them.
#if defined(_DEBUG)
    if ( !( ((CLR_RT_HeapBlock *)pHeapBlock)->DataType() == DATATYPE_I1 ||
            ((CLR_RT_HeapBlock *)pHeapBlock)->DataType() == DATATYPE_BOOLEAN )
       )
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
    }
#endif
    pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().s1;
    TINYCLR_NOCLEANUP();
}
//------------------ Unsigned Integral types ----------------------------------------------------------------------------
HRESULT Interop_Marshal_bool_ByRef( const CLR_RT_StackFrame &stackFrame, void *pHeapBlock, UINT32 paramIndex, UINT8 *&pParam )
{
    NATIVE_PROFILE_CLR_CORE();
    // Declare hRes ( #define TINYCLR_HEADER() HRESULT hr )
    TINYCLR_HEADER();

    // Loads heapblock data from heapblock in managed stack frame
    TINYCLR_CHECK_HRESULT(((CLR_RT_HeapBlock *)pHeapBlock)->LoadFromReference( stackFrame.ArgN(paramIndex) ));

    // Validates that data in heapblock correspond to requested parameter.
    TINYCLR_INTEROP_CHECK_REF_TYPE(DATATYPE_U1)

    // Now we have initialized pHeapBlock with reference paramenter.
    // Need to cast the pointer because &s1 is "CLR_INT8 *", while we need "UINT8 *"
    pParam = &((CLR_RT_HeapBlock *)pHeapBlock)->NumericByRef().u1;

    // Return S_OK or error if there is "go to" from TINYCLR_CHECK_HRESULT or TINYCLR_SET_AND_LEAVE
    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_hardware_native_Microsoft_SPOT_Hardware_HardwareProvider::NativeGetSerialPins___VOID__I4__BYREF_MicrosoftSPOTHardwareCpuPin__BYREF_MicrosoftSPOTHardwareCpuPin__BYREF_MicrosoftSPOTHardwareCpuPin__BYREF_MicrosoftSPOTHardwareCpuPin( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock  hbrxPin;
    CLR_RT_HeapBlock  hbtxPin;
    CLR_RT_HeapBlock  hbctsPin;
    CLR_RT_HeapBlock  hbrtsPin;

    CLR_UINT32 port, rxPin, txPin, ctsPin, rtsPin;

    port = stack.Arg1().NumericByRef().u4;

    rxPin  = (CLR_UINT32)-1; // GPIO_NONE
    txPin  = (CLR_UINT32)-1; // GPIO_NONE
    ctsPin = (CLR_UINT32)-1; // GPIO_NONE
    rtsPin = (CLR_UINT32)-1; // GPIO_NONE
    
    // COM ports are numbered from 0 up
    if(port >= CPU_USART_PortsCount())
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
    }
    
    ::CPU_USART_GetPins( port, rxPin, txPin, ctsPin, rtsPin );

    hbrxPin.SetInteger ( (CLR_INT32)rxPin  ); TINYCLR_CHECK_HRESULT(hbrxPin.StoreToReference ( stack.Arg2(),  0 ));
    hbtxPin.SetInteger ( (CLR_INT32)txPin  ); TINYCLR_CHECK_HRESULT(hbtxPin.StoreToReference ( stack.Arg3(),  0 ));
    hbctsPin.SetInteger( (CLR_INT32)ctsPin ); TINYCLR_CHECK_HRESULT(hbctsPin.StoreToReference( stack.Arg4(),  0 ));
    hbrtsPin.SetInteger( (CLR_INT32)rtsPin ); TINYCLR_CHECK_HRESULT(hbrtsPin.StoreToReference( stack.ArgN(5), 0 ));
    

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_native_Microsoft_SPOT_Net_SocketNative::SendRecvHelper( CLR_RT_StackFrame& stack, bool fSend, bool fAddress )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       socket    = stack.Arg0().Dereference();
    CLR_INT32               handle;
    CLR_RT_HeapBlock_Array* arrData   = stack.Arg1().DereferenceArray(); 
    CLR_UINT32              offset    = stack.Arg2().NumericByRef().u4;
    CLR_UINT32              count     = stack.Arg3().NumericByRef().u4;
    CLR_INT32               flags     = stack.Arg4().NumericByRef().s4;
    CLR_INT32               timeout_ms = stack.ArgN(5).NumericByRef().s4;
    CLR_RT_HeapBlock        hbTimeout;

    CLR_INT64* timeout;
    CLR_UINT8* buf;
    bool       fRes = true;
    CLR_INT32  totReadWrite;
    CLR_INT32  ret = 0;

    FAULT_ON_NULL(socket);
    handle = socket[ FIELD__m_Handle ].NumericByRef().s4;

    FAULT_ON_NULL(arrData);
    
    if(offset + count > arrData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_INDEX_OUT_OF_RANGE);    

    /* Because we could have been a rescheduled call due to a prior call that would have blocked, we need to see
     * if our handle has been shutdown before continuing. */
    if (handle == DISPOSED_HANDLE)
    {
        ThrowError( stack, CLR_E_OBJECT_DISPOSED );
        TINYCLR_SET_AND_LEAVE (CLR_E_PROCESS_EXCEPTION);
    }

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

    //
    // Push "totReadWrite" onto the eval stack.
    //
    if(stack.m_customState == 1)
    {
        stack.PushValueI4( 0 );
        
        stack.m_customState = 2;
    }

    totReadWrite = stack.m_evalStack[ 1 ].NumericByRef().s4;

    buf    = arrData->GetElement( offset + totReadWrite );
    count -= totReadWrite;

    while(count > 0)
    {
        CLR_INT32 bytes = 0;

        // first make sure we have data to read or ability to write
        while(fRes)
        {
            ret = Helper__SelectSocket( handle, fSend ? 1 : 0 );

            if(ret != 0) break;

            // 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 ));
        }

        // timeout expired
        if(!fRes)
        {
            ret = SOCK_SOCKET_ERROR;
            
            ThrowError( stack, SOCK_ETIMEDOUT );

            TINYCLR_SET_AND_LEAVE( CLR_E_PROCESS_EXCEPTION );
        }

        // socket is in the excepted state, so let's bail out
        if(SOCK_SOCKET_ERROR == ret)
        {
            break;
        }

        if(fAddress)
        {
            struct SOCK_sockaddr addr;
            CLR_UINT32 addrLen = sizeof(addr);
            CLR_RT_HeapBlock& blkAddr = stack.ArgN( 6 );

            if(fSend)
            {
                TINYCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, blkAddr ));
                
                bytes = SOCK_sendto( handle, (const char*)buf, count, flags, &addr, addrLen );
            }
            else
            {
                CLR_RT_HeapBlock* pBlkAddr = blkAddr.Dereference();
                
                TINYCLR_CHECK_HRESULT(MarshalSockAddress( &addr, addrLen, *pBlkAddr ));

                bytes = SOCK_recvfrom( handle, (char*)buf, count, flags, &addr, (int*)&addrLen );

                if(bytes != SOCK_SOCKET_ERROR)
                {
                    TINYCLR_CHECK_HRESULT(MarshalSockAddress( blkAddr, &addr, addrLen ));
                }
            }
        }
        else
        {
            if(fSend)
            {
                bytes = SOCK_send( handle, (const char*)buf, count, flags );
            }
            else
            {
                bytes = SOCK_recv( handle, (char*)buf, count, flags );
            }
        }

        // send/recv/sendto/recvfrom failed
        if(bytes == SOCK_SOCKET_ERROR)
        {
            CLR_INT32 err = SOCK_getlasterror();
            
            if(err != SOCK_EWOULDBLOCK)
            {
                ret = SOCK_SOCKET_ERROR;
                break;
            }
            
            continue;
        }
                // zero recv bytes indicates the handle has been closed.
        else if(!fSend && (bytes == 0)) 
        {
            break;
        }
        
        buf          += bytes;
        totReadWrite += bytes;
        count        -= bytes;

        stack.m_evalStack[ 1 ].NumericByRef().s4 = totReadWrite;        

        // receive returns immediately after receiving bytes.
        if(!fSend && (totReadWrite > 0))
        {
            break;
        }

    }

    stack.PopValue();       // totReadWrite
    stack.PopValue();       // Timeout
    
    TINYCLR_CHECK_HRESULT(ThrowOnError( stack, ret ));

    stack.SetResult_I4( totReadWrite );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_net_security_native_Microsoft_SPOT_Net_Security_SslNative::ParseCertificate___STATIC__VOID__SZARRAY_U1__STRING__BYREF_STRING__BYREF_STRING__BYREF_mscorlibSystemDateTime__BYREF_mscorlibSystemDateTime( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_NETWORK();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_Array* arrData    = stack.Arg0().DereferenceArray(); 
    CLR_UINT8*              certBytes;
    CLR_RT_HeapBlock        hbIssuer;
    CLR_RT_HeapBlock        hbSubject;
    CLR_RT_ProtectFromGC    gc1( hbIssuer  );
    CLR_RT_ProtectFromGC    gc2( hbSubject );
    X509CertData            cert;
    CLR_INT64*              val;
    CLR_INT64               tzOffset;
    SYSTEMTIME              st;
    INT32                   standardBias;
    CLR_RT_HeapBlock*       hbPwd     = stack.Arg1().DereferenceString();
    LPCSTR                  szPwd;


    FAULT_ON_NULL_ARG(hbPwd);

    szPwd = hbPwd->StringText();

    CLR_RT_Memory::ZeroFill( &cert, sizeof(cert) );

    FAULT_ON_NULL(arrData);

    certBytes = arrData->GetFirstElement();

    if(!SSL_ParseCertificate( (const char*)certBytes, arrData->m_numOfElements, szPwd, &cert )) TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbIssuer, cert.Issuer ));
    TINYCLR_CHECK_HRESULT(hbIssuer.StoreToReference( stack.Arg2(), 0 ));

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_String::CreateInstance( hbSubject, cert.Subject ));
    TINYCLR_CHECK_HRESULT(hbSubject.StoreToReference( stack.Arg3(), 0 ));

    st.wYear         = cert.EffectiveDate.year;
    st.wMonth        = cert.EffectiveDate.month;
    st.wDay          = cert.EffectiveDate.day;
    st.wHour         = cert.EffectiveDate.hour;
    st.wMinute       = cert.EffectiveDate.minute;
    st.wSecond       = cert.EffectiveDate.second;
    st.wMilliseconds = cert.EffectiveDate.msec;

    standardBias     = Time_GetTimeZoneOffset();
    standardBias    *= TIME_CONVERSION__ONEMINUTE;

    val = Library_corlib_native_System_DateTime::GetValuePtr( stack.Arg4() );
    *val = Time_FromSystemTime( &st );

    tzOffset = cert.EffectiveDate.tzOffset;

    // adjust for timezone differences
    if(standardBias != tzOffset)
    {
        *val += tzOffset - standardBias; 
    }

    st.wYear         = cert.ExpirationDate.year;
    st.wMonth        = cert.ExpirationDate.month;
    st.wDay          = cert.ExpirationDate.day;
    st.wHour         = cert.ExpirationDate.hour;
    st.wMinute       = cert.ExpirationDate.minute;
    st.wSecond       = cert.ExpirationDate.second;
    st.wMilliseconds = cert.ExpirationDate.msec;
    
    val = Library_corlib_native_System_DateTime::GetValuePtr( stack.ArgN( 5 ) );
    *val = Time_FromSystemTime( &st );

    tzOffset = cert.ExpirationDate.tzOffset;
    
    if(standardBias != tzOffset)
    {
       *val += tzOffset - standardBias; 
    }

    TINYCLR_NOCLEANUP();
}