server: Add ioctl to the fd_ops. ntdll: Call server with unknown ioctls.

Vitaliy Margolen wine-patch at kievinfo.com
Sun Jul 9 12:30:25 CDT 2006


ChangeLog:
server: Add ioctl to the fd_ops. ntdll: Call server with unknown ioctls.

This patch sets the required infrastructure to pass ioctls to the wineserver.
In turn wineserver will be able to pass these iocts to other places, such as
ntoskrnl.

 dlls/ntdll/file.c   |   41 ++++++++++++++++++++++++++++++++++++++---
 server/change.c     |    4 +++-
 server/fd.c         |   25 +++++++++++++++++++++++++
 server/file.c       |    3 ++-
 server/file.h       |    4 ++++
 server/mailslot.c   |    9 ++++++---
 server/named_pipe.c |    7 +++++--
 server/process.c    |    3 ++-
 server/protocol.def |   11 +++++++++++
 server/request.c    |    3 ++-
 server/serial.c     |    3 ++-
 server/signal.c     |    3 ++-
 server/sock.c       |    3 ++-
 server/thread.c     |    3 ++-
 14 files changed, 106 insertions(+), 16 deletions(-)
-------------- next part --------------
e5df22eb5e4fbbca51a50bf95c601fbaea9e214d
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index e6257f9..6423516 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -838,6 +838,42 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile
     return io_status->u.Status;
 }
 
+NTSTATUS WINAPI DEVICE_DeviceIoControl(HANDLE handle, HANDLE event,
+                                       PIO_APC_ROUTINE apc, PVOID apc_context,
+                                       PIO_STATUS_BLOCK iosb, ULONG code,
+                                       PVOID in_buffer, ULONG in_size,
+                                       PVOID out_buffer, ULONG out_size)
+{
+    HANDLE irp_handle;
+
+    /* Parameter checking */
+    if (!iosb) return STATUS_ACCESS_VIOLATION;
+
+    if (event)
+    {
+        FIXME("Asynch not implemented yet\n");
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    SERVER_START_REQ(device_io_control)
+    {
+        req->handle   = handle;
+        req->code     = code;
+        wine_server_add_data( req, in_buffer, in_size );
+        if (out_buffer)
+            wine_server_set_reply( req, out_buffer, out_size );
+        iosb->u.Status = wine_server_call( req );
+        irp_handle    = reply->wait_handle;
+    }
+    SERVER_END_REQ;
+
+    if (iosb->u.Status == STATUS_NOT_SUPPORTED)
+        FIXME("Unsupported ioctl %lx (device=%lx access=%lx func=%lx method=%lx)\n",
+              code, (code >> 16), (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
+
+    return iosb->u.Status;
+}
+
 /**************************************************************************
  *		NtDeviceIoControlFile			[NTDLL.@]
  *		ZwDeviceIoControlFile			[NTDLL.@]
@@ -891,9 +927,8 @@ NTSTATUS WINAPI NtDeviceIoControlFile(HA
                                             in_buffer, in_size, out_buffer, out_size);
         break;
     default:
-        FIXME("Unsupported ioctl %lx (device=%lx access=%lx func=%lx method=%lx)\n",
-              code, device, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
-        io->u.Status = STATUS_NOT_SUPPORTED;
+        io->u.Status = DEVICE_DeviceIoControl(handle, event, apc, apc_context, io, code,
+                                              in_buffer, in_size, out_buffer, out_size);
         break;
     }
     return io->u.Status;
diff --git a/server/change.c b/server/change.c
index 01833dd..a0b83be 100644
--- a/server/change.c
+++ b/server/change.c
@@ -192,7 +192,8 @@ static const struct fd_ops dir_fd_ops =
     no_flush,                 /* flush */
     dir_get_info,             /* get_file_info */
     default_fd_queue_async,   /* queue_async */
-    dir_cancel_async          /* cancel_async */
+    dir_cancel_async,         /* cancel_async */
+    no_ioctl                  /* ioctl */
 };
 
 static struct list change_list = LIST_INIT(change_list);
@@ -561,6 +562,7 @@ static const struct fd_ops inotify_fd_op
     inotify_get_info,         /* get_file_info */
     default_fd_queue_async,   /* queue_async */
     default_fd_cancel_async,  /* cancel_async */
+    no_ioctl                  /* ioctl */
 };
 
 static int inotify_get_poll_events( struct fd *fd )
diff --git a/server/fd.c b/server/fd.c
index 7806bae..0d88919 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1655,6 +1655,14 @@ void no_cancel_async( struct fd *fd )
     set_error( STATUS_OBJECT_TYPE_MISMATCH );
 }
 
