xref: /freebsd/contrib/wpa/wpa_supplicant/main_winsvc.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
1*c1d255d3SCy Schubert /*
2*c1d255d3SCy Schubert  * WPA Supplicant / main() function for Win32 service
3*c1d255d3SCy Schubert  * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
4*c1d255d3SCy Schubert  *
5*c1d255d3SCy Schubert  * This software may be distributed under the terms of the BSD license.
6*c1d255d3SCy Schubert  * See README for more details.
7*c1d255d3SCy Schubert  *
8*c1d255d3SCy Schubert  * The root of wpa_supplicant configuration in registry is
9*c1d255d3SCy Schubert  * HKEY_LOCAL_MACHINE\\SOFTWARE\\%wpa_supplicant. This level includes global
10*c1d255d3SCy Schubert  * parameters and a 'interfaces' subkey with all the interface configuration
11*c1d255d3SCy Schubert  * (adapter to confname mapping). Each such mapping is a subkey that has
12*c1d255d3SCy Schubert  * 'adapter' and 'config' values.
13*c1d255d3SCy Schubert  *
14*c1d255d3SCy Schubert  * This program can be run either as a normal command line application, e.g.,
15*c1d255d3SCy Schubert  * for debugging, with 'wpasvc.exe app' or as a Windows service. Service need
16*c1d255d3SCy Schubert  * to be registered with 'wpasvc.exe reg <full path to wpasvc.exe>'. After
17*c1d255d3SCy Schubert  * this, it can be started like any other Windows service (e.g., 'net start
18*c1d255d3SCy Schubert  * wpasvc') or it can be configured to start automatically through the Services
19*c1d255d3SCy Schubert  * tool in administrative tasks. The service can be unregistered with
20*c1d255d3SCy Schubert  * 'wpasvc.exe unreg'.
21*c1d255d3SCy Schubert  */
22*c1d255d3SCy Schubert 
23*c1d255d3SCy Schubert #include "includes.h"
24*c1d255d3SCy Schubert #include <windows.h>
25*c1d255d3SCy Schubert 
26*c1d255d3SCy Schubert #include "common.h"
27*c1d255d3SCy Schubert #include "wpa_supplicant_i.h"
28*c1d255d3SCy Schubert #include "eloop.h"
29*c1d255d3SCy Schubert 
30*c1d255d3SCy Schubert #ifndef WPASVC_NAME
31*c1d255d3SCy Schubert #define WPASVC_NAME TEXT("wpasvc")
32*c1d255d3SCy Schubert #endif
33*c1d255d3SCy Schubert #ifndef WPASVC_DISPLAY_NAME
34*c1d255d3SCy Schubert #define WPASVC_DISPLAY_NAME TEXT("wpa_supplicant service")
35*c1d255d3SCy Schubert #endif
36*c1d255d3SCy Schubert #ifndef WPASVC_DESCRIPTION
37*c1d255d3SCy Schubert #define WPASVC_DESCRIPTION \
38*c1d255d3SCy Schubert TEXT("Provides IEEE 802.1X and WPA/WPA2 supplicant functionality")
39*c1d255d3SCy Schubert #endif
40*c1d255d3SCy Schubert 
41*c1d255d3SCy Schubert static HANDLE kill_svc;
42*c1d255d3SCy Schubert 
43*c1d255d3SCy Schubert static SERVICE_STATUS_HANDLE svc_status_handle;
44*c1d255d3SCy Schubert static SERVICE_STATUS svc_status;
45*c1d255d3SCy Schubert 
46*c1d255d3SCy Schubert 
47*c1d255d3SCy Schubert #ifndef WPA_KEY_ROOT
48*c1d255d3SCy Schubert #define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
49*c1d255d3SCy Schubert #endif
50*c1d255d3SCy Schubert #ifndef WPA_KEY_PREFIX
51*c1d255d3SCy Schubert #define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
52*c1d255d3SCy Schubert #endif
53*c1d255d3SCy Schubert 
54*c1d255d3SCy Schubert #ifdef UNICODE
55*c1d255d3SCy Schubert #define TSTR "%S"
56*c1d255d3SCy Schubert #else /* UNICODE */
57*c1d255d3SCy Schubert #define TSTR "%s"
58*c1d255d3SCy Schubert #endif /* UNICODE */
59*c1d255d3SCy Schubert 
60*c1d255d3SCy Schubert 
read_interface(struct wpa_global * global,HKEY _hk,const TCHAR * name)61*c1d255d3SCy Schubert static int read_interface(struct wpa_global *global, HKEY _hk,
62*c1d255d3SCy Schubert 			  const TCHAR *name)
63*c1d255d3SCy Schubert {
64*c1d255d3SCy Schubert 	HKEY hk;
65*c1d255d3SCy Schubert #define TBUFLEN 255
66*c1d255d3SCy Schubert 	TCHAR adapter[TBUFLEN], config[TBUFLEN], ctrl_interface[TBUFLEN];
67*c1d255d3SCy Schubert 	DWORD buflen, val;
68*c1d255d3SCy Schubert 	LONG ret;
69*c1d255d3SCy Schubert 	struct wpa_interface iface;
70*c1d255d3SCy Schubert 	int skip_on_error = 0;
71*c1d255d3SCy Schubert 
72*c1d255d3SCy Schubert 	ret = RegOpenKeyEx(_hk, name, 0, KEY_QUERY_VALUE, &hk);
73*c1d255d3SCy Schubert 	if (ret != ERROR_SUCCESS) {
74*c1d255d3SCy Schubert 		printf("Could not open wpa_supplicant interface key\n");
75*c1d255d3SCy Schubert 		return -1;
76*c1d255d3SCy Schubert 	}
77*c1d255d3SCy Schubert 
78*c1d255d3SCy Schubert 	os_memset(&iface, 0, sizeof(iface));
79*c1d255d3SCy Schubert 	iface.driver = "ndis";
80*c1d255d3SCy Schubert 
81*c1d255d3SCy Schubert 	buflen = sizeof(ctrl_interface);
82*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("ctrl_interface"), NULL, NULL,
83*c1d255d3SCy Schubert 			      (LPBYTE) ctrl_interface, &buflen);
84*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS) {
85*c1d255d3SCy Schubert 		ctrl_interface[TBUFLEN - 1] = TEXT('\0');
86*c1d255d3SCy Schubert 		wpa_unicode2ascii_inplace(ctrl_interface);
87*c1d255d3SCy Schubert 		printf("ctrl_interface[len=%d] '%s'\n",
88*c1d255d3SCy Schubert 		       (int) buflen, (char *) ctrl_interface);
89*c1d255d3SCy Schubert 		iface.ctrl_interface = (char *) ctrl_interface;
90*c1d255d3SCy Schubert 	}
91*c1d255d3SCy Schubert 
92*c1d255d3SCy Schubert 	buflen = sizeof(adapter);
93*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("adapter"), NULL, NULL,
94*c1d255d3SCy Schubert 			      (LPBYTE) adapter, &buflen);
95*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS) {
96*c1d255d3SCy Schubert 		adapter[TBUFLEN - 1] = TEXT('\0');
97*c1d255d3SCy Schubert 		wpa_unicode2ascii_inplace(adapter);
98*c1d255d3SCy Schubert 		printf("adapter[len=%d] '%s'\n",
99*c1d255d3SCy Schubert 		       (int) buflen, (char *) adapter);
100*c1d255d3SCy Schubert 		iface.ifname = (char *) adapter;
101*c1d255d3SCy Schubert 	}
102*c1d255d3SCy Schubert 
103*c1d255d3SCy Schubert 	buflen = sizeof(config);
104*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("config"), NULL, NULL,
105*c1d255d3SCy Schubert 			      (LPBYTE) config, &buflen);
106*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS) {
107*c1d255d3SCy Schubert 		config[sizeof(config) - 1] = '\0';
108*c1d255d3SCy Schubert 		wpa_unicode2ascii_inplace(config);
109*c1d255d3SCy Schubert 		printf("config[len=%d] '%s'\n",
110*c1d255d3SCy Schubert 		       (int) buflen, (char *) config);
111*c1d255d3SCy Schubert 		iface.confname = (char *) config;
112*c1d255d3SCy Schubert 	}
113*c1d255d3SCy Schubert 
114*c1d255d3SCy Schubert 	buflen = sizeof(val);
115*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("skip_on_error"), NULL, NULL,
116*c1d255d3SCy Schubert 			      (LPBYTE) &val, &buflen);
117*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS && buflen == sizeof(val))
118*c1d255d3SCy Schubert 		skip_on_error = val;
119*c1d255d3SCy Schubert 
120*c1d255d3SCy Schubert 	RegCloseKey(hk);
121*c1d255d3SCy Schubert 
122*c1d255d3SCy Schubert 	if (wpa_supplicant_add_iface(global, &iface, NULL) == NULL) {
123*c1d255d3SCy Schubert 		if (skip_on_error)
124*c1d255d3SCy Schubert 			wpa_printf(MSG_DEBUG, "Skipped interface '%s' due to "
125*c1d255d3SCy Schubert 				   "initialization failure", iface.ifname);
126*c1d255d3SCy Schubert 		else
127*c1d255d3SCy Schubert 			return -1;
128*c1d255d3SCy Schubert 	}
129*c1d255d3SCy Schubert 
130*c1d255d3SCy Schubert 	return 0;
131*c1d255d3SCy Schubert }
132*c1d255d3SCy Schubert 
133*c1d255d3SCy Schubert 
wpa_supplicant_thread(void)134*c1d255d3SCy Schubert static int wpa_supplicant_thread(void)
135*c1d255d3SCy Schubert {
136*c1d255d3SCy Schubert 	int exitcode;
137*c1d255d3SCy Schubert 	struct wpa_params params;
138*c1d255d3SCy Schubert 	struct wpa_global *global;
139*c1d255d3SCy Schubert 	HKEY hk, ihk;
140*c1d255d3SCy Schubert 	DWORD val, buflen, i;
141*c1d255d3SCy Schubert 	LONG ret;
142*c1d255d3SCy Schubert 
143*c1d255d3SCy Schubert 	if (os_program_init())
144*c1d255d3SCy Schubert 		return -1;
145*c1d255d3SCy Schubert 
146*c1d255d3SCy Schubert 	os_memset(&params, 0, sizeof(params));
147*c1d255d3SCy Schubert 	params.wpa_debug_level = MSG_INFO;
148*c1d255d3SCy Schubert 
149*c1d255d3SCy Schubert 	ret = RegOpenKeyEx(WPA_KEY_ROOT, WPA_KEY_PREFIX,
150*c1d255d3SCy Schubert 			   0, KEY_QUERY_VALUE, &hk);
151*c1d255d3SCy Schubert 	if (ret != ERROR_SUCCESS) {
152*c1d255d3SCy Schubert 		printf("Could not open wpa_supplicant registry key\n");
153*c1d255d3SCy Schubert 		return -1;
154*c1d255d3SCy Schubert 	}
155*c1d255d3SCy Schubert 
156*c1d255d3SCy Schubert 	buflen = sizeof(val);
157*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("debug_level"), NULL, NULL,
158*c1d255d3SCy Schubert 			      (LPBYTE) &val, &buflen);
159*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
160*c1d255d3SCy Schubert 		params.wpa_debug_level = val;
161*c1d255d3SCy Schubert 	}
162*c1d255d3SCy Schubert 
163*c1d255d3SCy Schubert 	buflen = sizeof(val);
164*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("debug_show_keys"), NULL, NULL,
165*c1d255d3SCy Schubert 			      (LPBYTE) &val, &buflen);
166*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
167*c1d255d3SCy Schubert 		params.wpa_debug_show_keys = val;
168*c1d255d3SCy Schubert 	}
169*c1d255d3SCy Schubert 
170*c1d255d3SCy Schubert 	buflen = sizeof(val);
171*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("debug_timestamp"), NULL, NULL,
172*c1d255d3SCy Schubert 			      (LPBYTE) &val, &buflen);
173*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
174*c1d255d3SCy Schubert 		params.wpa_debug_timestamp = val;
175*c1d255d3SCy Schubert 	}
176*c1d255d3SCy Schubert 
177*c1d255d3SCy Schubert 	buflen = sizeof(val);
178*c1d255d3SCy Schubert 	ret = RegQueryValueEx(hk, TEXT("debug_use_file"), NULL, NULL,
179*c1d255d3SCy Schubert 			      (LPBYTE) &val, &buflen);
180*c1d255d3SCy Schubert 	if (ret == ERROR_SUCCESS && buflen == sizeof(val) && val) {
181*c1d255d3SCy Schubert 		params.wpa_debug_file_path = "\\Temp\\wpa_supplicant-log.txt";
182*c1d255d3SCy Schubert 	}
183*c1d255d3SCy Schubert 
184*c1d255d3SCy Schubert 	exitcode = 0;
185*c1d255d3SCy Schubert 	global = wpa_supplicant_init(&params);
186*c1d255d3SCy Schubert 	if (global == NULL) {
187*c1d255d3SCy Schubert 		printf("Failed to initialize wpa_supplicant\n");
188*c1d255d3SCy Schubert 		exitcode = -1;
189*c1d255d3SCy Schubert 	}
190*c1d255d3SCy Schubert 
191*c1d255d3SCy Schubert 	ret = RegOpenKeyEx(hk, TEXT("interfaces"), 0, KEY_ENUMERATE_SUB_KEYS,
192*c1d255d3SCy Schubert 			   &ihk);
193*c1d255d3SCy Schubert 	RegCloseKey(hk);
194*c1d255d3SCy Schubert 	if (ret != ERROR_SUCCESS) {
195*c1d255d3SCy Schubert 		printf("Could not open wpa_supplicant interfaces registry "
196*c1d255d3SCy Schubert 		       "key\n");
197*c1d255d3SCy Schubert 		return -1;
198*c1d255d3SCy Schubert 	}
199*c1d255d3SCy Schubert 
200*c1d255d3SCy Schubert 	for (i = 0; ; i++) {
201*c1d255d3SCy Schubert 		TCHAR name[255];
202*c1d255d3SCy Schubert 		DWORD namelen;
203*c1d255d3SCy Schubert 
204*c1d255d3SCy Schubert 		namelen = 255;
205*c1d255d3SCy Schubert 		ret = RegEnumKeyEx(ihk, i, name, &namelen, NULL, NULL, NULL,
206*c1d255d3SCy Schubert 				   NULL);
207*c1d255d3SCy Schubert 
208*c1d255d3SCy Schubert 		if (ret == ERROR_NO_MORE_ITEMS)
209*c1d255d3SCy Schubert 			break;
210*c1d255d3SCy Schubert 
211*c1d255d3SCy Schubert 		if (ret != ERROR_SUCCESS) {
212*c1d255d3SCy Schubert 			printf("RegEnumKeyEx failed: 0x%x\n",
213*c1d255d3SCy Schubert 			       (unsigned int) ret);
214*c1d255d3SCy Schubert 			break;
215*c1d255d3SCy Schubert 		}
216*c1d255d3SCy Schubert 
217*c1d255d3SCy Schubert 		if (namelen >= 255)
218*c1d255d3SCy Schubert 			namelen = 255 - 1;
219*c1d255d3SCy Schubert 		name[namelen] = '\0';
220*c1d255d3SCy Schubert 
221*c1d255d3SCy Schubert 		wpa_printf(MSG_DEBUG, "interface %d: %s\n", (int) i, name);
222*c1d255d3SCy Schubert 		if (read_interface(global, ihk, name) < 0)
223*c1d255d3SCy Schubert 			exitcode = -1;
224*c1d255d3SCy Schubert 	}
225*c1d255d3SCy Schubert 
226*c1d255d3SCy Schubert 	RegCloseKey(ihk);
227*c1d255d3SCy Schubert 
228*c1d255d3SCy Schubert 	if (exitcode == 0)
229*c1d255d3SCy Schubert 		exitcode = wpa_supplicant_run(global);
230*c1d255d3SCy Schubert 
231*c1d255d3SCy Schubert 	wpa_supplicant_deinit(global);
232*c1d255d3SCy Schubert 
233*c1d255d3SCy Schubert 	os_program_deinit();
234*c1d255d3SCy Schubert 
235*c1d255d3SCy Schubert 	return exitcode;
236*c1d255d3SCy Schubert }
237*c1d255d3SCy Schubert 
238*c1d255d3SCy Schubert 
svc_thread(LPDWORD param)239*c1d255d3SCy Schubert static DWORD svc_thread(LPDWORD param)
240*c1d255d3SCy Schubert {
241*c1d255d3SCy Schubert 	int ret = wpa_supplicant_thread();
242*c1d255d3SCy Schubert 
243*c1d255d3SCy Schubert 	svc_status.dwCurrentState = SERVICE_STOPPED;
244*c1d255d3SCy Schubert 	svc_status.dwWaitHint = 0;
245*c1d255d3SCy Schubert 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
246*c1d255d3SCy Schubert 		printf("SetServiceStatus() failed: %d\n",
247*c1d255d3SCy Schubert 		       (int) GetLastError());
248*c1d255d3SCy Schubert 	}
249*c1d255d3SCy Schubert 
250*c1d255d3SCy Schubert 	return ret;
251*c1d255d3SCy Schubert }
252*c1d255d3SCy Schubert 
253*c1d255d3SCy Schubert 
register_service(const TCHAR * exe)254*c1d255d3SCy Schubert static int register_service(const TCHAR *exe)
255*c1d255d3SCy Schubert {
256*c1d255d3SCy Schubert 	SC_HANDLE svc, scm;
257*c1d255d3SCy Schubert 	SERVICE_DESCRIPTION sd;
258*c1d255d3SCy Schubert 
259*c1d255d3SCy Schubert 	printf("Registering service: " TSTR "\n", WPASVC_NAME);
260*c1d255d3SCy Schubert 
261*c1d255d3SCy Schubert 	scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
262*c1d255d3SCy Schubert 	if (!scm) {
263*c1d255d3SCy Schubert 		printf("OpenSCManager failed: %d\n", (int) GetLastError());
264*c1d255d3SCy Schubert 		return -1;
265*c1d255d3SCy Schubert 	}
266*c1d255d3SCy Schubert 
267*c1d255d3SCy Schubert 	svc = CreateService(scm, WPASVC_NAME, WPASVC_DISPLAY_NAME,
268*c1d255d3SCy Schubert 			    SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
269*c1d255d3SCy Schubert 			    SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
270*c1d255d3SCy Schubert 			    exe, NULL, NULL, NULL, NULL, NULL);
271*c1d255d3SCy Schubert 
272*c1d255d3SCy Schubert 	if (!svc) {
273*c1d255d3SCy Schubert 		printf("CreateService failed: %d\n\n", (int) GetLastError());
274*c1d255d3SCy Schubert 		CloseServiceHandle(scm);
275*c1d255d3SCy Schubert 		return -1;
276*c1d255d3SCy Schubert 	}
277*c1d255d3SCy Schubert 
278*c1d255d3SCy Schubert 	os_memset(&sd, 0, sizeof(sd));
279*c1d255d3SCy Schubert 	sd.lpDescription = WPASVC_DESCRIPTION;
280*c1d255d3SCy Schubert 	if (!ChangeServiceConfig2(svc, SERVICE_CONFIG_DESCRIPTION, &sd)) {
281*c1d255d3SCy Schubert 		printf("ChangeServiceConfig2 failed: %d\n",
282*c1d255d3SCy Schubert 		       (int) GetLastError());
283*c1d255d3SCy Schubert 		/* This is not a fatal error, so continue anyway. */
284*c1d255d3SCy Schubert 	}
285*c1d255d3SCy Schubert 
286*c1d255d3SCy Schubert 	CloseServiceHandle(svc);
287*c1d255d3SCy Schubert 	CloseServiceHandle(scm);
288*c1d255d3SCy Schubert 
289*c1d255d3SCy Schubert 	printf("Service registered successfully.\n");
290*c1d255d3SCy Schubert 
291*c1d255d3SCy Schubert 	return 0;
292*c1d255d3SCy Schubert }
293*c1d255d3SCy Schubert 
294*c1d255d3SCy Schubert 
unregister_service(void)295*c1d255d3SCy Schubert static int unregister_service(void)
296*c1d255d3SCy Schubert {
297*c1d255d3SCy Schubert 	SC_HANDLE svc, scm;
298*c1d255d3SCy Schubert 	SERVICE_STATUS status;
299*c1d255d3SCy Schubert 
300*c1d255d3SCy Schubert 	printf("Unregistering service: " TSTR "\n", WPASVC_NAME);
301*c1d255d3SCy Schubert 
302*c1d255d3SCy Schubert 	scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
303*c1d255d3SCy Schubert 	if (!scm) {
304*c1d255d3SCy Schubert 		printf("OpenSCManager failed: %d\n", (int) GetLastError());
305*c1d255d3SCy Schubert 		return -1;
306*c1d255d3SCy Schubert 	}
307*c1d255d3SCy Schubert 
308*c1d255d3SCy Schubert 	svc = OpenService(scm, WPASVC_NAME, SERVICE_ALL_ACCESS | DELETE);
309*c1d255d3SCy Schubert 	if (!svc) {
310*c1d255d3SCy Schubert 		printf("OpenService failed: %d\n\n", (int) GetLastError());
311*c1d255d3SCy Schubert 		CloseServiceHandle(scm);
312*c1d255d3SCy Schubert 		return -1;
313*c1d255d3SCy Schubert 	}
314*c1d255d3SCy Schubert 
315*c1d255d3SCy Schubert 	if (QueryServiceStatus(svc, &status)) {
316*c1d255d3SCy Schubert 		if (status.dwCurrentState != SERVICE_STOPPED) {
317*c1d255d3SCy Schubert 			printf("Service currently active - stopping "
318*c1d255d3SCy Schubert 			       "service...\n");
319*c1d255d3SCy Schubert 			if (!ControlService(svc, SERVICE_CONTROL_STOP,
320*c1d255d3SCy Schubert 					    &status)) {
321*c1d255d3SCy Schubert 				printf("ControlService failed: %d\n",
322*c1d255d3SCy Schubert 				       (int) GetLastError());
323*c1d255d3SCy Schubert 			}
324*c1d255d3SCy Schubert 			Sleep(500);
325*c1d255d3SCy Schubert 		}
326*c1d255d3SCy Schubert 	}
327*c1d255d3SCy Schubert 
328*c1d255d3SCy Schubert 	if (DeleteService(svc)) {
329*c1d255d3SCy Schubert 		printf("Service unregistered successfully.\n");
330*c1d255d3SCy Schubert 	} else {
331*c1d255d3SCy Schubert 		printf("DeleteService failed: %d\n", (int) GetLastError());
332*c1d255d3SCy Schubert 	}
333*c1d255d3SCy Schubert 
334*c1d255d3SCy Schubert 	CloseServiceHandle(svc);
335*c1d255d3SCy Schubert 	CloseServiceHandle(scm);
336*c1d255d3SCy Schubert 
337*c1d255d3SCy Schubert 	return 0;
338*c1d255d3SCy Schubert }
339*c1d255d3SCy Schubert 
340*c1d255d3SCy Schubert 
service_ctrl_handler(DWORD control_code)341*c1d255d3SCy Schubert static void WINAPI service_ctrl_handler(DWORD control_code)
342*c1d255d3SCy Schubert {
343*c1d255d3SCy Schubert 	switch (control_code) {
344*c1d255d3SCy Schubert 	case SERVICE_CONTROL_INTERROGATE:
345*c1d255d3SCy Schubert 		break;
346*c1d255d3SCy Schubert 	case SERVICE_CONTROL_SHUTDOWN:
347*c1d255d3SCy Schubert 	case SERVICE_CONTROL_STOP:
348*c1d255d3SCy Schubert 		svc_status.dwCurrentState = SERVICE_STOP_PENDING;
349*c1d255d3SCy Schubert 		svc_status.dwWaitHint = 2000;
350*c1d255d3SCy Schubert 		eloop_terminate();
351*c1d255d3SCy Schubert 		SetEvent(kill_svc);
352*c1d255d3SCy Schubert 		break;
353*c1d255d3SCy Schubert 	}
354*c1d255d3SCy Schubert 
355*c1d255d3SCy Schubert 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
356*c1d255d3SCy Schubert 		printf("SetServiceStatus() failed: %d\n",
357*c1d255d3SCy Schubert 		       (int) GetLastError());
358*c1d255d3SCy Schubert 	}
359*c1d255d3SCy Schubert }
360*c1d255d3SCy Schubert 
361*c1d255d3SCy Schubert 
service_start(DWORD argc,LPTSTR * argv)362*c1d255d3SCy Schubert static void WINAPI service_start(DWORD argc, LPTSTR *argv)
363*c1d255d3SCy Schubert {
364*c1d255d3SCy Schubert 	DWORD id;
365*c1d255d3SCy Schubert 
366*c1d255d3SCy Schubert 	svc_status_handle = RegisterServiceCtrlHandler(WPASVC_NAME,
367*c1d255d3SCy Schubert 						       service_ctrl_handler);
368*c1d255d3SCy Schubert 	if (svc_status_handle == (SERVICE_STATUS_HANDLE) 0) {
369*c1d255d3SCy Schubert 		printf("RegisterServiceCtrlHandler failed: %d\n",
370*c1d255d3SCy Schubert 		       (int) GetLastError());
371*c1d255d3SCy Schubert 		return;
372*c1d255d3SCy Schubert 	}
373*c1d255d3SCy Schubert 
374*c1d255d3SCy Schubert 	os_memset(&svc_status, 0, sizeof(svc_status));
375*c1d255d3SCy Schubert 	svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
376*c1d255d3SCy Schubert 	svc_status.dwCurrentState = SERVICE_START_PENDING;
377*c1d255d3SCy Schubert 	svc_status.dwWaitHint = 1000;
378*c1d255d3SCy Schubert 
379*c1d255d3SCy Schubert 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
380*c1d255d3SCy Schubert 		printf("SetServiceStatus() failed: %d\n",
381*c1d255d3SCy Schubert 		       (int) GetLastError());
382*c1d255d3SCy Schubert 		return;
383*c1d255d3SCy Schubert 	}
384*c1d255d3SCy Schubert 
385*c1d255d3SCy Schubert 	kill_svc = CreateEvent(0, TRUE, FALSE, 0);
386*c1d255d3SCy Schubert 	if (!kill_svc) {
387*c1d255d3SCy Schubert 		printf("CreateEvent failed: %d\n", (int) GetLastError());
388*c1d255d3SCy Schubert 		return;
389*c1d255d3SCy Schubert 	}
390*c1d255d3SCy Schubert 
391*c1d255d3SCy Schubert 	if (CreateThread(0, 0, (LPTHREAD_START_ROUTINE) svc_thread, 0, 0, &id)
392*c1d255d3SCy Schubert 	    == 0) {
393*c1d255d3SCy Schubert 		printf("CreateThread failed: %d\n", (int) GetLastError());
394*c1d255d3SCy Schubert 		return;
395*c1d255d3SCy Schubert 	}
396*c1d255d3SCy Schubert 
397*c1d255d3SCy Schubert 	if (svc_status.dwCurrentState == SERVICE_START_PENDING) {
398*c1d255d3SCy Schubert 		svc_status.dwCurrentState = SERVICE_RUNNING;
399*c1d255d3SCy Schubert 		svc_status.dwWaitHint = 0;
400*c1d255d3SCy Schubert 		svc_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
401*c1d255d3SCy Schubert 			SERVICE_ACCEPT_SHUTDOWN;
402*c1d255d3SCy Schubert 	}
403*c1d255d3SCy Schubert 
404*c1d255d3SCy Schubert 	if (!SetServiceStatus(svc_status_handle, &svc_status)) {
405*c1d255d3SCy Schubert 		printf("SetServiceStatus() failed: %d\n",
406*c1d255d3SCy Schubert 		       (int) GetLastError());
407*c1d255d3SCy Schubert 		return;
408*c1d255d3SCy Schubert 	}
409*c1d255d3SCy Schubert 
410*c1d255d3SCy Schubert 	/* wait until service gets killed */
411*c1d255d3SCy Schubert 	WaitForSingleObject(kill_svc, INFINITE);
412*c1d255d3SCy Schubert }
413*c1d255d3SCy Schubert 
414*c1d255d3SCy Schubert 
main(int argc,char * argv[])415*c1d255d3SCy Schubert int main(int argc, char *argv[])
416*c1d255d3SCy Schubert {
417*c1d255d3SCy Schubert 	SERVICE_TABLE_ENTRY dt[] = {
418*c1d255d3SCy Schubert 		{ WPASVC_NAME, service_start },
419*c1d255d3SCy Schubert 		{ NULL, NULL }
420*c1d255d3SCy Schubert 	};
421*c1d255d3SCy Schubert 
422*c1d255d3SCy Schubert 	if (argc > 1) {
423*c1d255d3SCy Schubert 		if (os_strcmp(argv[1], "reg") == 0) {
424*c1d255d3SCy Schubert 			TCHAR *path;
425*c1d255d3SCy Schubert 			int ret;
426*c1d255d3SCy Schubert 
427*c1d255d3SCy Schubert 			if (argc < 3) {
428*c1d255d3SCy Schubert 				path = os_malloc(MAX_PATH * sizeof(TCHAR));
429*c1d255d3SCy Schubert 				if (path == NULL)
430*c1d255d3SCy Schubert 					return -1;
431*c1d255d3SCy Schubert 				if (!GetModuleFileName(NULL, path, MAX_PATH)) {
432*c1d255d3SCy Schubert 					printf("GetModuleFileName failed: "
433*c1d255d3SCy Schubert 					       "%d\n", (int) GetLastError());
434*c1d255d3SCy Schubert 					os_free(path);
435*c1d255d3SCy Schubert 					return -1;
436*c1d255d3SCy Schubert 				}
437*c1d255d3SCy Schubert 			} else {
438*c1d255d3SCy Schubert 				path = wpa_strdup_tchar(argv[2]);
439*c1d255d3SCy Schubert 				if (path == NULL)
440*c1d255d3SCy Schubert 					return -1;
441*c1d255d3SCy Schubert 			}
442*c1d255d3SCy Schubert 			ret = register_service(path);
443*c1d255d3SCy Schubert 			os_free(path);
444*c1d255d3SCy Schubert 			return ret;
445*c1d255d3SCy Schubert 		} else if (os_strcmp(argv[1], "unreg") == 0) {
446*c1d255d3SCy Schubert 			return unregister_service();
447*c1d255d3SCy Schubert 		} else if (os_strcmp(argv[1], "app") == 0) {
448*c1d255d3SCy Schubert 			return wpa_supplicant_thread();
449*c1d255d3SCy Schubert 		}
450*c1d255d3SCy Schubert 	}
451*c1d255d3SCy Schubert 
452*c1d255d3SCy Schubert 	if (!StartServiceCtrlDispatcher(dt)) {
453*c1d255d3SCy Schubert 		printf("StartServiceCtrlDispatcher failed: %d\n",
454*c1d255d3SCy Schubert 		       (int) GetLastError());
455*c1d255d3SCy Schubert 	}
456*c1d255d3SCy Schubert 
457*c1d255d3SCy Schubert 	return 0;
458*c1d255d3SCy Schubert }
459