+struct output_data {
+ DWORD len, lenwritten;
+ int writeret;
+ char *buffer;
+ int is_stderr, done;
+ HANDLE event, eventback;
+ int busy;
+};
+
+static DWORD WINAPI stdout_write_thread(void *param)
+{
+ struct output_data *odata = (struct output_data *) param;
+ HANDLE outhandle, errhandle;
+
+ outhandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ errhandle = GetStdHandle(STD_ERROR_HANDLE);
+
+ while (1) {
+ WaitForSingleObject(odata->eventback, INFINITE);
+ if (odata->done)
+ break;
+ odata->writeret =
+ WriteFile(odata->is_stderr ? errhandle : outhandle,
+ odata->buffer, odata->len, &odata->lenwritten, NULL);
+ SetEvent(odata->event);
+ }
+
+ return 0;
+}
+
+bufchain stdout_data, stderr_data;
+struct output_data odata, edata;
+
+void try_output(int is_stderr)
+{
+ struct output_data *data = (is_stderr ? &edata : &odata);
+ void *senddata;
+ int sendlen;
+
+ if (!data->busy) {
+ bufchain_prefix(is_stderr ? &stderr_data : &stdout_data,
+ &senddata, &sendlen);
+ data->buffer = senddata;
+ data->len = sendlen;
+ SetEvent(data->eventback);
+ data->busy = 1;
+ }
+}
+
+int from_backend(int is_stderr, char *data, int len)
+{
+ HANDLE h = (is_stderr ? errhandle : outhandle);
+ int osize, esize;
+
+ if (is_stderr) {
+ bufchain_add(&stderr_data, data, len);
+ try_output(1);
+ } else {
+ bufchain_add(&stdout_data, data, len);
+ try_output(0);
+ }
+
+ osize = bufchain_size(&stdout_data);
+ esize = bufchain_size(&stderr_data);
+
+ return osize + esize;
+}
+