void *privdata; /* for client to remember who they are */
/*
+ * Data set at initialisation and then read-only.
+ */
+ int flags;
+
+ /*
* Data set by the input thread before signalling ev_to_main,
* and read by the main thread after receiving that signal.
*/
static DWORD WINAPI handle_input_threadfunc(void *param)
{
struct handle_input *ctx = (struct handle_input *) param;
+ OVERLAPPED ovl, *povl;
+
+ if (ctx->flags & HANDLE_FLAG_OVERLAPPED)
+ povl = &ovl;
+ else
+ povl = NULL;
while (1) {
+ if (povl)
+ memset(povl, 0, sizeof(OVERLAPPED));
ctx->readret = ReadFile(ctx->h, ctx->buffer, sizeof(ctx->buffer),
- &ctx->len, NULL);
+ &ctx->len, povl);
+ if (povl && !ctx->readret && GetLastError() == ERROR_IO_PENDING)
+ ctx->readret = GetOverlappedResult(ctx->h, povl, &ctx->len, TRUE);
+
if (!ctx->readret)
ctx->len = 0;
+ if (ctx->readret && ctx->len == 0 &&
+ (ctx->flags & HANDLE_FLAG_IGNOREEOF))
+ continue;
+
SetEvent(ctx->ev_to_main);
if (!ctx->len)
void *privdata; /* for client to remember who they are */
/*
+ * Data set at initialisation and then read-only.
+ */
+ int flags;
+
+ /*
* Data set by the main thread before signalling ev_from_main,
* and read by the input thread after receiving that signal.
*/
static DWORD WINAPI handle_output_threadfunc(void *param)
{
struct handle_output *ctx = (struct handle_output *) param;
+ OVERLAPPED ovl, *povl;
+
+ if (ctx->flags & HANDLE_FLAG_OVERLAPPED)
+ povl = &ovl;
+ else
+ povl = NULL;
while (1) {
WaitForSingleObject(ctx->ev_from_main, INFINITE);
SetEvent(ctx->ev_to_main);
break;
}
+ if (povl)
+ memset(povl, 0, sizeof(OVERLAPPED));
ctx->writeret = WriteFile(ctx->h, ctx->buffer, ctx->len,
- &ctx->lenwritten, NULL);
+ &ctx->lenwritten, povl);
+ if (povl && !ctx->writeret && GetLastError() == ERROR_IO_PENDING)
+ ctx->writeret = GetOverlappedResult(ctx->h, povl,
+ &ctx->lenwritten, TRUE);
+
SetEvent(ctx->ev_to_main);
if (!ctx->writeret)
break;
}
struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
- void *privdata)
+ void *privdata, int flags)
{
struct handle *h = snew(struct handle);
h->u.i.moribund = FALSE;
h->u.i.done = FALSE;
h->u.i.privdata = privdata;
+ h->u.i.flags = flags;
if (!handles_by_evtomain)
handles_by_evtomain = newtree234(handle_cmp_evtomain);
}
struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
- void *privdata)
+ void *privdata, int flags)
{
struct handle *h = snew(struct handle);
h->u.o.privdata = privdata;
bufchain_init(&h->u.o.queued_data);
h->u.o.sentdata = sentdata;
+ h->u.o.flags = flags;
if (!handles_by_evtomain)
handles_by_evtomain = newtree234(handle_cmp_evtomain);
* (The input one we leave until we're through the
* authentication process.)
*/
- stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL);
- stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL);
+ stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL, 0);
+ stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL, 0);
main_thread_id = GetCurrentThreadId();
DWORD ticks;
if (!sending && back->sendok(backhandle)) {
- stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL);
+ stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL,
+ 0);
sending = TRUE;
}
ret->to_cmd_H = us_to_cmd;\r
ret->from_cmd_H = us_from_cmd;\r
\r
- ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata, ret);\r
- ret->to_cmd_h = handle_output_new(ret->to_cmd_H,\r
- localproxy_sentdata, ret);\r
+ ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata,\r
+ ret, 0);\r
+ ret->to_cmd_h = handle_output_new(ret->to_cmd_H, localproxy_sentdata,\r
+ ret, 0);\r
\r
/* We are responsible for this and don't need it any more */\r
sk_addr_free(addr);\r
/*
* Exports from winhandl.c.
*/
+#define HANDLE_FLAG_OVERLAPPED 1
+#define HANDLE_FLAG_IGNOREEOF 2
struct handle;
typedef int (*handle_inputfn_t)(struct handle *h, void *data, int len);
typedef void (*handle_outputfn_t)(struct handle *h, int new_backlog);
struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
- void *privdata);
+ void *privdata, int flags);
struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
- void *privdata);
+ void *privdata, int flags);
int handle_write(struct handle *h, const void *data, int len);
HANDLE *handle_get_events(int *nevents);
void handle_free(struct handle *h);