Alexandre Julliard : ntdll:
Queue an intermediate user APC routine to free the async info.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Jun 5 05:48:11 CDT 2007
Module: wine
Branch: master
Commit: f6a3a4689f2483bc383b881eab11a0a9e551adb0
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f6a3a4689f2483bc383b881eab11a0a9e551adb0
Author: Alexandre Julliard <julliard at winehq.org>
Date: Sun Jun 3 12:05:02 2007 +0200
ntdll: Queue an intermediate user APC routine to free the async info.
---
dlls/ntdll/directory.c | 18 +++++++++--
dlls/ntdll/file.c | 76 ++++++++++++++++++++++++++++++++----------------
2 files changed, 65 insertions(+), 29 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 64d5ba9..3256c59 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -2168,8 +2168,18 @@ struct read_changes_info
HANDLE FileHandle;
PVOID Buffer;
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 )
{
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->Information = len;
-
- RtlFreeHeap( GetProcessHeap(), 0, info );
return ret;
}
@@ -2265,6 +2273,8 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
info->FileHandle = FileHandle;
info->Buffer = Buffer;
info->BufferSize = BufferSize;
+ info->apc = ApcRoutine;
+ info->apc_arg = ApcContext;
SERVER_START_REQ( read_directory_changes )
{
@@ -2275,8 +2285,8 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event,
req->async.callback = read_changes_apc;
req->async.iosb = IoStatusBlock;
req->async.arg = info;
- req->async.apc = ApcRoutine;
- req->async.apc_arg = ApcContext;
+ req->async.apc = read_changes_user_apc;
+ req->async.apc_arg = info;
req->async.event = Event;
status = wine_server_call( req );
}
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index dc39735..7c166a9 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -237,9 +237,16 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
* Asynchronous file I/O *
*/
-typedef struct
+struct async_fileio
{
HANDLE handle;
+ PIO_APC_ROUTINE apc;
+ void *apc_arg;
+};
+
+typedef struct
+{
+ struct async_fileio io;
char* buffer;
unsigned int already;
unsigned int count;
@@ -248,13 +255,21 @@ typedef struct
typedef struct
{
- HANDLE handle;
+ struct async_fileio io;
const char *buffer;
unsigned int already;
unsigned int count;
} 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)
*
@@ -315,7 +330,7 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU
{
case STATUS_ALERTED: /* got some new data */
/* 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 )))
break;
@@ -365,7 +380,6 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU
{
iosb->u.Status = status;
iosb->Information = fileio->already;
- RtlFreeHeap( GetProcessHeap(), 0, fileio );
}
return status;
}
@@ -608,7 +622,9 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
status = STATUS_NO_MEMORY;
goto done;
}
- fileio->handle = hFile;
+ fileio->io.handle = hFile;
+ fileio->io.apc = apc;
+ fileio->io.apc_arg = apc_user;
fileio->already = total;
fileio->count = length;
fileio->buffer = buffer;
@@ -622,8 +638,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
req->async.callback = FILE_AsyncReadService;
req->async.iosb = io_status;
req->async.arg = fileio;
- req->async.apc = apc;
- req->async.apc_arg = apc_user;
+ req->async.apc = fileio_apc;
+ req->async.apc_arg = fileio;
req->async.event = hEvent;
status = wine_server_call( req );
}
@@ -701,7 +717,7 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
{
case STATUS_ALERTED:
/* 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 )))
break;
@@ -734,7 +750,6 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
{
iosb->u.Status = status;
iosb->Information = fileio->already;
- RtlFreeHeap( GetProcessHeap(), 0, fileio );
}
return status;
}
@@ -842,7 +857,9 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
status = STATUS_NO_MEMORY;
goto done;
}
- fileio->handle = hFile;
+ fileio->io.handle = hFile;
+ fileio->io.apc = apc;
+ fileio->io.apc_arg = apc_user;
fileio->already = total;
fileio->count = length;
fileio->buffer = buffer;
@@ -855,8 +872,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
req->async.callback = FILE_AsyncWriteService;
req->async.iosb = io_status;
req->async.arg = fileio;
- req->async.apc = apc;
- req->async.apc_arg = apc_user;
+ req->async.apc = fileio_apc;
+ req->async.apc_arg = fileio;
req->async.event = hEvent;
status = wine_server_call( req );
}
@@ -920,9 +937,11 @@ done:
struct async_ioctl
{
- HANDLE handle; /* handle to the device */
- void *buffer; /* buffer for output */
- ULONG size; /* size of buffer */
+ HANDLE handle; /* handle to the device */
+ void *buffer; /* buffer for output */
+ ULONG size; /* size of buffer */
+ PIO_APC_ROUTINE apc; /* user apc params */
+ void *apc_arg;
};
/* 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;
}
- if (status != STATUS_PENDING)
- {
- RtlFreeHeap( GetProcessHeap(), 0, async );
- io->u.Status = status;
- }
+ if (status != STATUS_PENDING) io->u.Status = 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 */
static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
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) )))
return STATUS_NO_MEMORY;
- async->handle = handle;
- async->buffer = out_buffer;
- async->size = out_size;
+ async->handle = handle;
+ async->buffer = out_buffer;
+ async->size = out_size;
+ async->apc = apc;
+ async->apc_arg = apc_context;
SERVER_START_REQ( ioctl )
{
@@ -975,8 +1000,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
req->async.callback = ioctl_completion;
req->async.iosb = io;
req->async.arg = async;
- req->async.apc = apc;
- req->async.apc_arg = apc_context;
+ req->async.apc = (apc || event) ? ioctl_apc : NULL;
+ req->async.apc_arg = async;
req->async.event = event;
wine_server_add_data( req, in_buffer, in_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 );
status = io->u.Status;
NtClose( wait_handle );
+ RtlFreeHeap( GetProcessHeap(), 0, async );
}
return status;
More information about the wine-cvs
mailing list