Author: ion
Date: Tue Jan 31 02:38:42 2012
New Revision: 55346
URL:
http://svn.reactos.org/svn/reactos?rev=55346&view=rev
Log:
[SMSS2]: Implement helper functions for reading and writing to the BSD (What lets Windows
know if this was a good boot/shutdown or a bad one, and to display the recovery settings
or not (FreeLDR should do this...)). Implement the functions needed to launch native
applications, and add support for launching autochk and any other bootexecute
applications. Set the correct SessionID with the kernel by calling
ProcessSessionInformation. Pending File Rename Operations are the last big thing left,
plus actual pagefile creation.
[SMSS2]: Fix a bug in SmpParseCommandLine.
Modified:
trunk/reactos/base/system/smss2/smsessn.c
trunk/reactos/base/system/smss2/smss.c
trunk/reactos/base/system/smss2/smss.h
trunk/reactos/base/system/smss2/smsubsys.c
trunk/reactos/base/system/smss2/smutil.c
Modified: trunk/reactos/base/system/smss2/smsessn.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smsessn.…
==============================================================================
--- trunk/reactos/base/system/smss2/smsessn.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smsessn.c [iso-8859-1] Tue Jan 31 02:38:42 2012
@@ -22,3 +22,25 @@
HANDLE SmpSessionsObjectDirectory;
/* FUNCTIONS ******************************************************************/
+
+NTSTATUS
+NTAPI
+SmpSetProcessMuSessionId(IN HANDLE ProcessHandle,
+ IN ULONG SessionId)
+{
+ NTSTATUS Status;
+
+ /* Tell the kernel about our session ID */
+ Status = NtSetInformationProcess(ProcessHandle,
+ ProcessSessionInformation,
+ &SessionId,
+ sizeof(SessionId));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS: SetProcessMuSessionId, Process=%x, Status=%x\n",
+ ProcessHandle, Status);
+ }
+
+ /* Return */
+ return Status;
+}
Modified: trunk/reactos/base/system/smss2/smss.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smss.c?r…
==============================================================================
--- trunk/reactos/base/system/smss2/smss.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smss.c [iso-8859-1] Tue Jan 31 02:38:42 2012
@@ -28,19 +28,271 @@
UNICODE_STRING SmpSystemRoot;
ULONG AttachedSessionId = -1;
-BOOLEAN SmpDebug;
+BOOLEAN SmpDebug, SmpEnableDots;
/* FUNCTIONS ******************************************************************/
+
+/* GCC's incompetence strikes again */
+VOID
+sprintf_nt(IN PCHAR Buffer,
+ IN PCHAR Format,
+ IN ...)
+{
+ va_list ap;
+ va_start(ap, Format);
+ sprintf(Buffer, Format, ap);
+ va_end(ap);
+}
+
+NTSTATUS
+NTAPI
+SmpExecuteImage(IN PUNICODE_STRING FileName,
+ IN PUNICODE_STRING Directory,
+ IN PUNICODE_STRING CommandLine,
+ IN ULONG MuSessionId,
+ IN ULONG Flags,
+ IN PRTL_USER_PROCESS_INFORMATION ProcessInformation)
+{
+ PRTL_USER_PROCESS_INFORMATION ProcessInfo;
+ NTSTATUS Status;
+ RTL_USER_PROCESS_INFORMATION LocalProcessInfo;
+ PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
+
+ /* Use the input process information if we have it, otherwise use local */
+ ProcessInfo = ProcessInformation;
+ if (!ProcessInfo) ProcessInfo = &LocalProcessInfo;
+
+ /* Create parameters for the target process */
+ Status = RtlCreateProcessParameters(&ProcessParameters,
+ FileName,
+ SmpDefaultLibPath.Length ?
+ &SmpDefaultLibPath : NULL,
+ Directory,
+ CommandLine,
+ SmpDefaultEnvironment,
+ NULL,
+ NULL,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* This is a pretty bad failure. ASSERT on checked builds and exit */
+ ASSERTMSG(NT_SUCCESS(Status), "RtlCreateProcessParameters");
+ DPRINT1("SMSS: RtlCreateProcessParameters failed for %wZ - Status ==
%lx\n",
+ FileName, Status);
+ return Status;
+ }
+
+ /* Set the size field as required */
+ ProcessInfo->Size = sizeof(RTL_USER_PROCESS_INFORMATION);
+
+ /* Check if the debug flag was requested */
+ if (Flags & SMP_DEBUG_FLAG)
+ {
+ /* Write it in the process parameters */
+ ProcessParameters->DebugFlags = 1;
+ }
+ else
+ {
+ /* Otherwise inherit the flag that was passed to SMSS itself */
+ ProcessParameters->DebugFlags = SmpDebug;
+ }
+
+ /* Subsystems get the first 1MB of memory reserved for DOS/IVT purposes */
+ if (Flags & SMP_SUBSYSTEM_FLAG)
+ {
+ ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
+ }
+
+ /* And always force NX for anything that SMSS launches */
+ ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_NX;
+
+ /* Now create the process */
+ Status = RtlCreateUserProcess(FileName,
+ OBJ_CASE_INSENSITIVE,
+ ProcessParameters,
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ NULL,
+ NULL,
+ ProcessInfo);
+ RtlDestroyProcessParameters(ProcessParameters);
+ if (!NT_SUCCESS(Status))
+ {
+ /* If we couldn't create it, fail back to the caller */
+ DPRINT1("SMSS: Failed load of %wZ - Status == %lx\n",
+ FileName, Status);
+ return Status;
+ }
+
+ /* Associate a session with this process */
+ Status = SmpSetProcessMuSessionId(ProcessInfo->ProcessHandle, MuSessionId);
+
+ /* If the application is deferred (suspended), there's nothing to do */
+ if (Flags & SMP_DEFERRED_FLAG) return Status;
+
+ /* Otherwise, get ready to start it, but make sure it's a native app */
+ if (ProcessInfo->ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE)
+ {
+ /* Resume it */
+ NtResumeThread(ProcessInfo->ThreadHandle, NULL);
+ if (!(Flags & SMP_ASYNC_FLAG))
+ {
+ /* Block on it unless Async was requested */
+ NtWaitForSingleObject(ProcessInfo->ThreadHandle, FALSE, NULL);
+ }
+
+ /* It's up and running now, close our handles */
+ NtClose(ProcessInfo->ThreadHandle);
+ NtClose(ProcessInfo->ProcessHandle);
+ }
+ else
+ {
+ /* This image is invalid, so kill it, close our handles, and fail */
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ NtTerminateProcess(ProcessInfo->ProcessHandle, Status);
+ NtWaitForSingleObject(ProcessInfo->ThreadHandle, 0, 0);
+ NtClose(ProcessInfo->ThreadHandle);
+ NtClose(ProcessInfo->ProcessHandle);
+ DPRINT1("SMSS: Not an NT image - %wZ\n", FileName);
+ }
+
+ /* Return the outcome of the process create */
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+SmpInvokeAutoChk(IN PUNICODE_STRING FileName,
+ IN PUNICODE_STRING Directory,
+ IN PUNICODE_STRING Arguments,
+ IN ULONG Flags)
+{
+ ANSI_STRING DestinationString;
+ CHAR SourceString[256];
+ UNICODE_STRING Destination;
+ WCHAR Buffer[1024];
+ BOOLEAN BootState, BootOkay, ShutdownOkay;
+
+ /* Check if autochk should show dots (if the user booted with /SOS) */
+ if (SmpQueryRegistrySosOption()) SmpEnableDots = FALSE;
+
+ /* Make sure autochk was actually found */
+ if (Flags & SMP_INVALID_PATH)
+ {
+ /* It wasn't, so create an error message to print on the screen */
+ sprintf_nt(SourceString,
+ "%wZ program not found - skipping AUTOCHECK\n",
+ FileName);
+ RtlInitAnsiString(&DestinationString, SourceString);
+ if (RtlAnsiStringToUnicodeString(&Destination,
+ &DestinationString,
+ TRUE))
+ {
+ /* And show it */
+ NtDisplayString(&Destination);
+ RtlFreeUnicodeString(&Destination);
+ }
+ }
+ else
+ {
+ /* Autochk is there, so record the BSD state */
+ BootState = SmpSaveAndClearBootStatusData(&BootOkay, &ShutdownOkay);
+
+ /* Build the path to autochk and place its arguments */
+ RtlInitEmptyUnicodeString(&Destination, Buffer, sizeof(Buffer));
+ RtlAppendUnicodeStringToString(&Destination, FileName);
+ RtlAppendUnicodeToString(&Destination, L" ");
+ RtlAppendUnicodeStringToString(&Destination, Arguments);
+
+ /* Execute it */
+ SmpExecuteImage(FileName,
+ Directory,
+ &Destination,
+ 0,
+ Flags & ~SMP_AUTOCHK_FLAG,
+ NULL);
+
+ /* Restore the BSD state */
+ if (BootState) SmpRestoreBootStatusData(BootOkay, ShutdownOkay);
+ }
+
+ /* We're all done! */
+ return STATUS_SUCCESS;
+}
NTSTATUS
NTAPI
SmpExecuteCommand(IN PUNICODE_STRING CommandLine,
IN ULONG MuSessionId,
- OUT PULONG ProcessId,
+ OUT PHANDLE ProcessId,
IN ULONG Flags)
{
- DPRINT1("Should run: %wZ for session %d\n", CommandLine, MuSessionId);
- return STATUS_SUCCESS;
+ NTSTATUS Status;
+ UNICODE_STRING Arguments, Directory, FileName;
+
+ /* There's no longer a debugging subsystem */
+ if (Flags & SMP_DEBUG_FLAG) return STATUS_SUCCESS;
+
+ /* Parse the command line to see what execution flags are requested */
+ Status = SmpParseCommandLine(CommandLine,
+ &Flags,
+ &FileName,
+ &Directory,
+ &Arguments);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail if we couldn't do that */
+ DPRINT1("SMSS: SmpParseCommand( %wZ ) failed - Status == %lx\n",
+ CommandLine, Status);
+ return Status;
+ }
+
+ /* Check if autochk is requested */
+ if (Flags & SMP_AUTOCHK_FLAG)
+ {
+ /* Run it */
+ Status = SmpInvokeAutoChk(&FileName, &Directory, &Arguments, Flags);
+ }
+ else if (Flags & SMP_SUBSYSTEM_FLAG)
+ {
+ Status = SmpLoadSubSystem(&FileName,
+ &Directory,
+ CommandLine,
+ MuSessionId,
+ ProcessId);
+ }
+ else if (Flags & SMP_INVALID_PATH)
+ {
+ /* An invalid image was specified, fail */
+ DPRINT1("SMSS: Image file (%wZ) not found\n", &FileName);
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ else
+ {
+ /* An actual image name was present -- execute it */
+ Status = SmpExecuteImage(&FileName,
+ &Directory,
+ CommandLine,
+ MuSessionId,
+ Flags,
+ NULL);
+ }
+
+ /* Free all the token parameters */
+ if (FileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
+ if (Directory.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Directory.Buffer);
+ if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer);
+
+ /* Return to the caller */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS: Command '%wZ' failed - Status == %x\n",
+ CommandLine, Status);
+ }
+ return Status;
}
NTSTATUS
Modified: trunk/reactos/base/system/smss2/smss.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smss.h?r…
==============================================================================
--- trunk/reactos/base/system/smss2/smss.h [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smss.h [iso-8859-1] Tue Jan 31 02:38:42 2012
@@ -33,7 +33,9 @@
#define SMP_DEBUG_FLAG 0x01
#define SMP_ASYNC_FLAG 0x02
#define SMP_AUTOCHK_FLAG 0x04
+#define SMP_SUBSYSTEM_FLAG 0x08
#define SMP_INVALID_PATH 0x10
+#define SMP_DEFERRED_FLAG 0x20
/* EXTERNALS ******************************************************************/
@@ -102,7 +104,7 @@
SmpExecuteCommand(
IN PUNICODE_STRING CommandLine,
IN ULONG MuSessionId,
- OUT PULONG ProcessId,
+ OUT PHANDLE ProcessId,
IN ULONG Flags
);
@@ -141,3 +143,42 @@
OUT PUNICODE_STRING Directory,
OUT PUNICODE_STRING Arguments
);
+
+NTSTATUS
+NTAPI
+SmpLoadSubSystem(
+ IN PUNICODE_STRING FileName,
+ IN PUNICODE_STRING Directory,
+ IN PUNICODE_STRING CommandLine,
+ IN ULONG MuSessionId,
+ OUT PHANDLE ProcessId
+);
+
+NTSTATUS
+NTAPI
+SmpSetProcessMuSessionId(
+ IN HANDLE ProcessHandle,
+ IN ULONG SessionId
+);
+
+BOOLEAN
+NTAPI
+SmpQueryRegistrySosOption(
+ VOID
+);
+
+BOOLEAN
+NTAPI
+SmpSaveAndClearBootStatusData(
+ OUT PBOOLEAN BootOkay,
+ OUT PBOOLEAN ShutdownOkay
+);
+
+VOID
+NTAPI
+SmpRestoreBootStatusData(
+ IN BOOLEAN BootOkay,
+ IN BOOLEAN ShutdownOkay
+);
+
+
Modified: trunk/reactos/base/system/smss2/smsubsys.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smsubsys…
==============================================================================
--- trunk/reactos/base/system/smss2/smsubsys.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smsubsys.c [iso-8859-1] Tue Jan 31 02:38:42 2012
@@ -24,6 +24,18 @@
NTSTATUS
NTAPI
+SmpLoadSubSystem(IN PUNICODE_STRING FileName,
+ IN PUNICODE_STRING Directory,
+ IN PUNICODE_STRING CommandLine,
+ IN ULONG MuSessionId,
+ OUT PHANDLE ProcessId)
+{
+ DPRINT1("Should start subsystem %wZ for Session: %lx\n", FileName,
MuSessionId);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
SmpLoadSubSystemsForMuSession(IN PULONG MuSessionId,
OUT PHANDLE ProcessId,
IN PUNICODE_STRING InitialCommand)
Modified: trunk/reactos/base/system/smss2/smutil.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smutil.c…
==============================================================================
--- trunk/reactos/base/system/smss2/smutil.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smutil.c [iso-8859-1] Tue Jan 31 02:38:42 2012
@@ -13,6 +13,11 @@
#include "debug.h"
/* GLOBALS ********************************************************************/
+
+//
+// Taken from an ASSERT
+//
+#define VALUE_BUFFER_SIZE (sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 512)
typedef struct _SMP_PRIVILEGE_STATE
{
@@ -399,8 +404,7 @@
else
{
/* There is a directory, and a filename -- separate those two */
- FilePart -= sizeof(UNICODE_NULL);
- *FilePart = UNICODE_NULL;
+ *--FilePart = UNICODE_NULL;
RtlCreateUnicodeString(Directory, PathBuffer);
}
}
@@ -408,3 +412,139 @@
/* We are done -- move on to the second pass to get the arguments */
return SmpParseToken(&CmdLineCopy, TRUE, Arguments);
}
+
+BOOLEAN
+NTAPI
+SmpQueryRegistrySosOption(VOID)
+{
+ NTSTATUS Status;
+ UNICODE_STRING KeyName, ValueName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE KeyHandle;
+ WCHAR ValueBuffer[VALUE_BUFFER_SIZE];
+ PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)ValueBuffer;
+ ULONG Length;
+
+ /* Open the key */
+ RtlInitUnicodeString(&KeyName,
+
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS: can't open control key: 0x%x\n", Status);
+ return FALSE;
+ }
+
+ /* Query the value */
+ RtlInitUnicodeString(&ValueName, L"SystemStartOptions");
+ Status = NtQueryValueKey(KeyHandle,
+ &ValueName,
+ KeyValuePartialInformation,
+ PartialInfo,
+ sizeof(ValueBuffer),
+ &Length);
+ ASSERT(Length < VALUE_BUFFER_SIZE);
+ NtClose(KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("SMSS: can't query value key: 0x%x\n", Status);
+ return FALSE;
+ }
+
+ /* Check if it's set to SOS or sos */
+ if (!(wcsstr((PWCHAR)PartialInfo->Data, L"SOS")) ||
+ (wcsstr((PWCHAR)PartialInfo->Data, L"sos")))
+ {
+ /* It's not set, return FALSE */
+ return FALSE;
+ }
+
+ /* It's set, return TRUE */
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+SmpSaveAndClearBootStatusData(OUT PBOOLEAN BootOkay,
+ OUT PBOOLEAN ShutdownOkay)
+{
+ NTSTATUS Status;
+ BOOLEAN Value = TRUE;
+ PVOID BootStatusDataHandle;
+
+ /* Assume failure */
+ *BootOkay = FALSE;
+ *ShutdownOkay = FALSE;
+
+ /* Lock the BSD and fail if we couldn't */
+ Status = RtlLockBootStatusData(&BootStatusDataHandle);
+ if (!NT_SUCCESS(Status)) return FALSE;
+
+ /* Read the old settings */
+ RtlGetSetBootStatusData(BootStatusDataHandle,
+ TRUE,
+ RtlBsdItemBootGood,
+ BootOkay,
+ sizeof(BOOLEAN),
+ NULL);
+ RtlGetSetBootStatusData(BootStatusDataHandle,
+ TRUE,
+ RtlBsdItemBootShutdown,
+ ShutdownOkay,
+ sizeof(BOOLEAN),
+ NULL);
+
+ /* Set new ones indicating we got at least this far */
+ RtlGetSetBootStatusData(BootStatusDataHandle,
+ FALSE,
+ RtlBsdItemBootGood,
+ &Value,
+ sizeof(Value),
+ NULL);
+ RtlGetSetBootStatusData(BootStatusDataHandle,
+ FALSE,
+ RtlBsdItemBootShutdown,
+ &Value,
+ sizeof(Value),
+ NULL);
+
+ /* Unlock the BSD and return */
+ RtlUnlockBootStatusData(BootStatusDataHandle);
+ return TRUE;
+}
+
+VOID
+NTAPI
+SmpRestoreBootStatusData(IN BOOLEAN BootOkay,
+ IN BOOLEAN ShutdownOkay)
+{
+ NTSTATUS Status;
+ PVOID BootState;
+
+ /* Lock the BSD */
+ Status = RtlLockBootStatusData(&BootState);
+ if (NT_SUCCESS(Status))
+ {
+ /* Write the bootokay and bootshudown values */
+ RtlGetSetBootStatusData(BootState,
+ FALSE,
+ RtlBsdItemBootGood,
+ &BootOkay,
+ sizeof(BootOkay),
+ NULL);
+ RtlGetSetBootStatusData(BootState,
+ FALSE,
+ RtlBsdItemBootShutdown,
+ &ShutdownOkay,
+ sizeof(ShutdownOkay),
+ NULL);
+
+ /* Unlock the BSD and return */
+ RtlUnlockBootStatusData(BootState);
+ }
+}