mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Replace SetNamedPipeHandleState patch with proper implementation.
This commit is contained in:
parent
183dabb19e
commit
13f3004ee7
@ -60,6 +60,7 @@ Included bugfixes and improvements
|
||||
* Support for NtSetInformationFile class FileDispositionInformation ([Wine Bug #30397](http://bugs.winehq.org/show_bug.cgi?id=30397 "Multiple applications need support for NtSetInformationFile class FileDispositionInformation (Cygwin installer, Stylizer 5.x Visual CSS editor, Spoon Studio 2011 (ex Xenocode) application sandboxing scheme)"))
|
||||
* Support for PulseAudio backend for audio ([Wine Bug #10495](http://bugs.winehq.org/show_bug.cgi?id=10495 "Wine should support PulseAudio"))
|
||||
* Support for SHCreateSessionKey ([Wine Bug #35630](http://bugs.winehq.org/show_bug.cgi?id=35630 "SHCreateSessionKey is unimplemented"))
|
||||
* Support for SetNamedPipeHandleState ([Wine Bug #17273](http://bugs.winehq.org/show_bug.cgi?id=17273 "Many apps and games need SetNamedPipeHandleState implementation (support for named pipe message mode)(FireFox+Flash, Win8/NET 4.x SDK/vcrun2012, WiX installers)"))
|
||||
* Support for TOOLTIPS_GetTipText edge cases ([Wine Bug #30648](http://bugs.winehq.org/show_bug.cgi?id=30648 "SEGA Genesis / Mega Drive Classic Collection (Steam) crashes on startup"))
|
||||
* Support for TransmitFile ([Wine Bug #5048](http://bugs.winehq.org/show_bug.cgi?id=5048 "Multiple applications and games need support for ws2_32 SIO_GET_EXTENSION_FUNCTION_POINTER TransmitFile (WSAID_TRANSMITFILE)"))
|
||||
* Support for WTSEnumerateProcessesW ([Wine Bug #29903](http://bugs.winehq.org/show_bug.cgi?id=29903 "Some Microsoft debuggers fail to enumerate processes due to wtsapi32.WTSEnumerateProcessesW() being a stub (Microsoft Visual Studio 2005, DbgCLR from .NET 2.0 SDK)"))
|
||||
@ -71,7 +72,6 @@ Included bugfixes and improvements
|
||||
* Support for stored file ACLs ([Wine Bug #31858](http://bugs.winehq.org/show_bug.cgi?id=31858 "Netflix on Firefox fails with Internet Connection Problem when loading bar is at 99%"))
|
||||
* Support for ws2_32.inet_pton ([Wine Bug #36713](http://bugs.winehq.org/show_bug.cgi?id=36713 "Watch_Dogs requires ws2_32.inet_pton"))
|
||||
* Use manual relay for RunDLL_CallEntry16 in shell32 ([Wine Bug #23033](http://bugs.winehq.org/show_bug.cgi?id=23033 "Tages Protection v5.x: games report \"DLL not found shell.dll16.dll\" (Runaway 2: The Dream Of The Turtle, ...)"))
|
||||
* Workaround for TransactNamedPipe not being supported ([Wine Bug #17273](http://bugs.winehq.org/show_bug.cgi?id=17273 "Many apps and games need SetNamedPipeHandleState implementation (support for named pipe message mode)(FireFox+Flash, Win8/NET 4.x SDK/vcrun2012, WiX installers)"))
|
||||
* Workaround for shlwapi URLs with relative paths
|
||||
* XEMBED support for embedding Wine windows inside Linux applications
|
||||
|
||||
|
@ -328,21 +328,29 @@ kernel32-GetVolumePathName.ok:
|
||||
# Patchset kernel32-Named_Pipe
|
||||
# |
|
||||
# | Included patches:
|
||||
# | * Support for NamedPipe operations. [rev 2, by Sebastian Lackner / Dan Kegel]
|
||||
# | * Fix for ConnectNamedPort return value in overlapped mode. [by Dan Kegel]
|
||||
# | * Add proper implementation for SetNamedPipeHandleState. [rev 7, by Sebastian Lackner / Adam Martinson]
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#16550] Fix for ConnectNamedPort return value in overlapped mode
|
||||
# | * [#17273] Workaround for TransactNamedPipe not being supported
|
||||
# | * [#17273] Support for SetNamedPipeHandleState
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/kernel32/sync.c
|
||||
# | * dlls/kernel32/sync.c, dlls/kernel32/tests/pipe.c, dlls/ntdll/file.c, dlls/ntdll/tests/pipe.c, include/winternl.h,
|
||||
# | server/named_pipe.c, server/protocol.def
|
||||
# |
|
||||
.INTERMEDIATE: kernel32-Named_Pipe.ok
|
||||
kernel32-Named_Pipe.ok:
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0001-kernel32-Change-return-value-of-stub-SetNamedPipeHandl.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0002-kernel32-ConnectNamedPort-should-return-FALSE-and-se.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0001-kernel32-ConnectNamedPort-should-return-FALSE-and-se.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0002-ntdll-Implement-FILE_PIPE_INFORMATION-for-NtQueryInf.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0003-server-Store-pipe_flags-in-a-separate-variable-for-b.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0004-server-Implement-set_named_pipe_info-wineserver-call.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0005-ntdll-tests-Add-tests-for-FILE_PIPE_INFORMATION.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0006-kernel32-tests-Always-allow-only-one-specific-test-r.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0007-kernel32-Implement-Get-Set-NamedPipeHandleState.patch)
|
||||
@( \
|
||||
echo '+ { "kernel32-Named_Pipe", "Sebastian Lackner / Dan Kegel", "Support for NamedPipe operations. [rev 2]" },'; \
|
||||
echo '+ { "kernel32-Named_Pipe", "Dan Kegel", "Fix for ConnectNamedPort return value in overlapped mode." },'; \
|
||||
echo '+ { "kernel32-Named_Pipe", "Sebastian Lackner / Adam Martinson", "Add proper implementation for SetNamedPipeHandleState. [rev 7]" },'; \
|
||||
) > kernel32-Named_Pipe.ok
|
||||
|
||||
# Patchset kernel32-SystemFileCacheSize
|
||||
|
@ -1,44 +0,0 @@
|
||||
From 852f784dd4dd407d1183c01ce43c1a8e07231275 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 26 Oct 2013 19:39:33 +0200
|
||||
Subject: kernel32: Change return value of stub SetNamedPipeHandleState to
|
||||
TRUE
|
||||
|
||||
---
|
||||
dlls/kernel32/sync.c | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
|
||||
index 5b7f810..331188f 100644
|
||||
--- a/dlls/kernel32/sync.c
|
||||
+++ b/dlls/kernel32/sync.c
|
||||
@@ -1730,7 +1730,8 @@ BOOL WINAPI SetNamedPipeHandleState(
|
||||
* runtime, and it slows down InstallShield a fair bit. */
|
||||
WARN("stub: %p %p/%d %p %p\n",
|
||||
hNamedPipe, lpMode, lpMode ? *lpMode : 0, lpMaxCollectionCount, lpCollectDataTimeout);
|
||||
- return FALSE;
|
||||
+ /* some programs expect this to return TRUE, and will abort otherwise */
|
||||
+ return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -1793,14 +1794,12 @@ BOOL WINAPI CallNamedPipeW(
|
||||
mode = PIPE_READMODE_MESSAGE;
|
||||
ret = SetNamedPipeHandleState(pipe, &mode, NULL, NULL);
|
||||
|
||||
- /* Currently SetNamedPipeHandleState() is a stub returning FALSE */
|
||||
- if (ret) FIXME("Now that SetNamedPipeHandleState() is more than a stub, please update CallNamedPipeW\n");
|
||||
- /*
|
||||
+ /* Currently SetNamedPipeHandleState() is a stub returning TRUE */
|
||||
if (!ret)
|
||||
{
|
||||
CloseHandle(pipe);
|
||||
return FALSE;
|
||||
- }*/
|
||||
+ }
|
||||
|
||||
ret = TransactNamedPipe(pipe, lpInput, lpInputSize, lpOutput, lpOutputSize, lpBytesRead, NULL);
|
||||
CloseHandle(pipe);
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 873c6600c711af413a0f2b8e71ebf74e3638f474 Mon Sep 17 00:00:00 2001
|
||||
From 68eb737ebb05ea27d51588c2f5c8fa5d6dce7cff Mon Sep 17 00:00:00 2001
|
||||
From: Dan Kegel <dank@kegel.com>
|
||||
Date: Sat, 26 Jul 2014 14:07:55 -0600
|
||||
Subject: kernel32: ConnectNamedPort should return FALSE and set
|
||||
@ -9,7 +9,7 @@ Subject: kernel32: ConnectNamedPort should return FALSE and set
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
|
||||
index a274fd3..cf84269 100644
|
||||
index 8210624..ff0e234 100644
|
||||
--- a/dlls/kernel32/sync.c
|
||||
+++ b/dlls/kernel32/sync.c
|
||||
@@ -1609,6 +1609,7 @@ BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
@ -0,0 +1,98 @@
|
||||
From a621406ad321dc6871fbaf7c43d70fa6da9df07a Mon Sep 17 00:00:00 2001
|
||||
From: Adam Martinson <adam.r.martinson@gmail.com>
|
||||
Date: Tue, 12 Aug 2014 21:29:47 +0200
|
||||
Subject: ntdll: Implement FILE_PIPE_INFORMATION for NtQueryInformationFile.
|
||||
|
||||
This is a subset of my current work-in-progress named pipe message mode
|
||||
patches, see: http://bugs.winehq.org/show_bug.cgi?id=17195#c157
|
||||
|
||||
Please note that none of the patches in this series focuses on a specific
|
||||
implementation of message mode pipes yet - whatever finally is used, we
|
||||
always need the redirection kernel32 -> ntdll -> wineserver.
|
||||
|
||||
This first patch (by Adam Martinson) implements FILE_PIPE_INFORMATION
|
||||
based on the existing get_named_pipe_info wineserver call.
|
||||
---
|
||||
dlls/ntdll/file.c | 22 ++++++++++++++++++++--
|
||||
include/winternl.h | 11 +++++++++++
|
||||
2 files changed, 31 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index d2efcc1..2ae8bee 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -1981,7 +1981,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
sizeof(FILE_END_OF_FILE_INFORMATION), /* FileEndOfFileInformation */
|
||||
0, /* FileAlternateNameInformation */
|
||||
sizeof(FILE_STREAM_INFORMATION)-sizeof(WCHAR), /* FileStreamInformation */
|
||||
- 0, /* FilePipeInformation */
|
||||
+ sizeof(FILE_PIPE_INFORMATION), /* FilePipeInformation */
|
||||
sizeof(FILE_PIPE_LOCAL_INFORMATION), /* FilePipeLocalInformation */
|
||||
0, /* FilePipeRemoteInformation */
|
||||
sizeof(FILE_MAILSLOT_QUERY_INFORMATION), /* FileMailslotQueryInformation */
|
||||
@@ -2032,7 +2032,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
if (len < info_sizes[class])
|
||||
return io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
- if (class != FilePipeLocalInformation)
|
||||
+ if (class != FilePipeInformation && class != FilePipeLocalInformation)
|
||||
{
|
||||
if ((io->u.Status = server_get_unix_fd( hFile, 0, &fd, &needs_close, NULL, NULL )))
|
||||
return io->u.Status;
|
||||
@@ -2146,6 +2146,24 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
}
|
||||
}
|
||||
break;
|
||||
+ case FilePipeInformation:
|
||||
+ {
|
||||
+ FILE_PIPE_INFORMATION* pi = ptr;
|
||||
+
|
||||
+ SERVER_START_REQ( get_named_pipe_info )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( hFile );
|
||||
+ if (!(io->u.Status = wine_server_call( req )))
|
||||
+ {
|
||||
+ pi->ReadMode = (reply->flags & NAMED_PIPE_MESSAGE_STREAM_READ) ?
|
||||
+ FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
|
||||
+ pi->CompletionMode = (reply->flags & NAMED_PIPE_NONBLOCKING_MODE) ?
|
||||
+ FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
|
||||
+ }
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ }
|
||||
+ break;
|
||||
case FilePipeLocalInformation:
|
||||
{
|
||||
FILE_PIPE_LOCAL_INFORMATION* pli = ptr;
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index a95a016..95951e2 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -623,6 +623,11 @@ typedef struct _FILE_MAILSLOT_SET_INFORMATION {
|
||||
LARGE_INTEGER ReadTimeout;
|
||||
} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION;
|
||||
|
||||
+typedef struct _FILE_PIPE_INFORMATION {
|
||||
+ ULONG ReadMode;
|
||||
+ ULONG CompletionMode;
|
||||
+} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION;
|
||||
+
|
||||
typedef struct _FILE_PIPE_LOCAL_INFORMATION {
|
||||
ULONG NamedPipeType;
|
||||
ULONG NamedPipeConfiguration;
|
||||
@@ -1602,6 +1607,12 @@ typedef struct _RTL_HANDLE_TABLE
|
||||
/* options for pipe's type */
|
||||
#define FILE_PIPE_TYPE_MESSAGE 0x00000001
|
||||
#define FILE_PIPE_TYPE_BYTE 0x00000000
|
||||
+/* options for pipe's message mode */
|
||||
+#define FILE_PIPE_MESSAGE_MODE 0x00000001
|
||||
+#define FILE_PIPE_BYTE_STREAM_MODE 0x00000000
|
||||
+/* options for pipe's blocking mode */
|
||||
+#define FILE_PIPE_COMPLETE_OPERATION 0x00000001
|
||||
+#define FILE_PIPE_QUEUE_OPERATION 0x00000000
|
||||
/* and client / server end */
|
||||
#define FILE_PIPE_SERVER_END 0x00000001
|
||||
#define FILE_PIPE_CLIENT_END 0x00000000
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,112 @@
|
||||
From 0826b4c53e337639519e8aabe7a6a57f67d6dd0c Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Tue, 12 Aug 2014 21:29:59 +0200
|
||||
Subject: server: Store pipe_flags in a separate variable for both server and
|
||||
client of named pipes.
|
||||
|
||||
One global "flags" member for a pipe is not sufficient to store different values
|
||||
for each opened server/connection. This patch adds an additional pipe_flags member
|
||||
to both the server and client.
|
||||
|
||||
pipe->flags contain attributes which are valid for all servers/client - the
|
||||
server->pipe_flags and client->pipe_flags values are separate for each connection.
|
||||
|
||||
When requesting get_named_pipe_info then return the information for the specific
|
||||
instance, instead of the global information.
|
||||
---
|
||||
server/named_pipe.c | 16 ++++++++++------
|
||||
1 file changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/server/named_pipe.c b/server/named_pipe.c
|
||||
index 4b23ba2..59fb0ab 100644
|
||||
--- a/server/named_pipe.c
|
||||
+++ b/server/named_pipe.c
|
||||
@@ -77,6 +77,7 @@ struct pipe_server
|
||||
struct timeout_user *flush_poll;
|
||||
struct event *event;
|
||||
unsigned int options; /* pipe options */
|
||||
+ unsigned int pipe_flags;
|
||||
};
|
||||
|
||||
struct pipe_client
|
||||
@@ -85,6 +86,7 @@ struct pipe_client
|
||||
struct fd *fd; /* pipe file descriptor */
|
||||
struct pipe_server *server; /* server that this client is connected to */
|
||||
unsigned int flags; /* file flags */
|
||||
+ unsigned int pipe_flags;
|
||||
};
|
||||
|
||||
struct named_pipe
|
||||
@@ -737,7 +739,7 @@ static struct pipe_server *get_pipe_server_obj( struct process *process,
|
||||
return (struct pipe_server *) obj;
|
||||
}
|
||||
|
||||
-static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned int options )
|
||||
+static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned int options, int pipe_flags )
|
||||
{
|
||||
struct pipe_server *server;
|
||||
|
||||
@@ -750,6 +752,7 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned
|
||||
server->client = NULL;
|
||||
server->flush_poll = NULL;
|
||||
server->options = options;
|
||||
+ server->pipe_flags = pipe_flags;
|
||||
|
||||
list_add_head( &pipe->servers, &server->entry );
|
||||
grab_object( pipe );
|
||||
@@ -762,7 +765,7 @@ static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned
|
||||
return server;
|
||||
}
|
||||
|
||||
-static struct pipe_client *create_pipe_client( unsigned int flags )
|
||||
+static struct pipe_client *create_pipe_client( unsigned int flags, int pipe_flags )
|
||||
{
|
||||
struct pipe_client *client;
|
||||
|
||||
@@ -773,6 +776,7 @@ static struct pipe_client *create_pipe_client( unsigned int flags )
|
||||
client->fd = NULL;
|
||||
client->server = NULL;
|
||||
client->flags = flags;
|
||||
+ client->pipe_flags = pipe_flags;
|
||||
|
||||
return client;
|
||||
}
|
||||
@@ -822,7 +826,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if ((client = create_pipe_client( options )))
|
||||
+ if ((client = create_pipe_client( options, pipe->flags )))
|
||||
{
|
||||
if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds ))
|
||||
{
|
||||
@@ -977,7 +981,7 @@ DECL_HANDLER(create_named_pipe)
|
||||
pipe->outsize = req->outsize;
|
||||
pipe->maxinstances = req->maxinstances;
|
||||
pipe->timeout = req->timeout;
|
||||
- pipe->flags = req->flags;
|
||||
+ pipe->flags = req->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE;
|
||||
pipe->sharing = req->sharing;
|
||||
}
|
||||
else
|
||||
@@ -997,7 +1001,7 @@ DECL_HANDLER(create_named_pipe)
|
||||
clear_error(); /* clear the name collision */
|
||||
}
|
||||
|
||||
- server = create_pipe_server( pipe, req->options );
|
||||
+ server = create_pipe_server( pipe, req->options, req->flags );
|
||||
if (server)
|
||||
{
|
||||
reply->handle = alloc_handle( current->process, server, req->access, req->attributes );
|
||||
@@ -1026,7 +1030,7 @@ DECL_HANDLER(get_named_pipe_info)
|
||||
server = client->server;
|
||||
}
|
||||
|
||||
- reply->flags = server->pipe->flags;
|
||||
+ reply->flags = client ? client->pipe_flags : server->pipe_flags;
|
||||
reply->sharing = server->pipe->sharing;
|
||||
reply->maxinstances = server->pipe->maxinstances;
|
||||
reply->instances = server->pipe->instances;
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,130 @@
|
||||
From cf370c3fae81841e2b2984ddc3ea313607a3a824 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Tue, 12 Aug 2014 21:30:34 +0200
|
||||
Subject: server: Implement set_named_pipe_info wineserver call for
|
||||
NtSetInformationFile/FilePipeInformation.
|
||||
|
||||
Based on patch by Adam Martinson.
|
||||
|
||||
This patch adds a new wineserver call set_named_pipe_info to change the properties
|
||||
stored in server->pipe_flags or client->pipe_flags. This request is then used to
|
||||
implement NtSetInformationFile(FilePipeInformation, ...)
|
||||
|
||||
Invalid combinations (like requesting read message mode when using a byte mode pipe)
|
||||
are rejected with STATUS_INVALID_PARAMETER.
|
||||
|
||||
Requires ./tools/make_requests
|
||||
---
|
||||
dlls/ntdll/file.c | 23 +++++++++++++++++++++++
|
||||
server/named_pipe.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
server/protocol.def | 7 ++++++-
|
||||
3 files changed, 67 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 2ae8bee..92d9829 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -2335,6 +2335,29 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||
else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
break;
|
||||
|
||||
+ case FilePipeInformation:
|
||||
+ if (len >= sizeof(FILE_PIPE_INFORMATION))
|
||||
+ {
|
||||
+ FILE_PIPE_INFORMATION *info = ptr;
|
||||
+
|
||||
+ if ((info->CompletionMode | info->ReadMode) & ~1)
|
||||
+ {
|
||||
+ io->u.Status = STATUS_INVALID_PARAMETER;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ SERVER_START_REQ( set_named_pipe_info )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( handle );
|
||||
+ req->flags = (info->CompletionMode ? NAMED_PIPE_NONBLOCKING_MODE : 0) |
|
||||
+ (info->ReadMode ? NAMED_PIPE_MESSAGE_STREAM_READ : 0);
|
||||
+ io->u.Status = wine_server_call( req );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ }
|
||||
+ else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
+ break;
|
||||
+
|
||||
case FileMailslotSetInformation:
|
||||
{
|
||||
FILE_MAILSLOT_SET_INFORMATION *info = ptr;
|
||||
diff --git a/server/named_pipe.c b/server/named_pipe.c
|
||||
index 59fb0ab..0ec069d 100644
|
||||
--- a/server/named_pipe.c
|
||||
+++ b/server/named_pipe.c
|
||||
@@ -1045,3 +1045,41 @@ DECL_HANDLER(get_named_pipe_info)
|
||||
release_object(server);
|
||||
}
|
||||
}
|
||||
+
|
||||
+DECL_HANDLER(set_named_pipe_info)
|
||||
+{
|
||||
+ struct pipe_server *server;
|
||||
+ struct pipe_client *client = NULL;
|
||||
+
|
||||
+ server = get_pipe_server_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES );
|
||||
+ if (!server)
|
||||
+ {
|
||||
+ if (get_error() != STATUS_OBJECT_TYPE_MISMATCH)
|
||||
+ return;
|
||||
+
|
||||
+ clear_error();
|
||||
+ client = (struct pipe_client *)get_handle_obj( current->process, req->handle,
|
||||
+ 0, &pipe_client_ops );
|
||||
+ if (!client) return;
|
||||
+ server = client->server;
|
||||
+ }
|
||||
+
|
||||
+ if ((req->flags & ~(NAMED_PIPE_MESSAGE_STREAM_READ | NAMED_PIPE_NONBLOCKING_MODE)) ||
|
||||
+ ((req->flags & NAMED_PIPE_MESSAGE_STREAM_READ) && !(server->pipe->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)))
|
||||
+ {
|
||||
+ set_error( STATUS_INVALID_PARAMETER );
|
||||
+ }
|
||||
+ else if (client)
|
||||
+ {
|
||||
+ client->pipe_flags = server->pipe->flags | req->flags;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ server->pipe_flags = server->pipe->flags | req->flags;
|
||||
+ }
|
||||
+
|
||||
+ if (client)
|
||||
+ release_object(client);
|
||||
+ else
|
||||
+ release_object(server);
|
||||
+}
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index a8c1fb9..c9270ea 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -2294,7 +2294,7 @@ enum message_type
|
||||
#define NAMED_PIPE_NONBLOCKING_MODE 0x0004
|
||||
#define NAMED_PIPE_SERVER_END 0x8000
|
||||
|
||||
-
|
||||
+/* Get named pipe information by handle */
|
||||
@REQ(get_named_pipe_info)
|
||||
obj_handle_t handle;
|
||||
@REPLY
|
||||
@@ -2306,6 +2306,11 @@ enum message_type
|
||||
unsigned int insize;
|
||||
@END
|
||||
|
||||
+/* Set named pipe information by handle */
|
||||
+@REQ(set_named_pipe_info)
|
||||
+ obj_handle_t handle;
|
||||
+ unsigned int flags;
|
||||
+@END
|
||||
|
||||
/* Create a window */
|
||||
@REQ(create_window)
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,244 @@
|
||||
From f78c4bb06e2c463ea2e7a7cee374714814a5fdb1 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Tue, 12 Aug 2014 21:31:00 +0200
|
||||
Subject: ntdll/tests: Add tests for FILE_PIPE_INFORMATION.
|
||||
|
||||
Based on patch by Adam Martinson.
|
||||
|
||||
I've added more tests, and have marked failing tests as broken(...). On Windows 8
|
||||
we still get some failures, but as there is a lot more going wrong there, we probably shouldn't
|
||||
worry about that. ;)
|
||||
---
|
||||
dlls/ntdll/tests/pipe.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 188 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c
|
||||
index c275e3d..75faf76 100644
|
||||
--- a/dlls/ntdll/tests/pipe.c
|
||||
+++ b/dlls/ntdll/tests/pipe.c
|
||||
@@ -34,6 +34,11 @@
|
||||
#ifndef __WINE_WINTERNL_H
|
||||
|
||||
typedef struct {
|
||||
+ ULONG ReadMode;
|
||||
+ ULONG CompletionMode;
|
||||
+} FILE_PIPE_INFORMATION;
|
||||
+
|
||||
+typedef struct {
|
||||
ULONG NamedPipeType;
|
||||
ULONG NamedPipeConfiguration;
|
||||
ULONG MaximumInstances;
|
||||
@@ -68,6 +73,7 @@ static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access,
|
||||
ULONG inbound_quota, ULONG outbound_quota,
|
||||
PLARGE_INTEGER timeout);
|
||||
static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass);
|
||||
+static NTSTATUS (WINAPI *pNtSetInformationFile) (HANDLE handle, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class);
|
||||
static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status);
|
||||
static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source);
|
||||
|
||||
@@ -87,6 +93,7 @@ static BOOL init_func_ptrs(void)
|
||||
loadfunc(NtFsControlFile)
|
||||
loadfunc(NtCreateNamedPipeFile)
|
||||
loadfunc(NtQueryInformationFile)
|
||||
+ loadfunc(NtSetInformationFile)
|
||||
loadfunc(NtCancelIoFile)
|
||||
loadfunc(RtlInitUnicodeString)
|
||||
|
||||
@@ -479,6 +486,184 @@ static void test_cancelio(void)
|
||||
CloseHandle(hPipe);
|
||||
}
|
||||
|
||||
+#define check_pipe_handle_state(handle, r, c) \
|
||||
+ do \
|
||||
+ { \
|
||||
+ memset(&fpi, 0x55, sizeof(fpi)); \
|
||||
+ if (handle == INVALID_HANDLE_VALUE) break; \
|
||||
+ res = pNtQueryInformationFile(handle, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); \
|
||||
+ ok(!res, "NtQueryInformationFile returned %x\n", res); \
|
||||
+ ok(fpi.ReadMode == r, "ReadMode == %x\n", fpi.ReadMode); \
|
||||
+ ok(fpi.CompletionMode == c, "CompletionMode == %x\n", fpi.CompletionMode); \
|
||||
+ } \
|
||||
+ while (0)
|
||||
+
|
||||
+static void test_filepipeinfo(void)
|
||||
+{
|
||||
+ IO_STATUS_BLOCK iosb;
|
||||
+ OBJECT_ATTRIBUTES attr;
|
||||
+ UNICODE_STRING name;
|
||||
+ LARGE_INTEGER timeout;
|
||||
+ HANDLE hServer, hClient;
|
||||
+ FILE_PIPE_INFORMATION fpi;
|
||||
+ NTSTATUS res;
|
||||
+
|
||||
+ pRtlInitUnicodeString(&name, testpipe_nt);
|
||||
+
|
||||
+ attr.Length = sizeof(attr);
|
||||
+ attr.RootDirectory = 0;
|
||||
+ attr.ObjectName = &name;
|
||||
+ attr.Attributes = 0x40; /* case insensitive */
|
||||
+ attr.SecurityDescriptor = NULL;
|
||||
+ attr.SecurityQualityOfService = NULL;
|
||||
+
|
||||
+ timeout.QuadPart = -100000000000ll;
|
||||
+
|
||||
+ /* test with INVALID_HANDLE_VALUE */
|
||||
+ res = pNtQueryInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtQueryInformationFile returned %x\n", res);
|
||||
+
|
||||
+ fpi.ReadMode = 0;
|
||||
+ fpi.CompletionMode = 0;
|
||||
+ res = pNtSetInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ /* server end with read-only attributes */
|
||||
+ res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb,
|
||||
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */,
|
||||
+ 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout);
|
||||
+ ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+
|
||||
+ hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
|
||||
+ ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError: %x\n", GetLastError());
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+ check_pipe_handle_state(hClient, 0, 0);
|
||||
+
|
||||
+ fpi.ReadMode = 0;
|
||||
+ fpi.CompletionMode = 0;
|
||||
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+ check_pipe_handle_state(hClient, 0, 0);
|
||||
+
|
||||
+ fpi.ReadMode = 1; /* invalid on a byte stream pipe */
|
||||
+ fpi.CompletionMode = 1;
|
||||
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+ check_pipe_handle_state(hClient, 0, 0);
|
||||
+
|
||||
+ if (hClient != INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ fpi.ReadMode = 1; /* invalid on a byte stream pipe */
|
||||
+ fpi.CompletionMode = 1;
|
||||
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_INVALID_PARAMETER, "NtSetInformationFile returned %x\n", res);
|
||||
+ }
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+ check_pipe_handle_state(hClient, 0, 0);
|
||||
+
|
||||
+ if (hClient != INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ fpi.ReadMode = 0;
|
||||
+ fpi.CompletionMode = 1;
|
||||
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(!res, "NtSetInformationFile returned %x\n", res);
|
||||
+ }
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+ check_pipe_handle_state(hClient, 0, 1);
|
||||
+
|
||||
+ if (hClient != INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ fpi.ReadMode = 0;
|
||||
+ fpi.CompletionMode = 2; /* not in range 0-1 */
|
||||
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ fpi.ReadMode = 2; /* not in range 0-1 */
|
||||
+ fpi.CompletionMode = 0;
|
||||
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
|
||||
+ }
|
||||
+
|
||||
+ CloseHandle(hClient);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+
|
||||
+ fpi.ReadMode = 0;
|
||||
+ fpi.CompletionMode = 0;
|
||||
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ CloseHandle(hServer);
|
||||
+
|
||||
+ /* message mode server with read/write attributes */
|
||||
+ res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb,
|
||||
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */,
|
||||
+ 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout);
|
||||
+ ok(!res, "NtCreateNamedPipeFile returned %x\n", res);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 1, 0);
|
||||
+
|
||||
+ hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
|
||||
+ ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError: %x\n", GetLastError());
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 1, 0);
|
||||
+ check_pipe_handle_state(hClient, 0, 0);
|
||||
+
|
||||
+ if (hClient != INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ fpi.ReadMode = 1;
|
||||
+ fpi.CompletionMode = 1;
|
||||
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(!res, "NtSetInformationFile returned %x\n", res);
|
||||
+ }
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 1, 0);
|
||||
+ check_pipe_handle_state(hClient, 1, 1);
|
||||
+
|
||||
+ fpi.ReadMode = 0;
|
||||
+ fpi.CompletionMode = 1;
|
||||
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(!res, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+ check_pipe_handle_state(hClient, 1, 1);
|
||||
+
|
||||
+ if (hClient != INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ fpi.ReadMode = 0;
|
||||
+ fpi.CompletionMode = 2; /* not in range 0-1 */
|
||||
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ fpi.ReadMode = 2; /* not in range 0-1 */
|
||||
+ fpi.CompletionMode = 0;
|
||||
+ res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res);
|
||||
+ }
|
||||
+
|
||||
+ CloseHandle(hClient);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 0, 1);
|
||||
+
|
||||
+ fpi.ReadMode = 1;
|
||||
+ fpi.CompletionMode = 0;
|
||||
+ res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
|
||||
+ ok(!res, "NtSetInformationFile returned %x\n", res);
|
||||
+
|
||||
+ check_pipe_handle_state(hServer, 1, 0);
|
||||
+
|
||||
+ CloseHandle(hServer);
|
||||
+}
|
||||
+
|
||||
START_TEST(pipe)
|
||||
{
|
||||
if (!init_func_ptrs())
|
||||
@@ -493,6 +678,9 @@ START_TEST(pipe)
|
||||
trace("starting overlapped tests\n");
|
||||
test_overlapped();
|
||||
|
||||
+ trace("starting FILE_PIPE_INFORMATION tests\n");
|
||||
+ test_filepipeinfo();
|
||||
+
|
||||
if (!pOpenThread || !pQueueUserAPC)
|
||||
return;
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,126 @@
|
||||
From 2ae3b0fe9a03067879de3c7409e212510e134900 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 30 Jul 2014 18:00:19 +0200
|
||||
Subject: kernel32/tests: Always allow only one specific test result, add
|
||||
todo_wine where necessary.
|
||||
|
||||
The current pipe tests are not really a good base for fixing the implemenation -
|
||||
some of the todo_wine's depend on the return value itself. This hides if one of
|
||||
the following patches breaks things. Besides that some of the tests are currently
|
||||
broken on kernel >= 3.12 (bug #35781), mark those as todo_wine.
|
||||
|
||||
Changes in v2:
|
||||
* Ensure that the APC is properly removed - as it turned out this broke like 20 patches
|
||||
later one of the other new tests... ^^
|
||||
---
|
||||
dlls/kernel32/tests/pipe.c | 57 +++++++++++++++++---------------------------
|
||||
1 file changed, 22 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index f7c7531..5790be8 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -153,20 +153,13 @@ static void test_CreateNamedPipe(int pipemode)
|
||||
ok(written == sizeof(obuf2), "write file len 3b\n");
|
||||
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
|
||||
if (pipemode == PIPE_TYPE_BYTE) {
|
||||
- if (readden != sizeof(obuf)) /* Linux only returns the first message */
|
||||
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
|
||||
- else
|
||||
- todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
|
||||
+ todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
|
||||
}
|
||||
else
|
||||
{
|
||||
- if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both messages */
|
||||
- ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
|
||||
- else
|
||||
- todo_wine ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
|
||||
+ ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
|
||||
}
|
||||
- if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
|
||||
- ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
|
||||
+ ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
|
||||
pbuf = ibuf;
|
||||
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
|
||||
if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
|
||||
@@ -188,21 +181,13 @@ static void test_CreateNamedPipe(int pipemode)
|
||||
ok(written == sizeof(obuf2), "write file len 4b\n");
|
||||
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
|
||||
if (pipemode == PIPE_TYPE_BYTE) {
|
||||
- if (readden != sizeof(obuf)) /* Linux only returns the first message */
|
||||
- /* should return all 23 bytes */
|
||||
- ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
|
||||
- else
|
||||
- todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
|
||||
+ todo_wine ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
|
||||
}
|
||||
else
|
||||
{
|
||||
- if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both messages */
|
||||
- ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
|
||||
- else
|
||||
- todo_wine ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
|
||||
+ ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
|
||||
}
|
||||
- if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
|
||||
- ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
|
||||
+ ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
|
||||
pbuf = ibuf;
|
||||
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
|
||||
if (pipemode == PIPE_TYPE_BYTE && readden >= sizeof(obuf)+sizeof(obuf2)) {
|
||||
@@ -243,14 +228,8 @@ static void test_CreateNamedPipe(int pipemode)
|
||||
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
|
||||
ok(written == sizeof(obuf2), "write file len 3b\n");
|
||||
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
|
||||
- if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both writes */
|
||||
- ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
|
||||
- else
|
||||
- todo_wine ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
|
||||
- if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
|
||||
- ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
|
||||
- else
|
||||
- todo_wine ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
|
||||
+ ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
|
||||
+ ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
|
||||
pbuf = ibuf;
|
||||
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
|
||||
ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
|
||||
@@ -279,12 +258,8 @@ static void test_CreateNamedPipe(int pipemode)
|
||||
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
|
||||
ok(written == sizeof(obuf2), "write file len 6b\n");
|
||||
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
|
||||
- if (readden != sizeof(obuf) + sizeof(obuf2)) /* MacOS returns both writes */
|
||||
- ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
|
||||
- else
|
||||
- todo_wine ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
|
||||
- if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
|
||||
- ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
|
||||
+ ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
|
||||
+ ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
|
||||
pbuf = ibuf;
|
||||
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
|
||||
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
|
||||
@@ -1856,7 +1831,19 @@ static void test_readfileex_pending(void)
|
||||
ok(completion_called == 0, "completion routine called during ReadFile\n");
|
||||
|
||||
wait = WaitForSingleObjectEx(event, 0, TRUE);
|
||||
+ todo_wine
|
||||
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
|
||||
+ if (wait == WAIT_TIMEOUT)
|
||||
+ {
|
||||
+ /* work around kernel regression, and read some more */
|
||||
+ ret = ReadFile(client, read_buf, sizeof(read_buf), &num_bytes, NULL);
|
||||
+ ok(ret == TRUE, "ReadFile failed\n");
|
||||
+
|
||||
+ ok(completion_called == 0, "completion routine called during ReadFile\n");
|
||||
+
|
||||
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
|
||||
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
|
||||
+ }
|
||||
|
||||
ok(completion_called == 1, "completion routine not called\n");
|
||||
ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -0,0 +1,218 @@
|
||||
From 5b33f8fd992f8944442e8428e433461157b9e6c9 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Mon, 11 Aug 2014 17:26:18 +0200
|
||||
Subject: kernel32: Implement {Get,Set}NamedPipeHandleState.
|
||||
|
||||
Based on patch by Adam Martinson.
|
||||
---
|
||||
dlls/kernel32/sync.c | 88 +++++++++++++++++++++++++++++++++++++++-----
|
||||
dlls/kernel32/tests/pipe.c | 16 +-------
|
||||
2 files changed, 81 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
|
||||
index ff0e234..96a36b9 100644
|
||||
--- a/dlls/kernel32/sync.c
|
||||
+++ b/dlls/kernel32/sync.c
|
||||
@@ -1713,12 +1713,16 @@ BOOL WINAPI GetNamedPipeHandleStateA(
|
||||
LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
|
||||
LPSTR lpUsername, DWORD nUsernameMaxSize)
|
||||
{
|
||||
- FIXME("%p %p %p %p %p %p %d\n",
|
||||
- hNamedPipe, lpState, lpCurInstances,
|
||||
- lpMaxCollectionCount, lpCollectDataTimeout,
|
||||
- lpUsername, nUsernameMaxSize);
|
||||
+ WARN("%p %p %p %p %p %p %d: semi-stub\n",
|
||||
+ hNamedPipe, lpState, lpCurInstances,
|
||||
+ lpMaxCollectionCount, lpCollectDataTimeout,
|
||||
+ lpUsername, nUsernameMaxSize);
|
||||
|
||||
- return FALSE;
|
||||
+ if (lpUsername && nUsernameMaxSize)
|
||||
+ *lpUsername = 0;
|
||||
+
|
||||
+ return GetNamedPipeHandleStateW(hNamedPipe, lpState, lpCurInstances,
|
||||
+ lpMaxCollectionCount, lpCollectDataTimeout, NULL, 0);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -1729,12 +1733,53 @@ BOOL WINAPI GetNamedPipeHandleStateW(
|
||||
LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
|
||||
LPWSTR lpUsername, DWORD nUsernameMaxSize)
|
||||
{
|
||||
- FIXME("%p %p %p %p %p %p %d\n",
|
||||
+ IO_STATUS_BLOCK iosb;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ FIXME("%p %p %p %p %p %p %d: semi-stub\n",
|
||||
hNamedPipe, lpState, lpCurInstances,
|
||||
lpMaxCollectionCount, lpCollectDataTimeout,
|
||||
lpUsername, nUsernameMaxSize);
|
||||
|
||||
- return FALSE;
|
||||
+ if (lpMaxCollectionCount)
|
||||
+ *lpMaxCollectionCount = 0;
|
||||
+
|
||||
+ if (lpCollectDataTimeout)
|
||||
+ *lpCollectDataTimeout = 0;
|
||||
+
|
||||
+ if (lpUsername && nUsernameMaxSize)
|
||||
+ *lpUsername = 0;
|
||||
+
|
||||
+ if (lpState)
|
||||
+ {
|
||||
+ FILE_PIPE_INFORMATION fpi;
|
||||
+ status = NtQueryInformationFile(hNamedPipe, &iosb, &fpi, sizeof(fpi),
|
||||
+ FilePipeInformation);
|
||||
+ if (status)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ *lpState = (fpi.ReadMode ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE) |
|
||||
+ (fpi.CompletionMode ? PIPE_NOWAIT : PIPE_WAIT);
|
||||
+ }
|
||||
+
|
||||
+ if (lpCurInstances)
|
||||
+ {
|
||||
+ FILE_PIPE_LOCAL_INFORMATION fpli;
|
||||
+ status = NtQueryInformationFile(hNamedPipe, &iosb, &fpli, sizeof(fpli),
|
||||
+ FilePipeLocalInformation);
|
||||
+ if (status)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ *lpCurInstances = fpli.CurrentInstances;
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -1746,9 +1791,34 @@ BOOL WINAPI SetNamedPipeHandleState(
|
||||
{
|
||||
/* should be a fixme, but this function is called a lot by the RPC
|
||||
* runtime, and it slows down InstallShield a fair bit. */
|
||||
- WARN("stub: %p %p/%d %p %p\n",
|
||||
+ WARN("semi-stub: %p %p/%d %p %p\n",
|
||||
hNamedPipe, lpMode, lpMode ? *lpMode : 0, lpMaxCollectionCount, lpCollectDataTimeout);
|
||||
- return FALSE;
|
||||
+
|
||||
+ if (lpMode)
|
||||
+ {
|
||||
+ FILE_PIPE_INFORMATION fpi;
|
||||
+ IO_STATUS_BLOCK iosb;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ if (*lpMode & ~(PIPE_READMODE_MESSAGE | PIPE_NOWAIT))
|
||||
+ status = STATUS_INVALID_PARAMETER;
|
||||
+ else
|
||||
+ {
|
||||
+ fpi.CompletionMode = (*lpMode & PIPE_NOWAIT) ?
|
||||
+ FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
|
||||
+ fpi.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
|
||||
+ FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
|
||||
+ status = NtSetInformationFile(hNamedPipe, &iosb, &fpi, sizeof(fpi), FilePipeInformation);
|
||||
+ }
|
||||
+
|
||||
+ if (status)
|
||||
+ {
|
||||
+ SetLastError( RtlNtStatusToDosError(status) );
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index 5790be8..46004a3 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -218,10 +218,8 @@ static void test_CreateNamedPipe(int pipemode)
|
||||
ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
|
||||
}
|
||||
else {
|
||||
- todo_wine {
|
||||
- ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
|
||||
- }
|
||||
-
|
||||
+ ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
|
||||
+
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
|
||||
ok(written == sizeof(obuf), "write file len 3a\n");
|
||||
@@ -1637,11 +1635,9 @@ static void test_NamedPipeHandleState(void)
|
||||
/* lpSecurityAttrib */ NULL);
|
||||
ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
|
||||
ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
- todo_wine
|
||||
ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
|
||||
0);
|
||||
- todo_wine
|
||||
ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
@@ -1662,7 +1658,6 @@ static void test_NamedPipeHandleState(void)
|
||||
state = PIPE_READMODE_MESSAGE;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
|
||||
- todo_wine
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
@@ -1672,13 +1667,11 @@ static void test_NamedPipeHandleState(void)
|
||||
|
||||
state = PIPE_READMODE_BYTE;
|
||||
ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
|
||||
- todo_wine
|
||||
ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
/* A byte-mode pipe client can't be changed to message mode, either. */
|
||||
state = PIPE_READMODE_MESSAGE;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
|
||||
- todo_wine
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
|
||||
@@ -1694,11 +1687,9 @@ static void test_NamedPipeHandleState(void)
|
||||
/* lpSecurityAttrib */ NULL);
|
||||
ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
|
||||
ret = GetNamedPipeHandleStateA(server, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
- todo_wine
|
||||
ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
ret = GetNamedPipeHandleStateA(server, &state, &instances, NULL, NULL, NULL,
|
||||
0);
|
||||
- todo_wine
|
||||
ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
@@ -1710,7 +1701,6 @@ static void test_NamedPipeHandleState(void)
|
||||
*/
|
||||
state = PIPE_READMODE_BYTE;
|
||||
ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
|
||||
- todo_wine
|
||||
ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
|
||||
client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
|
||||
@@ -1719,13 +1709,11 @@ static void test_NamedPipeHandleState(void)
|
||||
|
||||
state = PIPE_READMODE_MESSAGE;
|
||||
ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
|
||||
- todo_wine
|
||||
ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
/* A message-mode pipe client can also be changed to byte mode.
|
||||
*/
|
||||
state = PIPE_READMODE_BYTE;
|
||||
ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
|
||||
- todo_wine
|
||||
ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
|
||||
|
||||
CloseHandle(client);
|
||||
--
|
||||
1.7.9.5
|
||||
|
@ -1,6 +1,10 @@
|
||||
Author: Sebastian Lackner / Dan Kegel
|
||||
Subject: Support for NamedPipe operations.
|
||||
Revision: 2
|
||||
Author: Dan Kegel
|
||||
Subject: Fix for ConnectNamedPort return value in overlapped mode.
|
||||
Revision: 1
|
||||
|
||||
Author: Sebastian Lackner / Adam Martinson
|
||||
Subject: Add proper implementation for SetNamedPipeHandleState.
|
||||
Revision: 7
|
||||
|
||||
Fixes: [16550] Fix for ConnectNamedPort return value in overlapped mode
|
||||
Fixes: [17273] Workaround for TransactNamedPipe not being supported
|
||||
Fixes: [17273] Support for SetNamedPipeHandleState
|
||||
|
Loading…
Reference in New Issue
Block a user