Merge branch 'master' into npdmfixup

This commit is contained in:
SciresM
2018-10-31 18:02:07 +09:00
committed by GitHub
235 changed files with 6301 additions and 9851 deletions

View File

@@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src
DEFINES := -DDISABLE_IPC
@@ -34,7 +34,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX -DSM_ENABLE_MITM -DSM_MINIMUM_SESSION_LIMIT=8
CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX -DSM_ENABLE_MITM -DSM_ENABLE_INIT_DEFERS -DSM_MINIMUM_SESSION_LIMIT=8
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17

View File

@@ -1,7 +1,7 @@
{
"name": "sm",
"title_id": "0x0100000000000004",
"main_thread_stack_size": "0x1000",
"main_thread_stack_size": "0x2000",
"main_thread_priority": 27,
"default_cpu_id": 3,
"process_category": 1,
@@ -13,58 +13,59 @@
{
"type": "syscalls",
"value": {
"svcSetHeapSize": "0x01",
"svcSetMemoryPermission": "0x02",
"svcSetMemoryAttribute": "0x03",
"svcMapMemory": "0x04",
"svcUnmapMemory": "0x05",
"svcQueryMemory": "0x06",
"svcExitProcess": "0x07",
"svcCreateThread": "0x08",
"svcStartThread": "0x09",
"svcExitThread": "0x0A",
"svcSleepThread": "0x0B",
"svcGetThreadPriority": "0x0C",
"svcSetThreadPriority": "0x0D",
"svcGetThreadCoreMask": "0x0E",
"svcSetThreadCoreMask": "0x0F",
"svcGetCurrentProcessorNumber": "0x10",
"svcSignalEvent": "0x11",
"svcClearEvent": "0x12",
"svcMapSharedMemory": "0x13",
"svcUnmapSharedMemory": "0x14",
"svcCreateTransferMemory": "0x15",
"svcCloseHandle": "0x16",
"svcResetSignal": "0x17",
"svcWaitSynchronization": "0x18",
"svcCancelSynchronization": "0x19",
"svcArbitrateLock": "0x1A",
"svcArbitrateUnlock": "0x1B",
"svcWaitProcessWideKeyAtomic": "0x1C",
"svcSignalProcessWideKey": "0x1D",
"svcGetSystemTick": "0x1E",
"svcConnectToNamedPort": "0x1F",
"svcSendSyncRequestLight": "0x20",
"svcSendSyncRequest": "0x21",
"svcSendSyncRequestWithUserBuffer": "0x22",
"svcSendAsyncRequestWithUserBuffer": "0x23",
"svcGetProcessId": "0x24",
"svcGetThreadId": "0x25",
"svcBreak": "0x26",
"svcOutputDebugString": "0x27",
"svcReturnFromException": "0x28",
"svcGetInfo": "0x29",
"svcWaitForAddress": "0x34",
"svcSignalToAddress": "0x35",
"svcCreateSession": "0x40",
"svcAcceptSession": "0x41",
"svcReplyAndReceiveLight": "0x42",
"svcReplyAndReceive": "0x43",
"svcReplyAndReceiveWithUserBuffer": "0x44",
"svcGetMemoryInfo": "0x6F",
"svcCreatePort": "0x70",
"svcManageNamedPort": "0x71",
"svcConnectToPort": "0x72"
"svcSetHeapSize" : "0x01",
"svcSetMemoryPermission" : "0x02",
"svcSetMemoryAttribute" : "0x03",
"svcMapMemory" : "0x04",
"svcUnmapMemory" : "0x05",
"svcQueryMemory" : "0x06",
"svcExitProcess" : "0x07",
"svcCreateThread" : "0x08",
"svcStartThread" : "0x09",
"svcExitThread" : "0x0A",
"svcSleepThread" : "0x0B",
"svcGetThreadPriority" : "0x0C",
"svcSetThreadPriority" : "0x0D",
"svcGetThreadCoreMask" : "0x0E",
"svcSetThreadCoreMask" : "0x0F",
"svcGetCurrentProcessorNumber" : "0x10",
"svcSignalEvent" : "0x11",
"svcClearEvent" : "0x12",
"svcMapSharedMemory" : "0x13",
"svcUnmapSharedMemory" : "0x14",
"svcCreateTransferMemory" : "0x15",
"svcCloseHandle" : "0x16",
"svcResetSignal" : "0x17",
"svcWaitSynchronization" : "0x18",
"svcCancelSynchronization" : "0x19",
"svcArbitrateLock" : "0x1A",
"svcArbitrateUnlock" : "0x1B",
"svcWaitProcessWideKeyAtomic" : "0x1C",
"svcSignalProcessWideKey" : "0x1D",
"svcGetSystemTick" : "0x1E",
"svcConnectToNamedPort" : "0x1F",
"svcSendSyncRequestLight" : "0x20",
"svcSendSyncRequest" : "0x21",
"svcSendSyncRequestWithUserBuffer" : "0x22",
"svcSendAsyncRequestWithUserBuffer" : "0x23",
"svcGetProcessId" : "0x24",
"svcGetThreadId" : "0x25",
"svcBreak" : "0x26",
"svcOutputDebugString" : "0x27",
"svcReturnFromException" : "0x28",
"svcGetInfo" : "0x29",
"svcWaitForAddress" : "0x34",
"svcSignalToAddress" : "0x35",
"svcCreateSession" : "0x40",
"svcAcceptSession" : "0x41",
"svcReplyAndReceiveLight" : "0x42",
"svcReplyAndReceive" : "0x43",
"svcReplyAndReceiveWithUserBuffer" : "0x44",
"svcCreateEvent" : "0x45",
"svcGetMemoryInfo" : "0x6F",
"svcCreatePort" : "0x70",
"svcManageNamedPort" : "0x71",
"svcConnectToPort" : "0x72"
}
}
]

