Move named pipe objects into directory name space.
Vitaliy Margolen
wine-patch at kievinfo.com
Fri Dec 2 12:12:01 CST 2005
ChangeLog:
Move named pipe objects into directory name space.
Change tests accordingly.
Add small test for WaitNamedPipe.
dlls/kernel/sync.c | 3 +
dlls/kernel/tests/pipe.c | 4 +
dlls/ntdll/file.c | 20 +++---
dlls/ntdll/tests/om.c | 4 +
server/directory.c | 35 ++++++++---
server/named_pipe.c | 153 +++++++++++++++++++++++++++++++++++++++-------
server/object.h | 4 +
server/protocol.def | 2 +
8 files changed, 180 insertions(+), 45 deletions(-)
-------------- next part --------------
ec40e86b762abd98131fd8cae4a4d7ad9604bf0f
diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index 762cf2f..64e6bbc 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -1340,7 +1340,8 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name
req->timeout = nTimeOut;
req->overlapped = &ov;
req->func = PIPE_CompletionWait;
- wine_server_add_data( req, nt_name.Buffer + 4, nt_name.Length - 4*sizeof(WCHAR) );
+ wine_server_add_data( req, nt_name.Buffer + sizeof(leadin)/sizeof(WCHAR),
+ nt_name.Length - sizeof(leadin) );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
diff --git a/dlls/kernel/tests/pipe.c b/dlls/kernel/tests/pipe.c
index aaad8d6..a4c15fe 100644
--- a/dlls/kernel/tests/pipe.c
+++ b/dlls/kernel/tests/pipe.c
@@ -91,8 +91,10 @@ static void test_CreateNamedPipe(int pip
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+ todo_wine ok(WaitNamedPipeA(PIPENAME, 2000), "WaitNamedPipe failed (%08lx)\n", GetLastError());
+
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
- ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
+ ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%08lx)\n", GetLastError());
/* don't try to do i/o if one side couldn't be opened, as it hangs */
if (hFile != INVALID_HANDLE_VALUE) {
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index c52e16b..6b6df2c 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -151,11 +151,6 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE ha
if (!attr || !attr->ObjectName) return STATUS_INVALID_PARAMETER;
- if (attr->RootDirectory)
- {
- FIXME( "RootDirectory %p not supported\n", attr->RootDirectory );
- return STATUS_OBJECT_NAME_NOT_FOUND;
- }
if (alloc_size) FIXME( "alloc_size not supported\n" );
/* check for named pipe */
@@ -167,9 +162,10 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE ha
{
req->access = access;
req->attributes = (attr) ? attr->Attributes : 0;
+ req->rootdir = attr ? attr->RootDirectory : 0;
req->flags = options;
- wine_server_add_data( req, attr->ObjectName->Buffer + 4,
- attr->ObjectName->Length - 4*sizeof(WCHAR) );
+ wine_server_add_data( req, attr->ObjectName->Buffer,
+ attr->ObjectName->Length );
io->u.Status = wine_server_call( req );
*handle = reply->handle;
}
@@ -177,6 +173,11 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE ha
return io->u.Status;
}
+ if (attr->RootDirectory)
+ {
+ FIXME( "RootDirectory %p not supported\n", attr->RootDirectory );
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
/* check for mailslot */
if (attr->ObjectName->Length > sizeof(mailslotW) &&
@@ -1957,6 +1958,7 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( P
{
req->access = access;
req->attributes = (attr) ? attr->Attributes : 0;
+ req->rootdir = attr ? attr->RootDirectory : 0;
req->options = options;
req->flags =
(pipe_type) ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0 |
@@ -1966,8 +1968,8 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( P
req->outsize = outbound_quota;
req->insize = inbound_quota;
req->timeout = timeout->QuadPart / -10000;
- wine_server_add_data( req, attr->ObjectName->Buffer + 4,
- attr->ObjectName->Length - 4 * sizeof(WCHAR) );
+ wine_server_add_data( req, attr->ObjectName->Buffer,
+ attr->ObjectName->Length );
status = wine_server_call( req );
if (!status) *handle = reply->handle;
}
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index 492033d..96a68a5 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -126,7 +126,7 @@ void test_namespace_pipe(void)
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
status = pNtCreateNamedPipeFile(&pipe, GENERIC_READ|GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_CREATE, FILE_PIPE_FULL_DUPLEX, FALSE, FALSE, FALSE, 1, 256, 256, &timeout);
- todo_wine ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
+ ok(status == STATUS_INSTANCE_NOT_AVAILABLE,
"NtCreateNamedPipeFile should have failed with STATUS_INSTANCE_NOT_AVAILABLE got(%08lx)\n", status);
attr.Attributes = OBJ_CASE_INSENSITIVE;
@@ -137,7 +137,7 @@ void test_namespace_pipe(void)
pRtlInitUnicodeString(&str, buffer3);
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
status = pNtOpenFile(&h, GENERIC_READ, &attr, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN);
- todo_wine ok(status == STATUS_OBJECT_PATH_NOT_FOUND || status == STATUS_PIPE_NOT_AVAILABLE,
+ ok(status == STATUS_OBJECT_PATH_NOT_FOUND || status == STATUS_PIPE_NOT_AVAILABLE,
"pNtOpenFile should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08lx)\n", status);
pRtlInitUnicodeString(&str, buffer4);
diff --git a/server/directory.c b/server/directory.c
index 052de10..e7c392e 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -259,12 +259,9 @@ void *create_named_object_dir( struct di
return new_obj;
}
-/* open a new handle to an existing object */
-obj_handle_t open_object_dir( struct directory *root, const struct unicode_str *name,
- unsigned int attr, const struct object_ops *ops,
- unsigned int access )
+struct object *reference_by_name( struct directory *root, const struct unicode_str *name,
+ unsigned int attr, const struct object_ops *ops )
{
- obj_handle_t handle = 0;
struct unicode_str name_left;
struct object *obj;
@@ -275,10 +272,26 @@ obj_handle_t open_object_dir( struct dir
else if (ops && obj->ops != ops)
set_error( STATUS_OBJECT_TYPE_MISMATCH );
else
- handle = alloc_handle( current->process, obj, access, attr & OBJ_INHERIT );
+ return obj;
release_object( obj );
}
+ return NULL;
+}
+
+/* open a new handle to an existing object */
+obj_handle_t open_object_dir( struct directory *root, const struct unicode_str *name,
+ unsigned int attr, const struct object_ops *ops,
+ unsigned int access )
+{
+ obj_handle_t handle = 0;
+ struct object *obj;
+
+ if ((obj = reference_by_name( root, name, attr, ops )))
+ {
+ handle = alloc_handle( current->process, obj, access, attr & OBJ_INHERIT );
+ release_object( obj );
+ }
return handle;
}
@@ -287,6 +300,7 @@ obj_handle_t open_object_dir( struct dir
static struct directory *dir_driver, *dir_device;
static struct symlink *link_dosdev, *link_global1, *link_global2, *link_local;
+static struct named_pipe_device *dev_named_pipe;
void init_directories(void)
{
@@ -324,20 +338,25 @@ void init_directories(void)
link_global2 = create_symlink( dir_basenamed, &link_global_str, 0, &dir_basenamed_str );
link_local = create_symlink( dir_basenamed, &link_local_str, 0, &dir_basenamed_str );
- /* the symlinks hold references so we can release these */
+ /* devices */
+ dev_named_pipe = create_named_pipe_device();
+
+ /* the symlinks or devices hold references so we can release these */
+ release_object( dir_device );
release_object( dir_global );
release_object( dir_basenamed );
}
void close_directories(void)
{
+ release_object( dev_named_pipe );
+
release_object( link_dosdev );
release_object( link_global1 );
release_object( link_global2 );
release_object( link_local );
release_object( dir_driver );
- release_object( dir_device );
release_object( root_directory );
}
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 0aa5733..7ac67e6 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -99,6 +99,12 @@ struct named_pipe
struct list waiters; /* list of clients waiting to connect */
};
+struct named_pipe_device
+{
+ struct object obj; /* object header */
+ struct namespace *pipes; /* named pipe namespace */
+};
+
static void named_pipe_dump( struct object *obj, int verbose );
static void named_pipe_destroy( struct object *obj );
@@ -181,6 +187,26 @@ static const struct fd_ops pipe_client_f
default_fd_cancel_async /* cancel_async */
};
+static void named_pipe_device_dump( struct object *obj, int verbose );
+static struct object *named_pipe_device_lookup_name( struct object *obj,
+ struct unicode_str *name, unsigned int attr );
+static void named_pipe_device_destroy( struct object *obj );
+
+static const struct object_ops named_pipe_device_ops =
+{
+ sizeof(struct named_pipe_device), /* size */
+ named_pipe_device_dump, /* dump */
+ no_add_queue, /* add_queue */
+ NULL, /* remove_queue */
+ NULL, /* signaled */
+ no_satisfied, /* satisfied */
+ no_signal, /* signal */
+ no_get_fd, /* get_fd */
+ named_pipe_device_lookup_name, /* lookup_name */
+ no_close_handle, /* close_handle */
+ named_pipe_device_destroy /* destroy */
+};
+
static void named_pipe_dump( struct object *obj, int verbose )
{
struct named_pipe *pipe = (struct named_pipe *) obj;
@@ -338,6 +364,60 @@ static void pipe_client_destroy( struct
assert( !client->fd );
}
+static void named_pipe_device_dump( struct object *obj, int verbose )
+{
+ assert( obj->ops == &named_pipe_device_ops );
+ fprintf( stderr, "Named pipe device\n" );
+}
+
+static struct object *named_pipe_device_lookup_name( struct object *obj,
+ struct unicode_str *name, unsigned int attr )
+{
+ struct named_pipe_device *device = (struct named_pipe_device*)obj;
+ struct object *found;
+
+ assert( obj->ops == &named_pipe_device_ops );
+ assert( device->pipes );
+
+ if (!name || !name->len) return NULL;
+
+ if ((found = find_object( device->pipes, name, attr | OBJ_CASE_INSENSITIVE )))
+ {
+ name->str = NULL;
+ name->len = 0;
+ }
+ return found;
+}
+
+static void named_pipe_device_destroy( struct object *obj )
+{
+ struct named_pipe_device *device = (struct named_pipe_device*)obj;
+ assert( obj->ops == &named_pipe_device_ops );
+ free( device->pipes );
+}
+
+/* this will be deleted as soon an we fix wait_named_pipe */
+static struct named_pipe_device *named_pipe_device;
+
+struct named_pipe_device *create_named_pipe_device( void )
+{
+ static const WCHAR pipeW[] = {'\\','?','?','\\','P','I','P','E'};
+ static struct unicode_str pipe = {pipeW, sizeof(pipeW)};
+ struct named_pipe_device *dev;
+
+ if ((dev = create_named_object_dir( NULL, &pipe, 0, &named_pipe_device_ops )) &&
+ get_error() != STATUS_OBJECT_NAME_EXISTS)
+ {
+ if (!(dev->pipes = create_namespace( 7 )))
+ {
+ release_object( dev );
+ dev = NULL;
+ }
+ }
+ named_pipe_device = dev;
+ return dev;
+}
+
static int pipe_data_remaining( struct pipe_server *server )
{
struct pollfd pfd;
@@ -445,37 +525,43 @@ static int pipe_client_get_info( struct
return flags;
}
-static struct named_pipe *create_named_pipe( const struct unicode_str *name, unsigned int attr )
+static struct named_pipe *create_named_pipe( struct directory *root,
+ const struct unicode_str *name, unsigned int attr )
{
- struct named_pipe *pipe;
+ struct object *obj;
+ struct named_pipe *pipe = NULL;
+ struct unicode_str new_name;
+
+ if (!name || !name->len) return alloc_object( &named_pipe_ops );
- pipe = create_named_object( sync_namespace, &named_pipe_ops, name, attr | OBJ_OPENIF );
- if (pipe)
+ if (!(obj = find_object_dir( root, name, attr, &new_name ))) return NULL;
+ if (!new_name.len)
{
- if (get_error() != STATUS_OBJECT_NAME_EXISTS)
+ if (attr & OBJ_OPENIF && obj->ops == &named_pipe_ops)
+ set_error( STATUS_OBJECT_NAME_EXISTS );
+ else
{
- /* initialize it if it didn't already exist */
- pipe->instances = 0;
- list_init( &pipe->servers );
- list_init( &pipe->waiters );
+ release_object( obj );
+ obj = NULL;
+ if (attr & OBJ_OPENIF)
+ set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ else
+ set_error( STATUS_OBJECT_NAME_COLLISION );
}
+ return (struct named_pipe *)obj;
}
- return pipe;
-}
-static struct named_pipe *open_named_pipe( const struct unicode_str *name, unsigned int attr )
-{
- struct object *obj;
-
- if ((obj = find_object( sync_namespace, name, attr )))
- {
- if (obj->ops == &named_pipe_ops) return (struct named_pipe *)obj;
- release_object( obj );
+ if (obj->ops != &named_pipe_device_ops)
set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ else
+ {
+ struct named_pipe_device *dev = (struct named_pipe_device *)obj;
+ if ((pipe = create_object( dev->pipes, &named_pipe_ops, &new_name, NULL )))
+ clear_error();
}
- else set_error( STATUS_OBJECT_NAME_NOT_FOUND );
- return NULL;
+ release_object( obj );
+ return pipe;
}
static struct pipe_server *get_pipe_server_obj( struct process *process,
@@ -552,13 +638,24 @@ DECL_HANDLER(create_named_pipe)
struct named_pipe *pipe;
struct pipe_server *server;
struct unicode_str name;
+ struct directory *root = NULL;
reply->handle = 0;
get_req_unicode_str( &name );
- if (!(pipe = create_named_pipe( &name, req->attributes ))) return;
+ if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+ return;
+
+ pipe = create_named_pipe( root, &name, req->attributes | OBJ_OPENIF );
+
+ if (root) release_object( root );
+ if (!pipe) return;
if (get_error() != STATUS_OBJECT_NAME_EXISTS)
{
+ /* initialize it if it didn't already exist */
+ pipe->instances = 0;
+ list_init( &pipe->servers );
+ list_init( &pipe->waiters );
pipe->insize = req->insize;
pipe->outsize = req->outsize;
pipe->maxinstances = req->maxinstances;
@@ -601,11 +698,18 @@ DECL_HANDLER(open_named_pipe)
struct pipe_server *server;
struct pipe_client *client;
struct unicode_str name;
+ struct directory *root = NULL;
struct named_pipe *pipe;
int fds[2];
get_req_unicode_str( &name );
- if (!(pipe = open_named_pipe( &name, req->attributes ))) return;
+ if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+ return;
+
+ pipe = (struct named_pipe *)reference_by_name( root, &name, req->attributes, &named_pipe_ops );
+
+ if (root) release_object( root );
+ if (!pipe) return;
server = find_server2( pipe, ps_idle_server, ps_wait_open );
release_object( pipe );
@@ -701,7 +805,8 @@ DECL_HANDLER(wait_named_pipe)
struct unicode_str name;
get_req_unicode_str( &name );
- if (!(pipe = open_named_pipe( &name, OBJ_CASE_INSENSITIVE )))
+ pipe = (struct named_pipe *)find_object( named_pipe_device->pipes, &name, OBJ_CASE_INSENSITIVE );
+ if (!pipe)
{
set_error( STATUS_PIPE_NOT_AVAILABLE );
return;
diff --git a/server/object.h b/server/object.h
index d138729..ade820e 100644
--- a/server/object.h
+++ b/server/object.h
@@ -190,6 +190,8 @@ extern void *create_named_object_dir( st
extern obj_handle_t open_object_dir( struct directory *root, const struct unicode_str *name,
unsigned int attr, const struct object_ops *ops,
unsigned int access );
+extern struct object *reference_by_name( struct directory *root, const struct unicode_str *name,
+ unsigned int attr, const struct object_ops *ops );
extern void init_directories(void);
extern void close_directories(void);
@@ -198,6 +200,8 @@ extern void close_directories(void);
extern struct symlink *create_symlink( struct directory *root, const struct unicode_str *name,
unsigned int attr, const struct unicode_str *target );
+/* devices */
+extern struct named_pipe_device *create_named_pipe_device( void );
/* global variables */
diff --git a/server/protocol.def b/server/protocol.def
index 297313c..905e0ff 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1692,6 +1692,7 @@ enum message_type
@REQ(create_named_pipe)
unsigned int access;
unsigned int attributes; /* object attributes */
+ obj_handle_t rootdir; /* root directory */
unsigned int options;
unsigned int flags;
unsigned int maxinstances;
@@ -1713,6 +1714,7 @@ enum message_type
@REQ(open_named_pipe)
unsigned int access;
unsigned int attributes; /* object attributes */
+ obj_handle_t rootdir; /* root directory */
unsigned int flags; /* file flags */
VARARG(name,unicode_str); /* pipe name */
@REPLY
More information about the wine-patches
mailing list