--- a/c++/src/corelib/teamcity_boost.cpp
+++ b/c++/src/corelib/teamcity_boost.cpp
@@ -1,83 +1,106 @@
 /* Copyright 2011 JetBrains s.r.o.
- *
+ * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- *
+ * 
  *     http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
+ * 
  * $Id: teamcity_boost.cpp 488254 2015-12-29 13:56:26Z ivanov $
 */
 
 #include <sstream>
 
-#include <boost/test/unit_test_suite_impl.hpp>
 #include <boost/test/results_collector.hpp>
 #include <boost/test/utils/basic_cstring/io.hpp>
 #include <boost/test/unit_test_log.hpp>
-#include <boost/test/included/unit_test.hpp>
+#include <boost/test/execution_monitor.hpp>
+#include <boost/test/unit_test_log_formatter.hpp>
+#include <boost/test/unit_test.hpp>
+
+// In 1.59.0, they changed the name of this enum value, so we have to this hacky thing...
+#include <boost/version.hpp>
+#if BOOST_VERSION >= 105900
+    #define TUT_CASE_IDENTIFIER boost::unit_test::TUT_CASE
+    #define CURRENT_TEST_NAME   boost::unit_test_framework::framework::current_test_case().full_name()
+#else
+    #define TUT_CASE_IDENTIFIER boost::unit_test::tut_case
+    #define CURRENT_TEST_NAME   boost::unit_test_framework::framework::current_test_case().p_name
+#endif
 
 #include "teamcity_messages.h"
 
-///
-// NOTE: Using namespace boost::unit_test breaks GPIPE Static build!!
-///
-//using namespace boost::unit_test;
-using namespace std;
-
-namespace JetBrains {
+namespace jetbrains { namespace teamcity {
+const std::string ASSERT_CTX = "Assertion occurred in a following context:";
+const std::string FAILURE_CTX = "Failure occurred in a following context:";
 
 // Custom formatter for TeamCity messages
 class TeamcityBoostLogFormatter: public boost::unit_test::unit_test_log_formatter {
     TeamcityMessages messages;
     std::string currentDetails;
+    std::string currentContextDetails;
     std::string flowId;
 
 public:
     TeamcityBoostLogFormatter(const std::string &_flowId);
     TeamcityBoostLogFormatter();
 
-    void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount);
-    void log_finish(std::ostream&);
-    void log_build_info(std::ostream&);
+    virtual ~TeamcityBoostLogFormatter() {}
+
+    virtual void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount);
+    virtual void log_finish(std::ostream&);
+    virtual void log_build_info(std::ostream&);
 
-    void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu);
-    void test_unit_finish(std::ostream&,
+    virtual void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu);
+    virtual void test_unit_finish(std::ostream&,
         boost::unit_test::test_unit const& tu,
         unsigned long elapsed);
-    void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu);
+    virtual void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu);
+    virtual void test_unit_skipped(std::ostream&,
+        boost::unit_test::test_unit const& tu,
+        boost::unit_test::const_string reason);
 
-    void log_exception(std::ostream&,
+    virtual void log_exception(std::ostream&,
         boost::unit_test::log_checkpoint_data const&,
         boost::unit_test::const_string explanation);
+    virtual void log_exception_start(std::ostream&,
+        boost::unit_test::log_checkpoint_data const&,
+        const boost::execution_exception&);
+    virtual void log_exception_finish(std::ostream&);
 
-    void log_entry_start(std::ostream&,
-        boost::unit_test::log_entry_data const&,
+    virtual void log_entry_start(std::ostream & out,
+        boost::unit_test::log_entry_data const & entry_data,
         log_entry_types let);
-    void log_entry_value(std::ostream&, boost::unit_test::const_string value);
-    void log_entry_finish(std::ostream&);
+    virtual void log_entry_value(std::ostream&, boost::unit_test::const_string value);
+    virtual void log_entry_finish(std::ostream&);
+
+    virtual void entry_context_start(std::ostream&, boost::unit_test::log_level);
+    virtual void log_entry_context(std::ostream&, boost::unit_test::const_string);
+    virtual void entry_context_finish(std::ostream&);
 };
 
 // Fake fixture to register formatter
 struct TeamcityFormatterRegistrar {
     TeamcityFormatterRegistrar() {
-        if (JetBrains::underTeamcity()) {
-            boost::unit_test::unit_test_log.set_formatter(new JetBrains::TeamcityBoostLogFormatter());
-            boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::runtime_config::log_level());
+        if (underTeamcity()) {
+            boost::unit_test::unit_test_log.set_formatter(new TeamcityBoostLogFormatter());
+            boost::unit_test::unit_test_log.set_threshold_level
+                (RTCFG(but::log_level, LOG_LEVEL, log_level));
         }
     }
 };
+
 BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar);
 
 // Formatter implementation
