Exemplo n.º 1
0
// establish a connection to the specified pipe and returns its handle
// static
HANDLE Client::connectPipe(const wchar_t* pipeName) {
	bool hasErrors = false;
	HANDLE pipe = INVALID_HANDLE_VALUE;
	for (;;) {
		pipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
		if (pipe != INVALID_HANDLE_VALUE) {
			// the pipe is successfully created
			// security check: make sure that we're connecting to the correct server
			ULONG serverPid;
			if (GetNamedPipeServerProcessId(pipe, &serverPid)) {
				// FIXME: check the command line of the server?
				// See this: http://www.codeproject.com/Articles/19685/Get-Process-Info-with-NtQueryInformationProcess
				// Too bad! Undocumented Windows internal API might be needed here. :-(
			}
			break;
		}
		// being busy is not really an error since we just need to wait.
		if (GetLastError() != ERROR_PIPE_BUSY) {
			hasErrors = true; // otherwise, pipe creation fails
			break;
		}
		// All pipe instances are busy, so wait for 2 seconds.
		if (!WaitNamedPipe(pipeName, 2000)) {
			hasErrors = true;
			break;
		}
	}

	if (!hasErrors) {
		// The pipe is connected; change to message-read mode.
		DWORD mode = PIPE_READMODE_MESSAGE;
		if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) {
			hasErrors = true;
		}
	}

	// the pipe is created, but errors happened, destroy it.
	if (hasErrors && pipe != INVALID_HANDLE_VALUE) {
		DisconnectNamedPipe(pipe);
		CloseHandle(pipe);
		pipe = INVALID_HANDLE_VALUE;
	}
	return pipe;
}
Exemplo n.º 2
0
int main(int argc, char **argv)
{
  char result = 0;
  int err = 0;
  struct stat st;
#ifdef _WIN32
  HANDLE fds[3];
  ULONG pid;
  HANDLE hProcess, hServerProcess;
  DWORD dwNumberOfBytesRead;
  CHAR argv0[PATHSZ];
  GetModuleFileName(NULL, argv0, PATHSZ);
  compute_merlinpath(merlin_path, argv0, &st);
#else
  compute_merlinpath(merlin_path, argv[0], &st);
#endif
  if (argc >= 2 && strcmp(argv[1], "server") == 0)
  {
    IPC_SOCKET_TYPE sock;
    ssize_t len;
#ifdef _WIN32
    compute_socketname(socketname, eventname, merlin_path);
#else
    compute_socketname(socketname, &st);
#endif

    sock = connect_and_serve(socketname, eventname, merlin_path);
    len = prepare_args(argbuffer, sizeof(argbuffer), argc-2, argv+2);
#ifdef _WIN32
    hProcess = GetCurrentProcess();
    if (!GetNamedPipeServerProcessId(sock, &pid))
      failwith_perror("GetNamedPipeServerProcessId");
    hServerProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
    if (hServerProcess == INVALID_HANDLE_VALUE)
      failwith_perror("OpenProcess");
    if (!DuplicateHandle(hProcess, GetStdHandle(STD_INPUT_HANDLE), hServerProcess, &fds[0], 0, FALSE, DUPLICATE_SAME_ACCESS))
      failwith_perror("DuplicateHandle(stdin)");
    if (!DuplicateHandle(hProcess, GetStdHandle(STD_OUTPUT_HANDLE), hServerProcess, &fds[1], 0, FALSE, DUPLICATE_SAME_ACCESS))
      failwith_perror("DuplicateHandle(stdout)");
    CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
    if (!DuplicateHandle(hProcess, GetStdHandle(STD_ERROR_HANDLE), hServerProcess, &fds[2], 0, FALSE, DUPLICATE_SAME_ACCESS))
      failwith_perror("DuplicateHandle(stderr)");
#else
    int fds[3] = { STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO };
#endif
    ipc_send(sock, argbuffer, len, fds);

#ifdef _WIN32
    if (ReadFile(sock, &result, 1, &dwNumberOfBytesRead, NULL) && dwNumberOfBytesRead == 1)
      err = 1;
#else
    NO_EINTR(err, read(sock, &result, 1));
#endif
    if (err == 1)
      exit(result);

    unexpected_termination(argc, argv);
  }
  else
  {
    argv[0] = ocamlmerlin_server;
    execvp(merlin_path, argv);
    failwith_perror("execvp(ocamlmerlin-server)");
  }
}