// This is the main function of the executable hosting the service. // It parses the command line and passes the parameters to the service. // From a Sapphire perspective there is not much to see here. #include "Service.h" #include "string.h" #include "wtypes.h" #include "stdlib.h" #include "intsafe.h" #include "new" HRESULT ParseCommandLine( _In_ int argc, _In_reads_(argc) wchar_t** argv, _Out_ MESSAGE_ENCODING* messageEncoding, _Out_ DWORD* chunkSize, _Out_ long* maxConnections, _Out_ REPORTING_LEVEL* reportingLevel, _In_ bool server) { *messageEncoding = DEFAULT_ENCODING; *chunkSize = 32768; *maxConnections = 100; *reportingLevel = REPORT_ERROR; bool reportingSet = false; // Parse the optional parameters. for (int i = 0; i < argc; i++) { WCHAR* arg = argv[i]; if (!_wcsicmp(arg, L"-reporting:error") || !_wcsicmp(arg, L"/reporting:error")) { if (reportingSet) { wprintf(L"Error: More than one reporting level specified.\n"); return E_FAIL; } *reportingLevel = REPORT_ERROR; reportingSet = true; } else if (!_wcsicmp(arg, L"-reporting:info") || !_wcsicmp(arg, L"/reporting:info")) { if (reportingSet) { wprintf(L"Error: More than one reporting level specified.\n"); return E_FAIL; } reportingSet = true; *reportingLevel = REPORT_INFO; } else if (!_wcsicmp(arg, L"-reporting:verbose") || !_wcsicmp(arg, L"/reporting:verbose")) { if (reportingSet) { wprintf(L"Error: More than one reporting level specified.\n"); return E_FAIL; } reportingSet = true; *reportingLevel = REPORT_VERBOSE; } else if (wcsstr(arg, L"-reporting:") || wcsstr(arg, L"-reporting:")) { wprintf(L"Error: Illegal reporting level specified.\n"); return E_FAIL; } else if (!_wcsicmp(arg, L"-encoding:binary") || !_wcsicmp(arg, L"/encoding:binary")) { if (DEFAULT_ENCODING != *messageEncoding) { wprintf(L"Error: More than one encoding specified.\n"); return E_FAIL; } *messageEncoding = BINARY_ENCODING; } else if (!_wcsicmp(arg, L"-encoding:text") || !_wcsicmp(arg, L"/encoding:text")) { if (DEFAULT_ENCODING != *messageEncoding) { wprintf(L"Error: More than one encoding specified.\n"); return E_FAIL; } *messageEncoding = TEXT_ENCODING; } else if (!_wcsicmp(arg, L"-encoding:MTOM") || !_wcsicmp(arg, L"/encoding:MTOM")) { if (DEFAULT_ENCODING != *messageEncoding) { wprintf(L"Error: More than one encoding specified.\n"); return E_FAIL; } *messageEncoding = MTOM_ENCODING; } else if (!_wcsnicmp(arg, L"-encoding:", 10) || !_wcsnicmp(arg, L"/encoding:", 10)) { wprintf(L"Error: Illegal encoding specified.\n"); return E_FAIL; } else if (!_wcsnicmp(arg, L"-chunk:", 7) || !_wcsnicmp(arg, L"/chunk:", 7)) { if (!server) { wprintf(L"Chunk is not a legal setting on the client side.\n"); return E_FAIL; } *chunkSize = wcstoul(&arg[7], NULL, 10); } else if (!_wcsnicmp(arg, L"-connections:", 13) || !_wcsnicmp(arg, L"/connections:", 13)) { *maxConnections = wcstol(&arg[13], NULL, 10); } else { wprintf(L"Unrecognized parameter: %s.\n", arg); return E_FAIL; } } return S_OK; } int __cdecl wmain( _In_ int argc, _In_reads_(argc) wchar_t** argv) { int exitCode = -1; bool server = true; CFileRep* fileRep = NULL; TRANSPORT_MODE transport = TCP_TRANSPORT; SECURITY_MODE securityMode = NO_SECURITY; if (argc < 3) { wprintf(L"Usage:\n FileRepService.exe [/reporting:] [/encoding:]"); wprintf(L" [/connections:] [/chunk:]\n"); EXIT_FUNCTION } if (!_wcsicmp(argv[1], L"client")) { server = false; } else if (_wcsicmp(argv[1], L"server")) { wprintf(L"Must specify server or client\n"); EXIT_FUNCTION } LPWSTR url = argv[2]; // Default settings of optional parameters. MESSAGE_ENCODING messageEncoding = DEFAULT_ENCODING; DWORD chunkSize = 32768; long maxConnections = 100; REPORTING_LEVEL reportingLevel = REPORT_ERROR; if (argc > 3) { if (FAILED(ParseCommandLine(argc - 3, &argv[3], &messageEncoding, &chunkSize, &maxConnections, &reportingLevel, server))) { EXIT_FUNCTION } } if (FAILED(ParseTransport(url, &transport, &securityMode))) { wprintf(L"Illegal protocol.\n"); EXIT_FUNCTION } if (chunkSize > MAXMESSAGESIZE - 1024) // 1024 for overhead { wprintf(L"The chunk size specified exceeded the allowed maximum of %d.\n", MAXMESSAGESIZE); EXIT_FUNCTION } else if (0 == chunkSize) { wprintf(L"The chunk size must be greater than zero.\n"); EXIT_FUNCTION } if (maxConnections < 1) { wprintf(L"You must allow at least one connection.\n"); EXIT_FUNCTION } if (server) { fileRep = new(std::nothrow) CFileRepServer(reportingLevel, maxConnections, transport, securityMode, messageEncoding, chunkSize); } else { fileRep = new(std::nothrow) CFileRepClient(reportingLevel, maxConnections, transport, securityMode, messageEncoding); } if (fileRep == NULL) { wprintf(L"Unable to create client/service.\n"); EXIT_FUNCTION } ULONG urlSize; if (FAILED(SizeTToULong(::wcslen(url), &urlSize))) { wprintf(L"Url string too long. Exiting.\n"); EXIT_FUNCTION } if (FAILED(fileRep->Start(url, urlSize))) { wprintf(L"Service startup failed. Exiting.\n"); EXIT_FUNCTION } wprintf(L"Startup complete. Press any key to exit.\n"); (void)getchar(); fileRep->Stop(); wprintf(L"Shutdown complete.\n"); exitCode = 0; EXIT if (fileRep != NULL) { delete fileRep; fileRep = NULL; } return exitCode; }