2 * PROJECT: ReactOS Drivers
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/sac/driver/concmd.c
5 * PURPOSE: Driver for the Server Administration Console (SAC) for EMS
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
13 #include <ndk/exfuncs.h>
15 /* GLOBALS ********************************************************************/
18 ULONG GlobalBufferSize
;
20 /* FUNCTIONS ******************************************************************/
27 return STATUS_NOT_IMPLEMENTED
;
31 DoChannelCloseByNameCommand(
35 return STATUS_NOT_IMPLEMENTED
;
39 DoChannelCloseByIndexCommand(
43 return STATUS_NOT_IMPLEMENTED
;
47 DoChannelSwitchByNameCommand(
51 return STATUS_NOT_IMPLEMENTED
;
55 DoChannelSwitchByIndexCommand(
59 return STATUS_NOT_IMPLEMENTED
;
62 typedef struct _SAC_SYSTEM_INFORMATION
64 SYSTEM_BASIC_INFORMATION BasicInfo
;
65 SYSTEM_TIMEOFDAY_INFORMATION TimeInfo
;
66 SYSTEM_FILECACHE_INFORMATION CacheInfo
;
67 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
69 ULONG ProcessDataOffset
;
70 // SYSTEM_PAGEFILE_INFORMATION PageFileInfo;
71 // SYSTEM_PROCESS_INFORMATION ProcessInfo;
72 } SAC_SYSTEM_INFORMATION
, *PSAC_SYSTEM_INFORMATION
;
76 GetTListInfo(IN PSAC_SYSTEM_INFORMATION SacInfo
,
81 ULONG BufferLength
, ReturnLength
, RemainingSize
;
82 PSYSTEM_PAGEFILE_INFORMATION PageFileInfo
;
83 PSYSTEM_PROCESS_INFORMATION ProcessInfo
;
85 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering.\n");
90 /* Bail out if the buffer is way too small */
93 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory.\n");
94 return STATUS_NO_MEMORY
;
97 /* Make sure it's at least big enough to hold the static structure */
98 BufferLength
= InputSize
- sizeof(SAC_SYSTEM_INFORMATION
);
99 if (InputSize
< sizeof(SAC_SYSTEM_INFORMATION
))
101 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory (2).\n");
102 return STATUS_NO_MEMORY
;
106 Status
= ZwQuerySystemInformation(SystemTimeOfDayInformation
,
108 sizeof(SacInfo
->TimeInfo
),
110 if (!NT_SUCCESS(Status
))
112 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error.\n");
116 /* Query basic information */
117 Status
= ZwQuerySystemInformation(SystemBasicInformation
,
119 sizeof(SacInfo
->BasicInfo
),
121 if (!NT_SUCCESS(Status
))
123 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error (2).\n");
127 /* Now query the pagefile information, which comes right after */
128 P
= (ULONG_PTR
)(SacInfo
+ 1);
129 PageFileInfo
= (PSYSTEM_PAGEFILE_INFORMATION
)P
;
130 Status
= ZwQuerySystemInformation(SystemPageFileInformation
,
134 if (!NT_SUCCESS(Status
) || !(ReturnLength
))
136 /* We failed -- is it because our buffer was too small? */
137 if (BufferLength
< ReturnLength
)
140 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(5).\n");
141 return STATUS_NO_MEMORY
;
144 /* Some other reason, assume the buffer is now full */
145 SacInfo
->RemainingSize
= 0;
149 /* This is the leftover data */
150 SacInfo
->RemainingSize
= InputSize
- BufferLength
;
152 /* This much has now been consumed, and where we are now */
153 BufferLength
-= ReturnLength
;
156 /* Are we out of memory? */
157 if ((LONG
)BufferLength
< 0)
160 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(3).\n");
161 return STATUS_NO_MEMORY
;
164 /* All good, loop the pagefile data now */
167 /* Is the pagefile name too big to fit? */
168 if (PageFileInfo
->PageFileName
.Length
> (LONG
)BufferLength
)
171 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(3).\n");
172 return STATUS_INFO_LENGTH_MISMATCH
;
175 /* Copy the name into our own buffer */
176 RtlCopyMemory((PVOID
)P
,
177 PageFileInfo
->PageFileName
.Buffer
,
178 PageFileInfo
->PageFileName
.Length
);
179 PageFileInfo
->PageFileName
.Buffer
= (PWCHAR
)P
;
181 /* Update buffer lengths and offset */
182 BufferLength
-= PageFileInfo
->PageFileName
.Length
;
183 P
+= PageFileInfo
->PageFileName
.Length
;
185 /* Are we out of memory? */
186 if ((LONG
)BufferLength
< 0)
189 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(4).\n");
190 return STATUS_NO_MEMORY
;
193 /* If this was the only pagefile, break out */
194 if (!PageFileInfo
->NextEntryOffset
) break;
196 /* Otherwise, move to the next one */
197 PageFileInfo
= (PVOID
)((ULONG_PTR
)PageFileInfo
+
198 PageFileInfo
->NextEntryOffset
);
202 /* Next, query the file cache information */
203 Status
= ZwQuerySystemInformation(SystemFileCacheInformation
,
205 sizeof(SacInfo
->CacheInfo
),
207 if (!NT_SUCCESS(Status
))
209 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error (4).\n");
213 /* And then the performance information */
214 Status
= ZwQuerySystemInformation(SystemPerformanceInformation
,
216 sizeof(SacInfo
->PerfInfo
),
218 if (!NT_SUCCESS(Status
))
220 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(5).\n");
224 /* Finally, align the buffer to query process and thread information */
225 P
= ALIGN_UP(P
, SYSTEM_PROCESS_INFORMATION
);
226 RemainingSize
= (ULONG_PTR
)SacInfo
+ InputSize
- P
;
228 /* Are we out of memory? */
229 if ((LONG
)RemainingSize
< 0)
232 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory (6).\n");
233 return STATUS_NO_MEMORY
;
236 /* Now query the processes and threads */
237 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)P
;
238 Status
= ZwQuerySystemInformation(SystemProcessInformation
,
242 if (!NT_SUCCESS(Status
))
244 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(6).\n");
248 /* The first process name will be right after this buffer */
251 /* The caller should look for process info over here */
252 SacInfo
->ProcessDataOffset
= InputSize
- RemainingSize
;
254 /* This is how much buffer data we have left -- are we out? */
255 BufferLength
= RemainingSize
- ReturnLength
;
256 if ((LONG
)BufferLength
< 0)
259 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(7).\n");
260 return STATUS_NO_MEMORY
;
263 /* All good and ready to parse the process and thread list */
266 /* Does the process have a name? */
267 if (ProcessInfo
->ImageName
.Buffer
)
269 /* Is the process name too big to fit? */
270 if ((LONG
)BufferLength
< ProcessInfo
->ImageName
.Length
)
273 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(7).\n");
274 return STATUS_INFO_LENGTH_MISMATCH
;
277 /* Copy the name into our own buffer */
278 RtlCopyMemory((PVOID
)P
,
279 ProcessInfo
->ImageName
.Buffer
,
280 ProcessInfo
->ImageName
.Length
);
281 ProcessInfo
->ImageName
.Buffer
= (PWCHAR
)P
;
283 /* Update buffer lengths and offset */
284 BufferLength
-= ProcessInfo
->ImageName
.Length
;
285 P
+= ProcessInfo
->ImageName
.Length
;
287 /* Are we out of memory? */
288 if ((LONG
)BufferLength
< 0)
291 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(8).\n");
292 return STATUS_NO_MEMORY
;
296 /* If this was the only process, break out */
297 if (!ProcessInfo
->NextEntryOffset
) break;
299 /* Otherwise, move to the next one */
300 ProcessInfo
= (PVOID
)((ULONG_PTR
)ProcessInfo
+
301 ProcessInfo
->NextEntryOffset
);
305 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting.\n");
306 *TotalSize
= InputSize
- BufferLength
;
307 return STATUS_SUCCESS
;
312 PrintTListInfo(IN PSAC_SYSTEM_INFORMATION SacInfo
)
314 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Testing: %d %d %I64d\n",
315 SacInfo
->BasicInfo
.NumberOfPhysicalPages
,
316 SacInfo
->PerfInfo
.AvailablePages
,
317 SacInfo
->TimeInfo
.BootTime
);
322 PutMore(OUT PBOOLEAN ScreenFull
)
328 RetrieveIpAddressFromString(
338 IN HANDLE DriverHandle
,
339 IN PVOID DriverObject
,
341 IN PIO_STATUS_BLOCK IoStatusBlock
,
342 IN PVOID InputBuffer
,
343 IN ULONG InputBufferLength
,
344 IN PVOID OutputBuffer
,
345 IN ULONG OutputBufferLength
,
346 IN BOOLEAN PrintMessage
,
347 OUT PBOOLEAN MessagePrinted
350 return STATUS_NOT_IMPLEMENTED
;
355 DoRebootCommand(IN BOOLEAN Reboot
)
357 LARGE_INTEGER Timeout
, TickCount
;
360 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoRebootCommand: Entering.\n");
362 /* Get the current time now, and setup a timeout in 1 second */
363 KeQueryTickCount(&TickCount
);
364 Timeout
.QuadPart
= TickCount
.QuadPart
/ (10000000 / KeQueryTimeIncrement());
366 /* Check if the timeout is small enough */
367 if (Timeout
.QuadPart
< 60 )
369 /* Show the prompt */
370 ConMgrSimpleEventMessage(Reboot
?
371 SAC_RESTART_PROMPT
: SAC_SHUTDOWN_PROMPT
,
375 KeInitializeEvent(&Event
, SynchronizationEvent
, 0);
376 Timeout
.QuadPart
= -10000000 * (60 - Timeout
.LowPart
);
377 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, &Timeout
);
380 /* Do a shutdown or a reboot, based on the request */
381 Status
= NtShutdownSystem(Reboot
? ShutdownReboot
: ShutdownPowerOff
);
383 /* Check if anyone in the command channel already allocated this */
387 GlobalBuffer
= SacAllocatePool(PAGE_SIZE
, GLOBAL_BLOCK_TAG
);
390 /* We need the global buffer, bail out without it*/
391 SacPutSimpleMessage(SAC_OUT_OF_MEMORY_PROMPT
);
392 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoRebootCommand: Exiting (1).\n");
396 /* Set the size of the buffer */
397 GlobalBufferSize
= PAGE_SIZE
;
400 /* We came back from a reboot, this doesn't make sense, tell the user */
401 SacPutSimpleMessage(Reboot
? SAC_RESTART_FAIL_PROMPT
: SAC_SHUTDOWN_FAIL_PROMPT
);
402 swprintf(GlobalBuffer
, GetMessage(SAC_FAIL_PROMPT
), Status
);
403 SacPutString(GlobalBuffer
);
404 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoRebootCommand: Exiting.\n");
409 DoFullInfoCommand(VOID
)
412 GlobalDoThreads
= !GlobalDoThreads
;
414 /* Print out the new state */
415 SacPutSimpleMessage(GlobalDoThreads
? 8 : 7);
420 DoPagingCommand(VOID
)
423 GlobalPagingNeeded
= !GlobalPagingNeeded
;
425 /* Print out the new state */
426 SacPutSimpleMessage(GlobalPagingNeeded
? 10 : 9);
431 DoSetTimeCommand(IN PCHAR InputTime
)
433 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
438 DoKillCommand(IN PCHAR KillString
)
440 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
445 DoLowerPriorityCommand(IN PCHAR PrioString
)
447 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
452 DoRaisePriorityCommand(IN PCHAR PrioString
)
454 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
459 DoLimitMemoryCommand(IN PCHAR LimitString
)
461 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
468 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoCrashCommand: Entering.\n");
470 /* Crash the machine */
471 KeBugCheckEx(MANUALLY_INITIATED_CRASH
, 0, 0, 0, 0);
477 DoMachineInformationCommand(VOID
)
479 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
484 DoChannelCommand(IN PCHAR ChannelString
)
486 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
491 DoCmdCommand(IN PCHAR InputString
)
493 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
500 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
505 PrintHelpMessage(IN ULONG MessageId
,
511 /* Get the amount of lines this message will take */
512 NewCount
= GetMessageLineCount(MessageId
);
513 if ((NewCount
+ *Count
) > SAC_VTUTF8_ROW_HEIGHT
)
515 /* We are going to overflow the screen, wait for input */
516 PutMore(&ScreenFull
);
517 if (ScreenFull
) return FALSE
;
521 /* Print out the message and update the amount of lines printed */
522 SacPutSimpleMessage(MessageId
);
533 /* Print out all the help messages */
534 if (!PrintHelpMessage(112, &Count
)) return;
535 if (!PrintHelpMessage(12, &Count
)) return;
536 if (!PrintHelpMessage(13, &Count
)) return;
537 if (!PrintHelpMessage(14, &Count
)) return;
538 if (!PrintHelpMessage(15, &Count
)) return;
539 if (!PrintHelpMessage(16, &Count
)) return;
540 if (!PrintHelpMessage(31, &Count
)) return;
541 if (!PrintHelpMessage(18, &Count
)) return;
542 if (!PrintHelpMessage(19, &Count
)) return;
543 if (!PrintHelpMessage(32, &Count
)) return;
544 if (!PrintHelpMessage(20, &Count
)) return;
545 if (!PrintHelpMessage(21, &Count
)) return;
546 if (!PrintHelpMessage(22, &Count
)) return;
547 if (!PrintHelpMessage(23, &Count
)) return;
548 if (!PrintHelpMessage(24, &Count
)) return;
549 if (!PrintHelpMessage(25, &Count
)) return;
550 if (!PrintHelpMessage(27, &Count
)) return;
551 if (!PrintHelpMessage(28, &Count
)) return;
552 if (!PrintHelpMessage(29, &Count
)) return;
557 DoGetNetInfo(IN BOOLEAN DoPrint
)
559 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
564 DoSetIpAddressCommand(IN PCHAR IpString
)
566 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
574 PVOID NewGlobalBuffer
;
576 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoTlistCommand: Entering.\n");
578 /* Check if a global buffer already exists */
581 /* It doesn't, allocate one */
582 GlobalBuffer
= SacAllocatePool(4096, GLOBAL_BLOCK_TAG
);
585 /* Remember its current size */
586 GlobalBufferSize
= 4096;
590 /* Out of memory, bail out */
591 SacPutSimpleMessage(11);
592 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoTlistCommand: Exiting.\n");
597 /* Loop as long as the buffer is too small */
600 /* Get the process list */
601 Status
= GetTListInfo(GlobalBuffer
, GlobalBufferSize
, &Size
);
602 if ((Status
!= STATUS_NO_MEMORY
) &&
603 (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
605 /* It fits! Bail out */
609 /* We need a new bigger buffer */
610 NewGlobalBuffer
= SacAllocatePool(GlobalBufferSize
+ 4096,
612 if (!NewGlobalBuffer
)
614 /* Out of memory, bail out */
615 SacPutSimpleMessage(11);
616 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoTlistCommand: Exiting.\n");
620 /* Free the old one, update state */
621 SacFreePool(GlobalBuffer
);
622 GlobalBufferSize
+= 4096;
623 GlobalBuffer
= NewGlobalBuffer
;
626 /* Did we get here because we have the whole list? */
627 if (!NT_SUCCESS(Status
))
629 /* Nope, print out a failure message */
630 SacPutSimpleMessage(68);
631 swprintf(GlobalBuffer
, GetMessage(48), Status
);
632 SacPutString(GlobalBuffer
);
636 /* Yep, print out the list */
637 PrintTListInfo(GlobalBuffer
);
640 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoTlistCommand: Exiting.\n");