+/* default no_ioctl() routine */
+void no_ioctl( struct fd *fd, unsigned long code, const void* in_buff, size_t in_size,
+               struct object **obj )
+{
+    set_error( STATUS_NOT_SUPPORTED );
+    *obj = NULL;
+}
+
 /* close all Unix file descriptors on a device to allow unmounting it */
 static void unmount_device( struct fd *device_fd )
 {
@@ -1846,3 +1854,20 @@ DECL_HANDLER(cancel_async)
         release_object( fd );
     }        
 }
+
+/* User call to DeviceIoControl */
+DECL_HANDLER(device_io_control)
+{
+    struct object *obj;
+    struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
+
+    if (!fd) return;
+
+    fd->fd_ops->ioctl( fd, req->code, get_req_data(), get_req_data_size(), &obj );
+    if (obj)
+    {
+        reply->wait_handle = alloc_handle( current->process, obj, SYNCHRONIZE, 0 );
+        release_object( obj );
+    }
+    release_object( fd );
+}
diff --git a/server/file.c b/server/file.c
index 7ddcd35..7f3df3f 100644
--- a/server/file.c
+++ b/server/file.c
@@ -95,7 +95,8 @@ static const struct fd_ops file_fd_ops =
     file_flush,                   /* flush */
     file_get_info,                /* get_file_info */
     default_fd_queue_async,       /* queue_async */
-    default_fd_cancel_async       /* cancel_async */
+    default_fd_cancel_async,      /* cancel_async */
+    no_ioctl                      /* ioctl */
 };
 
 static inline int is_overlapped( const struct file *file )
diff --git a/server/file.h b/server/file.h
index 6bbf9b0..8925798 100644
--- a/server/file.h
+++ b/server/file.h
@@ -42,6 +42,9 @@ struct fd_ops
     void (*queue_async)(struct fd *, void* apc, void* user, void* io_sb, int type, int count);
     /* cancel an async operation */
     void (*cancel_async)(struct fd *);
+    /* perform ioctl */
+    void (*ioctl)(struct fd *, unsigned long code, const void* in_buff, size_t in_size,
+                  struct object **);
 };
 
 /* file descriptor functions */
@@ -73,6 +76,7 @@ extern int no_flush( struct fd *fd, stru
 extern int no_get_file_info( struct fd *fd );
 extern void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb, int type, int count);
 extern void no_cancel_async( struct fd *fd );
+extern void no_ioctl( struct fd *fd, unsigned long code, const void* in_buff, size_t in_size, struct object **obj );
 extern void main_loop(void);
 extern void remove_process_locks( struct process *process );
 
diff --git a/server/mailslot.c b/server/mailslot.c
index 3ff6b5c..012b0c3 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -94,7 +94,8 @@ static const struct fd_ops mailslot_fd_o
     no_flush,                   /* flush */
     mailslot_get_info,          /* get_file_info */
     mailslot_queue_async,       /* queue_async */
-    default_fd_cancel_async     /* cancel_async */
+    default_fd_cancel_async,    /* cancel_async */
+    no_ioctl                    /* ioctl */
 };
 
 
@@ -137,7 +138,8 @@ static const struct fd_ops mail_writer_f
     no_flush,                    /* flush */
     mail_writer_get_info,        /* get_file_info */
     no_queue_async,              /* queue_async */
-    NULL                         /* cancel_async */
+    NULL,                        /* cancel_async */
+    no_ioctl                     /* ioctl */
 };
 
 
@@ -178,7 +180,8 @@ static const struct fd_ops mailslot_devi
     no_flush,                       /* flush */
     mailslot_device_get_file_info,  /* get_file_info */
     default_fd_queue_async,         /* queue_async */
-    default_fd_cancel_async         /* cancel_async */
+    default_fd_cancel_async,        /* cancel_async */
+    no_ioctl                        /* ioctl */
 };
 
 static void mailslot_destroy( struct object *obj)
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 5c4da77..93a6aad 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -160,6 +160,7 @@ static const struct fd_ops pipe_server_f
     pipe_server_get_info,         /* get_file_info */
     default_fd_queue_async,       /* queue_async */
     default_fd_cancel_async,      /* cancel_async */
+    no_ioctl                      /* ioctl */
 };
 
 /* client end functions */
