/*++ * * 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 InstallHidserv( HWND hwnd, HINSTANCE hInstance, LPSTR szCmdLine, int iCmdShow ) /*++ Routine Description: Install the NT service to Auto-start with no dependencies. --*/ { SC_HANDLE hService; SC_HANDLE hSCM; // Open the SCM on this machine. hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (hSCM) { // Service exists, set to autostart hService = OpenService(hSCM, HidservServiceName, SERVICE_ALL_ACCESS); if (hService) { QUERY_SERVICE_CONFIG config; DWORD junk; HKEY hKey; LONG status; if (ChangeServiceConfig(hService, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, HidservDisplayName)) { // Wait until we're configured correctly. while (QueryServiceConfig(hService, &config, sizeof(config), &junk)) { if (config.dwStartType == SERVICE_AUTO_START) { break; } } } CloseServiceHandle(hService); } } // Go ahead and start the service for no-reboot install. StartHidserv(); } 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 service. --*/ { HANDLE initDoneEvent; HANDLE threadHandle; InitializeGlobals(); initDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!initDoneEvent) { goto ServiceMainError; } 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); if (!hService) { goto ServiceMainError; } SET_SERVICE_STATE(SERVICE_START_PENDING); threadHandle = 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 (!threadHandle) { goto ServiceMainError; } WaitForSingleObject(initDoneEvent, INFINITE); CloseHandle(threadHandle); ServiceMainError: if (initDoneEvent) { CloseHandle(initDoneEvent); } }