kernel32/tests: Add additional tests for multithreaded partial reads from named pipes.
This commit is contained in:
parent
e65a618538
commit
652f5d9b87
|
@ -43,6 +43,72 @@ static void CALLBACK user_apc(ULONG_PTR param)
|
|||
user_apc_ran = TRUE;
|
||||
}
|
||||
|
||||
|
||||
enum rpcThreadOp
|
||||
{
|
||||
RPC_READFILE
|
||||
};
|
||||
|
||||
struct rpcThreadArgs
|
||||
{
|
||||
ULONG_PTR returnValue;
|
||||
DWORD lastError;
|
||||
enum rpcThreadOp op;
|
||||
ULONG_PTR args[5];
|
||||
};
|
||||
|
||||
static DWORD CALLBACK rpcThreadMain(LPVOID arg)
|
||||
{
|
||||
struct rpcThreadArgs *rpcargs = (struct rpcThreadArgs *)arg;
|
||||
trace("rpcThreadMain starting\n");
|
||||
SetLastError( rpcargs->lastError );
|
||||
|
||||
switch (rpcargs->op)
|
||||
{
|
||||
case RPC_READFILE:
|
||||
rpcargs->returnValue = (ULONG_PTR)ReadFile( (HANDLE)rpcargs->args[0], /* hFile */
|
||||
(LPVOID)rpcargs->args[1], /* buffer */
|
||||
(DWORD)rpcargs->args[2], /* bytesToRead */
|
||||
(LPDWORD)rpcargs->args[3], /* bytesRead */
|
||||
(LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
|
||||
break;
|
||||
|
||||
default:
|
||||
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
|
||||
rpcargs->returnValue = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
rpcargs->lastError = GetLastError();
|
||||
trace("rpcThreadMain returning\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Runs ReadFile(...) from a different thread */
|
||||
static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead, LPOVERLAPPED overlapped)
|
||||
{
|
||||
struct rpcThreadArgs rpcargs;
|
||||
HANDLE thread;
|
||||
DWORD threadId;
|
||||
|
||||
rpcargs.returnValue = 0;
|
||||
rpcargs.lastError = GetLastError();
|
||||
rpcargs.op = RPC_READFILE;
|
||||
rpcargs.args[0] = (ULONG_PTR)hFile;
|
||||
rpcargs.args[1] = (ULONG_PTR)buffer;
|
||||
rpcargs.args[2] = (ULONG_PTR)bytesToRead;
|
||||
rpcargs.args[3] = (ULONG_PTR)bytesRead;
|
||||
rpcargs.args[4] = (ULONG_PTR)overlapped;
|
||||
|
||||
thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
|
||||
ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
|
||||
ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
|
||||
CloseHandle(thread);
|
||||
|
||||
SetLastError(rpcargs.lastError);
|
||||
return (BOOL)rpcargs.returnValue;
|
||||
}
|
||||
|
||||
static void test_CreateNamedPipe(int pipemode)
|
||||
{
|
||||
HANDLE hnp;
|
||||
|
@ -372,6 +438,99 @@ static void test_CreateNamedPipe(int pipemode)
|
|||
ok(readden == sizeof(obuf) - 4, "read got %d bytes 8\n", readden);
|
||||
ok(memcmp(obuf, ibuf, written) == 0, "content check 8\n");
|
||||
|
||||
/* The following test shows that when doing a partial read of a message, the rest
|
||||
* is still in the pipe, and can be received from a second thread. This shows
|
||||
* especially that the content is _not_ stored in thread-local-storage until it is
|
||||
* completely transmitted. The same method works even across multiple processes. */
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile 9\n");
|
||||
ok(written == sizeof(obuf), "write file len 9\n");
|
||||
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
|
||||
ok(written == sizeof(obuf2), "write file len 9\n");
|
||||
SetLastError(0xdeadbeef);
|
||||
todo_wine
|
||||
ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
|
||||
ok(readden == 4, "read got %d bytes 9\n", readden);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
|
||||
todo_wine
|
||||
ok(!ret, "RpcReadFile 9\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
|
||||
ok(readden == 4, "read got %d bytes 9\n", readden);
|
||||
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
|
||||
ok(ret, "RpcReadFile 9\n");
|
||||
todo_wine
|
||||
ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
|
||||
ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
|
||||
if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
|
||||
{
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
|
||||
ok(!ret, "RpcReadFile 9\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
|
||||
ok(readden == 4, "read got %d bytes 9\n", readden);
|
||||
SetLastError(0xdeadbeef);
|
||||
todo_wine
|
||||
ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
|
||||
ok(readden == 4, "read got %d bytes 9\n", readden);
|
||||
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
|
||||
ok(ret, "RpcReadFile 9\n");
|
||||
ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
|
||||
ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
|
||||
}
|
||||
|
||||
/* Now the reverse direction */
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 10\n");
|
||||
ok(written == sizeof(obuf2), "write file len 10\n");
|
||||
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
|
||||
ok(written == sizeof(obuf), "write file len 10\n");
|
||||
SetLastError(0xdeadbeef);
|
||||
todo_wine
|
||||
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
|
||||
ok(readden == 4, "read got %d bytes 10\n", readden);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
|
||||
todo_wine
|
||||
ok(!ret, "RpcReadFile 10\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
|
||||
ok(readden == 4, "read got %d bytes 10\n", readden);
|
||||
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
|
||||
ok(ret, "RpcReadFile 10\n");
|
||||
todo_wine
|
||||
ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
|
||||
ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
|
||||
if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
|
||||
{
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
|
||||
ok(!ret, "RpcReadFile 10\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
|
||||
ok(readden == 4, "read got %d bytes 10\n", readden);
|
||||
SetLastError(0xdeadbeef);
|
||||
todo_wine
|
||||
ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
|
||||
ok(readden == 4, "read got %d bytes 10\n", readden);
|
||||
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
|
||||
ok(ret, "RpcReadFile 10\n");
|
||||
ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
|
||||
ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Picky conformance tests */
|
||||
|
|
Loading…
Reference in New Issue