From a4b6633b0d85424bf152494d74f1b2963d4d67b8 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Fri, 29 Jun 2007 20:18:47 +0000 Subject: [PATCH] Add the vmwaregateway tool source code of Volkmar Uhlig . Upgraded project file and changed headers to get it to compile. svn path=/trunk/tools/vmwaregateway/; revision=270 --- servicemgr.cpp | 132 +++++++++++++++++++ servicemgr.h | 19 +++ vmwaregateway.cpp | 307 +++++++++++++++++++++++++++++++++++++++++++ vmwaregateway.sln | 20 +++ vmwaregateway.vcproj | 268 +++++++++++++++++++++++++++++++++++++ 5 files changed, 746 insertions(+) create mode 100644 servicemgr.cpp create mode 100644 servicemgr.h create mode 100644 vmwaregateway.cpp create mode 100644 vmwaregateway.sln create mode 100644 vmwaregateway.vcproj diff --git a/servicemgr.cpp b/servicemgr.cpp new file mode 100644 index 0000000..f11c2da --- /dev/null +++ b/servicemgr.cpp @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (c) 2000 by Volkmar Uhlig, volkmar@ira.uka.de, www.uhlig-langert.de/volkmar +// +// all code can be reused and modified +// +// +// + +#include +#include +#include "servicemgr.h" + +extern void Server(); + +SERVICE_STATUS ssStatus; +SERVICE_STATUS_HANDLE sshStatusHandle; + +HANDLE hServiceEvent = NULL; + +BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint) +{ + BOOL fResult; + if (dwCurrentState==SERVICE_START_PENDING) + ssStatus.dwControlsAccepted=0; + else + ssStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP; // | SERVICE_ACCEPT_PAUSE_CONTINUE; + ssStatus.dwCurrentState=dwCurrentState; + ssStatus.dwWin32ExitCode=dwWin32ExitCode; + ssStatus.dwCheckPoint=dwCheckPoint; + ssStatus.dwWaitHint=dwWaitHint; + if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) { + SetEvent(hServiceEvent); + } + return fResult; +} + + +void RegisterService(LPCSTR lpszBinaryPathName, LPCSTR lpszDependencies) +{ + printf("Create %s Service for executable %s\n", GetServiceName(), lpszBinaryPathName); + SC_HANDLE schService, schSCManager; + schSCManager=OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (schSCManager!=NULL) { + schService=CreateService( + schSCManager, + GetServiceName(FALSE), + GetServiceName(TRUE), + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + (char*)lpszBinaryPathName, + NULL, // no load ordering + NULL, // no tag id + lpszDependencies, + NULL, // Local system account + NULL); // no pwd + if (schService==NULL) + printf("CreateService Error: %ld", GetLastError()); + else + printf("CreateService SUCCESS\n"); + } + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); +} + +void UnregisterService() { + SC_HANDLE schService, schSCManager; + schSCManager=OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + schService=OpenService(schSCManager, + GetServiceName(FALSE), + SERVICE_ALL_ACCESS); + if (DeleteService(schService)) + printf("Service %s successfully unregistered.\n", GetServiceName()); + else + printf("Error while unregistering service %s: %ld\n", GetServiceName(), GetLastError()); + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); +} + +VOID service_ctrl(DWORD dwCtrlCode) { + DWORD dwState = SERVICE_RUNNING; + switch(dwCtrlCode) { + case SERVICE_CONTROL_STOP: + dwState = SERVICE_STOP_PENDING; + ReportStatusToSCMgr( + SERVICE_STOP_PENDING, + NO_ERROR, + 1, + 3000); + SetEvent(hServiceEvent); + return; + case SERVICE_CONTROL_INTERROGATE: + break; + default: + break; + } + ReportStatusToSCMgr(dwState, NO_ERROR, 0, 0); +} + +VOID service_main(DWORD dwArgs, LPTSTR *lpszArgv) +{ + DWORD dwWait; + sshStatusHandle=RegisterServiceCtrlHandler(GetServiceName(), + (LPHANDLER_FUNCTION)service_ctrl); + if (!sshStatusHandle) goto cleanup; + ssStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; + ssStatus.dwServiceSpecificExitCode=0; + if(!ReportStatusToSCMgr(SERVICE_START_PENDING, //service state + NO_ERROR, // exit code + 1, // checkpoint + 3000)) // wait hint + goto cleanup; + hServiceEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (hServiceEvent == (HANDLE)NULL) goto cleanup; + if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 2, 3000)) goto cleanup; + + // starting... + if (CreateThread(NULL, 4000, LPTHREAD_START_ROUTINE(Server), NULL, 0, NULL)==NULL) goto cleanup; + if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0, 0)) goto cleanup; + + dwWait = WaitForSingleObject( hServiceEvent, INFINITE); + +cleanup: + CloseHandle(hServiceEvent); + + if (sshStatusHandle!=NULL) + ReportStatusToSCMgr(SERVICE_STOPPED, 0, 0, 0); + + return; +} diff --git a/servicemgr.h b/servicemgr.h new file mode 100644 index 0000000..1a2c605 --- /dev/null +++ b/servicemgr.h @@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (c) 2000 by Volkmar Uhlig, volkmar@ira.uka.de, www.uhlig-langert.de/volkmar +// +// all code can be reused and modified +// +// +// + + +VOID service_ctrl(DWORD dwCtrlCode); +VOID service_main(DWORD dwArgs, LPTSTR *lpszArgv); + +void RegisterService(LPCSTR lpszBinaryPathName, LPCSTR lpszDependencies); +void UnregisterService(); + +LPCSTR GetServiceName(BOOL bLongName = FALSE); + +extern HANDLE hServiceEvent; \ No newline at end of file diff --git a/vmwaregateway.cpp b/vmwaregateway.cpp new file mode 100644 index 0000000..7d001ac --- /dev/null +++ b/vmwaregateway.cpp @@ -0,0 +1,307 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (c) 2000 by Volkmar Uhlig, volkmar@ira.uka.de, www.uhlig-langert.de/volkmar +// +// all code can be reused and modified +// +// +// + + +#define WINVER 0x401 + +#include "winsock2.h" +#include +#include "servicemgr.h" + +#define SERVICE_NAME "VMWareGateway" +#define DISPLAY_NAME "VMWareGateway" + +#define SERVER_PORT 567 +#define BUFFER_SIZE 1024 + +#define PIPE_NAME "\\\\.\\pipe\\vmwaredebug" + +const char* errServerBusy = "Server is currently connected\n"; + + +// event numbers/index into event array +#define LISTEN_EVENT 0 +#define IO_EVENT 1 +#define PIPE_CONNECT 2 +#define PIPE_READ 3 +#define SERVICE_EVENT 4 +#define MAX_EVENTS 5 + +// verbose output - traces a lot +BOOL verbose = FALSE; + +// the central server loop +void Server() +{ + WORD wVersionRequested; + WSADATA wsaData; + wVersionRequested = MAKEWORD( 2, 2 ); + + // socket and pipe handles + HANDLE pipe; + SOCKET s, conn; + WSAEVENT hEvents[MAX_EVENTS]; + OVERLAPPED ovRead, ovConnect; + + // copy buffers + char buffersocket[BUFFER_SIZE]; + char bufferpipe[BUFFER_SIZE]; + DWORD dwBytesSocket, dwBytesPipe; + + // booleans of connection states + BOOL pipeConnected = FALSE; + BOOL socketConnected = FALSE; + + // socket stuff + sockaddr_in sockaddr; + int err; + int addrlen; + + // init network + if (err = WSAStartup(wVersionRequested, &wsaData)) { + printf("Error initializing network\n"); + return; + } + + // first create the named pipe + pipe = CreateNamedPipe(PIPE_NAME, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + 0, + 1, + 100, + 100, + NMPWAIT_WAIT_FOREVER, + NULL); + + if (pipe == INVALID_HANDLE_VALUE) { + printf("Could not create named pipe (%d)\n", GetLastError()); + exit(0); + } + + hEvents[SERVICE_EVENT] = hServiceEvent; + + // now create the listen socket to wait for incoming requests + hEvents[LISTEN_EVENT] = WSACreateEvent(); + hEvents[IO_EVENT] = WSACreateEvent(); + ovConnect.hEvent = hEvents[PIPE_CONNECT] = CreateEvent(NULL, TRUE, FALSE, NULL); + ovRead.hEvent = hEvents[PIPE_READ] = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (hEvents[LISTEN_EVENT] == WSA_INVALID_EVENT || + hEvents[IO_EVENT] == WSA_INVALID_EVENT || + hEvents[PIPE_CONNECT] == NULL || + hEvents[PIPE_READ] == NULL) + { + printf("Error creating net event\n"); + return; + } + + // async connect to named pipe + err = ConnectNamedPipe(pipe, &ovConnect); + + // listen socket + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + printf("Could not initialize socket (%d)\n", GetLastError()); + return; + } + sockaddr.sin_family=AF_INET; + sockaddr.sin_port=htons(SERVER_PORT); + sockaddr.sin_addr.s_addr = ADDR_ANY; + + err = bind(s, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); + if (err) { + printf("Could not bind socket (%d)\n", GetLastError()); + return; + } + err = listen(s, 5); + WSAEventSelect(s, hEvents[LISTEN_EVENT], FD_ACCEPT); + + + // central loop + while(1) + { + DWORD numEvent = WSAWaitForMultipleEvents(MAX_EVENTS, hEvents, + FALSE, WSA_INFINITE, TRUE); + //printf("Event: %d\n", numEvent); + switch(numEvent) { + case LISTEN_EVENT: + printf("incoming telnet request "); + if (!socketConnected) { + addrlen = sizeof(sockaddr); + conn = accept(s, (struct sockaddr*)&sockaddr, &addrlen); + if (conn == INVALID_SOCKET) { + printf("error connecting\n"); + } + else { + //err = listen(s, 5); relisten??? + hEvents[IO_EVENT] = WSACreateEvent(); + WSAEventSelect(conn, hEvents[IO_EVENT], FD_READ|FD_CLOSE); + socketConnected = TRUE; + printf("accepted\n"); + } + } + else { + addrlen = sizeof(sockaddr); + SOCKET tmp = accept(s, (struct sockaddr*)&sockaddr, &addrlen); + send(tmp, errServerBusy, strlen(errServerBusy), 0); + closesocket(tmp); + printf("denied\n"); + } + + WSAResetEvent(hEvents[LISTEN_EVENT]); + break; + + case IO_EVENT: + { + WSANETWORKEVENTS NetEvents; + WSAEnumNetworkEvents(conn, hEvents[IO_EVENT], &NetEvents); + switch(NetEvents.lNetworkEvents) + { + case FD_READ: + dwBytesSocket = recv(conn, buffersocket, sizeof(buffersocket), 0); + if (verbose) { + buffersocket[dwBytesSocket]=0; + printf("%s", buffersocket); + } + if (pipeConnected) { + DWORD dwWritten; + WriteFile(pipe, buffersocket, dwBytesSocket, &dwWritten, NULL); + } + break; + case FD_CLOSE: + /* connection closed by host */ + closesocket(conn); + socketConnected = FALSE; + listen(s, 5); + printf("telnet session closed\n"); + break; + } + + } break; + case PIPE_CONNECT: + if (!GetOverlappedResult(pipe, &ovConnect, &dwBytesPipe, FALSE)) + { + printf("error pipe connect (%d)\n", GetLastError()); + break; + } + printf("pipe connected\n"); + ResetEvent(hEvents[PIPE_CONNECT]); + ResetEvent(hEvents[PIPE_READ]); + pipeConnected = TRUE; + + ovRead.Offset = 0; + ovRead.OffsetHigh = 0; + ReadFile(pipe, bufferpipe, sizeof(bufferpipe), &dwBytesPipe, &ovRead); + break; + + case PIPE_READ: + if (GetOverlappedResult(pipe, &ovRead, &dwBytesPipe, FALSE)) + { + if (verbose) { + bufferpipe[dwBytesPipe] = 0; + printf(bufferpipe); + } + if (socketConnected) + { + send(conn, bufferpipe, dwBytesPipe, 0); + } + ResetEvent(hEvents[PIPE_READ]); + } + else + { + DWORD err = GetLastError(); + switch (err) { + case ERROR_BROKEN_PIPE: /* disconnect and reconnect pipe */ + DisconnectNamedPipe(pipe); + ConnectNamedPipe(pipe, &ovConnect); + ResetEvent(hEvents[PIPE_CONNECT]); + ResetEvent(hEvents[PIPE_READ]); + pipeConnected = FALSE; + printf("pipe disconnected\n"); + continue;break; + } + } + ovRead.Offset = 0; + ovRead.OffsetHigh = 0; + ReadFile(pipe, bufferpipe, sizeof(bufferpipe), &dwBytesPipe, &ovRead); + break; + } + } + WSACleanup(); +} + +LPCSTR GetServiceName(BOOL bLongName) +{ + if (bLongName) + return DISPLAY_NAME; + else + return SERVICE_NAME; +} + +void ShowHelp() { + printf("Named pipe <-> telnet server for Windows NT/2000 (use on your own risk :)\n" + "Volkmar Uhlig (volkmar@ira.uka.de), www.uhlig-langert.de/volkmar\n\n" + "Commands:\n" + "\t/R register as a service\n" + "\t/U unregister service\n" + "\t/T testmode\n" + "\t/V verbose mode\n" + "\nThe pipe name is \"%s\" and the telnet port is %d.\n", PIPE_NAME, SERVER_PORT); +} + +BOOL CheckArg(int argc, char * argv[], char * arg) +{ + for (int i=1; i 1) { + if (CheckArg(argc, argv, "/v")) + { + verbose = TRUE; + printf("verbose mode\n"); + } + + if (CheckArg(argc, argv, "/r")) + { + RegisterService(modulename, "\0\0"); + return 0; + } + + if (CheckArg(argc, argv, "/u")) + { + UnregisterService(); + return 0; + } + + if (CheckArg(argc, argv, "/t")) { + printf("test mode - press Ctrl+C to stop program\n"); + hServiceEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + Server(); + CloseHandle(hServiceEvent); + return 0; + } + + ShowHelp(); + } + else { + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { TEXT(SERVICE_NAME), (LPSERVICE_MAIN_FUNCTION)service_main}, + { NULL, NULL } + }; + StartServiceCtrlDispatcher(dispatchTable); + } + return 0; +} diff --git a/vmwaregateway.sln b/vmwaregateway.sln new file mode 100644 index 0000000..66766b4 --- /dev/null +++ b/vmwaregateway.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmwaregateway", "vmwaregateway.vcproj", "{AF9DB704-DF0A-4DA0-8B73-676F07538978}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AF9DB704-DF0A-4DA0-8B73-676F07538978}.Debug|Win32.ActiveCfg = Debug|Win32 + {AF9DB704-DF0A-4DA0-8B73-676F07538978}.Debug|Win32.Build.0 = Debug|Win32 + {AF9DB704-DF0A-4DA0-8B73-676F07538978}.Release|Win32.ActiveCfg = Release|Win32 + {AF9DB704-DF0A-4DA0-8B73-676F07538978}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vmwaregateway.vcproj b/vmwaregateway.vcproj new file mode 100644 index 0000000..b0ef98c --- /dev/null +++ b/vmwaregateway.vcproj @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +