struct async-private - now tested and cleaned up
Martin Wilck
Martin.Wilck at fujitsu-siemens.com
Tue Jan 15 13:05:13 CST 2002
PATCH: async-struct.diff
This patch introduces a new API for asynchronous requests, which
- separates cleanly between async scheduling and file IO related issues
- thereby makes the API compatible with other types of async requests (e.g. Winsock2).
It is a polished resubmit of my former posting, without the GetOverlappedResult() stuff
which will follow in a separate patch. It is against clean CVS 2002-01-15.
I would be really grateful if this patch was applied, because it is a prerequisite for me to
get going with Winsock2 overlapped IO.
It was tested for regular file IO and (even 16 bit) serial IO (thanks 2 Lawson Whitney).
No regressions found.
ChangeLog:
server/protocol.def and server/async.c:
cancel_async(): new reqest type.
include/file.h:
struct async_ops: introduce "ops" field for different request types.
struct async_private: only fields necessary for async request scheduling
struct async_fileio: new struct, contains file IO related fields.
scheduler/synchro.c:
register_async(): replacement for FILE_StartAsync().
Hooks new requests in NtCurrentTeb()->pending_list.
finish_async(): Assume status is already set correctly.
Queue call_completion unconditionally.
check_async(): Use register_async() for rescheduling.
files/file.c:
CancelIo(): Use new cancel_async server request.
fileio_call_completion_func(): check if completion_func is non-NULL (see finish_async).
FILE_AsyncReadService(), FILE_AsyncWriteService(): type adjustments according to new API
FILE_ReadFileEx(), FILE_WriteFileEx(): use new async API.
kernel/comm.c:
COMM_WaitCommEventService(): Use new async API.
Martin Wilck <Martin.Wilck at Fujitsu-Siemens.com>
diff -ruX diffignore CVS/wine/dlls/kernel/comm.c MW/wine/dlls/kernel/comm.c
--- CVS/wine/dlls/kernel/comm.c Tue Jan 15 19:37:37 2002
+++ MW/wine/dlls/kernel/comm.c Tue Jan 15 19:09:42 2002
@@ -1514,12 +1514,13 @@
*/
static void COMM_WaitCommEventService(async_private *ovp)
{
- LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+ async_fileio *fileio = (async_fileio*) ovp;
+ LPOVERLAPPED lpOverlapped = fileio->lpOverlapped;
TRACE("overlapped %p\n",lpOverlapped);
/* FIXME: detect other events */
- *ovp->buffer = EV_RXCHAR;
+ *fileio->buffer = EV_RXCHAR;
lpOverlapped->Internal = STATUS_SUCCESS;
}
@@ -1536,7 +1537,7 @@
LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
{
int fd,ret;
- async_private *ovp;
+ async_fileio *ovp;
if(!lpOverlapped)
{
@@ -1547,52 +1548,34 @@
if(NtResetEvent(lpOverlapped->hEvent,NULL))
return FALSE;
- lpOverlapped->Internal = STATUS_PENDING;
- lpOverlapped->InternalHigh = 0;
- lpOverlapped->Offset = 0;
- lpOverlapped->OffsetHigh = 0;
-
fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
if(fd<0)
return FALSE;
- ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+ ovp = (async_fileio *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
{
close(fd);
return FALSE;
}
+
+ ovp->async.ops = &fileio_async_ops;
+ ovp->async.handle = hFile;
+ ovp->async.fd = fd;
+ ovp->async.type = ASYNC_TYPE_WAIT;
+ ovp->async.func = COMM_WaitCommEventService;
ovp->lpOverlapped = lpOverlapped;
- ovp->func = COMM_WaitCommEventService;
ovp->buffer = (char *)lpdwEvents;
- ovp->fd = fd;
ovp->count = 0;
ovp->completion_func = 0;
- ovp->type = ASYNC_TYPE_WAIT;
- ovp->handle = hFile;
-
- ovp->next = NtCurrentTeb()->pending_list;
- ovp->prev = NULL;
- if(ovp->next)
- ovp->next->prev=ovp;
- NtCurrentTeb()->pending_list = ovp;
- /* start an ASYNCHRONOUS WaitCommEvent */
- SERVER_START_REQ( register_async )
- {
- req->handle = hFile;
- req->overlapped = lpOverlapped;
- req->type = ASYNC_TYPE_WAIT;
- req->count = 0;
- req->func = check_async_list;
- req->status = STATUS_PENDING;
-
- ret=wine_server_call_err(req);
- }
- SERVER_END_REQ;
+ lpOverlapped->Internal = STATUS_USER_APC;
+ lpOverlapped->InternalHigh = 0;
+ lpOverlapped->Offset = 0;
+ lpOverlapped->OffsetHigh = 0;
- if (!ret)
- SetLastError(ERROR_IO_PENDING);
+ if ( register_async (&ovp->async) )
+ SetLastError( ERROR_IO_PENDING );
return FALSE;
}
diff -ruX diffignore CVS/wine/files/file.c MW/wine/files/file.c
--- CVS/wine/files/file.c Tue Jan 15 19:37:37 2002
+++ MW/wine/files/file.c Tue Jan 15 19:34:00 2002
@@ -60,6 +60,20 @@
static HANDLE dos_handles[DOS_TABLE_SIZE];
+/* Async operations struct (see file.h) */
+
+static DWORD fileio_get_async_status (async_private *ovp);
+static DWORD fileio_get_async_count (async_private *ovp);
+static void fileio_set_async_status (async_private *ovp, DWORD status);
+static void CALLBACK fileio_call_completion_func (ULONG_PTR data);
+
+async_ops fileio_async_ops =
+{
+ fileio_get_async_status, /* get_status */
+ fileio_set_async_status, /* set_status */
+ fileio_get_async_count, /* get_count */
+ fileio_call_completion_func /* call_completion */
+};
/***********************************************************************
* FILE_ConvertOFMode
@@ -1255,30 +1269,6 @@
return (r==WAIT_OBJECT_0);
}
-
-/***********************************************************************
- * FILE_StartAsync (INTERNAL)
- *
- * type==ASYNC_TYPE_NONE means cancel the indicated overlapped operation
- * lpOverlapped==NULL means all overlappeds match
- */
-BOOL FILE_StartAsync(HANDLE hFile, LPOVERLAPPED lpOverlapped, DWORD type, DWORD count, DWORD status)
-{
- BOOL ret;
- SERVER_START_REQ(register_async)
- {
- req->handle = hFile;
- req->overlapped = lpOverlapped;
- req->type = type;
- req->count = count;
- req->func = check_async_list;
- req->status = status;
- ret = wine_server_call( req );
- }
- SERVER_END_REQ;
- return !ret;
-}
-
/***********************************************************************
* CancelIo (KERNEL32.@)
*/
@@ -1288,21 +1278,61 @@
TRACE("handle = %x\n",handle);
- ovp = NtCurrentTeb()->pending_list;
- while(ovp)
+
+ for (ovp = NtCurrentTeb()->pending_list; ovp; ovp = t)
{
t = ovp->next;
- if(FILE_StartAsync(handle, ovp->lpOverlapped, ovp->type, 0, STATUS_CANCELLED))
+ if (ovp->handle != handle) continue;
+
+ SERVER_START_REQ ( cancel_async )
{
- TRACE("overlapped = %p\n",ovp->lpOverlapped);
- finish_async(ovp, STATUS_CANCELLED);
+ req->handle = handle;
+ req->type = ovp->type;
+ req->overlapped = ovp;
+ wine_server_call ( req );
+ if (reply->cancelled)
+ {
+ TRACE ("cancelling request: %p\n", ovp);
+ ovp->ops->set_status ( ovp, STATUS_CANCELLED );
+ finish_async (ovp);
+ }
}
- ovp = t;
+ SERVER_END_REQ;
}
WaitForMultipleObjectsEx(0,NULL,FALSE,1,TRUE);
return TRUE;
}
+static DWORD fileio_get_async_status (async_private *ovp)
+{
+ return ((async_fileio*) ovp)->lpOverlapped->Internal;
+}
+
+static void fileio_set_async_status (async_private *ovp, DWORD status)
+{
+ ((async_fileio*) ovp)->lpOverlapped->Internal = status;
+}
+
+static DWORD fileio_get_async_count (async_private *ovp)
+{
+ async_fileio *fileio = (async_fileio*) ovp;
+ DWORD ret = fileio->count - fileio->lpOverlapped->InternalHigh;
+ return (ret < 0 ? 0 : ret);
+}
+
+static void CALLBACK fileio_call_completion_func (ULONG_PTR data)
+{
+ async_fileio *ovp = (async_fileio*) data;
+ TRACE ("data: %p\n", ovp);
+
+ if (ovp->completion_func)
+ ovp->completion_func(ovp->lpOverlapped->Internal,
+ ovp->lpOverlapped->InternalHigh,
+ ovp->lpOverlapped);
+
+ HeapFree(GetProcessHeap(), 0, ovp);
+}
+
/***********************************************************************
* FILE_AsyncReadService (INTERNAL)
*
@@ -1311,18 +1341,19 @@
*/
static void FILE_AsyncReadService(async_private *ovp)
{
- LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+ async_fileio *fileio = (async_fileio*) ovp;
+ LPOVERLAPPED lpOverlapped = fileio->lpOverlapped;
int result, r;
int already = lpOverlapped->InternalHigh;
- TRACE("%p %p\n", lpOverlapped, ovp->buffer );
+ TRACE("%p %p\n", lpOverlapped, fileio->buffer );
/* check to see if the data is ready (non-blocking) */
- result = pread (ovp->fd, &ovp->buffer[already], ovp->count - already,
+ result = pread (ovp->fd, &fileio->buffer[already], fileio->count - already,
OVERLAPPED_OFFSET (lpOverlapped) + already);
if ((result < 0) && (errno == ESPIPE))
- result = read (ovp->fd, &ovp->buffer[already], ovp->count - already);
+ result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
{
@@ -1340,9 +1371,9 @@
}
lpOverlapped->InternalHigh += result;
- TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);
+ TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
- if(lpOverlapped->InternalHigh < ovp->count)
+ if(lpOverlapped->InternalHigh < fileio->count)
r = STATUS_PENDING;
else
r = STATUS_SUCCESS;
@@ -1358,7 +1389,7 @@
LPOVERLAPPED overlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- async_private *ovp;
+ async_fileio *ovp;
int fd;
TRACE("file %d to buf %p num %ld %p func %p\n",
@@ -1375,10 +1406,11 @@
if(fd<0)
{
TRACE("Couldn't get FD\n");
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
- ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+ ovp = (async_fileio *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
{
TRACE("HeapAlloc Failed\n");
@@ -1386,30 +1418,20 @@
close(fd);
return FALSE;
}
+
+ ovp->async.ops = &fileio_async_ops;
+ ovp->async.handle = hFile;
+ ovp->async.fd = fd;
+ ovp->async.type = ASYNC_TYPE_READ;
+ ovp->async.func = FILE_AsyncReadService;
ovp->lpOverlapped = overlapped;
- ovp->count = bytesToRead;
ovp->completion_func = lpCompletionRoutine;
- ovp->func = FILE_AsyncReadService;
ovp->buffer = buffer;
- ovp->fd = fd;
- ovp->type = ASYNC_TYPE_READ;
- ovp->handle = hFile;
-
- /* hook this overlap into the pending async operation list */
- ovp->next = NtCurrentTeb()->pending_list;
- ovp->prev = NULL;
- if(ovp->next)
- ovp->next->prev = ovp;
- NtCurrentTeb()->pending_list = ovp;
-
- if ( !FILE_StartAsync(hFile, overlapped, ASYNC_TYPE_READ, bytesToRead, STATUS_PENDING) )
- {
- /* FIXME: remove async_private and release memory */
- ERR("FILE_StartAsync failed\n");
- return FALSE;
- }
+ ovp->count = bytesToRead;
- return TRUE;
+ /* Tell register_async that this is a new request */
+ overlapped->Internal = STATUS_USER_APC;
+ return register_async (&ovp->async);
}
/***********************************************************************
@@ -1419,7 +1441,6 @@
LPOVERLAPPED overlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0;
return FILE_ReadFileEx(hFile,buffer,bytesToRead,overlapped,lpCompletionRoutine);
}
@@ -1503,7 +1524,6 @@
}
/* at last resort, do an overlapped read */
- overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = result;
if(!FILE_ReadFileEx(hFile, buffer, bytesToRead, overlapped, FILE_OverlappedComplete))
@@ -1559,18 +1579,19 @@
*/
static void FILE_AsyncWriteService(struct async_private *ovp)
{
- LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+ async_fileio *fileio = (async_fileio *) ovp;
+ LPOVERLAPPED lpOverlapped = fileio->lpOverlapped;
int result, r;
int already = lpOverlapped->InternalHigh;
- TRACE("(%p %p)\n",lpOverlapped,ovp->buffer);
+ TRACE("(%p %p)\n",lpOverlapped,fileio->buffer);
/* write some data (non-blocking) */
- result = pwrite(ovp->fd, &ovp->buffer[already], ovp->count - already,
+ result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
OVERLAPPED_OFFSET (lpOverlapped) + already);
if ((result < 0) && (errno == ESPIPE))
- result = write(ovp->fd, &ovp->buffer[already], ovp->count - already);
+ result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
{
@@ -1587,9 +1608,9 @@
lpOverlapped->InternalHigh += result;
- TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);
+ TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
- if(lpOverlapped->InternalHigh < ovp->count)
+ if(lpOverlapped->InternalHigh < fileio->count)
r = STATUS_PENDING;
else
r = STATUS_SUCCESS;
@@ -1605,7 +1626,8 @@
LPOVERLAPPED overlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- async_private *ovp;
+ async_fileio *ovp;
+ int fd;
TRACE("file %d to buf %p num %ld %p func %p stub\n",
hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
@@ -1616,45 +1638,36 @@
return FALSE;
}
- overlapped->Internal = STATUS_PENDING;
- overlapped->InternalHigh = 0;
-
- if (!FILE_StartAsync(hFile, overlapped, ASYNC_TYPE_WRITE, bytesToWrite, STATUS_PENDING ))
+ fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+ if(fd<0)
{
- TRACE("FILE_StartAsync failed\n");
+ TRACE("Couldn't get FD\n");
+ SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
- ovp = (async_private*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+ ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
if(!ovp)
{
TRACE("HeapAlloc Failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ close(fd);
return FALSE;
}
+
+ ovp->async.ops = &fileio_async_ops;
+ ovp->async.handle = hFile;
+ ovp->async.fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+ ovp->async.type = ASYNC_TYPE_WRITE;
+ ovp->async.func = FILE_AsyncWriteService;
ovp->lpOverlapped = overlapped;
- ovp->func = FILE_AsyncWriteService;
ovp->buffer = (LPVOID) buffer;
- ovp->count = bytesToWrite;
ovp->completion_func = lpCompletionRoutine;
- ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
- ovp->type = ASYNC_TYPE_WRITE;
- ovp->handle = hFile;
-
- if(ovp->fd <0)
- {
- HeapFree(GetProcessHeap(), 0, ovp);
- return FALSE;
- }
-
- /* hook this overlap into the pending async operation list */
- ovp->next = NtCurrentTeb()->pending_list;
- ovp->prev = NULL;
- if(ovp->next)
- ovp->next->prev = ovp;
- NtCurrentTeb()->pending_list = ovp;
+ ovp->count = bytesToWrite;
- return TRUE;
+ /* Tell register_async that this is a new request */
+ overlapped->Internal = STATUS_USER_APC;
+ return register_async (&ovp->async);
}
/***********************************************************************
@@ -1664,7 +1677,6 @@
LPOVERLAPPED overlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0;
return FILE_WriteFileEx(hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
diff -ruX diffignore CVS/wine/include/file.h MW/wine/include/file.h
--- CVS/wine/include/file.h Tue Jan 15 19:37:37 2002
+++ MW/wine/include/file.h Tue Jan 15 19:09:42 2002
@@ -33,23 +33,46 @@
/* overlapped private structure */
struct async_private;
-typedef void (*async_handler)(struct async_private *ovp);
+
+typedef void (*async_handler) (struct async_private *ovp);
+typedef void CALLBACK (*async_call_completion_func) (ULONG_PTR data);
+typedef DWORD (*async_get_status) (struct async_private *ovp);
+typedef DWORD (*async_get_count) (struct async_private *ovp);
+typedef void (*async_set_status) (struct async_private *ovp, DWORD status);
+
+typedef struct async_ops
+{
+ async_get_status get_status;
+ async_set_status set_status;
+ async_get_count get_count;
+ async_call_completion_func call_completion;
+} async_ops;
+
+extern async_ops fileio_async_ops;
+
typedef struct async_private
{
- LPOVERLAPPED lpOverlapped;
- HANDLE handle;
- int fd;
- char *buffer;
- async_handler func;
- int count;
- int type;
- LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
- struct async_private *next;
- struct async_private *prev;
+ async_ops *ops;
+ HANDLE handle;
+ int fd;
+ int type;
+ async_handler func;
+ struct async_private *next;
+ struct async_private *prev;
} async_private;
-extern void WINAPI check_async_list(LPOVERLAPPED ov, DWORD status);
-extern void finish_async(struct async_private *ovp, DWORD status);
+typedef struct async_fileio
+{
+ async_private async;
+ LPOVERLAPPED lpOverlapped;
+ LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
+ char *buffer;
+ int count;
+} async_fileio;
+
+extern BOOL register_async (async_private *ovp);
+extern void WINAPI check_async_list(async_private *ovp, DWORD status);
+extern void finish_async(async_private *ovp);
/* locale-independent case conversion */
inline static char FILE_tolower( char c )
@@ -82,7 +105,6 @@
DWORD attributes, HANDLE template, BOOL fail_read_only,
UINT drive_type );
extern HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa );
-extern BOOL FILE_StartAsync(HANDLE handle, LPOVERLAPPED lpOverlapped, DWORD type, DWORD count, DWORD status);
extern LONG WINAPI WIN16_hread(HFILE16,SEGPTR,LONG);
diff -ruX diffignore CVS/wine/scheduler/synchro.c MW/wine/scheduler/synchro.c
--- CVS/wine/scheduler/synchro.c Tue Jan 15 19:37:37 2002
+++ MW/wine/scheduler/synchro.c Tue Jan 15 19:09:42 2002
@@ -36,27 +36,60 @@
}
}
-static void CALLBACK call_completion_routine(ULONG_PTR data)
+/***********************************************************************
+ * register_async (INTERNAL)
+ *
+ * Manipulate async request queues.
+ */
+BOOL register_async (async_private *ovp)
{
- async_private* ovp = (async_private*)data;
+ BOOL ret;
+ DWORD status = ovp->ops->get_status (ovp);
- ovp->completion_func(ovp->lpOverlapped->Internal,
- ovp->lpOverlapped->InternalHigh,
- ovp->lpOverlapped);
- ovp->completion_func=NULL;
- HeapFree(GetProcessHeap(), 0, ovp);
-}
+ /* STATUS_USER_APC means this is a new request */
+ /* STATUS_PENDING means this request is rescheduled (IO incomplete) */
-void finish_async(async_private *ovp, DWORD status)
-{
- ovp->lpOverlapped->Internal=status;
+ if ( status == STATUS_USER_APC )
+ {
+ status = STATUS_PENDING;
+ ovp->ops->set_status (ovp, status);
+
+ /* hook this overlap into the pending async operation list */
+ ovp->next = NtCurrentTeb()->pending_list;
+ ovp->prev = NULL;
+ if (ovp->next) ovp->next->prev = ovp;
+ NtCurrentTeb()->pending_list = ovp;
+ }
- /* call ReadFileEx/WriteFileEx's overlapped completion function */
- if(ovp->completion_func)
+ /* The server call will destroy all except PENDING requests */
+ SERVER_START_REQ( register_async )
{
- QueueUserAPC(call_completion_routine,GetCurrentThread(),(ULONG_PTR)ovp);
+ req->handle = ovp->handle;
+ req->overlapped = ovp;
+ req->type = ovp->type;
+ req->count = ovp->ops->get_count (ovp);
+ req->func = check_async_list;
+ req->status = status;
+ ret = wine_server_call( req );
}
+ SERVER_END_REQ;
+
+ if (ret) ovp->ops->set_status ( ovp, GetLastError() );
+ if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
+ finish_async (ovp);
+
+ return !ret;
+}
+
+/***********************************************************************
+ * finish_async (INTERNAL)
+ *
+ * Called after completion or cancellation of an async request.
+ * Note: The completion status must be set already.
+ */
+void finish_async(async_private *ovp)
+{
/* remove it from the active list */
if(ovp->prev)
ovp->prev->next = ovp->next;
@@ -70,7 +103,9 @@
ovp->prev=NULL;
close(ovp->fd);
- if(!ovp->completion_func) HeapFree(GetProcessHeap(), 0, ovp);
+
+ /* Queue completion function unconditionally */
+ QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
}
/***********************************************************************
@@ -78,30 +113,29 @@
*
* Process a status event from the server.
*/
-void WINAPI check_async_list(LPOVERLAPPED overlapped, DWORD status)
+void WINAPI check_async_list(async_private *asp, DWORD status)
{
- async_private *ovp;
+ async_private *ovp = NULL;
+ DWORD ovp_status;
/* fprintf(stderr,"overlapped %p status %x\n",overlapped,status); */
- for(ovp = NtCurrentTeb()->pending_list; ovp; ovp = ovp->next)
- if(ovp->lpOverlapped == overlapped)
- break;
+ for( ovp = NtCurrentTeb()->pending_list; ovp && ovp != asp; ovp = ovp->next );
- if(!ovp)
+ if(!ovp)
return;
if(status != STATUS_ALERTED)
- ovp->lpOverlapped->Internal = status;
+ {
+ ovp_status = status;
+ ovp->ops->set_status (ovp, status);
+ }
+ else ovp_status = ovp->ops->get_status (ovp);
- if(ovp->lpOverlapped->Internal==STATUS_PENDING)
- {
- ovp->func(ovp);
- FILE_StartAsync(ovp->handle, ovp->lpOverlapped, ovp->type, 0, ovp->lpOverlapped->Internal);
- }
+ if( ovp_status == STATUS_PENDING ) ovp->func(ovp);
- if(ovp->lpOverlapped->Internal!=STATUS_PENDING)
- finish_async(ovp,ovp->lpOverlapped->Internal);
+ /* This will destroy all but PENDING requests */
+ register_async (ovp);
}
diff -ruX diffignore CVS/wine/server/async.c MW/wine/server/async.c
--- CVS/wine/server/async.c Tue Jan 15 19:37:37 2002
+++ MW/wine/server/async.c Tue Jan 15 19:09:42 2002
@@ -177,3 +177,28 @@
release_object(obj);
}
+DECL_HANDLER(cancel_async)
+{
+ struct object *obj;
+
+ if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL)) )
+ return;
+
+ if(obj->ops->queue_async)
+ {
+ struct async_queue *q = obj->ops->queue_async(obj, NULL, req->type, 0);
+ struct async *async;
+
+ async = find_async(q, current, req->overlapped);
+ if (async)
+ {
+ destroy_async(async);
+ reply->cancelled = 1;
+ set_select_events(obj,obj->ops->get_poll_events(obj));
+ }
+ else reply->cancelled = 0;
+ }
+
+ release_object(obj);
+}
+
diff -ruX diffignore CVS/wine/server/protocol.def MW/wine/server/protocol.def
--- CVS/wine/server/protocol.def Tue Jan 15 19:37:37 2002
+++ MW/wine/server/protocol.def Tue Jan 15 19:09:42 2002
@@ -1534,7 +1534,7 @@
#define SERIALINFO_SET_ERROR 0x04
-/* Create/Destroy an async I/O */
+/* Create / reschedule an async I/O */
@REQ(register_async)
handle_t handle; /* handle to comm port, socket or file */
void* func;
@@ -1548,6 +1548,14 @@
#define ASYNC_TYPE_WRITE 0x02
#define ASYNC_TYPE_WAIT 0x03
+/* Cancel an async I/O */
+ at REQ(cancel_async)
+ handle_t handle;
+ int type;
+ void* overlapped;
+ at REPLY
+ int cancelled;
+ at END
/* Create a named pipe */
@REQ(create_named_pipe)
More information about the wine-patches
mailing list