| /* | |
| * 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 <thread.h> | |
| #include <ntstatus.h> | |
| #include <wine/server.h> | |
| #include <winternl.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_count)(const struct async_private *ovp); | |
| typedef void (*async_cleanup)(struct async_private *ovp); | |
| typedef struct async_ops | |
| { | |
| 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; | |
| IO_STATUS_BLOCK* iosb; | |
| struct async_private* next; | |
| struct async_private* prev; | |
| } async_private; | |
| /* All functions declared static for Dll separation purposes */ | |
| static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 ) | |
| { | |
| PAPCFUNC func = (PAPCFUNC)arg1; | |
| func( arg2 ); | |
| } | |
| 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; | |
| wine_server_release_fd( ovp->handle, ovp->fd ); | |
| if ( ovp->event != INVALID_HANDLE_VALUE ) | |
| NtSetEvent( ovp->event, NULL ); | |
| if ( ovp->ops->call_completion ) | |
| NtQueueApcThread( GetCurrentThread(), call_user_apc, | |
| (ULONG_PTR)ovp->ops->call_completion, (ULONG_PTR)ovp, 0 ); | |
| else | |
| ovp->ops->cleanup( ovp ); | |
| } | |
| inline static NTSTATUS __register_async( async_private *ovp, const DWORD status ) | |
| { | |
| NTSTATUS 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) ovp->iosb->u.Status = ret; | |
| if ( ovp->iosb->u.Status != STATUS_PENDING ) | |
| finish_async(ovp); | |
| return ret; | |
| } | |
| inline static NTSTATUS register_old_async( async_private *ovp ) | |
| { | |
| return __register_async(ovp, ovp->iosb->u.Status); | |
| } | |
| inline static NTSTATUS register_new_async( async_private *ovp ) | |
| { | |
| ovp->iosb->u.Status = 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 NTSTATUS cancel_async( async_private *ovp ) | |
| { | |
| /* avoid multiple cancellations */ | |
| if ( ovp->iosb->u.Status != STATUS_PENDING ) | |
| return STATUS_SUCCESS; | |
| ovp->iosb->u.Status = STATUS_CANCELLED; | |
| return __register_async( ovp, STATUS_CANCELLED ); | |
| } | |
| #endif /* __WINE_ASYNC_H */ |