[REACTOS]
[reactos.git] / rostests / kmtests / npfs / NpfsConnect.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite NPFS Connect test
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <kmt_test.h>
9 #include "npfs.h"
10
11 #define MAX_INSTANCES 5
12 #define IN_QUOTA 4096
13 #define OUT_QUOTA 4096
14
15 #define CheckServer(ServerHandle, State) \
16 NpCheckServerPipe(ServerHandle, \
17 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
18 MAX_INSTANCES, 1, \
19 IN_QUOTA, 0, \
20 OUT_QUOTA, OUT_QUOTA, \
21 State)
22
23 #define CheckClient(ClientHandle, State) \
24 NpCheckClientPipe(ClientHandle, \
25 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX, \
26 MAX_INSTANCES, 1, \
27 IN_QUOTA, 0, \
28 OUT_QUOTA, OUT_QUOTA, \
29 State)
30
31 static
32 VOID
33 ConnectPipe(
34 IN OUT PTHREAD_CONTEXT Context)
35 {
36 HANDLE ClientHandle;
37
38 ClientHandle = NULL;
39 Context->Connect.Status = NpOpenPipe(&ClientHandle,
40 Context->Connect.PipePath,
41 FILE_PIPE_FULL_DUPLEX);
42 Context->Connect.ClientHandle = ClientHandle;
43 }
44
45 static
46 VOID
47 ListenPipe(
48 IN OUT PTHREAD_CONTEXT Context)
49 {
50 Context->Listen.Status = NpListenPipe(Context->Listen.ServerHandle);
51 }
52
53 static
54 BOOLEAN
55 CheckConnectPipe(
56 IN PTHREAD_CONTEXT Context,
57 IN PCWSTR PipePath,
58 IN ULONG MilliSeconds)
59 {
60 Context->Work = ConnectPipe;
61 Context->Connect.PipePath = PipePath;
62 return TriggerWork(Context, MilliSeconds);
63 }
64
65 static
66 BOOLEAN
67 CheckListenPipe(
68 IN PTHREAD_CONTEXT Context,
69 IN HANDLE ServerHandle,
70 IN ULONG MilliSeconds)
71 {
72 Context->Work = ListenPipe;
73 Context->Listen.ServerHandle = ServerHandle;
74 return TriggerWork(Context, MilliSeconds);
75 }
76
77 static
78 VOID
79 TestConnect(
80 IN HANDLE ServerHandle,
81 IN PCWSTR PipePath)
82 {
83 NTSTATUS Status;
84 THREAD_CONTEXT ConnectContext;
85 THREAD_CONTEXT ListenContext;
86 BOOLEAN Okay;
87 HANDLE ClientHandle;
88
89 StartWorkerThread(&ConnectContext);
90 StartWorkerThread(&ListenContext);
91
92 /* Server should start out listening */
93 CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
94
95 /* Connect a client */
96 ClientHandle = NULL;
97 Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
98 ok_bool_true(Okay, "CheckConnectPipe returned");
99 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
100 if (NT_SUCCESS(ConnectContext.Connect.Status))
101 {
102 ClientHandle = ConnectContext.Connect.ClientHandle;
103 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
104 }
105 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
106
107 /* Connect another client */
108 Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
109 ok_bool_true(Okay, "CheckConnectPipe returned");
110 ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
111 if (NT_SUCCESS(ConnectContext.Connect.Status))
112 ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
113 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
114 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
115
116 /* Disconnecting the client should fail */
117 Status = NpDisconnectPipe(ClientHandle);
118 ok_eq_hex(Status, STATUS_ILLEGAL_FUNCTION);
119 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
120 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
121
122 /* Listening on the client should fail */
123 Status = NpListenPipe(ClientHandle);
124 ok_eq_hex(Status, STATUS_ILLEGAL_FUNCTION);
125 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
126 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
127
128 /* Close client */
129 if (ClientHandle)
130 ObCloseHandle(ClientHandle, KernelMode);
131 CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
132
133 /* Connecting a client now should fail */
134 Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
135 ok_bool_true(Okay, "CheckConnectPipe returned");
136 ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
137 if (NT_SUCCESS(ConnectContext.Connect.Status))
138 ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
139 CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
140
141 /* Listening should fail */
142 Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
143 ok_bool_true(Okay, "CheckListenPipe returned");
144 if (!skip(Okay, "Listen succeeded unexpectedly\n"))
145 CheckServer(ServerHandle, FILE_PIPE_CLOSING_STATE);
146
147 /* Disconnect server */
148 Status = NpDisconnectPipe(ServerHandle);
149 ok_eq_hex(Status, STATUS_SUCCESS);
150 CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
151
152 /* Disconnecting again should fail */
153 Status = NpDisconnectPipe(ServerHandle);
154 ok_eq_hex(Status, STATUS_PIPE_DISCONNECTED);
155 CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
156
157 /* Connecting a client now should fail */
158 Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
159 ok_bool_true(Okay, "CheckConnectPipe returned");
160 ok_eq_hex(ConnectContext.Connect.Status, STATUS_PIPE_NOT_AVAILABLE);
161 if (NT_SUCCESS(ConnectContext.Connect.Status))
162 ObCloseHandle(ConnectContext.Connect.ClientHandle, KernelMode);
163 CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
164
165 /**************************************************************************/
166 /* Now listen again */
167 Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
168 ok_bool_false(Okay, "CheckListenPipe returned");
169 //blocks: CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
170
171 /* Connect client */
172 ClientHandle = NULL;
173 Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
174 ok_bool_true(Okay, "CheckConnectPipe returned");
175 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
176 if (NT_SUCCESS(ConnectContext.Connect.Status))
177 {
178 ClientHandle = ConnectContext.Connect.ClientHandle;
179 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
180 }
181 Okay = WaitForWork(&ListenContext, 100);
182 ok_bool_true(Okay, "WaitForWork returned");
183 ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
184 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
185
186 /* Listening again should fail */
187 Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
188 ok_bool_true(Okay, "CheckListenPipe returned");
189 ok_eq_hex(ListenContext.Listen.Status, STATUS_PIPE_CONNECTED);
190 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
191 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
192
193 /* Disconnect server */
194 Status = NpDisconnectPipe(ServerHandle);
195 ok_eq_hex(Status, STATUS_SUCCESS);
196 NpQueryPipe(ClientHandle, STATUS_PIPE_DISCONNECTED);
197 CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
198
199 /* Close client */
200 if (ClientHandle)
201 ObCloseHandle(ClientHandle, KernelMode);
202 CheckServer(ServerHandle, FILE_PIPE_DISCONNECTED_STATE);
203
204 /**************************************************************************/
205 /* Listen once more */
206 Okay = CheckListenPipe(&ListenContext, ServerHandle, 100);
207 ok_bool_false(Okay, "CheckListenPipe returned");
208 //blocks: CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
209
210 /* Connect client */
211 ClientHandle = NULL;
212 Okay = CheckConnectPipe(&ConnectContext, PipePath, 100);
213 ok_bool_true(Okay, "CheckConnectPipe returned");
214 ok_eq_hex(ConnectContext.Connect.Status, STATUS_SUCCESS);
215 if (NT_SUCCESS(ConnectContext.Connect.Status))
216 {
217 ClientHandle = ConnectContext.Connect.ClientHandle;
218 CheckClient(ClientHandle, FILE_PIPE_CONNECTED_STATE);
219 }
220 Okay = WaitForWork(&ListenContext, 100);
221 ok_bool_true(Okay, "WaitForWork returned");
222 ok_eq_hex(ListenContext.Listen.Status, STATUS_SUCCESS);
223 CheckServer(ServerHandle, FILE_PIPE_CONNECTED_STATE);
224
225 /* Close server */
226 Status = ObCloseHandle(ServerHandle, KernelMode);
227 ok_eq_hex(Status, STATUS_SUCCESS);
228 CheckClient(ClientHandle, FILE_PIPE_CLOSING_STATE);
229
230 /* Close client */
231 if (ClientHandle)
232 ObCloseHandle(ClientHandle, KernelMode);
233
234 FinishWorkerThread(&ListenContext);
235 FinishWorkerThread(&ConnectContext);
236 }
237
238 static KSTART_ROUTINE RunTest;
239 static
240 VOID
241 NTAPI
242 RunTest(
243 IN PVOID Context)
244 {
245 NTSTATUS Status;
246 HANDLE ServerHandle;
247
248 UNREFERENCED_PARAMETER(Context);
249
250 ServerHandle = INVALID_HANDLE_VALUE;
251 Status = NpCreatePipe(&ServerHandle,
252 DEVICE_NAMED_PIPE L"\\KmtestNpfsConnectTestPipe",
253 BYTE_STREAM, QUEUE, BYTE_STREAM, DUPLEX,
254 MAX_INSTANCES,
255 IN_QUOTA,
256 OUT_QUOTA);
257 ok_eq_hex(Status, STATUS_SUCCESS);
258 ok(ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE, "ServerHandle = %p\n", ServerHandle);
259 if (!skip(NT_SUCCESS(Status) && ServerHandle != NULL && ServerHandle != INVALID_HANDLE_VALUE, "No pipe\n"))
260 {
261 CheckServer(ServerHandle, FILE_PIPE_LISTENING_STATE);
262 TestConnect(ServerHandle, DEVICE_NAMED_PIPE L"\\KmtestNpfsConnectTestPipe");
263 }
264 }
265
266 START_TEST(NpfsConnect)
267 {
268 PKTHREAD Thread;
269
270 Thread = KmtStartThread(RunTest, NULL);
271 KmtFinishThread(Thread, NULL);
272 }