server: implement basics of object manager for nt_namespace

Vitaliy Margolen wine-patch at kievinfo.com
Sat Sep 3 22:04:42 CDT 2005


First step in implementing object manager the way it is on nt. I didn't want to
go to far it until I'll get part in.

This patch requires previous patch to find_object.

Vitaliy Margolen

changelog:
  Implement basics of object manager for nt_namespace
-------------- next part --------------
Index: include/wine/server_protocol.h
===================================================================
RCS file: /home/wine/wine/include/wine/server_protocol.h,v
retrieving revision 1.155
diff -u -p -r1.155 server_protocol.h
--- include/wine/server_protocol.h	24 Aug 2005 18:33:51 -0000	1.155
+++ include/wine/server_protocol.h	3 Sep 2005 23:49:07 -0000
@@ -3575,6 +3575,170 @@ struct set_mailslot_info_reply
 #define MAILSLOT_SET_READ_TIMEOUT  1
 
 
+
+struct create_file_ob_request
+{
+    struct request_header __header;
+    unsigned int   attributes;
+    unsigned int   access_mask;
+    /* VARARG(device_name,unicode_str); */
+};
+struct create_file_ob_reply
+{
+    struct reply_header __header;
+    obj_handle_t   handle;
+};
+
+
+struct make_temporary_object_request
+{
+    struct request_header __header;
+    obj_handle_t   handle;
+};
+struct make_temporary_object_reply
+{
+    struct reply_header __header;
+};
+
+
+struct query_object_request
+{
+    struct request_header __header;
+    obj_handle_t   handle;
+};
+struct query_object_reply
+{
+    struct reply_header __header;
+    unsigned int   attributes;
+    unsigned int   access_mask;
+    unsigned int   refcount;
+};
+
+
+
+struct create_symlink_request
+{
+    struct request_header __header;
+    unsigned int   attributes;
+    unsigned int   access_mask;
+    size_t         symlink_name_len;
+    /* VARARG(symlink_name,unicode_str,symlink_name_len); */
+    /* VARARG(target_name,unicode_str); */
+};
+struct create_symlink_reply
+{
+    struct reply_header __header;
+    obj_handle_t   handle;
+};
+
+
+struct open_symlink_request
+{
+    struct request_header __header;
+    unsigned int   attributes;
+    unsigned int   access_mask;
+    /* VARARG(symlink_name,unicode_str); */
+};
+struct open_symlink_reply
+{
+    struct reply_header __header;
+    obj_handle_t   handle;
+};
+
+
+struct query_symlink_request
+{
+    struct request_header __header;
+    obj_handle_t   handle;
+};
+struct query_symlink_reply
+{
+    struct reply_header __header;
+    /* VARARG(target_name,unicode_str); */
+};
+
+
+struct delete_symlink_request
+{
+    struct request_header __header;
+    unsigned int   attributes;
+    /* VARARG(symlink_name,unicode_str); */
+};
+struct delete_symlink_reply
+{
+    struct reply_header __header;
+};
+
+
+struct create_directory_request
+{
+    struct request_header __header;
+    unsigned int   attributes;
+    unsigned int   access_mask;
+    /* VARARG(directory_name,unicode_str); */
+};
+struct create_directory_reply
+{
+    struct reply_header __header;
+    obj_handle_t   handle;
+};
+
+
+struct open_directory_request
+{
+    struct request_header __header;
+    unsigned int   attributes;
+    unsigned int   access_mask;
+    /* VARARG(directory_name,unicode_str); */
+};
+struct open_directory_reply
+{
+    struct reply_header __header;
+    obj_handle_t   handle;
+};
+
+
+struct query_directory_request
+{
+    struct request_header __header;
+    obj_handle_t   handle;
+    unsigned int   index;
+    int            need_count;
+};
+struct query_directory_reply
+{
+    struct reply_header __header;
+    unsigned int   count;
+    size_t         name_len;
+    /* VARARG(name,unicode_str,name_len); */
+    /* VARARG(type,unicode_str); */
+};
+
+
+struct create_device_request
+{
+    struct request_header __header;
+    unsigned int   attributes;
+    void*          device_object;
+    /* VARARG(device_name,unicode_str); */
+};
+struct create_device_reply
+{
+    struct reply_header __header;
+};
+
+
+struct delete_device_request
+{
+    struct request_header __header;
+    void*          device_object;
+};
+struct delete_device_reply
+{
+    struct reply_header __header;
+};
+
+
 enum request
 {
     REQ_new_process,
@@ -3782,6 +3946,18 @@ enum request
     REQ_create_mailslot,
     REQ_open_mailslot,
     REQ_set_mailslot_info,
+    REQ_create_file_ob,
+    REQ_make_temporary_object,
+    REQ_query_object,
+    REQ_create_symlink,
+    REQ_open_symlink,
+    REQ_query_symlink,
+    REQ_delete_symlink,
+    REQ_create_directory,
+    REQ_open_directory,
+    REQ_query_directory,
+    REQ_create_device,
+    REQ_delete_device,
     REQ_NB_REQUESTS
 };
 
@@ -3994,6 +4170,18 @@ union generic_request
     struct create_mailslot_request create_mailslot_request;
     struct open_mailslot_request open_mailslot_request;
     struct set_mailslot_info_request set_mailslot_info_request;
