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();
}
static BOOL MFUpdate_SSL_GetDeviceCert( UINT8** caCert, UINT32* certLen )
{
    *caCert   = (UINT8*)s_SelfSignedCert;
    *certLen = hal_strlen_s(s_SelfSignedCert);

    return TRUE;
}
    // GenerateNextAvailableName will generate the next possible namespace
    // when the previous namespace is already taken. It does so by tagging
    // "_n"  to the end of the namespace where n is a number from 1 to 9
    // If the resulting namespace is longer than FS_NAME_DEFAULT_LENGTH, 
    // the namespace will be truncated to accomodate the _n.
    //
    // The result is in nextAvailableName field. The return value is true if it's successful.
    //
    // For example, if the namespace is originally "FLASH"
    // each subsequent call to GenerateNextAvailableName will generate the following:
    // "FLASH", "FLASH_1", "FLASH_2", "FLASH_3" .... "FLASH_9"
    //
    // Note that first time this is called, nextAvailableName is the originalName
    // given in Initialize()
    bool GenerateNextAvailableName()
    {
        if(iteration == 0) // the first time around, we use the original name
        {
            iteration++;
            return true;
        }
        else if (iteration == 1)
        {
            UINT32 digitPos = hal_strlen_s( nextAvailableName ) + 1;
            
            if(digitPos >= FS_NAME_DEFAULT_LENGTH)
            { // if suffix is too long, trim the namespace
                digitPos = FS_NAME_DEFAULT_LENGTH - 1;
            }

            digit = &(nextAvailableName[digitPos]);

            *(digit-1) = '_';
            *digit     = '1';

            iteration++;
        }
        else
        {
            // We only support _1 thru _9 for now, as it seems unlikely to need more
            if((*digit) == '9') return false;
            
            (*digit)++;
        }
        
        return true;
    }
HRESULT Library_corlib_native_System_Reflection_Assembly::get_FullName___STRING( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    //The defines for maxFULLNAME and parameters for snprintf are currently not validated.
    CLR_RT_Assembly_Instance instance;
    CLR_RT_Assembly*         assm;
    char                     buffer[ TINYCLR_MAX_ASSEMBLY_NAME * 2 ];
    const CLR_RECORD_ASSEMBLY* header ;


    TINYCLR_CHECK_HRESULT(GetTypeDescriptor( stack.Arg0(), instance ));
   
    assm                              = instance.m_assm;
    header = assm->m_header;

    if(hal_strlen_s(assm->m_szName) > TINYCLR_MAX_ASSEMBLY_NAME)
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
    }
    
    hal_snprintf( buffer, TINYCLR_MAX_ASSEMBLY_NAME * 2, 
                  "%s, Version=%d.%d.%d.%d", 
                  assm->m_szName, 
                  header->version.iMajorVersion, 
                  header->version.iMinorVersion, 
                  header->version.iBuildNumber, 
                  header->version.iRevisionNumber );
    
    stack.SetResult_String( buffer );

    TINYCLR_NOCLEANUP();
