return source;
}
+
+#ifdef G_OS_WIN32
+gboolean
+_g_win32_overlap_wait_result (HANDLE hfile,
+ OVERLAPPED *overlap,
+ DWORD *transferred,
+ GCancellable *cancellable G_GNUC_UNUSED)
+{
+ GPollFD pollfd[1] = { 0, };
+ gboolean result = FALSE;
+ gint num, npoll;
+
+ pollfd[0].fd = (gint)overlap->hEvent;
+ pollfd[0].events = G_IO_IN;
+ num = 1;
+
+ npoll = g_poll (pollfd, num, -1);
+ if (npoll <= 0)
+ /* error out, should never happen */
+ goto end;
+
+ /* either cancelled or IO completed, either way get the result */
+ result = GetOverlappedResult (overlap->hEvent, overlap, transferred, TRUE);
+
+end:
+ return result;
+}
+#endif
#include <gio/gio.h>
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+
G_BEGIN_DECLS
typedef gboolean (*GFDSourceFunc) (int fd,
gushort events,
GCancellable *cancellable);
+#ifdef G_OS_WIN32
+gboolean _g_win32_overlap_wait_result (HANDLE hfile,
+ OVERLAPPED *overlap,
+ DWORD *transferred,
+ GCancellable *cancellable);
+#endif
+
G_END_DECLS
#endif /* __G_ASYNC_HELPER_H__ */
GWin32InputStream *win32_stream;
BOOL res;
DWORD nbytes, nread;
+ OVERLAPPED overlap = { 0, };
+ gssize retval = -1;
win32_stream = G_WIN32_INPUT_STREAM (stream);
else
nbytes = count;
- res = ReadFile (win32_stream->priv->handle, buffer, nbytes, &nread, NULL);
- if (!res)
+ overlap.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+ g_return_val_if_fail (overlap.hEvent != NULL, -1);
+
+ res = ReadFile (win32_stream->priv->handle, buffer, nbytes, &nread, &overlap);
+ if (res)
+ retval = nread;
+ else
{
int errsv = GetLastError ();
- gchar *emsg;
- if (errsv == ERROR_HANDLE_EOF ||
- errsv == ERROR_BROKEN_PIPE)
- return 0;
+ if (errsv == ERROR_IO_PENDING &&
+ _g_win32_overlap_wait_result (win32_stream->priv->handle,
+ &overlap, &nread, cancellable))
+ {
+ retval = nread;
+ goto end;
+ }
- emsg = g_win32_error_message (errsv);
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_win32_error (errsv),
- _("Error reading from handle: %s"),
- emsg);
- g_free (emsg);
- return -1;
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ goto end;
+
+ errsv = GetLastError ();
+ if (errsv == ERROR_HANDLE_EOF ||
+ errsv == ERROR_BROKEN_PIPE)
+ {
+ /* TODO: the other end of a pipe may call the WriteFile
+ * function with nNumberOfBytesToWrite set to zero. In this
+ * case, it's not possible for the caller to know if it's
+ * broken pipe or a read of 0. Perhaps we should add a
+ * is_broken flag for this win32 case.. */
+ retval = 0;
+ }
+ else
+ {
+ gchar *emsg;
+
+ emsg = g_win32_error_message (errsv);
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ _("Error reading from handle: %s"),
+ emsg);
+ g_free (emsg);
+ }
}
- return nread;
+end:
+ CloseHandle (overlap.hEvent);
+ return retval;
}
static gboolean
GWin32OutputStream *win32_stream;
BOOL res;
DWORD nbytes, nwritten;
+ OVERLAPPED overlap = { 0, };
+ gssize retval = -1;
win32_stream = G_WIN32_OUTPUT_STREAM (stream);
else
nbytes = count;
- res = WriteFile (win32_stream->priv->handle, buffer, nbytes, &nwritten, NULL);
- if (!res)
+ overlap.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+ g_return_val_if_fail (overlap.hEvent != NULL, -1);
+
+ res = WriteFile (win32_stream->priv->handle, buffer, nbytes, &nwritten, &overlap);
+ if (res)
+ retval = nwritten;
+ else
{
int errsv = GetLastError ();
- gchar *emsg = g_win32_error_message (errsv);
-
- if (errsv == ERROR_HANDLE_EOF)
- return 0;
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_win32_error (errsv),
- _("Error writing to handle: %s"),
- emsg);
- g_free (emsg);
- return -1;
+ if (errsv == ERROR_IO_PENDING &&
+ _g_win32_overlap_wait_result (win32_stream->priv->handle,
+ &overlap, &nwritten, cancellable))
+ {
+ retval = nwritten;
+ goto end;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ goto end;
+
+ errsv = GetLastError ();
+ if (errsv == ERROR_HANDLE_EOF ||
+ errsv == ERROR_BROKEN_PIPE)
+ {
+ retval = 0;
+ }
+ else
+ {
+ gchar *emsg;
+
+ emsg = g_win32_error_message (errsv);
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ _("Error writing to handle: %s"),
+ emsg);
+ g_free (emsg);
+ }
}
- return nwritten;
+end:
+ CloseHandle (overlap.hEvent);
+ return retval;
}
static gboolean