Happens on windows when SetPixelFormat is called...
    }
 }
 
-static int reentrancy = 0;
-
 static void _Open(const char *szExtension) {
    _Close();
    
    if (g_gzFile == NULL)
       return;
    
-   if (reentrancy > 1)
-      return;
-
    gzwrite(g_gzFile, sBuffer, dwBytesToWrite);
 }
 
    _Close();
 }
 
-void BeginCall(const char *function) {
+static unsigned call_no = 0;
+
+unsigned BeginEnter(const char *function) {
    OS::AcquireMutex();
    Open();
-   ++reentrancy;
+   WriteByte(Trace::EVENT_ENTER);
    WriteName(function);
+   return call_no++;
+}
+
+void EndEnter(void) {
+   WriteByte(Trace::CALL_END);
+   gzflush(g_gzFile, Z_SYNC_FLUSH);
+   OS::ReleaseMutex();
+}
+
+void BeginLeave(unsigned call) {
+   OS::AcquireMutex();
+   WriteByte(Trace::EVENT_LEAVE);
+   WriteUInt(call);
 }
 
-void EndCall(void) {
+void EndLeave(void) {
    WriteByte(Trace::CALL_END);
-   --reentrancy;
    gzflush(g_gzFile, Z_SYNC_FLUSH);
    OS::ReleaseMutex();
 }
 
     void Open(void);
     void Close(void);
     
-    void BeginCall(const char *function);
-    void EndCall(void);
+    unsigned BeginEnter(const char *function);
+    void EndEnter(void);
+    
+    void BeginLeave(unsigned call);
+    void EndLeave(void);
     
     void BeginArg(unsigned index, const char *name);
     inline void EndArg(void) {}
 
 void
 AcquireMutex(void)
 {
-    //EnterCriticalSection(&CriticalSection); 
+    EnterCriticalSection(&CriticalSection); 
 }
 
 
 void
 ReleaseMutex(void)
 {
-    //LeaveCriticalSection(&CriticalSection); 
+    LeaveCriticalSection(&CriticalSection); 
 }
 
 
 
             print '    %s __result;' % function.type
             result = '__result = '
         self._get_true_pointer(function)
-        print '    Log::BeginCall("%s");' % (function.name)
+        print '    unsigned __call = Log::BeginEnter("%s");' % (function.name)
         for arg in function.args:
             if not arg.output:
                 self.unwrap_arg(function, arg)
                 self.dump_arg(function, arg)
+        print '    Log::EndEnter();'
         print '    %s%s(%s);' % (result, pvalue, ', '.join([str(arg.name) for arg in function.args]))
+        print '    Log::BeginLeave(__call);'
         for arg in function.args:
             if arg.output:
                 self.dump_arg(function, arg)
                 self.wrap_arg(function, arg)
         if function.type is not stdapi.Void:
             self.dump_ret(function, "__result")
-        print '    Log::EndCall();'
+        print '    Log::EndLeave();'
         if function.type is not stdapi.Void:
             self.wrap_ret(function, "__result")
             print '    return __result;'
 
 
 #define TRACE_VERSION 0
 
+enum Event {
+   EVENT_ENTER = 0,
+   EVENT_LEAVE,
+   EVENT_MESSAGE
+};
+
 enum CallDetail {
    CALL_END = 0,
    CALL_ARG,
 
 class Call
 {
 public:
+   unsigned no;
    std::string name;
    std::vector<Arg> args;
    Value *ret;
 
    typedef std::map<size_t, std::string> namemap;
    namemap names;
 
+   typedef std::map<unsigned, Call *> callmap;
+   callmap calls;
+
+   unsigned next_call_no;
+
 public:
    Parser() {
       file = NULL;
+      next_call_no = 0;
    }
 
    ~Parser() {
    }
 
    Call *parse_call(void) {
+      do {
+         int c = read_byte();
+         switch(c) {
+         case Trace::EVENT_ENTER:
+            parse_enter();
+            break;
+         case Trace::EVENT_LEAVE:
+            return parse_leave();
+         case Trace::EVENT_MESSAGE:
+            std::cerr << "message: " << read_string() << "\n";
+            break;
+         default:
+            std::cerr << "error: unknown call detail " << c << "\n";
+            assert(0);
+            /* fallthrough */
+         case -1:
+            return NULL;
+         }
+      } while(true);
+   }
+   
+   void parse_enter(void) {
       Call *call = new Call;
+      call->no = next_call_no++;
       call->name = read_name();
+      parse_call_details(call);
+      calls[call->no] = call;
+   }
+   
+   Call *parse_leave(void) {
+      unsigned call_no = read_uint();
+      Call *call = calls[call_no];
+      assert(call);
+      if (!call) {
+          return NULL;
+      }
+      parse_call_details(call);
+      return call;
+   }
+   
+   void parse_call_details(Call *call) {
       do {
          int c = read_byte();
          switch(c) {
          case Trace::CALL_END:
-            return call;
+            return;
          case Trace::CALL_ARG:
             parse_arg(call);
             break;
             assert(0);
             /* fallthrough */
          case -1:
-            delete call;
-            return NULL;
+            return;
          }
       } while(true);
    }