18dbcf02cSchristos /*
28dbcf02cSchristos  * WPA Supplicant / main() function for Win32 service
38dbcf02cSchristos  * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
562a52023Schristos  * This software may be distributed under the terms of the BSD license.
662a52023Schristos  * See README for more details.
78dbcf02cSchristos  *
88dbcf02cSchristos  * The root of wpa_supplicant configuration in registry is
98dbcf02cSchristos  * HKEY_LOCAL_MACHINE\\SOFTWARE\\%wpa_supplicant. This level includes global
108dbcf02cSchristos  * parameters and a 'interfaces' subkey with all the interface configuration
118dbcf02cSchristos  * (adapter to confname mapping). Each such mapping is a subkey that has
128dbcf02cSchristos  * 'adapter' and 'config' values.
138dbcf02cSchristos  *
148dbcf02cSchristos  * This program can be run either as a normal command line application, e.g.,
158dbcf02cSchristos  * for debugging, with 'wpasvc.exe app' or as a Windows service. Service need
168dbcf02cSchristos  * to be registered with 'wpasvc.exe reg <full path to wpasvc.exe>'. After
178dbcf02cSchristos  * this, it can be started like any other Windows service (e.g., 'net start
188dbcf02cSchristos  * wpasvc') or it can be configured to start automatically through the Services
198dbcf02cSchristos  * tool in administrative tasks. The service can be unregistered with
208dbcf02cSchristos  * 'wpasvc.exe unreg'.
218dbcf02cSchristos  */
228dbcf02cSchristos 
238dbcf02cSchristos #include "includes.h"
248dbcf02cSchristos #include <windows.h>
258dbcf02cSchristos 
268dbcf02cSchristos #include "common.h"
278dbcf02cSchristos #include "wpa_supplicant_i.h"
288dbcf02cSchristos #include "eloop.h"
298dbcf02cSchristos 
308dbcf02cSchristos #ifndef WPASVC_NAME
318dbcf02cSchristos #define WPASVC_NAME TEXT("wpasvc")
328dbcf02cSchristos #endif
338dbcf02cSchristos #ifndef WPASVC_DISPLAY_NAME
348dbcf02cSchristos #define WPASVC_DISPLAY_NAME TEXT("wpa_supplicant service")
358dbcf02cSchristos #endif
368dbcf02cSchristos #ifndef WPASVC_DESCRIPTION
378dbcf02cSchristos #define WPASVC_DESCRIPTION \
388dbcf02cSchristos TEXT("Provides IEEE 802.1X and WPA/WPA2 supplicant functionality")
398dbcf02cSchristos #endif
408dbcf02cSchristos 
418dbcf02cSchristos static HANDLE kill_svc;
428dbcf02cSchristos 
438dbcf02cSchristos static SERVICE_STATUS_HANDLE svc_status_handle;
448dbcf02cSchristos static SERVICE_STATUS svc_status;
458dbcf02cSchristos 
468dbcf02cSchristos 
478dbcf02cSchristos #ifndef WPA_KEY_ROOT
488dbcf02cSchristos #define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
498dbcf02cSchristos #endif
508dbcf02cSchristos #ifndef WPA_KEY_PREFIX
518dbcf02cSchristos #define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
528dbcf02cSchristos #endif
538dbcf02cSchristos 
548dbcf02cSchristos #ifdef UNICODE
558dbcf02cSchristos #define TSTR "%S"
568dbcf02cSchristos #else /* UNICODE */
578dbcf02cSchristos #define TSTR "%s"
588dbcf02cSchristos #endif /* UNICODE */
598dbcf02cSchristos 
608dbcf02cSchristos 
read_interface(struct wpa_global * global,HKEY _hk,const TCHAR * name)618dbcf02cSchristos static int read_interface(struct wpa_global *global, HKEY _hk,
628dbcf02cSchristos 			  const TCHAR *name)
638dbcf02cSchristos {
648dbcf02cSchristos 	HKEY hk;
658dbcf02cSchristos #define TBUFLEN 255
668dbcf02cSchristos 	TCHAR adapter[TBUFLEN], config[TBUFLEN], ctrl_interface[TBUFLEN];
678dbcf02cSchristos 	DWORD buflen, val;
688dbcf02cSchristos 	LONG ret;
698dbcf02cSchristos 	struct wpa_interface iface;
708dbcf02cSchristos 	int skip_on_error = 0;
718dbcf02cSchristos 
728dbcf02cSchristos 	ret = RegOpenKeyEx(_hk, name, 0, KEY_QUERY_VALUE, &hk);
738dbcf02cSchristos 	if (ret != ERROR_SUCCESS) {
748dbcf02cSchristos 		printf("Could not open wpa_supplicant interface key\n");
758dbcf02cSchristos 		return -1;
768dbcf02cSchristos 	}
778dbcf02cSchristos 
788dbcf02cSchristos 	os_memset(&iface, 0, sizeof(iface));
798dbcf02cSchristos 	iface.driver = "ndis";
808dbcf02cSchristos 
818dbcf02cSchristos 	buflen = sizeof(ctrl_interface);
828dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("ctrl_interface"), NULL, NULL,
838dbcf02cSchristos 			      (LPBYTE) ctrl_interface, &buflen);
848dbcf02cSchristos 	if (ret == ERROR_SUCCESS) {
858dbcf02cSchristos 		ctrl_interface[TBUFLEN - 1] = TEXT('\0');
868dbcf02cSchristos 		wpa_unicode2ascii_inplace(ctrl_interface);
878dbcf02cSchristos 		printf("ctrl_interface[len=%d] '%s'\n",
888dbcf02cSchristos 		       (int) buflen, (char *) ctrl_interface);
898dbcf02cSchristos 		iface.ctrl_interface = (char *) ctrl_interface;
908dbcf02cSchristos 	}
918dbcf02cSchristos 
928dbcf02cSchristos 	buflen = sizeof(adapter);
938dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("adapter"), NULL, NULL,
948dbcf02cSchristos 			      (LPBYTE) adapter, &buflen);
958dbcf02cSchristos 	if (ret == ERROR_SUCCESS) {
968dbcf02cSchristos 		adapter[TBUFLEN - 1] = TEXT('\0');
978dbcf02cSchristos 		wpa_unicode2ascii_inplace(adapter);
988dbcf02cSchristos 		printf("adapter[len=%d] '%s'\n",
998dbcf02cSchristos 		       (int) buflen, (char *) adapter);
1008dbcf02cSchristos 		iface.ifname = (char *) adapter;
1018dbcf02cSchristos 	}
1028dbcf02cSchristos 
1038dbcf02cSchristos 	buflen = sizeof(config);
1048dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("config"), NULL, NULL,
1058dbcf02cSchristos 			      (LPBYTE) config, &buflen);
1068dbcf02cSchristos 	if (ret == ERROR_SUCCESS) {
1078dbcf02cSchristos 		config[sizeof(config) - 1] = '\0';
1088dbcf02cSchristos 		wpa_unicode2ascii_inplace(config);
1098dbcf02cSchristos 		printf("config[len=%d] '%s'\n",
1108dbcf02cSchristos 		       (int) buflen, (char *) config);
1118dbcf02cSchristos 		iface.confname = (char *) config;
1128dbcf02cSchristos 	}
1138dbcf02cSchristos 
1148dbcf02cSchristos 	buflen = sizeof(val);
1158dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("skip_on_error"), NULL, NULL,
1168dbcf02cSchristos 			      (LPBYTE) &val, &buflen);
1178dbcf02cSchristos 	if (ret == ERROR_SUCCESS && buflen == sizeof(val))
1188dbcf02cSchristos 		skip_on_error = val;
1198dbcf02cSchristos 
1208dbcf02cSchristos 	RegCloseKey(hk);
1218dbcf02cSchristos 
122*9a53cbbeSchristos 	if (wpa_supplicant_add_iface(global, &iface, NULL) == NULL) {
1238dbcf02cSchristos 		if (skip_on_error)
1248dbcf02cSchristos 			wpa_printf(MSG_DEBUG, "Skipped interface '%s' due to "
1258dbcf02cSchristos 				   "initialization failure", iface.ifname);
1268dbcf02cSchristos 		else
1278dbcf02cSchristos 			return -1;
1288dbcf02cSchristos 	}
1298dbcf02cSchristos 
1308dbcf02cSchristos 	return 0;
1318dbcf02cSchristos }
1328dbcf02cSchristos 
1338dbcf02cSchristos 
wpa_supplicant_thread(void)1348dbcf02cSchristos static int wpa_supplicant_thread(void)
1358dbcf02cSchristos {
1368dbcf02cSchristos 	int exitcode;
1378dbcf02cSchristos 	struct wpa_params params;
1388dbcf02cSchristos 	struct wpa_global *global;
1398dbcf02cSchristos 	HKEY hk, ihk;
1408dbcf02cSchristos 	DWORD val, buflen, i;
1418dbcf02cSchristos 	LONG ret;
1428dbcf02cSchristos 
1438dbcf02cSchristos 	if (os_program_init())
1448dbcf02cSchristos 		return -1;
1458dbcf02cSchristos 
1468dbcf02cSchristos 	os_memset(&params, 0, sizeof(params));
1478dbcf02cSchristos 	params.wpa_debug_level = MSG_INFO;
1488dbcf02cSchristos 
1498dbcf02cSchristos 	ret = RegOpenKeyEx(WPA_KEY_ROOT, WPA_KEY_PREFIX,
1508dbcf02cSchristos 			   0, KEY_QUERY_VALUE, &hk);
1518dbcf02cSchristos 	if (ret != ERROR_SUCCESS) {
1528dbcf02cSchristos 		printf("Could not open wpa_supplicant registry key\n");
1538dbcf02cSchristos 		return -1;
1548dbcf02cSchristos 	}
1558dbcf02cSchristos 
1568dbcf02cSchristos 	buflen = sizeof(val);
1578dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("debug_level"), NULL, NULL,
1588dbcf02cSchristos 			      (LPBYTE) &val, &buflen);
1598dbcf02cSchristos 	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
1608dbcf02cSchristos 		params.wpa_debug_level = val;
1618dbcf02cSchristos 	}
1628dbcf02cSchristos 
1638dbcf02cSchristos 	buflen = sizeof(val);
1648dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("debug_show_keys"), NULL, NULL,
1658dbcf02cSchristos 			      (LPBYTE) &val, &buflen);
1668dbcf02cSchristos 	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
1678dbcf02cSchristos 		params.wpa_debug_show_keys = val;
1688dbcf02cSchristos 	}
1698dbcf02cSchristos 
1708dbcf02cSchristos 	buflen = sizeof(val);
1718dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("debug_timestamp"), NULL, NULL,
1728dbcf02cSchristos 			      (LPBYTE) &val, &buflen);
1738dbcf02cSchristos 	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
1748dbcf02cSchristos 		params.wpa_debug_timestamp = val;
1758dbcf02cSchristos 	}
1768dbcf02cSchristos 
1778dbcf02cSchristos 	buflen = sizeof(val);
1788dbcf02cSchristos 	ret = RegQueryValueEx(hk, TEXT("debug_use_file"), NULL, NULL,
1798dbcf02cSchristos 			      (LPBYTE) &val, &buflen);
1808dbcf02cSchristos 	if (ret == ERROR_SUCCESS && buflen == sizeof(val) && val) {
1818dbcf02cSchristos 		params.wpa_debug_file_path = "\\Temp\\wpa_supplicant-log.txt";
1828dbcf02cSchristos 	}
1838dbcf02cSchristos 
1848dbcf02cSchristos 	exitcode = 0;
1858dbcf02cSchristos 	global = wpa_supplicant_init(&params);
1868dbcf02cSchristos 	if (global == NULL) {
1878dbcf02cSchristos 		printf("Failed to initialize wpa_supplicant\n");
1888dbcf02cSchristos 		exitcode = -1;
1898dbcf02cSchristos 	}
1908dbcf02cSchristos 
1918dbcf02cSchristos 	ret = RegOpenKeyEx(hk, TEXT("interfaces"), 0, KEY_ENUMERATE_SUB_KEYS,
1928dbcf02cSchristos 			   &ihk);
1938dbcf02cSchristos 	RegCloseKey(hk);
1948dbcf02cSchristos 	if (ret != ERROR_SUCCESS) {
1958dbcf02cSchristos 		printf("Could not open wpa_supplicant interfaces registry "
1968dbcf02cSchristos 		       "key\n");
1978dbcf02cSchristos 		return -1;
1988dbcf02cSchristos 	}
1998dbcf02cSchristos 
2008dbcf02cSchristos 	for (i = 0; ; i++) {
2018dbcf02cSchristos 		TCHAR name[255];
2028dbcf02cSchristos 		DWORD namelen;
2038dbcf02cSchristos 
2048dbcf02cSchristos 		namelen = 255;
2058dbcf02cSchristos 		ret = RegEnumKeyEx(ihk, i, name, &namelen, NULL, NULL, NULL,
2068dbcf02cSchristos 				   NULL);
2078dbcf02cSchristos 
2088dbcf02cSchristos 		if (ret == ERROR_NO_MORE_ITEMS)
2098dbcf02cSchristos 			break;
2108dbcf02cSchristos 
2118dbcf02cSchristos 		if (ret != ERROR_SUCCESS) {
2128dbcf02cSchristos 			printf("RegEnumKeyEx failed: 0x%x\n",
2138dbcf02cSchristos 			       (unsigned int) ret);
2148dbcf02cSchristos 			break;
2158dbcf02cSchristos 		}
2168dbcf02cSchristos 
2178dbcf02cSchristos 		if (namelen >= 255)
2188dbcf02cSchristos 			namelen = 255 - 1;
2198dbcf02cSchristos 		name[namelen] = '\0';
2208dbcf02cSchristos 
2218dbcf02cSchristos 		wpa_printf(MSG_DEBUG, "interface %d: %s\n", (int) i, name);
2228dbcf02cSchristos 		if (read_interface(global, ihk, name) < 0)
2238dbcf02cSchristos 			exitcode = -1;
2248dbcf02cSchristos 	}
2258dbcf02cSchristos 
2268dbcf02cSchristos 	RegCloseKey(ihk);
2278dbcf02cSchristos 
2288dbcf02cSchristos 	if (exitcode == 0)
2298dbcf02cSchristos 		exitcode = wpa_supplicant_run(global);
2308dbcf02cSchristos 
2318dbcf02cSchristos 	wpa_supplicant_deinit(global);
2328dbcf02cSchristos 
2338dbcf02cSchristos 	os_program_deinit();
2348dbcf02cSchristos 
2358dbcf02cSchristos 	return exitcode;
2368dbcf02cSchristos }
2378dbcf02cSchristos 
2388dbcf02cSchristos 
svc_thread(LPDWORD param)2398dbcf02cSchristos static DWORD svc_thread(LPDWORD param)
2408dbcf02cSchristos {
2418dbcf02cSchristos 	int ret = wpa_supplicant_thread();
2428dbcf02cSchristos 
2438dbcf02cSchristos 	svc_status.dwCurrentState = SERVICE_STOPPED;
2448dbcf02cSchristos 	svc_status.dwWaitHint = 0;
2458dbcf02cSchristos 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
2468dbcf02cSchristos 		printf("SetServiceStatus() failed: %d\n",
2478dbcf02cSchristos 		       (int) GetLastError());
2488dbcf02cSchristos 	}
2498dbcf02cSchristos 
2508dbcf02cSchristos 	return ret;
2518dbcf02cSchristos }
2528dbcf02cSchristos 
2538dbcf02cSchristos 
register_service(const TCHAR * exe)2548dbcf02cSchristos static int register_service(const TCHAR *exe)
2558dbcf02cSchristos {
2568dbcf02cSchristos 	SC_HANDLE svc, scm;
2578dbcf02cSchristos 	SERVICE_DESCRIPTION sd;
2588dbcf02cSchristos 
2598dbcf02cSchristos 	printf("Registering service: " TSTR "\n", WPASVC_NAME);
2608dbcf02cSchristos 
2618dbcf02cSchristos 	scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
2628dbcf02cSchristos 	if (!scm) {
2638dbcf02cSchristos 		printf("OpenSCManager failed: %d\n", (int) GetLastError());
2648dbcf02cSchristos 		return -1;
2658dbcf02cSchristos 	}
2668dbcf02cSchristos 
2678dbcf02cSchristos 	svc = CreateService(scm, WPASVC_NAME, WPASVC_DISPLAY_NAME,
2688dbcf02cSchristos 			    SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
2698dbcf02cSchristos 			    SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
2708dbcf02cSchristos 			    exe, NULL, NULL, NULL, NULL, NULL);
2718dbcf02cSchristos 
2728dbcf02cSchristos 	if (!svc) {
2738dbcf02cSchristos 		printf("CreateService failed: %d\n\n", (int) GetLastError());
2748dbcf02cSchristos 		CloseServiceHandle(scm);
2758dbcf02cSchristos 		return -1;
2768dbcf02cSchristos 	}
2778dbcf02cSchristos 
2788dbcf02cSchristos 	os_memset(&sd, 0, sizeof(sd));
2798dbcf02cSchristos 	sd.lpDescription = WPASVC_DESCRIPTION;
2808dbcf02cSchristos 	if (!ChangeServiceConfig2(svc, SERVICE_CONFIG_DESCRIPTION, &sd)) {
2818dbcf02cSchristos 		printf("ChangeServiceConfig2 failed: %d\n",
2828dbcf02cSchristos 		       (int) GetLastError());
2838dbcf02cSchristos 		/* This is not a fatal error, so continue anyway. */
2848dbcf02cSchristos 	}
2858dbcf02cSchristos 
2868dbcf02cSchristos 	CloseServiceHandle(svc);
2878dbcf02cSchristos 	CloseServiceHandle(scm);
2888dbcf02cSchristos 
2898dbcf02cSchristos 	printf("Service registered successfully.\n");
2908dbcf02cSchristos 
2918dbcf02cSchristos 	return 0;
2928dbcf02cSchristos }
2938dbcf02cSchristos 
2948dbcf02cSchristos 
unregister_service(void)2958dbcf02cSchristos static int unregister_service(void)
2968dbcf02cSchristos {
2978dbcf02cSchristos 	SC_HANDLE svc, scm;
2988dbcf02cSchristos 	SERVICE_STATUS status;
2998dbcf02cSchristos 
3008dbcf02cSchristos 	printf("Unregistering service: " TSTR "\n", WPASVC_NAME);
3018dbcf02cSchristos 
3028dbcf02cSchristos 	scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
3038dbcf02cSchristos 	if (!scm) {
3048dbcf02cSchristos 		printf("OpenSCManager failed: %d\n", (int) GetLastError());
3058dbcf02cSchristos 		return -1;
3068dbcf02cSchristos 	}
3078dbcf02cSchristos 
3088dbcf02cSchristos 	svc = OpenService(scm, WPASVC_NAME, SERVICE_ALL_ACCESS | DELETE);
3098dbcf02cSchristos 	if (!svc) {
3108dbcf02cSchristos 		printf("OpenService failed: %d\n\n", (int) GetLastError());
3118dbcf02cSchristos 		CloseServiceHandle(scm);
3128dbcf02cSchristos 		return -1;
3138dbcf02cSchristos 	}
3148dbcf02cSchristos 
3158dbcf02cSchristos 	if (QueryServiceStatus(svc, &status)) {
3168dbcf02cSchristos 		if (status.dwCurrentState != SERVICE_STOPPED) {
3178dbcf02cSchristos 			printf("Service currently active - stopping "
3188dbcf02cSchristos 			       "service...\n");
3198dbcf02cSchristos 			if (!ControlService(svc, SERVICE_CONTROL_STOP,
3208dbcf02cSchristos 					    &status)) {
3218dbcf02cSchristos 				printf("ControlService failed: %d\n",
3228dbcf02cSchristos 				       (int) GetLastError());
3238dbcf02cSchristos 			}
3248dbcf02cSchristos 			Sleep(500);
3258dbcf02cSchristos 		}
3268dbcf02cSchristos 	}
3278dbcf02cSchristos 
3288dbcf02cSchristos 	if (DeleteService(svc)) {
3298dbcf02cSchristos 		printf("Service unregistered successfully.\n");
3308dbcf02cSchristos 	} else {
3318dbcf02cSchristos 		printf("DeleteService failed: %d\n", (int) GetLastError());
3328dbcf02cSchristos 	}
3338dbcf02cSchristos 
3348dbcf02cSchristos 	CloseServiceHandle(svc);
3358dbcf02cSchristos 	CloseServiceHandle(scm);
3368dbcf02cSchristos 
3378dbcf02cSchristos 	return 0;
3388dbcf02cSchristos }
3398dbcf02cSchristos 
3408dbcf02cSchristos 
service_ctrl_handler(DWORD control_code)3418dbcf02cSchristos static void WINAPI service_ctrl_handler(DWORD control_code)
3428dbcf02cSchristos {
3438dbcf02cSchristos 	switch (control_code) {
3448dbcf02cSchristos 	case SERVICE_CONTROL_INTERROGATE:
3458dbcf02cSchristos 		break;
3468dbcf02cSchristos 	case SERVICE_CONTROL_SHUTDOWN:
3478dbcf02cSchristos 	case SERVICE_CONTROL_STOP:
3488dbcf02cSchristos 		svc_status.dwCurrentState = SERVICE_STOP_PENDING;
3498dbcf02cSchristos 		svc_status.dwWaitHint = 2000;
3508dbcf02cSchristos 		eloop_terminate();
3518dbcf02cSchristos 		SetEvent(kill_svc);
3528dbcf02cSchristos 		break;
3538dbcf02cSchristos 	}
3548dbcf02cSchristos 
3558dbcf02cSchristos 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
3568dbcf02cSchristos 		printf("SetServiceStatus() failed: %d\n",
3578dbcf02cSchristos 		       (int) GetLastError());
3588dbcf02cSchristos 	}
3598dbcf02cSchristos }
3608dbcf02cSchristos 
3618dbcf02cSchristos 
service_start(DWORD argc,LPTSTR * argv)3628dbcf02cSchristos static void WINAPI service_start(DWORD argc, LPTSTR *argv)
3638dbcf02cSchristos {
3648dbcf02cSchristos 	DWORD id;
3658dbcf02cSchristos 
3668dbcf02cSchristos 	svc_status_handle = RegisterServiceCtrlHandler(WPASVC_NAME,
3678dbcf02cSchristos 						       service_ctrl_handler);
3688dbcf02cSchristos 	if (svc_status_handle == (SERVICE_STATUS_HANDLE) 0) {
3698dbcf02cSchristos 		printf("RegisterServiceCtrlHandler failed: %d\n",
3708dbcf02cSchristos 		       (int) GetLastError());
3718dbcf02cSchristos 		return;
3728dbcf02cSchristos 	}
3738dbcf02cSchristos 
3748dbcf02cSchristos 	os_memset(&svc_status, 0, sizeof(svc_status));
3758dbcf02cSchristos 	svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
3768dbcf02cSchristos 	svc_status.dwCurrentState = SERVICE_START_PENDING;
3778dbcf02cSchristos 	svc_status.dwWaitHint = 1000;
3788dbcf02cSchristos 
3798dbcf02cSchristos 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
3808dbcf02cSchristos 		printf("SetServiceStatus() failed: %d\n",
3818dbcf02cSchristos 		       (int) GetLastError());
3828dbcf02cSchristos 		return;
3838dbcf02cSchristos 	}
3848dbcf02cSchristos 
3858dbcf02cSchristos 	kill_svc = CreateEvent(0, TRUE, FALSE, 0);
3868dbcf02cSchristos 	if (!kill_svc) {
3878dbcf02cSchristos 		printf("CreateEvent failed: %d\n", (int) GetLastError());
3888dbcf02cSchristos 		return;
3898dbcf02cSchristos 	}
3908dbcf02cSchristos 
3918dbcf02cSchristos 	if (CreateThread(0, 0, (LPTHREAD_START_ROUTINE) svc_thread, 0, 0, &id)
3928dbcf02cSchristos 	    == 0) {
3938dbcf02cSchristos 		printf("CreateThread failed: %d\n", (int) GetLastError());
3948dbcf02cSchristos 		return;
3958dbcf02cSchristos 	}
3968dbcf02cSchristos 
3978dbcf02cSchristos 	if (svc_status.dwCurrentState == SERVICE_START_PENDING) {
3988dbcf02cSchristos 		svc_status.dwCurrentState = SERVICE_RUNNING;
3998dbcf02cSchristos 		svc_status.dwWaitHint = 0;
4008dbcf02cSchristos 		svc_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
4018dbcf02cSchristos 			SERVICE_ACCEPT_SHUTDOWN;
4028dbcf02cSchristos 	}
4038dbcf02cSchristos 
4048dbcf02cSchristos 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
4058dbcf02cSchristos 		printf("SetServiceStatus() failed: %d\n",
4068dbcf02cSchristos 		       (int) GetLastError());
4078dbcf02cSchristos 		return;
4088dbcf02cSchristos 	}
4098dbcf02cSchristos 
4108dbcf02cSchristos 	/* wait until service gets killed */
4118dbcf02cSchristos 	WaitForSingleObject(kill_svc, INFINITE);
4128dbcf02cSchristos }
4138dbcf02cSchristos 
4148dbcf02cSchristos 
main(int argc,char * argv[])4158dbcf02cSchristos int main(int argc, char *argv[])
4168dbcf02cSchristos {
4178dbcf02cSchristos 	SERVICE_TABLE_ENTRY dt[] = {
4188dbcf02cSchristos 		{ WPASVC_NAME, service_start },
4198dbcf02cSchristos 		{ NULL, NULL }
4208dbcf02cSchristos 	};
4218dbcf02cSchristos 
4228dbcf02cSchristos 	if (argc > 1) {
4238dbcf02cSchristos 		if (os_strcmp(argv[1], "reg") == 0) {
4248dbcf02cSchristos 			TCHAR *path;
4258dbcf02cSchristos 			int ret;
4268dbcf02cSchristos 
4278dbcf02cSchristos 			if (argc < 3) {
4288dbcf02cSchristos 				path = os_malloc(MAX_PATH * sizeof(TCHAR));
4298dbcf02cSchristos 				if (path == NULL)
4308dbcf02cSchristos 					return -1;
4318dbcf02cSchristos 				if (!GetModuleFileName(NULL, path, MAX_PATH)) {
4328dbcf02cSchristos 					printf("GetModuleFileName failed: "
4338dbcf02cSchristos 					       "%d\n", (int) GetLastError());
4348dbcf02cSchristos 					os_free(path);
4358dbcf02cSchristos 					return -1;
4368dbcf02cSchristos 				}
4378dbcf02cSchristos 			} else {
4388dbcf02cSchristos 				path = wpa_strdup_tchar(argv[2]);
4398dbcf02cSchristos 				if (path == NULL)
4408dbcf02cSchristos 					return -1;
4418dbcf02cSchristos 			}
4428dbcf02cSchristos 			ret = register_service(path);
4438dbcf02cSchristos 			os_free(path);
4448dbcf02cSchristos 			return ret;
4458dbcf02cSchristos 		} else if (os_strcmp(argv[1], "unreg") == 0) {
4468dbcf02cSchristos 			return unregister_service();
4478dbcf02cSchristos 		} else if (os_strcmp(argv[1], "app") == 0) {
4488dbcf02cSchristos 			return wpa_supplicant_thread();
4498dbcf02cSchristos 		}
4508dbcf02cSchristos 	}
4518dbcf02cSchristos 
4528dbcf02cSchristos 	if (!StartServiceCtrlDispatcher(dt)) {
4538dbcf02cSchristos 		printf("StartServiceCtrlDispatcher failed: %d\n",
4548dbcf02cSchristos 		       (int) GetLastError());
4558dbcf02cSchristos 	}
4568dbcf02cSchristos 
4578dbcf02cSchristos 	return 0;
4588dbcf02cSchristos }
459