Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Client part of the client/server communication |
| 3 | * |
| 4 | * Copyright (C) 1998 Alexandre Julliard |
| 5 | */ |
| 6 | |
| 7 | #include <assert.h> |
| 8 | #include <errno.h> |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 9 | #include <fcntl.h> |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 10 | #include <stdio.h> |
| 11 | #include <string.h> |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 12 | #include <sys/types.h> |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 13 | #include <sys/socket.h> |
| 14 | #include <sys/uio.h> |
| 15 | #include <unistd.h> |
| 16 | |
| 17 | #include "process.h" |
| 18 | #include "thread.h" |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 19 | #include "server/request.h" |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 20 | #include "server.h" |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 21 | #include "winerror.h" |
| 22 | |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 23 | /* Some versions of glibc don't define this */ |
| 24 | #ifndef SCM_RIGHTS |
| 25 | #define SCM_RIGHTS 1 |
| 26 | #endif |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 27 | |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 28 | |
| 29 | /*********************************************************************** |
| 30 | * CLIENT_ProtocolError |
| 31 | */ |
Alexandre Julliard | 6ebbe3c | 1999-01-01 17:04:00 +0000 | [diff] [blame] | 32 | static void CLIENT_ProtocolError( const char *err, ... ) |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 33 | { |
| 34 | THDB *thdb = THREAD_Current(); |
| 35 | va_list args; |
| 36 | |
| 37 | va_start( args, err ); |
| 38 | fprintf( stderr, "Client protocol error:%p: ", thdb->server_tid ); |
| 39 | vfprintf( stderr, err, args ); |
| 40 | va_end( args ); |
| 41 | ExitThread(1); |
| 42 | } |
| 43 | |
| 44 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 45 | /*********************************************************************** |
| 46 | * CLIENT_SendRequest_v |
| 47 | * |
| 48 | * Send a request to the server. |
| 49 | */ |
| 50 | static void CLIENT_SendRequest_v( enum request req, int pass_fd, |
| 51 | struct iovec *vec, int veclen ) |
| 52 | { |
| 53 | THDB *thdb = THREAD_Current(); |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 54 | #ifndef HAVE_MSGHDR_ACCRIGHTS |
| 55 | struct cmsg_fd cmsg = { sizeof(cmsg), SOL_SOCKET, SCM_RIGHTS, pass_fd }; |
| 56 | #endif |
| 57 | struct msghdr msghdr = { NULL, 0, vec, veclen, }; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 58 | struct header head; |
| 59 | int i, ret, len; |
| 60 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 61 | assert( veclen > 0 ); |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 62 | vec[0].iov_base = &head; |
| 63 | vec[0].iov_len = sizeof(head); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 64 | for (i = len = 0; i < veclen; i++) len += vec[i].iov_len; |
| 65 | |
| 66 | assert( len <= MAX_MSG_LENGTH ); |
| 67 | head.type = req; |
| 68 | head.len = len; |
| 69 | head.seq = thdb->seq++; |
| 70 | |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 71 | if (pass_fd != -1) /* we have an fd to send */ |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 72 | { |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 73 | #ifdef HAVE_MSGHDR_ACCRIGHTS |
| 74 | msghdr.msg_accrights = (void *)&pass_fd; |
| 75 | msghdr.msg_accrightslen = sizeof(pass_fd); |
| 76 | #else |
| 77 | msghdr.msg_control = &cmsg; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 78 | msghdr.msg_controllen = sizeof(cmsg); |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 79 | #endif |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | if ((ret = sendmsg( thdb->socket, &msghdr, 0 )) < len) |
| 83 | { |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 84 | if (ret == -1) perror( "sendmsg" ); |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 85 | CLIENT_ProtocolError( "partial msg sent %d/%d\n", ret, len ); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 86 | } |
| 87 | /* we passed the fd now we can close it */ |
| 88 | if (pass_fd != -1) close( pass_fd ); |
| 89 | } |
| 90 | |
| 91 | |
| 92 | /*********************************************************************** |
| 93 | * CLIENT_SendRequest |
| 94 | * |
| 95 | * Send a request to the server. |
| 96 | */ |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 97 | void CLIENT_SendRequest( enum request req, int pass_fd, |
| 98 | int n, ... /* arg_1, len_1, etc. */ ) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 99 | { |
| 100 | struct iovec vec[16]; |
| 101 | va_list args; |
| 102 | int i; |
| 103 | |
| 104 | n++; /* for vec[0] */ |
| 105 | assert( n < 16 ); |
| 106 | va_start( args, n ); |
| 107 | for (i = 1; i < n; i++) |
| 108 | { |
| 109 | vec[i].iov_base = va_arg( args, void * ); |
| 110 | vec[i].iov_len = va_arg( args, int ); |
| 111 | } |
| 112 | va_end( args ); |
| 113 | return CLIENT_SendRequest_v( req, pass_fd, vec, n ); |
| 114 | } |
| 115 | |
| 116 | |
| 117 | /*********************************************************************** |
| 118 | * CLIENT_WaitReply_v |
| 119 | * |
| 120 | * Wait for a reply from the server. |
| 121 | * Returns the error code (or 0 if OK). |
| 122 | */ |
| 123 | static unsigned int CLIENT_WaitReply_v( int *len, int *passed_fd, |
| 124 | struct iovec *vec, int veclen ) |
| 125 | { |
| 126 | THDB *thdb = THREAD_Current(); |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 127 | int pass_fd = -1; |
| 128 | #ifdef HAVE_MSGHDR_ACCRIGHTS |
| 129 | struct msghdr msghdr = { NULL, 0, vec, veclen, (void*)&pass_fd, sizeof(int) }; |
| 130 | #else |
| 131 | struct cmsg_fd cmsg = { sizeof(cmsg), SOL_SOCKET, SCM_RIGHTS, -1 }; |
| 132 | struct msghdr msghdr = { NULL, 0, vec, veclen, &cmsg, sizeof(cmsg), 0 }; |
| 133 | #endif |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 134 | struct header head; |
| 135 | int ret, remaining; |
| 136 | |
| 137 | assert( veclen > 0 ); |
| 138 | vec[0].iov_base = &head; |
| 139 | vec[0].iov_len = sizeof(head); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 140 | |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 141 | while ((ret = recvmsg( thdb->socket, &msghdr, 0 )) == -1) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 142 | { |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 143 | if (errno == EINTR) continue; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 144 | perror("recvmsg"); |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 145 | CLIENT_ProtocolError( "recvmsg\n" ); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 146 | } |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 147 | if (!ret) ExitThread(1); /* the server closed the connection; time to die... */ |
| 148 | |
| 149 | /* sanity checks */ |
| 150 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 151 | if (ret < sizeof(head)) |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 152 | CLIENT_ProtocolError( "partial header received %d/%d\n", ret, sizeof(head) ); |
| 153 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 154 | if ((head.len < sizeof(head)) || (head.len > MAX_MSG_LENGTH)) |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 155 | CLIENT_ProtocolError( "header length %d\n", head.len ); |
| 156 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 157 | if (head.seq != thdb->seq++) |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 158 | CLIENT_ProtocolError( "sequence %08x instead of %08x\n", head.seq, thdb->seq - 1 ); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 159 | |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 160 | #ifndef HAVE_MSGHDR_ACCRIGHTS |
| 161 | pass_fd = cmsg.fd; |
| 162 | #endif |
| 163 | |
Alexandre Julliard | d757fc6 | 1999-01-31 15:06:28 +0000 | [diff] [blame] | 164 | if (passed_fd) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 165 | { |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 166 | *passed_fd = pass_fd; |
| 167 | pass_fd = -1; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 168 | } |
| 169 | |
| 170 | if (len) *len = ret - sizeof(head); |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 171 | if (pass_fd != -1) close( pass_fd ); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 172 | remaining = head.len - ret; |
Geoff Clare | 0b78af7 | 1999-01-31 18:57:28 +0000 | [diff] [blame] | 173 | while (remaining > 0) /* get remaining data */ |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 174 | { |
Geoff Clare | 0b78af7 | 1999-01-31 18:57:28 +0000 | [diff] [blame] | 175 | char *bufp, buffer[1024]; |
| 176 | int addlen, i, iovtot = 0; |
| 177 | |
| 178 | /* see if any iovs are still incomplete, otherwise drop the rest */ |
| 179 | for (i = 0; i < veclen && remaining > 0; i++) |
| 180 | { |
| 181 | if (iovtot + vec[i].iov_len > head.len - remaining) |
| 182 | { |
| 183 | addlen = iovtot + vec[i].iov_len - (head.len - remaining); |
| 184 | bufp = (char *)vec[i].iov_base + (vec[i].iov_len - addlen); |
| 185 | if (addlen > remaining) addlen = remaining; |
| 186 | if ((addlen = recv( thdb->socket, bufp, addlen, 0 )) == -1) |
| 187 | { |
| 188 | perror( "recv" ); |
| 189 | CLIENT_ProtocolError( "recv\n" ); |
| 190 | } |
| 191 | if (!addlen) ExitThread(1); /* the server closed the connection; time to die... */ |
| 192 | if (len) *len += addlen; |
| 193 | remaining -= addlen; |
| 194 | } |
| 195 | iovtot += vec[i].iov_len; |
| 196 | } |
| 197 | |
| 198 | if (remaining > 0) |
| 199 | addlen = remaining < sizeof(buffer) ? remaining : sizeof(buffer); |
| 200 | else |
| 201 | break; |
| 202 | |
| 203 | if ((addlen = recv( thdb->socket, buffer, addlen, 0 )) == -1) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 204 | { |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 205 | perror( "recv" ); |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 206 | CLIENT_ProtocolError( "recv\n" ); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 207 | } |
Geoff Clare | 0b78af7 | 1999-01-31 18:57:28 +0000 | [diff] [blame] | 208 | if (!addlen) ExitThread(1); /* the server closed the connection; time to die... */ |
| 209 | remaining -= addlen; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 210 | } |
| 211 | |
Alexandre Julliard | d757fc6 | 1999-01-31 15:06:28 +0000 | [diff] [blame] | 212 | SetLastError( head.type ); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 213 | return head.type; /* error code */ |
| 214 | } |
| 215 | |
| 216 | |
| 217 | /*********************************************************************** |
| 218 | * CLIENT_WaitReply |
| 219 | * |
| 220 | * Wait for a reply from the server. |
| 221 | */ |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 222 | unsigned int CLIENT_WaitReply( int *len, int *passed_fd, |
| 223 | int n, ... /* arg_1, len_1, etc. */ ) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 224 | { |
| 225 | struct iovec vec[16]; |
| 226 | va_list args; |
| 227 | int i; |
| 228 | |
| 229 | n++; /* for vec[0] */ |
| 230 | assert( n < 16 ); |
| 231 | va_start( args, n ); |
| 232 | for (i = 1; i < n; i++) |
| 233 | { |
| 234 | vec[i].iov_base = va_arg( args, void * ); |
| 235 | vec[i].iov_len = va_arg( args, int ); |
| 236 | } |
| 237 | va_end( args ); |
| 238 | return CLIENT_WaitReply_v( len, passed_fd, vec, n ); |
| 239 | } |
| 240 | |
| 241 | |
| 242 | /*********************************************************************** |
Alexandre Julliard | 6ebbe3c | 1999-01-01 17:04:00 +0000 | [diff] [blame] | 243 | * CLIENT_WaitSimpleReply |
| 244 | * |
| 245 | * Wait for a simple fixed-length reply from the server. |
| 246 | */ |
| 247 | unsigned int CLIENT_WaitSimpleReply( void *reply, int len, int *passed_fd ) |
| 248 | { |
| 249 | struct iovec vec[2]; |
| 250 | unsigned int ret; |
| 251 | int got; |
| 252 | |
| 253 | vec[1].iov_base = reply; |
| 254 | vec[1].iov_len = len; |
| 255 | ret = CLIENT_WaitReply_v( &got, passed_fd, vec, 2 ); |
| 256 | if (got != len) |
| 257 | CLIENT_ProtocolError( "WaitSimpleReply: len %d != %d\n", len, got ); |
| 258 | return ret; |
| 259 | } |
| 260 | |
| 261 | |
| 262 | /*********************************************************************** |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 263 | * CLIENT_NewThread |
| 264 | * |
| 265 | * Send a new thread request. |
| 266 | */ |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 267 | int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle ) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 268 | { |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 269 | struct new_thread_request request; |
| 270 | struct new_thread_reply reply; |
Alexandre Julliard | 6ebbe3c | 1999-01-01 17:04:00 +0000 | [diff] [blame] | 271 | int fd[2]; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 272 | extern BOOL32 THREAD_InitDone; |
Alexandre Julliard | c6e45ed | 1998-12-27 08:35:39 +0000 | [diff] [blame] | 273 | extern void server_init( int fd ); |
| 274 | extern void select_loop(void); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 275 | |
| 276 | if (!THREAD_InitDone) /* first thread -> start the server */ |
| 277 | { |
| 278 | int tmpfd[2]; |
| 279 | char buffer[16]; |
| 280 | |
Alexandre Julliard | 829fe32 | 1998-07-26 14:27:39 +0000 | [diff] [blame] | 281 | if (socketpair( AF_UNIX, SOCK_STREAM, 0, tmpfd ) == -1) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 282 | { |
| 283 | perror("socketpair"); |
| 284 | exit(1); |
| 285 | } |
| 286 | switch(fork()) |
| 287 | { |
| 288 | case -1: /* error */ |
| 289 | perror("fork"); |
| 290 | exit(1); |
| 291 | case 0: /* child */ |
| 292 | close( tmpfd[0] ); |
| 293 | sprintf( buffer, "%d", tmpfd[1] ); |
Alexandre Julliard | 47b3f32 | 1999-01-26 13:29:00 +0000 | [diff] [blame] | 294 | /*#define EXEC_SERVER*/ |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 295 | #ifdef EXEC_SERVER |
| 296 | execlp( "wineserver", "wineserver", buffer, NULL ); |
| 297 | execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL ); |
| 298 | execl( "./server/wineserver", "wineserver", buffer, NULL ); |
| 299 | #endif |
Alexandre Julliard | c6e45ed | 1998-12-27 08:35:39 +0000 | [diff] [blame] | 300 | server_init( tmpfd[1] ); |
| 301 | select_loop(); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 302 | exit(0); |
| 303 | default: /* parent */ |
| 304 | close( tmpfd[1] ); |
| 305 | SET_CUR_THREAD( thdb ); |
| 306 | THREAD_InitDone = TRUE; |
| 307 | thdb->socket = tmpfd[0]; |
| 308 | break; |
| 309 | } |
| 310 | } |
| 311 | |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 312 | if (socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) == -1) |
| 313 | { |
| 314 | SetLastError( ERROR_TOO_MANY_OPEN_FILES ); /* FIXME */ |
| 315 | return -1; |
| 316 | } |
| 317 | |
| 318 | request.pid = thdb->process->server_pid; |
| 319 | CLIENT_SendRequest( REQ_NEW_THREAD, fd[1], 1, &request, sizeof(request) ); |
Alexandre Julliard | 6ebbe3c | 1999-01-01 17:04:00 +0000 | [diff] [blame] | 320 | if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error; |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 321 | thdb->server_tid = reply.tid; |
| 322 | thdb->process->server_pid = reply.pid; |
| 323 | if (thdb->socket != -1) close( thdb->socket ); |
| 324 | thdb->socket = fd[0]; |
| 325 | thdb->seq = 0; /* reset the sequence number for the new fd */ |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 326 | fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */ |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 327 | |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 328 | if (thandle) *thandle = reply.thandle; |
| 329 | else if (reply.thandle != -1) CLIENT_CloseHandle( reply.thandle ); |
| 330 | if (phandle) *phandle = reply.phandle; |
| 331 | else if (reply.phandle != -1) CLIENT_CloseHandle( reply.phandle ); |
| 332 | return 0; |
| 333 | |
| 334 | error: |
| 335 | close( fd[0] ); |
| 336 | return -1; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 337 | } |
| 338 | |
| 339 | |
| 340 | /*********************************************************************** |
| 341 | * CLIENT_InitThread |
| 342 | * |
| 343 | * Send an init thread request. Return 0 if OK. |
| 344 | */ |
| 345 | int CLIENT_InitThread(void) |
| 346 | { |
| 347 | THDB *thdb = THREAD_Current(); |
| 348 | struct init_thread_request init; |
| 349 | int len = strlen( thdb->process->env_db->cmd_line ); |
| 350 | |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 351 | init.unix_pid = getpid(); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 352 | len = MIN( len, MAX_MSG_LENGTH - sizeof(init) ); |
| 353 | |
| 354 | CLIENT_SendRequest( REQ_INIT_THREAD, -1, 2, |
| 355 | &init, sizeof(init), |
| 356 | thdb->process->env_db->cmd_line, len ); |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 357 | return CLIENT_WaitReply( NULL, NULL, 0 ); |
| 358 | } |
| 359 | |
| 360 | |
| 361 | /*********************************************************************** |
Alexandre Julliard | 338e757 | 1998-12-27 15:28:54 +0000 | [diff] [blame] | 362 | * CLIENT_SetDebug |
| 363 | * |
| 364 | * Send a set debug level request. Return 0 if OK. |
| 365 | */ |
| 366 | int CLIENT_SetDebug( int level ) |
| 367 | { |
| 368 | CLIENT_SendRequest( REQ_SET_DEBUG, -1, 1, &level, sizeof(level) ); |
| 369 | return CLIENT_WaitReply( NULL, NULL, 0 ); |
| 370 | } |
| 371 | |
| 372 | /*********************************************************************** |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 373 | * CLIENT_CloseHandle |
| 374 | * |
| 375 | * Send a close handle request. Return 0 if OK. |
| 376 | */ |
| 377 | int CLIENT_CloseHandle( int handle ) |
| 378 | { |
| 379 | CLIENT_SendRequest( REQ_CLOSE_HANDLE, -1, 1, &handle, sizeof(handle) ); |
| 380 | return CLIENT_WaitReply( NULL, NULL, 0 ); |
| 381 | } |
| 382 | |
| 383 | /*********************************************************************** |
| 384 | * CLIENT_DuplicateHandle |
| 385 | * |
| 386 | * Send a duplicate handle request. Return 0 if OK. |
| 387 | */ |
| 388 | int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process, int dst_handle, |
| 389 | DWORD access, BOOL32 inherit, DWORD options ) |
| 390 | { |
| 391 | struct dup_handle_request req; |
| 392 | struct dup_handle_reply reply; |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 393 | |
| 394 | req.src_process = src_process; |
| 395 | req.src_handle = src_handle; |
| 396 | req.dst_process = dst_process; |
| 397 | req.dst_handle = dst_handle; |
| 398 | req.access = access; |
| 399 | req.inherit = inherit; |
| 400 | req.options = options; |
| 401 | |
| 402 | CLIENT_SendRequest( REQ_DUP_HANDLE, -1, 1, &req, sizeof(req) ); |
Alexandre Julliard | 6ebbe3c | 1999-01-01 17:04:00 +0000 | [diff] [blame] | 403 | CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 404 | return reply.handle; |
| 405 | } |
| 406 | |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 407 | |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 408 | /*********************************************************************** |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 409 | * CLIENT_OpenProcess |
| 410 | * |
| 411 | * Open a handle to a process. |
| 412 | */ |
| 413 | int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit ) |
| 414 | { |
| 415 | struct open_process_request req; |
| 416 | struct open_process_reply reply; |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 417 | |
| 418 | req.pid = pid; |
| 419 | req.access = access; |
| 420 | req.inherit = inherit; |
| 421 | |
| 422 | CLIENT_SendRequest( REQ_OPEN_PROCESS, -1, 1, &req, sizeof(req) ); |
Alexandre Julliard | 6ebbe3c | 1999-01-01 17:04:00 +0000 | [diff] [blame] | 423 | CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); |
Alexandre Julliard | 767e6f6 | 1998-08-09 12:47:43 +0000 | [diff] [blame] | 424 | return reply.handle; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 425 | } |