Rizin
unix-like reverse engineering framework and cli tools
pipe.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 #include <assert.h>
23 #include <io.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "handle-inl.h"
29 #include "internal.h"
30 #include "req-inl.h"
31 #include "stream-inl.h"
32 #include "uv-common.h"
33 #include "uv.h"
34 
35 #include <aclapi.h>
36 #include <accctrl.h>
37 
38 /* A zero-size buffer for use by uv_pipe_read */
39 static char uv_zero_[] = "";
40 
41 /* Null uv_buf_t */
42 static const uv_buf_t uv_null_buf_ = { 0, NULL };
43 
44 /* The timeout that the pipe will wait for the remote end to write data when
45  * the local ends wants to shut it down. */
46 static const int64_t eof_timeout = 50; /* ms */
47 
48 static const int default_pending_pipe_instances = 4;
49 
50 /* Pipe prefix */
51 static char pipe_prefix[] = "\\\\?\\pipe";
52 static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
53 
54 /* IPC incoming xfer queue item. */
55 typedef struct {
60 
61 /* IPC frame header flags. */
62 /* clang-format off */
63 enum {
67  /* These are combinations of the flags above. */
70 };
71 /* clang-format on */
72 
73 /* IPC frame header. */
74 typedef struct {
76  uint32_t reserved1; /* Ignored. */
77  uint32_t data_length; /* Must be zero if there is no data. */
78  uint32_t reserved2; /* Must be zero. */
80 
81 /* To implement the IPC protocol correctly, these structures must have exactly
82  * the right size. */
85 
86 /* Coalesced write request. */
87 typedef struct {
88  uv_write_t req; /* Internal heap-allocated write request. */
89  uv_write_t* user_req; /* Pointer to user-specified uv_write_t. */
91 
92 
93 static void eof_timer_init(uv_pipe_t* pipe);
94 static void eof_timer_start(uv_pipe_t* pipe);
95 static void eof_timer_stop(uv_pipe_t* pipe);
96 static void eof_timer_cb(uv_timer_t* timer);
97 static void eof_timer_destroy(uv_pipe_t* pipe);
99 
100 
101 static void uv_unique_pipe_name(char* ptr, char* name, size_t size) {
102  snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId());
103 }
104 
105 
107  uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
108 
109  handle->reqs_pending = 0;
110  handle->handle = INVALID_HANDLE_VALUE;
111  handle->name = NULL;
112  handle->pipe.conn.ipc_remote_pid = 0;
113  handle->pipe.conn.ipc_data_frame.payload_remaining = 0;
114  QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue);
115  handle->pipe.conn.ipc_xfer_queue_length = 0;
116  handle->ipc = ipc;
117  handle->pipe.conn.non_overlapped_writes_tail = NULL;
118 
119  return 0;
120 }
121 
122 
125  handle->read_req.data = handle;
126  handle->pipe.conn.eof_timer = NULL;
127  assert(!(handle->flags & UV_HANDLE_PIPESERVER));
128  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
129  handle->pipe.conn.readfile_thread_handle = NULL;
130  InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
131  }
132 }
133 
134 
135 static HANDLE open_named_pipe(const WCHAR* name, DWORD* duplex_flags) {
136  HANDLE pipeHandle;
137 
138  /*
139  * Assume that we have a duplex pipe first, so attempt to
140  * connect with GENERIC_READ | GENERIC_WRITE.
141  */
142  pipeHandle = CreateFileW(name,
143  GENERIC_READ | GENERIC_WRITE,
144  0,
145  NULL,
146  OPEN_EXISTING,
147  FILE_FLAG_OVERLAPPED,
148  NULL);
149  if (pipeHandle != INVALID_HANDLE_VALUE) {
150  *duplex_flags = UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
151  return pipeHandle;
152  }
153 
154  /*
155  * If the pipe is not duplex CreateFileW fails with
156  * ERROR_ACCESS_DENIED. In that case try to connect
157  * as a read-only or write-only.
158  */
159  if (GetLastError() == ERROR_ACCESS_DENIED) {
160  pipeHandle = CreateFileW(name,
161  GENERIC_READ | FILE_WRITE_ATTRIBUTES,
162  0,
163  NULL,
164  OPEN_EXISTING,
165  FILE_FLAG_OVERLAPPED,
166  NULL);
167 
168  if (pipeHandle != INVALID_HANDLE_VALUE) {
169  *duplex_flags = UV_HANDLE_READABLE;
170  return pipeHandle;
171  }
172  }
173 
174  if (GetLastError() == ERROR_ACCESS_DENIED) {
175  pipeHandle = CreateFileW(name,
176  GENERIC_WRITE | FILE_READ_ATTRIBUTES,
177  0,
178  NULL,
179  OPEN_EXISTING,
180  FILE_FLAG_OVERLAPPED,
181  NULL);
182 
183  if (pipeHandle != INVALID_HANDLE_VALUE) {
184  *duplex_flags = UV_HANDLE_WRITABLE;
185  return pipeHandle;
186  }
187  }
188 
189  return INVALID_HANDLE_VALUE;
190 }
191 
192 
193 static void close_pipe(uv_pipe_t* pipe) {
194  assert(pipe->u.fd == -1 || pipe->u.fd > 2);
195  if (pipe->u.fd == -1)
196  CloseHandle(pipe->handle);
197  else
198  close(pipe->u.fd);
199 
200  pipe->u.fd = -1;
201  pipe->handle = INVALID_HANDLE_VALUE;
202 }
203 
204 
206  char* name, size_t nameSize) {
207  HANDLE pipeHandle;
208  int err;
209  char* ptr = (char*)handle;
210 
211  for (;;) {
212  uv_unique_pipe_name(ptr, name, nameSize);
213 
214  pipeHandle = CreateNamedPipeA(name,
215  access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
216  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,
217  NULL);
218 
219  if (pipeHandle != INVALID_HANDLE_VALUE) {
220  /* No name collisions. We're done. */
221  break;
222  }
223 
224  err = GetLastError();
225  if (err != ERROR_PIPE_BUSY && err != ERROR_ACCESS_DENIED) {
226  goto error;
227  }
228 
229  /* Pipe name collision. Increment the pointer and try again. */
230  ptr++;
231  }
232 
233  if (CreateIoCompletionPort(pipeHandle,
234  loop->iocp,
235  (ULONG_PTR)handle,
236  0) == NULL) {
237  err = GetLastError();
238  goto error;
239  }
240 
242  handle->handle = pipeHandle;
243 
244  return 0;
245 
246  error:
247  if (pipeHandle != INVALID_HANDLE_VALUE)
248  CloseHandle(pipeHandle);
249 
250  return err;
251 }
252 
253 
255  uv_pipe_t* handle,
256  HANDLE pipeHandle,
257  int fd,
258  DWORD duplex_flags) {
259  NTSTATUS nt_status;
260  IO_STATUS_BLOCK io_status;
261  FILE_MODE_INFORMATION mode_info;
262  DWORD mode = PIPE_READMODE_BYTE | PIPE_WAIT;
263  DWORD current_mode = 0;
264  DWORD err = 0;
265 
266  if (handle->flags & UV_HANDLE_PIPESERVER)
267  return UV_EINVAL;
268  if (handle->handle != INVALID_HANDLE_VALUE)
269  return UV_EBUSY;
270 
271  if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
272  err = GetLastError();
273  if (err == ERROR_ACCESS_DENIED) {
274  /*
275  * SetNamedPipeHandleState can fail if the handle doesn't have either
276  * GENERIC_WRITE or FILE_WRITE_ATTRIBUTES.
277  * But if the handle already has the desired wait and blocking modes
278  * we can continue.
279  */
280  if (!GetNamedPipeHandleState(pipeHandle, &current_mode, NULL, NULL,
281  NULL, NULL, 0)) {
282  return -1;
283  } else if (current_mode & PIPE_NOWAIT) {
284  SetLastError(ERROR_ACCESS_DENIED);
285  return -1;
286  }
287  } else {
288  /* If this returns ERROR_INVALID_PARAMETER we probably opened
289  * something that is not a pipe. */
290  if (err == ERROR_INVALID_PARAMETER) {
291  SetLastError(WSAENOTSOCK);
292  }
293  return -1;
294  }
295  }
296 
297  /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */
298  nt_status = pNtQueryInformationFile(pipeHandle,
299  &io_status,
300  &mode_info,
301  sizeof(mode_info),
303  if (nt_status != STATUS_SUCCESS) {
304  return -1;
305  }
306 
307  if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT ||
308  mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) {
309  /* Non-overlapped pipe. */
311  } else {
312  /* Overlapped pipe. Try to associate with IOCP. */
313  if (CreateIoCompletionPort(pipeHandle,
314  loop->iocp,
315  (ULONG_PTR) handle,
316  0) == NULL) {
317  handle->flags |= UV_HANDLE_EMULATE_IOCP;
318  }
319  }
320 
321  handle->handle = pipeHandle;
322  handle->u.fd = fd;
323  handle->flags |= duplex_flags;
324 
325  return 0;
326 }
327 
328 
330  uv_pipe_accept_t* req, BOOL firstInstance) {
331  assert(req->pipeHandle == INVALID_HANDLE_VALUE);
332 
333  req->pipeHandle =
334  CreateNamedPipeW(handle->name,
335  PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC |
336  (firstInstance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0),
337  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
338  PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
339 
340  if (req->pipeHandle == INVALID_HANDLE_VALUE) {
341  return 0;
342  }
343 
344  /* Associate it with IOCP so we can get events. */
345  if (CreateIoCompletionPort(req->pipeHandle,
346  loop->iocp,
347  (ULONG_PTR) handle,
348  0) == NULL) {
349  uv_fatal_error(GetLastError(), "CreateIoCompletionPort");
350  }
351 
352  /* Stash a handle in the server object for use from places such as
353  * getsockname and chmod. As we transfer ownership of these to client
354  * objects, we'll allocate new ones here. */
355  handle->handle = req->pipeHandle;
356 
357  return 1;
358 }
359 
360 
361 static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
362  uv_loop_t* loop;
363  uv_pipe_t* handle;
365 
366  req = (uv_shutdown_t*) parameter;
367  assert(req);
368  handle = (uv_pipe_t*) req->handle;
369  assert(handle);
370  loop = handle->loop;
371  assert(loop);
372 
373  FlushFileBuffers(handle->handle);
374 
375  /* Post completed */
377 
378  return 0;
379 }
380 
381 
383  int err;
384  DWORD result;
386  NTSTATUS nt_status;
387  IO_STATUS_BLOCK io_status;
388  FILE_PIPE_LOCAL_INFORMATION pipe_info;
389  uv__ipc_xfer_queue_item_t* xfer_queue_item;
390 
391  if ((handle->flags & UV_HANDLE_CONNECTION) &&
392  handle->stream.conn.shutdown_req != NULL &&
393  handle->stream.conn.write_reqs_pending == 0) {
394  req = handle->stream.conn.shutdown_req;
395 
396  /* Clear the shutdown_req field so we don't go here again. */
397  handle->stream.conn.shutdown_req = NULL;
398 
399  if (handle->flags & UV_HANDLE_CLOSING) {
401 
402  /* Already closing. Cancel the shutdown. */
403  if (req->cb) {
404  req->cb(req, UV_ECANCELED);
405  }
406 
408  return;
409  }
410 
411  /* Try to avoid flushing the pipe buffer in the thread pool. */
412  nt_status = pNtQueryInformationFile(handle->handle,
413  &io_status,
414  &pipe_info,
415  sizeof pipe_info,
417 
418  if (nt_status != STATUS_SUCCESS) {
419  /* Failure */
421 
422  handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
423  if (req->cb) {
424  err = pRtlNtStatusToDosError(nt_status);
426  }
427 
429  return;
430  }
431 
432  if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
433  /* Short-circuit, no need to call FlushFileBuffers. */
435  return;
436  }
437 
438  /* Run FlushFileBuffers in the thread pool. */
439  result = QueueUserWorkItem(pipe_shutdown_thread_proc,
440  req,
441  WT_EXECUTELONGFUNCTION);
442  if (result) {
443  return;
444 
445  } else {
446  /* Failure. */
448 
449  handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
450  if (req->cb) {
451  err = GetLastError();
453  }
454 
456  return;
457  }
458  }
459 
460  if (handle->flags & UV_HANDLE_CLOSING &&
461  handle->reqs_pending == 0) {
462  assert(!(handle->flags & UV_HANDLE_CLOSED));
463 
464  if (handle->flags & UV_HANDLE_CONNECTION) {
465  /* Free pending sockets */
466  while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
467  QUEUE* q;
468  SOCKET socket;
469 
470  q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
471  QUEUE_REMOVE(q);
472  xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
473 
474  /* Materialize socket and close it */
475  socket = WSASocketW(FROM_PROTOCOL_INFO,
476  FROM_PROTOCOL_INFO,
477  FROM_PROTOCOL_INFO,
478  &xfer_queue_item->xfer_info.socket_info,
479  0,
480  WSA_FLAG_OVERLAPPED);
481  uv__free(xfer_queue_item);
482 
483  if (socket != INVALID_SOCKET)
484  closesocket(socket);
485  }
486  handle->pipe.conn.ipc_xfer_queue_length = 0;
487 
488  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
489  if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
490  UnregisterWait(handle->read_req.wait_handle);
491  handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
492  }
493  if (handle->read_req.event_handle != NULL) {
494  CloseHandle(handle->read_req.event_handle);
495  handle->read_req.event_handle = NULL;
496  }
497  }
498 
500  DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
501  }
502 
503  if (handle->flags & UV_HANDLE_PIPESERVER) {
504  assert(handle->pipe.serv.accept_reqs);
505  uv__free(handle->pipe.serv.accept_reqs);
506  handle->pipe.serv.accept_reqs = NULL;
507  }
508 
510  }
511 }
512 
513 
515  if (handle->flags & UV_HANDLE_BOUND)
516  return;
517  handle->pipe.serv.pending_instances = count;
518  handle->flags |= UV_HANDLE_PIPESERVER;
519 }
520 
521 
522 /* Creates a pipe server. */
523 int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
524  uv_loop_t* loop = handle->loop;
525  int i, err, nameSize;
526  uv_pipe_accept_t* req;
527 
528  if (handle->flags & UV_HANDLE_BOUND) {
529  return UV_EINVAL;
530  }
531 
532  if (!name) {
533  return UV_EINVAL;
534  }
535 
536  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
537  handle->pipe.serv.pending_instances = default_pending_pipe_instances;
538  }
539 
540  handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*)
541  uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);
542  if (!handle->pipe.serv.accept_reqs) {
543  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
544  }
545 
546  for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
547  req = &handle->pipe.serv.accept_reqs[i];
548  UV_REQ_INIT(req, UV_ACCEPT);
549  req->data = handle;
550  req->pipeHandle = INVALID_HANDLE_VALUE;
551  req->next_pending = NULL;
552  }
553 
554  /* Convert name to UTF16. */
555  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
556  handle->name = uv__malloc(nameSize);
557  if (!handle->name) {
558  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
559  }
560 
561  if (!MultiByteToWideChar(CP_UTF8,
562  0,
563  name,
564  -1,
565  handle->name,
566  nameSize / sizeof(WCHAR))) {
567  err = GetLastError();
568  goto error;
569  }
570 
571  /*
572  * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
573  * If this fails then there's already a pipe server for the given pipe name.
574  */
575  if (!pipe_alloc_accept(loop,
576  handle,
577  &handle->pipe.serv.accept_reqs[0],
578  TRUE)) {
579  err = GetLastError();
580  if (err == ERROR_ACCESS_DENIED) {
581  err = WSAEADDRINUSE; /* Translates to UV_EADDRINUSE. */
582  } else if (err == ERROR_PATH_NOT_FOUND || err == ERROR_INVALID_NAME) {
583  err = WSAEACCES; /* Translates to UV_EACCES. */
584  }
585  goto error;
586  }
587 
588  handle->pipe.serv.pending_accepts = NULL;
589  handle->flags |= UV_HANDLE_PIPESERVER;
590  handle->flags |= UV_HANDLE_BOUND;
591 
592  return 0;
593 
594 error:
595  if (handle->name) {
596  uv__free(handle->name);
597  handle->name = NULL;
598  }
599 
600  return uv_translate_sys_error(err);
601 }
602 
603 
604 static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
605  uv_loop_t* loop;
606  uv_pipe_t* handle;
607  uv_connect_t* req;
608  HANDLE pipeHandle = INVALID_HANDLE_VALUE;
609  DWORD duplex_flags;
610 
611  req = (uv_connect_t*) parameter;
612  assert(req);
613  handle = (uv_pipe_t*) req->handle;
614  assert(handle);
615  loop = handle->loop;
616  assert(loop);
617 
618  /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait
619  * for the pipe to become available with WaitNamedPipe. */
620  while (WaitNamedPipeW(handle->name, 30000)) {
621  /* The pipe is now available, try to connect. */
622  pipeHandle = open_named_pipe(handle->name, &duplex_flags);
623  if (pipeHandle != INVALID_HANDLE_VALUE)
624  break;
625 
626  SwitchToThread();
627  }
628 
629  if (pipeHandle != INVALID_HANDLE_VALUE &&
630  !uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) {
632  } else {
633  SET_REQ_ERROR(req, GetLastError());
634  }
635 
636  /* Post completed */
638 
639  return 0;
640 }
641 
642 
644  const char* name, uv_connect_cb cb) {
645  uv_loop_t* loop = handle->loop;
646  int err, nameSize;
647  HANDLE pipeHandle = INVALID_HANDLE_VALUE;
648  DWORD duplex_flags;
649 
650  UV_REQ_INIT(req, UV_CONNECT);
651  req->handle = (uv_stream_t*) handle;
652  req->cb = cb;
653 
654  /* Convert name to UTF16. */
655  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
656  handle->name = uv__malloc(nameSize);
657  if (!handle->name) {
658  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
659  }
660 
661  if (!MultiByteToWideChar(CP_UTF8,
662  0,
663  name,
664  -1,
665  handle->name,
666  nameSize / sizeof(WCHAR))) {
667  err = GetLastError();
668  goto error;
669  }
670 
671  pipeHandle = open_named_pipe(handle->name, &duplex_flags);
672  if (pipeHandle == INVALID_HANDLE_VALUE) {
673  if (GetLastError() == ERROR_PIPE_BUSY) {
674  /* Wait for the server to make a pipe instance available. */
675  if (!QueueUserWorkItem(&pipe_connect_thread_proc,
676  req,
677  WT_EXECUTELONGFUNCTION)) {
678  err = GetLastError();
679  goto error;
680  }
681 
683  handle->reqs_pending++;
684 
685  return;
686  }
687 
688  err = GetLastError();
689  goto error;
690  }
691 
692  assert(pipeHandle != INVALID_HANDLE_VALUE);
693 
695  (uv_pipe_t*) req->handle,
696  pipeHandle,
697  -1,
698  duplex_flags)) {
699  err = GetLastError();
700  goto error;
701  }
702 
705  handle->reqs_pending++;
707  return;
708 
709 error:
710  if (handle->name) {
711  uv__free(handle->name);
712  handle->name = NULL;
713  }
714 
715  if (pipeHandle != INVALID_HANDLE_VALUE) {
716  CloseHandle(pipeHandle);
717  }
718 
719  /* Make this req pending reporting an error. */
722  handle->reqs_pending++;
724  return;
725 }
726 
727 
729  BOOL r;
730 
731  if (!(handle->flags & UV_HANDLE_READ_PENDING))
732  return; /* No pending reads. */
734  return; /* Already cancelled. */
735  if (handle->handle == INVALID_HANDLE_VALUE)
736  return; /* Pipe handle closed. */
737 
738  if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) {
739  /* Cancel asynchronous read. */
740  r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
741  assert(r || GetLastError() == ERROR_NOT_FOUND);
742 
743  } else {
744  /* Cancel synchronous read (which is happening in the thread pool). */
745  HANDLE thread;
746  volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
747 
748  EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock);
749 
750  thread = *thread_ptr;
751  if (thread == NULL) {
752  /* The thread pool thread has not yet reached the point of blocking, we
753  * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */
754  *thread_ptr = INVALID_HANDLE_VALUE;
755 
756  } else {
757  /* Spin until the thread has acknowledged (by setting the thread to
758  * INVALID_HANDLE_VALUE) that it is past the point of blocking. */
759  while (thread != INVALID_HANDLE_VALUE) {
760  r = CancelSynchronousIo(thread);
761  assert(r || GetLastError() == ERROR_NOT_FOUND);
762  SwitchToThread(); /* Yield thread. */
763  thread = *thread_ptr;
764  }
765  }
766 
767  LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock);
768  }
769 
770  /* Set flag to indicate that read has been cancelled. */
772 }
773 
774 
776  handle->flags &= ~UV_HANDLE_READING;
778 
780 }
781 
782 
783 /* Cleans up uv_pipe_t (server or connection) and all resources associated with
784  * it. */
786  int i;
787  HANDLE pipeHandle;
788 
790 
791  if (handle->name) {
792  uv__free(handle->name);
793  handle->name = NULL;
794  }
795 
796  if (handle->flags & UV_HANDLE_PIPESERVER) {
797  for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
798  pipeHandle = handle->pipe.serv.accept_reqs[i].pipeHandle;
799  if (pipeHandle != INVALID_HANDLE_VALUE) {
800  CloseHandle(pipeHandle);
801  handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;
802  }
803  }
804  handle->handle = INVALID_HANDLE_VALUE;
805  }
806 
807  if (handle->flags & UV_HANDLE_CONNECTION) {
808  handle->flags &= ~UV_HANDLE_WRITABLE;
810  }
811 
812  if ((handle->flags & UV_HANDLE_CONNECTION)
813  && handle->handle != INVALID_HANDLE_VALUE)
815 }
816 
817 
819  if (handle->flags & UV_HANDLE_READING) {
820  handle->flags &= ~UV_HANDLE_READING;
822  }
823 
824  if (handle->flags & UV_HANDLE_LISTENING) {
825  handle->flags &= ~UV_HANDLE_LISTENING;
827  }
828 
830 
831  if (handle->reqs_pending == 0) {
833  }
834 
837 }
838 
839 
841  uv_pipe_accept_t* req, BOOL firstInstance) {
843 
844  if (!firstInstance && !pipe_alloc_accept(loop, handle, req, FALSE)) {
845  SET_REQ_ERROR(req, GetLastError());
847  handle->reqs_pending++;
848  return;
849  }
850 
851  assert(req->pipeHandle != INVALID_HANDLE_VALUE);
852 
853  /* Prepare the overlapped structure. */
854  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
855 
856  if (!ConnectNamedPipe(req->pipeHandle, &req->u.io.overlapped) &&
857  GetLastError() != ERROR_IO_PENDING) {
858  if (GetLastError() == ERROR_PIPE_CONNECTED) {
860  } else {
861  CloseHandle(req->pipeHandle);
862  req->pipeHandle = INVALID_HANDLE_VALUE;
863  /* Make this req pending reporting an error. */
864  SET_REQ_ERROR(req, GetLastError());
865  }
867  handle->reqs_pending++;
868  return;
869  }
870 
871  /* Wait for completion via IOCP */
872  handle->reqs_pending++;
873 }
874 
875 
876 int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
877  uv_loop_t* loop = server->loop;
878  uv_pipe_t* pipe_client;
879  uv_pipe_accept_t* req;
880  QUEUE* q;
882  int err;
883 
884  if (server->ipc) {
885  if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) {
886  /* No valid pending sockets. */
887  return WSAEWOULDBLOCK;
888  }
889 
890  q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue);
891  QUEUE_REMOVE(q);
892  server->pipe.conn.ipc_xfer_queue_length--;
893  item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
894 
896  (uv_tcp_t*) client, item->xfer_type, &item->xfer_info);
897  if (err != 0)
898  return err;
899 
900  uv__free(item);
901 
902  } else {
903  pipe_client = (uv_pipe_t*) client;
904 
905  /* Find a connection instance that has been connected, but not yet
906  * accepted. */
907  req = server->pipe.serv.pending_accepts;
908 
909  if (!req) {
910  /* No valid connections found, so we error out. */
911  return WSAEWOULDBLOCK;
912  }
913 
914  /* Initialize the client handle and copy the pipeHandle to the client */
915  uv_pipe_connection_init(pipe_client);
916  pipe_client->handle = req->pipeHandle;
917  pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
918 
919  /* Prepare the req to pick up a new connection */
920  server->pipe.serv.pending_accepts = req->next_pending;
921  req->next_pending = NULL;
922  req->pipeHandle = INVALID_HANDLE_VALUE;
923 
924  server->handle = INVALID_HANDLE_VALUE;
925  if (!(server->flags & UV_HANDLE_CLOSING)) {
926  uv_pipe_queue_accept(loop, server, req, FALSE);
927  }
928  }
929 
930  return 0;
931 }
932 
933 
934 /* Starts listening for connections for the given pipe. */
936  uv_loop_t* loop = handle->loop;
937  int i;
938 
939  if (handle->flags & UV_HANDLE_LISTENING) {
940  handle->stream.serv.connection_cb = cb;
941  }
942 
943  if (!(handle->flags & UV_HANDLE_BOUND)) {
944  return WSAEINVAL;
945  }
946 
947  if (handle->flags & UV_HANDLE_READING) {
948  return WSAEISCONN;
949  }
950 
951  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
952  return ERROR_NOT_SUPPORTED;
953  }
954 
955  if (handle->ipc) {
956  return WSAEINVAL;
957  }
958 
959  handle->flags |= UV_HANDLE_LISTENING;
961  handle->stream.serv.connection_cb = cb;
962 
963  /* First pipe handle should have already been created in uv_pipe_bind */
964  assert(handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);
965 
966  for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
967  uv_pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0);
968  }
969 
970  return 0;
971 }
972 
973 
975  uv_read_t* req = (uv_read_t*) arg;
976  uv_pipe_t* handle = (uv_pipe_t*) req->data;
977  uv_loop_t* loop = handle->loop;
978  volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
979  CRITICAL_SECTION* lock = &handle->pipe.conn.readfile_thread_lock;
980  HANDLE thread;
981  DWORD bytes;
982  DWORD err;
983 
984  assert(req->type == UV_READ);
985  assert(handle->type == UV_NAMED_PIPE);
986 
987  err = 0;
988 
989  /* Create a handle to the current thread. */
990  if (!DuplicateHandle(GetCurrentProcess(),
991  GetCurrentThread(),
992  GetCurrentProcess(),
993  &thread,
994  0,
995  FALSE,
996  DUPLICATE_SAME_ACCESS)) {
997  err = GetLastError();
998  goto out1;
999  }
1000 
1001  /* The lock needs to be held when thread handle is modified. */
1002  EnterCriticalSection(lock);
1003  if (*thread_ptr == INVALID_HANDLE_VALUE) {
1004  /* uv__pipe_interrupt_read() cancelled reading before we got here. */
1005  err = ERROR_OPERATION_ABORTED;
1006  } else {
1007  /* Let main thread know which worker thread is doing the blocking read. */
1008  assert(*thread_ptr == NULL);
1009  *thread_ptr = thread;
1010  }
1011  LeaveCriticalSection(lock);
1012 
1013  if (err)
1014  goto out2;
1015 
1016  /* Block the thread until data is available on the pipe, or the read is
1017  * cancelled. */
1018  if (!ReadFile(handle->handle, &uv_zero_, 0, &bytes, NULL))
1019  err = GetLastError();
1020 
1021  /* Let the main thread know the worker is past the point of blocking. */
1022  assert(thread == *thread_ptr);
1023  *thread_ptr = INVALID_HANDLE_VALUE;
1024 
1025  /* Briefly acquire the mutex. Since the main thread holds the lock while it
1026  * is spinning trying to cancel this thread's I/O, we will block here until
1027  * it stops doing that. */
1028  EnterCriticalSection(lock);
1029  LeaveCriticalSection(lock);
1030 
1031 out2:
1032  /* Close the handle to the current thread. */
1033  CloseHandle(thread);
1034 
1035 out1:
1036  /* Set request status and post a completion record to the IOCP. */
1037  if (err)
1038  SET_REQ_ERROR(req, err);
1039  else
1042 
1043  return 0;
1044 }
1045 
1046 
1047 static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) {
1048  int result;
1049  DWORD bytes;
1050  uv_write_t* req = (uv_write_t*) parameter;
1051  uv_pipe_t* handle = (uv_pipe_t*) req->handle;
1052  uv_loop_t* loop = handle->loop;
1053 
1054  assert(req != NULL);
1055  assert(req->type == UV_WRITE);
1056  assert(handle->type == UV_NAMED_PIPE);
1057  assert(req->write_buffer.base);
1058 
1059  result = WriteFile(handle->handle,
1060  req->write_buffer.base,
1061  req->write_buffer.len,
1062  &bytes,
1063  NULL);
1064 
1065  if (!result) {
1066  SET_REQ_ERROR(req, GetLastError());
1067  }
1068 
1070  return 0;
1071 }
1072 
1073 
1074 static void CALLBACK post_completion_read_wait(void* context, BOOLEAN timed_out) {
1075  uv_read_t* req;
1076  uv_tcp_t* handle;
1077 
1078  req = (uv_read_t*) context;
1079  assert(req != NULL);
1080  handle = (uv_tcp_t*)req->data;
1081  assert(handle != NULL);
1082  assert(!timed_out);
1083 
1084  if (!PostQueuedCompletionStatus(handle->loop->iocp,
1085  req->u.io.overlapped.InternalHigh,
1086  0,
1087  &req->u.io.overlapped)) {
1088  uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
1089  }
1090 }
1091 
1092 
1093 static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out) {
1094  uv_write_t* req;
1095  uv_tcp_t* handle;
1096 
1097  req = (uv_write_t*) context;
1098  assert(req != NULL);
1099  handle = (uv_tcp_t*)req->handle;
1100  assert(handle != NULL);
1101  assert(!timed_out);
1102 
1103  if (!PostQueuedCompletionStatus(handle->loop->iocp,
1104  req->u.io.overlapped.InternalHigh,
1105  0,
1106  &req->u.io.overlapped)) {
1107  uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
1108  }
1109 }
1110 
1111 
1113  uv_read_t* req;
1114  int result;
1115 
1116  assert(handle->flags & UV_HANDLE_READING);
1117  assert(!(handle->flags & UV_HANDLE_READ_PENDING));
1118 
1119  assert(handle->handle != INVALID_HANDLE_VALUE);
1120 
1121  req = &handle->read_req;
1122 
1123  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
1124  handle->pipe.conn.readfile_thread_handle = NULL; /* Reset cancellation. */
1125  if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc,
1126  req,
1127  WT_EXECUTELONGFUNCTION)) {
1128  /* Make this req pending reporting an error. */
1129  SET_REQ_ERROR(req, GetLastError());
1130  goto error;
1131  }
1132  } else {
1133  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
1134  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1135  assert(req->event_handle != NULL);
1136  req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1);
1137  }
1138 
1139  /* Do 0-read */
1140  result = ReadFile(handle->handle,
1141  &uv_zero_,
1142  0,
1143  NULL,
1144  &req->u.io.overlapped);
1145 
1146  if (!result && GetLastError() != ERROR_IO_PENDING) {
1147  /* Make this req pending reporting an error. */
1148  SET_REQ_ERROR(req, GetLastError());
1149  goto error;
1150  }
1151 
1152  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1153  if (req->wait_handle == INVALID_HANDLE_VALUE) {
1154  if (!RegisterWaitForSingleObject(&req->wait_handle,
1155  req->event_handle, post_completion_read_wait, (void*) req,
1156  INFINITE, WT_EXECUTEINWAITTHREAD)) {
1157  SET_REQ_ERROR(req, GetLastError());
1158  goto error;
1159  }
1160  }
1161  }
1162  }
1163 
1164  /* Start the eof timer if there is one */
1166  handle->flags |= UV_HANDLE_READ_PENDING;
1167  handle->reqs_pending++;
1168  return;
1169 
1170 error:
1172  handle->flags |= UV_HANDLE_READ_PENDING;
1173  handle->reqs_pending++;
1174 }
1175 
1176 
1178  uv_alloc_cb alloc_cb,
1179  uv_read_cb read_cb) {
1180  uv_loop_t* loop = handle->loop;
1181 
1182  handle->flags |= UV_HANDLE_READING;
1184  handle->read_cb = read_cb;
1185  handle->alloc_cb = alloc_cb;
1186 
1187  /* If reading was stopped and then started again, there could still be a read
1188  * request pending. */
1189  if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
1190  if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
1191  handle->read_req.event_handle == NULL) {
1192  handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL);
1193  if (handle->read_req.event_handle == NULL) {
1194  uv_fatal_error(GetLastError(), "CreateEvent");
1195  }
1196  }
1198  }
1199 
1200  return 0;
1201 }
1202 
1203 
1205  uv_write_t* req) {
1206  req->next_req = NULL;
1207  if (handle->pipe.conn.non_overlapped_writes_tail) {
1208  req->next_req =
1209  handle->pipe.conn.non_overlapped_writes_tail->next_req;
1210  handle->pipe.conn.non_overlapped_writes_tail->next_req = (uv_req_t*)req;
1211  handle->pipe.conn.non_overlapped_writes_tail = req;
1212  } else {
1213  req->next_req = (uv_req_t*)req;
1214  handle->pipe.conn.non_overlapped_writes_tail = req;
1215  }
1216 }
1217 
1218 
1220  uv_write_t* req;
1221 
1222  if (handle->pipe.conn.non_overlapped_writes_tail) {
1223  req = (uv_write_t*)handle->pipe.conn.non_overlapped_writes_tail->next_req;
1224 
1225  if (req == handle->pipe.conn.non_overlapped_writes_tail) {
1226  handle->pipe.conn.non_overlapped_writes_tail = NULL;
1227  } else {
1228  handle->pipe.conn.non_overlapped_writes_tail->next_req =
1229  req->next_req;
1230  }
1231 
1232  return req;
1233  } else {
1234  /* queue empty */
1235  return NULL;
1236  }
1237 }
1238 
1239 
1242  if (req) {
1243  if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc,
1244  req,
1245  WT_EXECUTELONGFUNCTION)) {
1246  uv_fatal_error(GetLastError(), "QueueUserWorkItem");
1247  }
1248  }
1249 }
1250 
1251 
1253  const uv_buf_t bufs[],
1254  size_t nbufs,
1255  uv_write_t** req_out,
1256  uv_buf_t* write_buf_out) {
1257  /* Pack into a single heap-allocated buffer:
1258  * (a) a uv_write_t structure where libuv stores the actual state.
1259  * (b) a pointer to the original uv_write_t.
1260  * (c) data from all `bufs` entries.
1261  */
1262  char* heap_buffer;
1263  size_t heap_buffer_length, heap_buffer_offset;
1264  uv__coalesced_write_t* coalesced_write_req; /* (a) + (b) */
1265  char* data_start; /* (c) */
1266  size_t data_length;
1267  unsigned int i;
1268 
1269  /* Compute combined size of all combined buffers from `bufs`. */
1270  data_length = 0;
1271  for (i = 0; i < nbufs; i++)
1272  data_length += bufs[i].len;
1273 
1274  /* The total combined size of data buffers should not exceed UINT32_MAX,
1275  * because WriteFile() won't accept buffers larger than that. */
1276  if (data_length > UINT32_MAX)
1277  return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
1278 
1279  /* Compute heap buffer size. */
1280  heap_buffer_length = sizeof *coalesced_write_req + /* (a) + (b) */
1281  data_length; /* (c) */
1282 
1283  /* Allocate buffer. */
1284  heap_buffer = uv__malloc(heap_buffer_length);
1285  if (heap_buffer == NULL)
1286  return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
1287 
1288  /* Copy uv_write_t information to the buffer. */
1289  coalesced_write_req = (uv__coalesced_write_t*) heap_buffer;
1290  coalesced_write_req->req = *user_req; /* copy (a) */
1291  coalesced_write_req->req.coalesced = 1;
1292  coalesced_write_req->user_req = user_req; /* copy (b) */
1293  heap_buffer_offset = sizeof *coalesced_write_req; /* offset (a) + (b) */
1294 
1295  /* Copy data buffers to the heap buffer. */
1296  data_start = &heap_buffer[heap_buffer_offset];
1297  for (i = 0; i < nbufs; i++) {
1298  memcpy(&heap_buffer[heap_buffer_offset],
1299  bufs[i].base,
1300  bufs[i].len); /* copy (c) */
1301  heap_buffer_offset += bufs[i].len; /* offset (c) */
1302  }
1303  assert(heap_buffer_offset == heap_buffer_length);
1304 
1305  /* Set out arguments and return. */
1306  *req_out = &coalesced_write_req->req;
1307  *write_buf_out = uv_buf_init(data_start, (unsigned int) data_length);
1308  return 0;
1309 }
1310 
1311 
1313  uv_write_t* req,
1314  uv_pipe_t* handle,
1315  const uv_buf_t bufs[],
1316  size_t nbufs,
1317  uv_write_cb cb,
1318  int copy_always) {
1319  int err;
1320  int result;
1321  uv_buf_t write_buf;
1322 
1323  assert(handle->handle != INVALID_HANDLE_VALUE);
1324 
1325  UV_REQ_INIT(req, UV_WRITE);
1326  req->handle = (uv_stream_t*) handle;
1327  req->send_handle = NULL;
1328  req->cb = cb;
1329  /* Private fields. */
1330  req->coalesced = 0;
1331  req->event_handle = NULL;
1332  req->wait_handle = INVALID_HANDLE_VALUE;
1333 
1334  /* Prepare the overlapped structure. */
1335  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
1337  req->event_handle = CreateEvent(NULL, 0, 0, NULL);
1338  if (req->event_handle == NULL) {
1339  uv_fatal_error(GetLastError(), "CreateEvent");
1340  }
1341  req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1);
1342  }
1343  req->write_buffer = uv_null_buf_;
1344 
1345  if (nbufs == 0) {
1346  /* Write empty buffer. */
1347  write_buf = uv_null_buf_;
1348  } else if (nbufs == 1 && !copy_always) {
1349  /* Write directly from bufs[0]. */
1350  write_buf = bufs[0];
1351  } else {
1352  /* Coalesce all `bufs` into one big buffer. This also creates a new
1353  * write-request structure that replaces the old one. */
1354  err = uv__build_coalesced_write_req(req, bufs, nbufs, &req, &write_buf);
1355  if (err != 0)
1356  return err;
1357  }
1358 
1359  if ((handle->flags &
1362  DWORD bytes;
1363  result =
1364  WriteFile(handle->handle, write_buf.base, write_buf.len, &bytes, NULL);
1365 
1366  if (!result) {
1367  err = GetLastError();
1368  return err;
1369  } else {
1370  /* Request completed immediately. */
1371  req->u.io.queued_bytes = 0;
1372  }
1373 
1375  handle->reqs_pending++;
1376  handle->stream.conn.write_reqs_pending++;
1378  return 0;
1379  } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
1380  req->write_buffer = write_buf;
1382  if (handle->stream.conn.write_reqs_pending == 0) {
1384  }
1385 
1386  /* Request queued by the kernel. */
1387  req->u.io.queued_bytes = write_buf.len;
1388  handle->write_queue_size += req->u.io.queued_bytes;
1389  } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) {
1390  /* Using overlapped IO, but wait for completion before returning */
1391  result = WriteFile(handle->handle,
1392  write_buf.base,
1393  write_buf.len,
1394  NULL,
1395  &req->u.io.overlapped);
1396 
1397  if (!result && GetLastError() != ERROR_IO_PENDING) {
1398  err = GetLastError();
1399  CloseHandle(req->event_handle);
1400  req->event_handle = NULL;
1401  return err;
1402  }
1403 
1404  if (result) {
1405  /* Request completed immediately. */
1406  req->u.io.queued_bytes = 0;
1407  } else {
1408  /* Request queued by the kernel. */
1409  req->u.io.queued_bytes = write_buf.len;
1410  handle->write_queue_size += req->u.io.queued_bytes;
1411  if (WaitForSingleObject(req->event_handle, INFINITE) !=
1412  WAIT_OBJECT_0) {
1413  err = GetLastError();
1414  CloseHandle(req->event_handle);
1415  req->event_handle = NULL;
1416  return err;
1417  }
1418  }
1419  CloseHandle(req->event_handle);
1420  req->event_handle = NULL;
1421 
1423  handle->reqs_pending++;
1424  handle->stream.conn.write_reqs_pending++;
1425  return 0;
1426  } else {
1427  result = WriteFile(handle->handle,
1428  write_buf.base,
1429  write_buf.len,
1430  NULL,
1431  &req->u.io.overlapped);
1432 
1433  if (!result && GetLastError() != ERROR_IO_PENDING) {
1434  return GetLastError();
1435  }
1436 
1437  if (result) {
1438  /* Request completed immediately. */
1439  req->u.io.queued_bytes = 0;
1440  } else {
1441  /* Request queued by the kernel. */
1442  req->u.io.queued_bytes = write_buf.len;
1443  handle->write_queue_size += req->u.io.queued_bytes;
1444  }
1445 
1446  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1447  if (!RegisterWaitForSingleObject(&req->wait_handle,
1448  req->event_handle, post_completion_write_wait, (void*) req,
1449  INFINITE, WT_EXECUTEINWAITTHREAD)) {
1450  return GetLastError();
1451  }
1452  }
1453  }
1454 
1456  handle->reqs_pending++;
1457  handle->stream.conn.write_reqs_pending++;
1458 
1459  return 0;
1460 }
1461 
1462 
1464  DWORD* pid = &handle->pipe.conn.ipc_remote_pid;
1465 
1466  /* If the both ends of the IPC pipe are owned by the same process,
1467  * the remote end pid may not yet be set. If so, do it here.
1468  * TODO: this is weird; it'd probably better to use a handshake. */
1469  if (*pid == 0)
1470  *pid = GetCurrentProcessId();
1471 
1472  return *pid;
1473 }
1474 
1475 
1477  uv_write_t* req,
1478  uv_pipe_t* handle,
1479  const uv_buf_t data_bufs[],
1480  size_t data_buf_count,
1481  uv_stream_t* send_handle,
1482  uv_write_cb cb) {
1483  uv_buf_t stack_bufs[6];
1484  uv_buf_t* bufs;
1485  size_t buf_count, buf_index;
1486  uv__ipc_frame_header_t frame_header;
1488  uv__ipc_socket_xfer_info_t xfer_info;
1489  uint64_t data_length;
1490  size_t i;
1491  int err;
1492 
1493  /* Compute the combined size of data buffers. */
1494  data_length = 0;
1495  for (i = 0; i < data_buf_count; i++)
1496  data_length += data_bufs[i].len;
1497  if (data_length > UINT32_MAX)
1498  return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
1499 
1500  /* Prepare the frame's socket xfer payload. */
1501  if (send_handle != NULL) {
1502  uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle;
1503 
1504  /* Verify that `send_handle` it is indeed a tcp handle. */
1505  if (send_tcp_handle->type != UV_TCP)
1506  return ERROR_NOT_SUPPORTED;
1507 
1508  /* Export the tcp handle. */
1509  err = uv__tcp_xfer_export(send_tcp_handle,
1511  &xfer_type,
1512  &xfer_info);
1513  if (err != 0)
1514  return err;
1515  }
1516 
1517  /* Compute the number of uv_buf_t's required. */
1518  buf_count = 1 + data_buf_count; /* Frame header and data buffers. */
1519  if (send_handle != NULL)
1520  buf_count += 1; /* One extra for the socket xfer information. */
1521 
1522  /* Use the on-stack buffer array if it is big enough; otherwise allocate
1523  * space for it on the heap. */
1524  if (buf_count < ARRAY_SIZE(stack_bufs)) {
1525  /* Use on-stack buffer array. */
1526  bufs = stack_bufs;
1527  } else {
1528  /* Use heap-allocated buffer array. */
1529  bufs = uv__calloc(buf_count, sizeof(uv_buf_t));
1530  if (bufs == NULL)
1531  return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
1532  }
1533  buf_index = 0;
1534 
1535  /* Initialize frame header and add it to the buffers list. */
1536  memset(&frame_header, 0, sizeof frame_header);
1537  bufs[buf_index++] = uv_buf_init((char*) &frame_header, sizeof frame_header);
1538 
1539  if (send_handle != NULL) {
1540  /* Add frame header flags. */
1541  switch (xfer_type) {
1543  frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER |
1545  break;
1547  frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER;
1548  break;
1549  default:
1550  assert(0); /* Unreachable. */
1551  }
1552  /* Add xfer info buffer. */
1553  bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info);
1554  }
1555 
1556  if (data_length > 0) {
1557  /* Update frame header. */
1558  frame_header.flags |= UV__IPC_FRAME_HAS_DATA;
1559  frame_header.data_length = (uint32_t) data_length;
1560  /* Add data buffers to buffers list. */
1561  for (i = 0; i < data_buf_count; i++)
1562  bufs[buf_index++] = data_bufs[i];
1563  }
1564 
1565  /* Write buffers. We set the `always_copy` flag, so it is not a problem that
1566  * some of the written data lives on the stack. */
1567  err = uv__pipe_write_data(loop, req, handle, bufs, buf_count, cb, 1);
1568 
1569  /* If we had to heap-allocate the bufs array, free it now. */
1570  if (bufs != stack_bufs) {
1571  uv__free(bufs);
1572  }
1573 
1574  return err;
1575 }
1576 
1577 
1579  uv_write_t* req,
1580  uv_pipe_t* handle,
1581  const uv_buf_t bufs[],
1582  size_t nbufs,
1583  uv_stream_t* send_handle,
1584  uv_write_cb cb) {
1585  if (handle->ipc) {
1586  /* IPC pipe write: use framing protocol. */
1587  return uv__pipe_write_ipc(loop, req, handle, bufs, nbufs, send_handle, cb);
1588  } else {
1589  /* Non-IPC pipe write: put data on the wire directly. */
1590  assert(send_handle == NULL);
1591  return uv__pipe_write_data(loop, req, handle, bufs, nbufs, cb, 0);
1592  }
1593 }
1594 
1595 
1597  uv_buf_t buf) {
1598  /* If there is an eof timer running, we don't need it any more, so discard
1599  * it. */
1601 
1602  handle->flags &= ~UV_HANDLE_READABLE;
1604 
1605  handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf);
1606 }
1607 
1608 
1610  uv_buf_t buf) {
1611  /* If there is an eof timer running, we don't need it any more, so discard
1612  * it. */
1614 
1616 
1618 }
1619 
1620 
1622  int error, uv_buf_t buf) {
1623  if (error == ERROR_BROKEN_PIPE) {
1625  } else {
1627  }
1628 }
1629 
1630 
1632  uv_pipe_t* handle,
1633  uv__ipc_socket_xfer_type_t xfer_type,
1634  uv__ipc_socket_xfer_info_t* xfer_info) {
1636 
1637  item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item));
1638  if (item == NULL)
1639  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
1640 
1641  item->xfer_type = xfer_type;
1642  item->xfer_info = *xfer_info;
1643 
1644  QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member);
1645  handle->pipe.conn.ipc_xfer_queue_length++;
1646 }
1647 
1648 
1649 /* Read an exact number of bytes from a pipe. If an error or end-of-file is
1650  * encountered before the requested number of bytes are read, an error is
1651  * returned. */
1653  DWORD bytes_read, bytes_read_now;
1654 
1655  bytes_read = 0;
1656  while (bytes_read < count) {
1657  if (!ReadFile(h,
1658  (char*) buffer + bytes_read,
1659  count - bytes_read,
1660  &bytes_read_now,
1661  NULL)) {
1662  return GetLastError();
1663  }
1664 
1665  bytes_read += bytes_read_now;
1666  }
1667 
1668  assert(bytes_read == count);
1669  return 0;
1670 }
1671 
1672 
1674  uv_pipe_t* handle,
1675  DWORD suggested_bytes,
1676  DWORD max_bytes) {
1677  DWORD bytes_read;
1678  uv_buf_t buf;
1679 
1680  /* Ask the user for a buffer to read data into. */
1681  buf = uv_buf_init(NULL, 0);
1682  handle->alloc_cb((uv_handle_t*) handle, suggested_bytes, &buf);
1683  if (buf.base == NULL || buf.len == 0) {
1684  handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
1685  return 0; /* Break out of read loop. */
1686  }
1687 
1688  /* Ensure we read at most the smaller of:
1689  * (a) the length of the user-allocated buffer.
1690  * (b) the maximum data length as specified by the `max_bytes` argument.
1691  */
1692  if (max_bytes > buf.len)
1693  max_bytes = buf.len;
1694 
1695  /* Read into the user buffer. */
1696  if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) {
1697  uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
1698  return 0; /* Break out of read loop. */
1699  }
1700 
1701  /* Call the read callback. */
1702  handle->read_cb((uv_stream_t*) handle, bytes_read, &buf);
1703 
1704  return bytes_read;
1705 }
1706 
1707 
1709  uint32_t* data_remaining = &handle->pipe.conn.ipc_data_frame.payload_remaining;
1710  int err;
1711 
1712  if (*data_remaining > 0) {
1713  /* Read frame data payload. */
1714  DWORD bytes_read =
1715  uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining);
1716  *data_remaining -= bytes_read;
1717  return bytes_read;
1718 
1719  } else {
1720  /* Start of a new IPC frame. */
1721  uv__ipc_frame_header_t frame_header;
1722  uint32_t xfer_flags;
1723  uv__ipc_socket_xfer_type_t xfer_type;
1724  uv__ipc_socket_xfer_info_t xfer_info;
1725 
1726  /* Read the IPC frame header. */
1728  handle->handle, &frame_header, sizeof frame_header);
1729  if (err)
1730  goto error;
1731 
1732  /* Validate that flags are valid. */
1733  if ((frame_header.flags & ~UV__IPC_FRAME_VALID_FLAGS) != 0)
1734  goto invalid;
1735  /* Validate that reserved2 is zero. */
1736  if (frame_header.reserved2 != 0)
1737  goto invalid;
1738 
1739  /* Parse xfer flags. */
1740  xfer_flags = frame_header.flags & UV__IPC_FRAME_XFER_FLAGS;
1741  if (xfer_flags & UV__IPC_FRAME_HAS_SOCKET_XFER) {
1742  /* Socket coming -- determine the type. */
1743  xfer_type = xfer_flags & UV__IPC_FRAME_XFER_IS_TCP_CONNECTION
1746  } else if (xfer_flags == 0) {
1747  /* No socket. */
1748  xfer_type = UV__IPC_SOCKET_XFER_NONE;
1749  } else {
1750  /* Invalid flags. */
1751  goto invalid;
1752  }
1753 
1754  /* Parse data frame information. */
1755  if (frame_header.flags & UV__IPC_FRAME_HAS_DATA) {
1756  *data_remaining = frame_header.data_length;
1757  } else if (frame_header.data_length != 0) {
1758  /* Data length greater than zero but data flag not set -- invalid. */
1759  goto invalid;
1760  }
1761 
1762  /* If no socket xfer info follows, return here. Data will be read in a
1763  * subsequent invocation of uv__pipe_read_ipc(). */
1764  if (xfer_type == UV__IPC_SOCKET_XFER_NONE)
1765  return sizeof frame_header; /* Number of bytes read. */
1766 
1767  /* Read transferred socket information. */
1768  err = uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);
1769  if (err)
1770  goto error;
1771 
1772  /* Store the pending socket info. */
1773  uv__pipe_queue_ipc_xfer_info(handle, xfer_type, &xfer_info);
1774 
1775  /* Return number of bytes read. */
1776  return sizeof frame_header + sizeof xfer_info;
1777  }
1778 
1779 invalid:
1780  /* Invalid frame. */
1781  err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
1782 
1783 error:
1785  return 0; /* Break out of read loop. */
1786 }
1787 
1788 
1790  uv_pipe_t* handle,
1791  uv_req_t* req) {
1792  assert(handle->type == UV_NAMED_PIPE);
1793 
1797 
1798  /* At this point, we're done with bookkeeping. If the user has stopped
1799  * reading the pipe in the meantime, there is nothing left to do, since there
1800  * is no callback that we can call. */
1801  if (!(handle->flags & UV_HANDLE_READING))
1802  return;
1803 
1804  if (!REQ_SUCCESS(req)) {
1805  /* An error occurred doing the zero-read. */
1807 
1808  /* If the read was cancelled by uv__pipe_interrupt_read(), the request may
1809  * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to
1810  * the user; we'll start a new zero-read at the end of this function. */
1811  if (err != ERROR_OPERATION_ABORTED)
1813 
1814  } else {
1815  /* The zero-read completed without error, indicating there is data
1816  * available in the kernel buffer. */
1817  DWORD avail;
1818 
1819  /* Get the number of bytes available. */
1820  avail = 0;
1821  if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL))
1823 
1824  /* Read until we've either read all the bytes available, or the 'reading'
1825  * flag is cleared. */
1826  while (avail > 0 && handle->flags & UV_HANDLE_READING) {
1827  /* Depending on the type of pipe, read either IPC frames or raw data. */
1828  DWORD bytes_read =
1830  : uv__pipe_read_data(loop, handle, avail, (DWORD) -1);
1831 
1832  /* If no bytes were read, treat this as an indication that an error
1833  * occurred, and break out of the read loop. */
1834  if (bytes_read == 0)
1835  break;
1836 
1837  /* It is possible that more bytes were read than we thought were
1838  * available. To prevent `avail` from underflowing, break out of the loop
1839  * if this is the case. */
1840  if (bytes_read > avail)
1841  break;
1842 
1843  /* Recompute the number of bytes available. */
1844  avail -= bytes_read;
1845  }
1846  }
1847 
1848  /* Start another zero-read request if necessary. */
1849  if ((handle->flags & UV_HANDLE_READING) &&
1850  !(handle->flags & UV_HANDLE_READ_PENDING)) {
1852  }
1853 }
1854 
1855 
1857  uv_write_t* req) {
1858  int err;
1859 
1860  assert(handle->type == UV_NAMED_PIPE);
1861 
1862  assert(handle->write_queue_size >= req->u.io.queued_bytes);
1863  handle->write_queue_size -= req->u.io.queued_bytes;
1864 
1866 
1867  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
1868  if (req->wait_handle != INVALID_HANDLE_VALUE) {
1869  UnregisterWait(req->wait_handle);
1870  req->wait_handle = INVALID_HANDLE_VALUE;
1871  }
1872  if (req->event_handle) {
1873  CloseHandle(req->event_handle);
1874  req->event_handle = NULL;
1875  }
1876  }
1877 
1878  err = GET_REQ_ERROR(req);
1879 
1880  /* If this was a coalesced write, extract pointer to the user_provided
1881  * uv_write_t structure so we can pass the expected pointer to the callback,
1882  * then free the heap-allocated write req. */
1883  if (req->coalesced) {
1884  uv__coalesced_write_t* coalesced_write =
1886  req = coalesced_write->user_req;
1887  uv__free(coalesced_write);
1888  }
1889  if (req->cb) {
1891  }
1892 
1893  handle->stream.conn.write_reqs_pending--;
1894 
1895  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE &&
1896  handle->pipe.conn.non_overlapped_writes_tail) {
1897  assert(handle->stream.conn.write_reqs_pending > 0);
1899  }
1900 
1901  if (handle->stream.conn.shutdown_req != NULL &&
1902  handle->stream.conn.write_reqs_pending == 0) {
1904  }
1905 
1907 }
1908 
1909 
1911  uv_req_t* raw_req) {
1912  uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req;
1913 
1914  assert(handle->type == UV_NAMED_PIPE);
1915 
1916  if (handle->flags & UV_HANDLE_CLOSING) {
1917  /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */
1918  assert(req->pipeHandle == INVALID_HANDLE_VALUE);
1920  return;
1921  }
1922 
1923  if (REQ_SUCCESS(req)) {
1924  assert(req->pipeHandle != INVALID_HANDLE_VALUE);
1925  req->next_pending = handle->pipe.serv.pending_accepts;
1926  handle->pipe.serv.pending_accepts = req;
1927 
1928  if (handle->stream.serv.connection_cb) {
1929  handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
1930  }
1931  } else {
1932  if (req->pipeHandle != INVALID_HANDLE_VALUE) {
1933  CloseHandle(req->pipeHandle);
1934  req->pipeHandle = INVALID_HANDLE_VALUE;
1935  }
1936  if (!(handle->flags & UV_HANDLE_CLOSING)) {
1938  }
1939  }
1940 
1942 }
1943 
1944 
1946  uv_connect_t* req) {
1947  int err;
1948 
1949  assert(handle->type == UV_NAMED_PIPE);
1950 
1952 
1953  if (req->cb) {
1954  err = 0;
1955  if (REQ_SUCCESS(req)) {
1957  } else {
1958  err = GET_REQ_ERROR(req);
1959  }
1961  }
1962 
1964 }
1965 
1966 
1968  uv_shutdown_t* req) {
1969  assert(handle->type == UV_NAMED_PIPE);
1970 
1972 
1973  if (handle->flags & UV_HANDLE_READABLE) {
1974  /* Initialize and optionally start the eof timer. Only do this if the pipe
1975  * is readable and we haven't seen EOF come in ourselves. */
1977 
1978  /* If reading start the timer right now. Otherwise uv_pipe_queue_read will
1979  * start it. */
1980  if (handle->flags & UV_HANDLE_READ_PENDING) {
1982  }
1983 
1984  } else {
1985  /* This pipe is not readable. We can just close it to let the other end
1986  * know that we're done writing. */
1987  close_pipe(handle);
1988  }
1989 
1990  if (req->cb) {
1991  req->cb(req, 0);
1992  }
1993 
1995 }
1996 
1997 
1999  int r;
2000 
2001  assert(pipe->pipe.conn.eof_timer == NULL);
2002  assert(pipe->flags & UV_HANDLE_CONNECTION);
2003 
2004  pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer);
2005 
2006  r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer);
2007  assert(r == 0); /* timers can't fail */
2008  pipe->pipe.conn.eof_timer->data = pipe;
2009  uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer);
2010 }
2011 
2012 
2014  assert(pipe->flags & UV_HANDLE_CONNECTION);
2015 
2016  if (pipe->pipe.conn.eof_timer != NULL) {
2017  uv_timer_start(pipe->pipe.conn.eof_timer, eof_timer_cb, eof_timeout, 0);
2018  }
2019 }
2020 
2021 
2023  assert(pipe->flags & UV_HANDLE_CONNECTION);
2024 
2025  if (pipe->pipe.conn.eof_timer != NULL) {
2026  uv_timer_stop(pipe->pipe.conn.eof_timer);
2027  }
2028 }
2029 
2030 
2031 static void eof_timer_cb(uv_timer_t* timer) {
2032  uv_pipe_t* pipe = (uv_pipe_t*) timer->data;
2033  uv_loop_t* loop = timer->loop;
2034 
2035  assert(pipe->type == UV_NAMED_PIPE);
2036 
2037  /* This should always be true, since we start the timer only in
2038  * uv_pipe_queue_read after successfully calling ReadFile, or in
2039  * uv_process_pipe_shutdown_req if a read is pending, and we always
2040  * immediately stop the timer in uv_process_pipe_read_req. */
2042 
2043  /* If there are many packets coming off the iocp then the timer callback may
2044  * be called before the read request is coming off the queue. Therefore we
2045  * check here if the read request has completed but will be processed later.
2046  */
2047  if ((pipe->flags & UV_HANDLE_READ_PENDING) &&
2048  HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) {
2049  return;
2050  }
2051 
2052  /* Force both ends off the pipe. */
2053  close_pipe(pipe);
2054 
2055  /* Stop reading, so the pending read that is going to fail will not be
2056  * reported to the user. */
2058 
2059  /* Report the eof and update flags. This will get reported even if the user
2060  * stopped reading in the meantime. TODO: is that okay? */
2062 }
2063 
2064 
2066  assert(pipe->flags & UV_HANDLE_CONNECTION);
2067 
2068  if (pipe->pipe.conn.eof_timer) {
2069  uv_close((uv_handle_t*) pipe->pipe.conn.eof_timer, eof_timer_close_cb);
2070  pipe->pipe.conn.eof_timer = NULL;
2071  }
2072 }
2073 
2074 
2076  assert(handle->type == UV_TIMER);
2077  uv__free(handle);
2078 }
2079 
2080 
2082  HANDLE os_handle = uv__get_osfhandle(file);
2083  NTSTATUS nt_status;
2084  IO_STATUS_BLOCK io_status;
2086  DWORD duplex_flags = 0;
2087 
2088  if (os_handle == INVALID_HANDLE_VALUE)
2089  return UV_EBADF;
2090 
2091  uv__once_init();
2092  /* In order to avoid closing a stdio file descriptor 0-2, duplicate the
2093  * underlying OS handle and forget about the original fd.
2094  * We could also opt to use the original OS handle and just never close it,
2095  * but then there would be no reliable way to cancel pending read operations
2096  * upon close.
2097  */
2098  if (file <= 2) {
2099  if (!DuplicateHandle(INVALID_HANDLE_VALUE,
2100  os_handle,
2102  &os_handle,
2103  0,
2104  FALSE,
2105  DUPLICATE_SAME_ACCESS))
2106  return uv_translate_sys_error(GetLastError());
2107  file = -1;
2108  }
2109 
2110  /* Determine what kind of permissions we have on this handle.
2111  * Cygwin opens the pipe in message mode, but we can support it,
2112  * just query the access flags and set the stream flags accordingly.
2113  */
2114  nt_status = pNtQueryInformationFile(os_handle,
2115  &io_status,
2116  &access,
2117  sizeof(access),
2119  if (nt_status != STATUS_SUCCESS)
2120  return UV_EINVAL;
2121 
2122  if (pipe->ipc) {
2123  if (!(access.AccessFlags & FILE_WRITE_DATA) ||
2124  !(access.AccessFlags & FILE_READ_DATA)) {
2125  return UV_EINVAL;
2126  }
2127  }
2128 
2129  if (access.AccessFlags & FILE_WRITE_DATA)
2130  duplex_flags |= UV_HANDLE_WRITABLE;
2131  if (access.AccessFlags & FILE_READ_DATA)
2132  duplex_flags |= UV_HANDLE_READABLE;
2133 
2134  if (os_handle == INVALID_HANDLE_VALUE ||
2135  uv_set_pipe_handle(pipe->loop,
2136  pipe,
2137  os_handle,
2138  file,
2139  duplex_flags) == -1) {
2140  return UV_EINVAL;
2141  }
2142 
2144 
2145  if (pipe->ipc) {
2147  pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
2148  assert(pipe->pipe.conn.ipc_remote_pid != (DWORD)(uv_pid_t) -1);
2149  }
2150  return 0;
2151 }
2152 
2153 
2154 static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) {
2155  NTSTATUS nt_status;
2156  IO_STATUS_BLOCK io_status;
2157  FILE_NAME_INFORMATION tmp_name_info;
2158  FILE_NAME_INFORMATION* name_info;
2159  WCHAR* name_buf;
2160  unsigned int addrlen;
2161  unsigned int name_size;
2162  unsigned int name_len;
2163  int err;
2164 
2165  uv__once_init();
2166  name_info = NULL;
2167 
2168  if (handle->handle == INVALID_HANDLE_VALUE) {
2169  *size = 0;
2170  return UV_EINVAL;
2171  }
2172 
2173  /* NtQueryInformationFile will block if another thread is performing a
2174  * blocking operation on the queried handle. If the pipe handle is
2175  * synchronous, there may be a worker thread currently calling ReadFile() on
2176  * the pipe handle, which could cause a deadlock. To avoid this, interrupt
2177  * the read. */
2178  if (handle->flags & UV_HANDLE_CONNECTION &&
2180  uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */
2181  }
2182 
2183  nt_status = pNtQueryInformationFile(handle->handle,
2184  &io_status,
2185  &tmp_name_info,
2186  sizeof tmp_name_info,
2188  if (nt_status == STATUS_BUFFER_OVERFLOW) {
2189  name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;
2190  name_info = uv__malloc(name_size);
2191  if (!name_info) {
2192  *size = 0;
2193  err = UV_ENOMEM;
2194  goto cleanup;
2195  }
2196 
2197  nt_status = pNtQueryInformationFile(handle->handle,
2198  &io_status,
2199  name_info,
2200  name_size,
2202  }
2203 
2204  if (nt_status != STATUS_SUCCESS) {
2205  *size = 0;
2207  goto error;
2208  }
2209 
2210  if (!name_info) {
2211  /* the struct on stack was used */
2212  name_buf = tmp_name_info.FileName;
2213  name_len = tmp_name_info.FileNameLength;
2214  } else {
2215  name_buf = name_info->FileName;
2216  name_len = name_info->FileNameLength;
2217  }
2218 
2219  if (name_len == 0) {
2220  *size = 0;
2221  err = 0;
2222  goto error;
2223  }
2224 
2225  name_len /= sizeof(WCHAR);
2226 
2227  /* check how much space we need */
2228  addrlen = WideCharToMultiByte(CP_UTF8,
2229  0,
2230  name_buf,
2231  name_len,
2232  NULL,
2233  0,
2234  NULL,
2235  NULL);
2236  if (!addrlen) {
2237  *size = 0;
2238  err = uv_translate_sys_error(GetLastError());
2239  goto error;
2240  } else if (pipe_prefix_len + addrlen >= *size) {
2241  /* "\\\\.\\pipe" + name */
2242  *size = pipe_prefix_len + addrlen + 1;
2243  err = UV_ENOBUFS;
2244  goto error;
2245  }
2246 
2248  addrlen = WideCharToMultiByte(CP_UTF8,
2249  0,
2250  name_buf,
2251  name_len,
2254  NULL,
2255  NULL);
2256  if (!addrlen) {
2257  *size = 0;
2258  err = uv_translate_sys_error(GetLastError());
2259  goto error;
2260  }
2261 
2263  *size = addrlen;
2264  buffer[addrlen] = '\0';
2265 
2266  err = 0;
2267 
2268 error:
2269  uv__free(name_info);
2270 
2271 cleanup:
2272  return err;
2273 }
2274 
2275 
2277  if (!handle->ipc)
2278  return 0;
2279  return handle->pipe.conn.ipc_xfer_queue_length;
2280 }
2281 
2282 
2283 int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
2284  if (handle->flags & UV_HANDLE_BOUND)
2285  return uv__pipe_getname(handle, buffer, size);
2286 
2287  if (handle->flags & UV_HANDLE_CONNECTION ||
2288  handle->handle != INVALID_HANDLE_VALUE) {
2289  *size = 0;
2290  return 0;
2291  }
2292 
2293  return UV_EBADF;
2294 }
2295 
2296 
2297 int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
2298  /* emulate unix behaviour */
2299  if (handle->flags & UV_HANDLE_BOUND)
2300  return UV_ENOTCONN;
2301 
2302  if (handle->handle != INVALID_HANDLE_VALUE)
2303  return uv__pipe_getname(handle, buffer, size);
2304 
2305  return UV_EBADF;
2306 }
2307 
2308 
2310  if (!handle->ipc)
2311  return UV_UNKNOWN_HANDLE;
2312  if (handle->pipe.conn.ipc_xfer_queue_length == 0)
2313  return UV_UNKNOWN_HANDLE;
2314  else
2315  return UV_TCP;
2316 }
2317 
2319  SID_IDENTIFIER_AUTHORITY sid_world = { SECURITY_WORLD_SID_AUTHORITY };
2320  PACL old_dacl, new_dacl;
2321  PSECURITY_DESCRIPTOR sd;
2322  EXPLICIT_ACCESS ea;
2323  PSID everyone;
2324  int error;
2325 
2326  if (handle == NULL || handle->handle == INVALID_HANDLE_VALUE)
2327  return UV_EBADF;
2328 
2329  if (mode != UV_READABLE &&
2330  mode != UV_WRITABLE &&
2331  mode != (UV_WRITABLE | UV_READABLE))
2332  return UV_EINVAL;
2333 
2334  if (!AllocateAndInitializeSid(&sid_world,
2335  1,
2336  SECURITY_WORLD_RID,
2337  0, 0, 0, 0, 0, 0, 0,
2338  &everyone)) {
2339  error = GetLastError();
2340  goto done;
2341  }
2342 
2343  if (GetSecurityInfo(handle->handle,
2344  SE_KERNEL_OBJECT,
2345  DACL_SECURITY_INFORMATION,
2346  NULL,
2347  NULL,
2348  &old_dacl,
2349  NULL,
2350  &sd)) {
2351  error = GetLastError();
2352  goto clean_sid;
2353  }
2354 
2355  memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
2356  if (mode & UV_READABLE)
2357  ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
2358  if (mode & UV_WRITABLE)
2359  ea.grfAccessPermissions |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
2360  ea.grfAccessPermissions |= SYNCHRONIZE;
2361  ea.grfAccessMode = SET_ACCESS;
2362  ea.grfInheritance = NO_INHERITANCE;
2363  ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
2364  ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
2365  ea.Trustee.ptstrName = (LPTSTR)everyone;
2366 
2367  if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) {
2368  error = GetLastError();
2369  goto clean_sd;
2370  }
2371 
2372  if (SetSecurityInfo(handle->handle,
2373  SE_KERNEL_OBJECT,
2374  DACL_SECURITY_INFORMATION,
2375  NULL,
2376  NULL,
2377  new_dacl,
2378  NULL)) {
2379  error = GetLastError();
2380  goto clean_dacl;
2381  }
2382 
2383  error = 0;
2384 
2385 clean_dacl:
2386  LocalFree((HLOCAL) new_dacl);
2387 clean_sd:
2388  LocalFree((HLOCAL) sd);
2389 clean_sid:
2390  FreeSid(everyone);
2391 done:
2392  return uv_translate_sys_error(error);
2393 }
size_t len
Definition: 6502dis.c:15
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
static ut8 bytes[32]
Definition: asm_arc.c:23
static mcore_handle handle
Definition: asm_mcore.c:8
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec req
Definition: sflib.h:128
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd socket
Definition: sflib.h:79
struct tab * done
Definition: enough.c:233
void cleanup(void)
Definition: enough.c:244
void uv_fatal_error(const int errorno, const char *syscall)
Definition: error.c:35
#define DECREASE_ACTIVE_COUNT(loop, handle)
Definition: handle-inl.h:32
static INLINE void uv_want_endgame(uv_loop_t *loop, uv_handle_t *handle)
Definition: handle-inl.h:88
static INLINE HANDLE uv__get_osfhandle(int fd)
Definition: handle-inl.h:166
#define INCREASE_ACTIVE_COUNT(loop, handle)
Definition: handle-inl.h:42
#define uv__handle_close(handle)
Definition: handle-inl.h:76
#define DECREASE_PENDING_REQ_COUNT(handle)
Definition: handle-inl.h:51
#define uv__handle_closing(handle)
Definition: handle-inl.h:63
voidpf void uLong size
Definition: ioapi.h:138
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
snprintf
Definition: kernel.h:364
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause access
Definition: sflib.h:64
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname pipe
Definition: sflib.h:73
static const void static count static fd struct stat static buf struct pollfd unsigned static timeout void static offset void static length char static len const struct iovec static count unsigned long static filedes static sched_yield static flags static oldfd static pause unsigned static seconds static protocol struct sockaddr addrlen
Definition: sflib.h:75
assert(limit<=UINT32_MAX/2)
#define TRUE
Definition: mybfd.h:103
#define FALSE
Definition: mybfd.h:102
#define QUEUE_DATA(ptr, type, field)
Definition: queue.h:30
#define QUEUE_EMPTY(q)
Definition: queue.h:39
#define QUEUE_HEAD(q)
Definition: queue.h:42
#define QUEUE_INSERT_TAIL(h, q)
Definition: queue.h:92
#define QUEUE_INIT(q)
Definition: queue.h:45
void * QUEUE[2]
Definition: queue.h:21
#define QUEUE_REMOVE(q)
Definition: queue.h:101
#define GET_REQ_ERROR(req)
Definition: req-inl.h:49
static INLINE void uv_insert_pending_req(uv_loop_t *loop, uv_req_t *req)
Definition: req-inl.h:90
#define REQ_SUCCESS(req)
Definition: req-inl.h:46
#define SET_REQ_SUCCESS(req)
Definition: req-inl.h:40
#define UNREGISTER_HANDLE_REQ(loop, handle, req)
Definition: req-inl.h:62
#define REGISTER_HANDLE_REQ(loop, handle, req)
Definition: req-inl.h:56
#define POST_COMPLETION_FOR_REQ(loop, req)
Definition: req-inl.h:76
#define SET_REQ_ERROR(req, error)
Definition: req-inl.h:34
#define container_of(ptr, type, member)
Definition: rz_types.h:650
long int64_t
Definition: sftypes.h:32
unsigned int uint32_t
Definition: sftypes.h:29
unsigned long uint64_t
Definition: sftypes.h:28
#define h(i)
Definition: sha256.c:48
_W64 unsigned int uintptr_t
#define UINT32_MAX
static INLINE void uv_stream_init(uv_loop_t *loop, uv_stream_t *handle, uv_handle_type type)
Definition: stream-inl.h:33
static INLINE void uv_connection_init(uv_stream_t *handle)
Definition: stream-inl.h:49
Definition: buffer.h:15
Definition: gzappend.c:170
Definition: z80asm.h:102
uv_write_t * user_req
Definition: pipe.c:89
uv_write_t req
Definition: pipe.c:88
uint32_t flags
Definition: pipe.c:75
uint32_t reserved2
Definition: pipe.c:78
uint32_t data_length
Definition: pipe.c:77
uint32_t reserved1
Definition: pipe.c:76
WSAPROTOCOL_INFOW socket_info
Definition: internal.h:71
uv__ipc_socket_xfer_info_t xfer_info
Definition: pipe.c:57
uv__ipc_socket_xfer_type_t xfer_type
Definition: pipe.c:56
Definition: unix.h:123
size_t len
Definition: unix.h:125
char * base
Definition: unix.h:124
Definition: uv.h:1780
Definition: uv.h:767
UV_HANDLE_FIELDS UV_STREAM_FIELDS int ipc
Definition: uv.h:770
Definition: uv.h:407
Definition: uv.h:547
Definition: uv.h:860
Definition: uv.h:525
uv_loop_t * loop
Definition: main.c:7
int uv_pipe_bind(uv_pipe_t *handle, const char *name)
Definition: pipe.c:43
uv_handle_type uv_pipe_pending_type(uv_pipe_t *handle)
Definition: pipe.c:315
int uv_pipe_init(uv_loop_t *loop, uv_pipe_t *handle, int ipc)
Definition: pipe.c:33
int uv_pipe_pending_count(uv_pipe_t *handle)
Definition: pipe.c:298
int uv_pipe_listen(uv_pipe_t *handle, int backlog, uv_connection_cb cb)
Definition: pipe.c:94
void uv_pipe_pending_instances(uv_pipe_t *handle, int count)
Definition: pipe.c:294
void uv_pipe_connect(uv_connect_t *req, uv_pipe_t *handle, const char *name, uv_connect_cb cb)
Definition: pipe.c:173
int uv_pipe_chmod(uv_pipe_t *handle, int mode)
Definition: pipe.c:326
int uv_pipe_open(uv_pipe_t *handle, uv_file fd)
Definition: pipe.c:137
int uv_pipe_getpeername(const uv_pipe_t *handle, char *buffer, size_t *size)
Definition: pipe.c:289
int uv_pipe_getsockname(const uv_pipe_t *handle, char *buffer, size_t *size)
Definition: pipe.c:284
void uv__once_init(void)
Definition: core.c:329
int uv__tcp_xfer_import(uv_tcp_t *tcp, uv__ipc_socket_xfer_type_t xfer_type, uv__ipc_socket_xfer_info_t *xfer_info)
Definition: tcp.c:1277
uv__ipc_socket_xfer_type_t
Definition: internal.h:64
@ UV__IPC_SOCKET_XFER_NONE
Definition: internal.h:65
@ UV__IPC_SOCKET_XFER_TCP_CONNECTION
Definition: internal.h:66
@ UV__IPC_SOCKET_XFER_TCP_SERVER
Definition: internal.h:67
int uv__tcp_xfer_export(uv_tcp_t *handle, int pid, uv__ipc_socket_xfer_type_t *xfer_type, uv__ipc_socket_xfer_info_t *xfer_info)
Definition: tcp.c:1242
static void eof_timer_stop(uv_pipe_t *pipe)
Definition: pipe.c:2022
static DWORD WINAPI uv_pipe_writefile_thread_proc(void *parameter)
Definition: pipe.c:1047
void uv_pipe_close(uv_loop_t *loop, uv_pipe_t *handle)
Definition: pipe.c:818
STATIC_ASSERT(sizeof(uv__ipc_frame_header_t)==16)
static void CALLBACK post_completion_write_wait(void *context, BOOLEAN timed_out)
Definition: pipe.c:1093
static const int pipe_prefix_len
Definition: pipe.c:52
int uv_stdio_pipe_server(uv_loop_t *loop, uv_pipe_t *handle, DWORD access, char *name, size_t nameSize)
Definition: pipe.c:205
static int uv__pipe_write_data(uv_loop_t *loop, uv_write_t *req, uv_pipe_t *handle, const uv_buf_t bufs[], size_t nbufs, uv_write_cb cb, int copy_always)
Definition: pipe.c:1312
int uv__pipe_write(uv_loop_t *loop, uv_write_t *req, uv_pipe_t *handle, const uv_buf_t bufs[], size_t nbufs, uv_stream_t *send_handle, uv_write_cb cb)
Definition: pipe.c:1578
void uv_pipe_endgame(uv_loop_t *loop, uv_pipe_t *handle)
Definition: pipe.c:382
static void uv_unique_pipe_name(char *ptr, char *name, size_t size)
Definition: pipe.c:101
static DWORD WINAPI pipe_shutdown_thread_proc(void *parameter)
Definition: pipe.c:361
static void eof_timer_cb(uv_timer_t *timer)
Definition: pipe.c:2031
static void uv_pipe_read_eof(uv_loop_t *loop, uv_pipe_t *handle, uv_buf_t buf)
Definition: pipe.c:1596
static void eof_timer_init(uv_pipe_t *pipe)
Definition: pipe.c:1998
static int uv__pipe_read_exactly(HANDLE h, void *buffer, DWORD count)
Definition: pipe.c:1652
static int uv__build_coalesced_write_req(uv_write_t *user_req, const uv_buf_t bufs[], size_t nbufs, uv_write_t **req_out, uv_buf_t *write_buf_out)
Definition: pipe.c:1252
static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t *handle)
Definition: pipe.c:1463
void uv__pipe_read_stop(uv_pipe_t *handle)
Definition: pipe.c:775
static DWORD uv__pipe_read_data(uv_loop_t *loop, uv_pipe_t *handle, DWORD suggested_bytes, DWORD max_bytes)
Definition: pipe.c:1673
static int uv_set_pipe_handle(uv_loop_t *loop, uv_pipe_t *handle, HANDLE pipeHandle, int fd, DWORD duplex_flags)
Definition: pipe.c:254
static void eof_timer_close_cb(uv_handle_t *handle)
Definition: pipe.c:2075
static void uv_insert_non_overlapped_write_req(uv_pipe_t *handle, uv_write_t *req)
Definition: pipe.c:1204
void uv_process_pipe_read_req(uv_loop_t *loop, uv_pipe_t *handle, uv_req_t *req)
Definition: pipe.c:1789
static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void *arg)
Definition: pipe.c:974
void uv_process_pipe_write_req(uv_loop_t *loop, uv_pipe_t *handle, uv_write_t *req)
Definition: pipe.c:1856
void uv_process_pipe_shutdown_req(uv_loop_t *loop, uv_pipe_t *handle, uv_shutdown_t *req)
Definition: pipe.c:1967
static void uv_pipe_queue_accept(uv_loop_t *loop, uv_pipe_t *handle, uv_pipe_accept_t *req, BOOL firstInstance)
Definition: pipe.c:840
static void eof_timer_start(uv_pipe_t *pipe)
Definition: pipe.c:2013
@ UV__IPC_FRAME_VALID_FLAGS
Definition: pipe.c:69
@ UV__IPC_FRAME_HAS_SOCKET_XFER
Definition: pipe.c:65
@ UV__IPC_FRAME_XFER_FLAGS
Definition: pipe.c:68
@ UV__IPC_FRAME_XFER_IS_TCP_CONNECTION
Definition: pipe.c:66
@ UV__IPC_FRAME_HAS_DATA
Definition: pipe.c:64
static void CALLBACK post_completion_read_wait(void *context, BOOLEAN timed_out)
Definition: pipe.c:1074
static void uv__pipe_queue_ipc_xfer_info(uv_pipe_t *handle, uv__ipc_socket_xfer_type_t xfer_type, uv__ipc_socket_xfer_info_t *xfer_info)
Definition: pipe.c:1631
static void uv_pipe_read_error(uv_loop_t *loop, uv_pipe_t *handle, int error, uv_buf_t buf)
Definition: pipe.c:1609
static int pipe_alloc_accept(uv_loop_t *loop, uv_pipe_t *handle, uv_pipe_accept_t *req, BOOL firstInstance)
Definition: pipe.c:329
static DWORD WINAPI pipe_connect_thread_proc(void *parameter)
Definition: pipe.c:604
static const int64_t eof_timeout
Definition: pipe.c:46
int uv_pipe_read_start(uv_pipe_t *handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
Definition: pipe.c:1177
void uv__pipe_interrupt_read(uv_pipe_t *handle)
Definition: pipe.c:728
int uv_pipe_accept(uv_pipe_t *server, uv_stream_t *client)
Definition: pipe.c:876
static void uv_pipe_read_error_or_eof(uv_loop_t *loop, uv_pipe_t *handle, int error, uv_buf_t buf)
Definition: pipe.c:1621
static const int default_pending_pipe_instances
Definition: pipe.c:48
int uv__pipe_write_ipc(uv_loop_t *loop, uv_write_t *req, uv_pipe_t *handle, const uv_buf_t data_bufs[], size_t data_buf_count, uv_stream_t *send_handle, uv_write_cb cb)
Definition: pipe.c:1476
void uv_process_pipe_accept_req(uv_loop_t *loop, uv_pipe_t *handle, uv_req_t *raw_req)
Definition: pipe.c:1910
static void uv_pipe_queue_read(uv_loop_t *loop, uv_pipe_t *handle)
Definition: pipe.c:1112
static DWORD uv__pipe_read_ipc(uv_loop_t *loop, uv_pipe_t *handle)
Definition: pipe.c:1708
static void uv_queue_non_overlapped_write(uv_pipe_t *handle)
Definition: pipe.c:1240
static void eof_timer_destroy(uv_pipe_t *pipe)
Definition: pipe.c:2065
static int uv__pipe_getname(const uv_pipe_t *handle, char *buffer, size_t *size)
Definition: pipe.c:2154
static uv_write_t * uv_remove_non_overlapped_write_req(uv_pipe_t *handle)
Definition: pipe.c:1219
static HANDLE open_named_pipe(const WCHAR *name, DWORD *duplex_flags)
Definition: pipe.c:135
static void close_pipe(uv_pipe_t *pipe)
Definition: pipe.c:193
static void uv_pipe_connection_init(uv_pipe_t *handle)
Definition: pipe.c:123
void uv_pipe_cleanup(uv_loop_t *loop, uv_pipe_t *handle)
Definition: pipe.c:785
static char pipe_prefix[]
Definition: pipe.c:51
void uv_process_pipe_connect_req(uv_loop_t *loop, uv_pipe_t *handle, uv_connect_t *req)
Definition: pipe.c:1945
static char uv_zero_[]
Definition: pipe.c:39
static const uv_buf_t uv_null_buf_
Definition: pipe.c:42
static char bufs[4][128]
Buffers for uint64_to_str() and uint64_to_nicestr()
Definition: util.c:18
static void lock(volatile int *lk)
Definition: malloc.c:61
int uv_file
Definition: unix.h:128
pid_t uv_pid_t
Definition: unix.h:131
void error(const char *msg)
Definition: untgz.c:593
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void * uv__calloc(size_t count, size_t size)
Definition: uv-common.c:92
void uv__free(void *ptr)
Definition: uv-common.c:81
@ UV_HANDLE_PIPESERVER
Definition: uv-common.h:119
@ UV_HANDLE_BLOCKING_WRITES
Definition: uv-common.h:98
@ UV_HANDLE_CANCELLATION_PENDING
Definition: uv-common.h:99
@ UV_HANDLE_READING
Definition: uv-common.h:90
@ UV_HANDLE_LISTENING
Definition: uv-common.h:82
@ UV_HANDLE_CLOSING
Definition: uv-common.h:74
@ UV_HANDLE_EMULATE_IOCP
Definition: uv-common.h:97
@ UV_HANDLE_CONNECTION
Definition: uv-common.h:83
@ UV_HANDLE_WRITABLE
Definition: uv-common.h:93
@ UV_HANDLE_CLOSED
Definition: uv-common.h:75
@ UV_HANDLE_READ_PENDING
Definition: uv-common.h:94
@ UV_HANDLE_NON_OVERLAPPED_PIPE
Definition: uv-common.h:118
@ UV_HANDLE_BOUND
Definition: uv-common.h:91
@ UV_HANDLE_READABLE
Definition: uv-common.h:92
#define UV_REQ_INIT(req, typ)
Definition: uv-common.h:322
void(* uv_write_cb)(uv_write_t *req, int status)
Definition: uv.h:315
void(* uv_connection_cb)(uv_stream_t *server, int status)
Definition: uv.h:318
UV_EXTERN int uv_translate_sys_error(int sys_errno)
Definition: core.c:1249
UV_EXTERN int uv_timer_start(uv_timer_t *handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
Definition: timer.c:66
UV_EXTERN int uv_timer_init(uv_loop_t *, uv_timer_t *handle)
Definition: timer.c:58
uv_handle_type
Definition: uv.h:189
@ UV_UNKNOWN_HANDLE
Definition: uv.h:190
UV_EXTERN uv_buf_t uv_buf_init(char *base, unsigned int len)
Definition: uv-common.c:157
UV_EXTERN int uv_read_stop(uv_stream_t *)
Definition: stream.c:1590
UV_EXTERN int uv_timer_stop(uv_timer_t *handle)
Definition: timer.c:97
UV_EXTERN void uv_unref(uv_handle_t *)
Definition: uv-common.c:552
void(* uv_read_cb)(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
Definition: uv.h:312
void(* uv_alloc_cb)(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
Definition: uv.h:309
UV_EXTERN void uv_close(uv_handle_t *handle, uv_close_cb close_cb)
Definition: core.c:108
void(* uv_connect_cb)(uv_connect_t *req, int status)
Definition: uv.h:316
UV_EXTERN uv_pid_t uv_os_getppid(void)
Definition: core.c:1402
@ UV_WRITABLE
Definition: uv.h:801
@ UV_READABLE
Definition: uv.h:800
LONG NTSTATUS
Definition: win.h:198
sNtQueryInformationFile pNtQueryInformationFile
Definition: winapi.c:32
sRtlNtStatusToDosError pRtlNtStatusToDosError
Definition: winapi.c:30
@ FilePipeLocalInformation
Definition: winapi.h:4195
@ FileNameInformation
Definition: winapi.h:4180
@ FileAccessInformation
Definition: winapi.h:4179
@ FileModeInformation
Definition: winapi.h:4187
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: winapi.h:4340
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: winapi.h:4339
#define STATUS_BUFFER_OVERFLOW
Definition: winapi.h:520
#define STATUS_SUCCESS
Definition: winapi.h:68
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
DWORD * HANDLE
DWORD
static const z80_opcode fd[]
Definition: z80_tab.h:997
static const char * cb[]
Definition: z80_tab.h:176