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_corlib_native_System_Reflection_MethodBase::Invoke___OBJECT__OBJECT__SZARRAY_OBJECT( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    CLR_RT_HeapBlock&           obj     = stack.Arg1();
    CLR_RT_MethodDef_Instance   md;
    const CLR_RECORD_METHODDEF* mdR;
    CLR_RT_HeapBlock_Array*     pArray  = stack.Arg2().DereferenceArray();
    CLR_RT_HeapBlock*           args    = NULL;
    int                         numArgs = 0;
    CLR_RT_HeapBlock*           hbMeth  = stack.Arg0().Dereference();

    TINYCLR_CHECK_HRESULT(GetMethodDescriptor( stack, *hbMeth, md ));

    mdR = md.m_target;

    if(stack.m_customState == 0)
    {
        stack.m_customState = 1;

        if(pArray)
        {
            args    = (CLR_RT_HeapBlock*)pArray->GetFirstElement();
            numArgs =                    pArray->m_numOfElements;
        }

        TINYCLR_CHECK_HRESULT(stack.MakeCall( md, &obj, args, numArgs ));
    }
    else
    {                
        if(mdR->retVal != DATATYPE_VOID)
        {                    
            if(mdR->retVal < DATATYPE_I4)
            {
                stack.TopValue().ChangeDataType( mdR->retVal );
            }

            TINYCLR_CHECK_HRESULT(stack.TopValue().PerformBoxingIfNeeded());
        }
        else
        {               
            stack.SetResult_Object( NULL );
        }
    }

    TINYCLR_NOCLEANUP();
}
HRESULT Library_system_xml_native_System_Xml_XmlNameTable::Get___STRING__STRING( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_XmlNameTable* pThis;
    CLR_RT_HeapBlock_String*       ret  ;
    LPCSTR                         key  ;

    pThis = (CLR_RT_HeapBlock_XmlNameTable*)stack.This(); FAULT_ON_NULL(pThis);
    ret   = NULL;
    key   = stack.Arg1().RecoverString(); FAULT_ON_NULL(key);

    TINYCLR_CHECK_HRESULT(pThis->Add( key, hal_strlen_s( key ), ret, TRUE ));

    stack.SetResult_Object( ret );

    TINYCLR_NOCLEANUP();
}
HRESULT Library_system_xml_native_System_Xml_XmlNameTable::Add___STRING__STRING( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();

    CLR_RT_HeapBlock_XmlNameTable* pThis;
    CLR_RT_HeapBlock_String*       str  ;
    LPCSTR                         key  ;
    
    pThis = (CLR_RT_HeapBlock_XmlNameTable*)stack.This(); FAULT_ON_NULL(pThis);
    str   = stack.Arg1().DereferenceString();             FAULT_ON_NULL(str);
    key   = str->StringText();

    TINYCLR_CHECK_HRESULT(pThis->Add( key, hal_strlen_s( key ), str ));

    stack.SetResult_Object( str );

    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();
}
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_security_pkcs11_native_Microsoft_SPOT_Cryptoki_FindObjectEnum::FindObjects___SZARRAY_MicrosoftSPOTCryptokiCryptokiObject__I4( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER();
    CLR_RT_HeapBlock* pThis      = stack.This();
    CLR_RT_HeapBlock* pSession   = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_FindObjectEnum::FIELD__m_session].Dereference();
    CLR_RT_HeapBlock  ref, *pRef;
    CK_SESSION_HANDLE hSession;
    CK_ULONG          cntObj     = (CK_ULONG)stack.Arg1().NumericByRef().u4;
    CK_OBJECT_HANDLE  objs[128];
    CK_OBJECT_CLASS   objType = CKO_DATA;
    CLR_INT32         i;
    CLR_RT_TypeDef_Index objIndex = g_CLR_RT_WellKnownTypes.m_CryptokiObject;
    BOOL isKey = FALSE;
    CK_ATTRIBUTE      attribs[] =
    {
        { CKA_CLASS, &objType, sizeof(objType) },
    };

    FAULT_ON_NULL(pSession);

    if(cntObj > ARRAYSIZE(objs)) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);

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

    CRYPTOKI_CHECK_RESULT(stack, C_FindObjects(hSession, objs, cntObj, &cntObj ));

    CRYPTOKI_CHECK_RESULT(stack, C_GetAttributeValue(hSession, objs[0], attribs, ARRAYSIZE(attribs)));

    SwapEndianAndAssignIfBEc32(objType, objType);
    
    switch(objType)
    {
        case CKO_CERTIFICATE:
            objIndex = g_CLR_RT_WellKnownTypes.m_CryptokiCertificate;
            break;
    
        case CKO_PRIVATE_KEY:
        case CKO_PUBLIC_KEY:
        case CKO_SECRET_KEY:
        case CKO_OTP_KEY:
            objIndex = g_CLR_RT_WellKnownTypes.m_CryptoKey;
            isKey = TRUE;
            break;
    }

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(ref, (CLR_UINT32)cntObj, objIndex));

    if(cntObj == 0)
    {
        stack.SetResult_Object(ref.DereferenceArray());
        TINYCLR_SET_AND_LEAVE(S_OK);
    }

    pRef = (CLR_RT_HeapBlock*)ref.DereferenceArray()->GetFirstElement();

    for(i=0; i<(INT32)cntObj; i++)
    {
        CLR_RT_HeapBlock *pObject;        

        TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.NewObjectFromIndex( *pRef, objIndex ));

        pObject = pRef->Dereference();
        pObject[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiObject::FIELD__m_handle            ].SetInteger((CLR_INT32)objs[i]);
        pObject[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session         ].SetObjectReference(pSession);
        pObject[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_ownsSession     ].SetBoolean(false);
        pObject[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_isDisposed      ].SetBoolean(false);
        pObject[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_isSessionClosing].SetBoolean(false);

        if(isKey)
        {
            CK_ULONG keySize = (CK_ULONG)-1;
            CK_ULONG keyType = (CK_ULONG)-1;

            CK_ATTRIBUTE attribs[] =
            {
                { CKA_VALUE_BITS, &keySize, sizeof(keySize) },
                { CKA_KEY_TYPE  , &keyType, sizeof(keyType) },
            };

            pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_keyType].NumericByRef().s4 = SwapEndianIfBEc32(keyType);

            C_GetAttributeValue(hSession, objs[i], attribs, ARRAYSIZE(attribs));
            
            pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_length].NumericByRef().u4 = SwapEndianIfBEc32(keySize);

            switch(objType)
            {
                case CKO_PRIVATE_KEY:
                    pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_privateKeyHandle].NumericByRef().u4 = objs[i];
                    break;

                case CKO_PUBLIC_KEY:
                case CKO_SECRET_KEY:
                default:
                    pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_privateKeyHandle].NumericByRef().u4 = CK_OBJECT_HANDLE_INVALID;
                    break;
            }

        }
        else if(objType == CKO_CERTIFICATE)
        {
            CK_ULONG keySize   = (CK_ULONG)-1;
            CK_ULONG keyType   = (CK_ULONG)-1;
            BOOL     isPrivate = FALSE;
            
            CK_ATTRIBUTE attribs[] = 
            {
                { CKA_VALUE_BITS, &keySize, sizeof(keySize)},
                { CKA_KEY_TYPE  , &keyType, sizeof(keyType)},
                { CKA_PRIVATE   , &isPrivate, sizeof(isPrivate)},
            };

            C_GetAttributeValue(hSession, objs[i], attribs, ARRAYSIZE(attribs));            

            pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_keyType].NumericByRef().s4 = SwapEndianIfBEc32(keyType);

            pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_length].NumericByRef().u4 = SwapEndianIfBEc32(keySize);

            if(isPrivate == TRUE)
            {
                pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_privateKeyHandle].NumericByRef().u4 = objs[i];
            }
            else
            {
                pObject[Library_security_pkcs11_native_System_Security_Cryptography_CryptoKey::FIELD__m_privateKeyHandle].NumericByRef().u4 = CK_OBJECT_HANDLE_INVALID;
            }
        }

        pRef++;
    }

    stack.SetResult_Object(ref.DereferenceArray());

    TINYCLR_NOCLEANUP();
}