+    struct create_file_ob_request create_file_ob_request;
+    struct make_temporary_object_request make_temporary_object_request;
+    struct query_object_request query_object_request;
+    struct create_symlink_request create_symlink_request;
+    struct open_symlink_request open_symlink_request;
+    struct query_symlink_request query_symlink_request;
+    struct delete_symlink_request delete_symlink_request;
+    struct create_directory_request create_directory_request;
+    struct open_directory_request open_directory_request;
+    struct query_directory_request query_directory_request;
+    struct create_device_request create_device_request;
+    struct delete_device_request delete_device_request;
 };
 union generic_reply
 {
@@ -4204,8 +4392,20 @@ union generic_reply
     struct create_mailslot_reply create_mailslot_reply;
     struct open_mailslot_reply open_mailslot_reply;
     struct set_mailslot_info_reply set_mailslot_info_reply;
+    struct create_file_ob_reply create_file_ob_reply;
+    struct make_temporary_object_reply make_temporary_object_reply;
+    struct query_object_reply query_object_reply;
+    struct create_symlink_reply create_symlink_reply;
+    struct open_symlink_reply open_symlink_reply;
+    struct query_symlink_reply query_symlink_reply;
+    struct delete_symlink_reply delete_symlink_reply;
+    struct create_directory_reply create_directory_reply;
+    struct open_directory_reply open_directory_reply;
+    struct query_directory_reply query_directory_reply;
+    struct create_device_reply create_device_reply;
+    struct delete_device_reply delete_device_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 191
+#define SERVER_PROTOCOL_VERSION 192
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
Index: server/Makefile.in
===================================================================
RCS file: /home/wine/wine/server/Makefile.in,v
retrieving revision 1.55
diff -u -p -r1.55 Makefile.in
--- server/Makefile.in	8 Jun 2005 18:44:50 -0000	1.55
+++ server/Makefile.in	3 Sep 2005 23:49:07 -0000
@@ -16,6 +16,7 @@ C_SRCS = \
 	context_powerpc.c \
 	context_sparc.c \
 	debugger.c \
+	om.c \
 	event.c \
 	fd.c \
 	file.c \
Index: server/main.c
===================================================================
RCS file: /home/wine/wine/server/main.c,v
retrieving revision 1.34
diff -u -p -r1.34 main.c
--- server/main.c	25 May 2005 18:41:09 -0000	1.34
+++ server/main.c	3 Sep 2005 23:49:07 -0000
@@ -43,6 +43,9 @@ const char *server_argv0;
 /* name space for synchronization objects */
 struct namespace *sync_namespace;
 
+/* name space for NT devices */
+struct namespace *nt_namespace;
+
 /* parse-line args */
 /* FIXME: should probably use getopt, and add a (more complete?) help option */
 
@@ -130,11 +133,13 @@ int main( int argc, char *argv[] )
     sock_init();
     open_master_socket();
     sync_namespace = create_namespace( 37 );
+    nt_namespace = create_namespace( 37 );
     setvbuf( stderr, NULL, _IOLBF, 0 );
 
     if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
     init_signals();
     init_registry();
+    init_namespace();
     main_loop();
     return 0;
 }
