windows-nt/Source/XPSP1/NT/drivers/wdm/input/client/hidserv/hidserv.c
2020-09-26 16:20:57 +08:00

397 lines
11 KiB
C

/*++
*
* 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);
}