#undef MAXFULLNAME
}
BOOL Solution_GetReleaseInfo(MfReleaseInfo& releaseInfo)
{
    MfReleaseInfo::Init(releaseInfo,
                        VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION,
                        OEMSYSTEMINFOSTRING, hal_strlen_s(OEMSYSTEMINFOSTRING)
                        );
    return TRUE; // alternatively, return false if you didn't initialize the releaseInfo structure.
}
Exemple #6
0
BOOL Solution_GetReleaseInfo(MfReleaseInfo& releaseInfo)
{
    MfReleaseInfo::Init(releaseInfo,
                        4, 2, 2, 1,
                        OEMSYSTEMINFOSTRING, hal_strlen_s(OEMSYSTEMINFOSTRING)
                        );
    return TRUE; // alternatively, return false if you didn't initialize the releaseInfo structure.
}
Exemple #7
0
////////////////////////////////////////////////////////////////////////////////
// TinyBooter_GetOemInfo
//
// Return in version and oeminfostring the compile-time values of some OEM-specific
// data, which you provide in the ReleaseInfo.settings file to apply to all projects
// built in this Porting Kit, or in the settings file specific to this solution.
//
// The properties to set are 
//  MajorVersion, MinorVersion, BuildNumber, RevisionNumber, and OEMSystemInfoString.
// If OEMSystemInfoString is not provided, it will be created by concatenating your
// settings for MFCompanyName and MFCopyright, also defined in ReleaseInfo.settings
// or your solution's own settings file.
//
// It is typically not necessary actually to modify this function. If you do, note
// that the return value indicates to the caller whether the releaseInfo structure
// has been fully initialized and is valid. It is safe to return false if 
// there is no useful build information you wish to report.
////////////////////////////////////////////////////////////////////////////////
BOOL TinyBooter_GetReleaseInfo(MfReleaseInfo& releaseInfo)
{
    MfReleaseInfo::Init(
                    releaseInfo, 
                    VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION, 
                    OEMSYSTEMINFOSTRING, hal_strlen_s(OEMSYSTEMINFOSTRING)
                    );
    return TRUE;
}
HRESULT Library_spot_hardware_native_Microsoft_SPOT_Hardware_NativeEventDispatcher::_ctor___VOID__STRING__U8( CLR_RT_StackFrame& stack )
{
    TINYCLR_HEADER(); 

    CLR_RT_DriverInterruptMethods*          pDriverMethods;
    const CLR_RT_NativeAssemblyData*        pNativeDriverData;
    CLR_RT_HeapBlock_NativeEventDispatcher* pNativeDisp = NULL;
    
    LPCSTR                                  lpszDriverName;    
    UINT64                                  driverData;
    
    CLR_RT_HeapBlock*  pThis = stack.This();  FAULT_ON_NULL(pThis);
    
    // Retrieve paramenters; 
    if (stack.Arg1().DataType() != DATATYPE_OBJECT) 
    {   TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);                      
    }
    lpszDriverName = stack.Arg1().RecoverString();  FAULT_ON_NULL(lpszDriverName);

    driverData = stack.Arg2().NumericByRef().u8;

    // Throw NULL exception if string is empty. 
    if(hal_strlen_s( lpszDriverName ) == 0)
    {  
        TINYCLR_CHECK_HRESULT(CLR_E_ARGUMENT_NULL);
    }
    
    // Retrives pointers to driver implemented functions.
    pNativeDriverData = GetAssemblyNativeData( lpszDriverName );
    
    // Validates check sum and presence of the structure.
    if(pNativeDriverData == NULL || pNativeDriverData->m_checkSum != DRIVER_INTERRUPT_METHODS_CHECKSUM)
    {
       TINYCLR_CHECK_HRESULT(CLR_E_DRIVER_NOT_REGISTERED);
    }

    // Get pointer to CLR_RT_DriverInterruptMethods
    pDriverMethods = (CLR_RT_DriverInterruptMethods *)pNativeDriverData->m_pNativeMethods;
    // Check that all methods are present:
    if(pDriverMethods->m_InitProc == NULL || pDriverMethods->m_EnableProc == NULL || pDriverMethods->m_CleanupProc == NULL)
    {
       TINYCLR_CHECK_HRESULT(CLR_E_DRIVER_NOT_REGISTERED);
    }

    // So we found driver by name and now we create instance of CLR_RT_HeapBlock_NativeEventDispatcher
    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_NativeEventDispatcher::CreateInstance( *pThis, pThis[ FIELD__m_NativeEventDispatcher ] ));

    // Initialize the driver with and provide the instance of CLR_RT_HeapBlock_NativeEventDispatcher 
    TINYCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp ));

    // Now call the driver. First save pointer to driver data.
    pNativeDisp->m_DriverMethods = pDriverMethods;
    TINYCLR_CHECK_HRESULT(pDriverMethods->m_InitProc( pNativeDisp, driverData ));
    
    TINYCLR_NOCLEANUP();
}
////////////////////////////////////////////////////////////////////////////////
// TinyBooter_GetOemInfo
//
// Return in version and oeminfostring the compile-time values of some OEM-specific
// data, which you provide in the ReleaseInfo.settings file to apply to all projects
// built in this Porting Kit, or in the settings file specific to this solution.
//
// The properties to set are 
//  MajorVersion, MinorVersion, BuildNumber, RevisionNumber, and OEMSystemInfoString.
// If OEMSystemInfoString is not provided, it will be created by concatenating your
// settings for MFCompanyName and MFCopyright, also defined in ReleaseInfo.settings
// or your solution's own settings file.
//
// It is typically not necessary actually to modify this function. If you do, note
// that the return value indicates to the caller whether the releaseInfo structure
// has been fully initialized and is valid. It is safe to return false if 
// there is no useful build information you wish to report.
////////////////////////////////////////////////////////////////////////////////
BOOL TinyBooter_GetReleaseInfo(MfReleaseInfo& releaseInfo)
{
#undef OEMSTR(str)
#define OEMSTR(str) # str

    MfReleaseInfo::Init(
                    releaseInfo, 
                    VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION, 
                    OEMSTR(OEMSYSTEMINFOSTRING), hal_strlen_s(OEMSTR(OEMSYSTEMINFOSTRING))
                    );

    return TRUE;
}
BOOL HAL_CONFIG_BLOCK::Prepare( const char* Name, void* Data, UINT32 Size )
{
    if(Name == NULL || hal_strlen_s( Name ) >= sizeof(DriverName)) return FALSE;

    memset( this, 0, sizeof(*this) );

    this->Signature = c_Version_V2;
    this->DataCRC   = SUPPORT_ComputeCRC( Data, Size, 0 );
    this->Size      = Size;

    hal_strcpy_s( this->DriverName, ARRAYSIZE(this->DriverName), Name );

    this->HeaderCRC = SUPPORT_ComputeCRC( ((UINT8*)&DataCRC), sizeof(*this) - offsetof(HAL_CONFIG_BLOCK,DataCRC), c_Seed );

    return TRUE;
}
int hal_strcpy_s ( char* strDst, size_t sizeInBytes, const char* strSrc )
{
    NATIVE_PROFILE_PAL_CRT();
#undef strcpy

    size_t len;
    if(strDst == NULL || strSrc == NULL || sizeInBytes == 0) {_ASSERTE(FALSE); return 1;}
    
    len = hal_strlen_s(strSrc);
    if(sizeInBytes < len + 1) {_ASSERTE(FALSE); return 1;}

    strcpy( strDst, strSrc );
    return 0;

#define strcpy DoNotUse_*strcpy []
}
    bool Initialize( LPCSTR originalName )
    {
        if(!originalName) return false;
        
        UINT32 nameLength = hal_strlen_s( originalName );

        if(nameLength == 0 || nameLength >= FS_NAME_MAXLENGTH)
        {
            return false;
        }

        hal_strncpy_s( nextAvailableName, FS_NAME_MAXLENGTH, originalName, nameLength );

        iteration = 0;

        return true;
    }
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();
}
CK_DEFINE_FUNCTION(CK_RV, C_InitToken)
(
    CK_SLOT_ID      slotID,
    CK_UTF8CHAR_PTR pPin,
    CK_ULONG        ulPinLen,
    CK_UTF8CHAR_PTR pLabel
)
{
    // pLabel is required to be exactly 32 bytes long per spec
    //const int c_REQUIRED_LABEL_LEN = 32;
    CK_RV ret;
    CryptokiToken *pToken;
    
    if(pPin == NULL || pLabel == NULL) return CKR_ARGUMENTS_BAD;

    ret = GetTokenFromSlotID(slotID, &pToken);

    if(ret != CKR_OK) return ret;

    if(pToken->TokenInfo.ulSessionCount > 0) return CKR_SESSION_EXISTS;

    // label is required to be 32 bytes wth ' ' padding and NOT null terminated
    /*
    for(i=0; i<c_REQUIRED_LABEL_LEN; i++)
    {
        if(pLabel[i] == 0)
        {
            return CKR_ARGUMENTS_BAD;
        }
    }*/

    // TODO: DESTROY ALL OBJECTS ON TOKEN

    if(pToken->TokenState != NULL && pToken->TokenState->InitializeToken != NULL)
    {
        return pToken->TokenState->InitializeToken(pPin, ulPinLen, pLabel, hal_strlen_s((LPCSTR)pLabel)); //c_REQUIRED_LABEL_LEN); 
    }

    return CKR_FUNCTION_NOT_SUPPORTED;
}
HRESULT Library_corlib_native_System_Text_UTF8Encoding::GetBytes___SZARRAY_U1__STRING( CLR_RT_StackFrame& stack )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    size_t                  cBytes;
    CLR_RT_HeapBlock_Array* arr;
    LPCSTR                  str;
    CLR_RT_HeapBlock&       ret = stack.PushValueAndClear();

    str    = stack.Arg1().RecoverString();
    FAULT_ON_NULL(str);
    cBytes = hal_strlen_s(str);

    TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance( ret, (CLR_UINT32)cBytes, g_CLR_RT_WellKnownTypes.m_UInt8 ));

    arr = ret.DereferenceArray();

    memcpy( arr->GetFirstElement(), str, cBytes );

    TINYCLR_NOCLEANUP();
}
HRESULT CLR_RT_FileStream::SplitFilePath( LPCSTR fullPath, LPCSTR* nameSpace, UINT32* nameSpaceLength, LPCSTR* relativePath )
{
    NATIVE_PROFILE_CLR_IO();
    TINYCLR_HEADER();

    static const char root[] = "\\";

    char *c = (char *)fullPath;
    UINT32 nsLen = 0;

    if (!fullPath || !nameSpace || !nameSpaceLength || !relativePath || *c != '\\')
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
    }

    c++;
    *nameSpace = c;
    while((*c != '\\') && (*c != 0))
    {
        c++;        
        nsLen++;
    }    

    // relative path always have to start with a '\' (*c will be '\0' only when fullPath is \<namespace>)
    *relativePath = (*c == 0) ? (LPCSTR)&root : c;

    // Invalid paths should be taken care of by Path.NormalizePath() in the managed code.
    if(nsLen >= FS_NAME_MAXLENGTH || hal_strlen_s(*relativePath) >= FS_MAX_PATH_LENGTH)
    {
        TINYCLR_SET_AND_LEAVE(CLR_E_PATH_TOO_LONG);
    }
    
    *nameSpaceLength = nsLen;

    TINYCLR_NOCLEANUP();
}
CK_SLOT_ID Cryptoki_FindSlot(LPCSTR szProvider, CK_MECHANISM_TYPE_PTR mechs, INT32 mechCnt)
{
    CK_SLOT_ID slotList[10];
    CK_ULONG   slotCnt = ARRAYSIZE(slotList);
    UINT32 lenSP;
    CK_SLOT_ID slotID = CK_SLOT_ID_INVALID;
    UINT32      i;

    lenSP = szProvider == NULL ? 0 : hal_strlen_s(szProvider);
    
    if(CKR_OK == C_GetSlotList(TRUE, slotList, &slotCnt))
    {
        for(i=0; i<slotCnt; i++)
        {
            CK_TOKEN_INFO info;

            if(mechCnt == 0)
            {
                slotID = slotList[i];
                break;
            }
            else if(CKR_OK == C_GetTokenInfo(slotList[i], &info))
            {
                INT32 len2 = hal_strlen_s((const char*)info.label);
            
                if((lenSP == 0) || ((lenSP == len2) && (hal_strncmp_s(szProvider, (const char*)info.label, lenSP) == 0)))
                {
                    if(mechCnt > 0)
                    {
                        CK_MECHANISM_TYPE tokenMechs[100];
                        CK_ULONG cnt = 100;
                            
                        if(CKR_OK == C_GetMechanismList(slotList[i], tokenMechs, &cnt))
                        {
                            bool slotIsOK = false;
                            CK_ULONG t, s;

                            for(s = 0; (INT32)s < mechCnt; s++)
                            {
                                slotIsOK = false;

                                for(t = 0; t < cnt; t++)
                                {
                                    if(mechs[s] == tokenMechs[t])
                                    {
                                        slotIsOK = true;
                                        break;
                                    }
                                }

                                if(!slotIsOK) break;
                            }
                            
                            if(slotIsOK)
                            {
                                slotID = slotList[i];
                                break;
                            }
                        }
                    }
                    else 
                    {
                        slotID = slotList[i];
                        break;
                    }
                }
            }
        }
    }

    return slotID;
}
int RTIP_SOCKETS_Driver::GetAddrInfo(  const char* nodename, 
                                            char* servname, 
                                            const SOCK_addrinfo* hints, 
                                            SOCK_addrinfo** res )
{ 
    if(res == NULL || nodename == NULL) 
    {
        set_errno(EINVAL);
        return SOCK_SOCKET_ERROR;
    }


    *res = NULL;

    PFHOSTENT pHost = NULL;
    struct hostentext localHost;

    if(nodename[0] == '\0')
    {
        IFACE_INFO info;

        if(SOCK_SOCKET_ERROR != xn_interface_info(g_RTIP_SOCKETS_Driver.m_interfaces[0].m_interfaceNumber, &info ))
        {
            memset(&localHost, 0, sizeof(localHost));

            localHost.ip_addr.s_un.S_addr = *(UINT32*)info.my_ip_address;

            pHost = &localHost;
        }
    }
    else
    {
        // this method will be called to get both IP address from name and name from IP address, so nodename
        // can either be "www.xxx.com" or "xxx.xxx.xxx.xxx".  Therefore we will need to first get the IP bytes
        // gethostbyname will do this for either name or IP format, then we will need to get the name
        // by calling gethostbyaddr to get the host name.

        // first call is to get the IP bytes from string version (name or IP)
        pHost = gethostbyname((RTP_PFCHAR)nodename);

        // second call to get the host name
        if(pHost != NULL)
        {
            pHost = gethostbyaddr((RTP_PFCHAR)&pHost->ip_addr.s_un.S_addr, sizeof(UINT32), PF_INET);

            if(!pHost)
            {
                DEBUG_HANDLE_SOCKET_ERROR( "gethostbyaddr", FALSE );
            }
        }
        else
        {
            DEBUG_HANDLE_SOCKET_ERROR( "gethostbyname", FALSE );

        }
    }

    if(pHost)
    {
        SOCK_addrinfo* pAddrInfo = (SOCK_addrinfo*) private_malloc(sizeof(SOCK_addrinfo));

        if(pAddrInfo)
        {
            memset(pAddrInfo, 0, sizeof(SOCK_addrinfo));

            pAddrInfo->ai_family = RTP_NET_AF_INET;

            SOCK_sockaddr_in *pSockaddr = (SOCK_sockaddr_in*) private_malloc(sizeof(SOCK_sockaddr_in));

            if(pSockaddr)
            {
                memset(pSockaddr, 0, sizeof(SOCK_sockaddr_in));
                
                pSockaddr->sin_addr.S_un.S_addr = pHost->ip_addr.s_un.S_addr;
                pSockaddr->sin_family           = RTP_NET_AF_INET;

                pAddrInfo->ai_addr    = (SOCK_sockaddr*)pSockaddr;
                pAddrInfo->ai_addrlen = sizeof(SOCK_sockaddr_in);
            }

            if(pHost->sz_name != NULL)
            {
                int len = hal_strlen_s(pHost->sz_name);

                if(len > 0)
                {
                    int buffer_size = sizeof(char) * len + 1;
                    
                    pAddrInfo->ai_canonname = (char*) private_malloc(buffer_size);

                    if(pAddrInfo->ai_canonname)
                    {
                        hal_strcpy_s(pAddrInfo->ai_canonname, buffer_size, pHost->sz_name);
                    }
                }
            }
            
            *res = pAddrInfo;
        }
    }
    
    return (*res == NULL? SOCK_SOCKET_ERROR: 0);
}
HRESULT CLR_RT_HeapBlock_String::CreateInstance( CLR_RT_HeapBlock& reference, LPCSTR szText )
{
    NATIVE_PROFILE_CLR_CORE();
    TINYCLR_HEADER();

    if(!szText) szText = "";

    TINYCLR_SET_AND_LEAVE(CLR_RT_HeapBlock_String::CreateInstance( reference, szText, (CLR_UINT32)hal_strlen_s( szText ) ));

    TINYCLR_NOCLEANUP();
}
void CLR_Debug::Emit( const char *text, int len )
{
    NATIVE_PROFILE_CLR_DIAGNOSTICS();
    static char s_buffer[ 128 ];
    static int  s_chars = 0;

    if(len == -1) len = (int)hal_strlen_s( text );

#if defined(PLATFORM_WINDOWS)
    if(s_redirectedString)
    {
        s_redirectedString->append( text, len );
        return;
    }

    if(s_CLR_RT_fTrace_RedirectOutput.size())
    {
        static HANDLE hFile = INVALID_HANDLE_VALUE;
        static int    lines = 0;
        static int    num   = 0;

        if(hFile == INVALID_HANDLE_VALUE)
        {
            std::wstring file = s_CLR_RT_fTrace_RedirectOutput;

            if(s_CLR_RT_fTrace_RedirectLinesPerFile)
            {
                WCHAR rgBuf[ 64 ];

                swprintf( rgBuf, ARRAYSIZE(rgBuf), L".%08d", num++ );

                file.append( rgBuf );
            }

            hFile = ::CreateFileW( file.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0 );

            lines = 0;
        }

        if(hFile != INVALID_HANDLE_VALUE)
        {
            DWORD dwWritten;

            ::WriteFile( hFile, text, (DWORD)len, &dwWritten, NULL );

            if(s_CLR_RT_fTrace_RedirectLinesPerFile)
            {
                while((text = strchr( text, '\n' )) != NULL)
                {
                    lines++;
                    text++;

                    if(text[ 0 ] == 0)
                    {
                        if(lines > s_CLR_RT_fTrace_RedirectLinesPerFile)
                        {
                            ::CloseHandle( hFile ); hFile = INVALID_HANDLE_VALUE;
                        }

                        break;
                    }
                }
            }

            return;
        }
    }
#endif

    while(len > 0)
    {
        int avail = MAXSTRLEN(s_buffer) - s_chars;

        if(len < avail) avail = len;

        memcpy( &s_buffer[ s_chars ], text, avail );

        s_chars += avail;
        text    += avail;
        len     -= avail;
        s_buffer[ s_chars ] = 0;

        if(s_chars > 80 || strchr( s_buffer, '\n' ))
        {
            ::Watchdog_ResetCounter();

#if defined(PLATFORM_WINDOWS) || defined(PLATFORM_WINCE)
            HAL_Windows_Debug_Print( s_buffer );
#endif

            if(CLR_EE_DBG_IS( Enabled ) && !CLR_EE_DBG_IS( Quiet ))
            {
                CLR_EE_DBG_EVENT_BROADCAST( CLR_DBG_Commands::c_Monitor_Message, s_chars, s_buffer, WP_Flags::c_NonCritical | WP_Flags::c_NoCaching );
            }

            if(!CLR_EE_DBG_IS( Enabled ) || HalSystemConfig.DebugTextPort != HalSystemConfig.DebuggerPorts[ 0 ])
            {
#if !defined(PLATFORM_WINDOWS) && !defined(PLATFORM_WINCE)
                DebuggerPort_Write( HalSystemConfig.DebugTextPort, s_buffer, s_chars ); // skip null terminator
                DebuggerPort_Flush( HalSystemConfig.DebugTextPort );                    // skip null terminator
#endif
            }

            s_chars = 0;
        }
    }
}