Commit babfa794 authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

Move named pipe objects into directory name space.

Change tests accordingly. Add small test for WaitNamedPipe.
parent 3764da68
......@@ -1340,7 +1340,8 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
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;
......
......@@ -91,8 +91,10 @@ static void test_CreateNamedPipe(int pipemode)
/* 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) {
......
......@@ -151,11 +151,6 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
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 handle, ACCESS_MASK access, POBJECT_ATTRIB
{
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,12 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
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 +1959,7 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
{
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 +1969,8 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
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;
}
......
......@@ -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);
......
......@@ -2378,6 +2378,7 @@ struct create_named_pipe_request
struct request_header __header;
unsigned int access;
unsigned int attributes;
obj_handle_t rootdir;
unsigned int options;
unsigned int flags;
unsigned int maxinstances;
......@@ -2404,6 +2405,7 @@ struct open_named_pipe_request
struct request_header __header;
unsigned int access;
unsigned int attributes;
obj_handle_t rootdir;
unsigned int flags;
/* VARARG(name,unicode_str); */
};
......@@ -4312,6 +4314,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply;
};
#define SERVER_PROTOCOL_VERSION 205
#define SERVER_PROTOCOL_VERSION 206
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -283,8 +283,9 @@ void *open_object_dir( struct directory *root, const struct unicode_str *name,
/* Global initialization */
static struct directory *dir_driver, *dir_device;
static struct directory *dir_driver;
static struct symlink *link_dosdev, *link_global1, *link_global2, *link_local;
static struct named_pipe_device *dev_named_pipe;
void init_directories(void)
{
......@@ -306,7 +307,7 @@ void init_directories(void)
static const struct unicode_str link_global_str = {link_globalW, sizeof(link_globalW)};
static const struct unicode_str link_local_str = {link_localW, sizeof(link_localW)};
struct directory *dir_global, *dir_basenamed;
struct directory *dir_global, *dir_basenamed, *dir_device;
root_directory = create_directory( NULL, NULL, 0, HASH_SIZE );
dir_driver = create_directory( root_directory, &dir_driver_str, 0, HASH_SIZE );
......@@ -322,20 +323,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 );
}
......
......@@ -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_fd_ops =
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,58 @@ static void pipe_client_destroy( struct object *obj)
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->len) return NULL;
if ((found = find_object( device->pipes, name, attr | OBJ_CASE_INSENSITIVE )))
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 +523,43 @@ static int pipe_client_get_info( struct fd *fd )
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;
pipe = create_named_object( sync_namespace, &named_pipe_ops, name, attr | OBJ_OPENIF );
if (pipe)
if (!name || !name->len) return alloc_object( &named_pipe_ops );
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 +636,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 +696,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 = open_object_dir( 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 +803,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;
......
......@@ -197,6 +197,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 */
......
......@@ -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
......
......@@ -2154,6 +2154,7 @@ static void dump_create_named_pipe_request( const struct create_named_pipe_reque
{
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " attributes=%08x,", req->attributes );
fprintf( stderr, " rootdir=%p,", req->rootdir );
fprintf( stderr, " options=%08x,", req->options );
fprintf( stderr, " flags=%08x,", req->flags );
fprintf( stderr, " maxinstances=%08x,", req->maxinstances );
......@@ -2173,6 +2174,7 @@ static void dump_open_named_pipe_request( const struct open_named_pipe_request *
{
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " attributes=%08x,", req->attributes );
fprintf( stderr, " rootdir=%p,", req->rootdir );
fprintf( stderr, " flags=%08x,", req->flags );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( cur_size );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment