/*++ * * Component: hidserv.dll * File: hidserv.c * Purpose: main entry and NT service routines. * * Copyright (C) Microsoft Corporation 1997,1998. All rights reserved. * * WGJ --*/ #include "hidserv.h" TCHAR HidservDisplayName[] = TEXT("HID Input Service"); VOID InitializeGlobals() /*++ Routine Description: Since .dll might be unloaded/loaded into the same process, so must reinitialize global vars --*/ { PnpEnabled = FALSE; hNotifyArrival = 0; INITIAL_WAIT = 500; REPEAT_INTERVAL = 150; hInstance = 0; hWndHidServ = 0; cThreadRef = 0; hMutexOOC = 0; hService = 0; } void StartHidserv( void ) /*++ Routine Description: Cal the SCM to start the NT service. --*/ { SC_HANDLE hSCM; SC_HANDLE hService; BOOL Ret; INFO(("Start HidServ Service.")); // Open the SCM on this machine. hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT); if (hSCM) { // Open this service for DELETE access hService = OpenService( hSCM, HidservServiceName, SERVICE_START); if(hService) { // Start this service. Ret = StartService( hService, 0, NULL); // Close the service and the SCM CloseServiceHandle(hService); } CloseServiceHandle(hSCM); } } void StopHidserv( void ) /*++ Routine Description: Cal the SCM to stop the NT service. --*/ { SC_HANDLE hSCM; SC_HANDLE hService; SERVICE_STATUS Status; BOOL Ret; INFO(("Stop HidServ Service.")); // Open the SCM on this machine. hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT); if (hSCM) { // Open this service for DELETE access hService = OpenService( hSCM, HidservServiceName, SERVICE_STOP); if(hService) { // Stop this service. Ret = ControlService( hService, SERVICE_CONTROL_STOP, &Status); CloseServiceHandle(hService); } CloseServiceHandle(hSCM); } } void InstallHidserv( void ) /*++ Routine Description: Install the NT service to Auto-start with no dependencies. --*/ { SC_HANDLE hService; SC_HANDLE hSCM; TCHAR szModulePathname[] = TEXT("%SystemRoot%\\system32\\hidserv.exe"); BOOL stop = FALSE; INFO(("Install HidServ Service.")); // Open the SCM on this machine. hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCM) { // Add this service to the SCM's database. hService = CreateService( hSCM, HidservServiceName, HidservDisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, szModulePathname, NULL, NULL, NULL, NULL, NULL); if(hService) { CloseServiceHandle(hService); } else { if (GetLastError() == ERROR_SERVICE_EXISTS) { hService = OpenService(hSCM, HidservServiceName, SERVICE_ALL_ACCESS); if (hService) { QUERY_SERVICE_CONFIG config; DWORD junk; if (QueryServiceConfig(hService, &config, sizeof(QUERY_SERVICE_CONFIG), &junk)) { if (config.dwServiceType & SERVICE_INTERACTIVE_PROCESS) { ChangeServiceConfig(hService, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, szModulePathname, NULL, NULL, NULL, NULL, NULL, HidservDisplayName); stop = TRUE; } } } } } CloseServiceHandle(hSCM); if (stop) { StopHidserv(); } } // Go ahead and start the service for no-reboot install. StartHidserv(); } void RemoveHidserv( void ) /*++ Routine Description: Remove the NT service from the registry database. --*/ { SC_HANDLE hSCM; SC_HANDLE hService; INFO(("Remove HidServ Service.")); // Stop the service first StopHidserv(); // Open the SCM on this machine. hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT); if (hSCM) { // Open this service for DELETE access hService = OpenService( hSCM, HidservServiceName, DELETE); if(hService) { // Remove this service from the SCM's database. DeleteService(hService); CloseServiceHandle(hService); } CloseServiceHandle(hSCM); } } DWORD WINAPI ServiceHandlerEx( DWORD fdwControl, // requested control code DWORD dwEventType, // event type LPVOID lpEventData, // event data LPVOID lpContext // user-defined context data ) /*++ Routine Description: Handle the service handler requests as required by the app. This should virtually always be an async PostMessage. Do not block this thread. --*/ { PWTSSESSION_NOTIFICATION sessionNotification; switch (fdwControl) { case SERVICE_CONTROL_INTERROGATE: INFO(("ServiceHandler Request SERVICE_CONTROL_INTERROGATE (%x)", fdwControl)); SetServiceStatus(hService, &ServiceStatus); return NO_ERROR; case SERVICE_CONTROL_CONTINUE: INFO(("ServiceHandler Request SERVICE_CONTROL_CONTINUE (%x)", fdwControl)); //SET_SERVICE_STATE(SERVICE_START_PENDING); //PostMessage(hWndMmHid, WM_MMHID_START, 0, 0); return NO_ERROR; case SERVICE_CONTROL_PAUSE: INFO(("ServiceHandler Request SERVICE_CONTROL_PAUSE (%x)", fdwControl)); //SET_SERVICE_STATE(SERVICE_PAUSE_PENDING); //PostMessage(hWndMmHid, WM_MMHID_STOP, 0, 0); return NO_ERROR; case SERVICE_CONTROL_STOP: INFO(("ServiceHandler Request SERVICE_CONTROL_STOP (%x)", fdwControl)); SET_SERVICE_STATE(SERVICE_STOP_PENDING); PostMessage(hWndHidServ, WM_CLOSE, 0, 0); return NO_ERROR; case SERVICE_CONTROL_SHUTDOWN: INFO(("ServiceHandler Request SERVICE_CONTROL_SHUTDOWN (%x)", fdwControl)); SET_SERVICE_STATE(SERVICE_STOP_PENDING); PostMessage(hWndHidServ, WM_CLOSE, 0, 0); return NO_ERROR; case SERVICE_CONTROL_SESSIONCHANGE: INFO(("ServiceHandler Request SERVICE_CONTROL_SESSIONCHANGE (%x)", fdwControl)); sessionNotification = (PWTSSESSION_NOTIFICATION)lpEventData; PostMessage(hWndHidServ, WM_WTSSESSION_CHANGE, dwEventType, (LPARAM)sessionNotification->dwSessionId); return NO_ERROR; default: WARN(("Unhandled ServiceHandler code, (%x)", fdwControl)); } return ERROR_CALL_NOT_IMPLEMENTED; } VOID WINAPI ServiceMain( DWORD dwArgc, LPWSTR * lpszArgv ) /*++ Routine Description: The main thread for the Hid Audio service. --*/ { HANDLE initDoneEvent; InitializeGlobals(); initDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; ServiceStatus.dwCurrentState = SERVICE_START_PENDING; ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_SESSIONCHANGE; ServiceStatus.dwWin32ExitCode = NO_ERROR; ServiceStatus.dwServiceSpecificExitCode = NO_ERROR; ServiceStatus.dwCheckPoint = 0; ServiceStatus.dwWaitHint = 0; hService = RegisterServiceCtrlHandlerEx(HidservServiceName, ServiceHandlerEx, NULL); SET_SERVICE_STATE(SERVICE_START_PENDING); CreateThread( NULL, // pointer to thread security attributes 0, // initial thread stack size, in bytes (0 = default) HidServMain, // pointer to thread function initDoneEvent, // argument for new thread 0, // creation flags &MessagePumpThreadId // pointer to returned thread identifier ); if (initDoneEvent) { WaitForSingleObject(initDoneEvent, INFINITE); CloseHandle(initDoneEvent); } SET_SERVICE_STATE(SERVICE_RUNNING); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) /*++ Routine Description: HidServ starts as an NT Service (started by the SCM) unless a command line param is passed in. Command line params may be used to start HidServ as a free-standing app, or to control the NT service. If compiled non-unicode, we bypass all the NT stuff. --*/ { int nArgc = __argc; int i; #ifdef UNICODE LPCTSTR *ppArgv = (LPCTSTR*) CommandLineToArgvW(GetCommandLine(), &nArgc); #else LPCTSTR *ppArgv = NULL; #endif TRACE(("HidServ Service process WinMain.")); if(ppArgv){ for (i = 1; i < nArgc; i++) { if ((ppArgv[i][0] == TEXT('-')) || (ppArgv[i][0] == TEXT('/'))) { // Command line switch if (lstrcmpi(&ppArgv[i][1], TEXT("install")) == 0) InstallHidserv(); if (lstrcmpi(&ppArgv[i][1], TEXT("remove")) == 0) RemoveHidserv(); if (lstrcmpi(&ppArgv[i][1], TEXT("start")) == 0) StartHidserv(); if (lstrcmpi(&ppArgv[i][1], TEXT("stop")) == 0) StopHidserv(); } } #ifdef UNICODE HeapFree(GetProcessHeap(), 0, (PVOID) ppArgv); #endif } if (nArgc < 2) { // No command line params, so this is the SCM... SERVICE_TABLE_ENTRY ServiceTable[] = { { HidservServiceName, ServiceMain }, { NULL, NULL } // End of list }; INFO(("Start HidServ Service Control Dispatcher.")); StartServiceCtrlDispatcher(ServiceTable); } return(0); }