forked from Mirrors/wine-wine
ntdll: Queue an intermediate user APC routine to free the async info.
parent
41f15a769f
commit
f6a3a4689f
|
@ -2168,8 +2168,18 @@ struct read_changes_info
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle;
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
ULONG BufferSize;
|
ULONG BufferSize;
|
||||||
|
PIO_APC_ROUTINE apc;
|
||||||
|
void *apc_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* callback for ioctl user APC */
|
||||||
|
static void WINAPI read_changes_user_apc( void *arg, IO_STATUS_BLOCK *io, ULONG reserved )
|
||||||
|
{
|
||||||
|
struct read_changes_info *info = arg;
|
||||||
|
if (info->apc) info->apc( info->apc_arg, io, reserved );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, info );
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status )
|
static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status )
|
||||||
{
|
{
|
||||||
struct read_changes_info *info = user;
|
struct read_changes_info *info = user;
|
||||||
|
@ -2221,8 +2231,6 @@ static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS st
|
||||||
|
|
||||||
iosb->u.Status = ret;
|
iosb->u.Status = ret;
|
||||||
iosb->Information = len;
|
iosb->Information = len;
|
||||||
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, info );
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2265,6 +2273,8 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
|
||||||
info->FileHandle = FileHandle;
|
info->FileHandle = FileHandle;
|
||||||
info->Buffer = Buffer;
|
info->Buffer = Buffer;
|
||||||
info->BufferSize = BufferSize;
|
info->BufferSize = BufferSize;
|
||||||
|
info->apc = ApcRoutine;
|
||||||
|
info->apc_arg = ApcContext;
|
||||||
|
|
||||||
SERVER_START_REQ( read_directory_changes )
|
SERVER_START_REQ( read_directory_changes )
|
||||||
{
|
{
|
||||||
|
@ -2275,8 +2285,8 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
|
||||||
req->async.callback = read_changes_apc;
|
req->async.callback = read_changes_apc;
|
||||||
req->async.iosb = IoStatusBlock;
|
req->async.iosb = IoStatusBlock;
|
||||||
req->async.arg = info;
|
req->async.arg = info;
|
||||||
req->async.apc = ApcRoutine;
|
req->async.apc = read_changes_user_apc;
|
||||||
req->async.apc_arg = ApcContext;
|
req->async.apc_arg = info;
|
||||||
req->async.event = Event;
|
req->async.event = Event;
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,9 +237,16 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
|
||||||
* Asynchronous file I/O *
|
* Asynchronous file I/O *
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct
|
struct async_fileio
|
||||||
{
|
{
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
PIO_APC_ROUTINE apc;
|
||||||
|
void *apc_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct async_fileio io;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
unsigned int already;
|
unsigned int already;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
@ -248,13 +255,21 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE handle;
|
struct async_fileio io;
|
||||||
const char *buffer;
|
const char *buffer;
|
||||||
unsigned int already;
|
unsigned int already;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
} async_fileio_write;
|
} async_fileio_write;
|
||||||
|
|
||||||
|
|
||||||
|
/* callback for file I/O user APC */
|
||||||
|
static void WINAPI fileio_apc( void *arg, IO_STATUS_BLOCK *io, ULONG reserved )
|
||||||
|
{
|
||||||
|
struct async_fileio *async = arg;
|
||||||
|
if (async->apc) async->apc( async->apc_arg, io, reserved );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, async );
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_GetNtStatus(void)
|
* FILE_GetNtStatus(void)
|
||||||
*
|
*
|
||||||
|
@ -315,7 +330,7 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU
|
||||||
{
|
{
|
||||||
case STATUS_ALERTED: /* got some new data */
|
case STATUS_ALERTED: /* got some new data */
|
||||||
/* check to see if the data is ready (non-blocking) */
|
/* check to see if the data is ready (non-blocking) */
|
||||||
if ((status = server_get_unix_fd( fileio->handle, FILE_READ_DATA, &fd,
|
if ((status = server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
|
||||||
&needs_close, NULL, NULL )))
|
&needs_close, NULL, NULL )))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -365,7 +380,6 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU
|
||||||
{
|
{
|
||||||
iosb->u.Status = status;
|
iosb->u.Status = status;
|
||||||
iosb->Information = fileio->already;
|
iosb->Information = fileio->already;
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, fileio );
|
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +622,9 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
||||||
status = STATUS_NO_MEMORY;
|
status = STATUS_NO_MEMORY;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
fileio->handle = hFile;
|
fileio->io.handle = hFile;
|
||||||
|
fileio->io.apc = apc;
|
||||||
|
fileio->io.apc_arg = apc_user;
|
||||||
fileio->already = total;
|
fileio->already = total;
|
||||||
fileio->count = length;
|
fileio->count = length;
|
||||||
fileio->buffer = buffer;
|
fileio->buffer = buffer;
|
||||||
|
@ -622,8 +638,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
||||||
req->async.callback = FILE_AsyncReadService;
|
req->async.callback = FILE_AsyncReadService;
|
||||||
req->async.iosb = io_status;
|
req->async.iosb = io_status;
|
||||||
req->async.arg = fileio;
|
req->async.arg = fileio;
|
||||||
req->async.apc = apc;
|
req->async.apc = fileio_apc;
|
||||||
req->async.apc_arg = apc_user;
|
req->async.apc_arg = fileio;
|
||||||
req->async.event = hEvent;
|
req->async.event = hEvent;
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
}
|
}
|
||||||
|
@ -701,7 +717,7 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
|
||||||
{
|
{
|
||||||
case STATUS_ALERTED:
|
case STATUS_ALERTED:
|
||||||
/* write some data (non-blocking) */
|
/* write some data (non-blocking) */
|
||||||
if ((status = server_get_unix_fd( fileio->handle, FILE_WRITE_DATA, &fd,
|
if ((status = server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd,
|
||||||
&needs_close, &type, NULL )))
|
&needs_close, &type, NULL )))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -734,7 +750,6 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
|
||||||
{
|
{
|
||||||
iosb->u.Status = status;
|
iosb->u.Status = status;
|
||||||
iosb->Information = fileio->already;
|
iosb->Information = fileio->already;
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, fileio );
|
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -842,7 +857,9 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
|
||||||
status = STATUS_NO_MEMORY;
|
status = STATUS_NO_MEMORY;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
fileio->handle = hFile;
|
fileio->io.handle = hFile;
|
||||||
|
fileio->io.apc = apc;
|
||||||
|
fileio->io.apc_arg = apc_user;
|
||||||
fileio->already = total;
|
fileio->already = total;
|
||||||
fileio->count = length;
|
fileio->count = length;
|
||||||
fileio->buffer = buffer;
|
fileio->buffer = buffer;
|
||||||
|
@ -855,8 +872,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
|
||||||
req->async.callback = FILE_AsyncWriteService;
|
req->async.callback = FILE_AsyncWriteService;
|
||||||
req->async.iosb = io_status;
|
req->async.iosb = io_status;
|
||||||
req->async.arg = fileio;
|
req->async.arg = fileio;
|
||||||
req->async.apc = apc;
|
req->async.apc = fileio_apc;
|
||||||
req->async.apc_arg = apc_user;
|
req->async.apc_arg = fileio;
|
||||||
req->async.event = hEvent;
|
req->async.event = hEvent;
|
||||||
status = wine_server_call( req );
|
status = wine_server_call( req );
|
||||||
}
|
}
|
||||||
|
@ -920,9 +937,11 @@ done:
|
||||||
|
|
||||||
struct async_ioctl
|
struct async_ioctl
|
||||||
{
|
{
|
||||||
HANDLE handle; /* handle to the device */
|
HANDLE handle; /* handle to the device */
|
||||||
void *buffer; /* buffer for output */
|
void *buffer; /* buffer for output */
|
||||||
ULONG size; /* size of buffer */
|
ULONG size; /* size of buffer */
|
||||||
|
PIO_APC_ROUTINE apc; /* user apc params */
|
||||||
|
void *apc_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* callback for ioctl async I/O completion */
|
/* callback for ioctl async I/O completion */
|
||||||
|
@ -942,14 +961,18 @@ static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS statu
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
}
|
}
|
||||||
if (status != STATUS_PENDING)
|
if (status != STATUS_PENDING) io->u.Status = status;
|
||||||
{
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, async );
|
|
||||||
io->u.Status = status;
|
|
||||||
}
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* callback for ioctl user APC */
|
||||||
|
static void WINAPI ioctl_apc( void *arg, IO_STATUS_BLOCK *io, ULONG reserved )
|
||||||
|
{
|
||||||
|
struct async_ioctl *async = arg;
|
||||||
|
if (async->apc) async->apc( async->apc_arg, io, reserved );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, async );
|
||||||
|
}
|
||||||
|
|
||||||
/* do a ioctl call through the server */
|
/* do a ioctl call through the server */
|
||||||
static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
|
static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
|
||||||
PIO_APC_ROUTINE apc, PVOID apc_context,
|
PIO_APC_ROUTINE apc, PVOID apc_context,
|
||||||
|
@ -964,9 +987,11 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
|
||||||
|
|
||||||
if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
|
if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
async->handle = handle;
|
async->handle = handle;
|
||||||
async->buffer = out_buffer;
|
async->buffer = out_buffer;
|
||||||
async->size = out_size;
|
async->size = out_size;
|
||||||
|
async->apc = apc;
|
||||||
|
async->apc_arg = apc_context;
|
||||||
|
|
||||||
SERVER_START_REQ( ioctl )
|
SERVER_START_REQ( ioctl )
|
||||||
{
|
{
|
||||||
|
@ -975,8 +1000,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
|
||||||
req->async.callback = ioctl_completion;
|
req->async.callback = ioctl_completion;
|
||||||
req->async.iosb = io;
|
req->async.iosb = io;
|
||||||
req->async.arg = async;
|
req->async.arg = async;
|
||||||
req->async.apc = apc;
|
req->async.apc = (apc || event) ? ioctl_apc : NULL;
|
||||||
req->async.apc_arg = apc_context;
|
req->async.apc_arg = async;
|
||||||
req->async.event = event;
|
req->async.event = event;
|
||||||
wine_server_add_data( req, in_buffer, in_size );
|
wine_server_add_data( req, in_buffer, in_size );
|
||||||
wine_server_set_reply( req, out_buffer, out_size );
|
wine_server_set_reply( req, out_buffer, out_size );
|
||||||
|
@ -998,6 +1023,7 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
|
||||||
NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL );
|
NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL );
|
||||||
status = io->u.Status;
|
status = io->u.Status;
|
||||||
NtClose( wait_handle );
|
NtClose( wait_handle );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, async );
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
Loading…
Reference in New Issue