| 326 | } |
| 327 | |
| 328 | int PipeServer::exec(LPSTR cmd) { |
| 329 | parseCommandLine(cmd); |
| 330 | |
| 331 | if (quitExistingLauncher_) { // terminate existing launcher process |
| 332 | if (HWND existingHwnd = ::FindWindow(wndClassName_, nullptr)) { |
| 333 | terminateExistingLauncher(existingHwnd); |
| 334 | } |
| 335 | return 0; |
| 336 | } |
| 337 | // ensure that only one instance of PIMELauncher can be running |
| 338 | if (!initSingleInstance()) { |
| 339 | return 0; |
| 340 | } |
| 341 | |
| 342 | // Ask Windows to restart our process when crashes happen. |
| 343 | RegisterApplicationRestart(L"/restarted", 0); // should not include executable name. |
| 344 | |
| 345 | // get the PIME installation directory |
| 346 | topDirPath_ = getCurrentExecutableDir(); |
| 347 | // must set CWD to our dir. otherwise the backends won't launch. |
| 348 | ::SetCurrentDirectoryW(topDirPath_.c_str()); |
| 349 | |
| 350 | // this is the first instance |
| 351 | initBackendServers(topDirPath_); |
| 352 | |
| 353 | // preparing for the server pipe |
| 354 | SECURITY_ATTRIBUTES* sa = nullptr; |
| 355 | if (::IsWindows8OrGreater()) { |
| 356 | // Setting special security attributes to the named pipe is only needed |
| 357 | // for Windows >= 8 since older versions do not have app containers (metro apps) |
| 358 | // in which connecting to pipes are blocked by default permission settings. |
| 359 | sa = securityAttributes_.get(); |
| 360 | } |
| 361 | // initialize the server pipe |
| 362 | initPipe(&serverPipe_, L"Launcher", sa); |
| 363 | |
| 364 | // listen to events from clients |
| 365 | uv_listen(reinterpret_cast<uv_stream_t*>(&serverPipe_), 32, [](uv_stream_t* server, int status) { |
| 366 | auto _this = reinterpret_cast<PipeServer*>(server->data); |
| 367 | _this->onNewClientConnected(server, status); |
| 368 | }); |
| 369 | |
| 370 | // run GUI message loop in another worker thread |
| 371 | uv_thread_t uiThread; |
| 372 | uv_thread_create(&uiThread, [](void* arg) { |
| 373 | reinterpret_cast<PipeServer*>(arg)->runGuiThread(); |
| 374 | }, this); |
| 375 | |
| 376 | // run the main loop |
| 377 | uv_run(uv_default_loop(), UV_RUN_DEFAULT); |
| 378 | |
| 379 | uv_thread_join(&uiThread); // wait for the GUI message loop to quit |
| 380 | return 0; |
| 381 | } |
| 382 | |
| 383 | // Window procedure of the main window |
| 384 | // this method is called from an worker thread other than the main thread |
no test coverage detected