1c2c66affSColin Finck /* Unit test suite for Ntdll Port API functions
2c2c66affSColin Finck *
3c2c66affSColin Finck * Copyright 2006 James Hawkins
4c2c66affSColin Finck *
5c2c66affSColin Finck * This library is free software; you can redistribute it and/or
6c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
7c2c66affSColin Finck * License as published by the Free Software Foundation; either
8c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
9c2c66affSColin Finck *
10c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
11c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13c2c66affSColin Finck * Lesser General Public License for more details.
14c2c66affSColin Finck *
15c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
16c2c66affSColin Finck * License along with this library; if not, write to the Free Software
17c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18c2c66affSColin Finck */
19c2c66affSColin Finck
20*4ba4c415SAmine Khaldi #include <stdio.h>
21*4ba4c415SAmine Khaldi #include <stdarg.h>
22*4ba4c415SAmine Khaldi
23*4ba4c415SAmine Khaldi #include "ntstatus.h"
24*4ba4c415SAmine Khaldi #define WIN32_NO_STATUS
25*4ba4c415SAmine Khaldi #include "windef.h"
26*4ba4c415SAmine Khaldi #include "winbase.h"
27*4ba4c415SAmine Khaldi #include "winuser.h"
28*4ba4c415SAmine Khaldi #include "winreg.h"
29*4ba4c415SAmine Khaldi #include "winnls.h"
30*4ba4c415SAmine Khaldi #include "wine/test.h"
31*4ba4c415SAmine Khaldi #include "winternl.h"
32c2c66affSColin Finck
33c2c66affSColin Finck #ifndef __WINE_WINTERNL_H
34c2c66affSColin Finck
35c2c66affSColin Finck typedef struct _CLIENT_ID
36c2c66affSColin Finck {
37c2c66affSColin Finck HANDLE UniqueProcess;
38c2c66affSColin Finck HANDLE UniqueThread;
39c2c66affSColin Finck } CLIENT_ID, *PCLIENT_ID;
40c2c66affSColin Finck
41c2c66affSColin Finck typedef struct _LPC_SECTION_WRITE
42c2c66affSColin Finck {
43c2c66affSColin Finck ULONG Length;
44c2c66affSColin Finck HANDLE SectionHandle;
45c2c66affSColin Finck ULONG SectionOffset;
46c2c66affSColin Finck ULONG ViewSize;
47c2c66affSColin Finck PVOID ViewBase;
48c2c66affSColin Finck PVOID TargetViewBase;
49c2c66affSColin Finck } LPC_SECTION_WRITE, *PLPC_SECTION_WRITE;
50c2c66affSColin Finck
51c2c66affSColin Finck typedef struct _LPC_SECTION_READ
52c2c66affSColin Finck {
53c2c66affSColin Finck ULONG Length;
54c2c66affSColin Finck ULONG ViewSize;
55c2c66affSColin Finck PVOID ViewBase;
56c2c66affSColin Finck } LPC_SECTION_READ, *PLPC_SECTION_READ;
57c2c66affSColin Finck
58c2c66affSColin Finck typedef struct _LPC_MESSAGE
59c2c66affSColin Finck {
60c2c66affSColin Finck USHORT DataSize;
61c2c66affSColin Finck USHORT MessageSize;
62c2c66affSColin Finck USHORT MessageType;
63c2c66affSColin Finck USHORT VirtualRangesOffset;
64c2c66affSColin Finck CLIENT_ID ClientId;
65c2c66affSColin Finck ULONG_PTR MessageId;
66c2c66affSColin Finck ULONG_PTR SectionSize;
67c2c66affSColin Finck UCHAR Data[ANYSIZE_ARRAY];
68c2c66affSColin Finck } LPC_MESSAGE, *PLPC_MESSAGE;
69c2c66affSColin Finck
70c2c66affSColin Finck #endif
71c2c66affSColin Finck
72c2c66affSColin Finck /* on Wow64 we have to use the 64-bit layout */
73c2c66affSColin Finck typedef struct
74c2c66affSColin Finck {
75c2c66affSColin Finck USHORT DataSize;
76c2c66affSColin Finck USHORT MessageSize;
77c2c66affSColin Finck USHORT MessageType;
78c2c66affSColin Finck USHORT VirtualRangesOffset;
79c2c66affSColin Finck ULONGLONG ClientId[2];
80c2c66affSColin Finck ULONGLONG MessageId;
81c2c66affSColin Finck ULONGLONG SectionSize;
82c2c66affSColin Finck UCHAR Data[ANYSIZE_ARRAY];
83c2c66affSColin Finck } LPC_MESSAGE64;
84c2c66affSColin Finck
85c2c66affSColin Finck union lpc_message
86c2c66affSColin Finck {
87c2c66affSColin Finck LPC_MESSAGE msg;
88c2c66affSColin Finck LPC_MESSAGE64 msg64;
89c2c66affSColin Finck };
90c2c66affSColin Finck
91c2c66affSColin Finck /* Types of LPC messages */
92c2c66affSColin Finck #define UNUSED_MSG_TYPE 0
93c2c66affSColin Finck #define LPC_REQUEST 1
94c2c66affSColin Finck #define LPC_REPLY 2
95c2c66affSColin Finck #define LPC_DATAGRAM 3
96c2c66affSColin Finck #define LPC_LOST_REPLY 4
97c2c66affSColin Finck #define LPC_PORT_CLOSED 5
98c2c66affSColin Finck #define LPC_CLIENT_DIED 6
99c2c66affSColin Finck #define LPC_EXCEPTION 7
100c2c66affSColin Finck #define LPC_DEBUG_EVENT 8
101c2c66affSColin Finck #define LPC_ERROR_EVENT 9
102c2c66affSColin Finck #define LPC_CONNECTION_REQUEST 10
103c2c66affSColin Finck
104c2c66affSColin Finck static const WCHAR PORTNAME[] = {'\\','M','y','P','o','r','t',0};
105c2c66affSColin Finck
106c2c66affSColin Finck #define REQUEST1 "Request1"
107c2c66affSColin Finck #define REQUEST2 "Request2"
108c2c66affSColin Finck #define REPLY "Reply"
109c2c66affSColin Finck
110c2c66affSColin Finck #define MAX_MESSAGE_LEN 30
111c2c66affSColin Finck
112c2c66affSColin Finck static UNICODE_STRING port;
113c2c66affSColin Finck
114c2c66affSColin Finck /* Function pointers for ntdll calls */
115c2c66affSColin Finck static HMODULE hntdll = 0;
116c2c66affSColin Finck static NTSTATUS (WINAPI *pNtCompleteConnectPort)(HANDLE);
117c2c66affSColin Finck static NTSTATUS (WINAPI *pNtAcceptConnectPort)(PHANDLE,ULONG,PLPC_MESSAGE,ULONG,
118c2c66affSColin Finck PLPC_SECTION_WRITE,PLPC_SECTION_READ);
119c2c66affSColin Finck static NTSTATUS (WINAPI *pNtReplyPort)(HANDLE,PLPC_MESSAGE);
120c2c66affSColin Finck static NTSTATUS (WINAPI *pNtReplyWaitReceivePort)(PHANDLE,PULONG,PLPC_MESSAGE,
121c2c66affSColin Finck PLPC_MESSAGE);
122c2c66affSColin Finck static NTSTATUS (WINAPI *pNtCreatePort)(PHANDLE,POBJECT_ATTRIBUTES,ULONG,ULONG,ULONG);
123c2c66affSColin Finck static NTSTATUS (WINAPI *pNtRequestWaitReplyPort)(HANDLE,PLPC_MESSAGE,PLPC_MESSAGE);
124c2c66affSColin Finck static NTSTATUS (WINAPI *pNtRequestPort)(HANDLE,PLPC_MESSAGE);
125c2c66affSColin Finck static NTSTATUS (WINAPI *pNtRegisterThreadTerminatePort)(HANDLE);
126c2c66affSColin Finck static NTSTATUS (WINAPI *pNtConnectPort)(PHANDLE,PUNICODE_STRING,
127c2c66affSColin Finck PSECURITY_QUALITY_OF_SERVICE,
128c2c66affSColin Finck PLPC_SECTION_WRITE,PLPC_SECTION_READ,
129c2c66affSColin Finck PVOID,PVOID,PULONG);
130c2c66affSColin Finck static NTSTATUS (WINAPI *pRtlInitUnicodeString)(PUNICODE_STRING,LPCWSTR);
131c2c66affSColin Finck static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
132c2c66affSColin Finck
133c2c66affSColin Finck static BOOL is_wow64;
134c2c66affSColin Finck
init_function_ptrs(void)135c2c66affSColin Finck static BOOL init_function_ptrs(void)
136c2c66affSColin Finck {
137c2c66affSColin Finck hntdll = LoadLibraryA("ntdll.dll");
138c2c66affSColin Finck
139c2c66affSColin Finck if (!hntdll)
140c2c66affSColin Finck return FALSE;
141c2c66affSColin Finck
142c2c66affSColin Finck pNtCompleteConnectPort = (void *)GetProcAddress(hntdll, "NtCompleteConnectPort");
143c2c66affSColin Finck pNtAcceptConnectPort = (void *)GetProcAddress(hntdll, "NtAcceptConnectPort");
144c2c66affSColin Finck pNtReplyPort = (void *)GetProcAddress(hntdll, "NtReplyPort");
145c2c66affSColin Finck pNtReplyWaitReceivePort = (void *)GetProcAddress(hntdll, "NtReplyWaitReceivePort");
146c2c66affSColin Finck pNtCreatePort = (void *)GetProcAddress(hntdll, "NtCreatePort");
147c2c66affSColin Finck pNtRequestWaitReplyPort = (void *)GetProcAddress(hntdll, "NtRequestWaitReplyPort");
148c2c66affSColin Finck pNtRequestPort = (void *)GetProcAddress(hntdll, "NtRequestPort");
149c2c66affSColin Finck pNtRegisterThreadTerminatePort = (void *)GetProcAddress(hntdll, "NtRegisterThreadTerminatePort");
150c2c66affSColin Finck pNtConnectPort = (void *)GetProcAddress(hntdll, "NtConnectPort");
151c2c66affSColin Finck pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
152c2c66affSColin Finck
153c2c66affSColin Finck if (!pNtCompleteConnectPort || !pNtAcceptConnectPort ||
154c2c66affSColin Finck !pNtReplyWaitReceivePort || !pNtCreatePort || !pNtRequestWaitReplyPort ||
155c2c66affSColin Finck !pNtRequestPort || !pNtRegisterThreadTerminatePort ||
156c2c66affSColin Finck !pNtConnectPort || !pRtlInitUnicodeString)
157c2c66affSColin Finck {
158c2c66affSColin Finck win_skip("Needed port functions are not available\n");
159c2c66affSColin Finck FreeLibrary(hntdll);
160c2c66affSColin Finck return FALSE;
161c2c66affSColin Finck }
162c2c66affSColin Finck
163c2c66affSColin Finck pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
164c2c66affSColin Finck if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
165c2c66affSColin Finck return TRUE;
166c2c66affSColin Finck }
167c2c66affSColin Finck
ProcessConnectionRequest(union lpc_message * LpcMessage,PHANDLE pAcceptPortHandle)168c2c66affSColin Finck static void ProcessConnectionRequest(union lpc_message *LpcMessage, PHANDLE pAcceptPortHandle)
169c2c66affSColin Finck {
170c2c66affSColin Finck NTSTATUS status;
171c2c66affSColin Finck
172c2c66affSColin Finck if (is_wow64)
173c2c66affSColin Finck {
174c2c66affSColin Finck ok(LpcMessage->msg64.MessageType == LPC_CONNECTION_REQUEST,
175c2c66affSColin Finck "Expected LPC_CONNECTION_REQUEST, got %d\n", LpcMessage->msg64.MessageType);
176c2c66affSColin Finck ok(!*LpcMessage->msg64.Data, "Expected empty string!\n");
177c2c66affSColin Finck }
178c2c66affSColin Finck else
179c2c66affSColin Finck {
180c2c66affSColin Finck ok(LpcMessage->msg.MessageType == LPC_CONNECTION_REQUEST,
181c2c66affSColin Finck "Expected LPC_CONNECTION_REQUEST, got %d\n", LpcMessage->msg.MessageType);
182c2c66affSColin Finck ok(!*LpcMessage->msg.Data, "Expected empty string!\n");
183c2c66affSColin Finck }
184c2c66affSColin Finck
185c2c66affSColin Finck status = pNtAcceptConnectPort(pAcceptPortHandle, 0, &LpcMessage->msg, 1, NULL, NULL);
186c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
187c2c66affSColin Finck
188c2c66affSColin Finck status = pNtCompleteConnectPort(*pAcceptPortHandle);
189c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
190c2c66affSColin Finck }
191c2c66affSColin Finck
ProcessLpcRequest(HANDLE PortHandle,union lpc_message * LpcMessage)192c2c66affSColin Finck static void ProcessLpcRequest(HANDLE PortHandle, union lpc_message *LpcMessage)
193c2c66affSColin Finck {
194c2c66affSColin Finck NTSTATUS status;
195c2c66affSColin Finck
196c2c66affSColin Finck if (is_wow64)
197c2c66affSColin Finck {
198c2c66affSColin Finck ok(LpcMessage->msg64.MessageType == LPC_REQUEST,
199c2c66affSColin Finck "Expected LPC_REQUEST, got %d\n", LpcMessage->msg64.MessageType);
200c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REQUEST2),
201c2c66affSColin Finck "Expected %s, got %s\n", REQUEST2, LpcMessage->msg64.Data);
202c2c66affSColin Finck strcpy((LPSTR)LpcMessage->msg64.Data, REPLY);
203c2c66affSColin Finck
204c2c66affSColin Finck status = pNtReplyPort(PortHandle, &LpcMessage->msg);
205c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
206c2c66affSColin Finck ok(LpcMessage->msg64.MessageType == LPC_REQUEST,
207c2c66affSColin Finck "Expected LPC_REQUEST, got %d\n", LpcMessage->msg64.MessageType);
208c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REPLY),
209c2c66affSColin Finck "Expected %s, got %s\n", REPLY, LpcMessage->msg64.Data);
210c2c66affSColin Finck }
211c2c66affSColin Finck else
212c2c66affSColin Finck {
213c2c66affSColin Finck ok(LpcMessage->msg.MessageType == LPC_REQUEST,
214c2c66affSColin Finck "Expected LPC_REQUEST, got %d\n", LpcMessage->msg.MessageType);
215c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg.Data, REQUEST2),
216c2c66affSColin Finck "Expected %s, got %s\n", REQUEST2, LpcMessage->msg.Data);
217c2c66affSColin Finck strcpy((LPSTR)LpcMessage->msg.Data, REPLY);
218c2c66affSColin Finck
219c2c66affSColin Finck status = pNtReplyPort(PortHandle, &LpcMessage->msg);
220c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
221c2c66affSColin Finck ok(LpcMessage->msg.MessageType == LPC_REQUEST,
222c2c66affSColin Finck "Expected LPC_REQUEST, got %d\n", LpcMessage->msg.MessageType);
223c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg.Data, REPLY),
224c2c66affSColin Finck "Expected %s, got %s\n", REPLY, LpcMessage->msg.Data);
225c2c66affSColin Finck }
226c2c66affSColin Finck }
227c2c66affSColin Finck
test_ports_client(LPVOID arg)228c2c66affSColin Finck static DWORD WINAPI test_ports_client(LPVOID arg)
229c2c66affSColin Finck {
230c2c66affSColin Finck SECURITY_QUALITY_OF_SERVICE sqos;
231c2c66affSColin Finck union lpc_message *LpcMessage, *out;
232c2c66affSColin Finck HANDLE PortHandle;
233c2c66affSColin Finck ULONG len, size;
234c2c66affSColin Finck NTSTATUS status;
235c2c66affSColin Finck
236c2c66affSColin Finck sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
237c2c66affSColin Finck sqos.ImpersonationLevel = SecurityImpersonation;
238c2c66affSColin Finck sqos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
239c2c66affSColin Finck sqos.EffectiveOnly = TRUE;
240c2c66affSColin Finck
241c2c66affSColin Finck status = pNtConnectPort(&PortHandle, &port, &sqos, 0, 0, &len, NULL, NULL);
242c2c66affSColin Finck todo_wine ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
243c2c66affSColin Finck if (status != STATUS_SUCCESS) return 1;
244c2c66affSColin Finck
245c2c66affSColin Finck status = pNtRegisterThreadTerminatePort(PortHandle);
246c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
247c2c66affSColin Finck
248c2c66affSColin Finck if (is_wow64)
249c2c66affSColin Finck {
250c2c66affSColin Finck size = FIELD_OFFSET(LPC_MESSAGE64, Data[MAX_MESSAGE_LEN]);
251c2c66affSColin Finck LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
252c2c66affSColin Finck out = HeapAlloc(GetProcessHeap(), 0, size);
253c2c66affSColin Finck
254c2c66affSColin Finck LpcMessage->msg64.DataSize = strlen(REQUEST1) + 1;
255c2c66affSColin Finck LpcMessage->msg64.MessageSize = FIELD_OFFSET(LPC_MESSAGE64, Data[LpcMessage->msg64.DataSize]);
256c2c66affSColin Finck strcpy((LPSTR)LpcMessage->msg64.Data, REQUEST1);
257c2c66affSColin Finck
258c2c66affSColin Finck status = pNtRequestPort(PortHandle, &LpcMessage->msg);
259c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
260c2c66affSColin Finck ok(LpcMessage->msg64.MessageType == 0, "Expected 0, got %d\n", LpcMessage->msg64.MessageType);
261c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REQUEST1),
262c2c66affSColin Finck "Expected %s, got %s\n", REQUEST1, LpcMessage->msg64.Data);
263c2c66affSColin Finck
264c2c66affSColin Finck /* Fill in the message */
265c2c66affSColin Finck memset(LpcMessage, 0, size);
266c2c66affSColin Finck LpcMessage->msg64.DataSize = strlen(REQUEST2) + 1;
267c2c66affSColin Finck LpcMessage->msg64.MessageSize = FIELD_OFFSET(LPC_MESSAGE64, Data[LpcMessage->msg64.DataSize]);
268c2c66affSColin Finck strcpy((LPSTR)LpcMessage->msg64.Data, REQUEST2);
269c2c66affSColin Finck
270c2c66affSColin Finck /* Send the message and wait for the reply */
271c2c66affSColin Finck status = pNtRequestWaitReplyPort(PortHandle, &LpcMessage->msg, &out->msg);
272c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
273c2c66affSColin Finck ok(!strcmp((LPSTR)out->msg64.Data, REPLY), "Expected %s, got %s\n", REPLY, out->msg64.Data);
274c2c66affSColin Finck ok(out->msg64.MessageType == LPC_REPLY, "Expected LPC_REPLY, got %d\n", out->msg64.MessageType);
275c2c66affSColin Finck }
276c2c66affSColin Finck else
277c2c66affSColin Finck {
278c2c66affSColin Finck size = FIELD_OFFSET(LPC_MESSAGE, Data[MAX_MESSAGE_LEN]);
279c2c66affSColin Finck LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
280c2c66affSColin Finck out = HeapAlloc(GetProcessHeap(), 0, size);
281c2c66affSColin Finck
282c2c66affSColin Finck LpcMessage->msg.DataSize = strlen(REQUEST1) + 1;
283c2c66affSColin Finck LpcMessage->msg.MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data[LpcMessage->msg.DataSize]);
284c2c66affSColin Finck strcpy((LPSTR)LpcMessage->msg.Data, REQUEST1);
285c2c66affSColin Finck
286c2c66affSColin Finck status = pNtRequestPort(PortHandle, &LpcMessage->msg);
287c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
288c2c66affSColin Finck ok(LpcMessage->msg.MessageType == 0, "Expected 0, got %d\n", LpcMessage->msg.MessageType);
289c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg.Data, REQUEST1),
290c2c66affSColin Finck "Expected %s, got %s\n", REQUEST1, LpcMessage->msg.Data);
291c2c66affSColin Finck
292c2c66affSColin Finck /* Fill in the message */
293c2c66affSColin Finck memset(LpcMessage, 0, size);
294c2c66affSColin Finck LpcMessage->msg.DataSize = strlen(REQUEST2) + 1;
295c2c66affSColin Finck LpcMessage->msg.MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data[LpcMessage->msg.DataSize]);
296c2c66affSColin Finck strcpy((LPSTR)LpcMessage->msg.Data, REQUEST2);
297c2c66affSColin Finck
298c2c66affSColin Finck /* Send the message and wait for the reply */
299c2c66affSColin Finck status = pNtRequestWaitReplyPort(PortHandle, &LpcMessage->msg, &out->msg);
300c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %x\n", status);
301c2c66affSColin Finck ok(!strcmp((LPSTR)out->msg.Data, REPLY), "Expected %s, got %s\n", REPLY, out->msg.Data);
302c2c66affSColin Finck ok(out->msg.MessageType == LPC_REPLY, "Expected LPC_REPLY, got %d\n", out->msg.MessageType);
303c2c66affSColin Finck }
304c2c66affSColin Finck
305c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, out);
306c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LpcMessage);
307c2c66affSColin Finck
308c2c66affSColin Finck return 0;
309c2c66affSColin Finck }
310c2c66affSColin Finck
test_ports_server(HANDLE PortHandle)311c2c66affSColin Finck static void test_ports_server( HANDLE PortHandle )
312c2c66affSColin Finck {
313c2c66affSColin Finck HANDLE AcceptPortHandle;
314c2c66affSColin Finck union lpc_message *LpcMessage;
315c2c66affSColin Finck ULONG size;
316c2c66affSColin Finck NTSTATUS status;
317c2c66affSColin Finck BOOL done = FALSE;
318c2c66affSColin Finck
319c2c66affSColin Finck size = FIELD_OFFSET(LPC_MESSAGE, Data) + MAX_MESSAGE_LEN;
320c2c66affSColin Finck LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
321c2c66affSColin Finck
322c2c66affSColin Finck while (TRUE)
323c2c66affSColin Finck {
324c2c66affSColin Finck status = pNtReplyWaitReceivePort(PortHandle, NULL, NULL, &LpcMessage->msg);
325c2c66affSColin Finck todo_wine
326c2c66affSColin Finck {
327c2c66affSColin Finck ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d(%x)\n", status, status);
328c2c66affSColin Finck }
329c2c66affSColin Finck /* STATUS_INVALID_HANDLE: win2k without admin rights will perform an
330c2c66affSColin Finck * endless loop here
331c2c66affSColin Finck */
332c2c66affSColin Finck if ((status == STATUS_NOT_IMPLEMENTED) ||
333c2c66affSColin Finck (status == STATUS_INVALID_HANDLE)) return;
334c2c66affSColin Finck
335c2c66affSColin Finck switch (is_wow64 ? LpcMessage->msg64.MessageType : LpcMessage->msg.MessageType)
336c2c66affSColin Finck {
337c2c66affSColin Finck case LPC_CONNECTION_REQUEST:
338c2c66affSColin Finck ProcessConnectionRequest(LpcMessage, &AcceptPortHandle);
339c2c66affSColin Finck break;
340c2c66affSColin Finck
341c2c66affSColin Finck case LPC_REQUEST:
342c2c66affSColin Finck ProcessLpcRequest(PortHandle, LpcMessage);
343c2c66affSColin Finck done = TRUE;
344c2c66affSColin Finck break;
345c2c66affSColin Finck
346c2c66affSColin Finck case LPC_DATAGRAM:
347c2c66affSColin Finck if (is_wow64)
348c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg64.Data, REQUEST1),
349c2c66affSColin Finck "Expected %s, got %s\n", REQUEST1, LpcMessage->msg64.Data);
350c2c66affSColin Finck else
351c2c66affSColin Finck ok(!strcmp((LPSTR)LpcMessage->msg.Data, REQUEST1),
352c2c66affSColin Finck "Expected %s, got %s\n", REQUEST1, LpcMessage->msg.Data);
353c2c66affSColin Finck break;
354c2c66affSColin Finck
355c2c66affSColin Finck case LPC_CLIENT_DIED:
356c2c66affSColin Finck ok(done, "Expected LPC request to be completed!\n");
357c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LpcMessage);
358c2c66affSColin Finck return;
359c2c66affSColin Finck
360c2c66affSColin Finck default:
361c2c66affSColin Finck ok(FALSE, "Unexpected message: %d\n",
362c2c66affSColin Finck is_wow64 ? LpcMessage->msg64.MessageType : LpcMessage->msg.MessageType);
363c2c66affSColin Finck break;
364c2c66affSColin Finck }
365c2c66affSColin Finck }
366c2c66affSColin Finck
367c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, LpcMessage);
368c2c66affSColin Finck }
369c2c66affSColin Finck
START_TEST(port)370c2c66affSColin Finck START_TEST(port)
371c2c66affSColin Finck {
372c2c66affSColin Finck OBJECT_ATTRIBUTES obj;
373c2c66affSColin Finck HANDLE port_handle;
374c2c66affSColin Finck NTSTATUS status;
375c2c66affSColin Finck
376c2c66affSColin Finck if (!init_function_ptrs())
377c2c66affSColin Finck return;
378c2c66affSColin Finck
379c2c66affSColin Finck pRtlInitUnicodeString(&port, PORTNAME);
380c2c66affSColin Finck
381c2c66affSColin Finck memset(&obj, 0, sizeof(OBJECT_ATTRIBUTES));
382c2c66affSColin Finck obj.Length = sizeof(OBJECT_ATTRIBUTES);
383c2c66affSColin Finck obj.ObjectName = &port;
384c2c66affSColin Finck
385c2c66affSColin Finck status = pNtCreatePort(&port_handle, &obj, 100, 100, 0);
386c2c66affSColin Finck if (status == STATUS_ACCESS_DENIED) skip("Not enough rights\n");
387c2c66affSColin Finck else todo_wine ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %d\n", status);
388c2c66affSColin Finck
389c2c66affSColin Finck if (status == STATUS_SUCCESS)
390c2c66affSColin Finck {
391c2c66affSColin Finck DWORD id;
392c2c66affSColin Finck HANDLE thread = CreateThread(NULL, 0, test_ports_client, NULL, 0, &id);
393c2c66affSColin Finck ok(thread != NULL, "Expected non-NULL thread handle!\n");
394c2c66affSColin Finck
395c2c66affSColin Finck test_ports_server( port_handle );
396c2c66affSColin Finck ok( WaitForSingleObject( thread, 10000 ) == 0, "thread didn't exit\n" );
397c2c66affSColin Finck CloseHandle(thread);
398c2c66affSColin Finck }
399c2c66affSColin Finck FreeLibrary(hntdll);
400c2c66affSColin Finck }
401