mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-01 15:53:37 +00:00
Move named pipe objects into directory name space.
Change tests accordingly. Add small test for WaitNamedPipe.
This commit is contained in:
parent
3764da68de
commit
babfa79436
|
@ -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 )
|
||||
{
|
||||
struct named_pipe *pipe;
|
||||
|
||||
pipe = create_named_object( sync_namespace, &named_pipe_ops, name, attr | OBJ_OPENIF );
|
||||
if (pipe)
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
return pipe;
|
||||
}
|
||||
|
||||
static struct named_pipe *open_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 object *obj;
|
||||
struct named_pipe *pipe = NULL;
|
||||
struct unicode_str new_name;
|
||||
|
||||
if ((obj = find_object( sync_namespace, name, attr )))
|
||||
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 (obj->ops == &named_pipe_ops) return (struct named_pipe *)obj;
|
||||
release_object( obj );
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
if (attr & OBJ_OPENIF && obj->ops == &named_pipe_ops)
|
||||
set_error( STATUS_OBJECT_NAME_EXISTS );
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
else set_error( STATUS_OBJECT_NAME_NOT_FOUND );
|
||||
|
||||
return NULL;
|
||||
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();
|
||||
}
|
||||
|
||||
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 );
|
||||
|
|
Loading…
Reference in a new issue