void Service::Run() { // We use a message loop here because this is arguably the easiest // way to deal with the potential race conditions that exist between // the service thread and the handler thread. The SCM will make no // provisions for synchronizing status activity, the best bet is to // ensure that all calls are handled through the service main thread. MSG msg; while (GetMessage(&msg, NULL, WM_USER, WM_USER) > 0) { WPARAM opcode = msg.wParam; if (opcode == SERVICE_CONTROL_STOP) { SetStatus(SERVICE_STOP_PENDING); OnStop(); break; } else if (opcode == SERVICE_CONTROL_PAUSE) { OnPause(); } else if (opcode == SERVICE_CONTROL_CONTINUE) { OnContinue(); } else if (opcode == SERVICE_CONTROL_INTERROGATE) { OnInterrogate(); } else if (opcode == SERVICE_CONTROL_SHUTDOWN) { OnShutdown(); } ::SetServiceStatus(m_pThis->m_hServiceStatus, &m_pThis->m_Status); } }
DWORD Service::_HandlerEx(DWORD dwOpcode,DWORD dwEventType,LPVOID lpEventData,LPVOID lpContext) { m_dbgMsg(L"Service::Handler(%lu)", dwOpcode); switch (dwOpcode) { case SERVICE_CONTROL_STOP: // 1 SetStatus(SERVICE_STOP_PENDING); OnStop(); m_bIsRunning = FALSE; EVLOG_INFO(EVMSG_STOPPED); break; case SERVICE_CONTROL_PAUSE: // 2 OnPause(); break; case SERVICE_CONTROL_CONTINUE: // 3 OnContinue(); break; case SERVICE_CONTROL_INTERROGATE: // 4 OnInterrogate(); break; case SERVICE_CONTROL_SHUTDOWN: // 5 OnShutdown(); break; case SERVICE_CONTROL_DEVICEEVENT: OnDeviceEvent(dwEventType,lpEventData); break; default: if (dwOpcode >= SERVICE_CONTROL_USER) { if (!OnUserControl(dwOpcode)) { EVLOG_ERROR(EVMSG_BADREQUEST); } } else { EVLOG_ERROR(EVMSG_BADREQUEST); } break; } // Report current status m_dbgMsg(L"Updating status (%lu, %lu)", m_hServiceStatus, m_Status.dwCurrentState); ::SetServiceStatus(m_hServiceStatus, &m_Status); #ifdef HANDLEREX return NO_ERROR; #endif HANDLEREX }