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 } 273