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