1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant / Configuration backend: Windows registry
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This file implements a configuration backend for Windows registry. All the
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * configuration information is stored in the registry and the format for
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * network configuration fields is same as described in the sample
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * configuration file, wpa_supplicant.conf.
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Configuration data is in
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * \a HKEY_LOCAL_MACHINE\\SOFTWARE\\%wpa_supplicant\\configs
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * key. Each configuration profile has its own key under this. In terms of text
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * files, each profile would map to a separate text file with possibly multiple
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * networks. Under each profile, there is a networks key that lists all
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * networks as a subkey. Each network has set of values in the same way as
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * network block in the configuration file. In addition, blobs subkey has
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * possible blobs as values.
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Example network configuration block:
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * \verbatim
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtHKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt   ssid="example"
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt   key_mgmt=WPA-PSK
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt\endverbatim
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "uuid.h"
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "config.h"
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef WPA_KEY_ROOT
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef WPA_KEY_PREFIX
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define TSTR "%S"
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define TSTR "%s"
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_read_blobs(struct wpa_config *config, HKEY hk)
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_config_blob *blob;
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0;
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY bhk;
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD i;
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegOpenKeyEx(hk, TEXT("blobs"), 0, KEY_QUERY_VALUE, &bhk);
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config "
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "blobs key");
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0; /* assume no blobs */
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; ; i++) {
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define TNAMELEN 255
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		TCHAR name[TNAMELEN];
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		char data[4096];
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		DWORD namelen, datalen, type;
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		namelen = TNAMELEN;
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		datalen = sizeof(data);
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = RegEnumValue(bhk, i, name, &namelen, NULL, &type,
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   (LPBYTE) data, &datalen);
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret != ERROR_SUCCESS) {
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "RegEnumValue failed: 0x%x",
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   (unsigned int) ret);
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (namelen >= TNAMELEN)
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			namelen = TNAMELEN - 1;
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		name[namelen] = TEXT('\0');
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_unicode2ascii_inplace(name);
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (datalen >= sizeof(data))
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			datalen = sizeof(data) - 1;
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_MSGDUMP, "blob %d: field='%s' len %d",
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) i, name, (int) datalen);
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blob = os_zalloc(sizeof(*blob));
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (blob == NULL) {
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blob->name = os_strdup((char *) name);
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blob->data = os_malloc(datalen);
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (blob->name == NULL || blob->data == NULL) {
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_config_free_blob(blob);
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(blob->data, data, datalen);
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		blob->len = datalen;
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_set_blob(config, blob);
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(bhk);
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return errors ? -1 : 0;
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_read_reg_dword(HKEY hk, const TCHAR *name, int *_val)
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD val, buflen;
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buflen = sizeof(val);
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) &val, &buflen);
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, TSTR "=%d", name, (int) val);
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*_val = val;
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic char * wpa_config_read_reg_string(HKEY hk, const TCHAR *name)
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD buflen;
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR *val;
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	buflen = 0;
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegQueryValueEx(hk, name, NULL, NULL, NULL, &buflen);
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS)
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	val = os_malloc(buflen);
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (val == NULL)
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) val, &buflen);
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(val);
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_unicode2ascii_inplace(val);
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, TSTR "=%s", name, (char *) val);
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return (char *) val;
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_WPS
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_read_global_uuid(struct wpa_config *config, HKEY hk)
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *str;
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret = 0;
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	str = wpa_config_read_reg_string(hk, TEXT("uuid"));
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (str == NULL)
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (uuid_str2bin(str, config->uuid))
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = -1;
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(str);
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_read_global_os_version(struct wpa_config *config,
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					     HKEY hk)
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *str;
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int ret = 0;
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	str = wpa_config_read_reg_string(hk, TEXT("os_version"));
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (str == NULL)
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (hexstr2bin(str, config->os_version, 4))
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = -1;
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(str);
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ret;
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_WPS */
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_read_global(struct wpa_config *config, HKEY hk)
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0;
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("ap_scan"), &config->ap_scan);
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("fast_reauth"),
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  &config->fast_reauth);
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"),
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  (int *) &config->dot11RSNAConfigPMKLifetime);
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_read_reg_dword(hk,
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  TEXT("dot11RSNAConfigPMKReauthThreshold"),
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  (int *)
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  &config->dot11RSNAConfigPMKReauthThreshold);
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"),
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  (int *) &config->dot11RSNAConfigSATimeout);
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("update_config"),
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  &config->update_config);
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_config_read_reg_dword(hk, TEXT("eapol_version"),
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				      &config->eapol_version) == 0) {
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (config->eapol_version < 1 ||
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		    config->eapol_version > 2) {
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Invalid EAPOL version (%d)",
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->eapol_version);
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->ctrl_interface = wpa_config_read_reg_string(
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hk, TEXT("ctrl_interface"));
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_WPS
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_config_read_global_uuid(config, hk))
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->device_name = wpa_config_read_reg_string(
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hk, TEXT("device_name"));
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->manufacturer = wpa_config_read_reg_string(
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hk, TEXT("manufacturer"));
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->model_name = wpa_config_read_reg_string(
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hk, TEXT("model_name"));
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->serial_number = wpa_config_read_reg_string(
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hk, TEXT("serial_number"));
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->device_type = wpa_config_read_reg_string(
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hk, TEXT("device_type"));
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_config_read_global_os_version(config, hk))
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_read_reg_dword(hk, TEXT("wps_cred_processing"),
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  &config->wps_cred_processing);
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_WPS */
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return errors ? -1 : 0;
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw,
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						 int id)
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY nhk;
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD i;
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ssid *ssid;
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0;
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk);
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config "
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "network '" TSTR "'", netw);
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw);
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ssid = os_zalloc(sizeof(*ssid));
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid == NULL) {
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		RegCloseKey(nhk);
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ssid->id = id;
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_set_network_defaults(ssid);
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; ; i++) {
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		TCHAR name[255], data[1024];
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		DWORD namelen, datalen, type;
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		namelen = 255;
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		datalen = sizeof(data);
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type,
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   (LPBYTE) data, &datalen);
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret != ERROR_SUCCESS) {
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x",
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   (unsigned int) ret);
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (namelen >= 255)
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			namelen = 255 - 1;
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		name[namelen] = TEXT('\0');
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (datalen >= 1024)
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			datalen = 1024 - 1;
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		data[datalen] = TEXT('\0');
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_unicode2ascii_inplace(name);
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_unicode2ascii_inplace(data);
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0)
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(nhk);
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->passphrase) {
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ssid->psk_set) {
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Both PSK and passphrase "
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "configured for network '" TSTR "'.", netw);
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_update_psk(ssid);
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			       WPA_KEY_MGMT_PSK_SHA256)) &&
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !ssid->psk_set) {
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, "
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "but no PSK configured for network '" TSTR "'.",
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   netw);
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Group cipher cannot be stronger than the pairwise cipher. */
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher "
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "list since it was not allowed for pairwise "
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "cipher for network '" TSTR "'.", netw);
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ssid->group_cipher &= ~WPA_CIPHER_CCMP;
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (errors) {
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_free_ssid(ssid);
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ssid = NULL;
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ssid;
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_read_networks(struct wpa_config *config, HKEY hk)
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY nhk;
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0;
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD i;
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_ENUMERATE_SUB_KEYS,
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   &nhk);
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Could not open wpa_supplicant networks "
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "registry key");
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; ; i++) {
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		TCHAR name[255];
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		DWORD namelen;
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		namelen = 255;
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL,
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   NULL);
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret != ERROR_SUCCESS) {
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x",
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   (unsigned int) ret);
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (namelen >= 255)
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			namelen = 255 - 1;
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		name[namelen] = '\0';
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ssid = wpa_config_read_network(nhk, name, i);
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ssid == NULL) {
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to parse network "
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "profile '%s'.", name);
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (head == NULL) {
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			head = tail = ssid;
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			tail->next = ssid;
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			tail = ssid;
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wpa_config_add_prio_network(config, ssid)) {
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to add network profile "
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "'%s' to priority list.", name);
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(nhk);
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config->ssid = head;
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return errors ? -1 : 0;
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct wpa_config * wpa_config_read(const char *name)
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR buf[256];
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0;
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_config *config;
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY hk;
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	config = wpa_config_alloc_empty(NULL, NULL);
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (config == NULL)
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name);
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name);
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name);
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_QUERY_VALUE, &hk);
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Could not open wpa_supplicant "
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "configuration registry HKLM\\" TSTR, buf);
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(config);
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_config_read_global(config, hk))
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_config_read_networks(config, hk))
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_config_read_blobs(config, hk))
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_debug_dump_networks(config);
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(hk);
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (errors) {
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_free(config);
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		config = NULL;
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return config;
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val,
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				      int def)
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD _val = val;
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (val == def) {
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		RegDeleteValue(hk, name);
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegSetValueEx(hk, name, 0, REG_DWORD, (LPBYTE) &_val,
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    sizeof(_val));
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "WINREG: Failed to set %s=%d: error %d",
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   name, val, (int) GetLastError());
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_write_reg_string(HKEY hk, const char *name,
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       const char *val)
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR *_name, *_val;
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_name = wpa_strdup_tchar(name);
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (_name == NULL)
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (val == NULL) {
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		RegDeleteValue(hk, _name);
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(_name);
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_val = wpa_strdup_tchar(val);
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (_val == NULL) {
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(_name);
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegSetValueEx(hk, _name, 0, REG_SZ, (BYTE *) _val,
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    (os_strlen(val) + 1) * sizeof(TCHAR));
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "WINREG: Failed to set %s='%s': "
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "error %d", name, val, (int) GetLastError());
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(_name);
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(_val);
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(_name);
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(_val);
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_write_global(struct wpa_config *config, HKEY hk)
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_CTRL_IFACE
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "ctrl_interface",
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    config->ctrl_interface);
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_CTRL_IFACE */
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("eapol_version"),
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->eapol_version,
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   DEFAULT_EAPOL_VERSION);
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("ap_scan"), config->ap_scan,
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   DEFAULT_AP_SCAN);
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("fast_reauth"),
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->fast_reauth, DEFAULT_FAST_REAUTH);
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"),
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->dot11RSNAConfigPMKLifetime, 0);
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk,
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   TEXT("dot11RSNAConfigPMKReauthThreshold"),
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->dot11RSNAConfigPMKReauthThreshold,
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   0);
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"),
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->dot11RSNAConfigSATimeout, 0);
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("update_config"),
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->update_config,
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   0);
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_WPS
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!is_nil_uuid(config->uuid)) {
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		char buf[40];
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		uuid_bin2str(config->uuid, buf, sizeof(buf));
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "uuid", buf);
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "device_name", config->device_name);
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "manufacturer", config->manufacturer);
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "model_name", config->model_name);
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "model_number", config->model_number);
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "serial_number",
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				    config->serial_number);
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "device_type", config->device_type);
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (WPA_GET_BE32(config->os_version)) {
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		char vbuf[10];
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_snprintf(vbuf, sizeof(vbuf), "%08x",
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    WPA_GET_BE32(config->os_version));
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "os_version", vbuf);
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_dword(hk, TEXT("wps_cred_processing"),
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   config->wps_cred_processing, 0);
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_WPS */
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_delete_subkeys(HKEY hk, const TCHAR *key)
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY nhk;
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i, errors = 0;
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegOpenKeyEx(hk, key, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &nhk);
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not open key '" TSTR
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "' for subkey deletion: error 0x%x (%d)", key,
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned int) ret, (int) GetLastError());
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; ; i++) {
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		TCHAR name[255];
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		DWORD namelen;
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		namelen = 255;
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL,
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   NULL);
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret == ERROR_NO_MORE_ITEMS)
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret != ERROR_SUCCESS) {
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x (%d)",
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   (unsigned int) ret, (int) GetLastError());
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (namelen >= 255)
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			namelen = 255 - 1;
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		name[namelen] = TEXT('\0');
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ret = RegDeleteKey(nhk, name);
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ret != ERROR_SUCCESS) {
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "RegDeleteKey failed: 0x%x (%d)",
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   (unsigned int) ret, (int) GetLastError());
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(nhk);
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return errors ? -1 : 0;
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_str(HKEY hk, const char *field, struct wpa_ssid *ssid)
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value = wpa_config_get(ssid, field);
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, field, value);
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_int(HKEY hk, const char *field, int value, int def)
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char val[20];
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == def)
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(val, sizeof(val), "%d", value);
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, field, val);
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_bssid(HKEY hk, struct wpa_ssid *ssid)
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value = wpa_config_get(ssid, "bssid");
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "bssid", value);
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_psk(HKEY hk, struct wpa_ssid *ssid)
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value = wpa_config_get(ssid, "psk");
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_write_reg_string(hk, "psk", value);
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_proto(HKEY hk, struct wpa_ssid *ssid)
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->proto == DEFAULT_PROTO)
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "proto");
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "proto", value);
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_key_mgmt(HKEY hk, struct wpa_ssid *ssid)
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "key_mgmt");
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "key_mgmt", value);
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_pairwise(HKEY hk, struct wpa_ssid *ssid)
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->pairwise_cipher == DEFAULT_PAIRWISE)
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "pairwise");
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "pairwise", value);
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_group(HKEY hk, struct wpa_ssid *ssid)
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->group_cipher == DEFAULT_GROUP)
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "group");
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "group", value);
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_auth_alg(HKEY hk, struct wpa_ssid *ssid)
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ssid->auth_alg == 0)
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "auth_alg");
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "auth_alg", value);
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef IEEE8021X_EAPOL
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_eap(HKEY hk, struct wpa_ssid *ssid)
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *value;
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, "eap");
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value == NULL)
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value[0])
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, "eap", value);
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(value);
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* IEEE8021X_EAPOL */
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid)
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char field[20], *value;
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(field, sizeof(field), "wep_key%d", idx);
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	value = wpa_config_get(ssid, field);
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (value) {
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_config_write_reg_string(hk, field, value);
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(value);
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id)
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i, errors = 0;
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY nhk, netw;
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR name[5];
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_CREATE_SUB_KEY, &nhk);
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not open networks key "
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "for subkey addition: error 0x%x (%d)",
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned int) ret, (int) GetLastError());
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wsprintf(name, L"%04d", id);
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(name, sizeof(name), "%04d", id);
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegCreateKeyEx(nhk, name, 0, NULL, 0, KEY_WRITE, NULL, &netw,
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     NULL);
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(nhk);
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not add network key '%s':"
809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   " error 0x%x (%d)",
810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   name, (unsigned int) ret, (int) GetLastError());
811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define STR(t) write_str(netw, #t, ssid)
815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT(t) write_int(netw, #t, ssid->t, 0)
816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INTe(t) write_int(netw, #t, ssid->eap.t, 0)
817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT_DEF(t, def) write_int(netw, #t, ssid->t, def)
818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define INT_DEFe(t, def) write_int(netw, #t, ssid->eap.t, def)
819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ssid);
821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(scan_ssid);
822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_bssid(netw, ssid);
823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_psk(netw, ssid);
824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_proto(netw, ssid);
825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_key_mgmt(netw, ssid);
826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_pairwise(netw, ssid);
827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_group(netw, ssid);
828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_auth_alg(netw, ssid);
829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef IEEE8021X_EAPOL
830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	write_eap(netw, ssid);
831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(identity);
832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(anonymous_identity);
833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(password);
834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert);
835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_path);
836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(client_cert);
837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key);
838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key_passwd);
839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(dh_file);
840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(subject_match);
841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(altsubject_match);
842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert2);
843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_path2);
844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(client_cert2);
845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key2);
846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(private_key2_passwd);
847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(dh_file2);
848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(subject_match2);
849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(altsubject_match2);
850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(phase1);
851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(phase2);
852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pcsc);
853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pin);
854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(engine_id);
855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(key_id);
856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(cert_id);
857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert_id);
858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(key2_id);
859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pin2);
860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(engine2_id);
861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(cert2_id);
862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(ca_cert2_id);
863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INTe(engine);
864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INTe(engine2);
865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* IEEE8021X_EAPOL */
867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < 4; i++)
868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		write_wep_key(netw, i, ssid);
869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(wep_tx_keyidx);
870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(priority);
871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef IEEE8021X_EAPOL
872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(pac_file);
874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT_DEFe(fragment_size, DEFAULT_FRAGMENT_SIZE);
875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* IEEE8021X_EAPOL */
876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(mode);
877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(proactive_key_caching);
878526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(disabled);
879526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(peerkey);
880526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef CONFIG_IEEE80211W
881526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	INT(ieee80211w);
882526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* CONFIG_IEEE80211W */
883526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	STR(id_str);
884526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
885526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef STR
886526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef INT
887526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#undef INT_DEF
888526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
889526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(netw);
890526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
891526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return errors ? -1 : 0;
892526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
893526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
894526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
895526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_config_write_blob(HKEY hk, struct wpa_config_blob *blob)
896526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
897526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY bhk;
898526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
899526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR *name;
900526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
901526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegCreateKeyEx(hk, TEXT("blobs"), 0, NULL, 0, KEY_WRITE, NULL,
902526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			     &bhk, NULL);
903526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
904526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "WINREG: Could not add blobs key: "
905526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "error 0x%x (%d)",
906526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (unsigned int) ret, (int) GetLastError());
907526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
908526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
909526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
910526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	name = wpa_strdup_tchar(blob->name);
911526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegSetValueEx(bhk, name, 0, REG_BINARY, blob->data,
912526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			    blob->len);
913526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
914526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "WINREG: Failed to set blob %s': "
915526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "error 0x%x (%d)", blob->name, (unsigned int) ret,
916526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
917526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		RegCloseKey(bhk);
918526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(name);
919526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
920526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
921526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(name);
922526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
923526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(bhk);
924526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
925526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
926526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
927526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
928526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
929526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint wpa_config_write(const char *name, struct wpa_config *config)
930526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
931526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	TCHAR buf[256];
932526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HKEY hk;
933526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG ret;
934526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int errors = 0;
935526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_ssid *ssid;
936526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct wpa_config_blob *blob;
937526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int id;
938526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
939526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
940526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
941526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef UNICODE
942526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name);
943526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#else /* UNICODE */
944526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name);
945526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* UNICODE */
946526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
947526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_SET_VALUE | DELETE, &hk);
948526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ret != ERROR_SUCCESS) {
949526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Could not open wpa_supplicant "
950526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "configuration registry %s: error %d", buf,
951526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
952526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
953526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
954526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
955526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wpa_config_write_global(config, hk)) {
956526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Failed to write global configuration "
957526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "data");
958526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		errors++;
959526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
960526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
961526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_config_delete_subkeys(hk, TEXT("networks"));
962526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) {
963526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
964526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue; /* do not save temporary WPS networks */
965526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wpa_config_write_network(hk, ssid, id))
966526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
967526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
968526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
969526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegDeleteKey(hk, TEXT("blobs"));
970526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (blob = config->blobs; blob; blob = blob->next) {
971526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wpa_config_write_blob(hk, blob))
972526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			errors++;
973526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
974526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
975526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	RegCloseKey(hk);
976526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
977526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Configuration '%s' written %ssuccessfully",
978526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   name, errors ? "un" : "");
979526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return errors ? -1 : 0;
980526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
981