| /* |
| * ServiceMain function for wiaservc running within svchost |
| * |
| * Copyright 2009 Damjan Jovanovic |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "windef.h" |
| #include "objbase.h" |
| #include "winsvc.h" |
| #include "wia_lh.h" |
| |
| #include "wiaservc_private.h" |
| |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(wia); |
| |
| static HANDLE stop_event = NULL; |
| |
| static SERVICE_STATUS_HANDLE status_handle; |
| static SERVICE_STATUS status; |
| static DWORD dwReg; |
| |
| static VOID |
| UpdateStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) |
| { |
| status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; |
| status.dwCurrentState = dwCurrentState; |
| if (dwCurrentState == SERVICE_START_PENDING) |
| status.dwControlsAccepted = 0; |
| else |
| status.dwControlsAccepted |
| = (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE |
| | SERVICE_ACCEPT_SHUTDOWN); |
| status.dwWin32ExitCode = 0; |
| status.dwServiceSpecificExitCode = 0; |
| status.dwCheckPoint = 0; |
| status.dwWaitHint = dwWaitHint; |
| |
| if (!SetServiceStatus(status_handle, &status)) { |
| ERR("failed to set service status\n"); |
| SetEvent(stop_event); |
| } |
| } |
| |
| /* Handle incoming ControlService signals */ |
| static DWORD WINAPI |
| ServiceHandler(DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context) |
| { |
| switch (ctrl) { |
| case SERVICE_CONTROL_STOP: |
| case SERVICE_CONTROL_SHUTDOWN: |
| TRACE("shutting down service\n"); |
| UpdateStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); |
| SetEvent(stop_event); |
| break; |
| default: |
| FIXME("ignoring handle service ctrl %x\n", ctrl); |
| UpdateStatus(status.dwCurrentState, NO_ERROR, 0); |
| break; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| static BOOL |
| StartCount(void) |
| { |
| HRESULT hr; |
| |
| TRACE("\n"); |
| |
| hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); |
| if (FAILED(hr)) |
| return FALSE; |
| |
| hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, |
| RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, |
| NULL); |
| if (FAILED(hr)) |
| return FALSE; |
| |
| hr = CoRegisterClassObject(&CLSID_WiaDevMgr, |
| (IUnknown *) &WIASERVC_ClassFactory, |
| CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, |
| &dwReg); |
| if (FAILED(hr)) |
| return FALSE; |
| |
| return TRUE; |
| } |
| |
| /* Service entry point */ |
| VOID WINAPI |
| ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv) |
| { |
| static const WCHAR stisvc_nameW[] = {'s','t','i','s','v','c',0}; |
| TRACE("(%d, %p)\n", dwArgc, lpszArgv); |
| |
| stop_event = CreateEventW(NULL, TRUE, FALSE, NULL); |
| if (!stop_event) { |
| ERR("failed to create stop_event\n"); |
| return; |
| } |
| |
| status_handle = RegisterServiceCtrlHandlerExW(stisvc_nameW, ServiceHandler, NULL); |
| if (!status_handle) { |
| ERR("failed to register handler: %u\n", GetLastError()); |
| return; |
| } |
| |
| UpdateStatus(SERVICE_START_PENDING, NO_ERROR, 3000); |
| if (!StartCount()) { |
| ERR("failed starting service thread\n"); |
| UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0); |
| return; |
| } |
| |
| UpdateStatus(SERVICE_RUNNING, NO_ERROR, 0); |
| |
| WaitForSingleObject(stop_event, INFINITE); |
| |
| CoRevokeClassObject(dwReg); |
| UpdateStatus(SERVICE_STOPPED, NO_ERROR, 0); |
| CloseHandle(stop_event); |
| TRACE("service stopped\n"); |
| |
| CoUninitialize(); |
| } |