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