HRESULT Library_corlib_native_System_Text_UTF8Encoding::GetBytes___I4__STRING__I4__I4__SZARRAY_U1__I4( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    size_t                  cMaxBytes;
    LPCSTR                  str         = stack.Arg1().RecoverString();
    CLR_INT32               strIdx      = stack.Arg2().NumericByRef().s4;
    CLR_INT32               strCnt      = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock_Array* pArrayBytes = stack.Arg4().DereferenceArray();
    CLR_INT32               byteIdx     = stack.Arg5().NumericByRef().s4;

    FAULT_ON_NULL(str);
    FAULT_ON_NULL(pArrayBytes);

    cMaxBytes = hal_strlen_s(str);

    if((strIdx  + strCnt) > (CLR_INT32)cMaxBytes                   ) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
    if((byteIdx + strCnt) > (CLR_INT32)pArrayBytes->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    memcpy(pArrayBytes->GetElement(byteIdx), &str[strIdx], strCnt);

    stack.SetResult_I4(strCnt);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_spot_hardware_native_Microsoft_SPOT_Hardware_SPI::InternalWriteRead___VOID__SZARRAY_U2__I4__I4__SZARRAY_U2__I4__I4__I4( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_HARDWARE();
    TINYCLR_HEADER();
    {
        CLR_RT_HeapBlock*       pThis           = stack.This();                    FAULT_ON_NULL(pThis);
        CLR_RT_HeapBlock_Array* writeBuffer     = stack.Arg1().DereferenceArray(); FAULT_ON_NULL(writeBuffer);
        CLR_INT32               writeOffset     = stack.Arg2().NumericByRef().s4;
        CLR_INT32               writeCount      = stack.Arg3().NumericByRef().s4;
        CLR_RT_HeapBlock_Array* readBuffer      = stack.Arg4().DereferenceArray(); 
        CLR_INT32               readOffset      = stack.Arg5().NumericByRef().s4;
        CLR_INT32               readCount       = stack.Arg6().NumericByRef().s4;
        CLR_UINT32              startReadOffset = stack.Arg7().NumericByRef().s4;
        
        SPI_CONFIGURATION       config;
        TINYCLR_CHECK_HRESULT(Library_spot_hardware_native_Microsoft_SPOT_Hardware_SPI__Configuration::GetInitialConfig( pThis[ FIELD__m_config ], config ));

        config.MD_16bits = TRUE;

        CPU_SPI_Initialize();
        
        if(!::CPU_SPI_nWrite16_nRead16(
                                    config,
                                    (CLR_UINT16*)writeBuffer->GetElement(writeOffset), 
                                    writeCount,
                                    readBuffer == NULL ? NULL : (CLR_UINT16*)readBuffer ->GetElement(readOffset), 
                                    readBuffer == NULL ? 0    : readCount,
                                    startReadOffset
                                  ))
        {
            TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
        }
    }
    TINYCLR_NOCLEANUP();
}
// TODO: Make common functions for transformBlock for encrypt/decrypt when async logic is in place
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Decryptor::TransformBlockInternal___I4__SZARRAY_U1__I4__I4__SZARRAY_U1__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock*       pThis      = stack.This();
    CLR_RT_HeapBlock_Array* pData      = stack.Arg1().DereferenceArray(); 
    CLR_INT32               dataOffset = stack.Arg2().NumericByRef().s4;
    CLR_INT32               dataLen    = stack.Arg3().NumericByRef().s4;
    CLR_RT_HeapBlock_Array* pOutput    = stack.Arg4().DereferenceArray(); 
    CLR_INT32               outOffset  = stack.Arg5().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession   = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    CLR_UINT32              decrSize;   

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL_ARG(pOutput);
    FAULT_ON_NULL_ARG(pSession);

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

    if((dataOffset + dataLen) > (CLR_INT32)pData->m_numOfElements  ) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
    if((outOffset           ) > (CLR_INT32)pOutput->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

    decrSize = pOutput->m_numOfElements - outOffset;

    CRYPTOKI_CHECK_RESULT(stack, C_DecryptUpdate(hSession, pData->GetElement(dataOffset), dataLen, pOutput->GetElement(outOffset), (CK_ULONG_PTR)&decrSize));

    stack.SetResult_I4(decrSize);

    TINYCLR_NOCLEANUP();
}
HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiVerify::VerifyInternal___BOOLEAN__SZARRAY_U1__I4__I4__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_Array* pSig     = stack.Arg4().DereferenceArray(); 
    CLR_INT32               sigOff   = stack.Arg5().NumericByRef().s4;
    CLR_INT32               sigLen   = stack.Arg6().NumericByRef().s4;
    CLR_RT_HeapBlock*       pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference();
    CK_SESSION_HANDLE       hSession;
    bool                    retVal   = false;
    CK_RV                   result;

    FAULT_ON_NULL_ARG(pData);
    FAULT_ON_NULL_ARG(pSig);

    if((offset + len   ) > (CLR_INT32)pData->m_numOfElements) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
    if((sigOff + sigLen) > (CLR_INT32)pSig->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);

    result = C_Verify(hSession, pData->GetElement(offset), len, pSig->GetElement(sigOff), sigLen);

    retVal = CKR_OK == result;

    stack.SetResult_Boolean(retVal);

    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.Arg5().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.Arg6();

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