| /* |
| * Structures and static functions for handling asynchronous I/O. |
| * |
| * Copyright (C) 2002 Mike McCormack, Martin Wilck |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| /* |
| * This file declares static functions. |
| * It should only be included by those source files that implement async I/O requests. |
| */ |
| |
| #ifndef __WINE_ASYNC_H |
| #define __WINE_ASYNC_H |
| |
| #include "wine/server.h" |
| |
| struct async_private; |
| |
| typedef void (*async_handler)(struct async_private *ovp); |
| typedef void CALLBACK (*async_call_completion_func)(ULONG_PTR data); |
| typedef DWORD (*async_get_status)(const struct async_private *ovp); |
| typedef DWORD (*async_get_count)(const struct async_private *ovp); |
| typedef void (*async_set_status)(struct async_private *ovp, const DWORD status); |
| typedef void (*async_cleanup)(struct async_private *ovp); |
| |
| 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_cleanup cleanup; |
| } async_ops; |
| |
| typedef struct async_private |
| { |
| struct async_ops *ops; |
| HANDLE handle; |
| HANDLE event; |
| int fd; |
| async_handler func; |
| int type; |
| struct async_private *next; |
| struct async_private *prev; |
| } async_private; |
| |
| /* All functions declared static for Dll separation purposes */ |
| |
| inline static void finish_async( async_private *ovp ) |
| { |
| if(ovp->prev) |
| ovp->prev->next = ovp->next; |
| else |
| NtCurrentTeb()->pending_list = ovp->next; |
| |
| if(ovp->next) |
| ovp->next->prev = ovp->prev; |
| |
| ovp->next = ovp->prev = NULL; |
| |
| close( ovp->fd ); |
| if( ovp->event != INVALID_HANDLE_VALUE ) |
| NtSetEvent( ovp->event, NULL ); |
| |
| if ( ovp->ops->call_completion ) |
| QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp ); |
| else |
| ovp->ops->cleanup ( ovp ); |
| } |
| |
| inline static BOOL __register_async( async_private *ovp, const DWORD status ) |
| { |
| BOOL ret; |
| |
| SERVER_START_REQ( register_async ) |
| { |
| req->handle = ovp->handle; |
| req->overlapped = ovp; |
| req->type = ovp->type; |
| req->count = ovp->ops->get_count( ovp ); |
| req->status = status; |
| ret = wine_server_call( req ); |
| } |
| SERVER_END_REQ; |
| |
| if ( ret ) { |
| SetLastError( RtlNtStatusToDosError(ret) ); |
| ovp->ops->set_status ( ovp, ret ); |
| } |
| |
| if ( ovp->ops->get_status (ovp) != STATUS_PENDING ) |
| finish_async (ovp); |
| |
| return ret; |
| } |
| |
| #define register_old_async(ovp) \ |
| __register_async (ovp, ovp->ops->get_status( ovp )); |
| |
| inline static BOOL register_new_async( async_private *ovp ) |
| { |
| ovp->ops->set_status ( ovp, STATUS_PENDING ); |
| |
| ovp->next = NtCurrentTeb()->pending_list; |
| ovp->prev = NULL; |
| if ( ovp->next ) ovp->next->prev = ovp; |
| NtCurrentTeb()->pending_list = ovp; |
| |
| return __register_async( ovp, STATUS_PENDING ); |
| } |
| |
| inline static BOOL cancel_async ( async_private *ovp ) |
| { |
| /* avoid multiple cancellations */ |
| if ( ovp->ops->get_status( ovp ) != STATUS_PENDING ) |
| return 0; |
| ovp->ops->set_status ( ovp, STATUS_CANCELLED ); |
| return __register_async ( ovp, STATUS_CANCELLED ); |
| } |
| |
| #endif /* __WINE_ASYNC_H */ |