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 /* GLOBALS ********************************************************************/
16 ULONG GlobalBufferSize
;
18 /* FUNCTIONS ******************************************************************/
25 return STATUS_NOT_IMPLEMENTED
;
29 DoChannelCloseByNameCommand(
33 return STATUS_NOT_IMPLEMENTED
;
37 DoChannelCloseByIndexCommand(
41 return STATUS_NOT_IMPLEMENTED
;
45 DoChannelSwitchByNameCommand(
49 return STATUS_NOT_IMPLEMENTED
;
53 DoChannelSwitchByIndexCommand(
57 return STATUS_NOT_IMPLEMENTED
;
60 typedef struct _SAC_SYSTEM_INFORMATION
62 SYSTEM_BASIC_INFORMATION BasicInfo
;
63 SYSTEM_TIMEOFDAY_INFORMATION TimeInfo
;
64 SYSTEM_FILECACHE_INFORMATION CacheInfo
;
65 SYSTEM_PERFORMANCE_INFORMATION PerfInfo
;
67 ULONG ProcessDataOffset
;
68 // SYSTEM_PAGEFILE_INFORMATION PageFileInfo;
69 // SYSTEM_PROCESS_INFORMATINO ProcessInfo;
70 } SAC_SYSTEM_INFORMATION
, *PSAC_SYSTEM_INFORMATION
;
74 GetTListInfo(IN PSAC_SYSTEM_INFORMATION SacInfo
,
79 ULONG BufferLength
, ReturnLength
, RemainingSize
;
80 PSYSTEM_PAGEFILE_INFORMATION PageFileInfo
;
81 PSYSTEM_PROCESS_INFORMATION ProcessInfo
;
83 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering.\n");
88 /* Bail out if the buffer is way too small */
91 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory.\n");
92 return STATUS_NO_MEMORY
;
95 /* Make sure it's at least big enough to hold the static structure */
96 BufferLength
= InputSize
- sizeof(SAC_SYSTEM_INFORMATION
);
97 if (InputSize
< sizeof(SAC_SYSTEM_INFORMATION
))
99 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory (2).\n");
100 return STATUS_NO_MEMORY
;
104 Status
= ZwQuerySystemInformation(SystemTimeOfDayInformation
,
106 sizeof(SacInfo
->TimeInfo
),
108 if (!NT_SUCCESS(Status
))
110 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error.\n");
114 /* Query basic information */
115 Status
= ZwQuerySystemInformation(SystemBasicInformation
,
117 sizeof(SacInfo
->BasicInfo
),
119 if (!NT_SUCCESS(Status
))
121 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error (2).\n");
125 /* Now query the pagefile information, which comes right after */
126 P
= (ULONG_PTR
)(SacInfo
+ 1);
127 PageFileInfo
= (PSYSTEM_PAGEFILE_INFORMATION
)P
;
128 Status
= ZwQuerySystemInformation(SystemPageFileInformation
,
132 if (!NT_SUCCESS(Status
) || !(ReturnLength
))
134 /* We failed -- is it because our buffer was too small? */
135 if (BufferLength
< ReturnLength
)
138 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(5).\n");
139 return STATUS_NO_MEMORY
;
142 /* Some other reason, assume the buffer is now full */
143 SacInfo
->RemainingSize
= 0;
147 /* This is the leftover data */
148 SacInfo
->RemainingSize
= InputSize
- BufferLength
;
150 /* This much has now been consumed, and where we are now */
151 BufferLength
-= ReturnLength
;
154 /* Are we out of memory? */
155 if ((LONG
)BufferLength
< 0)
158 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(3).\n");
159 return STATUS_NO_MEMORY
;
162 /* All good, loop the pagefile data now */
165 /* Is the pagefile name too big to fit? */
166 if (PageFileInfo
->PageFileName
.Length
> (LONG
)BufferLength
)
169 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(3).\n");
170 return STATUS_INFO_LENGTH_MISMATCH
;
173 /* Copy the name into our own buffer */
174 RtlCopyMemory((PVOID
)P
,
175 PageFileInfo
->PageFileName
.Buffer
,
176 PageFileInfo
->PageFileName
.Length
);
177 PageFileInfo
->PageFileName
.Buffer
= (PWCHAR
)P
;
179 /* Update buffer lengths and offset */
180 BufferLength
-= PageFileInfo
->PageFileName
.Length
;
181 P
+= PageFileInfo
->PageFileName
.Length
;
183 /* Are we out of memory? */
184 if ((LONG
)BufferLength
< 0)
187 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(4).\n");
188 return STATUS_NO_MEMORY
;
191 /* If this was the only pagefile, break out */
192 if (!PageFileInfo
->NextEntryOffset
) break;
194 /* Otherwise, move to the next one */
195 PageFileInfo
= (PVOID
)((ULONG_PTR
)PageFileInfo
+
196 PageFileInfo
->NextEntryOffset
);
200 /* Next, query the file cache information */
201 Status
= ZwQuerySystemInformation(SystemFileCacheInformation
,
203 sizeof(SacInfo
->CacheInfo
),
205 if (!NT_SUCCESS(Status
))
207 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error (4).\n");
211 /* And then the performance information */
212 Status
= ZwQuerySystemInformation(SystemPerformanceInformation
,
214 sizeof(SacInfo
->PerfInfo
),
216 if (!NT_SUCCESS(Status
))
218 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(5).\n");
222 /* Finally, align the buffer to query process and thread information */
223 P
= ALIGN_UP(P
, SYSTEM_PROCESS_INFORMATION
);
224 RemainingSize
= (ULONG_PTR
)SacInfo
+ InputSize
- P
;
226 /* Are we out of memory? */
227 if ((LONG
)RemainingSize
< 0)
230 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory (6).\n");
231 return STATUS_NO_MEMORY
;
234 /* Now query the processes and threads */
235 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)P
;
236 Status
= ZwQuerySystemInformation(SystemProcessInformation
,
240 if (!NT_SUCCESS(Status
))
242 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(6).\n");
246 /* The first process name will be right after this buffer */
249 /* The caller should look for process info over here */
250 SacInfo
->ProcessDataOffset
= InputSize
- RemainingSize
;
252 /* This is how much buffer data we have left -- are we out? */
253 BufferLength
= RemainingSize
- ReturnLength
;
254 if ((LONG
)BufferLength
< 0)
257 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(7).\n");
258 return STATUS_NO_MEMORY
;
261 /* All good and ready to parse the process and thread list */
264 /* Does the process have a name? */
265 if (ProcessInfo
->ImageName
.Buffer
)
267 /* Is the process name too big to fit? */
268 if ((LONG
)BufferLength
< ProcessInfo
->ImageName
.Length
)
271 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, error(7).\n");
272 return STATUS_INFO_LENGTH_MISMATCH
;
275 /* Copy the name into our own buffer */
276 RtlCopyMemory((PVOID
)P
,
277 ProcessInfo
->ImageName
.Buffer
,
278 ProcessInfo
->ImageName
.Length
);
279 ProcessInfo
->ImageName
.Buffer
= (PWCHAR
)P
;
281 /* Update buffer lengths and offset */
282 BufferLength
-= ProcessInfo
->ImageName
.Length
;
283 P
+= ProcessInfo
->ImageName
.Length
;
285 /* Are we out of memory? */
286 if ((LONG
)BufferLength
< 0)
289 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting, no memory(8).\n");
290 return STATUS_NO_MEMORY
;
294 /* If this was the only process, break out */
295 if (!ProcessInfo
->NextEntryOffset
) break;
297 /* Otherwise, move to the next one */
298 ProcessInfo
= (PVOID
)((ULONG_PTR
)ProcessInfo
+
299 ProcessInfo
->NextEntryOffset
);
303 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting.\n");
304 *TotalSize
= InputSize
- BufferLength
;
305 return STATUS_SUCCESS
;
310 PrintTListInfo(IN PSAC_SYSTEM_INFORMATION SacInfo
)
312 SAC_DBG(1, "Testing: %d %d %I64d\n",
313 SacInfo
->BasicInfo
.NumberOfPhysicalPages
,
314 SacInfo
->PerfInfo
.AvailablePages
,
315 SacInfo
->TimeInfo
.BootTime
);
320 PutMore(OUT PBOOLEAN ScreenFull
)
326 RetrieveIpAddressFromString(
336 IN HANDLE DriverHandle
,
337 IN PVOID DriverObject
,
339 IN PIO_STATUS_BLOCK IoStatusBlock
,
340 IN PVOID InputBuffer
,
341 IN ULONG InputBufferLength
,
342 IN PVOID OutputBuffer
,
343 IN ULONG OutputBufferLength
,
344 IN BOOLEAN PrintMessage
,
345 OUT PBOOLEAN MessagePrinted
348 return STATUS_NOT_IMPLEMENTED
;
353 DoRebootCommand(IN BOOLEAN Reboot
)
355 LARGE_INTEGER Timeout
, TickCount
;
358 SAC_DBG(1, "SAC DoRebootCommand: Entering.\n");
360 /* Get the current time now, and setup a timeout in 1 second */
361 KeQueryTickCount(&TickCount
);
362 Timeout
.QuadPart
= TickCount
.QuadPart
/ (10000000 / KeQueryTimeIncrement());
364 /* Check if the timeout is small enough */
365 if (Timeout
.QuadPart
< 60 )
367 /* Show the prompt */
368 ConMgrSimpleEventMessage(Reboot
?
369 SAC_RESTART_PROMPT
: SAC_SHUTDOWN_PROMPT
,
373 KeInitializeEvent(&Event
, SynchronizationEvent
, 0);
374 Timeout
.QuadPart
= -10000000 * (60 - Timeout
.LowPart
);
375 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, &Timeout
);
378 /* Do a shutdown or a reboot, based on the request */
379 Status
= NtShutdownSystem(Reboot
? ShutdownReboot
: ShutdownPowerOff
);
381 /* Check if anyone in the command channel already allocated this */
385 GlobalBuffer
= SacAllocatePool(PAGE_SIZE
, GLOBAL_BLOCK_TAG
);
388 /* We need the global buffer, bail out without it*/
389 SacPutSimpleMessage(SAC_OUT_OF_MEMORY_PROMPT
);
390 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoRebootCommand: Exiting (1).\n");
394 /* Set the size of the buffer */
395 GlobalBufferSize
= PAGE_SIZE
;
398 /* We came back from a reboot, this doesn't make sense, tell the user */
399 SacPutSimpleMessage(Reboot
? SAC_RESTART_FAIL_PROMPT
: SAC_SHUTDOWN_FAIL_PROMPT
);
400 swprintf(GlobalBuffer
, GetMessage(SAC_FAIL_PROMPT
), Status
);
401 SacPutString(GlobalBuffer
);
402 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoRebootCommand: Exiting.\n");
407 DoFullInfoCommand(VOID
)
410 GlobalDoThreads
= !GlobalDoThreads
;
412 /* Print out the new state */
413 SacPutSimpleMessage(GlobalDoThreads
? 8 : 7);
418 DoPagingCommand(VOID
)
421 GlobalPagingNeeded
= !GlobalPagingNeeded
;
423 /* Print out the new state */
424 SacPutSimpleMessage(GlobalPagingNeeded
? 10 : 9);
429 DoSetTimeCommand(IN PCHAR InputTime
)
431 SAC_DBG(1, "Entering\n");
436 DoKillCommand(IN PCHAR KillString
)
438 SAC_DBG(1, "Entering\n");
443 DoLowerPriorityCommand(IN PCHAR PrioString
)
445 SAC_DBG(1, "Entering\n");
450 DoRaisePriorityCommand(IN PCHAR PrioString
)
452 SAC_DBG(1, "Entering\n");
457 DoLimitMemoryCommand(IN PCHAR LimitString
)
459 SAC_DBG(1, "Entering\n");
466 SAC_DBG(1, "SAC DoCrashCommand: Entering.\n");
468 /* Crash the machine */
469 KeBugCheckEx(MANUALLY_INITIATED_CRASH
, 0, 0, 0, 0);
475 DoMachineInformationCommand(VOID
)
477 SAC_DBG(1, "Entering\n");
482 DoChannelCommand(IN PCHAR ChannelString
)
484 SAC_DBG(1, "Entering\n");
489 DoCmdCommand(IN PCHAR InputString
)
491 SAC_DBG(1, "Entering\n");
498 SAC_DBG(1, "Entering\n");
503 PrintHelpMessage(IN ULONG MessageId
,
509 /* Get the amount of lines this message will take */
510 NewCount
= GetMessageLineCount(MessageId
);
511 if ((NewCount
+ *Count
) > SAC_VTUTF8_ROW_HEIGHT
)
513 /* We are going to overflow the screen, wait for input */
514 PutMore(&ScreenFull
);
515 if (ScreenFull
) return FALSE
;
519 /* Print out the message and update the amount of lines printed */
520 SacPutSimpleMessage(MessageId
);
531 /* Print out all the help messages */
532 if (!PrintHelpMessage(112, &Count
)) return;
533 if (!PrintHelpMessage(12, &Count
)) return;
534 if (!PrintHelpMessage(13, &Count
)) return;
535 if (!PrintHelpMessage(14, &Count
)) return;
536 if (!PrintHelpMessage(15, &Count
)) return;
537 if (!PrintHelpMessage(16, &Count
)) return;
538 if (!PrintHelpMessage(31, &Count
)) return;
539 if (!PrintHelpMessage(18, &Count
)) return;
540 if (!PrintHelpMessage(19, &Count
)) return;
541 if (!PrintHelpMessage(32, &Count
)) return;
542 if (!PrintHelpMessage(20, &Count
)) return;
543 if (!PrintHelpMessage(21, &Count
)) return;
544 if (!PrintHelpMessage(22, &Count
)) return;
545 if (!PrintHelpMessage(23, &Count
)) return;
546 if (!PrintHelpMessage(24, &Count
)) return;
547 if (!PrintHelpMessage(25, &Count
)) return;
548 if (!PrintHelpMessage(27, &Count
)) return;
549 if (!PrintHelpMessage(28, &Count
)) return;
550 if (!PrintHelpMessage(29, &Count
)) return;
555 DoGetNetInfo(IN BOOLEAN DoPrint
)
557 SAC_DBG(1, "Entering\n");
562 DoSetIpAddressCommand(IN PCHAR IpString
)
564 SAC_DBG(1, "Entering\n");
572 PVOID NewGlobalBuffer
;
574 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "SAC DoTlistCommand: Entering.\n");
576 /* Check if a global buffer already exists */
579 /* It doesn't, allocate one */
580 GlobalBuffer
= SacAllocatePool(4096, GLOBAL_BLOCK_TAG
);
583 /* Remember its current size */
584 GlobalBufferSize
= 4096;
588 /* Out of memory, bail out */
589 SacPutSimpleMessage(11);
590 SAC_DBG(1, "SAC DoTlistCommand: Exiting.\n");
595 /* Loop as long as the buffer is too small */
598 /* Get the process list */
599 Status
= GetTListInfo(GlobalBuffer
, GlobalBufferSize
, &Size
);
600 if ((Status
!= STATUS_NO_MEMORY
) &&
601 (Status
!= STATUS_INFO_LENGTH_MISMATCH
))
603 /* It fits! Bail out */
607 /* We need a new bigger buffer */
608 NewGlobalBuffer
= SacAllocatePool(GlobalBufferSize
+ 4096,
610 if (!NewGlobalBuffer
)
612 /* Out of memory, bail out */
613 SacPutSimpleMessage(11);
614 SAC_DBG(1, "SAC DoTlistCommand: Exiting.\n");
618 /* Free the old one, update state */
619 SacFreePool(GlobalBuffer
);
620 GlobalBufferSize
+= 4096;
621 GlobalBuffer
= NewGlobalBuffer
;
624 /* Did we get here because we have the whole list? */
625 if (!NT_SUCCESS(Status
))
627 /* Nope, print out a failure message */
628 SacPutSimpleMessage(68);
629 swprintf(GlobalBuffer
, GetMessage(48), Status
);
630 SacPutString(GlobalBuffer
);
634 /* Yep, print out the list */
635 PrintTListInfo(GlobalBuffer
);
638 SAC_DBG(1, "SAC DoTlistCommand: Exiting.\n");