/*++ Copyright (c) 1989 Microsoft Corporation Module Name: sm6432.c Abstract: Session Manager Client Support APIs for Wow64 executable (32-bit images running on Win64) Author: Samer Arafeh (samera) 20-Sep-2001 Revision History: --*/ #if defined(_X86_) /* * Enable LPC port-messages to have compatible layout between the 32-bit and 64-bit worlds. */ #define USE_LPC6432 1 #define BUILD_WOW6432 1 #include "smdllp.h" #include "smp6432.h" #include NTSTATUS SmpThunkUserProcessInfoTo64 ( IN PRTL_USER_PROCESS_INFORMATION UserProcessInformation32, OUT PRTL_USER_PROCESS_INFORMATION64 UserProcessInformation64 ) /*++ Routine Description: This routine thunks RTL_PROCESS_USER_INFORMATION structure from 32-bit structure offsets in Win64 structure offsets. Arguments: UserProcessInformation32 - 32-bit Input structure. UserProcessInformation64 - 64-bit Output structure allocated by the caller. Return Value: NTSTATUS. --*/ { NTSTATUS NtStatus = STATUS_SUCCESS; if (ARGUMENT_PRESENT (UserProcessInformation32)) { try { UserProcessInformation64->Length = sizeof (RTL_USER_PROCESS_INFORMATION64); UserProcessInformation64->Process = (LONGLONG)UserProcessInformation32->Process; UserProcessInformation64->Thread = (LONGLONG)UserProcessInformation32->Thread; UserProcessInformation64->ClientId.UniqueProcess = (ULONGLONG)UserProcessInformation32->ClientId.UniqueProcess; UserProcessInformation64->ClientId.UniqueThread = (ULONGLONG)UserProcessInformation32->ClientId.UniqueThread; UserProcessInformation64->ImageInformation.TransferAddress = (ULONGLONG)UserProcessInformation32->ImageInformation.TransferAddress; UserProcessInformation64->ImageInformation.ZeroBits = UserProcessInformation32->ImageInformation.ZeroBits; UserProcessInformation64->ImageInformation.MaximumStackSize = UserProcessInformation32->ImageInformation.MaximumStackSize; UserProcessInformation64->ImageInformation.CommittedStackSize = UserProcessInformation32->ImageInformation.CommittedStackSize; UserProcessInformation64->ImageInformation.SubSystemType = UserProcessInformation32->ImageInformation.SubSystemType; UserProcessInformation64->ImageInformation.SubSystemVersion = UserProcessInformation32->ImageInformation.SubSystemVersion; UserProcessInformation64->ImageInformation.GpValue = UserProcessInformation32->ImageInformation.GpValue; UserProcessInformation64->ImageInformation.ImageCharacteristics = UserProcessInformation32->ImageInformation.ImageCharacteristics; UserProcessInformation64->ImageInformation.DllCharacteristics = UserProcessInformation32->ImageInformation.DllCharacteristics; UserProcessInformation64->ImageInformation.Machine = UserProcessInformation32->ImageInformation.Machine; UserProcessInformation64->ImageInformation.ImageContainsCode = UserProcessInformation32->ImageInformation.ImageContainsCode; UserProcessInformation64->ImageInformation.Spare1 = UserProcessInformation32->ImageInformation.Spare1; UserProcessInformation64->ImageInformation.LoaderFlags = UserProcessInformation32->ImageInformation.LoaderFlags; RtlCopyMemory (&UserProcessInformation64->ImageInformation.Reserved, &UserProcessInformation32->ImageInformation.Reserved, sizeof (UserProcessInformation32->ImageInformation.Reserved)); } except (EXCEPTION_EXECUTE_HANDLER) { NtStatus = GetExceptionCode (); } } else { UserProcessInformation64 = (PRTL_USER_PROCESS_INFORMATION64)UserProcessInformation32; } return NtStatus; } BOOLEAN SmpIsWow64Process ( VOID ) /*++ Routine Description: This routine detects whether the currently executing process is running inside Wow64. The routine caches the result. Arguments: None. Return Value: BOOLEAN. --*/ { NTSTATUS NtStatus; PVOID Peb32; static BOOLEAN RunningInsideWow64 = -1; if (RunningInsideWow64 == (BOOLEAN)-1) { NtStatus = NtQueryInformationProcess ( NtCurrentProcess (), ProcessWow64Information, &Peb32, sizeof (Peb32), NULL ); if (NT_SUCCESS (NtStatus)) { if (Peb32 != NULL) { RunningInsideWow64 = TRUE; } else { RunningInsideWow64 = FALSE; } } else { RunningInsideWow64 = FALSE; } } return RunningInsideWow64; } NTSTATUS SmpWow64ExecPgm( IN HANDLE SmApiPort, IN PRTL_USER_PROCESS_INFORMATION ProcessInformation32, IN BOOLEAN DebugFlag ) /*++ Routine Description: This routine allows a process to start a process using the facilities provided by the NT Session manager. This function closes all handles passed to it. Arguments: SmApiPort - Supplies a handle to a communications port connected to the Session Manager. ProcessInformation32 - Supplies a process description as returned by RtlCreateUserProcess. DebugFlag - Supplies and optional parameter which if set indicates that the caller wants to debug this process and act as its debug user interface. Return Value: NSTATUS. --*/ { NTSTATUS st; SMAPIMSG64 SmApiMsg; PSMEXECPGM64 args; RTL_USER_PROCESS_INFORMATION64 ProcessInformation64; args = &SmApiMsg.u.ExecPgm; st = SmpThunkUserProcessInfoTo64 (ProcessInformation32, &ProcessInformation64); if (NT_SUCCESS (st)) { args->DebugFlag = DebugFlag; SmApiMsg.ApiNumber = SmExecPgmApi; SmApiMsg.h.u1.s1.DataLength = sizeof(*args) + 8; SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); SmApiMsg.h.u2.ZeroInit = 0L; st = NtRequestWaitReplyPort( SmApiPort, (PPORT_MESSAGE) &SmApiMsg, (PPORT_MESSAGE) &SmApiMsg ); if ( NT_SUCCESS(st) ) { st = SmApiMsg.ReturnedStatus; } else { KdPrint(("SmExecPgm: NtRequestWaitReply Failed %lx\n",st)); } NtClose(ProcessInformation32->Process); NtClose(ProcessInformation32->Thread); } return st; } NTSTATUS SmpWow64LoadDeferedSubsystem( IN HANDLE SmApiPort, IN PUNICODE_STRING DeferedSubsystem ) /*++ Routine Description: This routine allows a process to start a defered subsystem. Arguments: SmApiPort - Supplies a handle to a communications port connected to the Session Manager. DeferedSubsystem - Supplies the name of the defered subsystem to load. Return Value: NSTATUS. --*/ { NTSTATUS st; SMAPIMSG64 SmApiMsg; PSMLOADDEFERED args; if ( DeferedSubsystem->Length >> 1 > SMP_MAXIMUM_SUBSYSTEM_NAME ) { return STATUS_INVALID_PARAMETER; } args = &SmApiMsg.u.LoadDefered; args->SubsystemNameLength = DeferedSubsystem->Length; RtlZeroMemory(args->SubsystemName, sizeof (args->SubsystemName)); RtlCopyMemory(args->SubsystemName,DeferedSubsystem->Buffer,DeferedSubsystem->Length); SmApiMsg.ApiNumber = SmLoadDeferedSubsystemApi; SmApiMsg.h.u1.s1.DataLength = sizeof(*args) + 8; SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); SmApiMsg.h.u2.ZeroInit = 0L; st = NtRequestWaitReplyPort( SmApiPort, (PPORT_MESSAGE) &SmApiMsg, (PPORT_MESSAGE) &SmApiMsg ); if ( NT_SUCCESS(st) ) { st = SmApiMsg.ReturnedStatus; } else { KdPrint(("SmExecPgm: NtRequestWaitReply Failed %lx\n",st)); } return st; } NTSTATUS SmpWow64SessionComplete( IN HANDLE SmApiPort, IN ULONG SessionId, IN NTSTATUS CompletionStatus ) /*++ Routine Description: This routine is used to report completion of a session to the NT Session manager. Arguments: SmApiPort - Supplies a handle to a communications port connected to the Session Manager. SessionId - Supplies the session id of the session which is now completed. CompletionStatus - Supplies the completion status of the session. Return Value: NSTATUS. --*/ { NTSTATUS st; SMAPIMSG64 SmApiMsg; PSMSESSIONCOMPLETE args; args = &SmApiMsg.u.SessionComplete; args->SessionId = SessionId; args->CompletionStatus = CompletionStatus; SmApiMsg.ApiNumber = SmSessionCompleteApi; SmApiMsg.h.u1.s1.DataLength = sizeof(*args) + 8; SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); SmApiMsg.h.u2.ZeroInit = 0L; st = NtRequestWaitReplyPort( SmApiPort, (PPORT_MESSAGE) &SmApiMsg, (PPORT_MESSAGE) &SmApiMsg ); if ( NT_SUCCESS(st) ) { st = SmApiMsg.ReturnedStatus; } else { KdPrint(("SmCompleteSession: NtRequestWaitReply Failed %lx\n",st)); } return st; } NTSTATUS SmpWow64StartCsr( IN HANDLE SmApiPort, OUT PULONG pMuSessionId, IN PUNICODE_STRING InitialCommand, OUT PULONG_PTR pInitialCommandProcessId, OUT PULONG_PTR pWindowsSubSysProcessId ) /*++ Routine Description: This routine allows TERMSRV to start a new CSR. Arguments: SmApiPort - Supplies a handle to a communications port connected to the Session Manager. MuSessionId - Hydra Terminal Session Id to start CSR in. InitialCommand - String for Initial Command (for debug) pInitialCommandProcessId - pointer to Process Id of initial command. pWindowsSubSysProcessId - pointer to Process Id of Windows subsystem. Return Value: NSTATUS. --*/ { NTSTATUS st; SMAPIMSG64 SmApiMsg; PSMSTARTCSR64 args; args = &SmApiMsg.u.StartCsr; args->MuSessionId = *pMuSessionId; //Sm will reassign the actuall sessionID if ( InitialCommand && ( InitialCommand->Length >> 1 > SMP_MAXIMUM_INITIAL_COMMAND ) ) { return STATUS_INVALID_PARAMETER; } if ( !InitialCommand ) { args->InitialCommandLength = 0; } else { args->InitialCommandLength = InitialCommand->Length; RtlZeroMemory(args->InitialCommand, sizeof (args->InitialCommand)); RtlCopyMemory(args->InitialCommand,InitialCommand->Buffer,InitialCommand->Length); } SmApiMsg.ApiNumber = SmStartCsrApi; SmApiMsg.h.u1.s1.DataLength = sizeof(*args) + 8; SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); SmApiMsg.h.u2.ZeroInit = 0L; st = NtRequestWaitReplyPort( SmApiPort, (PPORT_MESSAGE) &SmApiMsg, (PPORT_MESSAGE) &SmApiMsg ); if ( NT_SUCCESS(st) ) { st = SmApiMsg.ReturnedStatus; } else { DbgPrint("SmStartCsr: NtRequestWaitReply Failed %lx\n",st); } *pInitialCommandProcessId = (ULONG)args->InitialCommandProcessId; *pWindowsSubSysProcessId = (ULONG)args->WindowsSubSysProcessId; *pMuSessionId = args->MuSessionId; return st; } NTSTATUS SmpWow64StopCsr( IN HANDLE SmApiPort, IN ULONG MuSessionId ) /*++ Routine Description: This routine allows TERMSRV to stop a CSR. Arguments: SmApiPort - Supplies a handle to a communications port connected to the Session Manager. MuSessionId - Terminal Server Session Id to stop Return Value: NSTATUS. --*/ { NTSTATUS st; SMAPIMSG64 SmApiMsg; PSMSTOPCSR args; args = &SmApiMsg.u.StopCsr; args->MuSessionId = MuSessionId; SmApiMsg.ApiNumber = SmStopCsrApi; SmApiMsg.h.u1.s1.DataLength = sizeof(*args) + 8; SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg); SmApiMsg.h.u2.ZeroInit = 0L; st = NtRequestWaitReplyPort( SmApiPort, (PPORT_MESSAGE) &SmApiMsg, (PPORT_MESSAGE) &SmApiMsg ); if ( NT_SUCCESS(st) ) { st = SmApiMsg.ReturnedStatus; } else { DbgPrint("SmStopCsr: NtRequestWaitReply Failed %lx\n",st); } return st; } #endif // #if defined(_X86_)