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