From 8026f8a27e7c378c0f84bf00733bc0122afd1410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20ZHOU?= Date: Fri, 17 Nov 2023 17:42:56 +0100 Subject: [PATCH] Add 'SIMATIC' simulator. --- windows/VS2015-WAB/Fakatic/Fakatic.sln | 31 ++ .../Fakatic/Fakatic/Fakatic.vcxproj | 181 ++++++++ .../Fakatic/Fakatic/Fakatic.vcxproj.filters | 30 ++ .../VS2015-WAB/Fakatic/Fakatic/fakatic.cpp | 427 ++++++++++++++++++ windows/VS2015-WAB/Fakatic/Fakatic/fakatic.h | 56 +++ windows/VS2015-WAB/Fakatic/Fakatic/fakatic.mc | 29 ++ 6 files changed, 754 insertions(+) create mode 100644 windows/VS2015-WAB/Fakatic/Fakatic.sln create mode 100644 windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj create mode 100644 windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj.filters create mode 100644 windows/VS2015-WAB/Fakatic/Fakatic/fakatic.cpp create mode 100644 windows/VS2015-WAB/Fakatic/Fakatic/fakatic.h create mode 100644 windows/VS2015-WAB/Fakatic/Fakatic/fakatic.mc diff --git a/windows/VS2015-WAB/Fakatic/Fakatic.sln b/windows/VS2015-WAB/Fakatic/Fakatic.sln new file mode 100644 index 00000000..9c030574 --- /dev/null +++ b/windows/VS2015-WAB/Fakatic/Fakatic.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.34112.143 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Fakatic", "Fakatic\Fakatic.vcxproj", "{0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Debug|x64.ActiveCfg = Debug|x64 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Debug|x64.Build.0 = Debug|x64 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Debug|x86.ActiveCfg = Debug|Win32 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Debug|x86.Build.0 = Debug|Win32 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Release|x64.ActiveCfg = Release|x64 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Release|x64.Build.0 = Release|x64 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Release|x86.ActiveCfg = Release|Win32 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {965F2DC9-9AA0-4EDA-B810-D24B7B1C320A} + EndGlobalSection +EndGlobal diff --git a/windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj b/windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj new file mode 100644 index 00000000..39ee08e9 --- /dev/null +++ b/windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj @@ -0,0 +1,181 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {0E7BBAC4-6639-4950-92D4-5B4A8330D1BD} + Win32Proj + Fakatic + 10.0.18362.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + mc -U fakatic.mc + + + + + + + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + mc -U fakatic.mc + + + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + + + mc -U fakatic.mc + + + + + + + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + + + mc -U fakatic.mc + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj.filters b/windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj.filters new file mode 100644 index 00000000..4a26e91c --- /dev/null +++ b/windows/VS2015-WAB/Fakatic/Fakatic/Fakatic.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + + + + Resource Files + + + \ No newline at end of file diff --git a/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.cpp b/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.cpp new file mode 100644 index 00000000..07c59fed --- /dev/null +++ b/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.cpp @@ -0,0 +1,427 @@ +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include "fakatic.h" + +#pragma comment(lib, "advapi32.lib") +#pragma comment(lib, "ws2_32.lib") + + +TCHAR SVCNAME[] = TEXT("s7oiehsx64"); + +SERVICE_STATUS gSvcStatus; +SERVICE_STATUS_HANDLE gSvcStatusHandle; +HANDLE ghSvcStopEvent = NULL; + +VOID SvcInstall(void); +VOID WINAPI SvcCtrlHandler(DWORD); +VOID WINAPI SvcMain(DWORD, LPTSTR *); + +VOID ReportSvcStatus(DWORD, DWORD, DWORD); +VOID SvcInit(DWORD, LPTSTR *); +VOID SvcReportEvent(LPCTSTR); + + +// +// Purpose: +// Entry point for the process +// +// Parameters: +// None +// +// Return value: +// None, defaults to 0 (zero) +// +int __cdecl _tmain(int argc, TCHAR *argv[]) +{ + // If command-line parameter is "install", install the service. + // Otherwise, the service is probably being started by the SCM. + + if (lstrcmpi(argv[1], TEXT("install")) == 0) + { + SvcInstall(); + return 0; + } + + // TO_DO: Add any additional services for the process to this table. + SERVICE_TABLE_ENTRY DispatchTable[] = + { + { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain }, + { NULL, NULL } + }; + + // This call returns when the service has stopped. + // The process should simply terminate when the call returns. + + if (!StartServiceCtrlDispatcher(DispatchTable)) + { + SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); + } +} + +// +// Purpose: +// Installs a service in the SCM database +// +// Parameters: +// None +// +// Return value: +// None +// +VOID SvcInstall() +{ + SC_HANDLE schSCManager; + SC_HANDLE schService; + TCHAR szUnquotedPath[MAX_PATH]; + + if (!GetModuleFileName(NULL, szUnquotedPath, MAX_PATH)) + { + printf("Cannot install service (%d)\n", GetLastError()); + return; + } + + // In case the path contains a space, it must be quoted so that + // it is correctly interpreted. For example, + // "d:\my share\myservice.exe" should be specified as + // ""d:\my share\myservice.exe"". + TCHAR szPath[MAX_PATH]; + StringCbPrintf(szPath, MAX_PATH, TEXT("\"%s\""), szUnquotedPath); + + // Get a handle to the SCM database. + + schSCManager = OpenSCManager( + NULL, // local computer + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access rights + + if (NULL == schSCManager) + { + printf("OpenSCManager failed (%d)\n", GetLastError()); + return; + } + + // Create the service + + schService = CreateService( + schSCManager, // SCM database + SVCNAME, // name of service + SVCNAME, // service name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_WIN32_OWN_PROCESS, // service type + SERVICE_DEMAND_START, // start type + SERVICE_ERROR_NORMAL, // error control type + szPath, // path to service's binary + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // no dependencies + NULL, // LocalSystem account + NULL); // no password + + if (schService == NULL) + { + printf("CreateService failed (%d)\n", GetLastError()); + CloseServiceHandle(schSCManager); + return; + } + else printf("Service installed successfully\n"); + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); +} + +// +// Purpose: +// Entry point for the service +// +// Parameters: +// dwArgc - Number of arguments in the lpszArgv array +// lpszArgv - Array of strings. The first string is the name of +// the service and subsequent strings are passed by the process +// that called the StartService function to start the service. +// +// Return value: +// None. +// +VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv) +{ + // Register the handler function for the service + + gSvcStatusHandle = RegisterServiceCtrlHandler( + SVCNAME, + SvcCtrlHandler); + + if (!gSvcStatusHandle) + { + SvcReportEvent(TEXT("RegisterServiceCtrlHandler")); + return; + } + + // These SERVICE_STATUS members remain as set here + + gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + gSvcStatus.dwServiceSpecificExitCode = 0; + + // Report initial status to the SCM + + ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000); + + // Perform service-specific initialization and work. + + SvcInit(dwArgc, lpszArgv); +} + +// +// Purpose: +// The service code +// +// Parameters: +// dwArgc - Number of arguments in the lpszArgv array +// lpszArgv - Array of strings. The first string is the name of +// the service and subsequent strings are passed by the process +// that called the StartService function to start the service. +// +// Return value: +// None +// +VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv) +{ + // TO_DO: Declare and set any required variables. + // Be sure to periodically call ReportSvcStatus() with + // SERVICE_START_PENDING. If initialization fails, call + // ReportSvcStatus with SERVICE_STOPPED. + + // Create an event. The control handler function, SvcCtrlHandler, + // signals this event when it receives the stop control code. + + ghSvcStopEvent = CreateEvent( + NULL, // default security attributes + TRUE, // manual reset event + FALSE, // not signaled + NULL); // no name + + if (ghSvcStopEvent == NULL) + { + ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0); + return; + } + + + + //---------------------- + // Initialize Winsock + WSADATA wsaData; + int iResult = 0; + + SOCKET ListenSocket = INVALID_SOCKET; + sockaddr_in service; + + iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != NO_ERROR) { +// wprintf(L"WSAStartup() failed with error: %d\n", iResult); + OutputDebugString(TEXT("WSAStartup() failed\n")); + ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0); + return; + } + //---------------------- + // Create a SOCKET for listening for incoming connection requests. + ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (ListenSocket == INVALID_SOCKET) { +// wprintf(L"socket function failed with error: %ld\n", WSAGetLastError()); + WSACleanup(); + OutputDebugString(TEXT("socket() failed\n")); + ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0); + return; + } + //---------------------- + // The sockaddr_in structure specifies the address family, + // IP address, and port for the socket that is being bound. + service.sin_family = AF_INET; +// service.sin_addr.s_addr = inet_addr("127.0.0.1"); + service.sin_addr.s_addr = INADDR_ANY; + service.sin_port = htons(102); + + iResult = bind(ListenSocket, (SOCKADDR *)& service, sizeof(service)); + if (iResult == SOCKET_ERROR) { +// wprintf(L"bind function failed with error %d\n", WSAGetLastError()); + OutputDebugString(TEXT("bind() failed\n")); + iResult = closesocket(ListenSocket); + if (iResult == SOCKET_ERROR) +// wprintf(L"closesocket function failed with error %d\n", WSAGetLastError()); + OutputDebugString(TEXT("closesocket() failed\n")); + WSACleanup(); + ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0); + return; + } + //---------------------- + // Listen for incoming connection requests + // on the created socket + if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) + { +// wprintf(L"listen function failed with error: %d\n", WSAGetLastError()); + OutputDebugString(TEXT("listen() failed\n")); + iResult = closesocket(ListenSocket); + if (iResult == SOCKET_ERROR) + // wprintf(L"closesocket function failed with error %d\n", WSAGetLastError()); + OutputDebugString(TEXT("closesocket() failed\n")); + WSACleanup(); + ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0); + return; + } + +// wprintf(L"Listening on socket...\n"); + OutputDebugString(TEXT("Listening on socket...\n")); + + + + + + // Report running status when initialization is complete. + + ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); + + OutputDebugString(TEXT("Fakatic is running\n")); + + // TO_DO: Perform work until service stops. + + + while (1) + { + // Check whether to stop the service. + + WaitForSingleObject(ghSvcStopEvent, INFINITE); + + + iResult = closesocket(ListenSocket); + if (iResult == SOCKET_ERROR) + // wprintf(L"closesocket function failed with error %d\n", WSAGetLastError()); + OutputDebugString(TEXT("closesocket() failed\n")); + WSACleanup(); + + + + ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); + + OutputDebugString(TEXT("Fakatic is stopped\n")); + return; + } +} + +// +// Purpose: +// Sets the current service status and reports it to the SCM. +// +// Parameters: +// dwCurrentState - The current state (see SERVICE_STATUS) +// dwWin32ExitCode - The system error code +// dwWaitHint - Estimated time for pending operation, +// in milliseconds +// +// Return value: +// None +// +VOID ReportSvcStatus(DWORD dwCurrentState, + DWORD dwWin32ExitCode, + DWORD dwWaitHint) +{ + static DWORD dwCheckPoint = 1; + + // Fill in the SERVICE_STATUS structure. + + gSvcStatus.dwCurrentState = dwCurrentState; + gSvcStatus.dwWin32ExitCode = dwWin32ExitCode; + gSvcStatus.dwWaitHint = dwWaitHint; + + if (dwCurrentState == SERVICE_START_PENDING) + gSvcStatus.dwControlsAccepted = 0; + else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + if ((dwCurrentState == SERVICE_RUNNING) || + (dwCurrentState == SERVICE_STOPPED)) + gSvcStatus.dwCheckPoint = 0; + else gSvcStatus.dwCheckPoint = dwCheckPoint++; + + // Report the status of the service to the SCM. + SetServiceStatus(gSvcStatusHandle, &gSvcStatus); +} + +// +// Purpose: +// Called by SCM whenever a control code is sent to the service +// using the ControlService function. +// +// Parameters: +// dwCtrl - control code +// +// Return value: +// None +// +VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) +{ + // Handle the requested control code. + + switch (dwCtrl) + { + case SERVICE_CONTROL_STOP: + ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); + + // Signal the service to stop. + + SetEvent(ghSvcStopEvent); + ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0); + + return; + + case SERVICE_CONTROL_INTERROGATE: + break; + + default: + break; + } + +} + +// +// Purpose: +// Logs messages to the event log +// +// Parameters: +// szFunction - name of function that failed +// +// Return value: +// None +// +// Remarks: +// The service must have an entry in the Application event log. +// +VOID SvcReportEvent(LPCTSTR szFunction) +{ + HANDLE hEventSource; + LPCTSTR lpszStrings[2]; + TCHAR Buffer[80]; + + hEventSource = RegisterEventSource(NULL, SVCNAME); + + if (NULL != hEventSource) + { + StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError()); + + lpszStrings[0] = SVCNAME; + lpszStrings[1] = Buffer; + + ReportEvent(hEventSource, // event log handle + EVENTLOG_ERROR_TYPE, // event type + 0, // event category + SVC_ERROR, // event identifier + NULL, // no security identifier + 2, // size of lpszStrings array + 0, // no binary data + lpszStrings, // array of strings + NULL); // no binary data + + DeregisterEventSource(hEventSource); + } +} \ No newline at end of file diff --git a/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.h b/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.h new file mode 100644 index 00000000..29b9229d --- /dev/null +++ b/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.h @@ -0,0 +1,56 @@ + // The following are message definitions. +// +// Values are 32 bit values laid out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// +#define FACILITY_SYSTEM 0x0 +#define FACILITY_RUNTIME 0x2 +#define FACILITY_STUBS 0x3 +#define FACILITY_IO_ERROR_CODE 0x4 + + +// +// Define the severity codes +// +#define STATUS_SEVERITY_SUCCESS 0x0 +#define STATUS_SEVERITY_INFORMATIONAL 0x1 +#define STATUS_SEVERITY_WARNING 0x2 +#define STATUS_SEVERITY_ERROR 0x3 + + +// +// MessageId: SVC_ERROR +// +// MessageText: +// +// An error has occurred (%2). +// +#define SVC_ERROR ((DWORD)0xC0020001L) + + // A message file must end with a period on its own line + // followed by a blank line. diff --git a/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.mc b/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.mc new file mode 100644 index 00000000..c178ab96 --- /dev/null +++ b/windows/VS2015-WAB/Fakatic/Fakatic/fakatic.mc @@ -0,0 +1,29 @@ +MessageIdTypedef=DWORD + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + + +FacilityNames=(System=0x0:FACILITY_SYSTEM + Runtime=0x2:FACILITY_RUNTIME + Stubs=0x3:FACILITY_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE +) + +LanguageNames=(English=0x409:MSG00409) + +; // The following are message definitions. + +MessageId=0x1 +Severity=Error +Facility=Runtime +SymbolicName=SVC_ERROR +Language=English +An error has occurred (%2). +. + +; // A message file must end with a period on its own line +; // followed by a blank line.