Win32 utility to bootstrap the PSX subsystem (it is an optional subsystem, therefore...
[reactos.git] / posix / server / port / api.c
1 /* $Id: api.c,v 1.4 2003/12/21 20:11:46 ea Exp $
2 *
3 * PROJECT : ReactOS / POSIX+ Environment Subsystem Server
4 * FILE : reactos/subsys/psx/server/port/api.c
5 * DESCRIPTION: \POSIX+\ApiPort LPC port logic.
6 * DATE : 2001-04-04
7 * AUTHOR : Emanuele Aliberti <eal@users.sf.net>
8 *
9 * --------------------------------------------------------------------
10 *
11 * This software is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this software; see the file COPYING. If not, write
23 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
24 * MA 02139, USA.
25 *
26 * --------------------------------------------------------------------
27 */
28 #include <psxss.h>
29 #include <psx/lpcproto.h>
30 #include "utils.h"
31
32 /**********************************************************************
33 * ProcessConnectionRequest/ PRIVATE
34 *
35 * DESCRIPTION
36 * This is called when a PSX process attaches to PSXDLL.DLL.
37 */
38 PRIVATE NTSTATUS STDCALL
39 ProcessConnectionRequest (PLPC_MAX_MESSAGE pRequest)
40 {
41 PPSX_CONNECT_PORT_DATA pConnectData = (PPSX_CONNECT_PORT_DATA) & pRequest->Data;
42 NTSTATUS Status;
43 HANDLE hConnectedPort;
44 ULONG ulPortIdentifier;
45
46 debug_print (L"PSXSS: ->%s", __FUNCTION__);
47 /* Check if the caller is a process */
48 Status = PsxCheckConnectionRequest (
49 pConnectData,
50 PSX_CONNECTION_TYPE_PROCESS
51 );
52 if (!NT_SUCCESS(Status))
53 {
54 Status = NtAcceptConnectPort (
55 & hConnectedPort,
56 NULL,
57 & pRequest->Header,
58 FALSE, /* reject connection request */
59 NULL,
60 NULL
61 );
62 if (!NT_SUCCESS(Status))
63 {
64 debug_print(
65 L"PSXSS: %s: NtAcceptConnectPort failed with status=%08x",
66 __FUNCTION__,
67 Status
68 );
69 }
70 return STATUS_UNSUCCESSFUL;
71 }
72 /* OK, accept the connection */
73 Status = NtAcceptConnectPort (
74 & hConnectedPort,
75 & ulPortIdentifier,
76 & pRequest->Header,
77 TRUE, /* accept connection request */
78 NULL,
79 NULL
80 );
81 if (!NT_SUCCESS(Status))
82 {
83 debug_print(L"PSXSS: %s: NtAcceptConnectPort failed with status=%08x", __FUNCTION__, Status);
84 return Status;
85 }
86 Status = PsxCreateProcess (pRequest,hConnectedPort,ulPortIdentifier);
87 if (!NT_SUCCESS(Status))
88 {
89 debug_print(L"PSXSS: %s: PsxCreateProcess failed with status=%08x", __FUNCTION__, Status);
90 return Status;
91 }
92 Status = NtCompleteConnectPort (hConnectedPort);
93 if (!NT_SUCCESS(Status))
94 {
95 debug_print(L"PSXSS: %s: NtCompleteConnectPort failed with status=%08x", __FUNCTION__, Status);
96 return Status;
97 }
98 debug_print (L"PSXSS: <-%s", __FUNCTION__);
99 return STATUS_SUCCESS;
100 }
101 /**********************************************************************
102 * ProcessRequest/ PRIVATE
103 *
104 * DESCRIPTION
105 * This is the actual POSIX system calls dispatcher.
106 */
107 PRIVATE NTSTATUS STDCALL
108 ProcessRequest (PPSX_MAX_MESSAGE pRequest)
109 {
110 debug_print (L"PSXSS: ->%s", __FUNCTION__);
111
112 if (pRequest->PsxHeader.Procedure < PSX_SYSCALL_APIPORT_COUNT)
113 {
114 pRequest->PsxHeader.Status =
115 SystemCall [pRequest->PsxHeader.Procedure] (pRequest);
116 }
117 else
118 {
119 pRequest->PsxHeader.Status = STATUS_INVALID_SYSTEM_SERVICE;
120 }
121 return STATUS_SUCCESS;
122 }
123 /**********************************************************************
124 * ApiPortListener/1
125 *
126 * DESCRIPTION
127 * The thread to process messages from the \POSIX+\ApiPort
128 * LPC port. Mostly used by PSXDLL.DLL.
129 */
130 VOID STDCALL
131 ApiPortListener (PVOID pArg)
132 {
133 ULONG ulIndex = (ULONG) pArg;
134 NTSTATUS Status;
135 LPC_TYPE RequestType;
136 ULONG PortIdentifier;
137 PSX_MAX_MESSAGE Request;
138 PPSX_MAX_MESSAGE Reply = NULL;
139 BOOL NullReply = FALSE;
140
141 debug_print (L"PSXSS: ->%s pArg=%d", __FUNCTION__, ulIndex);
142
143 while (TRUE)
144 {
145 Reply = NULL;
146 NullReply = FALSE;
147 while (!NullReply)
148 {
149 Status = NtReplyWaitReceivePort (
150 Server.Port[ulIndex].hObject,
151 0,
152 (PLPC_MESSAGE) Reply,
153 (PLPC_MESSAGE) & Request
154 );
155 if (!NT_SUCCESS(Status))
156 {
157 break;
158 }
159 RequestType = PORT_MESSAGE_TYPE(Request);
160 switch (RequestType)
161 {
162 case LPC_CONNECTION_REQUEST:
163 ProcessConnectionRequest ((PLPC_MAX_MESSAGE) & Request);
164 NullReply = TRUE;
165 continue;
166 case LPC_CLIENT_DIED:
167 case LPC_PORT_CLOSED:
168 case LPC_DEBUG_EVENT:
169 case LPC_ERROR_EVENT:
170 case LPC_EXCEPTION:
171 NullReply = TRUE;
172 continue;
173 default:
174 if (RequestType != LPC_REQUEST)
175 {
176 NullReply = TRUE;
177 continue;
178 }
179 }
180 Reply = & Request;
181 Reply->PsxHeader.Status = ProcessRequest (& Request);
182 NullReply = FALSE;
183 }
184 if ((STATUS_INVALID_HANDLE == Status) ||
185 (STATUS_OBJECT_TYPE_MISMATCH == Status))
186 {
187 break;
188 }
189 }
190 #ifdef __PSXSS_ON_W32__
191 TerminateThread(GetCurrentThread(),Status);
192 #else
193 NtTerminateThread(NtCurrentThread(),Status);
194 #endif
195 }
196 /* EOF */