mirror of
https://github.com/reactos/reactos.git
synced 2024-06-22 05:51:29 +00:00
[SMSS2]: Implement executing the initial command as well as doing the SM-to-SM initial connection.
[SMSS2]: Implement the main LPC loop and handle all the supported APIs (all stubs for now). Also handle new connection requests and implement SmpHandleConnectionRequest. [SMSS2]: Implement subsystem helper functions. [SMSS2]: Use SmApiPort2 instead of Sm2ApiPort. [SMSS2]: Rename the SMSRV_APIs not to conflict with the function names, nor with the client functions in smlib. svn path=/trunk/; revision=55478
This commit is contained in:
parent
35a3e62e9d
commit
dfb761830d
|
@ -15,7 +15,7 @@ list(APPEND SOURCE
|
|||
|
||||
add_executable(smss2 WIN32 ${SOURCE})
|
||||
|
||||
target_link_libraries(smss2 nt pseh)
|
||||
target_link_libraries(smss2 nt pseh smlib)
|
||||
|
||||
add_pch(smss2 smss.h)
|
||||
|
||||
|
|
|
@ -2439,7 +2439,7 @@ SmpInit(IN PUNICODE_STRING InitialCommand,
|
|||
RtlInitUnicodeString(&Os2Name, L"OS2");
|
||||
|
||||
/* Create the SM API Port */
|
||||
RtlInitUnicodeString(&PortName, L"\\Sm2ApiPort");
|
||||
RtlInitUnicodeString(&PortName, L"\\SmApiPort2");
|
||||
InitializeObjectAttributes(&ObjectAttributes, &PortName, 0, NULL, NULL);
|
||||
Status = NtCreatePort(&PortHandle,
|
||||
&ObjectAttributes,
|
||||
|
|
|
@ -14,26 +14,365 @@
|
|||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
typedef struct _SMP_CLIENT_CONTEXT
|
||||
{
|
||||
PVOID Subsystem;
|
||||
HANDLE ProcessHandle;
|
||||
HANDLE PortHandle;
|
||||
ULONG dword10;
|
||||
} SMP_CLIENT_CONTEXT, *PSMP_CLIENT_CONTEXT;
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(NTAPI *PSM_API_HANDLER)(
|
||||
IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort
|
||||
);
|
||||
|
||||
volatile LONG SmTotalApiThreads;
|
||||
HANDLE SmUniqueProcessId;
|
||||
|
||||
/* API HANDLERS ***************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpCreateForeignSession(IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort)
|
||||
{
|
||||
DPRINT1("%s is not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpSessionComplete(IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort)
|
||||
{
|
||||
DPRINT1("%s is not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpTerminateForeignSession(IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort)
|
||||
{
|
||||
DPRINT1("%s is not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpExecPgm(IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort)
|
||||
{
|
||||
DPRINT1("%s is not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpLoadDeferedSubsystem(IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort)
|
||||
{
|
||||
DPRINT1("%s is not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpStartCsr(IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort)
|
||||
{
|
||||
DPRINT1("%s is not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpStopCsr(IN PSM_API_MSG SmApiMsg,
|
||||
IN PSMP_CLIENT_CONTEXT ClientContext,
|
||||
IN HANDLE SmApiPort)
|
||||
{
|
||||
DPRINT1("%s is not yet implemented\n", __FUNCTION__);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PSM_API_HANDLER SmpApiDispatch[SmMaxApiNumber] =
|
||||
{
|
||||
SmpCreateForeignSession,
|
||||
SmpSessionComplete,
|
||||
SmpTerminateForeignSession,
|
||||
SmpExecPgm,
|
||||
SmpLoadDeferedSubsystem,
|
||||
SmpStartCsr,
|
||||
SmpStopCsr
|
||||
};
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpHandleConnectionRequest(IN HANDLE SmApiPort,
|
||||
IN PSB_API_MSG SbApiMsg)
|
||||
{
|
||||
BOOLEAN Accept = TRUE;
|
||||
HANDLE PortHandle, ProcessHandle;
|
||||
ULONG SessionId;
|
||||
UNICODE_STRING SubsystemPort;
|
||||
SMP_CLIENT_CONTEXT *ClientContext;
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
REMOTE_PORT_VIEW PortView;
|
||||
SECURITY_QUALITY_OF_SERVICE SecurityQos;
|
||||
PSMP_SUBSYSTEM CidSubsystem, TypeSubsystem;
|
||||
|
||||
/* Initialize QoS data */
|
||||
SecurityQos.ImpersonationLevel = SecurityIdentification;
|
||||
SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
||||
SecurityQos.EffectiveOnly = TRUE;
|
||||
|
||||
/* Check if this is SM connecting to itself */
|
||||
if (SbApiMsg->h.ClientId.UniqueProcess == SmUniqueProcessId)
|
||||
{
|
||||
/* No need to get any handle -- assume session 0 */
|
||||
DPRINT1("SM connecting to SM\n");
|
||||
ProcessHandle = NULL;
|
||||
SessionId = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reference the foreign process */
|
||||
DPRINT1("Incoming request from %lx\n", SbApiMsg->h.ClientId.UniqueProcess);
|
||||
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
|
||||
Status = NtOpenProcess(&ProcessHandle,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
&ObjectAttributes,
|
||||
&SbApiMsg->h.ClientId);
|
||||
if (!NT_SUCCESS(Status)) Accept = FALSE;
|
||||
|
||||
/* Get its session ID */
|
||||
SmpGetProcessMuSessionId(ProcessHandle, &SessionId);
|
||||
}
|
||||
|
||||
/* See if we already know about the caller's subystem */
|
||||
CidSubsystem = SmpLocateKnownSubSysByCid(&SbApiMsg->h.ClientId);
|
||||
if ((CidSubsystem) && (Accept))
|
||||
{
|
||||
/* Check if we already have a subsystem for this kind of image */
|
||||
TypeSubsystem = SmpLocateKnownSubSysByType(SessionId,
|
||||
SbApiMsg->ConnectionInfo.SubsystemType);
|
||||
if (TypeSubsystem == CidSubsystem)
|
||||
{
|
||||
/* Someone is trying to take control of an existing subsystem, fail */
|
||||
Accept = FALSE;
|
||||
DPRINT1("SMSS: Connection from SubSystem rejected\n");
|
||||
DPRINT1("SMSS: Image type already being served\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set this image type as the type for this subsystem */
|
||||
CidSubsystem->ImageType = SbApiMsg->ConnectionInfo.SubsystemType;
|
||||
}
|
||||
|
||||
/* Drop the reference we had acquired */
|
||||
if (TypeSubsystem) SmpDereferenceSubsystem(TypeSubsystem);
|
||||
}
|
||||
|
||||
/* Check if we'll be accepting the connection */
|
||||
if (Accept)
|
||||
{
|
||||
/* We will, so create a client context for it */
|
||||
ClientContext = RtlAllocateHeap(SmpHeap, 0, sizeof(SMP_CLIENT_CONTEXT));
|
||||
if (ClientContext)
|
||||
{
|
||||
ClientContext->ProcessHandle = ProcessHandle;
|
||||
ClientContext->Subsystem = CidSubsystem;
|
||||
ClientContext->dword10 = 0;
|
||||
ClientContext->PortHandle = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failed to allocate a client context, so reject the connection */
|
||||
DPRINT1("Rejecting connectiond due to lack of memory\n");
|
||||
Accept = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use a bogus context since we're going to reject the message */
|
||||
ClientContext = (PSMP_CLIENT_CONTEXT)SbApiMsg;
|
||||
}
|
||||
|
||||
/* Now send the actual accept reply (which could be a rejection) */
|
||||
PortView.Length = sizeof(PortView);
|
||||
DPRINT1("Accepting: %d connection with context: %p\n", Accept, ClientContext);
|
||||
Status = NtAcceptConnectPort(&PortHandle,
|
||||
ClientContext,
|
||||
&SbApiMsg->h,
|
||||
Accept,
|
||||
NULL,
|
||||
&PortView);
|
||||
if (!(Accept) || !(NT_SUCCESS(Status)))
|
||||
{
|
||||
/* Close the process handle, reference the subsystem, and exit */
|
||||
DPRINT1("Accept failed or rejected: %lx\n", Status);
|
||||
if (ClientContext != (PVOID)SbApiMsg) RtlFreeHeap(SmpHeap, 0, ClientContext);
|
||||
if (ProcessHandle) NtClose(ProcessHandle);
|
||||
if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Save the port handle now that we've accepted it */
|
||||
if (ClientContext) ClientContext->PortHandle = PortHandle;
|
||||
if (CidSubsystem) CidSubsystem->PortHandle = PortHandle;
|
||||
|
||||
/* Complete the port connection */
|
||||
Status = NtCompleteConnectPort(PortHandle);
|
||||
if ((NT_SUCCESS(Status)) && (CidSubsystem))
|
||||
{
|
||||
/* This was an actual subsystem, so connect back to it */
|
||||
DPRINT1("Connecting back to %wZ\n", &SubsystemPort);
|
||||
SbApiMsg->ConnectionInfo.SbApiPortName[119] = UNICODE_NULL;
|
||||
RtlCreateUnicodeString(&SubsystemPort,
|
||||
SbApiMsg->ConnectionInfo.SbApiPortName);
|
||||
Status = NtConnectPort(&CidSubsystem->SbApiPort,
|
||||
&SubsystemPort,
|
||||
&SecurityQos,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("SMSS: Connect back to Sb %wZ failed %lx\n", &SubsystemPort, Status);
|
||||
}
|
||||
RtlFreeUnicodeString(&SubsystemPort);
|
||||
|
||||
/* Now that we're connected, signal the event handle */
|
||||
NtSetEvent(CidSubsystem->Event, NULL);
|
||||
}
|
||||
else if (CidSubsystem)
|
||||
{
|
||||
/* We failed to complete the connection, so clear the port handle */
|
||||
DPRINT1("Completing the connection failed: %lx\n", Status);
|
||||
CidSubsystem->PortHandle = NULL;
|
||||
}
|
||||
|
||||
/* Dereference the subsystem and return the result */
|
||||
if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
SmpApiLoop(IN PVOID Parameter)
|
||||
{
|
||||
HANDLE SmApiPort = (HANDLE)Parameter;
|
||||
NTSTATUS Status;
|
||||
PVOID ClientContext;
|
||||
PSM_API_MSG RequestMsg = NULL;
|
||||
SM_API_MSG ReplyMsg;
|
||||
PSMP_CLIENT_CONTEXT ClientContext;
|
||||
PSM_API_MSG ReplyMsg = NULL;
|
||||
SM_API_MSG RequestMsg;
|
||||
PROCESS_BASIC_INFORMATION ProcessInformation;
|
||||
LARGE_INTEGER Timeout;
|
||||
|
||||
DPRINT1("API Loop: %p\n", SmApiPort);
|
||||
/* Increase the number of API threads for throttling code for later */
|
||||
_InterlockedExchangeAdd(&SmTotalApiThreads, 1);
|
||||
|
||||
/* Mark us critical */
|
||||
RtlSetThreadIsCritical(TRUE, NULL, TRUE);
|
||||
|
||||
/* Set the PID of the SM process itself for later checking */
|
||||
NtQueryInformationProcess(NtCurrentProcess(),
|
||||
ProcessBasicInformation,
|
||||
&ProcessInformation,
|
||||
sizeof(ProcessInformation),
|
||||
NULL);
|
||||
SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId;
|
||||
|
||||
/* Now process incoming messages */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Begin waiting on a request */
|
||||
DPRINT1("API Loop: %p\n", SmApiPort);
|
||||
Status = NtReplyWaitReceivePort(SmApiPort,
|
||||
&ClientContext,
|
||||
&RequestMsg->h,
|
||||
&ReplyMsg.h);
|
||||
DPRINT1("API loop returned: %lx\n", Status);
|
||||
(PVOID*)&ClientContext,
|
||||
&ReplyMsg->h,
|
||||
&RequestMsg.h);
|
||||
if (Status == STATUS_NO_MEMORY)
|
||||
{
|
||||
/* Ran out of memory, so do a little timeout and try again */
|
||||
if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n");
|
||||
Timeout.QuadPart = -50000000;
|
||||
NtDelayExecution(FALSE, &Timeout);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check what kind of request we received */
|
||||
switch (RequestMsg.h.u2.s2.Type)
|
||||
{
|
||||
/* A new connection */
|
||||
case LPC_CONNECTION_REQUEST:
|
||||
/* Create the right structures for it */
|
||||
DPRINT1("New connection request\n");
|
||||
SmpHandleConnectionRequest(SmApiPort, (PSB_API_MSG)&RequestMsg);
|
||||
ReplyMsg = NULL;
|
||||
break;
|
||||
|
||||
/* A closed connection */
|
||||
case LPC_PORT_CLOSED:
|
||||
/* Destroy any state we had for this client */
|
||||
DPRINT1("Port closed\n");
|
||||
//if (ClientContext) SmpPushDeferredClientContext(ClientContext);
|
||||
ReplyMsg = NULL;
|
||||
break;
|
||||
|
||||
/* An actual API message */
|
||||
default:
|
||||
if (!ClientContext)
|
||||
{
|
||||
ReplyMsg = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
RequestMsg.ReturnValue = STATUS_PENDING;
|
||||
|
||||
/* Check if the API is valid */
|
||||
if (RequestMsg.ApiNumber >= SmMaxApiNumber)
|
||||
{
|
||||
/* It isn't, fail */
|
||||
DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber);
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if ((RequestMsg.ApiNumber <= SmTerminateForeignSessionApi) &&
|
||||
!(ClientContext->Subsystem))
|
||||
{
|
||||
/* It's valid, but doesn't have a subsystem with it */
|
||||
DPRINT1("Invalid session API\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's totally okay, so call the dispatcher for it */
|
||||
DPRINT1("Calling dispatcher for ID: %lx\n", RequestMsg.ApiNumber);
|
||||
Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg,
|
||||
ClientContext,
|
||||
SmApiPort);
|
||||
}
|
||||
|
||||
/* Write the result valud and return the message back */
|
||||
RequestMsg.ReturnValue = Status;
|
||||
ReplyMsg = &RequestMsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,37 @@ HANDLE SmpSessionsObjectDirectory;
|
|||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpGetProcessMuSessionId(IN HANDLE ProcessHandle,
|
||||
OUT PULONG SessionId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG ProcessSession;
|
||||
|
||||
/* Query the kernel for the session ID */
|
||||
Status = NtQueryInformationProcess(ProcessHandle,
|
||||
ProcessSessionInformation,
|
||||
&ProcessSession,
|
||||
sizeof(ProcessSession),
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Copy it back into the buffer */
|
||||
*SessionId = ProcessSession;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failure -- assume session zero */
|
||||
DPRINT1("SMSS: GetProcessMuSessionId, Process=%x, Status=%x\n",
|
||||
ProcessHandle, Status);
|
||||
*SessionId = 0;
|
||||
}
|
||||
|
||||
/* Return result */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpSetProcessMuSessionId(IN HANDLE ProcessHandle,
|
||||
|
@ -30,7 +61,7 @@ SmpSetProcessMuSessionId(IN HANDLE ProcessHandle,
|
|||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Tell the kernel about our session ID */
|
||||
/* Tell the kernel about the session ID */
|
||||
Status = NtSetInformationProcess(ProcessHandle,
|
||||
ProcessSessionInformation,
|
||||
&SessionId,
|
||||
|
|
|
@ -29,6 +29,8 @@ ULONG NtInitialUserProcessBufferType = REG_SZ;
|
|||
UNICODE_STRING SmpSystemRoot;
|
||||
ULONG AttachedSessionId = -1;
|
||||
BOOLEAN SmpDebug, SmpEnableDots;
|
||||
HANDLE SmApiPort;
|
||||
HANDLE SmpInitialCommandProcessId;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
|
@ -57,6 +59,7 @@ SmpExecuteImage(IN PUNICODE_STRING FileName,
|
|||
NTSTATUS Status;
|
||||
RTL_USER_PROCESS_INFORMATION LocalProcessInfo;
|
||||
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
|
||||
DPRINT1("Executing image: %wZ\n", FileName);
|
||||
|
||||
/* Use the input process information if we have it, otherwise use local */
|
||||
ProcessInfo = ProcessInformation;
|
||||
|
@ -295,6 +298,103 @@ SmpExecuteCommand(IN PUNICODE_STRING CommandLine,
|
|||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpExecuteInitialCommand(IN ULONG MuSessionId,
|
||||
IN PUNICODE_STRING InitialCommand,
|
||||
IN HANDLE InitialCommandProcess,
|
||||
OUT PHANDLE ReturnPid)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
RTL_USER_PROCESS_INFORMATION ProcessInfo;
|
||||
UNICODE_STRING Arguments, ImageFileDirectory, ImageFileName;
|
||||
ULONG Flags = 0;
|
||||
|
||||
/* Check if we haven't yet connected to ourselves */
|
||||
if (!SmApiPort)
|
||||
{
|
||||
/* Connect to ourselves, as a client */
|
||||
Status = SmConnectToSm(0, 0, 0, &SmApiPort);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("SMSS: Unable to connect to SM - Status == %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the initial command line */
|
||||
Status = SmpParseCommandLine(InitialCommand,
|
||||
(PULONG)&Flags,
|
||||
&ImageFileName,
|
||||
&ImageFileDirectory,
|
||||
&Arguments);
|
||||
if (Flags & SMP_INVALID_PATH)
|
||||
{
|
||||
/* Fail if it doesn't exist */
|
||||
DPRINT1("SMSS: Initial command image (%wZ) not found\n", &ImageFileName);
|
||||
if (ImageFileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer);
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* And fail if any other reason is also true */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("SMSS: SmpParseCommand( %wZ ) failed - Status == %lx\n",
|
||||
InitialCommand, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Execute the initial command -- but defer its full execution */
|
||||
Status = SmpExecuteImage(&ImageFileName,
|
||||
&ImageFileDirectory,
|
||||
InitialCommand,
|
||||
MuSessionId,
|
||||
SMP_DEFERRED_FLAG,
|
||||
&ProcessInfo);
|
||||
|
||||
/* Free any buffers we had lying around */
|
||||
if (ImageFileName.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer);
|
||||
}
|
||||
if (ImageFileDirectory.Buffer)
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileDirectory.Buffer);
|
||||
}
|
||||
if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer);
|
||||
|
||||
/* Bail out if we couldn't execute the initial command */
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Now duplicate the handle to this process */
|
||||
Status = NtDuplicateObject(NtCurrentProcess(),
|
||||
ProcessInfo.ProcessHandle,
|
||||
NtCurrentProcess(),
|
||||
InitialCommandProcess,
|
||||
PROCESS_ALL_ACCESS,
|
||||
0,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Kill it utterly if duplication failed */
|
||||
DPRINT1("SMSS: DupObject Failed. Status == %lx\n", Status);
|
||||
NtTerminateProcess(ProcessInfo.ProcessHandle, Status);
|
||||
NtResumeThread(ProcessInfo.ThreadHandle, NULL);
|
||||
NtClose(ProcessInfo.ThreadHandle);
|
||||
NtClose(ProcessInfo.ProcessHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Return PID to the caller, and set this as the initial command PID */
|
||||
if (ReturnPid) *ReturnPid = ProcessInfo.ClientId.UniqueProcess;
|
||||
if (!MuSessionId) SmpInitialCommandProcessId = ProcessInfo.ClientId.UniqueProcess;
|
||||
|
||||
/* Now call our server execution function to wrap up its initialization */
|
||||
Status = SmExecPgm(SmApiPort, &ProcessInfo, FALSE);
|
||||
if (!NT_SUCCESS(Status)) DPRINT1("SMSS: SmExecPgm Failed. Status == %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer,
|
||||
|
@ -630,6 +730,9 @@ _main(IN INT argc,
|
|||
DPRINT1("SMSS: SmpInit return failure - Status == %x\n", Status);
|
||||
RtlInitUnicodeString(&DbgString, L"Session Manager Initialization");
|
||||
Parameters[1] = Status;
|
||||
DPRINT1("SMSS-2 Loaded... Launching original SMSS\n");
|
||||
Status = LaunchOldSmss(Handles);
|
||||
goto SetupHack;
|
||||
//_SEH2_LEAVE; Hack so that setup can work. will go away later
|
||||
}
|
||||
|
||||
|
@ -647,14 +750,21 @@ _main(IN INT argc,
|
|||
DPRINT1("Global Flags Set to SMSS Debugging: Not yet supported\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Execute the initial command (Winlogon.exe) */
|
||||
Status = SmpExecuteInitialCommand(0, &InitialCommand, &Handles[1], NULL);
|
||||
#else
|
||||
/* Launch the original SMSS */
|
||||
DPRINT1("SMSS-2 Loaded... Launching original SMSS\n");
|
||||
Status = LaunchOldSmss(Handles);
|
||||
#endif
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail and raise a hard error */
|
||||
DPRINT1("SMSS: Execute Old SMSS failed\n");
|
||||
RtlInitUnicodeString(&DbgString,
|
||||
L"Session Manager LaunchOldSmss");
|
||||
Parameters[1] = Status;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
/* Execute the initial command (Winlogon.exe) */
|
||||
Status = SmpExecuteInitialCommand(0, &InitialCommand, &Handles[1], NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail and raise a hard error */
|
||||
|
@ -679,6 +789,7 @@ _main(IN INT argc,
|
|||
SmpReleasePrivilege(State);
|
||||
|
||||
/* Wait on either CSRSS or Winlogon to die */
|
||||
SetupHack:
|
||||
Status = NtWaitForMultipleObjects(RTL_NUMBER_OF(Handles),
|
||||
Handles,
|
||||
WaitAny,
|
||||
|
|
|
@ -49,6 +49,20 @@ typedef struct _SMP_REGISTRY_VALUE
|
|||
PCHAR AnsiValue;
|
||||
} SMP_REGISTRY_VALUE, *PSMP_REGISTRY_VALUE;
|
||||
|
||||
typedef struct _SMP_SUBSYSTEM
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
HANDLE Event;
|
||||
HANDLE ProcessHandle;
|
||||
ULONG ImageType;
|
||||
HANDLE PortHandle;
|
||||
HANDLE SbApiPort;
|
||||
CLIENT_ID ClientId;
|
||||
ULONG MuSessionId;
|
||||
BOOLEAN Terminating;
|
||||
ULONG ReferenceCount;
|
||||
} SMP_SUBSYSTEM, *PSMP_SUBSYSTEM;
|
||||
|
||||
/* EXTERNALS ******************************************************************/
|
||||
|
||||
extern RTL_CRITICAL_SECTION SmpKnownSubSysLock;
|
||||
|
@ -209,4 +223,31 @@ NTAPI
|
|||
SmpTranslateSystemPartitionInformation(
|
||||
VOID
|
||||
);
|
||||
|
||||
PSMP_SUBSYSTEM
|
||||
NTAPI
|
||||
SmpLocateKnownSubSysByCid(
|
||||
IN PCLIENT_ID ClientId
|
||||
);
|
||||
|
||||
PSMP_SUBSYSTEM
|
||||
NTAPI
|
||||
SmpLocateKnownSubSysByType(
|
||||
IN ULONG MuSessionId,
|
||||
IN ULONG ImageType
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpGetProcessMuSessionId(
|
||||
IN HANDLE ProcessHandle,
|
||||
OUT PULONG SessionId
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
SmpDereferenceSubsystem(
|
||||
IN PSMP_SUBSYSTEM SubSystem
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<library>nt</library>
|
||||
<library>pseh</library>
|
||||
<library>ntdll</library>
|
||||
<library>smlib</library>
|
||||
<pch>smss.h</pch>
|
||||
<compilationunit name="unit.c">
|
||||
<file>smss.c</file>
|
||||
|
|
|
@ -23,6 +23,97 @@ WCHAR InitialCommandBuffer[256];
|
|||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
SmpDereferenceSubsystem(IN PSMP_SUBSYSTEM SubSystem)
|
||||
{
|
||||
/* Acquire the database lock while we (potentially) destroy this subsystem */
|
||||
RtlEnterCriticalSection(&SmpKnownSubSysLock);
|
||||
|
||||
/* Drop the reference and see if it's terminating */
|
||||
if (!(--SubSystem->ReferenceCount) && (SubSystem->Terminating))
|
||||
{
|
||||
/* Close all handles and free it */
|
||||
if (SubSystem->Event) NtClose(SubSystem->Event);
|
||||
if (SubSystem->ProcessHandle) NtClose(SubSystem->ProcessHandle);
|
||||
if (SubSystem->SbApiPort) NtClose(SubSystem->SbApiPort);
|
||||
RtlFreeHeap(SmpHeap, 0, SubSystem);
|
||||
}
|
||||
|
||||
/* Release the database lock */
|
||||
RtlLeaveCriticalSection(&SmpKnownSubSysLock);
|
||||
}
|
||||
|
||||
PSMP_SUBSYSTEM
|
||||
NTAPI
|
||||
SmpLocateKnownSubSysByCid(IN PCLIENT_ID ClientId)
|
||||
{
|
||||
PSMP_SUBSYSTEM Subsystem = NULL;
|
||||
PLIST_ENTRY NextEntry;
|
||||
|
||||
/* Lock the subsystem database */
|
||||
RtlEnterCriticalSection(&SmpKnownSubSysLock);
|
||||
|
||||
/* Loop each subsystem in the database */
|
||||
NextEntry = SmpKnownSubSysHead.Flink;
|
||||
while (NextEntry != &SmpKnownSubSysHead)
|
||||
{
|
||||
/* Check if this one matches the client ID and is still valid */
|
||||
Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry);
|
||||
if ((*(PULONGLONG)&Subsystem->ClientId == *(PULONGLONG)&ClientId) &&
|
||||
!(Subsystem->Terminating))
|
||||
{
|
||||
/* Add a reference and return it */
|
||||
Subsystem->ReferenceCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reset the current pointer and keep earching */
|
||||
Subsystem = NULL;
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Release the lock and return the subsystem we found */
|
||||
RtlLeaveCriticalSection(&SmpKnownSubSysLock);
|
||||
return Subsystem;
|
||||
}
|
||||
|
||||
PSMP_SUBSYSTEM
|
||||
NTAPI
|
||||
SmpLocateKnownSubSysByType(IN ULONG MuSessionId,
|
||||
IN ULONG ImageType)
|
||||
{
|
||||
PSMP_SUBSYSTEM Subsystem = NULL;
|
||||
PLIST_ENTRY NextEntry;
|
||||
|
||||
/* Lock the subsystem database */
|
||||
RtlEnterCriticalSection(&SmpKnownSubSysLock);
|
||||
|
||||
/* Loop each subsystem in the database */
|
||||
NextEntry = SmpKnownSubSysHead.Flink;
|
||||
while (NextEntry != &SmpKnownSubSysHead)
|
||||
{
|
||||
/* Check if this one matches the image and uID, and is still valid */
|
||||
Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry);
|
||||
if ((Subsystem->ImageType == ImageType) &&
|
||||
!(Subsystem->Terminating) &&
|
||||
(Subsystem->MuSessionId == MuSessionId))
|
||||
{
|
||||
/* Return it referenced for the caller */
|
||||
Subsystem->ReferenceCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reset the current pointer and keep earching */
|
||||
Subsystem = NULL;
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* Release the lock and return the subsystem we found */
|
||||
RtlLeaveCriticalSection(&SmpKnownSubSysLock);
|
||||
return Subsystem;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpLoadSubSystem(IN PUNICODE_STRING FileName,
|
||||
|
|
|
@ -21,14 +21,14 @@
|
|||
//
|
||||
typedef enum _SMSRV_API_NUMBER
|
||||
{
|
||||
SmpCreateForeignSession,
|
||||
SmpSessionComplete,
|
||||
SmpTerminateForeignSession,
|
||||
SmpExecPgm,
|
||||
SmpLoadDeferedSubsystem,
|
||||
SmpStartCsr,
|
||||
SmpStopCsr,
|
||||
SmpMaxApiNumber // Based on BasepMaxApiNumber, UserpMaxApiNumber...
|
||||
SmCreateForeignSessionApi,
|
||||
SmSessionCompleteApi,
|
||||
SmTerminateForeignSessionApi,
|
||||
SmExecPgmApi,
|
||||
SmLoadDeferedSubsystemApi,
|
||||
SmStartCsrApi,
|
||||
SmStopCsrApi,
|
||||
SmMaxApiNumber // Based on BasepMaxApiNumber, UserpMaxApiNumber...
|
||||
} SMSRV_API_NUMBER;
|
||||
|
||||
//
|
||||
|
@ -184,7 +184,7 @@ typedef struct _SB_CONNECTION_INFO
|
|||
//
|
||||
typedef struct _SB_API_MSG
|
||||
{
|
||||
PORT_MESSAGE Header;
|
||||
PORT_MESSAGE h;
|
||||
union
|
||||
{
|
||||
SB_CONNECTION_INFO ConnectionInfo;
|
||||
|
@ -208,4 +208,25 @@ typedef struct _SB_API_MSG
|
|||
//
|
||||
C_ASSERT(sizeof(SB_CONNECTION_INFO) == 0xF4);
|
||||
C_ASSERT(sizeof(SB_API_MSG) == 0x110);
|
||||
|
||||
//
|
||||
// The actual server functions that a client linking with smlib can call
|
||||
//
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmConnectToSm(
|
||||
IN PUNICODE_STRING SbApiPortName,
|
||||
IN HANDLE SbApiPort,
|
||||
IN ULONG ImageType,
|
||||
IN HANDLE SmApiPort
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmExecPgm(
|
||||
IN HANDLE SmApiPort,
|
||||
IN PRTL_USER_PROCESS_INFORMATION ProcessInformation,
|
||||
IN BOOLEAN DebugFlag
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue