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.

400 lines
11 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. event.c
  5. Abstract:
  6. This module contains the event handling routines for SAC.
  7. Author:
  8. Sean Selitrennikoff (v-seans) - Jan 22, 1999
  9. Revision History:
  10. --*/
  11. #include "sac.h"
  12. //
  13. // Definitions for this file.
  14. //
  15. #define RESPONSE_BUFFER_SIZE (80 + sizeof(HEADLESS_RSP_GET_LINE) - sizeof(UCHAR))
  16. UCHAR ResponseBuffer[RESPONSE_BUFFER_SIZE];
  17. //
  18. // Forward declarations for this file.
  19. //
  20. VOID
  21. ProcessInputLine(
  22. VOID
  23. );
  24. VOID
  25. WorkerProcessEvents(
  26. IN PSAC_DEVICE_CONTEXT DeviceContext
  27. )
  28. /*++
  29. Routine Description:
  30. This is the routine for the worker thread. It blocks on an event, when
  31. the event is signalled, then that indicates a request is ready to be processed.
  32. Arguments:
  33. DeviceContext - A pointer to this device.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. NTSTATUS Status;
  39. KIRQL OldIrql;
  40. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC WorkerProcessEvents: Entering.\n")));
  41. //
  42. // Loop forever.
  43. //
  44. while (1) {
  45. //
  46. // Block until there is work to do.
  47. //
  48. Status = KeWaitForSingleObject((PVOID)&(DeviceContext->ProcessEvent), Executive, KernelMode, FALSE, NULL);
  49. if (DeviceContext->UnloadDeferred) {
  50. CancelIPIoRequest();
  51. SacPutSimpleMessage(SAC_ENTER);
  52. SacPutSimpleMessage(SAC_UNLOADED);
  53. SacPutSimpleMessage(SAC_ENTER);
  54. KeSetEvent(&(DeviceContext->UnloadEvent), DeviceContext->PriorityBoost, FALSE);
  55. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE, KdPrint(("SAC WorkerProcessEvents: Terminating.\n")));
  56. PsTerminateSystemThread(STATUS_SUCCESS);
  57. }
  58. switch ( ProcessingType ){
  59. case SAC_PROCESS_INPUT:
  60. //
  61. // Process the input line.
  62. //
  63. ProcessInputLine();
  64. //
  65. // Put the next command prompt
  66. //
  67. SacPutSimpleMessage(SAC_PROMPT);
  68. break;
  69. case SAC_SUBMIT_IOCTL:
  70. if ( !IoctlSubmitted ) {
  71. // submit the notify request with the
  72. // IP driver. This procedure will also
  73. // ensure that it is done only once in
  74. // the lifetime of the driver.
  75. SubmitIPIoRequest();
  76. }
  77. break;
  78. default:
  79. break;
  80. }
  81. //
  82. // Unset the processing flag
  83. //
  84. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  85. DeviceContext->Processing = FALSE;
  86. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  87. //
  88. // If there is any stuff that got delayed, process it.
  89. //
  90. DoDeferred(DeviceContext);
  91. }
  92. ASSERT(0);
  93. }
  94. VOID
  95. DoDeferred(
  96. IN PSAC_DEVICE_CONTEXT DeviceContext
  97. )
  98. {
  99. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC DoDeferred: Entering.\n")));
  100. if (DeviceContext->UnloadDeferred) {
  101. KeSetEvent(&(DeviceContext->UnloadEvent), DeviceContext->PriorityBoost, FALSE);
  102. }
  103. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC DoDeferred: Exiting.\n")));
  104. }
  105. VOID
  106. TimerDpcRoutine(
  107. IN struct _KDPC *Dpc,
  108. IN PVOID DeferredContext,
  109. IN PVOID SystemArgument1,
  110. IN PVOID SystemArgument2
  111. )
  112. /*++
  113. Routine Description:
  114. This is a DPC routine that is queue'd by DriverEntry. It is used to check for any
  115. user input and then processes them.
  116. Arguments:
  117. DeferredContext - A pointer to the device context.
  118. All other parameters are unused.
  119. Return Value:
  120. None.
  121. --*/
  122. {
  123. PSAC_DEVICE_CONTEXT DeviceContext = (PSAC_DEVICE_CONTEXT)DeferredContext;
  124. KIRQL OldIrql;
  125. SIZE_T i;
  126. PHEADLESS_RSP_GET_LINE Response;
  127. NTSTATUS Status;
  128. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Entering.\n")));
  129. UNREFERENCED_PARAMETER(Dpc);
  130. UNREFERENCED_PARAMETER(SystemArgument1);
  131. UNREFERENCED_PARAMETER(SystemArgument2);
  132. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  133. //
  134. // If we are processing, then move on.
  135. //
  136. if (DeviceContext->Processing) {
  137. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  138. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Exiting.\n")));
  139. return;
  140. }
  141. DeviceContext->Processing = TRUE;
  142. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  143. //
  144. // Check for user input
  145. //
  146. i = RESPONSE_BUFFER_SIZE;
  147. Response = (PHEADLESS_RSP_GET_LINE)ResponseBuffer;
  148. Status = HeadlessDispatch(HeadlessCmdGetLine,
  149. NULL,
  150. 0,
  151. Response,
  152. &i
  153. );
  154. if (NT_SUCCESS(Status) && Response->LineComplete) {
  155. //
  156. // Lower case all the characters. We do not use strlwr() or the like, so that
  157. // the SAC (expecting ASCII always) doesn't accidently get DBCS or the like
  158. // translation of the UCHAR stream.
  159. //
  160. Response->Buffer[(RESPONSE_BUFFER_SIZE - sizeof(HEADLESS_RSP_GET_LINE)) / sizeof(UCHAR)] = '\0';
  161. for (i = 0; Response->Buffer[i] != '\0'; i++) {
  162. if ((Response->Buffer[i] >= 'A') && (Response->Buffer[i] <= 'Z')) {
  163. Response->Buffer[i] = Response->Buffer[i] - 'A' + 'a';
  164. }
  165. }
  166. //
  167. // Fire off the worker thread to do the line. It will unset the processing
  168. // flag when it is done.
  169. //
  170. ProcessingType = SAC_PROCESS_INPUT;
  171. KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
  172. } else {
  173. if ( !IoctlSubmitted ) {
  174. // We Still need to try and submit the notify IOCTL
  175. if(Attempts == 0){
  176. ProcessingType = SAC_SUBMIT_IOCTL;
  177. Attempts = SAC_RETRY_GAP;
  178. KeSetEvent(&(DeviceContext->ProcessEvent), DeviceContext->PriorityBoost, FALSE);
  179. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Exiting.\n")));
  180. return;
  181. } else {
  182. Attempts --;
  183. }
  184. }
  185. KeAcquireSpinLock(&(DeviceContext->SpinLock), &OldIrql);
  186. DeviceContext->Processing = FALSE;
  187. KeReleaseSpinLock(&(DeviceContext->SpinLock), OldIrql);
  188. //
  189. // If there is any, process it.
  190. //
  191. DoDeferred(DeviceContext);
  192. }
  193. IF_SAC_DEBUG(SAC_DEBUG_FUNC_TRACE_LOUD, KdPrint(("SAC TimerDpcRoutine: Exiting.\n")));
  194. }
  195. VOID
  196. ProcessInputLine(
  197. VOID
  198. )
  199. /*++
  200. Routine Description:
  201. This routine is called to process an input line.
  202. Arguments:
  203. None.
  204. Return Value:
  205. None.
  206. --*/
  207. {
  208. HEADLESS_CMD_DISPLAY_LOG Command;
  209. PUCHAR InputLine;
  210. BOOLEAN CommandFound = FALSE;
  211. InputLine = &(((PHEADLESS_RSP_GET_LINE)ResponseBuffer)->Buffer[0]);
  212. if (!strcmp((LPSTR)InputLine, TLIST_COMMAND_STRING)) {
  213. DoTlistCommand();
  214. CommandFound = TRUE;
  215. } else if ((!strcmp((LPSTR)InputLine, HELP1_COMMAND_STRING)) ||
  216. (!strcmp((LPSTR)InputLine, HELP2_COMMAND_STRING))) {
  217. DoHelpCommand();
  218. CommandFound = TRUE;
  219. } else if (!strcmp((LPSTR)InputLine, DUMP_COMMAND_STRING)) {
  220. Command.Paging = GlobalPagingNeeded;
  221. HeadlessDispatch(HeadlessCmdDisplayLog,
  222. &Command,
  223. sizeof(HEADLESS_CMD_DISPLAY_LOG),
  224. NULL,
  225. NULL
  226. );
  227. CommandFound = TRUE;
  228. } else if (!strcmp((LPSTR)InputLine, FULLINFO_COMMAND_STRING)) {
  229. DoFullInfoCommand();
  230. CommandFound = TRUE;
  231. } else if (!strcmp((LPSTR)InputLine, PAGING_COMMAND_STRING)) {
  232. DoPagingCommand();
  233. CommandFound = TRUE;
  234. } else if (!strcmp((LPSTR)InputLine, REBOOT_COMMAND_STRING)) {
  235. DoRebootCommand(TRUE);
  236. CommandFound = TRUE;
  237. } else if (!strcmp((LPSTR)InputLine, SHUTDOWN_COMMAND_STRING)) {
  238. DoRebootCommand(FALSE);
  239. CommandFound = TRUE;
  240. } else if (!strcmp((LPSTR)InputLine, CRASH_COMMAND_STRING)) {
  241. CommandFound = TRUE;
  242. DoCrashCommand(); // this call does not return
  243. } else if (!strncmp((LPSTR)InputLine,
  244. KILL_COMMAND_STRING,
  245. sizeof(KILL_COMMAND_STRING) - sizeof(UCHAR))) {
  246. if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
  247. DoKillCommand(InputLine);
  248. CommandFound = TRUE;
  249. }
  250. } else if (!strncmp((LPSTR)InputLine,
  251. LOWER_COMMAND_STRING,
  252. sizeof(LOWER_COMMAND_STRING) - sizeof(UCHAR))) {
  253. if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
  254. DoLowerPriorityCommand(InputLine);
  255. CommandFound = TRUE;
  256. }
  257. } else if (!strncmp((LPSTR)InputLine,
  258. RAISE_COMMAND_STRING,
  259. sizeof(RAISE_COMMAND_STRING) - sizeof(UCHAR))) {
  260. if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
  261. DoRaisePriorityCommand(InputLine);
  262. CommandFound = TRUE;
  263. }
  264. } else if (!strncmp((LPSTR)InputLine,
  265. LIMIT_COMMAND_STRING,
  266. sizeof(LIMIT_COMMAND_STRING) - sizeof(UCHAR))) {
  267. if ((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) {
  268. DoLimitMemoryCommand(InputLine);
  269. CommandFound = TRUE;
  270. }
  271. } else if (!strncmp((LPSTR)InputLine,
  272. TIME_COMMAND_STRING,
  273. sizeof(TIME_COMMAND_STRING) - sizeof(UCHAR))) {
  274. if (((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) ||
  275. (strlen((LPSTR)InputLine) == 1)) {
  276. DoSetTimeCommand(InputLine);
  277. CommandFound = TRUE;
  278. }
  279. } else if (!strcmp((LPSTR)InputLine, INFORMATION_COMMAND_STRING)) {
  280. DoMachineInformationCommand();
  281. CommandFound = TRUE;
  282. } else if (!strncmp((LPSTR)InputLine,
  283. SETIP_COMMAND_STRING,
  284. sizeof(SETIP_COMMAND_STRING) - sizeof(UCHAR))) {
  285. if (((strlen((LPSTR)InputLine) > 1) && (InputLine[1] == ' ')) ||
  286. (strlen((LPSTR)InputLine) == 1)) {
  287. DoSetIpAddressCommand(InputLine);
  288. CommandFound = TRUE;
  289. }
  290. } else if ((InputLine[0] == '\n') || (InputLine[0] == '\0')) {
  291. CommandFound = TRUE;
  292. }
  293. if( !CommandFound ) {
  294. //
  295. // We don't know what this is.
  296. //
  297. SacPutSimpleMessage(SAC_UNKNOWN_COMMAND);
  298. }
  299. }