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