void omni_thread::start(void) { omni_mutex_lock l(mutex); if (_state != STATE_NEW) throw omni_thread_invalid(); #ifndef __BCPLUSPLUS__ // MSVC++ or compatiable unsigned int t; handle = (HANDLE)_beginthreadex( NULL, 0, omni_thread_wrapper, (LPVOID)this, CREATE_SUSPENDED, &t); nt_id = t; if (handle == NULL) throw omni_thread_fatal(GetLastError()); #else // Borland C++ handle = (HANDLE)_beginthreadNT(omni_thread_wrapper, 0, (void*)this, NULL, CREATE_SUSPENDED, &nt_id); if (handle == INVALID_HANDLE_VALUE) throw omni_thread_fatal(errno); #endif if (!SetThreadPriority(handle, nt_priority(_priority))) throw omni_thread_fatal(GetLastError()); if (ResumeThread(handle) == 0xffffffff) throw omni_thread_fatal(GetLastError()); _state = STATE_RUNNING; }
// ------------------------------------------------------------------------- // void KsNtServiceServer::serviceMain(int argc, char **argv) { // // First, create some signaling objects. The _one_shot_event signals // the serviceRun() task that it should wake up and iterate once again, // thus spinning up the KS server, and process requests. The next event, // _service_done_event, signals, that the whole service task (executable) // is now ready to cease. // _service_done_event = CreateEvent(0, FALSE, FALSE, 0); _one_shot_event = CreateEvent(0, FALSE, FALSE, 0); if ( !_service_done_event || !_one_shot_event ) { lastError("Can't initialize signaling mechanism"); } // // Next, register the service controller. Remember, that only after we've // done this, we can report the service status to the service manager. // _service_status_handle = RegisterServiceCtrlHandler( (LPCTSTR) _service_name, (LPHANDLER_FUNCTION) ks_c_serviceController); if ( !_service_status_handle ) { lastError("Can't register service control handler"); return; } // // Next, we ask the developer for a KS server object, which will be // subsequently used within the real workhorse thread. // reportServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, _create_to); _my_server = createServer((int) argc, (char **) argv); if ( !_is_ok || (_my_server == 0) || !_my_server->isOk() ) { _is_ok = false; PltLog::Error("abnormal service termination"); return; } verbose("Created server object successfully"); reportServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, _spinup_to); // // We must use the apropriate function from the C++ RTL here, as we will // otherwise get memory leaks. As if NT wouldn't be the biggest memory // leak ever created by menkind... // #if PLT_COMPILER_MSVC _workhorse_thread = (HANDLE) _beginthread( (void (*)(void *)) ks_c_serviceRun, // entry point of new thread 0, // stack size (default) 0); // arguments (none) #else # if PLT_COMPILER_BORLAND _workhorse_thread = (HANDLE) _beginthreadNT( (void (*)(void *)) ks_c_serviceRun, // entry point of new thread 32768, // initial stack size 0, // no arguments to pass to thread 0, // no security, as NT hasn't one... 0, // spin up thread immediately &_workhorse_thread_id); # else # error "Don't know how to start threads" # endif #endif if ( _workhorse_thread <= 0) { _is_ok = false; PltLog::Error("Can't start service thread"); return; } verbose("Started service thread"); // // Gosh! Finally, we're up and running. Yeah, I can't believe it! // reportServiceStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0); if ( WaitForSingleObject(_service_done_event, INFINITE) != WAIT_OBJECT_0 ) { PltLog::Warning("\"Service Done\" signaling failed"); } verbose("Service thread woken up"); if ( !TerminateThread(_workhorse_thread, 0) ) { lastError("Can't terminate service thread"); } if ( _my_server ) { delete _my_server; _my_server = 0; } // // Simply terminate. This will throw us back to the main thread. // reportServiceStatus(SERVICE_STOPPED, _service_status.dwWin32ExitCode, _service_status.dwServiceSpecificExitCode, 0, 0); } // KsNtServiceServer::serviceMain
// ------------------------------------------------------------------------- // // void KsW95ServiceServer::run() { if ( _is_ok ) { if ( _service_done_event == 0 ) { _service_done_event = CreateEvent(0, FALSE, FALSE, 0); if ( _service_done_event == 0 ) { _is_ok = false; PltLog::Error("Can't initialize signalling mechanism"); return; } } _my_server = createServer(_argc, _argv); if ( !_is_ok || (_my_server == 0) || !_my_server->isOk() ) { _is_ok = false; PltLog::Error("abnormal service termination"); return; } DWORD thread_id; // // We must use the apropriate function from the C++ RTL here, as we will // otherwise get memory leaks. As if NT wouldn't be the biggest memory // leak ever created by menkind... // #if PLT_COMPILER_MSVC _workhorse_thread = (HANDLE) _beginthread( (void (*)(void *)) ks_c_w95serviceRun, // entry point of new thread 0, // stack size (default) 0); // arguments (none) #elif PLT_COMPILER_BORLAND _workhorse_thread = (HANDLE) _beginthreadNT( (void (*)(void *)) ks_c_w95serviceRun, 32768, 0, 0, 0, &thread_id); #else # error "Don't know how to start threads" #endif _workhorse_thread_id = thread_id; if ( _workhorse_thread <= 0 ) { _is_ok = false; PltLog::Error("Can't start service thread"); return; } verbose("Service thread started"); // // Now keep on going, dispatching messages until we'll notify // ourself to quit the game. // MSG messageForYouSir; while ( GetMessage(&messageForYouSir, 0, 0, 0) > 0 ) { DispatchMessage(&messageForYouSir); } if ( _workhorse_thread > 0 ) { TerminateThread(_workhorse_thread, 0); } _workhorse_thread = 0; if ( _my_server ) { delete _my_server; _my_server = 0; } } } // KsW95ServiceServer::run