Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
11 KiB

  1. /*++
  2. *
  3. * Component: hidserv.dll
  4. * File: hidserv.c
  5. * Purpose: main entry and NT service routines.
  6. *
  7. * Copyright (C) Microsoft Corporation 1997,1998. All rights reserved.
  8. *
  9. * WGJ
  10. --*/
  11. #include "hidserv.h"
  12. TCHAR HidservDisplayName[] = TEXT("HID Input Service");
  13. VOID
  14. InitializeGlobals()
  15. /*++
  16. Routine Description:
  17. Since .dll might be unloaded/loaded into the same process, so must reinitialize global vars
  18. --*/
  19. {
  20. PnpEnabled = FALSE;
  21. hNotifyArrival = 0;
  22. INITIAL_WAIT = 500;
  23. REPEAT_INTERVAL = 150;
  24. hInstance = 0;
  25. hWndHidServ = 0;
  26. cThreadRef = 0;
  27. hMutexOOC = 0;
  28. hService = 0;
  29. }
  30. void
  31. StartHidserv(
  32. void
  33. )
  34. /*++
  35. Routine Description:
  36. Cal the SCM to start the NT service.
  37. --*/
  38. {
  39. SC_HANDLE hSCM;
  40. SC_HANDLE hService;
  41. BOOL Ret;
  42. INFO(("Start HidServ Service."));
  43. // Open the SCM on this machine.
  44. hSCM = OpenSCManager( NULL,
  45. NULL,
  46. SC_MANAGER_CONNECT);
  47. if (hSCM) {
  48. // Open this service for DELETE access
  49. hService = OpenService( hSCM,
  50. HidservServiceName,
  51. SERVICE_START);
  52. if(hService) {
  53. // Start this service.
  54. Ret = StartService( hService,
  55. 0,
  56. NULL);
  57. // Close the service and the SCM
  58. CloseServiceHandle(hService);
  59. }
  60. CloseServiceHandle(hSCM);
  61. }
  62. }
  63. void
  64. StopHidserv(
  65. void
  66. )
  67. /*++
  68. Routine Description:
  69. Cal the SCM to stop the NT service.
  70. --*/
  71. {
  72. SC_HANDLE hSCM;
  73. SC_HANDLE hService;
  74. SERVICE_STATUS Status;
  75. BOOL Ret;
  76. INFO(("Stop HidServ Service."));
  77. // Open the SCM on this machine.
  78. hSCM = OpenSCManager( NULL,
  79. NULL,
  80. SC_MANAGER_CONNECT);
  81. if (hSCM) {
  82. // Open this service for DELETE access
  83. hService = OpenService( hSCM,
  84. HidservServiceName,
  85. SERVICE_STOP);
  86. if(hService) {
  87. // Stop this service.
  88. Ret = ControlService( hService,
  89. SERVICE_CONTROL_STOP,
  90. &Status);
  91. CloseServiceHandle(hService);
  92. }
  93. CloseServiceHandle(hSCM);
  94. }
  95. }
  96. void
  97. InstallHidserv(
  98. void
  99. )
  100. /*++
  101. Routine Description:
  102. Install the NT service to Auto-start with no dependencies.
  103. --*/
  104. {
  105. SC_HANDLE hService;
  106. SC_HANDLE hSCM;
  107. TCHAR szModulePathname[] = TEXT("%SystemRoot%\\system32\\hidserv.exe");
  108. BOOL stop = FALSE;
  109. INFO(("Install HidServ Service."));
  110. // Open the SCM on this machine.
  111. hSCM = OpenSCManager( NULL,
  112. NULL,
  113. SC_MANAGER_ALL_ACCESS);
  114. if (hSCM) {
  115. // Add this service to the SCM's database.
  116. hService = CreateService( hSCM,
  117. HidservServiceName,
  118. HidservDisplayName,
  119. SERVICE_ALL_ACCESS,
  120. SERVICE_WIN32_OWN_PROCESS,
  121. SERVICE_AUTO_START,
  122. SERVICE_ERROR_NORMAL,
  123. szModulePathname,
  124. NULL, NULL, NULL,
  125. NULL, NULL);
  126. if(hService) {
  127. CloseServiceHandle(hService);
  128. } else {
  129. if (GetLastError() == ERROR_SERVICE_EXISTS) {
  130. hService = OpenService(hSCM,
  131. HidservServiceName,
  132. SERVICE_ALL_ACCESS);
  133. if (hService) {
  134. QUERY_SERVICE_CONFIG config;
  135. DWORD junk;
  136. if (QueryServiceConfig(hService,
  137. &config,
  138. sizeof(QUERY_SERVICE_CONFIG),
  139. &junk)) {
  140. if (config.dwServiceType & SERVICE_INTERACTIVE_PROCESS) {
  141. ChangeServiceConfig(hService,
  142. SERVICE_WIN32_OWN_PROCESS,
  143. SERVICE_AUTO_START,
  144. SERVICE_ERROR_NORMAL,
  145. szModulePathname,
  146. NULL, NULL, NULL,
  147. NULL, NULL,
  148. HidservDisplayName);
  149. stop = TRUE;
  150. }
  151. }
  152. }
  153. }
  154. }
  155. CloseServiceHandle(hSCM);
  156. if (stop) {
  157. StopHidserv();
  158. }
  159. }
  160. // Go ahead and start the service for no-reboot install.
  161. StartHidserv();
  162. }
  163. void
  164. RemoveHidserv(
  165. void
  166. )
  167. /*++
  168. Routine Description:
  169. Remove the NT service from the registry database.
  170. --*/
  171. {
  172. SC_HANDLE hSCM;
  173. SC_HANDLE hService;
  174. INFO(("Remove HidServ Service."));
  175. // Stop the service first
  176. StopHidserv();
  177. // Open the SCM on this machine.
  178. hSCM = OpenSCManager( NULL,
  179. NULL,
  180. SC_MANAGER_CONNECT);
  181. if (hSCM) {
  182. // Open this service for DELETE access
  183. hService = OpenService( hSCM,
  184. HidservServiceName,
  185. DELETE);
  186. if(hService) {
  187. // Remove this service from the SCM's database.
  188. DeleteService(hService);
  189. CloseServiceHandle(hService);
  190. }
  191. CloseServiceHandle(hSCM);
  192. }
  193. }
  194. DWORD
  195. WINAPI
  196. ServiceHandlerEx(
  197. DWORD fdwControl, // requested control code
  198. DWORD dwEventType, // event type
  199. LPVOID lpEventData, // event data
  200. LPVOID lpContext // user-defined context data
  201. )
  202. /*++
  203. Routine Description:
  204. Handle the service handler requests as required by the app.
  205. This should virtually always be an async PostMessage. Do not
  206. block this thread.
  207. --*/
  208. {
  209. PWTSSESSION_NOTIFICATION sessionNotification;
  210. switch (fdwControl)
  211. {
  212. case SERVICE_CONTROL_INTERROGATE:
  213. INFO(("ServiceHandler Request SERVICE_CONTROL_INTERROGATE (%x)", fdwControl));
  214. SetServiceStatus(hService, &ServiceStatus);
  215. return NO_ERROR;
  216. case SERVICE_CONTROL_CONTINUE:
  217. INFO(("ServiceHandler Request SERVICE_CONTROL_CONTINUE (%x)", fdwControl));
  218. //SET_SERVICE_STATE(SERVICE_START_PENDING);
  219. //PostMessage(hWndMmHid, WM_MMHID_START, 0, 0);
  220. return NO_ERROR;
  221. case SERVICE_CONTROL_PAUSE:
  222. INFO(("ServiceHandler Request SERVICE_CONTROL_PAUSE (%x)", fdwControl));
  223. //SET_SERVICE_STATE(SERVICE_PAUSE_PENDING);
  224. //PostMessage(hWndMmHid, WM_MMHID_STOP, 0, 0);
  225. return NO_ERROR;
  226. case SERVICE_CONTROL_STOP:
  227. INFO(("ServiceHandler Request SERVICE_CONTROL_STOP (%x)", fdwControl));
  228. SET_SERVICE_STATE(SERVICE_STOP_PENDING);
  229. PostMessage(hWndHidServ, WM_CLOSE, 0, 0);
  230. return NO_ERROR;
  231. case SERVICE_CONTROL_SHUTDOWN:
  232. INFO(("ServiceHandler Request SERVICE_CONTROL_SHUTDOWN (%x)", fdwControl));
  233. SET_SERVICE_STATE(SERVICE_STOP_PENDING);
  234. PostMessage(hWndHidServ, WM_CLOSE, 0, 0);
  235. return NO_ERROR;
  236. case SERVICE_CONTROL_SESSIONCHANGE:
  237. INFO(("ServiceHandler Request SERVICE_CONTROL_SESSIONCHANGE (%x)", fdwControl));
  238. sessionNotification = (PWTSSESSION_NOTIFICATION)lpEventData;
  239. PostMessage(hWndHidServ, WM_WTSSESSION_CHANGE, dwEventType, (LPARAM)sessionNotification->dwSessionId);
  240. return NO_ERROR;
  241. default:
  242. WARN(("Unhandled ServiceHandler code, (%x)", fdwControl));
  243. }
  244. return ERROR_CALL_NOT_IMPLEMENTED;
  245. }
  246. VOID
  247. WINAPI
  248. ServiceMain(
  249. DWORD dwArgc,
  250. LPWSTR * lpszArgv
  251. )
  252. /*++
  253. Routine Description:
  254. The main thread for the Hid Audio service.
  255. --*/
  256. {
  257. HANDLE initDoneEvent;
  258. InitializeGlobals();
  259. initDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  260. ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  261. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  262. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_SESSIONCHANGE;
  263. ServiceStatus.dwWin32ExitCode = NO_ERROR;
  264. ServiceStatus.dwServiceSpecificExitCode = NO_ERROR;
  265. ServiceStatus.dwCheckPoint = 0;
  266. ServiceStatus.dwWaitHint = 0;
  267. hService =
  268. RegisterServiceCtrlHandlerEx(HidservServiceName,
  269. ServiceHandlerEx,
  270. NULL);
  271. SET_SERVICE_STATE(SERVICE_START_PENDING);
  272. CreateThread(
  273. NULL, // pointer to thread security attributes
  274. 0, // initial thread stack size, in bytes (0 = default)
  275. HidServMain, // pointer to thread function
  276. initDoneEvent, // argument for new thread
  277. 0, // creation flags
  278. &MessagePumpThreadId // pointer to returned thread identifier
  279. );
  280. if (initDoneEvent) {
  281. WaitForSingleObject(initDoneEvent, INFINITE);
  282. CloseHandle(initDoneEvent);
  283. }
  284. SET_SERVICE_STATE(SERVICE_RUNNING);
  285. }
  286. int
  287. WINAPI
  288. WinMain(
  289. HINSTANCE hInstance,
  290. HINSTANCE hPrevInstance,
  291. PSTR szCmdLine,
  292. int iCmdShow
  293. )
  294. /*++
  295. Routine Description:
  296. HidServ starts as an NT Service (started by the SCM) unless
  297. a command line param is passed in. Command line params may be
  298. used to start HidServ as a free-standing app, or to control
  299. the NT service.
  300. If compiled non-unicode, we bypass all the NT stuff.
  301. --*/
  302. {
  303. int nArgc = __argc;
  304. int i;
  305. #ifdef UNICODE
  306. LPCTSTR *ppArgv = (LPCTSTR*) CommandLineToArgvW(GetCommandLine(), &nArgc);
  307. #else
  308. LPCTSTR *ppArgv = NULL;
  309. #endif
  310. TRACE(("HidServ Service process WinMain."));
  311. if(ppArgv){
  312. for (i = 1; i < nArgc; i++) {
  313. if ((ppArgv[i][0] == TEXT('-')) || (ppArgv[i][0] == TEXT('/'))) {
  314. // Command line switch
  315. if (lstrcmpi(&ppArgv[i][1], TEXT("install")) == 0)
  316. InstallHidserv();
  317. if (lstrcmpi(&ppArgv[i][1], TEXT("remove")) == 0)
  318. RemoveHidserv();
  319. if (lstrcmpi(&ppArgv[i][1], TEXT("start")) == 0)
  320. StartHidserv();
  321. if (lstrcmpi(&ppArgv[i][1], TEXT("stop")) == 0)
  322. StopHidserv();
  323. }
  324. }
  325. #ifdef UNICODE
  326. HeapFree(GetProcessHeap(), 0, (PVOID) ppArgv);
  327. #endif
  328. }
  329. if (nArgc < 2) {
  330. // No command line params, so this is the SCM...
  331. SERVICE_TABLE_ENTRY ServiceTable[] = {
  332. { HidservServiceName, ServiceMain },
  333. { NULL, NULL } // End of list
  334. };
  335. INFO(("Start HidServ Service Control Dispatcher."));
  336. StartServiceCtrlDispatcher(ServiceTable);
  337. }
  338. return(0);
  339. }