diff --git a/files/dos_fs.c b/files/dos_fs.c
index d0d9e8f0d40bfe0e4a92f45f78b70128362fdf7e..5b83fb0cfc3fd0171b1ffa52d22b9eb046307e50 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -747,18 +747,8 @@ static HANDLE DOSFS_CreateCommPort(LPCWSTR name, DWORD access, DWORD attributes,
 
     TRACE("opening %s as %s\n", devname, debugstr_w(name));
 
-    SERVER_START_REQ( create_serial )
-    {
-        req->access  = access;
-        req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        req->attributes = attributes;
-        req->sharing = FILE_SHARE_READ|FILE_SHARE_WRITE;
-        wine_server_add_data( req, devname, strlen(devname) );
-        SetLastError(0);
-        wine_server_call_err( req );
-        ret = reply->handle;
-    }
-    SERVER_END_REQ;
+    ret = FILE_CreateFile( devname, access, FILE_SHARE_READ|FILE_SHARE_WRITE,
+                           sa, OPEN_EXISTING, attributes, NULL, FALSE, DRIVE_FIXED );
 
     if(!ret)
         ERR("Couldn't open device '%s' ! (check permissions)\n",devname);
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 9ee99545f5541dbe3255f288ae84e69b789608e9..a4ace65e34e957475334d38b4dfb33363470ebc6 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2299,23 +2299,6 @@ struct kill_win_timer_reply
 
 
 
-struct create_serial_request
-{
-    struct request_header __header;
-    unsigned int access;
-    int          inherit;
-    unsigned int attributes;
-    unsigned int sharing;
-    /* VARARG(name,string); */
-};
-struct create_serial_reply
-{
-    struct reply_header __header;
-    obj_handle_t handle;
-};
-
-
-
 struct get_serial_info_request
 {
     struct request_header __header;
@@ -3302,7 +3285,6 @@ enum request
     REQ_get_message_reply,
     REQ_set_win_timer,
     REQ_kill_win_timer,
-    REQ_create_serial,
     REQ_get_serial_info,
     REQ_set_serial_info,
     REQ_register_async,
@@ -3490,7 +3472,6 @@ union generic_request
     struct get_message_reply_request get_message_reply_request;
     struct set_win_timer_request set_win_timer_request;
     struct kill_win_timer_request kill_win_timer_request;
-    struct create_serial_request create_serial_request;
     struct get_serial_info_request get_serial_info_request;
     struct set_serial_info_request set_serial_info_request;
     struct register_async_request register_async_request;
@@ -3676,7 +3657,6 @@ union generic_reply
     struct get_message_reply_reply get_message_reply_reply;
     struct set_win_timer_reply set_win_timer_reply;
     struct kill_win_timer_reply kill_win_timer_reply;
-    struct create_serial_reply create_serial_reply;
     struct get_serial_info_reply get_serial_info_reply;
     struct set_serial_info_reply set_serial_info_reply;
     struct register_async_reply register_async_reply;
@@ -3730,6 +3710,6 @@ union generic_reply
     struct set_global_windows_reply set_global_windows_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 134
+#define SERVER_PROTOCOL_VERSION 135
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/file.c b/server/file.c
index a22d269f21729da4bb35787540003f2a5883607a..62bda2404fbab3c1d43af65996adbbd9a7f075ca 100644
--- a/server/file.c
+++ b/server/file.c
@@ -162,9 +162,9 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in
 }
 
 
-static struct file *create_file( const char *nameptr, size_t len, unsigned int access,
-                                 unsigned int sharing, int create, unsigned int options,
-                                 unsigned int attrs, int removable )
+static struct object *create_file( const char *nameptr, size_t len, unsigned int access,
+                                   unsigned int sharing, int create, unsigned int options,
+                                   unsigned int attrs, int removable )
 {
     struct file *file;
     int hash, flags;
@@ -231,7 +231,15 @@ static struct file *create_file( const char *nameptr, size_t len, unsigned int a
         release_object( file );
         return NULL;
     }
-    return file;
+    /* check for serial port */
+    if (S_ISCHR(mode) && is_serial_fd( file->fd ))
+    {
+        struct object *obj = create_serial( file->fd, file->options );
+        release_object( file );
+        return obj;
+    }
+
+    return &file->obj;
 
  error:
     free( name );
@@ -599,7 +607,7 @@ static int set_file_time( obj_handle_t handle, time_t access_time, time_t write_
 /* create a file */
 DECL_HANDLER(create_file)
 {
-    struct file *file;
+    struct object *file;
 
     reply->handle = 0;
     if ((file = create_file( get_req_data(), get_req_data_size(), req->access,
diff --git a/server/file.h b/server/file.h
index 890cdb3d511d9e8d4cbe8f35ab20d9987417fbbe..85b47ae9177d633bee8908acfb2841e3f8f86df6 100644
--- a/server/file.h
+++ b/server/file.h
@@ -101,4 +101,9 @@ extern void file_set_error(void);
 extern void do_change_notify( int unix_fd );
 extern void sigio_callback(void);
 
+/* serial port functions */
+
+extern int is_serial_fd( struct fd *fd );
+extern struct object *create_serial( struct fd *fd, unsigned int options );
+
 #endif  /* __WINE_SERVER_FILE_H */
diff --git a/server/protocol.def b/server/protocol.def
index 2253554872517c998e01248edc81c6e8ff6ba3e9..0ee3fdfc981245a1c5ccc33b61fa631aea9e6828 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1623,18 +1623,6 @@ enum message_type
 @END
 
 
-/* Open a serial port */
-@REQ(create_serial)
-    unsigned int access;       /* wanted access rights */
-    int          inherit;      /* inherit flag */
-    unsigned int attributes;   /* eg. FILE_FLAG_OVERLAPPED */
-    unsigned int sharing;      /* sharing flags */
-    VARARG(name,string);       /* file name */
-@REPLY
-    obj_handle_t handle;       /* handle to the port */
-@END
-
-
 /* Retrieve info about a serial port */
 @REQ(get_serial_info)
     obj_handle_t handle;       /* handle to comm port */
diff --git a/server/request.h b/server/request.h
index 624ac519605ac84e99a543b5ffb56902d6879dd7..46a3cee93d8c7e410f140613313fc118c4637364 100644
--- a/server/request.h
+++ b/server/request.h
@@ -232,7 +232,6 @@ DECL_HANDLER(reply_message);
 DECL_HANDLER(get_message_reply);
 DECL_HANDLER(set_win_timer);
 DECL_HANDLER(kill_win_timer);
-DECL_HANDLER(create_serial);
 DECL_HANDLER(get_serial_info);
 DECL_HANDLER(set_serial_info);
 DECL_HANDLER(register_async);
@@ -419,7 +418,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_get_message_reply,
     (req_handler)req_set_win_timer,
     (req_handler)req_kill_win_timer,
-    (req_handler)req_create_serial,
     (req_handler)req_get_serial_info,
     (req_handler)req_set_serial_info,
     (req_handler)req_register_async,
diff --git a/server/serial.c b/server/serial.c
index 65dd087caffefac2bea836b04039f097b6e02866..ae82199796e542c78751f48237962ff645985ce7 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -46,6 +46,8 @@
 #include "winerror.h"
 #include "windef.h"
 #include "winbase.h"
+#include "winreg.h"
+#include "winternl.h"
 
 #include "file.h"
 #include "handle.h"
@@ -67,8 +69,7 @@ struct serial
 {
     struct object       obj;
     struct fd          *fd;
-    unsigned int        access;
-    unsigned int        attrib;
+    unsigned int        options;
 
     /* timeout values */
     unsigned int        readinterval;
@@ -110,55 +111,32 @@ static const struct fd_ops serial_fd_ops =
     serial_queue_async            /* queue_async */
 };
 
-static struct serial *create_serial( const char *nameptr, size_t len, unsigned int access, int attributes )
+/* check if the given fd is a serial port */
+int is_serial_fd( struct fd *fd )
 {
-    struct serial *serial;
     struct termios tios;
-    int fd, flags = 0;
-    char *name;
-
-    if (!(name = mem_alloc( len + 1 ))) return NULL;
-    memcpy( name, nameptr, len );
-    name[len] = 0;
-
-    switch(access & (GENERIC_READ | GENERIC_WRITE))
-    {
-    case GENERIC_READ:  flags |= O_RDONLY; break;
-    case GENERIC_WRITE: flags |= O_WRONLY; break;
-    case GENERIC_READ|GENERIC_WRITE: flags |= O_RDWR; break;
-    default: break;
-    }
 
-    flags |= O_NONBLOCK;
+    return !tcgetattr( get_unix_fd(fd), &tios );
+}
 
-    fd = open( name, flags );
-    free( name );
-    if (fd < 0)
-    {
-        file_set_error();
-        return NULL;
-    }
+/* create a serial object for a given fd */
+struct object *create_serial( struct fd *fd, unsigned int options )
+{
+    struct serial *serial;
+    int unix_fd;
 
-    /* check its really a serial port */
-    if (tcgetattr(fd,&tios))
-    {
-        file_set_error();
-        close( fd );
-        return NULL;
-    }
+    if ((unix_fd = dup( get_unix_fd(fd) )) == -1) return NULL;
 
     /* set the fd back to blocking if necessary */
-    if( ! (attributes & FILE_FLAG_OVERLAPPED) )
-       if(0>fcntl(fd, F_SETFL, 0))
-           perror("fcntl");
+    if (options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
+        fcntl( unix_fd, F_SETFL, 0 );
 
     if (!(serial = alloc_object( &serial_ops )))
     {
-        close( fd );
+        close( unix_fd );
         return NULL;
     }
-    serial->attrib       = attributes;
-    serial->access       = access;
+    serial->options      = options;
     serial->readinterval = 0;
     serial->readmult     = 0;
     serial->readconst    = 0;
@@ -169,12 +147,12 @@ static struct serial *create_serial( const char *nameptr, size_t len, unsigned i
     init_async_queue(&serial->read_q);
     init_async_queue(&serial->write_q);
     init_async_queue(&serial->wait_q);
-    if (!(serial->fd = create_anonymous_fd( &serial_fd_ops, fd, &serial->obj )))
+    if (!(serial->fd = create_anonymous_fd( &serial_fd_ops, unix_fd, &serial->obj )))
     {
         release_object( serial );
         return NULL;
     }
-    return serial;
+    return &serial->obj;
 }
 
 static struct fd *serial_get_fd( struct object *obj )
@@ -243,7 +221,7 @@ static int serial_get_info( struct fd *fd, struct get_file_info_reply *reply, in
     }
 
     *flags = 0;
-    if(serial->attrib & FILE_FLAG_OVERLAPPED)
+    if (!(serial->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
         *flags |= FD_FLAG_OVERLAPPED;
     else if(!((serial->readinterval == MAXDWORD) &&
               (serial->readmult == 0) && (serial->readconst == 0)) )
@@ -341,19 +319,6 @@ static int serial_flush( struct fd *fd, struct event **event )
     return ret;
 }
 
-/* create a serial */
-DECL_HANDLER(create_serial)
-{
-    struct serial *serial;
-
-    reply->handle = 0;
-    if ((serial = create_serial( get_req_data(), get_req_data_size(), req->access, req->attributes )))
-    {
-        reply->handle = alloc_handle( current->process, serial, req->access, req->inherit );
-        release_object( serial );
-    }
-}
-
 DECL_HANDLER(get_serial_info)
 {
     struct serial *serial;
diff --git a/server/trace.c b/server/trace.c
index 30f0f31b5fae8d25f00149d8c04c09fdff5267d4..0294019540e562f00faec04ccde753eae9d33ba7 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1923,21 +1923,6 @@ static void dump_kill_win_timer_request( const struct kill_win_timer_request *re
     fprintf( stderr, " id=%08x", req->id );
 }
 
-static void dump_create_serial_request( const struct create_serial_request *req )
-{
-    fprintf( stderr, " access=%08x,", req->access );
-    fprintf( stderr, " inherit=%d,", req->inherit );
-    fprintf( stderr, " attributes=%08x,", req->attributes );
-    fprintf( stderr, " sharing=%08x,", req->sharing );
-    fprintf( stderr, " name=" );
-    dump_varargs_string( cur_size );
-}
-
-static void dump_create_serial_reply( const struct create_serial_reply *req )
-{
-    fprintf( stderr, " handle=%p", req->handle );
-}
-
 static void dump_get_serial_info_request( const struct get_serial_info_request *req )
 {
     fprintf( stderr, " handle=%p", req->handle );
@@ -2711,7 +2696,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_get_message_reply_request,
     (dump_func)dump_set_win_timer_request,
     (dump_func)dump_kill_win_timer_request,
-    (dump_func)dump_create_serial_request,
     (dump_func)dump_get_serial_info_request,
     (dump_func)dump_set_serial_info_request,
     (dump_func)dump_register_async_request,
@@ -2895,7 +2879,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_get_message_reply_reply,
     (dump_func)0,
     (dump_func)0,
-    (dump_func)dump_create_serial_reply,
     (dump_func)dump_get_serial_info_reply,
     (dump_func)0,
     (dump_func)0,
@@ -3079,7 +3062,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "get_message_reply",
     "set_win_timer",
     "kill_win_timer",
-    "create_serial",
     "get_serial_info",
     "set_serial_info",
     "register_async",