Commit 9bd4f6bf authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- 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)
parent 6235e935
......@@ -84,6 +84,8 @@
# include <sys/strtio.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "winbase.h"
#include "winerror.h"
......@@ -104,15 +106,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(comm);
* Asynchronous I/O for asynchronous wait requests *
*/
static DWORD commio_get_async_status (const async_private *ovp);
static DWORD commio_get_async_count (const async_private *ovp);
static void commio_set_async_status (async_private *ovp, const DWORD status);
static void commio_async_cleanup (async_private *ovp);
static async_ops commio_async_ops =
{
commio_get_async_status, /* get_status */
commio_set_async_status, /* set_status */
commio_get_async_count, /* get_count */
NULL, /* call_completion */
commio_async_cleanup /* cleanup */
......@@ -121,20 +119,9 @@ static async_ops commio_async_ops =
typedef struct async_commio
{
struct async_private async;
LPOVERLAPPED lpOverlapped;
char *buffer;
} async_commio;
static DWORD commio_get_async_status (const struct async_private *ovp)
{
return ((async_commio*) ovp)->lpOverlapped->Internal;
}
static void commio_set_async_status (async_private *ovp, const DWORD status)
{
((async_commio*) ovp)->lpOverlapped->Internal = status;
}
static DWORD commio_get_async_count (const struct async_private *ovp)
{
return 0;
......@@ -1664,14 +1651,14 @@ BOOL WINAPI GetCommModemStatus(
static void COMM_WaitCommEventService(async_private *ovp)
{
async_commio *commio = (async_commio*) ovp;
LPOVERLAPPED lpOverlapped = commio->lpOverlapped;
IO_STATUS_BLOCK* iosb = commio->async.iosb;
TRACE("overlapped %p\n",lpOverlapped);
TRACE("iosb %p\n",iosb);
/* FIXME: detect other events */
*commio->buffer = EV_RXCHAR;
lpOverlapped->Internal = STATUS_SUCCESS;
iosb->u.Status = STATUS_SUCCESS;
}
......@@ -1714,7 +1701,7 @@ static BOOL COMM_WaitCommEvent(
ovp->async.type = ASYNC_TYPE_WAIT;
ovp->async.func = COMM_WaitCommEventService;
ovp->async.event = lpOverlapped->hEvent;
ovp->lpOverlapped = lpOverlapped;
ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
ovp->buffer = (char *)lpdwEvents;
lpOverlapped->InternalHigh = 0;
......
......@@ -32,11 +32,12 @@
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "wincon.h"
#include "kernel_private.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "async.h"
WINE_DEFAULT_DEBUG_CHANNEL(file);
......@@ -45,6 +46,106 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
**************************************************************************/
/***********************************************************************
* GetOverlappedResult (KERNEL32.@)
*
* Check the result of an Asynchronous data transfer from a file.
*
* Parameters
* HANDLE hFile [in] handle of file to check on
* LPOVERLAPPED lpOverlapped [in/out] pointer to overlapped
* LPDWORD lpTransferred [in/out] number of bytes transferred
* BOOL bWait [in] wait for the transfer to complete ?
*
* RETURNS
* TRUE on success
* FALSE on failure
*
* If successful (and relevant) lpTransferred will hold the number of
* bytes transferred during the async operation.
*
* BUGS
*
* Currently only works for WaitCommEvent, ReadFile, WriteFile
* with communications ports.
*
*/
BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
LPDWORD lpTransferred, BOOL bWait)
{
DWORD r;
TRACE("(%p %p %p %x)\n", hFile, lpOverlapped, lpTransferred, bWait);
if (lpOverlapped==NULL)
{
ERR("lpOverlapped was null\n");
return FALSE;
}
if (!lpOverlapped->hEvent)
{
ERR("lpOverlapped->hEvent was null\n");
return FALSE;
}
if ( bWait )
{
do {
TRACE("waiting on %p\n",lpOverlapped);
r = WaitForSingleObjectEx(lpOverlapped->hEvent, INFINITE, TRUE);
TRACE("wait on %p returned %ld\n",lpOverlapped,r);
} while (r==STATUS_USER_APC);
}
else if ( lpOverlapped->Internal == STATUS_PENDING )
{
/* Wait in order to give APCs a chance to run. */
/* This is cheating, so we must set the event again in case of success -
it may be a non-manual reset event. */
do {
TRACE("waiting on %p\n",lpOverlapped);
r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE);
TRACE("wait on %p returned %ld\n",lpOverlapped,r);
} while (r==STATUS_USER_APC);
if ( r == WAIT_OBJECT_0 )
NtSetEvent ( lpOverlapped->hEvent, NULL );
}
if(lpTransferred)
*lpTransferred = lpOverlapped->InternalHigh;
switch ( lpOverlapped->Internal )
{
case STATUS_SUCCESS:
return TRUE;
case STATUS_PENDING:
SetLastError ( ERROR_IO_INCOMPLETE );
if ( bWait ) ERR ("PENDING status after waiting!\n");
return FALSE;
default:
SetLastError ( RtlNtStatusToDosError ( lpOverlapped->Internal ) );
return FALSE;
}
}
/***********************************************************************
* CancelIo (KERNEL32.@)
*/
BOOL WINAPI CancelIo(HANDLE handle)
{
async_private *ovp,*t;
TRACE("handle = %p\n",handle);
for (ovp = NtCurrentTeb()->pending_list; ovp; ovp = t)
{
t = ovp->next;
if ( ovp->handle == handle )
cancel_async ( ovp );
}
WaitForMultipleObjectsEx(0,NULL,FALSE,1,TRUE);
return TRUE;
}
/***********************************************************************
* _hread (KERNEL32.@)
*/
LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count)
......
......@@ -446,9 +446,9 @@ static void WINAPI check_async_list(async_private *asp, DWORD status)
if( status != STATUS_ALERTED )
{
ovp_status = status;
ovp->ops->set_status (ovp, status);
ovp->iosb->u.Status = status;
}
else ovp_status = ovp->ops->get_status (ovp);
else ovp_status = ovp->iosb->u.Status;
if( ovp_status == STATUS_PENDING ) ovp->func( ovp );
......
......@@ -107,6 +107,8 @@
# include <sys/time.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "wine/winbase16.h"
#include "wingdi.h"
#include "winuser.h"
......@@ -147,16 +149,12 @@ extern CRITICAL_SECTION csWSgetXXXbyYYY;
****************************************************************/
#include "async.h"
static DWORD ws2_async_get_status (const struct async_private *ovp);
static DWORD ws2_async_get_count (const struct async_private *ovp);
static void ws2_async_set_status (struct async_private *ovp, const DWORD status);
static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
static void ws2_async_cleanup ( struct async_private *ovp );
static struct async_ops ws2_async_ops =
{
ws2_async_get_status,
ws2_async_set_status,
ws2_async_get_count,
ws2_async_call_completion,
ws2_async_cleanup
......@@ -164,8 +162,6 @@ static struct async_ops ws2_async_ops =
static struct async_ops ws2_nocomp_async_ops =
{
ws2_async_get_status,
ws2_async_set_status,
ws2_async_get_count,
NULL, /* call_completion */
ws2_async_cleanup
......@@ -174,12 +170,11 @@ static struct async_ops ws2_nocomp_async_ops =
typedef struct ws2_async
{
async_private async;
LPWSAOVERLAPPED overlapped;
LPWSAOVERLAPPED user_overlapped;
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
struct iovec *iovec;
int n_iovecs;
struct WS_sockaddr *addr;
struct WS_sockaddr *addr;
union {
int val; /* for send operations */
int *ptr; /* for recv operations */
......@@ -1021,31 +1016,24 @@ inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_socka
* Functions for handling overlapped I/O
**************************************************************************/
static DWORD ws2_async_get_status (const struct async_private *ovp)
{
return ((ws2_async*) ovp)->overlapped->Internal;
}
static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
{
((ws2_async*) ovp)->overlapped->Internal = status;
}
static DWORD ws2_async_get_count (const struct async_private *ovp)
{
return ((ws2_async*) ovp)->overlapped->InternalHigh;
return ovp->iosb->Information;
}
static void ws2_async_cleanup ( struct async_private *ap )
{
struct ws2_async *as = (struct ws2_async*) ap;
TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
if ( !as->user_overlapped )
{
#if 0
/* FIXME: I don't think this is really used */
if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
WSACloseEvent ( as->overlapped->hEvent );
HeapFree ( GetProcessHeap(), 0, as->overlapped );
#endif
HeapFree ( GetProcessHeap(), 0, as->async.iosb );
}
if ( as->iovec )
......@@ -1060,8 +1048,8 @@ static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
TRACE ("data: %p\n", as);
as->completion_func ( NtStatusToWSAError (as->overlapped->Internal),
as->overlapped->InternalHigh,
as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
as->async.iosb->Information,
as->user_overlapped,
as->flags );
ws2_async_cleanup ( &as->async );
......@@ -1114,22 +1102,22 @@ WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferC
if ( lpOverlapped )
{
wsa->overlapped = lpOverlapped;
wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
}
else
{
wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
sizeof (WSAOVERLAPPED) );
if ( !wsa->overlapped )
wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
sizeof (IO_STATUS_BLOCK) );
if ( !wsa->async.iosb )
goto error;
wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
wsa->async.event = INVALID_HANDLE_VALUE;
}
wsa->overlapped->InternalHigh = 0;
TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
wsa->async.iosb->Information = 0;
TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
return wsa;
......@@ -1220,9 +1208,9 @@ static void WS2_async_recv ( async_private *as )
TRACE ( "async %p\n", wsa );
if ( wsa->overlapped->Internal != STATUS_PENDING )
if ( wsa->async.iosb->u.Status != STATUS_PENDING )
{
TRACE ( "status: %ld\n", wsa->overlapped->Internal );
TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
return;
}
......@@ -1231,8 +1219,8 @@ static void WS2_async_recv ( async_private *as )
if (result >= 0)
{
wsa->overlapped->Internal = STATUS_SUCCESS;
wsa->overlapped->InternalHigh = result;
wsa->async.iosb->u.Status = STATUS_SUCCESS;
wsa->async.iosb->Information = result;
TRACE ( "received %d bytes\n", result );
_enable_event ( wsa->async.handle, FD_READ, 0, 0 );
return;
......@@ -1241,13 +1229,13 @@ static void WS2_async_recv ( async_private *as )
err = wsaErrno ();
if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
{
wsa->overlapped->Internal = STATUS_PENDING;
wsa->async.iosb->u.Status = STATUS_PENDING;
_enable_event ( wsa->async.handle, FD_READ, 0, 0 );
TRACE ( "still pending\n" );
}
else
{
wsa->overlapped->Internal = err;
wsa->async.iosb->u.Status = err;
TRACE ( "Error: %x\n", err );
}
}
......@@ -1312,9 +1300,9 @@ static void WS2_async_send ( async_private *as )
TRACE ( "async %p\n", wsa );
if ( wsa->overlapped->Internal != STATUS_PENDING )
if ( wsa->async.iosb->u.Status != STATUS_PENDING )
{
TRACE ( "status: %ld\n", wsa->overlapped->Internal );
TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
return;
}
......@@ -1323,8 +1311,8 @@ static void WS2_async_send ( async_private *as )
if (result >= 0)
{
wsa->overlapped->Internal = STATUS_SUCCESS;
wsa->overlapped->InternalHigh = result;
wsa->async.iosb->u.Status = STATUS_SUCCESS;
wsa->async.iosb->Information = result;
TRACE ( "sent %d bytes\n", result );
_enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
return;
......@@ -1333,7 +1321,7 @@ static void WS2_async_send ( async_private *as )
err = wsaErrno ();
if ( err == WSAEINTR )
{
wsa->overlapped->Internal = STATUS_PENDING;
wsa->async.iosb->u.Status = STATUS_PENDING;
_enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
TRACE ( "still pending\n" );
}
......@@ -1341,7 +1329,7 @@ static void WS2_async_send ( async_private *as )
{
/* We set the status to a winsock error code and check for that
later in NtStatusToWSAError () */
wsa->overlapped->Internal = err;
wsa->async.iosb->u.Status = err;
TRACE ( "Error: %x\n", err );
}
}
......@@ -1370,9 +1358,9 @@ static void WS2_async_shutdown ( async_private *as )
}
if ( err )
wsa->overlapped->Internal = wsaErrno ();
wsa->async.iosb->u.Status = wsaErrno ();
else
wsa->overlapped->Internal = STATUS_SUCCESS;
wsa->async.iosb->u.Status = STATUS_SUCCESS;
}
/***********************************************************************
......@@ -2461,7 +2449,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
err = NtStatusToWSAError ( ret );
if ( !lpOverlapped )
HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
HeapFree ( GetProcessHeap(), 0, wsa );
goto err_free;
}
......@@ -3918,7 +3906,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
err = NtStatusToWSAError ( ret );
if ( !lpOverlapped )
HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
HeapFree ( GetProcessHeap(), 0, wsa );
goto err_free;
}
......
......@@ -100,6 +100,8 @@
#include <netdb.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
......@@ -202,7 +204,7 @@ static inline CHAR *SMB_nextSepA (CHAR *s) {while (*s && !SMB_isSepA (*s)) s++;
* replacing separators with null characters
*/
USHORT SMB_MultiplexId = 0;
static USHORT SMB_MultiplexId = 0;
struct NB_Buffer
{
......@@ -1532,16 +1534,15 @@ done:
return handle;
}
static BOOL SMB_GetSmbInfo(HANDLE hFile, USHORT *tree_id, USHORT *user_id, USHORT *dialect, USHORT *file_id, LPDWORD offset)
static NTSTATUS SMB_GetSmbInfo(HANDLE hFile, USHORT *tree_id, USHORT *user_id, USHORT *dialect, USHORT *file_id, LPDWORD offset)
{
int r;
NTSTATUS status;
SERVER_START_REQ( get_smb_info )
{
req->handle = hFile;
req->flags = 0;
SetLastError(0);
r = wine_server_call_err( req );
status = wine_server_call( req );
if(tree_id)
*tree_id = reply->tree_id;
if(user_id)
......@@ -1555,12 +1556,12 @@ static BOOL SMB_GetSmbInfo(HANDLE hFile, USHORT *tree_id, USHORT *user_id, USHOR
}
SERVER_END_REQ;
return !r;
return status;
}
static BOOL SMB_SetOffset(HANDLE hFile, DWORD offset)
static NTSTATUS SMB_SetOffset(HANDLE hFile, DWORD offset)
{
int r;
NTSTATUS status;
TRACE("offset = %08lx\n",offset);
......@@ -1569,61 +1570,53 @@ static BOOL SMB_SetOffset(HANDLE hFile, DWORD offset)
req->handle = hFile;
req->flags = SMBINFO_SET_OFFSET;
req->offset = offset;
SetLastError(0);
r = wine_server_call_err( req );
status = wine_server_call( req );
/* if(offset)
*offset = reply->offset; */
}
SERVER_END_REQ;
return !r;
return status;
}
BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED lpOverlapped)
NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
PIO_STATUS_BLOCK io_status)
{
int fd;
DWORD total, count, offset;
DWORD count, offset;
USHORT user_id, tree_id, dialect, file_id, read;
BOOL r=TRUE;
TRACE("%p %p %ld %p\n", hFile, buffer, bytesToRead, bytesRead);
TRACE("%p %p %ld %p\n", hFile, buffer, bytesToRead, io_status);
if(!SMB_GetSmbInfo(hFile, &tree_id, &user_id, &dialect, &file_id, &offset))
return FALSE;
io_status->Information = 0;
io_status->u.Status = SMB_GetSmbInfo(hFile, &tree_id, &user_id, &dialect, &file_id, &offset);
if (io_status->u.Status) return io_status->u.Status;
fd = FILE_GetUnixHandle(hFile, GENERIC_READ);
if(fd<0)
return FALSE;
if (fd<0) return io_status->u.Status = STATUS_INVALID_HANDLE;
total = 0;
while(1)
{
count = bytesToRead - total;
count = bytesToRead - io_status->Information;
if(count>0x400)
count = 0x400;
if(count==0)
break;
read = 0;
r = SMB_Read(fd, tree_id, user_id, dialect, file_id, offset, buffer, count, &read);
if(!r)
if (!SMB_Read(fd, tree_id, user_id, dialect, file_id, offset, buffer, count, &read))
break;
if(!read)
break;
total += read;
io_status->Information += read;
buffer = (char*)buffer + read;
offset += read;
if(total>=bytesToRead)
if(io_status->Information >= bytesToRead)
break;
}
close(fd);
if(bytesRead)
*bytesRead = total;
if(!SMB_SetOffset(hFile, offset))
return FALSE;
return r;
return io_status->u.Status = SMB_SetOffset(hFile, offset);
}
SMB_DIR* WINAPI SMB_FindFirst(LPCWSTR name)
......
......@@ -22,7 +22,8 @@
extern inline int SMB_isSepW (WCHAR c) {return (c == '\\' || c == '/');}
extern inline int SMB_isUNCW (LPCWSTR filename) {return (filename && SMB_isSepW (filename[0]) && SMB_isSepW (filename[1]));}
extern BOOL WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED lpOverlapped);
NTSTATUS WINAPI SMB_ReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
PIO_STATUS_BLOCK io_status);
extern HANDLE WINAPI SMB_CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE template );
......
......@@ -27,20 +27,17 @@
#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_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;
......@@ -48,43 +45,50 @@ typedef struct 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;
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)
if (ovp->prev)
ovp->prev->next = ovp->next;
else
NtCurrentTeb()->pending_list = ovp->next;
if(ovp->next)
if (ovp->next)
ovp->next->prev = ovp->prev;
ovp->next = ovp->prev = NULL;
close( ovp->fd );
if( ovp->event != INVALID_HANDLE_VALUE )
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 );
NtQueueApcThread( GetCurrentThread(), call_user_apc,
(ULONG_PTR)ovp->ops->call_completion, (ULONG_PTR)ovp, 0 );
else
ovp->ops->cleanup ( ovp );
ovp->ops->cleanup( ovp );
}
inline static BOOL __register_async( async_private *ovp, const DWORD status )
inline static NTSTATUS __register_async( async_private *ovp, const DWORD status )
{
BOOL ret;
NTSTATUS ret;
SERVER_START_REQ( register_async )
{
......@@ -97,23 +101,20 @@ inline static BOOL __register_async( async_private *ovp, const DWORD status )
}
SERVER_END_REQ;
if ( ret ) {
SetLastError( RtlNtStatusToDosError(ret) );
ovp->ops->set_status ( ovp, ret );
}
if (ret) ovp->iosb->u.Status = ret;
if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
finish_async (ovp);
if ( ovp->iosb->u.Status != STATUS_PENDING )
finish_async(ovp);
return ret;
}
#define register_old_async(ovp) \
__register_async (ovp, ovp->ops->get_status( ovp ));
__register_async(ovp, ovp->iosb->u.Status);
inline static BOOL register_new_async( async_private *ovp )
inline static NTSTATUS register_new_async( async_private *ovp )
{
ovp->ops->set_status ( ovp, STATUS_PENDING );
ovp->iosb->u.Status = STATUS_PENDING;
ovp->next = NtCurrentTeb()->pending_list;
ovp->prev = NULL;
......@@ -123,13 +124,13 @@ inline static BOOL register_new_async( async_private *ovp )
return __register_async( ovp, STATUS_PENDING );
}
inline static BOOL cancel_async ( async_private *ovp )
inline static NTSTATUS 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 );
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 */
......@@ -991,6 +991,7 @@ NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,PLARGE_INTEGER);
NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,PLARGE_INTEGER);
NTSTATUS WINAPI NtWriteFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,const void*,ULONG,PLARGE_INTEGER,PULONG);
void WINAPI RtlAcquirePebLock(void);
BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK,BYTE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment