45#include "blocxx/BLOCXX_config.h"
51#ifdef BLOCXX_HAVE_SYS_SOCKET_H
52#include <sys/socket.h>
57#include "blocxx/WinProcessUtils.hpp"
65 char const MAGIC_CHAR =
'\xa5';
67 AutoDescriptor copy_error(
char * dst,
size_t dstsz,
char const * src)
69 std::strncpy(dst, src, dstsz);
70 dst[dstsz - 1] =
'\0';
85 DWORD targetProcessId = WinUtils::getProcessIdNT(targetProcessHd);
88 HANDLE dupDescriptor = INVALID_HANDLE_VALUE;
89 HANDLE hProcess = targetProcessId == 0 ? GetCurrentProcess() : OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcessId);
91 BOOL fSuccess = DuplicateHandle(GetCurrentProcess(), descriptor,
92 hProcess, &dupDescriptor, 0,
93 FALSE, DUPLICATE_SAME_ACCESS);
95 CloseHandle(hProcess);
103 ZeroMemory(&ovl,
sizeof(OVERLAPPED));
105 fSuccess = WriteFile(streamPipe, &dupDescriptor,
sizeof(
long), &rc, &ovl);
109 DWORD lastError = GetLastError();
111 if (lastError != ERROR_IO_INCOMPLETE && lastError != ERROR_IO_PENDING)
113 SetLastError(lastError);
118 DWORD waitFlag = WaitForSingleObject(streamPipe, INFINITE);
120 if (waitFlag == WAIT_OBJECT_0)
122 GetOverlappedResult(streamPipe, &ovl, &rc, FALSE);
138 BOOL bSuccess = FALSE;
143 ZeroMemory(&ovl,
sizeof(OVERLAPPED));
145 bSuccess = ReadFile(streamPipe, &desc,
sizeof(
long), &rc, &ovl);
149 DWORD lastError = GetLastError();
151 if (lastError != ERROR_IO_INCOMPLETE && lastError != ERROR_IO_PENDING)
153 SetLastError(lastError);
154 return copy_error(errbuf, bufsz,
"ReadFile() failed");
158 DWORD waitFlag = WaitForSingleObject(streamPipe, INFINITE);
160 if (waitFlag == WAIT_OBJECT_0)
162 GetOverlappedResult(streamPipe, &ovl, &rc, FALSE);
166 return copy_error(errbuf, bufsz,
"WaitForSingleObject() failed");
174 return copy_error(errbuf, bufsz,
"receiveDescriptor() error");
182 ::memset(&msg, 0,
sizeof(msg));
184 ::memset(iov, 0,
sizeof(iov[0]));
186#ifdef BLOCXX_HAVE_MSGHDR_MSG_CONTROL
192#define CMSG_LEN(size) (sizeof(struct cmsghdr) + (size))
196#define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size))
201 char control[CMSG_SPACE(
sizeof(
int))];
203 ::memset(&control_un, 0,
sizeof(control_un));
204 struct cmsghdr * cmptr;
206 msg.msg_control = control_un.control;
207 msg.msg_controllen =
sizeof(control_un.control);
209 cmptr = CMSG_FIRSTHDR(&msg);
210 cmptr->cmsg_len = CMSG_LEN(
sizeof(
int));
211 cmptr->cmsg_level = SOL_SOCKET;
212 cmptr->cmsg_type = SCM_RIGHTS;
213 *(
reinterpret_cast<int *
>(CMSG_DATA(cmptr))) = descriptor;
217 void *temp_cast = &descriptor;
218 msg.msg_accrights =
static_cast<caddr_t
>(temp_cast);
220 msg.msg_accrights =
static_cast<caddr_t
>(&descriptor);
223 msg.msg_accrightslen =
sizeof(int);
229 char dummy[1] = { MAGIC_CHAR };
230 iov[0].iov_base = dummy;
235 return ::sendmsg(streamPipe, &msg, 0);
244#ifdef BLOCXX_HAVE_MSGHDR_MSG_CONTROL
247 char control[CMSG_SPACE(
sizeof(
int))];
250 msg.msg_control = control_un.control;
251 msg.msg_controllen =
sizeof(control_un.control);
256 void *temp_cast = &newfd;
257 msg.msg_accrights =
static_cast<caddr_t
>(temp_cast);
259 msg.msg_accrights =
static_cast<caddr_t
>(&newfd);
262 msg.msg_accrightslen =
sizeof(int);
268 char dummy[1] = {
'\x7F' };
269 iov[0].iov_base = dummy;
274 ssize_t n = ::recvmsg(streamPipe, &msg, 0);
277 return copy_error(errbuf, bufsz,
278 "unexpected end of input when receiving handle");
282 return copy_error(errbuf, bufsz,
"recvmsg() failed");
286 return copy_error(errbuf, bufsz,
"received more than 1 byte.");
288 if (dummy[0] != MAGIC_CHAR)
290 return copy_error(errbuf, bufsz,
"bad magic char when receiving handle");
294#ifdef BLOCXX_HAVE_MSGHDR_MSG_CONTROL
295 struct cmsghdr * cmptr = CMSG_FIRSTHDR(&msg);
298 return copy_error(errbuf, bufsz,
299 "missing control message when receiving handle");
302#if !defined (BLOCXX_HPUX)
303 if (cmptr->cmsg_len != CMSG_LEN(
sizeof(
int)))
305 return copy_error(errbuf, bufsz,
306 "cmptr->cmsg_len != CMSG_LEN(sizeof(int)) when receiving handle");
309 if (cmptr->cmsg_level != SOL_SOCKET)
311 return copy_error(errbuf, bufsz,
312 "control level != SOL_SOCKET when receiving handle");
314 if (cmptr->cmsg_type != SCM_RIGHTS)
316 return copy_error(errbuf, bufsz,
317 "control type != SCM_RIGHTS when receiving handle");
319 return AutoDescriptor(*(
reinterpret_cast<int *
>(CMSG_DATA(cmptr))));
321 if (msg.msg_accrightslen !=
sizeof(
int))
323 return copy_error(errbuf, bufsz,
324 "bad control message when receiving handle");
#define BLOCXX_INVALID_HANDLE
PURPOSE: The AutoResource class template is an analog of std::auto_ptr for managing arbitrary resourc...
AutoDescriptor receiveDescriptor(Descriptor streamPipe)
Gets a Descriptor from the peer.
int passDescriptor(Descriptor streamPipe, Descriptor descriptor, ProcId targetProcessId)
Sends a Descriptor to the peer.
AutoResource< AutoDescriptorPolicy > AutoDescriptor
An analog of std::auto_ptr for descriptors.