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(¶ms, 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(¶ms);
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