int pthread_np_notice_thread() { if (!pthread_self()) { pthread_t pth = (pthread_t)calloc(sizeof(pthread_thread),1); pth->teb = NtCurrentTeb(); pthread_mutex_init(&pth->fiber_lock,NULL); pthread_mutex_init(&pth->lock,NULL); pth->state = pthread_state_running; pth->fiber_group = pth; sigemptyset(&pth->blocked_signal_set); DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &pth->handle, 0, TRUE, DUPLICATE_SAME_ACCESS); tls_impersonate(pth); if (pthread_initialized) { RegisterWaitForSingleObject(&pth->wait_handle, pth->handle, pthreads_win32_unnotice, pth, INFINITE, WT_EXECUTEONLYONCE); } return 1; } else { return 0; } }
void ExplorerAliveChecker::init() { DWORD dwExplorerProcessId = NULL; GetWindowThreadProcessId(_explorerHwnd, &dwExplorerProcessId); if (dwExplorerProcessId == NULL) ExplorerQuitCallback(this, FALSE); HANDLE explorerProcessHandle = OpenProcess(SYNCHRONIZE, FALSE, dwExplorerProcessId); if (explorerProcessHandle != NULL) { HANDLE waitObjectHandle; // request function to t RegisterWaitForSingleObject(&waitObjectHandle, explorerProcessHandle, ExplorerQuitCallback, this, // argument to pass to callback function INFINITE, WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE); } }
bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) { CHECK(delegate); if (wait_object_) { NOTREACHED() << "Already watching an object"; return false; } // Since our job is to just notice when an object is signaled and report the // result back to this thread, we can just run on a Windows wait thread. DWORD wait_flags = WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE; // DoneWaiting can be synchronously called from RegisterWaitForSingleObject, // so set up all state now. callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(), delegate); object_ = object; origin_loop_ = MessageLoop::current(); if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting, this, INFINITE, wait_flags)) { DPLOG(FATAL) << "RegisterWaitForSingleObject failed"; object_ = NULL; wait_object_ = NULL; return false; } // We need to know if the current message loop is going away so we can // prevent the wait thread from trying to access a dead message loop. MessageLoop::current()->AddDestructionObserver(this); return true; }
static PyObject * overlapped_RegisterWaitWithQueue(PyObject *self, PyObject *args) { HANDLE NewWaitObject; HANDLE Object; ULONG Milliseconds; struct PostCallbackData data, *pdata; if (!PyArg_ParseTuple(args, F_HANDLE F_HANDLE F_POINTER F_DWORD, &Object, &data.CompletionPort, &data.Overlapped, &Milliseconds)) return NULL; /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since PostToQueueCallback() will call PyMem_Free() from a new C thread which doesn't hold the GIL. */ pdata = PyMem_RawMalloc(sizeof(struct PostCallbackData)); if (pdata == NULL) return SetFromWindowsErr(0); *pdata = data; if (!RegisterWaitForSingleObject( &NewWaitObject, Object, (WAITORTIMERCALLBACK)PostToQueueCallback, pdata, Milliseconds, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) { PyMem_RawFree(pdata); return SetFromWindowsErr(0); } return Py_BuildValue(F_HANDLE, NewWaitObject); }
bool DirectoryWinAPI::setWatch(const std::string& path, ICallbackBase<void>* cb) { if(callbacks.size() > MAXIMUM_WAIT_OBJECTS) { LOGERROR("Too many objects being watched", "setWatch"); } HANDLE watchHandle = FindFirstChangeNotification(path.c_str(), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE); if (watchHandle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); LOGERROR(err, "FindFirstChangeNotification"); return false; } HANDLE poolHandle; if(!RegisterWaitForSingleObject(&poolHandle, watchHandle, onEventTriggered, watchHandle, INFINITE, WT_EXECUTEINWAITTHREAD)) { DWORD err = GetLastError(); LOGERROR(err, "RegisterWaitForSingleObject"); return false; } DirWinAPIWait waitStruct = { cb, poolHandle }; callbacks[watchHandle] = waitStruct; return true; }
OP_STATUS WindowsOpAutoUpdatePI::PackageExtractor::Extract(uni_char *package) { if (m_is_extracting) return OpStatus::ERR; m_is_extracting = TRUE; SHELLEXECUTEINFO info; memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); info.fMask = SEE_MASK_NOCLOSEPROCESS; info.lpVerb = NULL; info.lpFile = package; info.nShow = SW_HIDE; if (!ShellExecuteEx(&info)) { return OpStatus::ERR; } m_process_handle = info.hProcess; if (!RegisterWaitForSingleObject(&m_wait_object, m_process_handle, WaitOrTimerCallback, this, INFINITE, WT_EXECUTEONLYONCE)) { CloseHandle(m_process_handle); return OpStatus::ERR; } return OpStatus::OK; }
bool MonitorIPs::Initialize() { Log(LOG_DEBUG,__LINE__,">> MonIPs.Init"); m_hSync = CreateMutex(NULL,FALSE,NULL); if(!m_hSync) { Log(LOG_DEBUG,__LINE__,"<< MonIPs.Init, Sync Obj %u",GetLastError()); return false; } m_o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!m_o.hEvent) { Log(LOG_DEBUG,__LINE__,"<< MonIPs.Init, CreateEv %u",GetLastError()); return false; } if(!RegisterWaitForSingleObject(&m_hWait,m_o.hEvent,s_OnChange,this,INFINITE,0)) { Log(LOG_DEBUG,__LINE__,"<< MonIPs.Init, RegWaitForSnglObj %u",GetLastError()); return false; } CheckIPAddress(); Log(LOG_DEBUG,__LINE__,"<< MonIPs.Init, Ev 0x%p, ret True",m_o.hEvent); return true; }
static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) { uv_req_t* req; BOOL r; assert(handle->flags & UV_HANDLE_READING); assert(!(handle->flags & UV_HANDLE_READ_PENDING)); assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE); handle->read_line_buffer = uv_null_buf_; req = &handle->read_req; memset(&req->overlapped, 0, sizeof(req->overlapped)); r = RegisterWaitForSingleObject(&handle->read_raw_wait, handle->handle, uv_tty_post_raw_read, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); if (!r) { handle->read_raw_wait = NULL; SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, req); } handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; }
void NetworkConnection::continueReceive() { if (closed || sendError) // Close if anything is wrong { close(); } else { bufferInfo.buf = (char*)receiveBuffer; // Set buffer data bufferInfo.len = BUFFER_SIZE; // 0 means send completed instantly if (WSARecv(connection, &bufferInfo, 1, &bytesReceived, &flags, &receiveOverlapped, NULL) == 0) { dataReceived(); // Wait for more data } else { if (WSAGetLastError() == WSA_IO_PENDING) // Data is pending { // Send a wait handle to the WinAPI thread pool RegisterWaitForSingleObject(&newWaitHandle, receiveOverlapped.hEvent, DataReceivedCallback, this, INFINITE, WT_EXECUTEONLYONCE); } else { close(); } } } }
int evfilt_timer_knote_create(struct filter *filt, struct knote *kn) { HANDLE th; LARGE_INTEGER liDueTime; kn->kev.flags |= EV_CLEAR; th = CreateWaitableTimer(NULL, FALSE, NULL); if (th == NULL) { dbg_lasterror("CreateWaitableTimer()"); return (-1); } dbg_printf("created timer handle %p", th); convert_msec_to_filetime(&liDueTime, kn->kev.data); // XXX-FIXME add completion routine to this call if (!SetWaitableTimer(th, &liDueTime, (LONG)( (kn->kev.flags & EV_ONESHOT) ? 0 : kn->kev.data ), NULL, NULL, FALSE)) { dbg_lasterror("SetWaitableTimer()"); CloseHandle(th); return (-1); } kn->data.handle = th; RegisterWaitForSingleObject(&kn->kn_event_whandle, th, evfilt_timer_callback, kn, INFINITE, 0); knote_retain(kn); return (0); }
int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, uv_buf_t bufs[], int bufcnt, uv_write_cb cb) { int result; DWORD bytes; uv_req_init(loop, (uv_req_t*) req); req->type = UV_WRITE; req->handle = (uv_stream_t*) handle; req->cb = cb; memset(&req->overlapped, 0, sizeof(req->overlapped)); /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); req->wait_handle = INVALID_HANDLE_VALUE; } result = WSASend(handle->socket, (WSABUF*)bufs, bufcnt, &bytes, 0, &req->overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Request completed immediately. */ req->queued_bytes = 0; handle->reqs_pending++; handle->write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); uv_insert_pending_req(loop, (uv_req_t*) req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ req->queued_bytes = uv_count_bufs(bufs, bufcnt); handle->reqs_pending++; handle->write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); handle->write_queue_size += req->queued_bytes; if (handle->flags & UV_HANDLE_EMULATE_IOCP && !RegisterWaitForSingleObject(&req->wait_handle, req->event_handle, post_write_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); } } else { /* Send failed due to an error. */ uv__set_sys_error(loop, WSAGetLastError()); return -1; } return 0; }
/* function registers `exit` callback */ BOOL Process::RegisterExitCallback(ProcessCallback callback) { if (!callback) return FALSE; exitCallback = callback; /* directs a wait thread in the thread pool to wait on the object */ return RegisterWaitForSingleObject(&hWait, hProcess, OnExited, this, INFINITE, WT_EXECUTEONLYONCE); }
static void register_wait( int job_id ) { if ( globs.jobs > MAXIMUM_WAIT_OBJECTS ) { HANDLE ignore; RegisterWaitForSingleObject( &cmdtab[ job_id ].wait_handle, cmdtab[ job_id ].pi.hProcess, &try_wait_callback, &cmdtab[ job_id ], INFINITE, WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE ); } }
extern "C" __declspec(dllexport) DWORD WINAPI OnAttach(LPDWORD args) { try { const DWORD access = PROCESS_DUP_HANDLE | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | SYNCHRONIZE; HANDLE hProcess = OpenProcess(access, FALSE, args[0]); if (!hProcess) throw L"OpenProcess"; //init shared memory HANDLE mmf = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, sizeof(SharedMemory), nullptr); if (!mmf) throw L"CreateFileMapping"; shared = (SharedMemory*)MapViewOfFile(mmf, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (!shared) throw L"MapViewOfFile"; HANDLE mmfRemote = Duplicate(hProcess, mmf); CloseHandle(mmf); if (!RegisterWaitForSingleObject(&mmf, hProcess, OnExit, nullptr, INFINITE, WT_EXECUTEONLYONCE)) throw L"RegisterWaitForSingleObject"; CloseHandle(mmf); //init events sentOut = CreateEvent(nullptr, FALSE, FALSE, nullptr); handledOut = CreateEvent(nullptr, FALSE, FALSE, nullptr); sentIn = CreateEvent(nullptr, FALSE, FALSE, nullptr); handledIn = CreateEvent(nullptr, FALSE, FALSE, nullptr); if (!sentOut || !handledOut || !sentIn || !handledIn) throw L"CreateEvent"; shared->msgOut[0] = (UINT)Duplicate(hProcess, sentOut); shared->msgOut[1] = (UINT)Duplicate(hProcess, handledOut); shared->msgOut[2] = (UINT)Duplicate(hProcess, sentIn); shared->msgOut[3] = (UINT)Duplicate(hProcess, handledIn); CloseHandle(hProcess); //init UOHooks Client client; Hooks::Imports(client); Hooks::Packets(client); Hooks::Other(client); if (args[1]) Patches::Encryption(client); Patches::Multi(client); Patches::Intro(client); memcpy(shared->dataOut, Hooks::GetPacketTable(), 0x100 * sizeof(UINT)); std::thread(MessagePump).detach();//start ipc server return (DWORD)mmfRemote; } catch (LPCWSTR str) { MessageBox(nullptr, str, L"OnAttach", MB_ICONERROR | MB_OK); } return 0; }
void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { if (handle->wait_handle != INVALID_HANDLE_VALUE) { handle->close_handle = CreateEvent(NULL, FALSE, FALSE, NULL); UnregisterWaitEx(handle->wait_handle, handle->close_handle); handle->wait_handle = NULL; RegisterWaitForSingleObject(&handle->wait_handle, handle->close_handle, close_wait_callback, (void*)handle, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); } else { uv_want_endgame(loop, (uv_handle_t*)handle); } }
//----------------------------------------------------------------------------- // Function: MonitorPeopleNearMe // // Purpose: Watches for change events in PeopleNearMe data // // Returns: HRESULT // HRESULT MonitorPeopleNearMe() { HRESULT hr = S_OK; PEER_COLLAB_EVENT_REGISTRATION eventReg = {0}; // Create the event handle for the model // g_hModelEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == g_hModelEvent) { return E_OUTOFMEMORY; } // Setup the event registration specifying the type of event to be notified about // eventReg.eventType = PEER_EVENT_PEOPLE_NEAR_ME_CHANGED; eventReg.pInstance = NULL; // Register to be notified when the People Near Me change // hr = PeerCollabRegisterEvent(g_hModelEvent, 1, &eventReg, &g_hModelPeerEvent); if (SUCCEEDED(hr)) { // Registers a wait object that will call ProcessUpdateCallBack // whenever a PEER_EVENT_PEOPLE_NEAR_ME_CHANGED is received. // if (!RegisterWaitForSingleObject(&g_hModelWaitObject, g_hModelEvent, ProcessUpdateCallBack, NULL, INFINITE, 0)) { hr = HRESULT_FROM_WIN32(GetLastError()); } } if (FAILED(hr)) { MessageBox(g_hModelDlgOwner, L"Error", L"Could not initialize People Near Me monitoring.", MB_OK); } return hr; }
int monitor_service() { /* Set service status to started */ int ret = start_service(); if (ret) { char code[16]; _snprintf(code, sizeof(code), "%d", ret); log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_START_SERVICE_FAILED, exe, service_name, ret, 0); return ret; } log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_STARTED_SERVICE, exe, flags, service_name, dir, 0); /* Monitor service service */ if (! RegisterWaitForSingleObject(&wait_handle, process_handle, end_service, (void *) pid, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION)) { log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED, service_name, exe, error_string(GetLastError()), 0); } return 0; }
bool CEXIETHERNET::RecvInit() { // Set up recv event if ((mHRecvEvent = CreateEvent(nullptr, false, false, nullptr)) == nullptr) { ERROR_LOG(SP1, "Failed to create recv event:%x", GetLastError()); return false; } ZeroMemory(&mReadOverlapped, sizeof(mReadOverlapped)); RegisterWaitForSingleObject(&mHReadWait, mHRecvEvent, ReadWaitCallback, this, INFINITE, WT_EXECUTEDEFAULT); mReadOverlapped.hEvent = mHRecvEvent; return true; }
//------------------------------------------------------------------------- Bool Instance::Load( DWORD process_id ) { xassert(_process_id == 0); // open process with all access privileges required by the tools that will use it (dont use PROCESS_ALL_ACCESS) _process = OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_CREATE_THREAD|PROCESS_VM_READ|PROCESS_VM_WRITE|SYNCHRONIZE, FALSE, process_id); if( _process ) { // choose inject dll const Char* inject_dll = _ChooseInjectDll(); if( inject_dll != NULL ) { // set notify name _injector.SetNotifyName(INJECT_NOTIFY_FUNCTION); // load if( _injector.Load(_process, inject_dll) ) { // notify init if( Notify(NOTIFY_INIT) ) { // register process exit handler if( RegisterWaitForSingleObject(&_wait_handle, _process, _ProcessExitHandler, this, INFINITE, WT_EXECUTEONLYONCE) ) { _process_id = process_id; return true; } } } } // unload Unload(); } return false; }
int __pmSetSignalHandler(int sig, __pmSignalHandler func) { int sts, index; char *signame, evname[64]; HANDLE eventhdl, waithdl; if ((signame = MapSignals(sig, &index)) < 0) return index; if (signals[index].callback) { /* remove old handler */ UnregisterWait(signals[index].waithandle); CloseHandle(signals[index].eventhandle); signals[index].callback = NULL; signals[index].signal = -1; } if (func == SIG_IGN) return 0; sts = 0; snprintf(evname, sizeof(evname), "PCP/%" FMT_PID "/%s", getpid(), signame); if (!(eventhdl = CreateEvent(NULL, FALSE, FALSE, TEXT(evname)))) { sts = GetLastError(); fprintf(stderr, "CreateEvent::%s failed (%d)\n", signame, sts); } else if (!RegisterWaitForSingleObject(&waithdl, eventhdl, SignalCallback, (PVOID)index, INFINITE, 0)) { sts = GetLastError(); fprintf(stderr, "RegisterWait::%s failed (%d)\n", signame, sts); } else { signals[index].eventhandle = eventhdl; signals[index].waithandle = waithdl; signals[index].callback = func; signals[index].signal = sig; } return sts; }
int orte_wait_cb(pid_t wpid, orte_wait_fn_t callback, void *data) { opal_process_handle_t* handle; if (wpid <= 0) return ORTE_ERR_NOT_IMPLEMENTED; if (NULL == callback) return ORTE_ERR_BAD_PARAM; OPAL_THREAD_LOCK(&mutex); handle = find_pending_pid(wpid, false); if( handle != NULL ) { opal_list_remove_item( &pending_pids, (opal_list_item_t*)handle ); OBJ_RELEASE(handle); return ORTE_SUCCESS; } handle = find_pending_cb( wpid, true ); handle->pid = wpid; handle->callback = callback; handle->data = data; if( false == RegisterWaitForSingleObject( &handle->registered_handle, (HANDLE)handle->pid, trigger_process_detection, (void*)handle, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION) ) { DWORD errcode = GetLastError(); char* localbuf = NULL; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errcode, 0, (LPTSTR)&localbuf, 1024, NULL ); opal_output( 0, "Failed to initialize the process callback for pid %lu error %s\n", (unsigned long)(handle->pid), localbuf ); LocalFree( localbuf ); } OPAL_THREAD_UNLOCK(&mutex); return OPAL_SUCCESS; }
INT_PTR PluginHangUIChild::HangUIDlgProc(HWND aDlgHandle, UINT aMsgCode, WPARAM aWParam, LPARAM aLParam) { mDlgHandle = aDlgHandle; switch (aMsgCode) { case WM_INITDIALOG: { // Register a wait on the Firefox process so that we will be informed // if it dies while the dialog is showing RegisterWaitForSingleObject(&mRegWaitProcess, mParentProcess, &SOnParentProcessExit, this, INFINITE, WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE); SetWindowText(aDlgHandle, mWindowTitle); SetDlgItemText(aDlgHandle, IDC_MSG, mMessageText); SetDlgItemText(aDlgHandle, IDC_NOFUTURE, mNoFutureText); SetDlgItemText(aDlgHandle, IDC_CONTINUE, mWaitBtnText); SetDlgItemText(aDlgHandle, IDC_STOP, mKillBtnText); ResizeButtons(); HANDLE icon = LoadImage(NULL, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); if (icon) { SendDlgItemMessage(aDlgHandle, IDC_DLGICON, STM_SETICON, (WPARAM)icon, 0); } EnableWindow(mParentWindow, FALSE); return TRUE; } case WM_CLOSE: { mResponseBits |= HANGUI_USER_RESPONSE_CANCEL; EndDialog(aDlgHandle, 0); SetWindowLongPtr(aDlgHandle, DWLP_MSGRESULT, 0); return TRUE; } case WM_COMMAND: { switch (LOWORD(aWParam)) { case IDC_CONTINUE: if (HIWORD(aWParam) == BN_CLICKED) { mResponseBits |= HANGUI_USER_RESPONSE_CONTINUE; EndDialog(aDlgHandle, 1); SetWindowLongPtr(aDlgHandle, DWLP_MSGRESULT, 0); return TRUE; } break; case IDC_STOP: if (HIWORD(aWParam) == BN_CLICKED) { mResponseBits |= HANGUI_USER_RESPONSE_STOP; EndDialog(aDlgHandle, 1); SetWindowLongPtr(aDlgHandle, DWLP_MSGRESULT, 0); return TRUE; } break; case IDC_NOFUTURE: if (HIWORD(aWParam) == BN_CLICKED) { if (Button_GetCheck(GetDlgItem(aDlgHandle, IDC_NOFUTURE)) == BST_CHECKED) { mResponseBits |= HANGUI_USER_RESPONSE_DONT_SHOW_AGAIN; } else { mResponseBits &= ~static_cast<DWORD>(HANGUI_USER_RESPONSE_DONT_SHOW_AGAIN); } SetWindowLongPtr(aDlgHandle, DWLP_MSGRESULT, 0); return TRUE; } break; default: break; } break; } case WM_DESTROY: { EnableWindow(mParentWindow, TRUE); break; } default: break; } return FALSE; }
int uv_spawn_jx(uv_loop_t* loop, uv_process_t* process, uv_process_options_t* options) { #ifdef WINONECORE error_console("Error: WindowsOneCore does not support spawning a process.\n"); return -1; // not supported #else int i; uv_err_t err = uv_ok_; WCHAR* path = NULL; BOOL result; WCHAR* application_path = NULL, *application = NULL, *arguments = NULL, *env = NULL, *cwd = NULL; STARTUPINFOW startup; PROCESS_INFORMATION info; DWORD process_flags; if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } if (options->file == NULL || options->args == NULL) { uv__set_artificial_error(loop, UV_EINVAL); return -1; } assert(options->file != NULL); assert(!(options->flags & ~(UV_PROCESS_DETACHED | UV_PROCESS_SETGID | UV_PROCESS_SETUID | UV_PROCESS_WINDOWS_HIDE | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); uv_process_init(loop, process); process->exit_cb = options->exit_cb; err = uv_utf8_to_utf16_alloc(options->file, &application); if (err.code != UV_OK) goto done; err = make_program_args( options->args, options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, &arguments); if (err.code != UV_OK) goto done; if (options->env) { err = make_program_env(options->env, &env); if (err.code != UV_OK) goto done; } if (options->cwd) { /* Explicit cwd */ err = uv_utf8_to_utf16_alloc(options->cwd, &cwd); if (err.code != UV_OK) goto done; } else { /* Inherit cwd */ DWORD cwd_len, r; cwd_len = GetCurrentDirectoryW(0, NULL); if (!cwd_len) { err = uv__new_sys_error(GetLastError()); goto done; } cwd = (WCHAR*)malloc(cwd_len * sizeof(WCHAR)); if (cwd == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto done; } r = GetCurrentDirectoryW(cwd_len, cwd); if (r == 0 || r >= cwd_len) { err = uv__new_sys_error(GetLastError()); goto done; } } /* Get PATH environment variable. */ { DWORD path_len, r; path_len = GetEnvironmentVariableW(L"PATH", NULL, 0); if (path_len == 0) { err = uv__new_sys_error(GetLastError()); goto done; } path = (WCHAR*)malloc(path_len * sizeof(WCHAR)); if (path == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto done; } r = GetEnvironmentVariableW(L"PATH", path, path_len); if (r == 0 || r >= path_len) { err = uv__new_sys_error(GetLastError()); goto done; } } application_path = search_path(application, cwd, path); if (application_path == NULL) { /* Not found. */ err = uv__new_artificial_error(UV_ENOENT); goto done; } err = uv__stdio_create(loop, options, &process->child_stdio_buffer); if (err.code != UV_OK) goto done; startup.cb = sizeof(startup); startup.lpReserved = NULL; startup.lpDesktop = NULL; startup.lpTitle = NULL; startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer); startup.lpReserved2 = (BYTE*)process->child_stdio_buffer; startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0); startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1); startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2); if (options->flags & UV_PROCESS_WINDOWS_HIDE) { /* Use SW_HIDE to avoid any potential process window. */ startup.wShowWindow = SW_HIDE; } else { startup.wShowWindow = SW_SHOWDEFAULT; } process_flags = CREATE_UNICODE_ENVIRONMENT; if (options->flags & UV_PROCESS_DETACHED) { /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That * means that libuv might not let you create a fully deamonized process * when run under job control. However the type of job control that libuv * itself creates doesn't trickle down to subprocesses so they can still * daemonize. * * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the * CreateProcess call fail if we're under job control that doesn't allow * breakaway. */ process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; } if (CreateProcessW(application_path, arguments, NULL, NULL, 1, process_flags, env, cwd, &startup, &info)) { /* Spawn succeeded */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; /* If the process isn't spawned as detached, assign to the global job */ /* object so windows will kill it when the parent process dies. */ if (!(options->flags & UV_PROCESS_DETACHED)) { uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) { /* AssignProcessToJobObject might fail if this process is under job * control and the job doesn't have the * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version * that doesn't support nested jobs. * * When that happens we just swallow the error and continue without * establishing a kill-child-on-parent-exit relationship, otherwise * there would be no way for libuv applications run under job control * to spawn processes at all. */ DWORD err = GetLastError(); if (err != ERROR_ACCESS_DENIED) uv_fatal_error(err, "AssignProcessToJobObject"); } } /* Set IPC pid to all IPC pipes. */ for (i = 0; i < options->stdio_count; i++) { const uv_stdio_container_t* fdopt = &options->stdio[i]; if (fdopt->flags & UV_CREATE_PIPE && fdopt->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*)fdopt->data.stream)->ipc) { ((uv_pipe_t*)fdopt->data.stream)->ipc_pid = info.dwProcessId; } } /* Setup notifications for when the child process exits. */ result = RegisterWaitForSingleObject( &process->wait_handle, process->process_handle, exit_wait_callback, (void*)process, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); if (!result) { uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } CloseHandle(info.hThread); } else { /* CreateProcessW failed. */ err = uv__new_sys_error(GetLastError()); } done: JX_FREE(process, application); JX_FREE(process, application_path); JX_FREE(process, arguments); JX_FREE(process, cwd); JX_FREE(process, env); JX_FREE(process, path); process->spawn_error = err; if (process->child_stdio_buffer != NULL) { /* Clean up child stdio handles. */ uv__stdio_destroy(process->child_stdio_buffer); process->child_stdio_buffer = NULL; } /* Make the handle active. It will remain active until the exit callback */ /* is made or the handle is closed, whichever happens first. */ uv__handle_start(process); /* If an error happened, queue the exit req. */ if (err.code != UV_OK) { process->exit_cb_pending = 1; uv_insert_pending_req(loop, (uv_req_t*)&process->exit_req); } return 0; #endif }
static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcnt, uv_stream_t* send_handle, uv_write_cb cb) { int result; uv_tcp_t* tcp_send_handle; uv_write_t* ipc_header_req; uv_ipc_frame_uv_stream ipc_frame; if (bufcnt != 1 && (bufcnt != 0 || !send_handle)) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } /* Only TCP handles are supported for sharing. */ if (send_handle && ((send_handle->type != UV_TCP) || (!(send_handle->flags & UV_HANDLE_BOUND) && !(send_handle->flags & UV_HANDLE_CONNECTION)))) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } assert(handle->handle != INVALID_HANDLE_VALUE); uv_req_init(loop, (uv_req_t*) req); req->type = UV_WRITE; req->handle = (uv_stream_t*) handle; req->cb = cb; req->ipc_header = 0; req->event_handle = NULL; req->wait_handle = INVALID_HANDLE_VALUE; memset(&req->overlapped, 0, sizeof(req->overlapped)); if (handle->ipc) { assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); ipc_frame.header.flags = 0; /* Use the IPC framing protocol. */ if (send_handle) { tcp_send_handle = (uv_tcp_t*)send_handle; if (uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid, &ipc_frame.socket_info)) { return -1; } ipc_frame.header.flags |= UV_IPC_TCP_SERVER; if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) { ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION; } } if (bufcnt == 1) { ipc_frame.header.flags |= UV_IPC_RAW_DATA; ipc_frame.header.raw_data_length = bufs[0].len; } /* * Use the provided req if we're only doing a single write. * If we're doing multiple writes, use ipc_header_write_req to do * the first write, and then use the provided req for the second write. */ if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { ipc_header_req = req; } else { /* * Try to use the preallocated write req if it's available. * Otherwise allocate a new one. */ if (handle->ipc_header_write_req.type != UV_WRITE) { ipc_header_req = (uv_write_t*)&handle->ipc_header_write_req; } else { ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t)); if (!ipc_header_req) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } } uv_req_init(loop, (uv_req_t*) ipc_header_req); ipc_header_req->type = UV_WRITE; ipc_header_req->handle = (uv_stream_t*) handle; ipc_header_req->cb = NULL; ipc_header_req->ipc_header = 1; } /* Write the header or the whole frame. */ memset(&ipc_header_req->overlapped, 0, sizeof(ipc_header_req->overlapped)); result = WriteFile(handle->handle, &ipc_frame, ipc_frame.header.flags & UV_IPC_TCP_SERVER ? sizeof(ipc_frame) : sizeof(ipc_frame.header), NULL, &ipc_header_req->overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { uv__set_sys_error(loop, GetLastError()); return -1; } if (result) { /* Request completed immediately. */ ipc_header_req->queued_bytes = 0; } else { /* Request queued by the kernel. */ ipc_header_req->queued_bytes = ipc_frame.header.flags & UV_IPC_TCP_SERVER ? sizeof(ipc_frame) : sizeof(ipc_frame.header); handle->write_queue_size += ipc_header_req->queued_bytes; } REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); handle->reqs_pending++; handle->write_reqs_pending++; /* If we don't have any raw data to write - we're done. */ if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { return 0; } } if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { req->write_buffer = bufs[0]; uv_insert_non_overlapped_write_req(handle, req); if (handle->write_reqs_pending == 0) { uv_queue_non_overlapped_write(handle); } /* Request queued by the kernel. */ req->queued_bytes = uv_count_bufs(bufs, bufcnt); handle->write_queue_size += req->queued_bytes; } else { result = WriteFile(handle->handle, bufs[0].base, bufs[0].len, NULL, &req->overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { uv__set_sys_error(loop, GetLastError()); return -1; } if (result) { /* Request completed immediately. */ req->queued_bytes = 0; } else { /* Request queued by the kernel. */ req->queued_bytes = uv_count_bufs(bufs, bufcnt); handle->write_queue_size += req->queued_bytes; } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } if (!RegisterWaitForSingleObject(&req->wait_handle, req->overlapped.hEvent, post_completion_write_wait, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { uv__set_sys_error(loop, GetLastError()); return -1; } } } REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; handle->write_reqs_pending++; return 0; }
TProcess startSubProcess(void* self, int argc, char* argv[]) { IProcessManager _ = (IProcessManager)self; IErrorLogger elog = _->errorLogger; STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; BackendParams paramSm; char paramSmStr[32]; char commandLine[MAX_PATH * 2]; int cmdCharCount; HANDLE paramMap; DeadChildInfo childInfo; HANDLE tokenHandle = NULL; int i, j; ASSERT(elog, argv != NULL, -1); ASSERT(elog, argv[0] != NULL, -1); ASSERT(elog, argv[1] != NULL, -1); ASSERT(elog, argv[2] == NULL, -1); /* Set up shared memory for parameter passing */ ZeroMemory(&sa, sizeof(sa)); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &tokenHandle)) { elog->log(LOG_ERROR, ERROR_CODE_OPEN_PROCESS_TOKEN, "could not open process token: error code %lu", GetLastError()); return -1; } if (!SetPrivilege( _, tokenHandle, SE_CREATE_GLOBAL_NAME, True)) { elog->log(LOG_ERROR, ERROR_CODE_SET_PRIVILEDGE_FAILED, "could not open process token: error code %lu", GetLastError()); return -1; } /* If the first parameter is INVALID_HANDLE_VALUE, * the calling process must also specify a size * for the file mapping object. In this scenario, * CreateFileMapping creates a file mapping object * of a specified size that is backed by the system paging file * instead of by a file in the file system. */ paramMap = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sizeof(SBackendParams), sharedMemParamsName); if (paramMap == NULL || paramMap == INVALID_HANDLE_VALUE) { int error = GetLastError(); elog->log(LOG_ERROR, ERROR_CODE_CREATE_FILE_MAP_FAILED, "could not create file mapping: error code %lu", error); return -1; } sharedMemID = paramMap; sharedMemSegmSize = sizeof(SBackendParams); /* Maps a view of a file mapping into the address space of a calling process. */ paramSm = MapViewOfFile(paramMap, FILE_MAP_WRITE, 0, 0, sizeof(SBackendParams)); if (!paramSm) { elog->log(LOG_ERROR, ERROR_CODE_MAP_MEMORY_TO_FILE, "could not map backend parameter memory: error code %lu", GetLastError()); CloseHandle(paramSm); return -1; } sprintf(paramSmStr, "%lu", (DWORD)paramSm); argv[2] = paramSmStr; cmdCharCount = sizeof(commandLine); commandLine[cmdCharCount - 1] = '\0'; commandLine[cmdCharCount - 2] = '\0'; snprintf(commandLine, cmdCharCount - 1, "\"%s\"", ExecPath); i = 0; while (argv[++i] != NULL) { j = strlen(commandLine); snprintf(commandLine + j, sizeof(commandLine) - 1 - j, " \"%s\"", argv[i]); } if (commandLine[sizeof(commandLine) - 2] != '\0') { elog->log(LOG_ERROR, ERROR_CODE_PROC_CMD_LINE_TO_LONG, "subprocess command line too long"); return -1; } memset(&pi, 0, sizeof(pi)); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); /* Create the subprocess in a suspended state. * This will be resumed later, * once we have written out the parameter file. * If this parameter TRUE, each inheritable handle * in the calling process is inherited by the new process. * If the parameter is FALSE, the handles are not inherited. * Note that inherited handles have the same value * and access rights as the original handles. */ if (!CreateProcess(NULL, commandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { elog->log(LOG_ERROR, ERROR_CODE_CREATE_PROCESS_FAILED, "CreateProcess call failed: (error code %lu)", GetLastError()); return -1; } if (!fillBackandParams( _, paramSm, pi.hProcess, pi.dwProcessId)) { /* Delete the process */ if (!TerminateProcess(pi.hProcess, 255)) elog->log(LOG_ERROR, ERROR_CODE_TERMINATE_PROCESS_FAILED, "Terminate process failed: (error code %lu)", GetLastError()); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return -1; } /* Drop the handler to the shared memory. * Now the shared memory has already been passed * along to the child process. */ if (!UnmapViewOfFile(paramSm)) elog->log(LOG_ERROR, ERROR_CODE_UNMAP_VIEW_OF_FILE, "could not unmap view of backend parameter file: error code %lu", GetLastError()); if (!CloseHandle(paramMap)) elog->log(LOG_ERROR, ERROR_CODE_CLOSE_HANDLER_FAILED, "could not close handle to backend parameter file: error code %lu", GetLastError()); /* All variables are written out, so we can resume the thread */ if (ResumeThread(pi.hThread) == -1) { /* Delete the process */ if (!TerminateProcess(pi.hProcess, 255)) { elog->log(LOG_ERROR, ERROR_CODE_TERMINATE_PROCESS_FAILED, "Terminate process failed: (error code %lu)", GetLastError()); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return -1; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); elog->log(LOG_ERROR, ERROR_CODE_RESUME_THREAD_FAILED, "Terminate process failed: (error code %lu)", GetLastError()); return -1; } childInfo = malloc(sizeof(SDeadChildInfo)); if (childInfo == NULL) elog->log(LOG_FATAL, ERROR_CODE_OUT_OF_MEMORY, "out of memory"); childInfo->procHandle = pi.hProcess; childInfo->procId = pi.dwProcessId; /* Directs a wait thread in the thread pool to wait on the object. * The wait thread queues the specified callback function to the thread pool * when one of the following occurs: * - The specified object is in the signaled state. * - The time-out interval elapses. * When a process terminates, the state of the process object * becomes signaled, releasing any threads * that had been waiting for the process to terminate. */ if (!RegisterWaitForSingleObject( &childInfo->waitHandle, pi.hProcess, deadChildProcCallBack, childInfo, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD)) elog->log(LOG_ERROR, ERROR_CODE_REGISTER_WAIT_HANDLER_FAILED, "Could not register process for wait: error code %lu", GetLastError()); /* Don't close pi.hProcess here - * the wait thread needs access to it. */ CloseHandle(pi.hThread); return pi.hProcess; }
static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { uv_loop_t* loop = handle->loop; BOOL success; DWORD bytes; SOCKET accept_socket; short family; assert(handle->flags & UV_HANDLE_LISTENING); assert(req->accept_socket == INVALID_SOCKET); /* choose family and extension function */ if (handle->flags & UV_HANDLE_IPV6) { family = AF_INET6; } else { family = AF_INET; } /* Open a socket for the accepted connection. */ accept_socket = socket(family, SOCK_STREAM, 0); if (accept_socket == INVALID_SOCKET) { SET_REQ_ERROR(req, WSAGetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; return; } /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->overlapped.hEvent = (HANDLE) ((DWORD) req->event_handle | 1); } success = handle->func_acceptex(handle->socket, accept_socket, (void*)req->accept_buffer, 0, sizeof(struct sockaddr_storage), sizeof(struct sockaddr_storage), &bytes, &req->overlapped); if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { /* Process the req without IOCP. */ req->accept_socket = accept_socket; handle->reqs_pending++; uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(success)) { /* The req will be processed with IOCP. */ req->accept_socket = accept_socket; handle->reqs_pending++; if (handle->flags & UV_HANDLE_EMULATE_IOCP && req->wait_handle == INVALID_HANDLE_VALUE && !RegisterWaitForSingleObject(&req->wait_handle, req->overlapped.hEvent, post_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; return; } } else { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; /* Destroy the preallocated client socket. */ closesocket(accept_socket); /* Destroy the event handle */ if (handle->flags & UV_HANDLE_EMULATE_IOCP) { CloseHandle(req->overlapped.hEvent); req->event_handle = NULL; } } }
static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { uv_read_t* req; uv_buf_t buf; int result; DWORD bytes, flags; assert(handle->flags & UV_HANDLE_READING); assert(!(handle->flags & UV_HANDLE_READ_PENDING)); req = &handle->read_req; memset(&req->overlapped, 0, sizeof(req->overlapped)); /* * Preallocate a read buffer if the number of active streams is below * the threshold. */ if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) { handle->flags &= ~UV_HANDLE_ZERO_READ; handle->read_buffer = handle->alloc_cb((uv_handle_t*) handle, 65536); assert(handle->read_buffer.len > 0); buf = handle->read_buffer; } else { handle->flags |= UV_HANDLE_ZERO_READ; buf.base = (char*) &uv_zero_; buf.len = 0; } /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { assert(req->event_handle); req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); } flags = 0; result = WSARecv(handle->socket, (WSABUF*)&buf, 1, &bytes, &flags, &req->overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Process the req without IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; req->overlapped.InternalHigh = bytes; handle->reqs_pending++; uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* The req will be processed with IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; if (handle->flags & UV_HANDLE_EMULATE_IOCP && req->wait_handle == INVALID_HANDLE_VALUE && !RegisterWaitForSingleObject(&req->wait_handle, req->event_handle, post_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); } } else { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; } }
DWORD WINAPI SvcRegisterStopCallback ( _In_ PHANDLE phNewWaitObject, _In_ LPCWSTR ServiceName, _In_ HANDLE hObject, _In_ PSVCHOST_STOP_CALLBACK pfnStopCallback, _In_ PVOID pContext, _In_ ULONG dwFlags ) { ULONG i; PSVCHOST_CALLBACK_CONTEXT pSvcsStopCbContext = NULL; PSVCHOST_SERVICE pService = NULL; DWORD dwError = ERROR_SUCCESS; /* All parameters must be present */ if ((phNewWaitObject == NULL) || (ServiceName == NULL) || (hObject == NULL) || (pfnStopCallback == NULL)) { /* Fail otherwise */ return ERROR_INVALID_PARAMETER; } /* Don't allow new DLLs while we send notifications */ EnterCriticalSection(&ListLock); /* Scan all registered services */ for (i = 0; i < ServiceCount; i++) { /* Search for the service entry matching this service name */ if (lstrcmpiW(ServiceName, ServiceArray[i].pszServiceName) == 0) { /* Found it */ pService = &ServiceArray[i]; break; } } /* Do we have a service? Does it already have a callback? */ if ((pService == NULL) || (pService->pfnStopCallback != NULL)) { /* Affirmative, nothing for us to do */ dwError = ERROR_INVALID_DATA; DBG_ERR("Service %ws missing or already registered for callback, " "status %d\n", ServiceName, dwError); goto Quickie; } /* Allocate our internal context */ pSvcsStopCbContext = MemAlloc(HEAP_ZERO_MEMORY, sizeof(*pSvcsStopCbContext)); if (pSvcsStopCbContext == NULL) { /* We failed, bail out */ dwError = ERROR_NOT_ENOUGH_MEMORY; DBG_ERR("MemAlloc for context block for service %ws failed, status " "%d\n", ServiceName, dwError); goto Quickie; } /* Setup the context and register for the wait */ pSvcsStopCbContext->pContext = pContext; pSvcsStopCbContext->pService = pService; if (RegisterWaitForSingleObject(phNewWaitObject, hObject, SvchostStopCallback, pSvcsStopCbContext, INFINITE, dwFlags)) { /* We now have an active thread associated with this wait */ pService->cServiceActiveThreadCount++; pService->pfnStopCallback = pfnStopCallback; DBG_TRACE("Registered stop callback for service %ws, active threads %d\n", ServiceName, pService->cServiceActiveThreadCount); } else { /* Registration failed, bail out */ dwError = GetLastError(); DBG_ERR("Registration for stop callback for service %ws failed, " "status %d\n", ServiceName, dwError); } Quickie: /* Drop the lock, and free the context if we failed */ LeaveCriticalSection(&ListLock); if (dwError != ERROR_SUCCESS) MemFree(pSvcsStopCbContext); return dwError; }
int uv_spawn(uv_loop_t* loop, uv_process_t* process, uv_process_options_t options) { int i; uv_err_t err = uv_ok_; WCHAR* path = NULL; BOOL result; WCHAR* application_path = NULL, *application = NULL, *arguments = NULL, *env = NULL, *cwd = NULL; STARTUPINFOW startup; PROCESS_INFORMATION info; DWORD process_flags; if (options.flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } if (options.file == NULL || options.args == NULL) { uv__set_artificial_error(loop, UV_EINVAL); return -1; } assert(options.file != NULL); assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS | UV_PROCESS_DETACHED | UV_PROCESS_SETGID | UV_PROCESS_SETUID))); uv_process_init(loop, process); process->exit_cb = options.exit_cb; err = uv_utf8_to_utf16_alloc(options.file, &application); if (err.code != UV_OK) goto done; err = make_program_args(options.args, options.flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, &arguments); if (err.code != UV_OK) goto done; if (options.cwd) { /* Explicit cwd */ err = uv_utf8_to_utf16_alloc(options.cwd, &cwd); if (err.code != UV_OK) goto done; } else { /* Inherit cwd */ DWORD cwd_len, r; cwd_len = GetCurrentDirectoryW(0, NULL); if (!cwd_len) { err = uv__new_sys_error(GetLastError()); goto done; } cwd = (WCHAR*) malloc(cwd_len * sizeof(WCHAR)); if (cwd == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto done; } r = GetCurrentDirectoryW(cwd_len, cwd); if (r == 0 || r >= cwd_len) { err = uv__new_sys_error(GetLastError()); goto done; } } /* Get PATH environment variable. */ { DWORD path_len, r; path_len = GetEnvironmentVariableW(L"PATH", NULL, 0); if (path_len == 0) { err = uv__new_sys_error(GetLastError()); goto done; } path = (WCHAR*) malloc(path_len * sizeof(WCHAR)); if (path == NULL) { err = uv__new_artificial_error(UV_ENOMEM); goto done; } r = GetEnvironmentVariableW(L"PATH", path, path_len); if (r == 0 || r >= path_len) { err = uv__new_sys_error(GetLastError()); goto done; } } application_path = search_path(application, cwd, path); if (application_path == NULL) { /* Not found. */ err = uv__new_artificial_error(UV_ENOENT); goto done; } err = uv__stdio_create(loop, &options, &process->child_stdio_buffer); if (err.code != UV_OK) goto done; startup.cb = sizeof(startup); startup.lpReserved = NULL; startup.lpDesktop = NULL; startup.lpTitle = NULL; startup.dwFlags = STARTF_USESTDHANDLES; startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer); startup.lpReserved2 = (BYTE*) process->child_stdio_buffer; startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0); startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1); startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2); process_flags = CREATE_UNICODE_ENVIRONMENT; if (options.flags & UV_PROCESS_DETACHED) { process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; } if (CreateProcessW(application_path, arguments, NULL, NULL, 1, process_flags, env, cwd, &startup, &info)) { /* Spawn succeeded */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; /* Set IPC pid to all IPC pipes. */ for (i = 0; i < options.stdio_count; i++) { const uv_stdio_container_t* fdopt = &options.stdio[i]; if (fdopt->flags & UV_CREATE_PIPE && fdopt->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) fdopt->data.stream)->ipc) { ((uv_pipe_t*) fdopt->data.stream)->ipc_pid = info.dwProcessId; } } /* Setup notifications for when the child process exits. */ result = RegisterWaitForSingleObject(&process->wait_handle, process->process_handle, exit_wait_callback, (void*)process, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); if (!result) { uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } CloseHandle(info.hThread); } else { /* CreateProcessW failed. */ err = uv__new_sys_error(GetLastError()); } done: free(application); free(application_path); free(arguments); free(cwd); free(env); free(path); process->spawn_error = err; if (process->child_stdio_buffer != NULL) { /* Clean up child stdio handles. */ uv__stdio_destroy(process->child_stdio_buffer); process->child_stdio_buffer = NULL; } /* Make the handle active. It will remain active until the exit callback */ /* is made or the handle is closed, whichever happens first. */ uv__handle_start(process); /* If an error happened, queue the exit req. */ if (err.code != UV_OK) { process->exit_cb_pending = 1; uv_insert_pending_req(loop, (uv_req_t*) &process->exit_req); } return 0; }
static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { uv_read_t* req; int result; assert(handle->flags & UV_HANDLE_READING); assert(!(handle->flags & UV_HANDLE_READ_PENDING)); assert(handle->handle != INVALID_HANDLE_VALUE); req = &handle->read_req; if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc, req, WT_EXECUTELONGFUNCTION)) { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, GetLastError()); goto error; } } else { memset(&req->overlapped, 0, sizeof(req->overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1); } /* Do 0-read */ result = ReadFile(handle->handle, &uv_zero_, 0, NULL, &req->overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, GetLastError()); goto error; } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (!req->event_handle) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } } if (req->wait_handle == INVALID_HANDLE_VALUE) { if (!RegisterWaitForSingleObject(&req->wait_handle, req->overlapped.hEvent, post_completion_read_wait, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); goto error; } } } } /* Start the eof timer if there is one */ eof_timer_start(handle); handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; return; error: uv_insert_pending_req(loop, (uv_req_t*)req); handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; }