1 /* Unit test suite for Ntdll Port API functions
3 * Copyright 2006 James Hawkins
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "ntdll_test.h"
26 #ifndef __WINE_WINTERNL_H
28 typedef struct _CLIENT_ID
32 } CLIENT_ID
, *PCLIENT_ID
;
34 typedef struct _LPC_SECTION_WRITE
42 } LPC_SECTION_WRITE
, *PLPC_SECTION_WRITE
;
44 typedef struct _LPC_SECTION_READ
49 } LPC_SECTION_READ
, *PLPC_SECTION_READ
;
51 typedef struct _LPC_MESSAGE
56 USHORT VirtualRangesOffset
;
60 UCHAR Data
[ANYSIZE_ARRAY
];
61 } LPC_MESSAGE
, *PLPC_MESSAGE
;
65 /* Types of LPC messages */
66 #define UNUSED_MSG_TYPE 0
69 #define LPC_DATAGRAM 3
70 #define LPC_LOST_REPLY 4
71 #define LPC_PORT_CLOSED 5
72 #define LPC_CLIENT_DIED 6
73 #define LPC_EXCEPTION 7
74 #define LPC_DEBUG_EVENT 8
75 #define LPC_ERROR_EVENT 9
76 #define LPC_CONNECTION_REQUEST 10
78 static const WCHAR PORTNAME
[] = {'\\','M','y','P','o','r','t',0};
80 #define REQUEST1 "Request1"
81 #define REQUEST2 "Request2"
84 #define MAX_MESSAGE_LEN 30
87 static char selfname
[MAX_PATH
];
91 /* Function pointers for ntdll calls */
92 static HMODULE hntdll
= 0;
93 static NTSTATUS (WINAPI
*pNtCompleteConnectPort
)(HANDLE
);
94 static NTSTATUS (WINAPI
*pNtAcceptConnectPort
)(PHANDLE
,ULONG
,PLPC_MESSAGE
,ULONG
,
95 ULONG
,PLPC_SECTION_READ
);
96 static NTSTATUS (WINAPI
*pNtReplyPort
)(HANDLE
,PLPC_MESSAGE
);
97 static NTSTATUS (WINAPI
*pNtReplyWaitReceivePort
)(PHANDLE
,PULONG
,PLPC_MESSAGE
,
99 static NTSTATUS (WINAPI
*pNtCreatePort
)(PHANDLE
,POBJECT_ATTRIBUTES
,ULONG
,ULONG
,ULONG
);
100 static NTSTATUS (WINAPI
*pNtRequestWaitReplyPort
)(HANDLE
,PLPC_MESSAGE
,PLPC_MESSAGE
);
101 static NTSTATUS (WINAPI
*pNtRequestPort
)(HANDLE
,PLPC_MESSAGE
);
102 static NTSTATUS (WINAPI
*pNtRegisterThreadTerminatePort
)(HANDLE
);
103 static NTSTATUS (WINAPI
*pNtConnectPort
)(PHANDLE
,PUNICODE_STRING
,
104 PSECURITY_QUALITY_OF_SERVICE
,
105 PLPC_SECTION_WRITE
,PLPC_SECTION_READ
,
107 static NTSTATUS (WINAPI
*pRtlInitUnicodeString
)(PUNICODE_STRING
,LPCWSTR
);
108 static NTSTATUS (WINAPI
*pNtWaitForSingleObject
)(HANDLE
,BOOLEAN
,PLARGE_INTEGER
);
110 static BOOL
init_function_ptrs(void)
112 hntdll
= LoadLibraryA("ntdll.dll");
116 pNtCompleteConnectPort
= (void *)GetProcAddress(hntdll
, "NtCompleteConnectPort");
117 pNtAcceptConnectPort
= (void *)GetProcAddress(hntdll
, "NtAcceptConnectPort");
118 pNtReplyPort
= (void *)GetProcAddress(hntdll
, "NtReplyPort");
119 pNtReplyWaitReceivePort
= (void *)GetProcAddress(hntdll
, "NtReplyWaitReceivePort");
120 pNtCreatePort
= (void *)GetProcAddress(hntdll
, "NtCreatePort");
121 pNtRequestWaitReplyPort
= (void *)GetProcAddress(hntdll
, "NtRequestWaitReplyPort");
122 pNtRequestPort
= (void *)GetProcAddress(hntdll
, "NtRequestPort");
123 pNtRegisterThreadTerminatePort
= (void *)GetProcAddress(hntdll
, "NtRegisterThreadTerminatePort");
124 pNtConnectPort
= (void *)GetProcAddress(hntdll
, "NtConnectPort");
125 pRtlInitUnicodeString
= (void *)GetProcAddress(hntdll
, "RtlInitUnicodeString");
126 pNtWaitForSingleObject
= (void *)GetProcAddress(hntdll
, "NtWaitForSingleObject");
129 if (!pNtCompleteConnectPort
|| !pNtAcceptConnectPort
||
130 !pNtReplyWaitReceivePort
|| !pNtCreatePort
|| !pNtRequestWaitReplyPort
||
131 !pNtRequestPort
|| !pNtRegisterThreadTerminatePort
||
132 !pNtConnectPort
|| !pRtlInitUnicodeString
)
140 static void ProcessConnectionRequest(PLPC_MESSAGE LpcMessage
, PHANDLE pAcceptPortHandle
)
144 ok(LpcMessage
->MessageType
== LPC_CONNECTION_REQUEST
,
145 "Expected LPC_CONNECTION_REQUEST, got %d\n", LpcMessage
->MessageType
);
146 ok(!*LpcMessage
->Data
, "Expected empty string!\n");
148 status
= pNtAcceptConnectPort(pAcceptPortHandle
, 0, LpcMessage
, 1, 0, NULL
);
149 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
151 status
= pNtCompleteConnectPort(*pAcceptPortHandle
);
152 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
155 static void ProcessLpcRequest(HANDLE PortHandle
, PLPC_MESSAGE LpcMessage
)
159 ok(LpcMessage
->MessageType
== LPC_REQUEST
,
160 "Expected LPC_REQUEST, got %d\n", LpcMessage
->MessageType
);
161 ok(!lstrcmp((LPSTR
)LpcMessage
->Data
, REQUEST2
),
162 "Expected %s, got %s\n", REQUEST2
, LpcMessage
->Data
);
164 lstrcpy((LPSTR
)LpcMessage
->Data
, REPLY
);
166 status
= pNtReplyPort(PortHandle
, LpcMessage
);
167 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
168 ok(LpcMessage
->MessageType
== LPC_REQUEST
,
169 "Expected LPC_REQUEST, got %d\n", LpcMessage
->MessageType
);
170 ok(!lstrcmp((LPSTR
)LpcMessage
->Data
, REPLY
),
171 "Expected %s, got %s\n", REPLY
, LpcMessage
->Data
);
174 static DWORD WINAPI
test_ports_client(LPVOID arg
)
176 SECURITY_QUALITY_OF_SERVICE sqos
;
177 LPC_MESSAGE
*LpcMessage
, *out
;
182 sqos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
183 sqos
.ImpersonationLevel
= SecurityImpersonation
;
184 sqos
.ContextTrackingMode
= SECURITY_STATIC_TRACKING
;
185 sqos
.EffectiveOnly
= TRUE
;
187 status
= pNtConnectPort(&PortHandle
, &port
, &sqos
, 0, 0, &len
, NULL
, NULL
);
188 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
190 status
= pNtRegisterThreadTerminatePort(PortHandle
);
191 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
193 size
= FIELD_OFFSET(LPC_MESSAGE
, Data
) + MAX_MESSAGE_LEN
;
194 LpcMessage
= HeapAlloc(GetProcessHeap(), 0, size
);
195 out
= HeapAlloc(GetProcessHeap(), 0, size
);
197 memset(LpcMessage
, 0, size
);
198 LpcMessage
->DataSize
= lstrlen(REQUEST1
) + 1;
199 LpcMessage
->MessageSize
= FIELD_OFFSET(LPC_MESSAGE
, Data
) + LpcMessage
->DataSize
;
200 lstrcpy((LPSTR
)LpcMessage
->Data
, REQUEST1
);
202 status
= pNtRequestPort(PortHandle
, LpcMessage
);
203 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
204 ok(LpcMessage
->MessageType
== 0, "Expected 0, got %d\n", LpcMessage
->MessageType
);
205 ok(!lstrcmp((LPSTR
)LpcMessage
->Data
, REQUEST1
),
206 "Expected %s, got %s\n", REQUEST1
, LpcMessage
->Data
);
208 /* Fill in the message */
209 memset(LpcMessage
, 0, size
);
210 LpcMessage
->DataSize
= lstrlen(REQUEST2
) + 1;
211 LpcMessage
->MessageSize
= FIELD_OFFSET(LPC_MESSAGE
, Data
) + LpcMessage
->DataSize
;
212 lstrcpy((LPSTR
)LpcMessage
->Data
, REQUEST2
);
214 /* Send the message and wait for the reply */
215 status
= pNtRequestWaitReplyPort(PortHandle
, LpcMessage
, out
);
216 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
217 ok(!lstrcmp((LPSTR
)out
->Data
, REPLY
), "Expected %s, got %s\n", REPLY
, out
->Data
);
218 ok(out
->MessageType
== LPC_REPLY
, "Expected LPC_REPLY, got %d\n", out
->MessageType
);
223 static void test_ports_server(void)
225 OBJECT_ATTRIBUTES obj
;
227 HANDLE AcceptPortHandle
;
228 PLPC_MESSAGE LpcMessage
;
233 pRtlInitUnicodeString(&port
, PORTNAME
);
235 memset(&obj
, 0, sizeof(OBJECT_ATTRIBUTES
));
236 obj
.Length
= sizeof(OBJECT_ATTRIBUTES
);
237 obj
.ObjectName
= &port
;
239 status
= pNtCreatePort(&PortHandle
, &obj
, 100, 100, 0);
242 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld\n", status
);
245 size
= FIELD_OFFSET(LPC_MESSAGE
, Data
) + MAX_MESSAGE_LEN
;
246 LpcMessage
= HeapAlloc(GetProcessHeap(), 0, size
);
247 memset(LpcMessage
, 0, size
);
251 status
= pNtReplyWaitReceivePort(PortHandle
, NULL
, NULL
, LpcMessage
);
254 ok(status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got %ld(%lx)\n", status
, status
);
256 /* STATUS_INVALID_HANDLE: win2k without admin rights will perform an
259 if ((status
== STATUS_NOT_IMPLEMENTED
) ||
260 (status
== STATUS_INVALID_HANDLE
)) return;
262 switch (LpcMessage
->MessageType
)
264 case LPC_CONNECTION_REQUEST
:
265 ProcessConnectionRequest(LpcMessage
, &AcceptPortHandle
);
269 ProcessLpcRequest(PortHandle
, LpcMessage
);
274 ok(!lstrcmp((LPSTR
)LpcMessage
->Data
, REQUEST1
),
275 "Expected %s, got %s\n", REQUEST1
, LpcMessage
->Data
);
278 case LPC_CLIENT_DIED
:
279 ok(done
, "Expected LPC request to be completed!\n");
283 ok(FALSE
, "Unexpected message: %d\n", LpcMessage
->MessageType
);
294 if (!init_function_ptrs())
297 myARGC
= winetest_get_mainargs(&myARGV
);
298 strcpy(selfname
, myARGV
[0]);
300 thread
= CreateThread(NULL
, 0, test_ports_client
, NULL
, 0, &id
);
301 ok(thread
!= NULL
, "Expected non-NULL thread handle!\n");