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 @@ ...@@ -84,6 +84,8 @@
# include <sys/strtio.h> # include <sys/strtio.h>
#endif #endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "winbase.h" #include "winbase.h"
#include "winerror.h" #include "winerror.h"
...@@ -104,15 +106,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(comm); ...@@ -104,15 +106,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(comm);
* Asynchronous I/O for asynchronous wait requests * * 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 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 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_set_async_status, /* set_status */
commio_get_async_count, /* get_count */ commio_get_async_count, /* get_count */
NULL, /* call_completion */ NULL, /* call_completion */
commio_async_cleanup /* cleanup */ commio_async_cleanup /* cleanup */
...@@ -121,20 +119,9 @@ static async_ops commio_async_ops = ...@@ -121,20 +119,9 @@ static async_ops commio_async_ops =
typedef struct async_commio typedef struct async_commio
{ {
struct async_private async; struct async_private async;
LPOVERLAPPED lpOverlapped;
char *buffer; char *buffer;
} async_commio; } 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) static DWORD commio_get_async_count (const struct async_private *ovp)
{ {
return 0; return 0;
...@@ -1664,14 +1651,14 @@ BOOL WINAPI GetCommModemStatus( ...@@ -1664,14 +1651,14 @@ BOOL WINAPI GetCommModemStatus(
static void COMM_WaitCommEventService(async_private *ovp) static void COMM_WaitCommEventService(async_private *ovp)
{ {
async_commio *commio = (async_commio*) 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 */ /* FIXME: detect other events */
*commio->buffer = EV_RXCHAR; *commio->buffer = EV_RXCHAR;
lpOverlapped->Internal = STATUS_SUCCESS; iosb->u.Status = STATUS_SUCCESS;
} }
...@@ -1714,7 +1701,7 @@ static BOOL COMM_WaitCommEvent( ...@@ -1714,7 +1701,7 @@ static BOOL COMM_WaitCommEvent(
ovp->async.type = ASYNC_TYPE_WAIT; ovp->async.type = ASYNC_TYPE_WAIT;
ovp->async.func = COMM_WaitCommEventService; ovp->async.func = COMM_WaitCommEventService;
ovp->async.event = lpOverlapped->hEvent; ovp->async.event = lpOverlapped->hEvent;
ovp->lpOverlapped = lpOverlapped; ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
ovp->buffer = (char *)lpdwEvents; ovp->buffer = (char *)lpdwEvents;
lpOverlapped->InternalHigh = 0; lpOverlapped->InternalHigh = 0;
......
...@@ -32,11 +32,12 @@ ...@@ -32,11 +32,12 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winternl.h" #include "winternl.h"
#include "wincon.h"
#include "kernel_private.h" #include "kernel_private.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "async.h"
WINE_DEFAULT_DEBUG_CHANNEL(file); WINE_DEFAULT_DEBUG_CHANNEL(file);
...@@ -45,6 +46,106 @@ 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.@) * _hread (KERNEL32.@)
*/ */
LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count) LONG WINAPI _hread( HFILE hFile, LPVOID buffer, LONG count)
......
...@@ -446,9 +446,9 @@ static void WINAPI check_async_list(async_private *asp, DWORD status) ...@@ -446,9 +446,9 @@ static void WINAPI check_async_list(async_private *asp, DWORD status)
if( status != STATUS_ALERTED ) if( status != STATUS_ALERTED )
{ {
ovp_status = status; 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 ); if( ovp_status == STATUS_PENDING ) ovp->func( ovp );
......
...@@ -107,6 +107,8 @@ ...@@ -107,6 +107,8 @@
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wingdi.h" #include "wingdi.h"
#include "winuser.h" #include "winuser.h"
...@@ -147,16 +149,12 @@ extern CRITICAL_SECTION csWSgetXXXbyYYY; ...@@ -147,16 +149,12 @@ extern CRITICAL_SECTION csWSgetXXXbyYYY;
****************************************************************/ ****************************************************************/
#include "async.h" #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 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 CALLBACK ws2_async_call_completion (ULONG_PTR data);
static void ws2_async_cleanup ( struct async_private *ovp ); static void ws2_async_cleanup ( struct async_private *ovp );
static struct async_ops ws2_async_ops = static struct async_ops ws2_async_ops =
{ {
ws2_async_get_status,
ws2_async_set_status,
ws2_async_get_count, ws2_async_get_count,
ws2_async_call_completion, ws2_async_call_completion,
ws2_async_cleanup ws2_async_cleanup
...@@ -164,8 +162,6 @@ static struct async_ops ws2_async_ops = ...@@ -164,8 +162,6 @@ static struct async_ops ws2_async_ops =
static struct async_ops ws2_nocomp_async_ops = static struct async_ops ws2_nocomp_async_ops =
{ {
ws2_async_get_status,
ws2_async_set_status,
ws2_async_get_count, ws2_async_get_count,
NULL, /* call_completion */ NULL, /* call_completion */
ws2_async_cleanup ws2_async_cleanup
...@@ -174,7 +170,6 @@ static struct async_ops ws2_nocomp_async_ops = ...@@ -174,7 +170,6 @@ static struct async_ops ws2_nocomp_async_ops =
typedef struct ws2_async typedef struct ws2_async
{ {
async_private async; async_private async;
LPWSAOVERLAPPED overlapped;
LPWSAOVERLAPPED user_overlapped; LPWSAOVERLAPPED user_overlapped;
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func; LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
struct iovec *iovec; struct iovec *iovec;
...@@ -1021,31 +1016,24 @@ inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_socka ...@@ -1021,31 +1016,24 @@ inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_socka
* Functions for handling overlapped I/O * 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) 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 ) static void ws2_async_cleanup ( struct async_private *ap )
{ {
struct ws2_async *as = (struct ws2_async*) 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 ( !as->user_overlapped )
{ {
#if 0
/* FIXME: I don't think this is really used */
if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE ) if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
WSACloseEvent ( as->overlapped->hEvent ); WSACloseEvent ( as->overlapped->hEvent );
HeapFree ( GetProcessHeap(), 0, as->overlapped ); #endif
HeapFree ( GetProcessHeap(), 0, as->async.iosb );
} }
if ( as->iovec ) if ( as->iovec )
...@@ -1060,8 +1048,8 @@ static void CALLBACK ws2_async_call_completion (ULONG_PTR data) ...@@ -1060,8 +1048,8 @@ static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
TRACE ("data: %p\n", as); TRACE ("data: %p\n", as);
as->completion_func ( NtStatusToWSAError (as->overlapped->Internal), as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
as->overlapped->InternalHigh, as->async.iosb->Information,
as->user_overlapped, as->user_overlapped,
as->flags ); as->flags );
ws2_async_cleanup ( &as->async ); ws2_async_cleanup ( &as->async );
...@@ -1114,22 +1102,22 @@ WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferC ...@@ -1114,22 +1102,22 @@ WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferC
if ( lpOverlapped ) if ( lpOverlapped )
{ {
wsa->overlapped = lpOverlapped; wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent ); wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
} }
else else
{ {
wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0, wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
sizeof (WSAOVERLAPPED) ); sizeof (IO_STATUS_BLOCK) );
if ( !wsa->overlapped ) if ( !wsa->async.iosb )
goto error; goto error;
wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE; wsa->async.event = INVALID_HANDLE_VALUE;
} }
wsa->overlapped->InternalHigh = 0; wsa->async.iosb->Information = 0;
TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, ov %p, uov %p, cfunc %p\n", 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, 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; return wsa;
...@@ -1220,9 +1208,9 @@ static void WS2_async_recv ( async_private *as ) ...@@ -1220,9 +1208,9 @@ static void WS2_async_recv ( async_private *as )
TRACE ( "async %p\n", wsa ); 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; return;
} }
...@@ -1231,8 +1219,8 @@ static void WS2_async_recv ( async_private *as ) ...@@ -1231,8 +1219,8 @@ static void WS2_async_recv ( async_private *as )
if (result >= 0) if (result >= 0)
{ {
wsa->overlapped->Internal = STATUS_SUCCESS; wsa->async.iosb->u.Status = STATUS_SUCCESS;
wsa->overlapped->InternalHigh = result; wsa->async.iosb->Information = result;
TRACE ( "received %d bytes\n", result ); TRACE ( "received %d bytes\n", result );
_enable_event ( wsa->async.handle, FD_READ, 0, 0 ); _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
return; return;
...@@ -1241,13 +1229,13 @@ static void WS2_async_recv ( async_private *as ) ...@@ -1241,13 +1229,13 @@ static void WS2_async_recv ( async_private *as )
err = wsaErrno (); err = wsaErrno ();
if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */ 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 ); _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
TRACE ( "still pending\n" ); TRACE ( "still pending\n" );
} }
else else
{ {
wsa->overlapped->Internal = err; wsa->async.iosb->u.Status = err;
TRACE ( "Error: %x\n", err ); TRACE ( "Error: %x\n", err );
} }
} }
...@@ -1312,9 +1300,9 @@ static void WS2_async_send ( async_private *as ) ...@@ -1312,9 +1300,9 @@ static void WS2_async_send ( async_private *as )
TRACE ( "async %p\n", wsa ); 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; return;
} }
...@@ -1323,8 +1311,8 @@ static void WS2_async_send ( async_private *as ) ...@@ -1323,8 +1311,8 @@ static void WS2_async_send ( async_private *as )
if (result >= 0) if (result >= 0)
{ {
wsa->overlapped->Internal = STATUS_SUCCESS; wsa->async.iosb->u.Status = STATUS_SUCCESS;
wsa->overlapped->InternalHigh = result; wsa->async.iosb->Information = result;
TRACE ( "sent %d bytes\n", result ); TRACE ( "sent %d bytes\n", result );
_enable_event ( wsa->async.handle, FD_WRITE, 0, 0 ); _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
return; return;
...@@ -1333,7 +1321,7 @@ static void WS2_async_send ( async_private *as ) ...@@ -1333,7 +1321,7 @@ static void WS2_async_send ( async_private *as )
err = wsaErrno (); err = wsaErrno ();
if ( err == WSAEINTR ) if ( err == WSAEINTR )
{ {
wsa->overlapped->Internal = STATUS_PENDING; wsa->async.iosb->u.Status = STATUS_PENDING;
_enable_event ( wsa->async.handle, FD_WRITE, 0, 0 ); _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
TRACE ( "still pending\n" ); TRACE ( "still pending\n" );
} }
...@@ -1341,7 +1329,7 @@ static void WS2_async_send ( async_private *as ) ...@@ -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 /* We set the status to a winsock error code and check for that
later in NtStatusToWSAError () */ later in NtStatusToWSAError () */
wsa->overlapped->Internal = err; wsa->async.iosb->u.Status = err;
TRACE ( "Error: %x\n", err ); TRACE ( "Error: %x\n", err );
} }
} }
...@@ -1370,9 +1358,9 @@ static void WS2_async_shutdown ( async_private *as ) ...@@ -1370,9 +1358,9 @@ static void WS2_async_shutdown ( async_private *as )
} }
if ( err ) if ( err )
wsa->overlapped->Internal = wsaErrno (); wsa->async.iosb->u.Status = wsaErrno ();
else 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, ...@@ -2461,7 +2449,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
err = NtStatusToWSAError ( ret ); err = NtStatusToWSAError ( ret );
if ( !lpOverlapped ) if ( !lpOverlapped )
HeapFree ( GetProcessHeap(), 0, wsa->overlapped ); HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
HeapFree ( GetProcessHeap(), 0, wsa ); HeapFree ( GetProcessHeap(), 0, wsa );
goto err_free; goto err_free;
} }
...@@ -3918,7 +3906,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -3918,7 +3906,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
err = NtStatusToWSAError ( ret ); err = NtStatusToWSAError ( ret );
if ( !lpOverlapped ) if ( !lpOverlapped )
HeapFree ( GetProcessHeap(), 0, wsa->overlapped ); HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
HeapFree ( GetProcessHeap(), 0, wsa ); HeapFree ( GetProcessHeap(), 0, wsa );
goto err_free; goto err_free;
} }
......
...@@ -100,6 +100,8 @@ ...@@ -100,6 +100,8 @@
#include <netdb.h> #include <netdb.h>
#endif #endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "winerror.h" #include "winerror.h"
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
...@@ -202,7 +204,7 @@ static inline CHAR *SMB_nextSepA (CHAR *s) {while (*s && !SMB_isSepA (*s)) s++; ...@@ -202,7 +204,7 @@ static inline CHAR *SMB_nextSepA (CHAR *s) {while (*s && !SMB_isSepA (*s)) s++;
* replacing separators with null characters * replacing separators with null characters
*/ */
USHORT SMB_MultiplexId = 0; static USHORT SMB_MultiplexId = 0;
struct NB_Buffer struct NB_Buffer
{ {
...@@ -1532,16 +1534,15 @@ done: ...@@ -1532,16 +1534,15 @@ done:
return handle; 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 ) SERVER_START_REQ( get_smb_info )
{ {
req->handle = hFile; req->handle = hFile;
req->flags = 0; req->flags = 0;
SetLastError(0); status = wine_server_call( req );
r = wine_server_call_err( req );
if(tree_id) if(tree_id)
*tree_id = reply->tree_id; *tree_id = reply->tree_id;
if(user_id) if(user_id)
...@@ -1555,12 +1556,12 @@ static BOOL SMB_GetSmbInfo(HANDLE hFile, USHORT *tree_id, USHORT *user_id, USHOR ...@@ -1555,12 +1556,12 @@ static BOOL SMB_GetSmbInfo(HANDLE hFile, USHORT *tree_id, USHORT *user_id, USHOR
} }
SERVER_END_REQ; 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); TRACE("offset = %08lx\n",offset);
...@@ -1569,61 +1570,53 @@ static BOOL SMB_SetOffset(HANDLE hFile, DWORD offset) ...@@ -1569,61 +1570,53 @@ static BOOL SMB_SetOffset(HANDLE hFile, DWORD offset)
req->handle = hFile; req->handle = hFile;
req->flags = SMBINFO_SET_OFFSET; req->flags = SMBINFO_SET_OFFSET;
req->offset = offset; req->offset = offset;
SetLastError(0); status = wine_server_call( req );
r = wine_server_call_err( req );
/* if(offset) /* if(offset)
*offset = reply->offset; */ *offset = reply->offset; */
} }
SERVER_END_REQ; 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; int fd;
DWORD total, count, offset; DWORD count, offset;
USHORT user_id, tree_id, dialect, file_id, read; 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)) io_status->Information = 0;
return FALSE;
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); fd = FILE_GetUnixHandle(hFile, GENERIC_READ);
if(fd<0) if (fd<0) return io_status->u.Status = STATUS_INVALID_HANDLE;
return FALSE;
total = 0;
while(1) while(1)
{ {
count = bytesToRead - total; count = bytesToRead - io_status->Information;
if(count>0x400) if(count>0x400)
count = 0x400; count = 0x400;
if(count==0) if(count==0)
break; break;
read = 0; read = 0;
r = SMB_Read(fd, tree_id, user_id, dialect, file_id, offset, buffer, count, &read); if (!SMB_Read(fd, tree_id, user_id, dialect, file_id, offset, buffer, count, &read))
if(!r)
break; break;
if(!read) if(!read)
break; break;
total += read; io_status->Information += read;
buffer = (char*)buffer + read; buffer = (char*)buffer + read;
offset += read; offset += read;
if(total>=bytesToRead) if(io_status->Information >= bytesToRead)
break; break;
} }
close(fd); close(fd);
if(bytesRead) return io_status->u.Status = SMB_SetOffset(hFile, offset);
*bytesRead = total;
if(!SMB_SetOffset(hFile, offset))
return FALSE;
return r;
} }
SMB_DIR* WINAPI SMB_FindFirst(LPCWSTR name) SMB_DIR* WINAPI SMB_FindFirst(LPCWSTR name)
......
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
extern inline int SMB_isSepW (WCHAR c) {return (c == '\\' || c == '/');} 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 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, extern HANDLE WINAPI SMB_CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
LPSECURITY_ATTRIBUTES sa, DWORD creation, LPSECURITY_ATTRIBUTES sa, DWORD creation,
DWORD attributes, HANDLE template ); DWORD attributes, HANDLE template );
......
...@@ -27,20 +27,17 @@ ...@@ -27,20 +27,17 @@
#define __WINE_ASYNC_H #define __WINE_ASYNC_H
#include "wine/server.h" #include "wine/server.h"
#include "winternl.h"
struct async_private; struct async_private;
typedef void (*async_handler)(struct async_private *ovp); typedef void (*async_handler)(struct async_private *ovp);
typedef void (CALLBACK *async_call_completion_func)(ULONG_PTR data); 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 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 void (*async_cleanup)(struct async_private *ovp);
typedef struct async_ops typedef struct async_ops
{ {
async_get_status get_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_cleanup cleanup;
...@@ -48,43 +45,50 @@ typedef struct async_ops ...@@ -48,43 +45,50 @@ typedef struct async_ops
typedef struct async_private typedef struct async_private
{ {
struct async_ops *ops; struct async_ops* ops;
HANDLE handle; HANDLE handle;
HANDLE event; HANDLE event;
int fd; int fd;
async_handler func; async_handler func;
int type; int type;
struct async_private *next; IO_STATUS_BLOCK* iosb;
struct async_private *prev; struct async_private* next;
struct async_private* prev;
} async_private; } async_private;
/* All functions declared static for Dll separation purposes */ /* 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 ) inline static void finish_async( async_private *ovp )
{ {
if(ovp->prev) if (ovp->prev)
ovp->prev->next = ovp->next; ovp->prev->next = ovp->next;
else else
NtCurrentTeb()->pending_list = ovp->next; NtCurrentTeb()->pending_list = ovp->next;
if(ovp->next) if (ovp->next)
ovp->next->prev = ovp->prev; ovp->next->prev = ovp->prev;
ovp->next = ovp->prev = NULL; ovp->next = ovp->prev = NULL;
close( ovp->fd ); close(ovp->fd);
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 ) 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 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 ) SERVER_START_REQ( register_async )
{ {
...@@ -97,23 +101,20 @@ inline static BOOL __register_async( async_private *ovp, const DWORD status ) ...@@ -97,23 +101,20 @@ inline static BOOL __register_async( async_private *ovp, const DWORD status )
} }
SERVER_END_REQ; SERVER_END_REQ;
if ( ret ) { if (ret) ovp->iosb->u.Status = ret;
SetLastError( RtlNtStatusToDosError(ret) );
ovp->ops->set_status ( ovp, ret );
}
if ( ovp->ops->get_status (ovp) != STATUS_PENDING ) if ( ovp->iosb->u.Status != STATUS_PENDING )
finish_async (ovp); finish_async(ovp);
return ret; return ret;
} }
#define register_old_async(ovp) \ #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->next = NtCurrentTeb()->pending_list;
ovp->prev = NULL; ovp->prev = NULL;
...@@ -123,13 +124,13 @@ inline static BOOL register_new_async( async_private *ovp ) ...@@ -123,13 +124,13 @@ inline static BOOL register_new_async( async_private *ovp )
return __register_async( ovp, STATUS_PENDING ); 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 */ /* avoid multiple cancellations */
if ( ovp->ops->get_status( ovp ) != STATUS_PENDING ) if ( ovp->iosb->u.Status != STATUS_PENDING )
return 0; return STATUS_SUCCESS;
ovp->ops->set_status ( ovp, STATUS_CANCELLED ); ovp->iosb->u.Status = STATUS_CANCELLED;
return __register_async ( ovp, STATUS_CANCELLED ); return __register_async( ovp, STATUS_CANCELLED );
} }
#endif /* __WINE_ASYNC_H */ #endif /* __WINE_ASYNC_H */
...@@ -991,6 +991,7 @@ NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG); ...@@ -991,6 +991,7 @@ NTSTATUS WINAPI NtUnlockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID); NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,PLARGE_INTEGER); NTSTATUS WINAPI NtWaitForSingleObject(HANDLE,BOOLEAN,PLARGE_INTEGER);
NTSTATUS WINAPI NtWaitForMultipleObjects(ULONG,const HANDLE*,BOOLEAN,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); void WINAPI RtlAcquirePebLock(void);
BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK,BYTE); 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