-string toString(boost::unit_test::const_string bstr) {
-    stringstream ss;
+static std::string toString(boost::unit_test::const_string bstr) {
+    std::stringstream ss;
 
     ss << bstr;
 
@@ -92,19 +115,19 @@ TeamcityBoostLogFormatter::TeamcityBoost
 : flowId(getFlowIdFromEnvironment())
 {}
 
-void TeamcityBoostLogFormatter::log_start(ostream &out, boost::unit_test::counter_t test_cases_amount)
+void TeamcityBoostLogFormatter::log_start(std::ostream &/*out*/, boost::unit_test::counter_t /*test_cases_amount*/)
 {}
 
-void TeamcityBoostLogFormatter::log_finish(ostream &out)
+void TeamcityBoostLogFormatter::log_finish(std::ostream &/*out*/)
 {}
 
-void TeamcityBoostLogFormatter::log_build_info(ostream &out)
+void TeamcityBoostLogFormatter::log_build_info(std::ostream &/*out*/)
 {}
 
-void TeamcityBoostLogFormatter::test_unit_start(ostream &out, boost::unit_test::test_unit const& tu) {
+void TeamcityBoostLogFormatter::test_unit_start(std::ostream &out, boost::unit_test::test_unit const& tu) {
     messages.setOutput(out);
 
-    if (tu.p_type == boost::unit_test::tut_case) {
+    if (tu.p_type == TUT_CASE_IDENTIFIER) {
         messages.testStarted(tu.p_name, flowId);
     } else {
         messages.suiteStarted(tu.p_name, flowId);
@@ -113,11 +136,11 @@ void TeamcityBoostLogFormatter::test_uni
     currentDetails.clear();
 }
 
-void TeamcityBoostLogFormatter::test_unit_finish(ostream &out, boost::unit_test::test_unit const& tu, unsigned long elapsed) {
+void TeamcityBoostLogFormatter::test_unit_finish(std::ostream &out, boost::unit_test::test_unit const& tu, unsigned long elapsed) {
     messages.setOutput(out);
 
     boost::unit_test::test_results const& tr = boost::unit_test::results_collector.results(tu.p_id);
-    if (tu.p_type == boost::unit_test::tut_case) {
+    if (tu.p_type == TUT_CASE_IDENTIFIER) {
         if(!tr.passed()) {
             if(tr.p_skipped) {
                 messages.testIgnored(tu.p_name, "ignored", flowId);
@@ -134,27 +157,62 @@ void TeamcityBoostLogFormatter::test_uni
     }
 }
 
-void TeamcityBoostLogFormatter::test_unit_skipped(ostream &out, boost::unit_test::test_unit const& tu)
+void TeamcityBoostLogFormatter::test_unit_skipped(std::ostream &/*out*/, boost::unit_test::test_unit const& /*tu*/)
 {}
 
-void TeamcityBoostLogFormatter::log_exception(ostream &out, boost::unit_test::log_checkpoint_data const&, boost::unit_test::const_string explanation) {
-    string what = toString(explanation);
+void TeamcityBoostLogFormatter::test_unit_skipped(std::ostream &out, boost::unit_test::test_unit const& tu, boost::unit_test::const_string reason)
+{
+    messages.testIgnored(tu.p_name, toString(reason), flowId);
+}
+
+void TeamcityBoostLogFormatter::log_exception(std::ostream &out, boost::unit_test::log_checkpoint_data const &, boost::unit_test::const_string explanation) {
+    std::string what = toString(explanation);
 
-    out << what << endl;
+    out << what << std::endl;
     currentDetails += what + "\n";
 }
 
-void TeamcityBoostLogFormatter::log_entry_start(ostream&, boost::unit_test::log_entry_data const&, log_entry_types let)
-{}
+void TeamcityBoostLogFormatter::log_exception_start(std::ostream &out, boost::unit_test::log_checkpoint_data const &data, const boost::execution_exception& excpt) {
+    log_exception(out, data, excpt.what());
+}
+
+void TeamcityBoostLogFormatter::log_exception_finish(std::ostream &/*out*/) {}
 
-void TeamcityBoostLogFormatter::log_entry_value(ostream &out, boost::unit_test::const_string value) {
+
+void TeamcityBoostLogFormatter::log_entry_start(std::ostream & out, boost::unit_test::log_entry_data const & entry_data, log_entry_types /*let*/)
+{
+    std::stringstream ss(std::ios_base::out);
+
+    out << entry_data.m_file_name << "(" << entry_data.m_line_num << "): ";
+    ss  << entry_data.m_file_name << "(" << entry_data.m_line_num << "): ";
+
+    currentDetails += ss.str();
+}
+
+void TeamcityBoostLogFormatter::log_entry_value(std::ostream &out, boost::unit_test::const_string value) {
     out << value;
     currentDetails += toString(value);
 }
 
-void TeamcityBoostLogFormatter::log_entry_finish(ostream &out) {
-    out << endl;
+void TeamcityBoostLogFormatter::log_entry_finish(std::ostream &out) {
+    out << std::endl;
     currentDetails += "\n";
 }
 
+void TeamcityBoostLogFormatter::entry_context_start(std::ostream &out, boost::unit_test::log_level l) {
+    const std::string& initial_msg = (l == boost::unit_test::log_successful_tests ? ASSERT_CTX : FAILURE_CTX);
+    out << initial_msg;
+    currentContextDetails = initial_msg;
 }
+
+void TeamcityBoostLogFormatter::log_entry_context(std::ostream &out, boost::unit_test::const_string ctx) {
+    out << "\n " << ctx;
+    currentContextDetails += "\n " + toString(ctx);
+}
+
+void TeamcityBoostLogFormatter::entry_context_finish(std::ostream &out) {
+    out.flush();
+    messages.testOutput(CURRENT_TEST_NAME, currentContextDetails, flowId, TeamcityMessages::StdErr);
+}
+
+}}                                                          // namespace teamcity, jetbrains
--- a/c++/src/corelib/teamcity_messages.cpp
+++ b/c++/src/corelib/teamcity_messages.cpp
@@ -15,40 +15,61 @@
  * $Id: teamcity_messages.cpp 435791 2014-05-20 18:47:58Z camacho $
 */
 
-#include <ncbi_pch.hpp>
-
-#include <stdlib.h>
-#include <sstream>
-
 #include "teamcity_messages.h"
 
-using namespace std;
+#include <cstdlib>
+#include <sstream>
 
-namespace JetBrains {
+namespace jetbrains {
+namespace teamcity {
 
 std::string getFlowIdFromEnvironment() {
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
+    char *flowId = NULL;
+    size_t sz = 0;
+    std::string result;
+    if(!_dupenv_s(&flowId, &sz,"TEAMCITY_PROCESS_FLOW_ID")) {
+        result = flowId != NULL ? flowId : "";
+        free(flowId);
+    }
+
+    return result;
+#else
     const char *flowId = getenv("TEAMCITY_PROCESS_FLOW_ID");
     return flowId == NULL ? "" : flowId;
+#endif
 }
 
 bool underTeamcity() {
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
+    char *teamCityProjectName = 0;
+    size_t sz = 0;
+    bool result = false;
+    if(!_dupenv_s(&teamCityProjectName, &sz, "TEAMCITY_PROJECT_NAME")) {
+        result = teamCityProjectName != NULL;
+        free(teamCityProjectName);
+    }
+
+    return result;
+#else
     return getenv("TEAMCITY_PROJECT_NAME") != NULL;
+#endif
 }
 
 TeamcityMessages::TeamcityMessages()
-: m_out(&cout)
+: m_out(&std::cout)
 {}
 
-void TeamcityMessages::setOutput(ostream &out) {
+void TeamcityMessages::setOutput(std::ostream &out) {
     m_out = &out;
 }
 
-string TeamcityMessages::escape(string s) {
-    string result;
-    
+std::string TeamcityMessages::escape(std::string s) {
+    std::string result;
+
     for (size_t i = 0; i < s.length(); i++) {
         char c = s[i];
-        
+
         switch (c) {
         case '\n': result.append("|n"); break;
         case '\r': result.append("|r"); break;
@@ -58,56 +79,60 @@ string TeamcityMessages::escape(string s
         default:   result.append(&c, 1);
         }
     }
-    
+
     return result;
 }
 
-void TeamcityMessages::openMsg(const string &name) {
-    *m_out << "##teamcity[" << name;
+void TeamcityMessages::openMsg(const std::string &name) {
+    // endl for http://jetbrains.net/tracker/issue/TW-4412
+    *m_out << std::endl << "##teamcity[" << name;
 }
 
 void TeamcityMessages::closeMsg() {
     *m_out << "]";
     // endl for http://jetbrains.net/tracker/issue/TW-4412
-    *m_out << endl;
-    m_out->flush();
+    *m_out << std::endl;
 }
 
-void TeamcityMessages::writeProperty(string name, string value) {
+void TeamcityMessages::writeProperty(std::string name, std::string value) {
     *m_out << " " << name << "='" << escape(value) << "'";
 }
 
-void TeamcityMessages::suiteStarted(string name, string flowid) {
+void TeamcityMessages::suiteStarted(std::string name, std::string flowid) {
     openMsg("testSuiteStarted");
     writeProperty("name", name);
     if(flowid.length() > 0) {
         writeProperty("flowId", flowid);
     }
-    
+
     closeMsg();
 }
 
-void TeamcityMessages::suiteFinished(string name, string flowid) {
+void TeamcityMessages::suiteFinished(std::string name, std::string flowid) {
     openMsg("testSuiteFinished");
     writeProperty("name", name);
     if(flowid.length() > 0) {
         writeProperty("flowId", flowid);
     }
-    
+
     closeMsg();
 }
 
-void TeamcityMessages::testStarted(string name, string flowid) {
+void TeamcityMessages::testStarted(std::string name, std::string flowid, bool captureStandardOutput) {
     openMsg("testStarted");
     writeProperty("name", name);
     if(flowid.length() > 0) {
         writeProperty("flowId", flowid);
     }
-    
+
+    if(captureStandardOutput) {
+        writeProperty("captureStandardOutput", "true"); // false by default
+    }
+
     closeMsg();
 }
 
-void TeamcityMessages::testFinished(string name, int durationMs, string flowid) {
+void TeamcityMessages::testFinished(std::string name, int durationMs, std::string flowid) {
     openMsg("testFinished");
 
     writeProperty("name", name);
@@ -117,15 +142,15 @@ void TeamcityMessages::testFinished(stri
     }
 
     if(durationMs >= 0) {
-        stringstream out;
+        std::stringstream out(std::ios_base::out);
         out << durationMs;
         writeProperty("duration", out.str());
     }
-    
+
     closeMsg();
 }
 
-void TeamcityMessages::testFailed(string name, string message, string details, string flowid) {
+void TeamcityMessages::testFailed(std::string name, std::string message, std::string details, std::string flowid) {
     openMsg("testFailed");
     writeProperty("name", name);
     writeProperty("message", message);
@@ -133,19 +158,31 @@ void TeamcityMessages::testFailed(string
     if(flowid.length() > 0) {
         writeProperty("flowId", flowid);
     }
-    
+
     closeMsg();
 }
 
-void TeamcityMessages::testIgnored(std::string name, std::string message, string flowid) {
+void TeamcityMessages::testIgnored(std::string name, std::string message, std::string flowid) {
     openMsg("testIgnored");
     writeProperty("name", name);
     writeProperty("message", message);
     if(flowid.length() > 0) {
         writeProperty("flowId", flowid);
     }
-    
+
     closeMsg();
 }
 
+void TeamcityMessages::testOutput(std::string name, std::string output, std::string flowid, bool isStdError) {
+    openMsg(isStdError ? "testStdErr" : "testStdOut");
+    writeProperty("name", name);
+    writeProperty("out", output);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    closeMsg();
+}
+
+}
 }
--- a/c++/src/corelib/teamcity_messages.h
+++ b/c++/src/corelib/teamcity_messages.h
@@ -18,17 +18,18 @@
 #ifndef H_TEAMCITY_MESSAGES
 #define H_TEAMCITY_MESSAGES
 
-#include <string>
 #include <iostream>
+#include <string>
 
-namespace JetBrains {
+namespace jetbrains {
+namespace teamcity {
 
 std::string getFlowIdFromEnvironment();
 bool underTeamcity();
 
 class TeamcityMessages {
     std::ostream *m_out;
-    
+
 protected:
     std::string escape(std::string s);
 
@@ -37,19 +38,24 @@ protected:
     void closeMsg();
 
 public:
+    static const bool StdErr = true;
+    static const bool StdOut = false;
+
     TeamcityMessages();
-    
+
     void setOutput(std::ostream &);
-    
-    void suiteStarted(std::string name, std::string flowid = "");
-    void suiteFinished(std::string name, std::string flowid = "");
-    
-    void testStarted(std::string name, std::string flowid = "");
-    void testFailed(std::string name, std::string message, std::string details, std::string flowid = "");
-    void testIgnored(std::string name, std::string message, std::string flowid = "");
-    void testFinished(std::string name, int durationMs = -1, std::string flowid = "");    
+
+    void suiteStarted(std::string name, std::string flowid =  std::string());
+    void suiteFinished(std::string name, std::string flowid =  std::string());
+
+    void testStarted(std::string name, std::string flowid =  std::string(), bool captureStandardOutput = false);
+    void testFailed(std::string name, std::string message, std::string details, std::string flowid =  std::string());
+    void testIgnored(std::string name, std::string message, std::string flowid =  std::string());
+    void testOutput(std::string name, std::string output, std::string flowid, bool isStdErr = StdOut);
+    void testFinished(std::string name, int durationMs = -1, std::string flowid = std::string());
 };
 
 }
+}
 
 #endif /* H_TEAMCITY_MESSAGES */