View File

@@ -61,15 +61,18 @@ void __appExit(void) {
/* Nothing to clean up, because we're sm. */
}
int main(int argc, char **argv)
{
consoleDebugInit(debugDevice_SVC);
/* TODO: What's a good timeout value to use here? */
WaitableManager *server_manager = new WaitableManager(U64_MAX);
auto server_manager = new WaitableManager(1);
/* Create sm:, (and thus allow things to register to it). */
server_manager->add_waitable(new ManagedPortServer<UserService>("sm:", 0x40));
server_manager->AddWaitable(new ManagedPortServer<UserService>("sm:", 0x40));
/* Create sm:m manually. */
Handle smm_h;
@@ -78,10 +81,10 @@ int main(int argc, char **argv)
while (1) { }
}
server_manager->add_waitable(new ExistingPortServer<ManagerService>(smm_h, 1));
server_manager->AddWaitable(new ExistingPortServer<ManagerService>(smm_h, 1));
/* Loop forever, servicing our services. */
server_manager->process();
server_manager->Process();
/* Cleanup. */
delete server_manager;

View File

@@ -19,31 +19,15 @@
#include "sm_manager_service.hpp"
#include "sm_registration.hpp"
Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
switch ((ManagerServiceCmd)cmd_id) {
case Manager_Cmd_RegisterProcess:
rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Manager_Cmd_UnregisterProcess:
rc = WrapIpcCommandImpl<&ManagerService::unregister_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
return rc;
Result ManagerService::RegisterProcess(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac) {
return Registration::RegisterProcess(pid, acid_sac.buffer, acid_sac.num_elements, aci0_sac.buffer, aci0_sac.num_elements);
}
Result ManagerService::handle_deferred() {
/* This service is never deferrable. */
return 0;
Result ManagerService::UnregisterProcess(u64 pid) {
return Registration::UnregisterProcess(pid);
}
std::tuple<Result> ManagerService::register_process(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac) {
return {Registration::RegisterProcess(pid, acid_sac.buffer, acid_sac.num_elements, aci0_sac.buffer, aci0_sac.num_elements)};
void ManagerService::AtmosphereEndInitDefers() {
Registration::EndInitDefers();
}
std::tuple<Result> ManagerService::unregister_process(u64 pid) {
return {Registration::UnregisterProcess(pid)};
}

View File

@@ -16,24 +16,27 @@
#pragma once
#include <switch.h>
#include <stratosphere/iserviceobject.hpp>
#include <stratosphere.hpp>
enum ManagerServiceCmd {
Manager_Cmd_RegisterProcess = 0,
Manager_Cmd_UnregisterProcess = 1
Manager_Cmd_UnregisterProcess = 1,
Manager_Cmd_AtmosphereEndInitDefers = 65000,
};
class ManagerService final : public IServiceObject {
public:
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
Result handle_deferred() override;
ManagerService *clone() override {
return new ManagerService();
}
private:
/* Actual commands. */
std::tuple<Result> register_process(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac);
std::tuple<Result> unregister_process(u64 pid);
virtual Result RegisterProcess(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac);
virtual Result UnregisterProcess(u64 pid);
virtual void AtmosphereEndInitDefers();
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<Manager_Cmd_RegisterProcess, &ManagerService::RegisterProcess>(),
MakeServiceCommandMeta<Manager_Cmd_UnregisterProcess, &ManagerService::UnregisterProcess>(),
MakeServiceCommandMeta<Manager_Cmd_AtmosphereEndInitDefers, &ManagerService::AtmosphereEndInitDefers>(),
};
};

View File

@@ -16,7 +16,7 @@
#include <switch.h>
#include <algorithm>
#include <stratosphere/servicesession.hpp>
#include <stratosphere.hpp>
#include "sm_registration.hpp"
#include "meta_tools.hpp"
@@ -26,6 +26,7 @@ static std::array<Registration::Service, REGISTRATION_LIST_MAX_SERVICE> g_servic
static u64 g_initial_process_id_low = 0;
static u64 g_initial_process_id_high = 0;
static bool g_determined_initial_process_ids = false;
static bool g_end_init_defers = false;
u64 GetServiceNameLength(u64 service) {
u64 service_name_len = 0;
@@ -36,6 +37,38 @@ u64 GetServiceNameLength(u64 service) {
return service_name_len;
}
/* Atmosphere extension utilities. */
void Registration::EndInitDefers() {
g_end_init_defers = true;
}
constexpr u64 EncodeNameConstant(const char *name) {
u64 service = 0;
for (unsigned int i = 0; i < sizeof(service); i++) {
if (name[i] == '\x00') {
break;
}
service |= ((u64)name[i]) << (8 * i);
}
return service;
}
bool Registration::ShouldInitDefer(u64 service) {
/* Only enable if compile-time generated. */
#ifndef SM_ENABLE_INIT_DEFERS
return false;
#endif
if (g_end_init_defers) {
return false;
}
/* This is a mechanism by which certain services will always be deferred until sm:m receives a special command. */
/* This can be extended with more services as needed at a later date. */
constexpr u64 FSP_SRV = EncodeNameConstant("fsp-srv");
return service == FSP_SRV;
}
/* Utilities. */
Registration::Process *Registration::GetProcessForPid(u64 pid) {
auto process_it = std::find_if(g_process_list.begin(), g_process_list.end(), member_equals_fn(&Process::pid, pid));
@@ -188,11 +221,13 @@ bool Registration::HasService(u64 service) {
Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) {
Registration::Service *target_service = GetService(service);
if (target_service == NULL) {
if (target_service == NULL || ShouldInitDefer(service)) {
/* Note: This defers the result until later. */
return RESULT_DEFER_SESSION;
}
/* */
*out = 0;
Result rc;
if (target_service->mitm_pid == 0 || target_service->mitm_pid == pid) {
@@ -215,7 +250,7 @@ Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) {
struct {
u64 magic;
u64 result;
u64 should_mitm;
bool should_mitm;
} *resp = ((decltype(resp))r.Raw);
rc = resp->result;
if (R_SUCCEEDED(rc)) {

View File

@@ -46,6 +46,9 @@ class Registration {
};
/* Utilities. */
static void EndInitDefers();
static bool ShouldInitDefer(u64 service);
static Registration::Process *GetProcessForPid(u64 pid);
static Registration::Process *GetFreeProcess();
static Registration::Service *GetService(u64 service);

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
struct SmServiceName {
char name[sizeof(u64)];
};
static_assert(__alignof__(SmServiceName) == 1, "SmServiceName definition!");

View File

@@ -15,116 +15,90 @@
*/
#include <switch.h>
#include <stratosphere/servicesession.hpp>
#include <stratosphere.hpp>
#include "sm_user_service.hpp"
#include "sm_registration.hpp"
Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
switch ((UserServiceCmd)cmd_id) {
case User_Cmd_Initialize:
rc = WrapIpcCommandImpl<&UserService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case User_Cmd_GetService:
rc = WrapIpcCommandImpl<&UserService::get_service>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case User_Cmd_RegisterService:
rc = WrapIpcCommandImpl<&UserService::register_service>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case User_Cmd_UnregisterService:
rc = WrapIpcCommandImpl<&UserService::unregister_service>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
#ifdef SM_ENABLE_MITM
case User_Cmd_AtmosphereInstallMitm:
rc = WrapIpcCommandImpl<&UserService::install_mitm>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case User_Cmd_AtmosphereUninstallMitm:
rc = WrapIpcCommandImpl<&UserService::uninstall_mitm>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case User_Cmd_AtmosphereAssociatePidTidForMitm:
rc = WrapIpcCommandImpl<&UserService::associate_pid_tid_for_mitm>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
Result UserService::Initialize(PidDescriptor pid) {
this->pid = pid.pid;
this->has_initialized = true;
return 0;
}
Result UserService::GetService(Out<MovedHandle> out_h, SmServiceName service) {
Handle session_h = 0;
Result rc = 0x415;
#ifdef SM_ENABLE_SMHAX
if (!this->has_initialized) {
rc = Registration::GetServiceForPid(Registration::GetInitialProcessId(), smEncodeName(service.name), &session_h);
}
#endif
default:
break;
if (this->has_initialized) {
rc = Registration::GetServiceForPid(this->pid, smEncodeName(service.name), &session_h);
}
if (R_SUCCEEDED(rc)) {
out_h.SetValue(session_h);
}
return rc;
}
Result UserService::handle_deferred() {
/* If we're deferred, GetService failed. */
return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);;
}
std::tuple<Result> UserService::initialize(PidDescriptor pid) {
this->pid = pid.pid;
this->has_initialized = true;
return {0};
}
std::tuple<Result, MovedHandle> UserService::get_service(u64 service) {
Handle session_h = 0;
Result rc = 0x415;
#ifdef SM_ENABLE_SMHAX
if (!this->has_initialized) {
rc = Registration::GetServiceForPid(Registration::GetInitialProcessId(), service, &session_h);
}
#endif
if (this->has_initialized) {
rc = Registration::GetServiceForPid(this->pid, service, &session_h);
}
/* It's possible that this will end up deferring us...take that into account. */
if (rc == RESULT_DEFER_SESSION) {
this->deferred_service = service;
}
return {rc, MovedHandle{session_h}};
}
std::tuple<Result, MovedHandle> UserService::deferred_get_service(u64 service) {
Handle session_h = 0;
Result rc = Registration::GetServiceHandle(this->pid, service, &session_h);
return {rc, MovedHandle{session_h}};
}
std::tuple<Result, MovedHandle> UserService::register_service(u64 service, u8 is_light, u32 max_sessions) {
Result UserService::RegisterService(Out<MovedHandle> out_h, SmServiceName service, u32 max_sessions, bool is_light) {
Handle service_h = 0;
Result rc = 0x415;
#ifdef SM_ENABLE_SMHAX
if (!this->has_initialized) {
rc = Registration::RegisterServiceForPid(Registration::GetInitialProcessId(), service, max_sessions, (is_light & 1) != 0, &service_h);
rc = Registration::RegisterServiceForPid(Registration::GetInitialProcessId(), smEncodeName(service.name), max_sessions, (is_light & 1) != 0, &service_h);
}
#endif
if (this->has_initialized) {
rc = Registration::RegisterServiceForPid(this->pid, service, max_sessions, (is_light & 1) != 0, &service_h);
rc = Registration::RegisterServiceForPid(this->pid, smEncodeName(service.name), max_sessions, (is_light & 1) != 0, &service_h);
}
return {rc, MovedHandle{service_h}};
if (R_SUCCEEDED(rc)) {
out_h.SetValue(service_h);
}
return rc;
}
std::tuple<Result> UserService::unregister_service(u64 service) {
Result UserService::UnregisterService(SmServiceName service) {
Result rc = 0x415;
#ifdef SM_ENABLE_SMHAX
if (!this->has_initialized) {
rc = Registration::UnregisterServiceForPid(Registration::GetInitialProcessId(), service);
rc = Registration::UnregisterServiceForPid(Registration::GetInitialProcessId(), smEncodeName(service.name));
}
#endif
if (this->has_initialized) {
rc = Registration::UnregisterServiceForPid(this->pid, service);
rc = Registration::UnregisterServiceForPid(this->pid, smEncodeName(service.name));
}
return {rc};
return rc;
}
std::tuple<Result, MovedHandle, MovedHandle> UserService::install_mitm(u64 service) {
Result UserService::AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, SmServiceName service) {
Handle service_h = 0;
Handle query_h = 0;
Result rc = 0x415;
if (this->has_initialized) {
rc = Registration::InstallMitmForPid(this->pid, service, &service_h, &query_h);
rc = Registration::InstallMitmForPid(this->pid, smEncodeName(service.name), &service_h, &query_h);
}
return {rc, MovedHandle{service_h}, MovedHandle{query_h}};
if (R_SUCCEEDED(rc)) {
srv_h.SetValue(service_h);
qry_h.SetValue(query_h);
}
return rc;
}
std::tuple<Result> UserService::associate_pid_tid_for_mitm(u64 pid, u64 tid) {
Result UserService::AtmosphereUninstallMitm(SmServiceName service) {
Result rc = 0x415;
if (this->has_initialized) {
rc = Registration::UninstallMitmForPid(this->pid, smEncodeName(service.name));
}
return rc;
}
Result UserService::AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid) {
Result rc = 0x415;
if (this->has_initialized) {
if (Registration::IsInitialProcess(pid)) {
@@ -133,13 +107,5 @@ std::tuple<Result> UserService::associate_pid_tid_for_mitm(u64 pid, u64 tid) {
rc = Registration::AssociatePidTidForMitm(pid, tid);
}
}
return {rc};
return rc;
}
std::tuple<Result> UserService::uninstall_mitm(u64 service) {
Result rc = 0x415;
if (this->has_initialized) {
rc = Registration::UninstallMitmForPid(this->pid, service);
}
return {rc};
}

View File

@@ -16,7 +16,8 @@
#pragma once
#include <switch.h>
#include <stratosphere/iserviceobject.hpp>
#include <stratosphere.hpp>
#include "sm_types.hpp"
enum UserServiceCmd {
User_Cmd_Initialize = 0,
@@ -30,32 +31,31 @@ enum UserServiceCmd {
};
class UserService final : public IServiceObject {
u64 pid = U64_MAX;
bool has_initialized = false;
u64 deferred_service = 0;
public:
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
Result handle_deferred() override;
UserService *clone() override {
auto new_srv = new UserService();
new_srv->pid = pid;
new_srv->has_initialized = has_initialized;
new_srv->deferred_service = deferred_service;
return new_srv;
}
private:
u64 pid = U64_MAX;
bool has_initialized = false;
/* Actual commands. */
std::tuple<Result> initialize(PidDescriptor pid);
std::tuple<Result, MovedHandle> get_service(u64 service);
std::tuple<Result, MovedHandle> deferred_get_service(u64 service);
std::tuple<Result, MovedHandle> register_service(u64 service, u8 is_light, u32 max_sessions);
std::tuple<Result> unregister_service(u64 service);
virtual Result Initialize(PidDescriptor pid);
virtual Result GetService(Out<MovedHandle> out_h, SmServiceName service);
virtual Result RegisterService(Out<MovedHandle> out_h, SmServiceName service, u32 max_sessions, bool is_light);
virtual Result UnregisterService(SmServiceName service);
/* Atmosphere commands. */
std::tuple<Result, MovedHandle, MovedHandle> install_mitm(u64 service);
std::tuple<Result> uninstall_mitm(u64 service);
std::tuple<Result> associate_pid_tid_for_mitm(u64 pid, u64 tid);
virtual Result AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, SmServiceName service);
virtual Result AtmosphereUninstallMitm(SmServiceName service);
virtual Result AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<User_Cmd_Initialize, &UserService::Initialize>(),
MakeServiceCommandMeta<User_Cmd_GetService, &UserService::GetService>(),
MakeServiceCommandMeta<User_Cmd_RegisterService, &UserService::RegisterService>(),
MakeServiceCommandMeta<User_Cmd_UnregisterService, &UserService::UnregisterService>(),
#ifdef SM_ENABLE_MITM
MakeServiceCommandMeta<User_Cmd_AtmosphereInstallMitm, &UserService::AtmosphereInstallMitm>(),
MakeServiceCommandMeta<User_Cmd_AtmosphereUninstallMitm, &UserService::AtmosphereUninstallMitm>(),
MakeServiceCommandMeta<User_Cmd_AtmosphereAssociatePidTidForMitm, &UserService::AtmosphereAssociatePidTidForMitm>(),
#endif
};
};