wine/include/async.h
Eric Pouech 9bd4f6bf15 - made async.h ready for use in ntdll: replaced all calls to kernel32
functions with ntdll equivalent
- replaced status setter/getter for wine async structures with direct
  access to a (now included) IO_STATUS_BLOCK structure
- since we now have a IO_STATUS_BLOCK in async_private, we no longer
  need in most of the user (derivated) structures a field for
  LPOVERLAPPED (it's stored as the IO_STATUS_BLOCK)
- rewrote the async.h users accordingly
- implemented ntdll.Nt{Read|Write}File and let
  kernel32.{Read|Write}File(Ex)? use those new ntdll functions
- rewrote smb read/write interfaces to be more ntdll stylish (no
  overlapped yet)
2003-06-26 02:08:17 +00:00

137 lines
3.8 KiB
C

/*
* 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"
#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;
close(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;
}
#define register_old_async(ovp) \
__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 */