@@ -192,7 +193,8 @@ static const struct fd_ops pipe_client_f
     pipe_client_flush,            /* flush */
     pipe_client_get_info,         /* get_file_info */
     default_fd_queue_async,       /* queue_async */
-    default_fd_cancel_async       /* cancel_async */
+    default_fd_cancel_async,      /* cancel_async */
+    no_ioctl                      /* ioctl */
 };
 
 static void named_pipe_device_dump( struct object *obj, int verbose );
@@ -225,7 +227,8 @@ static const struct fd_ops named_pipe_de
     no_flush,                         /* flush */
     named_pipe_device_get_file_info,  /* get_file_info */
     default_fd_queue_async,           /* queue_async */
-    default_fd_cancel_async           /* cancel_async */
+    default_fd_cancel_async,          /* cancel_async */
+    no_ioctl                          /* ioctl */
 };
 
 static void named_pipe_dump( struct object *obj, int verbose )
diff --git a/server/process.c b/server/process.c
index 0c71540..71a24ff 100644
--- a/server/process.c
+++ b/server/process.c
@@ -86,7 +86,8 @@ static const struct fd_ops process_fd_op
     no_flush,                    /* flush */
     no_get_file_info,            /* get_file_info */
     no_queue_async,              /* queue_async */
-    no_cancel_async              /* cancel async */
+    no_cancel_async,             /* cancel async */
+    no_ioctl                     /* ioctl */
 };
 
 /* process startup info */
diff --git a/server/protocol.def b/server/protocol.def
index 502762d..a161707 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2615,3 +2615,14 @@ #define MAILSLOT_SET_READ_TIMEOUT  1
 @REPLY
     VARARG(target_name,unicode_str); /* target name */
 @END
+
+
+/* User call to DeviceIoControl */
+ at REQ(device_io_control)
+    obj_handle_t   handle;        /* handle to the device */
+    unsigned int   code;          /* ioctl code */
+    VARARG(in_buffer,bytes);      /* input buffer */
+ at REPLY
+    obj_handle_t   wait_handle;   /* handle to the irp */
+    VARARG(out_buffer,bytes);     /* output buffer */
+ at END
diff --git a/server/request.c b/server/request.c
index a78916e..510f34f 100644
--- a/server/request.c
+++ b/server/request.c
@@ -108,7 +108,8 @@ static const struct fd_ops master_socket
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
     no_queue_async,                /* queue_async */
-    no_cancel_async                /* cancel_async */
+    no_cancel_async,               /* cancel_async */
+    no_ioctl                       /* ioctl */
 };
 
 
diff --git a/server/serial.c b/server/serial.c
index 859202c..ba18006 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -115,7 +115,8 @@ static const struct fd_ops serial_fd_ops
     serial_flush,                 /* flush */
     serial_get_info,              /* get_file_info */
     serial_queue_async,           /* queue_async */
-    serial_cancel_async           /* cancel_async */
+    serial_cancel_async,          /* cancel_async */
+    no_ioctl                      /* ioctl */
 };
 
 /* check if the given fd is a serial port */
diff --git a/server/signal.c b/server/signal.c
index 8f638d8..1ba5080 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -83,7 +83,8 @@ static const struct fd_ops handler_fd_op
     no_flush,                 /* flush */
     no_get_file_info,         /* get_file_info */
     no_queue_async,           /* queue_async */
-    no_cancel_async           /* cancel_async */
+    no_cancel_async,          /* cancel_async */
+    no_ioctl                  /* ioctl */
 };
 
 static struct handler *handler_sighup;
diff --git a/server/sock.c b/server/sock.c
index ce63932..b8d0eef 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -125,7 +125,8 @@ static const struct fd_ops sock_fd_ops =
     no_flush,                     /* flush */
     sock_get_info,                /* get_file_info */
     sock_queue_async,             /* queue_async */
-    sock_cancel_async             /* cancel_async */
+    sock_cancel_async,            /* cancel_async */
+    no_ioctl                      /* ioctl */
 };
 
 
diff --git a/server/thread.c b/server/thread.c
index 36b7309..658b875 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -111,7 +111,8 @@ static const struct fd_ops thread_fd_ops
     no_flush,                   /* flush */
     no_get_file_info,           /* get_file_info */
     no_queue_async,             /* queue_async */
-    no_cancel_async             /* cancel_async */
+    no_cancel_async,            /* cancel_async */
+    no_ioctl                    /* ioctl */
 };
 
 static struct list thread_list = LIST_INIT(thread_list);


More information about the wine-patches mailing list