void winansi_init(void) { int con1, con2; char name[32]; /* check if either stdout or stderr is a console output screen buffer */ con1 = is_console(1); con2 = is_console(2); /* Also compute console bit for fd 0 even though we don't need the result here. */ is_console(0); if (!con1 && !con2) { #ifdef DETECT_MSYS_TTY /* check if stdin / stdout / stderr are MSYS2 pty pipes */ detect_msys_tty(0); detect_msys_tty(1); detect_msys_tty(2); #endif return; } /* create a named pipe to communicate with the console thread */ xsnprintf(name, sizeof(name), "\\\\.\\pipe\\winansi%lu", GetCurrentProcessId()); hwrite = CreateNamedPipe(name, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_WAIT, 1, BUFFER_SIZE, 0, 0, NULL); if (hwrite == INVALID_HANDLE_VALUE) die_lasterr("CreateNamedPipe failed"); hread = CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hread == INVALID_HANDLE_VALUE) die_lasterr("CreateFile for named pipe failed"); /* start console spool thread on the pipe's read end */ hthread = CreateThread(NULL, 0, console_thread, NULL, 0, NULL); if (hthread == INVALID_HANDLE_VALUE) die_lasterr("CreateThread(console_thread) failed"); /* schedule cleanup routine */ if (atexit(winansi_exit)) die_errno("atexit(winansi_exit) failed"); /* redirect stdout / stderr to the pipe */ if (con1) hconsole1 = swap_osfhnd(1, duplicate_handle(hwrite)); if (con2) hconsole2 = swap_osfhnd(2, duplicate_handle(hwrite)); }
extern void native_make_top_thread(struct c_state *c_state) { HANDLE pseudo_top_thread_handle; c_state->native.event = (word*) CreateEvent (NULL, /* no security */ FALSE, /* auto-reset */ FALSE, /* initially unsignalled */ NULL); /* un-named */ if (c_state->native.event == NULL) error("CreateEvent() has failed; GetLastError() returns %u", GetLastError()); DIAGNOSTIC(4,"Native threads created event handle 0x%x for top thread", c_state->native.event,0); pseudo_top_thread_handle = GetCurrentThread(); c_state->native.thread = (word*) duplicate_handle(pseudo_top_thread_handle); DIAGNOSTIC(4,"top thread handle 0x%x obtained",c_state->native.thread,0); }
static HANDLE swap_osfhnd(int fd, HANDLE new_handle) { /* * Create a copy of the original handle associated with fd * because the original will get closed when we dup2(). */ HANDLE handle = (HANDLE)_get_osfhandle(fd); HANDLE duplicate = duplicate_handle(handle); /* Create a temp fd associated with the already open "new_handle". */ int new_fd = _open_osfhandle((intptr_t)new_handle, O_BINARY); assert((fd == 1) || (fd == 2)); /* * Use stock dup2() to re-bind fd to the new handle. Note that * this will implicitly close(1) and close both fd=1 and the * originally associated handle. It will open a new fd=1 and * call DuplicateHandle() on the handle associated with new_fd. * It is because of this implicit close() that we created the * copy of the original. * * Note that we need to update the cached console handle to the * duplicated one because the dup2() call will implicitly close * the original one. * * Note that dup2() when given target := {0,1,2} will also * call SetStdHandle(), so we don't need to worry about that. */ if (console == handle) console = duplicate; dup2(new_fd, fd); /* Close the temp fd. This explicitly closes "new_handle" * (because it has been associated with it). */ close(new_fd); if (fd == 2) setvbuf(stderr, NULL, _IONBF, BUFSIZ); fd_is_interactive[fd] |= FD_SWAPPED; return duplicate; }
handle duplicate() const { return duplicate_handle(handle_to_manage); }
static DWORD CALLBACK copy_thread(LPVOID unused) { uint32_t pitch = thread_data.pitch; uint32_t cy = thread_data.cy; HANDLE events[2] = {NULL, NULL}; int shmem_id = 0; if (!duplicate_handle(&events[0], thread_data.copy_event)) { hlog_hr("copy_thread: Failed to duplicate copy event: %d", GetLastError()); return 0; } if (!duplicate_handle(&events[1], thread_data.stop_event)) { hlog_hr("copy_thread: Failed to duplicate stop event: %d", GetLastError()); goto finish; } for (;;) { int copy_tex; void *cur_data; DWORD ret = WaitForMultipleObjects(2, events, false, INFINITE); if (ret != WAIT_OBJECT_0) { break; } EnterCriticalSection(&thread_data.data_mutex); copy_tex = thread_data.cur_tex; cur_data = thread_data.cur_data; LeaveCriticalSection(&thread_data.data_mutex); if (copy_tex < NUM_BUFFERS && !!cur_data) { EnterCriticalSection(&thread_data.mutexes[copy_tex]); int lock_id = try_lock_shmem_tex(shmem_id); if (lock_id != -1) { memcpy(thread_data.shmem_textures[lock_id], cur_data, pitch * cy); unlock_shmem_tex(lock_id); ((struct shmem_data*)shmem_info)->last_tex = lock_id; shmem_id = lock_id == 0 ? 1 : 0; } LeaveCriticalSection(&thread_data.mutexes[copy_tex]); } } finish: for (size_t i = 0; i < 2; i++) { if (events[i]) { CloseHandle(events[i]); } } (void)unused; return 0; }
static void set_main_thread(void) { HANDLE pseudo_main_thread_handle = GetCurrentThread(); main_thread = (word*) duplicate_handle(pseudo_main_thread_handle); DIAGNOSTIC(4,"main thread handle 0x%x obtained", main_thread,0); }