VOID wmainCRTStartup ( VOID ) { PSVCHOST_OPTIONS lpOptions; SERVICE_TABLE_ENTRYW *pServiceTable; LPWSTR pszCmdLine; /* Set a generic SEH filter and hard fail all critical errors */ SetUnhandledExceptionFilter(SvchostUnhandledExceptionFilter); SetErrorMode(SEM_FAILCRITICALERRORS); /* Initialize the heap allocator */ MemInit(GetProcessHeap()); /* Initialize the DLL database and lock */ InitializeListHead(&DllList); InitializeCriticalSection(&ListLock); /* Get the command-line and parse it to get the service group */ pszCmdLine = GetCommandLineW(); lpOptions = BuildCommandOptions(pszCmdLine); if (lpOptions == NULL) { /* Without a valid command-line, there's nothing for us to do */ DBG_TRACE("Calling ExitProcess for %ws\n", pszCmdLine); ExitProcess(0); } /* Now use the service group information to lookup all the services */ BuildServiceArray(lpOptions); /* Convert the list of services in this group to the SCM format */ pServiceTable = BuildServiceTable(); if (pServiceTable == NULL) { /* This is critical, bail out without it */ MemFree(lpOptions); return; } /* Initialize COM and RPC as needed for this service group */ if (CallPerInstanceInitFunctions(lpOptions) == FALSE) { /* Exit with a special code indicating COM/RPC setup has failed */ DBG_ERR("%s", "CallPerInstanceInitFunctions failed -- exiting!\n"); ExitProcess(1); } /* We're ready to go -- free the options buffer */ MemFree(lpOptions); /* And call into ADVAPI32 to get our services going */ StartServiceCtrlDispatcherW(pServiceTable); }
int wmain(int argc, LPWSTR argv[]) { if (!StartServiceCtrlDispatcherW(ServiceTable)) { DPRINT1("StartServiceCtrlDispatcherW() failed\n"); return 1; } return 0; }
int wmain( int argc, WCHAR *argv[] ) { static const SERVICE_TABLE_ENTRYW service_table[] = { { termserviceW, ServiceMain }, { NULL, NULL } }; StartServiceCtrlDispatcherW( service_table ); return 0; }
int APIENTRY _tWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 // TO_DO: Add any additional services for the process to this table. SERVICE_TABLE_ENTRYW DispatchTable[] = { { SVCNAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain }, { NULL, NULL } }; // This call returns when the service has stopped. // The process should simply terminate when the call returns. if (StartServiceCtrlDispatcherW( DispatchTable )) { return 0; } MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_C_WINDOW, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_C_WINDOW)); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; }
void Service::run( ThreadController* thread ) { mThread = thread; WCHAR name[256]; wcscpy_s( name, 256, mName.c_str() ); SERVICE_TABLE_ENTRYW stServiceTable[] = { { name, _serviceMain }, { 0, 0 } }; if ( !StartServiceCtrlDispatcherW( stServiceTable ) ) EXCEPT_WINAPI( L"Couldn't start service control dispatcher" ); }
int wmain(int argc, WCHAR* argv[]) { SERVICE_TABLE_ENTRYW ServiceTable[] = { {wszServiceName, _ServiceMain}, {NULL, NULL} }; UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(argv); StartServiceCtrlDispatcherW(ServiceTable); return 0; }
// // FUNCTION: CServiceBase::Run(CServiceBase &) // // PURPOSE: Register the executable for a service with the Service Control // Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start // command, which results in a call to the OnStart method in the service. // This method blocks until the service has stopped. // // PARAMETERS: // * service - the reference to a CServiceBase object. It will become the // singleton service instance of this service application. // // RETURN VALUE: If the function succeeds, the return value is TRUE. If the // function fails, the return value is FALSE. To get extended error // information, call GetLastError. // BOOL CServiceBase::Run(CServiceBase &service) { s_service = &service; SERVICE_TABLE_ENTRYW serviceTable[] = { { service.m_name, ServiceMain }, { NULL, NULL } }; // Connects the main thread of a service process to the service control // manager, which causes the thread to be the service control dispatcher // thread for the calling process. This call returns when the service has // stopped. The process should simply terminate when the call returns. return StartServiceCtrlDispatcherW(serviceTable); }
int main(int argc, char* argv[]) { // Load configuration std::string path(argv[0]); unsigned found = path.find_last_of("/\\"); path = path.substr(0, found + 1); Configuration *configuration = Configuration::getInstance(path); Log *loggr = Log::getInstance(); serviceName = L"ChatServer"; SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); ServiceTable[0].lpServiceName = serviceName; ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONW)ServiceMain; StartServiceCtrlDispatcherW(&ServiceTable[0]); return 0; }
/* Initialize the service table for a list (REG_MULTI_SZ) of services */ static BOOL StartGroupServices(LPWSTR services) { LPWSTR service_name = NULL; SERVICE_TABLE_ENTRYW *service_table = NULL; DWORD service_count; BOOL ret; /* Count the services to load */ service_count = 0; service_name = services; while (*service_name != '\0') { ++service_count; service_name = service_name + lstrlenW(service_name); ++service_name; } WINE_TRACE("Service group contains %d services\n", service_count); /* Populate the service table */ service_table = HeapAlloc(GetProcessHeap(), 0, (service_count + 1) * sizeof(SERVICE_TABLE_ENTRYW)); service_count = 0; service_name = services; while (*service_name != '\0') { if (!AddServiceElem(service_name, &service_table[service_count])) { HeapFree(GetProcessHeap(), 0, service_table); return FALSE; } ++service_count; service_name = service_name + lstrlenW(service_name); ++service_name; } service_table[service_count].lpServiceName = NULL; service_table[service_count].lpServiceProc = NULL; /* Start the services */ if (!(ret = StartServiceCtrlDispatcherW(service_table))) WINE_ERR("StartServiceCtrlDispatcherW failed to start %s: %u\n", wine_dbgstr_w(services), GetLastError()); HeapFree(GetProcessHeap(), 0, service_table); return ret; }
int _tmain (int argc, LPTSTR argv []) { SERVICE_TABLE_ENTRYW ServiceTable[] = { {ServiceName, ServiceMain}, {NULL, NULL } }; if (InitLogging()) { if (!StartServiceCtrlDispatcherW(ServiceTable)) LogEvent(L"failed to start the service control dispatcher", GetLastError(), 101, LOG_ALL); UninitLogging(); } return 0; }
int wmain( int argc, WCHAR *argv[] ) { SERVICE_TABLE_ENTRYW service_table[2]; if (!(driver_name = argv[1])) { WINE_ERR( "missing device name, winedevice isn't supposed to be run manually\n" ); return 1; } service_table[0].lpServiceName = argv[1]; service_table[0].lpServiceProc = ServiceMain; service_table[1].lpServiceName = NULL; service_table[1].lpServiceProc = NULL; StartServiceCtrlDispatcherW( service_table ); return 0; }
bool dtr_daemon (const dtr_callbacks * cb, void * cb_arg, bool foreground, int * exit_code, tr_error ** error) { callbacks = cb; callback_arg = cb_arg; *exit_code = 1; if (foreground) { if (!SetConsoleCtrlHandler (&handle_console_ctrl, TRUE)) { set_system_error (error, GetLastError (), "SetConsoleCtrlHandler() failed"); return false; } *exit_code = cb->on_start (cb_arg, true); } else { const SERVICE_TABLE_ENTRY service_table[] = { { (LPWSTR) service_name, &service_main }, { NULL, NULL } }; if (!StartServiceCtrlDispatcherW (service_table)) { set_system_error (error, GetLastError (), "StartServiceCtrlDispatcher() failed"); return false; } *exit_code = 0; } return true; }
int wmain(int argc, WCHAR *argv[]) { SERVICE_TABLE_ENTRYW ServiceTable[2] = { {ServiceName, ServiceMain}, {NULL, NULL} }; UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(argv); DPRINT("wlansvc: main() started\n"); StartServiceCtrlDispatcherW(ServiceTable); DPRINT("wlansvc: main() done\n"); ExitThread(0); return 0; }
VOID wmain(int argc, wchar_t *argv[], wchar_t *envp[]) { if (argc > 1) { AccountName = argv[1]; DebugOut("argv[1] = \"%S\"\n", argv[1]); } SERVICE_TABLE_ENTRY DispatchTable[] = { { SERVICE_NAME, ServiceStart }, { NULL, NULL } }; if (!StartServiceCtrlDispatcherW(DispatchTable)) { DWORD LastError = GetLastError(); if (LastError == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { for (;;) { printf("Service %S options:\n", SERVICE_NAME); printf("\t[1] - Install\n"); printf("\t[2] - Uninstall\n"); printf("\t[0] - Exit\n"); printf("Your choose: "); char action = getchar(); while (getchar() != '\n') {} switch (action) { case '1': SvcInstall(); break; case '2': SvcUninstall(); break; case '0': return; default: printf(">> Unrecongnized action\n"); break; } } } else DebugOut(">> StartServiceCtrlDispatcherW failed! (LastError=0x%x)\n", LastError); } }
/* ** Try to start the http server as a windows service. If we are running in ** a interactive console session, this routine fails and returns a non zero ** integer value. When running as service, this routine does not return until ** the service is stopped. In this case, the return value is zero. */ int win32_http_service( int nPort, /* TCP port number */ const char *zNotFound, /* The --notfound option, or NULL */ int flags /* One or more HTTP_SERVER_ flags */ ){ /* Define the service table. */ SERVICE_TABLE_ENTRYW ServiceTable[] = {{L"", (LPSERVICE_MAIN_FUNCTIONW)win32_http_service_main}, {NULL, NULL}}; /* Initialize the HttpService structure. */ hsData.port = nPort; hsData.zNotFound = zNotFound; hsData.flags = flags; /* Try to start the control dispatcher thread for the service. */ if( !StartServiceCtrlDispatcherW(ServiceTable) ){ if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ return 1; }else{ fossil_fatal("error from StartServiceCtrlDispatcher()"); } } return 0; }
int wmain(int argc, wchar_t* argv[]) { //Windows XP with SP3 support #if (defined(PLATFORM_WIN32) && !defined(PLATFORM_WIN64)) GetFunctionPointer(FUNCTION_GETTICKCOUNT64); GetFunctionPointer(FUNCTION_INET_NTOP); #endif #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) int main(int argc, char *argv[]) { #endif //Get commands. if (argc > 0) { if (!ReadCommand(argc, argv)) return EXIT_SUCCESS; } else { return EXIT_FAILURE; } //Read configuration file and WinPcap or LibPcap initialization. if (!ReadParameter()) { WSACleanup(); return EXIT_FAILURE; } //Mark Local DNS address to PTR Records. std::thread NetworkInformationMonitorThread(NetworkInformationMonitor); NetworkInformationMonitorThread.detach(); //Read IPFilter and Hosts. if (Parameter.OperationMode == LISTEN_MODE_CUSTOM || Parameter.BlacklistCheck || Parameter.LocalRouting) { std::thread IPFilterThread(ReadIPFilter); IPFilterThread.detach(); } std::thread HostsThread(ReadHosts); HostsThread.detach(); //DNSCurve initialization #if defined(ENABLE_LIBSODIUM) if (Parameter.DNSCurve && DNSCurveParameter.IsEncryption) { randombytes_set_implementation(&randombytes_salsa20_implementation); randombytes_stir(); DNSCurveInit(); } #endif #if defined(PLATFORM_WIN) //Service initialization and start service. SERVICE_TABLE_ENTRYW ServiceTable[] = {{DEFAULT_LOCAL_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTIONW)ServiceMain}, {nullptr, nullptr}}; if (!StartServiceCtrlDispatcherW(ServiceTable)) { Parameter.Console = true; wprintf_s(L"System Error: Service start error, error code is %lu.\n", GetLastError()); wprintf_s(L"System Error: Program will continue to run in console mode.\n"); wprintf_s(L"Please ignore those error messages if you want to run in console mode.\n"); //Handle the system signal and start all monitors. SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); MonitorInit(); } #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) MonitorInit(); #endif WSACleanup(); return EXIT_SUCCESS; } //Read commands from main program #if defined(PLATFORM_WIN) bool __fastcall ReadCommand(int argc, wchar_t* argv[]) #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) bool ReadCommand(int argc, char *argv[]) #endif { //Path initialization #if defined(PLATFORM_WIN) if (!FileNameInit(argv[0])) return false; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) std::shared_ptr<char> FileName(new char[PATH_MAX + 1U]()); memset(FileName.get(), 0, PATH_MAX + 1U); if (getcwd(FileName.get(), PATH_MAX) == nullptr) { wprintf(L"Path initialization error.\n"); return false; } if (!FileNameInit(FileName.get())) return false; FileName.reset(); #endif #if defined(PLATFORM_WIN) //Winsock initialization std::shared_ptr<WSAData> WSAInitialization(new WSAData()); if (WSAStartup(MAKEWORD(WINSOCK_VERSION_HIGH, WINSOCK_VERSION_LOW), WSAInitialization.get()) != 0 || LOBYTE(WSAInitialization->wVersion) != WINSOCK_VERSION_LOW || HIBYTE(WSAInitialization->wVersion) != WINSOCK_VERSION_HIGH) { wprintf_s(L"Winsock initialization error, error code is %d.\n", WSAGetLastError()); PrintError(LOG_ERROR_NETWORK, L"Winsock initialization error", WSAGetLastError(), nullptr, 0); WSACleanup(); return false; } //Read commands. std::wstring Commands; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) std::string Commands; #endif for (size_t Index = 1U;(SSIZE_T)Index < argc;++Index) { Commands = argv[Index]; //Flush DNS Cache from user. if (Commands == COMMAND_FLUSH_DNS) { #if defined(PLATFORM_WIN) FlushDNSMailSlotSender(); #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) FlushDNSFIFOSender(); #endif WSACleanup(); return false; } //Windows Firewall Test in first start. #if defined(PLATFORM_WIN) else if (Commands == COMMAND_FIREWALL_TEST) { if (!FirewallTest(AF_INET6) && !FirewallTest(AF_INET)) { wprintf_s(L"Windows Firewall Test error.\n"); PrintError(LOG_ERROR_NETWORK, L"Windows Firewall Test error", WSAGetLastError(), nullptr, 0); } WSACleanup(); return false; } #endif //Set system daemon. #if defined(PLATFORM_LINUX) else if (Commands == COMMAND_DISABLE_DAEMON) { Parameter.Daemon = false; } #endif //Print current version. else if (Commands == COMMAND_LONG_PRINT_VERSION || Commands == COMMAND_SHORT_PRINT_VERSION) { wprintf_s(L"Pcap_DNSProxy "); wprintf_s(FULL_VERSION); wprintf_s(L"\n"); WSACleanup(); return false; } //Print help messages. else if (Commands == COMMAND_LONG_HELP || Commands == COMMAND_SHORT_HELP) { wprintf_s(L"Usage: Please see ReadMe... files in Documents folder.\n"); WSACleanup(); return false; } //Set working directory from commands. else if (Commands == COMMAND_LONG_SET_PATH || Commands == COMMAND_SHORT_SET_PATH) { //Commands check if ((SSIZE_T)Index + 1 >= argc) { wprintf_s(L"Commands error.\n"); PrintError(LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0); WSACleanup(); return false; } else { ++Index; Commands = argv[Index]; //Path check. if (Commands.length() > MAX_PATH) { wprintf_s(L"Commands error.\n"); PrintError(LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0); WSACleanup(); return false; } else { if (!FileNameInit(Commands.c_str())) return false; } } } } //Set system daemon. #if defined(PLATFORM_LINUX) if (Parameter.Daemon && daemon(0, 0) == RETURN_ERROR) { PrintError(LOG_ERROR_SYSTEM, L"Set system daemon error", 0, nullptr, 0); return false; } #endif return true; } //Get path of program from the main function parameter and Winsock initialization #if defined(PLATFORM_WIN) bool __fastcall FileNameInit(const wchar_t *OriginalPath) #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) bool FileNameInit(const char *OriginalPath) #endif { //Path process #if defined(PLATFORM_WIN) Parameter.Path_Global->clear(); Parameter.Path_Global->push_back(OriginalPath); Parameter.Path_Global->front().erase(Parameter.Path_Global->front().rfind(L"\\") + 1U); for (size_t Index = 0;Index < Parameter.Path_Global->front().length();++Index) { if ((Parameter.Path_Global->front()).at(Index) == L'\\') { Parameter.Path_Global->front().insert(Index, L"\\"); ++Index; } } #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) Parameter.sPath_Global->clear(); Parameter.sPath_Global->push_back(OriginalPath); Parameter.sPath_Global->front().append("/"); std::wstring StringTemp; MBSToWCSString(StringTemp, OriginalPath); StringTemp.append(L"/"); Parameter.Path_Global->clear(); Parameter.Path_Global->push_back(StringTemp); StringTemp.clear(); #endif //Get path of error/running status log file and mark start time. Parameter.Path_ErrorLog->clear(); *Parameter.Path_ErrorLog = Parameter.Path_Global->front(); Parameter.Path_ErrorLog->append(L"Error.log"); #if (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) Parameter.sPath_ErrorLog->clear(); *Parameter.sPath_ErrorLog = Parameter.sPath_Global->front(); Parameter.sPath_ErrorLog->append("Error.log"); #endif Parameter.PrintError = true; time(&StartTime); return true; }
//The Main function of program int main(int argc, char *argv[]) { #ifdef _DEBUG //Handle the system signal. SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); #endif if (argc > 0) { std::shared_ptr<wchar_t> wPath(new wchar_t[MAX_PATH]()); //Path initialization and Winsock initialization. MultiByteToWideChar(CP_ACP, NULL, argv[0], MBSTOWCS_NULLTERMINATE, wPath.get(), MAX_PATH); if (FileInit(wPath.get()) == EXIT_FAILURE) return EXIT_FAILURE; wPath.reset(); //Windows Firewall Test in first start. if (argc > 1 && strlen(argv[1U]) == strlen("--FirstStart") && memcmp(argv[1], ("--FirstStart"), strlen("--FirstStart")) == 0) { if (FirewallTest(AF_INET6) == EXIT_FAILURE && FirewallTest(AF_INET) == EXIT_FAILURE) { PrintError(WINSOCK_ERROR, L"Windows Firewall Test error", NULL, nullptr, NULL); WSACleanup(); return EXIT_FAILURE; } else { return EXIT_SUCCESS; } } } else { return EXIT_FAILURE; } //Read configuration file and WinPcap initialization. if (Parameter.ReadParameter() == EXIT_FAILURE) { WSACleanup(); return EXIT_FAILURE; } std::thread CaptureInitializationThread(CaptureInit); CaptureInitializationThread.detach(); //Get Localhost DNS PTR Records. std::thread IPv6LocalAddressThread(LocalAddressToPTR, AF_INET6); std::thread IPv4LocalAddressThread(LocalAddressToPTR, AF_INET); IPv6LocalAddressThread.detach(); IPv4LocalAddressThread.detach(); //DNSCurve initialization if (Parameter.DNSCurve && DNSCurveParameter.Encryption) { randombytes_set_implementation(&randombytes_salsa20_implementation); DNSCurveInit(); } //Read IPFilter, start DNS Cache monitor(Timer type) and read Hosts. if (Parameter.FileRefreshTime > 0) { if (Parameter.OperationMode == LISTEN_CUSTOMMODE) { std::thread IPFilterThread(&Configuration::ReadIPFilter, std::ref(Parameter)); IPFilterThread.detach(); } if (Parameter.CacheType != 0) { std::thread DNSCacheTimerThread(DNSCacheTimerMonitor, Parameter.CacheType); DNSCacheTimerThread.detach(); } std::thread HostsThread(&Configuration::ReadHosts, std::ref(Parameter)); HostsThread.detach(); } //Service initialization and start service. SERVICE_TABLE_ENTRYW ServiceTable[] = {{LOCAL_SERVICENAME, (LPSERVICE_MAIN_FUNCTIONW)ServiceMain}, {nullptr, NULL}}; if (!StartServiceCtrlDispatcherW(ServiceTable)) { PrintError(SYSTEM_ERROR, L"Service start error", GetLastError(), nullptr, NULL); WSACleanup(); return EXIT_FAILURE; } WSACleanup(); return EXIT_SUCCESS; }
int wmain(int argc, WCHAR **argv) { // If command-line parameter is "install", install the service // or upgrade if already installed // If command line parameter is "forceinstall", install the service // even if it is older than what is already installed. // If command-line parameter is "upgrade", upgrade the service // but do not install it if it is not already installed. // If command line parameter is "uninstall", uninstall the service. // Otherwise, the service is probably being started by the SCM. bool forceInstall = !lstrcmpi(argv[1], L"forceinstall"); if (!lstrcmpi(argv[1], L"install") || forceInstall) { WCHAR updatePath[MAX_PATH + 1]; if (GetLogDirectoryPath(updatePath)) { LogInit(updatePath, L"maintenanceservice-install.log"); } LOG(("Installing service")); SvcInstallAction action = InstallSvc; if (forceInstall) { action = ForceInstallSvc; LOG((" with force specified")); } LOG(("...\n")); if (!SvcInstall(action)) { LOG(("Could not install service (%d)\n", GetLastError())); LogFinish(); return 1; } LOG(("The service was installed successfully\n")); LogFinish(); return 0; } if (!lstrcmpi(argv[1], L"upgrade")) { WCHAR updatePath[MAX_PATH + 1]; if (GetLogDirectoryPath(updatePath)) { LogInit(updatePath, L"maintenanceservice-install.log"); } LOG(("Upgrading service if installed...\n")); if (!SvcInstall(UpgradeSvc)) { LOG(("Could not upgrade service (%d)\n", GetLastError())); LogFinish(); return 1; } LOG(("The service was upgraded successfully\n")); LogFinish(); return 0; } if (!lstrcmpi(argv[1], L"uninstall")) { WCHAR updatePath[MAX_PATH + 1]; if (GetLogDirectoryPath(updatePath)) { LogInit(updatePath, L"maintenanceservice-uninstall.log"); } LOG(("Uninstalling service...\n")); if (!SvcUninstall()) { LOG(("Could not uninstall service (%d)\n", GetLastError())); LogFinish(); return 1; } LOG(("The service was uninstalled successfully\n")); LogFinish(); return 0; } SERVICE_TABLE_ENTRYW DispatchTable[] = { { SVC_NAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain }, { NULL, NULL } }; // This call returns when the service has stopped. // The process should simply terminate when the call returns. if (!StartServiceCtrlDispatcherW(DispatchTable)) { LOG(("StartServiceCtrlDispatcher failed (%d)\n", GetLastError())); } return 0; }
int wmain( int argc, wchar_t* argv[]) { #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) int main( int argc, char *argv[]) { #endif //Get commands. if (argc > 0) { if (!ReadCommand(argc, argv)) return EXIT_SUCCESS; } else { return EXIT_FAILURE; } //Read configuration file. if (!ReadParameter(true)) return EXIT_FAILURE; //DNSCurve initialization #if defined(ENABLE_LIBSODIUM) if (Parameter.DNSCurve) { DNSCurveParameterModificating.SetToMonitorItem(); //Encryption mode initialization if (DNSCurveParameter.IsEncryption) DNSCurveInit(); } #endif //Mark Local DNS address to PTR Records, read Parameter(Monitor mode), IPFilter and Hosts. ParameterModificating.SetToMonitorItem(); std::thread NetworkInformationMonitorThread(std::bind(NetworkInformationMonitor)); NetworkInformationMonitorThread.detach(); std::thread ReadParameterThread(std::bind(ReadParameter, false)); ReadParameterThread.detach(); std::thread ReadHostsThread(std::bind(ReadHosts)); ReadHostsThread.detach(); if (Parameter.OperationMode == LISTEN_MODE_CUSTOM || Parameter.DataCheck_Blacklist || Parameter.LocalRouting) { std::thread ReadIPFilterThread(std::bind(ReadIPFilter)); ReadIPFilterThread.detach(); } #if defined(PLATFORM_WIN) //Service initialization and start service. SERVICE_TABLE_ENTRYW ServiceTable[]{{SYSTEM_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTIONW)ServiceMain}, {nullptr, nullptr}}; if (!StartServiceCtrlDispatcherW(ServiceTable)) { GlobalRunningStatus.Console = true; auto ErrorCode = GetLastError(); //Print to screen. std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf_s(stderr, L"System Error: Service start error, error code is %lu.\n", ErrorCode); fwprintf_s(stderr, L"System Error: Program will continue to run in console mode.\n"); fwprintf_s(stderr, L"Please ignore these error messages if you want to run in console mode.\n\n"); ScreenMutex.unlock(); //Handle the system signal and start all monitors. SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); MonitorInit(); } #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) MonitorInit(); #endif return EXIT_SUCCESS; } //Read commands from main program #if defined(PLATFORM_WIN) bool __fastcall ReadCommand( int argc, wchar_t *argv[]) #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) bool ReadCommand( int argc, char *argv[]) #endif { //Path initialization #if defined(PLATFORM_WIN) if (!FileNameInit(argv[0])) return false; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) char FileName[PATH_MAX + 1U] = {0}; if (getcwd(FileName, PATH_MAX) == nullptr) { std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf(stderr, L"Path initialization error.\n"); return false; } if (!FileNameInit(FileName)) return false; #endif //Screen output buffer setting if (setvbuf(stderr, NULL, _IONBF, 0) != 0) { auto ErrorCode = errno; std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf_s(stderr, L"Screen output buffer setting error, error code is %d.\n", ErrorCode); ScreenLock.unlock(); PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"Screen output buffer setting error", ErrorCode, nullptr, 0); return false; } //Winsock initialization #if defined(PLATFORM_WIN) WSAData WSAInitialization = {0}; if (WSAStartup(MAKEWORD(WINSOCK_VERSION_HIGH, WINSOCK_VERSION_LOW), &WSAInitialization) != 0 || LOBYTE(WSAInitialization.wVersion) != WINSOCK_VERSION_LOW || HIBYTE(WSAInitialization.wVersion) != WINSOCK_VERSION_HIGH) { auto ErrorCode = WSAGetLastError(); std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf_s(stderr, L"Winsock initialization error, error code is %d.\n", ErrorCode); ScreenLock.unlock(); PrintError(LOG_LEVEL_1, LOG_ERROR_NETWORK, L"Winsock initialization error", ErrorCode, nullptr, 0); return false; } else { GlobalRunningStatus.Initialization_WinSock = true; } //Read commands. std::wstring Commands; #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) std::string Commands; #endif for (size_t Index = 1U;(SSIZE_T)Index < argc;++Index) { Commands = argv[Index]; //Flush DNS Cache from user. if (Commands == COMMAND_FLUSH_DNS) { #if defined(PLATFORM_WIN) FlushDNSMailSlotSender(); #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) FlushDNSFIFOSender(); #endif return false; } //Windows Firewall Test in first start. #if defined(PLATFORM_WIN) else if (Commands == COMMAND_FIREWALL_TEST) { if (!FirewallTest(AF_INET6) && !FirewallTest(AF_INET)) { auto ErrorCode = WSAGetLastError(); std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf_s(stderr, L"Windows Firewall Test error, error code is %d.\n", ErrorCode); ScreenMutex.unlock(); PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"Windows Firewall Test error", ErrorCode, nullptr, 0); } return false; } #endif //Set system daemon. #if defined(PLATFORM_LINUX) else if (Commands == COMMAND_DISABLE_DAEMON) { GlobalRunningStatus.Daemon = false; } #endif //Print current version. else if (Commands == COMMAND_LONG_PRINT_VERSION || Commands == COMMAND_SHORT_PRINT_VERSION) { std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf_s(stderr, L"Pcap_DNSProxy "); fwprintf_s(stderr, FULL_VERSION); fwprintf_s(stderr, L"\n"); return false; } //Print library version. else if (Commands == COMMAND_LIB_VERSION) { std::unique_lock<std::mutex> ScreenMutex(ScreenLock); #if (defined(ENABLE_LIBSODIUM) || defined(ENABLE_PCAP)) std::wstring LibVersion; //LibSodium version #if defined(ENABLE_LIBSODIUM) if (MBSToWCSString(SODIUM_VERSION_STRING, strlen(SODIUM_VERSION_STRING), LibVersion)) fwprintf_s(stderr, L"LibSodium version %ls\n", LibVersion.c_str()); #endif //WinPcap or LibPcap version #if defined(ENABLE_PCAP) if (MBSToWCSString(pcap_lib_version(), strlen(pcap_lib_version()), LibVersion)) fwprintf_s(stderr, L"%ls\n", LibVersion.c_str()); #endif #else fwprintf(stderr, L"No any available libraries.\n"); #endif return false; } //Print help messages. else if (Commands == COMMAND_LONG_HELP || Commands == COMMAND_SHORT_HELP) { std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf_s(stderr, L"Pcap_DNSProxy "); fwprintf_s(stderr, FULL_VERSION); #if defined(PLATFORM_WIN) fwprintf_s(stderr, L"(Windows)\n"); #elif defined(PLATFORM_OPENWRT) fwprintf(stderr, L"(OpenWrt)\n"); #elif defined(PLATFORM_LINUX) fwprintf(stderr, L"(Linux)\n"); #elif defined(PLATFORM_MACX) fwprintf(stderr, L"(Mac)\n"); #endif fwprintf_s(stderr, COPYRIGHT_MESSAGE); fwprintf_s(stderr, L"\nUsage: Please visit ReadMe... files in Documents folder.\n"); fwprintf_s(stderr, L" -v/--version: Print current version on screen.\n"); fwprintf_s(stderr, L" --lib-version: Print current version of libraries on screen.\n"); fwprintf_s(stderr, L" -h/--help: Print help messages on screen.\n"); fwprintf_s(stderr, L" --flush-dns: Flush all DNS cache in program and system immediately.\n"); #if defined(PLATFORM_WIN) fwprintf_s(stderr, L" --first-setup: Test local firewall.\n"); #endif fwprintf_s(stderr, L" -c/--config-file Path: Set path of configuration file.\n"); #if defined(PLATFORM_LINUX) fwprintf(stderr, L" --disable-daemon: Disable daemon mode.\n"); #endif return false; } //Set working directory from commands. else if (Commands == COMMAND_LONG_SET_PATH || Commands == COMMAND_SHORT_SET_PATH) { //Commands check if ((SSIZE_T)Index + 1 >= argc) { std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf(stderr, L"Commands error.\n"); ScreenMutex.unlock(); PrintError(LOG_LEVEL_1, LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0); return false; } else { ++Index; Commands = argv[Index]; //Path check. if (Commands.length() > MAX_PATH) { std::unique_lock<std::mutex> ScreenMutex(ScreenLock); fwprintf_s(stderr, L"Commands error.\n"); ScreenLock.unlock(); PrintError(LOG_LEVEL_1, LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0); return false; } else { if (!FileNameInit(Commands.c_str())) return false; } } } } //Set system daemon. #if defined(PLATFORM_LINUX) if (GlobalRunningStatus.Daemon && daemon(0, 0) == RETURN_ERROR) { PrintError(LOG_LEVEL_2, LOG_ERROR_SYSTEM, L"Set system daemon error", 0, nullptr, 0); return false; } #endif return true; } //Get path of program from the main function parameter and Winsock initialization #if defined(PLATFORM_WIN) bool __fastcall FileNameInit( const wchar_t *OriginalPath) #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) bool FileNameInit( const char *OriginalPath) #endif { //Path process #if defined(PLATFORM_WIN) GlobalRunningStatus.Path_Global->clear(); GlobalRunningStatus.Path_Global->push_back(OriginalPath); GlobalRunningStatus.Path_Global->front().erase(GlobalRunningStatus.Path_Global->front().rfind(L"\\") + 1U); for (size_t Index = 0;Index < GlobalRunningStatus.Path_Global->front().length();++Index) { if ((GlobalRunningStatus.Path_Global->front()).at(Index) == L'\\') { GlobalRunningStatus.Path_Global->front().insert(Index, L"\\"); ++Index; } } #elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) GlobalRunningStatus.sPath_Global->clear(); GlobalRunningStatus.sPath_Global->push_back(OriginalPath); GlobalRunningStatus.sPath_Global->front().append("/"); std::wstring StringTemp; if (!MBSToWCSString(OriginalPath, PATH_MAX + 1U, StringTemp)) return false; StringTemp.append(L"/"); GlobalRunningStatus.Path_Global->clear(); GlobalRunningStatus.Path_Global->push_back(StringTemp); StringTemp.clear(); #endif //Get path of error/running status log file and mark start time. GlobalRunningStatus.Path_ErrorLog->clear(); *GlobalRunningStatus.Path_ErrorLog = GlobalRunningStatus.Path_Global->front(); GlobalRunningStatus.Path_ErrorLog->append(L"Error.log"); #if (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX)) GlobalRunningStatus.sPath_ErrorLog->clear(); *GlobalRunningStatus.sPath_ErrorLog = GlobalRunningStatus.sPath_Global->front(); GlobalRunningStatus.sPath_ErrorLog->append("Error.log"); #endif Parameter.PrintLogLevel = DEFAULT_LOG_LEVEL; GlobalRunningStatus.StartupTime = time(nullptr); return true; }