CreateNamedPipe questions
Oddly enough, it looks like it's ok to pass NULL as the filename to CreateNamedPipe. Anyone know what programs do that, and why? Here's a patch that makes our CreateNamedPipe check for legal filenames (or NULL). It should probably allow forward slashes... The patch also adds a quickie regression test, but I still have to use late binding for CreateNamedPipe (or is it ok for the test to fail on win9x?). Would this test have caught the recent named pipe breakage? If not, what would I need to add? Comments welcome; I'll send it to wine-patches after addressing any feedback. - Dan -- Dan Kegel http://www.kegel.com http://counter.li.org/cgi-bin/runscript/display-person.cgi?user=78045 Index: dlls/kernel/sync.c =================================================================== RCS file: /home/wine/wine/dlls/kernel/sync.c,v retrieving revision 1.26 diff -u -p -u -r1.26 sync.c --- dlls/kernel/sync.c 25 Oct 2002 21:02:30 -0000 1.26 +++ dlls/kernel/sync.c 13 Feb 2003 07:47:27 -0000 @@ -508,6 +508,8 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR { HANDLE ret; DWORD len = name ? strlenW(name) : 0; + static const WCHAR leadin[] = {'\\','\\','.','\\','P','I','P','E'}; + int i; TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n", debugstr_w(name), dwOpenMode, dwPipeMode, nMaxInstances, @@ -516,7 +518,13 @@ HANDLE WINAPI CreateNamedPipeW( LPCWSTR if (len >= MAX_PATH) { SetLastError( ERROR_FILENAME_EXCED_RANGE ); - return 0; + return INVALID_HANDLE_VALUE; + } + /* FIXME: can name really be NULL?! */ + if (name && strncmpiW(name, leadin, sizeof(leadin)/sizeof(leadin[0]))) + { + SetLastError( ERROR_INVALID_NAME ); + return INVALID_HANDLE_VALUE; } SERVER_START_REQ( create_named_pipe ) { Index: dlls/kernel/tests/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/kernel/tests/Makefile.in,v retrieving revision 1.6 diff -u -p -u -r1.6 Makefile.in --- dlls/kernel/tests/Makefile.in 4 Oct 2002 17:42:27 -0000 1.6 +++ dlls/kernel/tests/Makefile.in 13 Feb 2003 07:47:27 -0000 @@ -17,6 +17,7 @@ CTESTS = \ generated.c \ locale.c \ path.c \ + pipe.c \ process.c \ thread.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ dlls/kernel/tests/pipe.c 2003-02-12 23:44:20.000000000 -0800 @@ -0,0 +1,109 @@ +/* + * Unit tests for named pipe functions in Wine + * + * Copyright (c) 2002 Dan Kegel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#ifndef STANDALONE +#include "wine/test.h" +#else +#include <assert.h> +#define START_TEST(name) main(int argc, char **argv) +#define ok(condition, msg) assert(condition) +#endif + +#include <windef.h> +#include <winbase.h> +#include <winerror.h> +#include <wtypes.h> + +#define PIPENAME "\\\\.\\PiPe\\tests_" __FILE__ + +void test_CreateNamedPipeA(void) +{ + HANDLE hnp; + HANDLE hFile; + const char obuf[] = "Bit Bucket"; + char ibuf[32]; + DWORD written; + DWORD gelesen; + + /* Bad parameter checks */ + hnp = CreateNamedPipeA("not a named pipe", + PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_WAIT, + /* nMaxInstances */ 1, + /* nOutBufSize */ 1024, + /* nInBufSize */ 1024, + /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT, + /* lpSecurityAttrib */ NULL); + + ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME, + "CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe"); + +#if 0 /* Evidently it's ok in windows to pass NULL as the pipe name! */ + hnp = CreateNamedPipeA(NULL, + PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_WAIT, + 1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL); + ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME, + "CreateNamedPipe should fail if name is NULL"); +#endif + + /* Functional checks */ + + hnp = CreateNamedPipeA(PIPENAME, + PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_WAIT, + /* nMaxInstances */ 1, + /* nOutBufSize */ 1024, + /* nInBufSize */ 1024, + /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT, + /* lpSecurityAttrib */ NULL); + ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed"); + + hFile = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, + NULL, OPEN_EXISTING, 0, 0); + ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed"); + if (hFile == INVALID_HANDLE_VALUE) + return; + + /* Make sure we can read and write a few bytes in both directions*/ + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile"); + ok(written == sizeof(obuf), "write file len"); + ok(ReadFile(hFile, ibuf, sizeof(obuf), &gelesen, NULL), "ReadFile"); + ok(gelesen == sizeof(obuf), "read file len"); + ok(memcmp(obuf, ibuf, written) == 0, "content check"); + + memset(ibuf, 0, sizeof(ibuf)); + ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile"); + ok(written == sizeof(obuf), "write file len"); + ok(ReadFile(hnp, ibuf, sizeof(obuf), &gelesen, NULL), "ReadFile"); + ok(gelesen == sizeof(obuf), "read file len"); + ok(memcmp(obuf, ibuf, written) == 0, "content check"); + + CloseHandle(hFile); + CloseHandle(hnp); +} + +START_TEST(pipe) +{ + test_CreateNamedPipeA(); +} +
On Wed, 12 Feb 2003, Dan Kegel wrote: [...]
The patch also adds a quickie regression test, but I still have to use late binding for CreateNamedPipe (or is it ok for the test to fail on win9x?).
Nope. Tests should succeed on all Windows platforms. For platforms where the API is not supported, the individual checks should be skipped. Typically this involves either: 1. either using GetProcAddress if the API is missing altogether on some platforms 2. of calling the API and testing for the error code, usually ERROR_CALL_NOT_IMPLEMENTED CreateNamedPipe{A,W} exists on Win95 so at most you will need something along the lines of 2. -- Francois Gouget fgouget(a)free.fr http://fgouget.free.fr/ Linux, WinNT, MS-DOS - also known as the Good, the Bad and the Ugly.
Francois Gouget wrote:
2. of calling the API and testing for the error code, usually ERROR_CALL_NOT_IMPLEMENTED
CreateNamedPipe{A,W} exists on Win95 so at most you will need something along the lines of 2.
Will do, thanks. -- Dan Kegel http://www.kegel.com http://counter.li.org/cgi-bin/runscript/display-person.cgi?user=78045
"Dan Kegel" <dank(a)kegel.com> wrote:
Oddly enough, it looks like it's ok to pass NULL as the filename to CreateNamedPipe.
Under Win2k CreateNamedPipe(NULL) in your test returns INVALID_HANDLE_VALUE but sets last error to ERROR_PATH_NOT_FOUND, not ERROR_INVALID_NAME as your test expects. It worth to verify last error at least under NT 4.0 since it's known that NT 4 either doesn't set last error at all, or often sets it differently than win2k/XP. -- Dmitry.
Dmitry Timoshkov wrote:
Under Win2k CreateNamedPipe(NULL) in your test returns INVALID_HANDLE_VALUE but sets last error to ERROR_PATH_NOT_FOUND, not ERROR_INVALID_NAME as your test expects.
Thanks! For some reason, when I ran it on Win2K Professional, it seemed to succeed. I'll have to try it again. Also, dlls/kernel/sync.c seems to allow for NULL filenames for some reason.
It worth to verify last error at least under NT 4.0 since it's ^^^^^^^ "it's worthless"? known that NT 4 either doesn't set last error at all, or often sets it differently than win2k/XP.
What about NT 3.51? Same as NT 4? IMHO it's worth checking error codes anyway... maybe we could make that optional. - Dan -- Dan Kegel http://www.kegel.com http://counter.li.org/cgi-bin/runscript/display-person.cgi?user=78045
participants (3)
-
Dan Kegel -
Dmitry Timoshkov -
Francois Gouget