Commit 08867f71 authored by Martin Wilck's avatar Martin Wilck Committed by Alexandre Julliard

- Need a "cleanup" method.

- calling the "call_completion" method unconditionally in finish_async (introduced by me) was wrong, because the thread may never be in an alertable wait state -> call it only if user completion function is present. - We need two constant "ops" objects, one with and one without call_completion method (the event field may NOT be used to determine whether the completion must be called or not).
parent 18c1514c
...@@ -99,14 +99,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(comm); ...@@ -99,14 +99,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(comm);
static DWORD commio_get_async_status (const async_private *ovp); static DWORD commio_get_async_status (const async_private *ovp);
static DWORD commio_get_async_count (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_set_async_status (async_private *ovp, const DWORD status);
static void CALLBACK commio_call_completion_func (ULONG_PTR data); static void commio_async_cleanup (async_private *ovp);
static async_ops commio_async_ops = static async_ops commio_async_ops =
{ {
commio_get_async_status, /* get_status */ commio_get_async_status, /* get_status */
commio_set_async_status, /* set_status */ commio_set_async_status, /* set_status */
commio_get_async_count, /* get_count */ commio_get_async_count, /* get_count */
commio_call_completion_func /* call_completion */ NULL, /* call_completion */
commio_async_cleanup /* cleanup */
}; };
typedef struct async_commio typedef struct async_commio
...@@ -131,9 +132,9 @@ static DWORD commio_get_async_count (const struct async_private *ovp) ...@@ -131,9 +132,9 @@ static DWORD commio_get_async_count (const struct async_private *ovp)
return 0; return 0;
} }
static void CALLBACK commio_call_completion_func (ULONG_PTR data) static void commio_async_cleanup (async_private *ovp)
{ {
HeapFree(GetProcessHeap(), 0, (void*) data); HeapFree(GetProcessHeap(), 0, ovp );
} }
/***********************************************************************/ /***********************************************************************/
......
...@@ -88,13 +88,24 @@ static DWORD fileio_get_async_status (const async_private *ovp); ...@@ -88,13 +88,24 @@ static DWORD fileio_get_async_status (const async_private *ovp);
static DWORD fileio_get_async_count (const async_private *ovp); static DWORD fileio_get_async_count (const async_private *ovp);
static void fileio_set_async_status (async_private *ovp, const DWORD status); static void fileio_set_async_status (async_private *ovp, const DWORD status);
static void CALLBACK fileio_call_completion_func (ULONG_PTR data); static void CALLBACK fileio_call_completion_func (ULONG_PTR data);
static void fileio_async_cleanup (async_private *ovp);
static async_ops fileio_async_ops = static async_ops fileio_async_ops =
{ {
fileio_get_async_status, /* get_status */ fileio_get_async_status, /* get_status */
fileio_set_async_status, /* set_status */ fileio_set_async_status, /* set_status */
fileio_get_async_count, /* get_count */ fileio_get_async_count, /* get_count */
fileio_call_completion_func /* call_completion */ fileio_call_completion_func, /* call_completion */
fileio_async_cleanup /* cleanup */
};
static async_ops fileio_nocomp_async_ops =
{
fileio_get_async_status, /* get_status */
fileio_set_async_status, /* set_status */
fileio_get_async_count, /* get_count */
NULL, /* call_completion */
fileio_async_cleanup /* cleanup */
}; };
typedef struct async_fileio typedef struct async_fileio
...@@ -128,12 +139,16 @@ static void CALLBACK fileio_call_completion_func (ULONG_PTR data) ...@@ -128,12 +139,16 @@ static void CALLBACK fileio_call_completion_func (ULONG_PTR data)
async_fileio *ovp = (async_fileio*) data; async_fileio *ovp = (async_fileio*) data;
TRACE ("data: %p\n", ovp); TRACE ("data: %p\n", ovp);
if (ovp->completion_func) ovp->completion_func( ovp->lpOverlapped->Internal,
ovp->completion_func(ovp->lpOverlapped->Internal,
ovp->lpOverlapped->InternalHigh, ovp->lpOverlapped->InternalHigh,
ovp->lpOverlapped); ovp->lpOverlapped );
HeapFree(GetProcessHeap(), 0, ovp); fileio_async_cleanup ( &ovp->async );
}
static void fileio_async_cleanup ( struct async_private *ovp )
{
HeapFree ( GetProcessHeap(), 0, ovp );
} }
/*********************************************************************** /***********************************************************************
...@@ -1478,6 +1493,8 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, ...@@ -1478,6 +1493,8 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
{ {
async_fileio *ovp; async_fileio *ovp;
int fd; int fd;
int flags;
enum fd_type type;
TRACE("file %d to buf %p num %ld %p func %p\n", TRACE("file %d to buf %p num %ld %p func %p\n",
hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine); hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine);
...@@ -1489,10 +1506,11 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, ...@@ -1489,10 +1506,11 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
return FALSE; return FALSE;
} }
fd = FILE_GetUnixHandle( hFile, GENERIC_READ ); fd = FILE_GetUnixHandleType ( hFile, GENERIC_READ, &type, &flags);
if(fd<0) if ( fd < 0 )
{ {
TRACE("Couldn't get FD\n"); WARN ( "Couldn't get FD\n" );
SetLastError ( ERROR_INVALID_PARAMETER );
return FALSE; return FALSE;
} }
...@@ -1501,11 +1519,10 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, ...@@ -1501,11 +1519,10 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
{ {
TRACE("HeapAlloc Failed\n"); TRACE("HeapAlloc Failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY); SetLastError(ERROR_NOT_ENOUGH_MEMORY);
close(fd); goto error;
return FALSE;
} }
ovp->async.ops = &fileio_async_ops; ovp->async.ops = ( lpCompletionRoutine ? &fileio_async_ops : &fileio_nocomp_async_ops );
ovp->async.handle = hFile; ovp->async.handle = hFile;
ovp->async.fd = fd; ovp->async.fd = fd;
ovp->async.type = ASYNC_TYPE_READ; ovp->async.type = ASYNC_TYPE_READ;
...@@ -1517,6 +1534,11 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, ...@@ -1517,6 +1534,11 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
ovp->buffer = buffer; ovp->buffer = buffer;
return !register_new_async (&ovp->async); return !register_new_async (&ovp->async);
error:
close (fd);
return FALSE;
} }
/*********************************************************************** /***********************************************************************
...@@ -1710,6 +1732,8 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, ...@@ -1710,6 +1732,8 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
{ {
async_fileio *ovp; async_fileio *ovp;
int fd; int fd;
int flags;
enum fd_type type;
TRACE("file %d to buf %p num %ld %p func %p stub\n", TRACE("file %d to buf %p num %ld %p func %p stub\n",
hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine); hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
...@@ -1720,7 +1744,7 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, ...@@ -1720,7 +1744,7 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
return FALSE; return FALSE;
} }
fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE ); fd = FILE_GetUnixHandleType ( hFile, GENERIC_WRITE, &type, &flags );
if ( fd < 0 ) if ( fd < 0 )
{ {
TRACE( "Couldn't get FD\n" ); TRACE( "Couldn't get FD\n" );
...@@ -1732,8 +1756,7 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, ...@@ -1732,8 +1756,7 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
{ {
TRACE("HeapAlloc Failed\n"); TRACE("HeapAlloc Failed\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY); SetLastError(ERROR_NOT_ENOUGH_MEMORY);
close (fd); goto error;
return FALSE;
} }
ovp->async.ops = &fileio_async_ops; ovp->async.ops = &fileio_async_ops;
...@@ -1748,6 +1771,10 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, ...@@ -1748,6 +1771,10 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
ovp->completion_func = lpCompletionRoutine; ovp->completion_func = lpCompletionRoutine;
return !register_new_async (&ovp->async); return !register_new_async (&ovp->async);
error:
close (fd);
return FALSE;
} }
/*********************************************************************** /***********************************************************************
......
...@@ -35,6 +35,7 @@ typedef void CALLBACK (*async_call_completion_func)(ULONG_PTR data); ...@@ -35,6 +35,7 @@ typedef void CALLBACK (*async_call_completion_func)(ULONG_PTR data);
typedef DWORD (*async_get_status)(const struct async_private *ovp); typedef DWORD (*async_get_status)(const struct async_private *ovp);
typedef DWORD (*async_get_count)(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_set_status)(struct async_private *ovp, const DWORD status);
typedef void (*async_cleanup)(struct async_private *ovp);
typedef struct async_ops typedef struct async_ops
{ {
...@@ -42,6 +43,7 @@ typedef struct async_ops ...@@ -42,6 +43,7 @@ typedef struct async_ops
async_set_status set_status; async_set_status set_status;
async_get_count get_count; async_get_count get_count;
async_call_completion_func call_completion; async_call_completion_func call_completion;
async_cleanup cleanup;
} async_ops; } async_ops;
typedef struct async_private typedef struct async_private
...@@ -74,7 +76,10 @@ inline static void finish_async( async_private *ovp ) ...@@ -74,7 +76,10 @@ inline static void finish_async( async_private *ovp )
if( ovp->event != INVALID_HANDLE_VALUE ) if( ovp->event != INVALID_HANDLE_VALUE )
NtSetEvent( ovp->event, NULL ); NtSetEvent( ovp->event, NULL );
if ( ovp->ops->call_completion )
QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp ); 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 ) inline static BOOL __register_async( async_private *ovp, const DWORD status )
...@@ -92,7 +97,11 @@ inline static BOOL __register_async( async_private *ovp, const DWORD status ) ...@@ -92,7 +97,11 @@ inline static BOOL __register_async( async_private *ovp, const DWORD status )
} }
SERVER_END_REQ; SERVER_END_REQ;
if ( ret ) ovp->ops->set_status ( ovp, GetLastError() ); if ( ret ) {
SetLastError( RtlNtStatusToDosError(ret) );
ovp->ops->set_status ( ovp, ret );
}
if ( ovp->ops->get_status (ovp) != STATUS_PENDING ) if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
finish_async (ovp); finish_async (ovp);
......
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