Index: server/object.h
===================================================================
RCS file: /home/wine/wine/server/object.h,v
retrieving revision 1.66
diff -u -p -r1.66 object.h
--- server/object.h	19 Aug 2005 14:01:43 -0000	1.66
+++ server/object.h	3 Sep 2005 23:49:07 -0000
@@ -166,6 +167,11 @@ extern atom_t find_global_atom( struct w
 extern int grab_global_atom( struct winstation *winstation, atom_t atom );
 extern void release_global_atom( struct winstation *winstation, atom_t atom );
 
+/* object management functions */
+
+extern void init_namespace(void);
+extern void close_namespace(void);
+
 /* global variables */
 
   /* command-line options */
@@ -180,4 +186,7 @@ extern time_t server_start_time;
 /* name space for synchronization objects */
 extern struct namespace *sync_namespace;
 
+/* NT name space */
+struct namespace *nt_namespace;
+
 #endif  /* __WINE_SERVER_OBJECT_H */
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.154
diff -u -p -r1.154 protocol.def
--- server/protocol.def	24 Aug 2005 18:33:50 -0000	1.154
+++ server/protocol.def	3 Sep 2005 23:49:07 -0000
@@ -2503,3 +2503,111 @@ enum message_type
     unsigned int   next_msgsize;
 @END
 #define MAILSLOT_SET_READ_TIMEOUT  1
+
+
+/* the way real NtCreateFile should be */
+ at REQ(create_file_ob)
+    unsigned int   attributes;    /* object attributes */
+    unsigned int   access_mask;   /* access flags */
+    VARARG(device_name,unicode_str); /* object name */
+ at REPLY
+    obj_handle_t   handle;        /* object handle */
+ at END
+
+/* Make object temporary */
+ at REQ(make_temporary_object)
+    obj_handle_t   handle;        /* any object handle */
+ at END
+
+/* Query basic object info */
+ at REQ(query_object)
+    obj_handle_t   handle;        /* handle to the object */
+ at REPLY
+    unsigned int   attributes;
+    unsigned int   access_mask;
+    unsigned int   refcount;
+ at END
+
+
+/* Create symbolik link */
+ at REQ(create_symlink)
+    unsigned int   attributes;    /* object attributes */
+    unsigned int   access_mask;   /* access flags */
+    size_t         symlink_name_len; /* length of target_name in bytes */
+    VARARG(symlink_name,unicode_str,symlink_name_len); /* SymbolicLink name */
+    VARARG(target_name,unicode_str); /* Target name */
+ at REPLY
+    obj_handle_t   handle;        /* handle to the symlink */
+ at END
+
+/* Open symbolik link */
+ at REQ(open_symlink)
+    unsigned int   attributes;    /* object attributes */
+    unsigned int   access_mask;   /* access flags */
+    VARARG(symlink_name,unicode_str); /* SymbolicLink name */
+ at REPLY
+    obj_handle_t   handle;        /* handle to the symlink */
+ at END
+
+/* Query symbolik link */
+ at REQ(query_symlink)
+    obj_handle_t   handle;        /* handle to the symlink */
+ at REPLY
+    VARARG(target_name,unicode_str); /* Target name */
+ at END
+
+/* Delete symbolik link */
+ at REQ(delete_symlink)
+    unsigned int   attributes;    /* object attributes */
+    VARARG(symlink_name,unicode_str); /* SymbolicLink name */
+ at END
+
+/* Create directory object */
+ at REQ(create_directory)
+    unsigned int   attributes;    /* object attributes */
+    unsigned int   access_mask;   /* access flags */
+    VARARG(directory_name,unicode_str); /* Directory name */
+ at REPLY
+    obj_handle_t   handle;        /* handle to the directory */
+ at END
+
+/* Open directory object */
+ at REQ(open_directory)
+    unsigned int   attributes;    /* object attributes */
+    unsigned int   access_mask;   /* access flags */
+    VARARG(directory_name,unicode_str); /* Directory name */
+ at REPLY
+    obj_handle_t   handle;        /* handle to the directory */
+ at END
+
+/* Query directory object */
+ at REQ(query_directory)
+    obj_handle_t   handle;        /* handle to the directory */
+    unsigned int   index;         /* index of an object */
+    int            need_count;    /* need to count objects */
+ at REPLY
+    unsigned int   count;         /* number of objects in directory */
+    size_t         name_len;      /* object name size */
+    VARARG(name,unicode_str,name_len); /* object name */
+    VARARG(type,unicode_str);     /* type name */
+ at END
+
+/* Create device object */
+ at REQ(create_device)
+    unsigned int   attributes;    /* object attributes */
+    void*          device_object; /* pointer to DEVICE_OBJECT */
+    VARARG(device_name,unicode_str); /* Device name */
+ at END
+
+/* Delete device object */
+ at REQ(delete_device)
+    void*          device_object; /* pointer to DEVICE_OBJECT */
+ at END
+
+ at REQ(io_resolve_handle)
+    unsigned int access;          /* wanted access rights */
+    obj_handle_t handle;          /* user mode handle */
+    obj_handle_t process;         /* user process handle */
+ at REPLY
+    void*        device_object;   /* kernel mode device object */
+ at END
Index: server/request.c
===================================================================
RCS file: /home/wine/wine/server/request.c,v
retrieving revision 1.93
diff -u -p -r1.93 request.c
--- server/request.c	9 Aug 2005 10:37:50 -0000	1.93
+++ server/request.c	3 Sep 2005 23:49:08 -0000
@@ -797,6 +797,7 @@ static void close_socket_timeout( void *
     close_signals();
     close_global_handles();
     close_registry();
+    close_namespace();
     dump_objects();  /* dump any remaining objects */
 #else
     exit(0);
Index: server/request.h
===================================================================
RCS file: /home/wine/wine/server/request.h,v
retrieving revision 1.123
diff -u -p -r1.123 request.h
--- server/request.h	24 Aug 2005 18:33:50 -0000	1.123
+++ server/request.h	3 Sep 2005 23:49:08 -0000
@@ -308,6 +308,18 @@ DECL_HANDLER(get_token_user);
 DECL_HANDLER(create_mailslot);
 DECL_HANDLER(open_mailslot);
 DECL_HANDLER(set_mailslot_info);
+DECL_HANDLER(create_file_ob);
+DECL_HANDLER(make_temporary_object);
+DECL_HANDLER(query_object);
+DECL_HANDLER(create_symlink);
+DECL_HANDLER(open_symlink);
+DECL_HANDLER(query_symlink);
+DECL_HANDLER(delete_symlink);
+DECL_HANDLER(create_directory);
+DECL_HANDLER(open_directory);
+DECL_HANDLER(query_directory);
+DECL_HANDLER(create_device);
+DECL_HANDLER(delete_device);
 
 #ifdef WANT_REQUEST_HANDLERS
 
@@ -519,6 +531,18 @@ static const req_handler req_handlers[RE
     (req_handler)req_create_mailslot,
     (req_handler)req_open_mailslot,
     (req_handler)req_set_mailslot_info,
+    (req_handler)req_create_file_ob,
+    (req_handler)req_make_temporary_object,
+    (req_handler)req_query_object,
+    (req_handler)req_create_symlink,
+    (req_handler)req_open_symlink,
+    (req_handler)req_query_symlink,
+    (req_handler)req_delete_symlink,
+    (req_handler)req_create_directory,
+    (req_handler)req_open_directory,
+    (req_handler)req_query_directory,
+    (req_handler)req_create_device,
+    (req_handler)req_delete_device,
 };
 #endif  /* WANT_REQUEST_HANDLERS */
 
Index: server/trace.c
===================================================================
RCS file: /home/wine/wine/server/trace.c,v
retrieving revision 1.262
diff -u -p -r1.262 trace.c
--- server/trace.c	24 Aug 2005 18:33:50 -0000	1.262
+++ server/trace.c	3 Sep 2005 23:49:08 -0000
@@ -3089,6 +3089,141 @@ static void dump_set_mailslot_info_reply
     fprintf( stderr, " next_msgsize=%08x", req->next_msgsize );
 }
 
+static void dump_create_file_ob_request( const struct create_file_ob_request *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " access_mask=%08x,", req->access_mask );
+    fprintf( stderr, " device_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_create_file_ob_reply( const struct create_file_ob_reply *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_make_temporary_object_request( const struct make_temporary_object_request *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_query_object_request( const struct query_object_request *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_query_object_reply( const struct query_object_reply *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " access_mask=%08x,", req->access_mask );
+    fprintf( stderr, " refcount=%08x", req->refcount );
+}
+
+static void dump_create_symlink_request( const struct create_symlink_request *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " access_mask=%08x,", req->access_mask );
+    fprintf( stderr, " symlink_name_len=%d,", req->symlink_name_len );
+    fprintf( stderr, " symlink_name=" );
+    dump_varargs_unicode_str( min(cur_size,req->symlink_name_len) );
+    fputc( ',', stderr );
+    fprintf( stderr, " target_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_create_symlink_reply( const struct create_symlink_reply *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_open_symlink_request( const struct open_symlink_request *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " access_mask=%08x,", req->access_mask );
+    fprintf( stderr, " symlink_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_open_symlink_reply( const struct open_symlink_reply *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_query_symlink_request( const struct query_symlink_request *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_query_symlink_reply( const struct query_symlink_reply *req )
+{
+    fprintf( stderr, " target_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_delete_symlink_request( const struct delete_symlink_request *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " symlink_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_create_directory_request( const struct create_directory_request *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " access_mask=%08x,", req->access_mask );
+    fprintf( stderr, " directory_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_create_directory_reply( const struct create_directory_reply *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_open_directory_request( const struct open_directory_request *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " access_mask=%08x,", req->access_mask );
+    fprintf( stderr, " directory_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_open_directory_reply( const struct open_directory_reply *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
+}
+
+static void dump_query_directory_request( const struct query_directory_request *req )
+{
+    fprintf( stderr, " handle=%p,", req->handle );
+    fprintf( stderr, " index=%08x,", req->index );
+    fprintf( stderr, " need_count=%d", req->need_count );
+}
+
+static void dump_query_directory_reply( const struct query_directory_reply *req )
+{
+    fprintf( stderr, " count=%08x,", req->count );
+    fprintf( stderr, " name_len=%d,", req->name_len );
+    fprintf( stderr, " name=" );
+    dump_varargs_unicode_str( min(cur_size,req->name_len) );
+    fputc( ',', stderr );
+    fprintf( stderr, " type=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_create_device_request( const struct create_device_request *req )
+{
+    fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " device_object=%p,", req->device_object );
+    fprintf( stderr, " device_name=" );
+    dump_varargs_unicode_str( cur_size );
+}
+
+static void dump_delete_device_request( const struct delete_device_request *req )
+{
+    fprintf( stderr, " device_object=%p", req->device_object );
+}
+
 static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_process_request,
     (dump_func)dump_get_new_process_info_request,
@@ -3295,6 +3430,18 @@ static const dump_func req_dumpers[REQ_N
     (dump_func)dump_create_mailslot_request,
     (dump_func)dump_open_mailslot_request,
     (dump_func)dump_set_mailslot_info_request,
+    (dump_func)dump_create_file_ob_request,
+    (dump_func)dump_make_temporary_object_request,
+    (dump_func)dump_query_object_request,
+    (dump_func)dump_create_symlink_request,
+    (dump_func)dump_open_symlink_request,
+    (dump_func)dump_query_symlink_request,
+    (dump_func)dump_delete_symlink_request,
+    (dump_func)dump_create_directory_request,
+    (dump_func)dump_open_directory_request,
+    (dump_func)dump_query_directory_request,
+    (dump_func)dump_create_device_request,
+    (dump_func)dump_delete_device_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -3503,6 +3650,18 @@ static const dump_func reply_dumpers[REQ
     (dump_func)dump_create_mailslot_reply,
     (dump_func)dump_open_mailslot_reply,
     (dump_func)dump_set_mailslot_info_reply,
+    (dump_func)dump_create_file_ob_reply,
+    (dump_func)0,
+    (dump_func)dump_query_object_reply,
+    (dump_func)dump_create_symlink_reply,
+    (dump_func)dump_open_symlink_reply,
+    (dump_func)dump_query_symlink_reply,
+    (dump_func)0,
+    (dump_func)dump_create_directory_reply,
+    (dump_func)dump_open_directory_reply,
+    (dump_func)dump_query_directory_reply,
+    (dump_func)0,
+    (dump_func)0,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -3711,6 +3870,18 @@ static const char * const req_names[REQ_
     "create_mailslot",
     "open_mailslot",
     "set_mailslot_info",
+    "create_file_ob",
+    "make_temporary_object",
+    "query_object",
+    "create_symlink",
+    "open_symlink",
+    "query_symlink",
+    "delete_symlink",
+    "create_directory",
+    "open_directory",
+    "query_directory",
+    "create_device",
+    "delete_device",
 };
 
 static const struct
@@ -3726,6 +3897,7 @@ static const struct
     { "BUFFER_TOO_SMALL",            STATUS_BUFFER_TOO_SMALL },
     { "CHILD_MUST_BE_VOLATILE",      STATUS_CHILD_MUST_BE_VOLATILE },
     { "DEVICE_BUSY",                 STATUS_DEVICE_BUSY },
+    { "DEVICE_DOES_NOT_EXIST",       STATUS_DEVICE_DOES_NOT_EXIST },
     { "DIRECTORY_NOT_EMPTY",         STATUS_DIRECTORY_NOT_EMPTY },
     { "DISK_FULL",                   STATUS_DISK_FULL },
     { "DLL_NOT_FOUND",               STATUS_DLL_NOT_FOUND },
@@ -3763,6 +3935,7 @@ static const struct
     { "OBJECT_NAME_INVALID",         STATUS_OBJECT_NAME_INVALID },
     { "OBJECT_NAME_NOT_FOUND",       STATUS_OBJECT_NAME_NOT_FOUND },
     { "OBJECT_PATH_INVALID",         STATUS_OBJECT_PATH_INVALID },
+    { "OBJECT_PATH_NOT_FOUND",       STATUS_OBJECT_PATH_NOT_FOUND },
     { "OBJECT_TYPE_MISMATCH",        STATUS_OBJECT_TYPE_MISMATCH },
     { "PENDING",                     STATUS_PENDING },
     { "PIPE_BUSY",                   STATUS_PIPE_BUSY },
@@ -3774,6 +3947,7 @@ static const struct
     { "SECTION_TOO_BIG",             STATUS_SECTION_TOO_BIG },
     { "SEMAPHORE_LIMIT_EXCEEDED",    STATUS_SEMAPHORE_LIMIT_EXCEEDED },
     { "SHARING_VIOLATION",           STATUS_SHARING_VIOLATION },
+    { "SUCCESS",                     STATUS_SUCCESS },
     { "SUSPEND_COUNT_EXCEEDED",      STATUS_SUSPEND_COUNT_EXCEEDED },
     { "TIMEOUT",                     STATUS_TIMEOUT },
     { "UNSUCCESSFUL",                STATUS_UNSUCCESSFUL },
--- /dev/null	2005-03-19 12:36:14.000000000 -0700
+++ server/om.h	2005-09-03 14:09:32.000000000 -0600
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2005 Vitaliy Margolen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define OB_TYPE_TYPE                    1
+#define OB_TYPE_DIRECTORY               2
+#define OB_TYPE_SYMBOLIC_LINK           3
+#define OB_TYPE_TOKEN                   4
+#define OB_TYPE_PROCESS                 5
+#define OB_TYPE_THREAD                  6
+#define OB_TYPE_EVENT                   7
+#define OB_TYPE_EVENT_PAIR              8
+#define OB_TYPE_MUTANT                  9
+#define OB_TYPE_SEMAPHORE               10
+#define OB_TYPE_TIMER                   11
+#define OB_TYPE_PROFILE                 12
+#define OB_TYPE_WINDOW_STATION          13
+#define OB_TYPE_DESKTOP                 14
+#define OB_TYPE_SECTION                 15
+#define OB_TYPE_KEY                     16
+#define OB_TYPE_PORT                    17
+#define OB_TYPE_ADAPTER                 18
+#define OB_TYPE_CONTROLLER              19
+#define OB_TYPE_DEVICE                  20
+#define OB_TYPE_DRIVER                  21
+#define OB_TYPE_IO_COMPLETION           22
+#define OB_TYPE_FILE                    23
+
+#define SYMBOLIC_LINK_QUERY             0x0001
+#define SYMBOLIC_LINK_ALL_ACCESS        (STANDARD_RIGHTS_REQUIRED | 0x1)
+
+#define DIRECTORY_QUERY                 (0x0001)
+#define DIRECTORY_TRAVERSE              (0x0002)
+#define DIRECTORY_CREATE_OBJECT         (0x0004)
+#define DIRECTORY_CREATE_SUBDIRECTORY   (0x0008)
+#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF)
+
+static const WCHAR STR_NONE          []={'u','n','k','n','o','w','n',0};
+static const WCHAR STR_TYPE          []={'T','y','p','e',0};
+static const WCHAR STR_DIRECTORY     []={'D','i','r','e','c','t','o','r','y',0};
+static const WCHAR STR_SYMBOLIC_LINK []={'S','y','m','b','o','l','i','c','L','i','n','k',0};
+static const WCHAR STR_TOKEN         []={'T','o','k','e','n',0};
+static const WCHAR STR_PROCESS       []={'P','r','o','c','e','s','s',0};
+static const WCHAR STR_THREAD        []={'T','h','r','e','a','d',0};
+static const WCHAR STR_EVENT         []={'E','v','e','n','t',0};
+static const WCHAR STR_EVENT_PAIR    []={'E','v','e','n','t','P','a','i','r',0};
+static const WCHAR STR_MUTANT        []={'M','u','t','a','n','t',0};
+static const WCHAR STR_SEMAPHORE     []={'S','e','m','a','p','h','o','r','e',0};
+static const WCHAR STR_TIMER         []={'T','i','m','e','r',0};
+static const WCHAR STR_PROFILE       []={'P','r','o','f','i','l','e',0};
+static const WCHAR STR_WINDOW_STATION[]={'W','i','n','d','o','w','S','t','a','t','i','o','n',0};
+static const WCHAR STR_DESKTOP       []={'D','e','s','k','t','o','p',0};
+static const WCHAR STR_SECTION       []={'S','e','c','t','i','o','n',0};
+static const WCHAR STR_KEY           []={'K','e','y',0};
+static const WCHAR STR_PORT          []={'P','o','r','t',0};
+static const WCHAR STR_ADAPTER       []={'A','d','a','p','t','e','r',0};
+static const WCHAR STR_CONTROLLER    []={'C','o','n','t','r','o','l','l','e','r',0};
+static const WCHAR STR_DEVICE        []={'D','e','v','i','c','e',0};
+static const WCHAR STR_DRIVER        []={'D','r','i','v','e','r',0};
+static const WCHAR STR_IO_COMPLETION []={'I','o','C','o','m','p','l','e','t','i','o','n',0};
+static const WCHAR STR_FILE          []={'F','i','l','e',0};
+                                           
+const WCHAR *type_names [24] =
+{
+    STR_NONE,
+    STR_TYPE,
+    STR_DIRECTORY,
+    STR_SYMBOLIC_LINK,
+    STR_TOKEN,
+    STR_PROCESS,
+    STR_THREAD,
+    STR_EVENT,
+    STR_EVENT_PAIR,
+    STR_MUTANT,
+    STR_SEMAPHORE,
+    STR_TIMER,
+    STR_PROFILE,
+    STR_WINDOW_STATION,
+    STR_DESKTOP,
+    STR_SECTION,
+    STR_KEY,
+    STR_PORT,
+    STR_ADAPTER,
+    STR_CONTROLLER,
+    STR_DEVICE,
+    STR_DRIVER,
+    STR_IO_COMPLETION,
+    STR_FILE
+};
--- /dev/null	2005-03-19 12:36:14.000000000 -0700
+++ server/om.c	2005-09-03 17:33:14.000000000 -0600
@@ -0,0 +1,675 @@
+/*
+ * Server-side object management
+ *
+ * Copyright (C) 2005 Vitaliy Margolen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#include <time.h>
+#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
+#include "windef.h"
+#include "winternl.h"
+#include "om.h"
+
+#include "file.h"
+#include "handle.h"
+#include "request.h"
+#include "process.h"
+#include "unicode.h"
+#include "wine/list.h"
+
+#define IS_PERMANENT(o) ((o)->attributes & OBJ_PERMANENT)
+
+/* list of created devices */
+static struct list devices_list = LIST_INIT(devices_list);
+
+struct ob_directory;
+
+struct generic_obj
+{
+    struct object  obj;           /* object header */
+    struct list    entry;         /* entry in directory list */
+    struct ob_directory *parent;  /* parent directory */
+    unsigned short type;          /* object type */
+    unsigned long  attributes;    /* object attributes */
+    unsigned long  access_mask;   /* access mask */
+};
+
+static void delete_generic_obj(struct generic_obj *obj);
+static void remove_from_dir(struct object *obj);
+
+struct ob_symlink
+{
+    struct generic_obj g_obj;     /* common fields */
+    WCHAR *target_name;           /* target of the symlink */
+    size_t target_name_len;       /* length of the target name */
+};
+
+struct ob_directory
+{
+    struct generic_obj g_obj;     /* common fields */
+    struct list entries;          /* list objects in this directory */
+};
+
+struct ob_device
+{
+    struct generic_obj g_obj;     /* common fields */
+    struct list entry;            /* entry in devices_list */
+    void *device_object;          /* pointer to DEVICE_OBJECT */
+};
+
+static void ob_symlink_dump( struct object *obj, int verbose );
+static void ob_symlink_destroy( struct object *obj );
+static const struct object_ops ob_symlink_ops =
+{
+    sizeof(struct ob_symlink),    /* size */
+    ob_symlink_dump,              /* dump */
+    no_add_queue,                 /* add_queue */
+    NULL,                         /* remove_queue */
+    NULL,                         /* signaled */
+    NULL,                         /* satisfied */
+    no_signal,                    /* signal */
+    no_get_fd,                    /* get_fd */
+    no_close_handle,              /* close_handle */
+    ob_symlink_destroy            /* destroy */
+};
+
+static void ob_directory_dump( struct object *obj, int verbose );
+static void ob_directory_destroy( struct object *obj );
+static const struct object_ops ob_directory_ops =
+{
+    sizeof(struct ob_directory),     /* size */
+    ob_directory_dump,               /* dump */
+    no_add_queue,                 /* add_queue */
+    NULL,                         /* remove_queue */
+    NULL,                         /* signaled */
+    NULL,                         /* satisfied */
+    no_signal,                    /* signal */
+    no_get_fd,                    /* get_fd */
+    no_close_handle,              /* close_handle */
+    ob_directory_destroy             /* destroy */
+};
+
+static void ob_device_dump( struct object *obj, int verbose );
+static void ob_device_destroy( struct object *obj );
+static const struct object_ops ob_device_ops =
+{
+    sizeof(struct ob_device),     /* size */
+    ob_device_dump,               /* dump */
+    no_add_queue,                 /* add_queue */
+    NULL,                         /* remove_queue */
+    NULL,                         /* signaled */
+    NULL,                         /* satisfied */
+    no_signal,                    /* signal */
+    no_get_fd,                    /* get_fd */
+    no_close_handle,              /* close_handle */
+    ob_device_destroy             /* destroy */
+};
+
+static void ob_symlink_dump( struct object *obj, int verbose )
+{
+    struct ob_symlink *symlink = (struct ob_symlink *)obj;
+    fputs( "Symbolic Link ", stderr );
+    dump_object_name( obj );
+    fprintf( stderr, " -> L\"" );
+    dump_strW( symlink->target_name, symlink->target_name_len / sizeof(WCHAR), stderr, "\"\"" );
+    fputs( "\"\n", stderr );
+}
+
+static void ob_symlink_destroy( struct object *obj )
+{
+    assert( obj->ops == &ob_symlink_ops );
+    remove_from_dir( obj );
+    free( ((struct ob_symlink *)obj)->target_name );
+}
+
+static void ob_directory_dump( struct object *obj, int verbose )
+{
+    struct ob_directory *dir = (struct ob_directory *)obj;
+    
+    fputs( "Directory ", stderr );
+    dump_object_name( obj );
+    if (verbose)
+    {
+        struct generic_obj *g_obj;
+
+        assert( obj->ops == &ob_directory_ops );
+        fputs( " entries:\n", stderr );
+        LIST_FOR_EACH_ENTRY(g_obj, &dir->entries, struct generic_obj, entry)
+        {
+            fputs( "  ", stderr );
+            dump_strW( type_names[g_obj->type], strlenW(type_names[g_obj->type]),
+                       stderr, "\"\"" );
+            fputs( " object ", stderr );
+            dump_object_name( &g_obj->obj );
+            fputc( '\n', stderr );
+        }
+    }
+    else
+        fputc( '\n', stderr );
+}
+
+static void ob_directory_destroy( struct object *obj )
+{
+    struct generic_obj *g_obj, *next;
+    struct ob_directory *dir = (struct ob_directory *)obj;
+    assert( obj->ops == &ob_directory_ops );
+
+    LIST_FOR_EACH_ENTRY_SAFE( g_obj, next, &dir->entries, struct generic_obj , entry )
+    {
+        if (IS_PERMANENT( g_obj ))
+            release_object( g_obj );
+        delete_generic_obj( g_obj );
+    }
+
+    remove_from_dir( obj );
+}
+
+static void ob_device_dump( struct object *obj, int verbose )
+{
+    struct ob_device *device = (struct ob_device *) obj;
+    assert( obj->ops == &ob_device_ops );
+    fprintf( stderr, "Device " );
+    dump_object_name( obj );
+    if (verbose)
+    {
+        fprintf( stderr, " device_obj=%p", device->device_object );
+    }
+    fputc( '\n', stderr );
+}
+
+static void ob_device_destroy( struct object *obj )
+{
+    assert( obj->ops == &ob_device_ops );
+    remove_from_dir( obj );
+}
+
+/******************************************************************************/
+
+static struct object *get_real_object(const WCHAR *name, size_t len, int case_sensitive)
+{
+    struct object *obj;
+    
+    if ((obj = find_object( nt_namespace, name, len, case_sensitive )))
+    {
+        if (obj->ops == &ob_symlink_ops)
+        {
+            struct ob_symlink *symlink = (struct ob_symlink *)obj;
+            struct object *obj1;
+
+            /* symlinks could be nested */
+            while ((obj1 = find_object( nt_namespace, symlink->target_name,
+                                        symlink->target_name_len, case_sensitive )))
+            {
+                symlink = (struct ob_symlink *)obj1;
+                release_object( obj );
+                obj = obj1;
+                if (obj1->ops != &ob_symlink_ops)
+                    break;
+            }
+        }
+        return obj;
+    }
+    return NULL;
+}
+
+static struct ob_directory *get_parent_directory(const WCHAR *name, size_t len, int case_sensitive)
+{
+    WCHAR *p = memrchrW( name, '\\', len / sizeof(WCHAR) );
+    struct object *obj;
+
+    /* No parent for root */
+    if (p && len == sizeof(WCHAR))
+        return NULL;
+
+    /* Keep leading \\ */
+    if (!(p - name)) p++;
+
+    obj = get_real_object( name, (p - name)*sizeof(WCHAR), case_sensitive );
+    if (obj)
+    {
+        if (obj->ops == &ob_directory_ops)
+            return (struct ob_directory *)obj;
+        else
+            release_object( obj );
+    }
+    return NULL;
+}
+
+static BOOL add_to_dir(struct generic_obj *obj, int case_sensitive)
+{
+    size_t len;
+    const WCHAR *name = get_object_name((struct object *)obj, &len);
+    struct ob_directory *dir = get_parent_directory( name, len, case_sensitive );
+
+    /* No parent for root */
+    if (len == sizeof(WCHAR) && *name == '\\')
+        return TRUE;
+    
+    if (dir)
+    {
+        obj->parent = dir;
+        list_add_tail( &dir->entries, &obj->entry );
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static void remove_from_dir(struct object *obj)
+{
+    struct ob_directory *dir = ((struct generic_obj *)obj)->parent;
+    if (dir)
+    {
+        list_remove( &((struct generic_obj *)obj)->entry );
+        /* double release for get_parent_directory: 1) here, 2) creation */
+        release_object( dir );
+        release_object( dir );
+    }
+}
+
+static struct generic_obj *
+create_generic_obj( const struct object_ops *ops, const WCHAR *name, size_t len,
+                    unsigned long attributes, unsigned long access_mask )
+{
+    struct generic_obj *obj = create_named_object( nt_namespace, ops, name, len );
+
+    if (!obj) return NULL;
+    if (obj && !add_to_dir( obj, !(attributes & OBJ_CASE_INSENSITIVE)))
+    {
+        set_error( STATUS_OBJECT_PATH_NOT_FOUND );
+        release_object( obj );
+        return NULL;
+    }
+    obj->attributes = attributes;
+    obj->access_mask = access_mask;
+    if (IS_PERMANENT(obj))
+        grab_object(&obj->obj);
+
+    return obj;
+}
+
+static obj_handle_t
+open_generic_obj_ex( const struct object_ops *ops, const WCHAR *name, size_t len,
+                     unsigned long attributes, unsigned long access_mask,
+                     int follow_symlinks )
+{
+    struct object *obj;
+    obj_handle_t handle = 0;
+
+    if (follow_symlinks)
+        obj = get_real_object( name, len, !(attributes & OBJ_CASE_INSENSITIVE) );
+    else
+        obj = find_object( nt_namespace, name, len,
+                           !(attributes & OBJ_CASE_INSENSITIVE) );
+    if (obj)
+    {
+        if (ops && obj->ops != ops)
+            set_error( STATUS_OBJECT_TYPE_MISMATCH );
+        else
+            handle = alloc_handle( current->process, obj, access_mask,
+                                   attributes & OBJ_INHERIT );
+        release_object( obj );
+    }
+    else set_error( STATUS_OBJECT_NAME_NOT_FOUND );
+    return handle;
+}
+
+static obj_handle_t
+open_generic_obj( const struct object_ops *ops, const WCHAR *name, size_t len,
+                  unsigned long attributes, unsigned long access_mask)
+{
+    return open_generic_obj_ex( ops, name, len, attributes, access_mask, 0);
+}
+
+static void delete_generic_obj( struct generic_obj *obj)
+{
+    release_object( obj );
+}
+
+static void make_temporary_obj( obj_handle_t handle )
+{
+    struct object * obj;
+    
+    if ((obj = get_handle_obj( current->process, handle, 0, &ob_symlink_ops )) ||
+        (obj = get_handle_obj( current->process, handle, 0, &ob_directory_ops )) ||
+        (obj = get_handle_obj( current->process, handle, 0, &ob_device_ops )))
+    {
+        if (IS_PERMANENT( (struct generic_obj*)obj ))
+            release_object( obj );
+        set_error( STATUS_SUCCESS );
+    }
+}
+
+
+/******************************************************************************/
+
+static struct ob_symlink *
+create_symlink(const WCHAR *symlink_name, size_t symlink_len, const WCHAR *target_name,
+               size_t target_len, unsigned long attributes, unsigned long access_mask)
+{
+    struct ob_symlink *symlink = (struct ob_symlink *)
+        create_generic_obj( &ob_symlink_ops, symlink_name, symlink_len, attributes,
+                            access_mask );
+
+    if (!symlink) return NULL;
+
+    symlink->g_obj.type = OB_TYPE_SYMBOLIC_LINK;
+    symlink->target_name = memdup(target_name, target_len);
+    symlink->target_name_len = target_len;
+
+    return symlink;
+}
+
+/******************************************************************************/
+
+static struct ob_directory*
+create_directory(const WCHAR *name, size_t len, unsigned long attributes,
+                 unsigned long access_mask)
+{
+    struct ob_directory *dir = (struct ob_directory *)
+        create_generic_obj( &ob_directory_ops, name, len, attributes, access_mask );
+
+    if (!dir) return NULL;
+    dir->g_obj.type = OB_TYPE_DIRECTORY;
+    list_init(&dir->entries);
+
+    return dir;
+}
+
+static void delete_directory ( struct ob_directory *dir )
+{
+    if (dir)
+    {
+        struct generic_obj *obj, *next;
+
+        LIST_FOR_EACH_ENTRY_SAFE( obj, next, &dir->entries, struct generic_obj , entry )
+        {
+            if (obj->obj.ops == &ob_directory_ops)
+            {
+                delete_directory( (struct ob_directory *)obj );
+            }
+            else
+            {
+                if (IS_PERMANENT( obj ))
+                    release_object( obj );
+                delete_generic_obj( obj );
+            }
+        }
+        if (IS_PERMANENT( &dir->g_obj ))
+            release_object( dir );
+        release_object( dir );
+    }
+}
+
+/******************************************************************************/
+
+static struct ob_device *
+create_device(const WCHAR *name, size_t len, unsigned long attributes,
+              unsigned long access_mask, void *dev)
+{
+    struct ob_device *device = (struct ob_device *)
+        create_generic_obj( &ob_device_ops, name, len, attributes, access_mask );
+
+    if (!device) return NULL;
+    device->g_obj.type = OB_TYPE_DEVICE;
+    device->device_object = dev;
+
+    list_add_tail(&devices_list, &device->entry);
+    return device;
+}
+
+/******************************************************************************/
+
+/* Create default entries */
+void init_namespace(void)
+{
+    /* Directories */
+    static const WCHAR rootW[]={'\\'};
+    static const WCHAR ntspaceW[]={'\\','?','?'};
+    static const WCHAR deviceW[]={'\\','D','e','v','i','c','e'};
+    static const WCHAR driverW[]={'\\','D','r','i','v','e','r'};
+    /* Symlinks */
+    static const WCHAR dosdevW[]={'\\','D','o','s','D','e','v','i','c','e','s'};
+    static const WCHAR globalW[]={'\\','?','?','\\','G','l','o','b','a','l'};
+
+    create_directory(rootW, sizeof(rootW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS);
+    create_directory(ntspaceW, sizeof(ntspaceW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS);
+    create_directory(deviceW, sizeof(deviceW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS);
+    create_directory(driverW, sizeof(driverW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS);
+
+    create_symlink(dosdevW, sizeof(dosdevW), ntspaceW, sizeof(ntspaceW), OBJ_PERMANENT, SYMBOLIC_LINK_ALL_ACCESS);
+    create_symlink(globalW, sizeof(globalW), ntspaceW, sizeof(ntspaceW), OBJ_PERMANENT, SYMBOLIC_LINK_ALL_ACCESS);
+}
+
+void close_namespace(void)
+{
+    static const WCHAR rootW[]={'\\'};
+    struct object *obj = find_object( nt_namespace, rootW, sizeof(rootW), TRUE );
+    delete_directory( (struct ob_directory *)obj );
+    release_object( obj );
+}
+
+/******************************************************************************/
+
+DECL_HANDLER(create_file_ob)
+{
+    reply->handle = open_generic_obj_ex( NULL,
+                                         get_req_data(), get_req_data_size(),
+                                         req->attributes, req->access_mask, 1 );
+}
+
+DECL_HANDLER(make_temporary_object)
+{
+    make_temporary_obj(req->handle);
+}
+
+DECL_HANDLER(query_object)
+{
+    struct object *obj = get_handle_obj( current->process, req->handle,
+                                        DIRECTORY_QUERY, NULL );
+    if (!obj) return;
+    reply->attributes = ((struct generic_obj*)obj)->attributes;
+    reply->access_mask = get_handle_access( current->process, req->handle );
+    reply->refcount = obj->refcount;
+}
+
+/******************************************************************************/
+
+DECL_HANDLER(create_symlink)
+{
+    struct ob_symlink *symlink;
+    WCHAR *target_name, *link_name;
+    size_t target_len, link_len;
+
+    link_name = (WCHAR*)get_req_data();
+    link_len = req->symlink_name_len;
+    target_name = (WCHAR*)get_req_data() + link_len / sizeof(WCHAR);
+    target_len = get_req_data_size() - link_len;
+
+    symlink = create_symlink( link_name, link_len, target_name, target_len,
+                              req->attributes, req->access_mask );
+    if (!symlink) return;
+
+    reply->handle = alloc_handle( current->process, symlink, req->access_mask,
+                                  symlink->g_obj.attributes & OBJ_INHERIT );
+    release_object( symlink );
+}
+
+DECL_HANDLER(open_symlink)
+{
+    reply->handle = open_generic_obj( &ob_symlink_ops,
+                                      get_req_data(), get_req_data_size(),
+                                      req->attributes, req->access_mask );
+}
+
+DECL_HANDLER(query_symlink)
+{
+    struct ob_symlink *symlink = (struct ob_symlink *)get_handle_obj(
+        current->process, req->handle, SYMBOLIC_LINK_QUERY, &ob_symlink_ops);
+
+    if (!symlink) return;
+    
+    if (get_reply_max_size() < symlink->target_name_len)
+    {
+        set_error( STATUS_BUFFER_TOO_SMALL );
+        return;
+    }
+    set_reply_data( symlink->target_name, symlink->target_name_len);
+    release_object( symlink );
+}
+
+DECL_HANDLER(delete_symlink)
+{
+    struct object *obj;
+
+    if ((obj = find_object( nt_namespace, get_req_data(), get_req_data_size(),
+                            !(req->attributes & OBJ_CASE_INSENSITIVE) )))
+    {
+        if (obj->ops == &ob_symlink_ops)
+        {
+            delete_generic_obj( (struct generic_obj*)obj );
+            return;
+        }
+        release_object( obj );
+        set_error( STATUS_OBJECT_TYPE_MISMATCH );
+    }
+    else set_error( STATUS_OBJECT_NAME_NOT_FOUND );
+}
+
+/******************************************************************************/
+
+DECL_HANDLER(create_directory)
+{
+    struct ob_directory *dir;
+    
+    dir = create_directory( get_req_data(), get_req_data_size(),
+                            req->attributes, req->access_mask );
+    if (!dir) return;
+
+    reply->handle = alloc_handle( current->process, dir, req->access_mask,
+                                  dir->g_obj.attributes & OBJ_INHERIT );
+    release_object( dir );
+}
+
+DECL_HANDLER(open_directory)
+{
+    reply->handle = open_generic_obj( &ob_directory_ops,
+                                      get_req_data(), get_req_data_size(),
+                                      req->attributes, req->access_mask );
+}
+
+DECL_HANDLER(query_directory)
+{
+    struct ob_directory * dir;
+    struct generic_obj *obj = NULL, *obj1 = NULL;
+    unsigned int i = 0;
+    const WCHAR *name, *p;
+    size_t len, len1, data_size;
+    char *buffer;
+
+    dir = (struct ob_directory *)get_handle_obj( current->process, req->handle,
+                                            DIRECTORY_QUERY, &ob_directory_ops);    
+    if (!dir) return;
+
+    LIST_FOR_EACH_ENTRY( obj, &dir->entries, struct generic_obj, entry )
+    {
+        if (i++ == req->index)
+        {
+            obj1 = obj;
+            if (!req->need_count)
+                break;
+        }
+    }
+    if (!obj1)
+    {
+        set_error( STATUS_OBJECT_NAME_NOT_FOUND );
+        goto done;
+    }
+    grab_object(&obj1->obj);
+    
+    name = get_object_name(&obj1->obj, &len);
+
+    /* get a name without path */
+    p = memrchrW( name, '\\', len / sizeof(WCHAR) );
+    /* Keep root as a root \\ */
+    if (p && len > sizeof(WCHAR)) p++;
+
+    len -= (p - name) * sizeof(WCHAR);
+    len1 = strlenW(type_names[obj1->type]) * sizeof(WCHAR);
+    data_size = len + len1 + sizeof(OBJDIR_INFORMATION) - 1;
+    if (get_reply_max_size() < data_size)
+    {
+        release_object(&obj1->obj);
+        set_error( STATUS_BUFFER_TOO_SMALL );
+        goto done;
+    }
+    reply->count = i;
+    reply->name_len = len;
+
+    buffer = set_reply_data_size( data_size );
+    buffer = (void*)((POBJDIR_INFORMATION)buffer)->Data;
+    memcpy( buffer, p, len );
+    memcpy( buffer+len, type_names[obj1->type], len1 );
+    
+    release_object(&obj1->obj);
+
+    done:
+    release_object(dir);
+}
+/******************************************************************************/
+
+DECL_HANDLER(create_device)
+{
+    create_device( get_req_data(), get_req_data_size(), req->attributes, 0,
+                   req->device_object );
+}
+
+DECL_HANDLER(delete_device)
+{
+    struct ob_device *obj;
+    int found = 0;
+
+    LIST_FOR_EACH_ENTRY( obj, &devices_list, struct ob_device, entry )
+    {
+        if (obj->device_object == req->device_object)
+        {
+            found = 1;
+            break;
+        }
+    }
+
+    if (found)
+        delete_generic_obj( (struct generic_obj*)obj );
+    else
+        set_error( STATUS_DEVICE_DOES_NOT_EXIST );
+}


More information about the wine-patches mailing list