Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1044 lines
36 KiB

  1. #include <precomp.h>
  2. #include "tracing.h"
  3. #include "utils.h"
  4. #include "intflist.h"
  5. #include "hash.h"
  6. #include "storage.h"
  7. #include "rpcsrv.h"
  8. #include "wzcsvc.h"
  9. //-----------------------------------------------------------
  10. // Loads per interface configuration parameters to the persistent
  11. // storage.
  12. // Parameters:
  13. // hkRoot
  14. // [in] Opened registry key to the "...WZCSVC\Parameters" location
  15. // pIntf
  16. // [in] Interface context to load from the registry
  17. // Returned value:
  18. // Win32 error code
  19. DWORD
  20. StoLoadIntfConfig(
  21. HKEY hkRoot,
  22. PINTF_CONTEXT pIntfContext)
  23. {
  24. DWORD dwErr = ERROR_SUCCESS;
  25. HKEY hkIntf = NULL;
  26. LPWSTR pKeyName = NULL;
  27. UINT nLength;
  28. UINT nType;
  29. DWORD dwData;
  30. DWORD dwVersion;
  31. UINT nEntries;
  32. RAW_DATA rdBuffer = {0, NULL};
  33. DWORD dwGuidLen = 0;
  34. DbgPrint((TRC_TRACK|TRC_STORAGE,"[StoLoadIntfConfig(%S)",
  35. (pIntfContext->wszGuid == NULL)? L"Global" : pIntfContext->wszGuid));
  36. if (pIntfContext->wszGuid != NULL)
  37. dwGuidLen = wcslen(pIntfContext->wszGuid) + 1;
  38. if (hkRoot == NULL)
  39. {
  40. // if no root has been provided allocate space for the absolute path to WZC params,
  41. // the relative path to the interfaces location, the guid plus 2 '\' and one null terminator
  42. pKeyName = MemCAlloc((
  43. wcslen(WZCREGK_ABS_PARAMS) +
  44. dwGuidLen +
  45. wcslen(WZCREGK_REL_INTF) +
  46. 2)*sizeof(WCHAR));
  47. if (pKeyName == 0)
  48. {
  49. dwErr = GetLastError();
  50. goto exit;
  51. }
  52. if (dwGuidLen != 0)
  53. wsprintf(pKeyName,L"%s\\%s\\%s", WZCREGK_ABS_PARAMS, WZCREGK_REL_INTF, pIntfContext->wszGuid);
  54. else
  55. wsprintf(pKeyName,L"%s\\%s", WZCREGK_ABS_PARAMS, WZCREGK_REL_INTF);
  56. hkRoot = HKEY_LOCAL_MACHINE;
  57. }
  58. else
  59. {
  60. // if a root has been provided, allocate space just for the "Interfaces\{guid}"
  61. // add 2 wchars: one for the '\' after 'Interfaces' and one for the null terminator
  62. pKeyName = MemCAlloc((wcslen(WZCREGK_REL_INTF) + dwGuidLen + 1)*sizeof(WCHAR));
  63. if (pKeyName == NULL)
  64. {
  65. dwErr = GetLastError();
  66. goto exit;
  67. }
  68. // create the local key name
  69. if (dwGuidLen != 0)
  70. wsprintf(pKeyName,L"%s\\%s", WZCREGK_REL_INTF, pIntfContext->wszGuid);
  71. else
  72. wsprintf(pKeyName,L"%s", WZCREGK_REL_INTF);
  73. }
  74. // open the interface's key first
  75. dwErr = RegOpenKeyEx(
  76. hkRoot,
  77. pKeyName,
  78. 0,
  79. KEY_READ,
  80. &hkIntf);
  81. // break out if not successful
  82. if (dwErr != ERROR_SUCCESS)
  83. {
  84. // if the key is not there, no harm, go on with the defaults
  85. if (dwErr == ERROR_FILE_NOT_FOUND)
  86. dwErr = ERROR_SUCCESS;
  87. goto exit;
  88. }
  89. // get first the whole number of values in this key and the size of the largest data
  90. dwErr = RegQueryInfoKey(
  91. hkIntf, // handle to key
  92. NULL, // class buffer
  93. NULL, // size of class buffer
  94. NULL, // reserved
  95. NULL, // number of subkeys
  96. NULL, // longest subkey name
  97. NULL, // longest class string
  98. &nEntries, // number of value entries
  99. NULL, // longest value name
  100. &rdBuffer.dwDataLen, // longest value data
  101. NULL, // descriptor length
  102. NULL); // last write time
  103. // this call should better be not failing
  104. if (dwErr != ERROR_SUCCESS)
  105. goto exit;
  106. // if there are no keys at all, exit now.
  107. if (rdBuffer.dwDataLen == 0)
  108. goto exit;
  109. // prepare the receiving buffer for the size of the largest data
  110. // this will be used when reading in the active settings and each
  111. // of the static configurations
  112. rdBuffer.pData = MemCAlloc(rdBuffer.dwDataLen);
  113. if (rdBuffer.pData == NULL)
  114. {
  115. dwErr = GetLastError();
  116. goto exit;
  117. }
  118. // load the registry layout version information
  119. // don't worry about the return code. In case of any error,
  120. // we'll assume we deal with the latest registry layout
  121. nLength = sizeof(DWORD);
  122. dwVersion = REG_LAYOUT_VERSION;
  123. dwErr = RegQueryValueEx(
  124. hkIntf,
  125. WZCREGV_VERSION,
  126. 0,
  127. &nType,
  128. (LPBYTE)&dwVersion,
  129. &nLength);
  130. // load the interface's control flags
  131. nLength = sizeof(DWORD);
  132. dwData = 0;
  133. dwErr = RegQueryValueEx(
  134. hkIntf,
  135. WZCREGV_CTLFLAGS,
  136. 0,
  137. &nType,
  138. (LPBYTE)&dwData,
  139. &nLength);
  140. // if this entry is not there, no harm, rely on defaults
  141. // break out only in case of any other error
  142. if (dwErr != ERROR_SUCCESS && dwErr != ERROR_FILE_NOT_FOUND)
  143. goto exit;
  144. // copy the control flags to the INTF_CONTEXT only in the case the registry entry
  145. // has the REG_DWORD type and the right length
  146. if (dwErr == ERROR_SUCCESS &&
  147. nType == REG_DWORD &&
  148. nLength == sizeof(REG_DWORD))
  149. {
  150. pIntfContext->dwCtlFlags = dwData & INTFCTL_PUBLIC_MASK;
  151. }
  152. // load the last active settings
  153. //
  154. // NOTE: loading the whole set of parameters from below (excluding here the static list)
  155. // could be useless since these params should come directly from querying the driver. However
  156. // we load them here in the attemt to restore a previously saved state - at some point this
  157. // information could be useful in the configuration selection logic.
  158. //
  159. ZeroMemory(&pIntfContext->wzcCurrent, sizeof(WZC_WLAN_CONFIG));
  160. pIntfContext->wzcCurrent.Length = sizeof(WZC_WLAN_CONFIG);
  161. dwErr = StoLoadWZCConfig(
  162. hkIntf,
  163. NULL, // not passing a GUID here means don't mess with 802.1X setting!
  164. dwVersion,
  165. WZCREGV_INTFSETTINGS,
  166. &pIntfContext->wzcCurrent,
  167. &rdBuffer);
  168. // if this entry is not there, no harm, rely on defaults
  169. // break out in case of any other error
  170. if (dwErr != ERROR_SUCCESS && dwErr != ERROR_FILE_NOT_FOUND)
  171. goto exit;
  172. // load the static configurations for this interface
  173. dwErr = StoLoadStaticConfigs(
  174. hkIntf,
  175. nEntries,
  176. pIntfContext,
  177. dwVersion,
  178. &rdBuffer);
  179. DbgAssert((dwErr == ERROR_SUCCESS, "Failed to load the static configurations"));
  180. exit:
  181. if (hkIntf != NULL)
  182. RegCloseKey(hkIntf);
  183. MemFree(pKeyName);
  184. MemFree(rdBuffer.pData);
  185. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoLoadIntfConfig]=%d", dwErr));
  186. return dwErr;
  187. }
  188. //-----------------------------------------------------------
  189. // Loads the list of the static configurations from the registry
  190. // Parameters:
  191. // hkRoot
  192. // [in] Opened registry key to the "...WZCSVC\Parameters\Interfaces\{guid}" location
  193. // nEntries
  194. // [in] Number of registry entries in the above reg key
  195. // pIntf
  196. // [in] Interface context to load the static list into
  197. // dwRegLayoutVer
  198. // [in] the version of the registry layout
  199. // prdBuffer
  200. // [in] assumed large enough for getting any static config
  201. // Returned value:
  202. // Win32 error code
  203. DWORD
  204. StoLoadStaticConfigs(
  205. HKEY hkIntf,
  206. UINT nEntries,
  207. PINTF_CONTEXT pIntfContext,
  208. DWORD dwRegLayoutVer,
  209. PRAW_DATA prdBuffer)
  210. {
  211. DWORD dwErr = ERROR_SUCCESS;
  212. UINT nPrefrd, nIdx;
  213. WCHAR wszStConfigName[sizeof(WZCREGV_STSETTINGS)/sizeof(WCHAR)];
  214. LPWSTR pwszStConfigNum;
  215. PWZC_WLAN_CONFIG pwzcPArray = NULL;
  216. UINT nStructSize = (dwRegLayoutVer == REG_LAYOUT_VERSION) ?
  217. sizeof(WZC_WLAN_CONFIG) :
  218. FIELD_OFFSET(WZC_WLAN_CONFIG, rdUserData);
  219. DbgPrint((TRC_TRACK|TRC_STORAGE,"[StoLoadStaticConfigs"));
  220. // we need to scan all the entries named "Static#0001, Static#0002, etc". We could assume
  221. // they are numbered sequentially, but if we want to be smart we can't rely on this assumption.
  222. // There could be a user intervention there (i.e deleting by hand some of the configs directly
  223. // from the registry hence breaking the sequence).
  224. // So, what we'll do is:
  225. // 1. allocate a buffer large enough to hold so many static configs.
  226. // 2. iterate through all the values - if a value is Static#** and has the right length, type,
  227. // and value, copy it in the buffer and keep a count of them.
  228. // 3. copy the exact number of static configs to the INTF_CONTEXT allocating as much memory
  229. // as needed.
  230. // get the estimated memory for all the static entries.
  231. pwzcPArray = (PWZC_WLAN_CONFIG) MemCAlloc(nEntries * sizeof(WZC_WLAN_CONFIG));
  232. if (pwzcPArray == NULL)
  233. {
  234. dwErr = GetLastError();
  235. goto exit;
  236. }
  237. // build the prefix for the static configuration's name
  238. wcscpy(wszStConfigName, WZCREGV_STSETTINGS);
  239. pwszStConfigNum = wcschr(wszStConfigName, REG_STSET_DELIM);
  240. // iterate through the whole set of entries in this key
  241. for (nIdx = 0, nPrefrd = 0;
  242. nIdx < nEntries && nPrefrd < nEntries;
  243. nIdx++)
  244. {
  245. // complete the configuration's name
  246. wsprintf(pwszStConfigNum, L"%04x", nIdx);
  247. dwErr = StoLoadWZCConfig(
  248. hkIntf,
  249. pIntfContext->wszGuid,
  250. dwRegLayoutVer,
  251. wszStConfigName,
  252. &(pwzcPArray[nPrefrd]),
  253. prdBuffer);
  254. if (dwErr == ERROR_SUCCESS)
  255. nPrefrd++;
  256. }
  257. DbgPrint((TRC_STORAGE,"Uploading %d static configurations", nPrefrd));
  258. // no matter what error we might have had till now, we can safely reset it.
  259. dwErr = ERROR_SUCCESS;
  260. // here, pwzcPArray has nPrefrd static configurations, in the correct order
  261. if (pIntfContext->pwzcPList != NULL)
  262. MemFree(pIntfContext->pwzcPList);
  263. // if there is anything to upload into the INTF_CONTEXT, do it now
  264. if (nPrefrd > 0)
  265. {
  266. pIntfContext->pwzcPList = (PWZC_802_11_CONFIG_LIST)
  267. MemCAlloc(sizeof(WZC_802_11_CONFIG_LIST) + (nPrefrd-1)*sizeof(WZC_WLAN_CONFIG));
  268. if (pIntfContext->pwzcPList == NULL)
  269. {
  270. dwErr = GetLastError();
  271. goto exit;
  272. }
  273. pIntfContext->pwzcPList->NumberOfItems = nPrefrd;
  274. pIntfContext->pwzcPList->Index = nPrefrd;
  275. memcpy(&(pIntfContext->pwzcPList->Config), pwzcPArray, nPrefrd*sizeof(WZC_WLAN_CONFIG));
  276. }
  277. exit:
  278. if (pwzcPArray != NULL)
  279. MemFree(pwzcPArray);
  280. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoLoadStaticConfigs]=%d", dwErr));
  281. return dwErr;
  282. }
  283. //-----------------------------------------------------------
  284. // Saves all the configuration parameters to the persistant
  285. // storage (registry in our case).
  286. // Uses the global external g_lstIntfHashes.
  287. // Returned value:
  288. // Win32 error code
  289. DWORD
  290. StoSaveConfig()
  291. {
  292. DWORD dwErr = ERROR_SUCCESS;
  293. HKEY hkRoot = NULL;
  294. PLIST_ENTRY pEntry;
  295. DbgPrint((TRC_TRACK|TRC_STORAGE,"[StoSaveConfig"));
  296. // open the root key first
  297. dwErr = RegCreateKeyExW(
  298. HKEY_LOCAL_MACHINE,
  299. WZCREGK_ABS_PARAMS,
  300. 0,
  301. NULL,
  302. 0,
  303. KEY_WRITE,
  304. NULL,
  305. &hkRoot,
  306. NULL);
  307. // failure at this point breaks the function
  308. if (dwErr != ERROR_SUCCESS)
  309. goto exit;
  310. if (g_lstIntfHashes.bValid)
  311. {
  312. // lock the hashes since we're iterating through all
  313. // the interfaces contexts
  314. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  315. for (pEntry = g_lstIntfHashes.lstIntfs.Flink;
  316. pEntry != &g_lstIntfHashes.lstIntfs;
  317. pEntry = pEntry->Flink)
  318. {
  319. PINTF_CONTEXT pIntfContext;
  320. pIntfContext = CONTAINING_RECORD(pEntry, INTF_CONTEXT, Link);
  321. // save per interface configuration settings
  322. dwErr = StoSaveIntfConfig(hkRoot, pIntfContext);
  323. if (dwErr != ERROR_SUCCESS)
  324. {
  325. // some event logging should be added here in the future
  326. DbgAssert((FALSE, "Couldn't save interface configuration. Ignore and go on!"));
  327. dwErr = ERROR_SUCCESS;
  328. }
  329. }
  330. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  331. }
  332. if (g_wzcInternalCtxt.bValid)
  333. {
  334. //Save users preferences
  335. EnterCriticalSection(&g_wzcInternalCtxt.csContext);
  336. dwErr = StoSaveWZCContext(hkRoot, &g_wzcInternalCtxt.wzcContext);
  337. DbgAssert((dwErr == ERROR_SUCCESS, "Couldn't save service context. Ignore and go on!"));
  338. // save the global interface template
  339. dwErr = StoSaveIntfConfig(NULL, g_wzcInternalCtxt.pIntfTemplate);
  340. DbgAssert((dwErr == ERROR_SUCCESS, "Couldn't save the global interface template. Ignore and go on!"));
  341. dwErr = ERROR_SUCCESS;
  342. LeaveCriticalSection(&g_wzcInternalCtxt.csContext);
  343. }
  344. exit:
  345. if (hkRoot != NULL)
  346. RegCloseKey(hkRoot);
  347. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoSaveConfig]=%d", dwErr));
  348. return dwErr;
  349. }
  350. //-----------------------------------------------------------
  351. // Saves per interface configuration parameters to the persistant
  352. // storage.
  353. // Parameters:
  354. // hkRoot
  355. // [in] Opened registry key to the "...WZCSVC\Parameters" location
  356. // pIntf
  357. // [in] Interface context to save to the registry
  358. // Returned value:
  359. // Win32 error code
  360. DWORD
  361. StoSaveIntfConfig(
  362. HKEY hkRoot,
  363. PINTF_CONTEXT pIntfContext)
  364. {
  365. DWORD dwErr = ERROR_SUCCESS;
  366. HKEY hkIntf = NULL;
  367. LPWSTR pKeyName = NULL;
  368. DWORD dwLayoutVer = REG_LAYOUT_VERSION;
  369. DWORD dwCtlFlags;
  370. RAW_DATA rdBuffer = {0, NULL};
  371. DWORD dwGuidLen = 0;
  372. DbgPrint((TRC_TRACK|TRC_STORAGE,"[StoSaveIntfConfig(%S)",
  373. (pIntfContext->wszGuid == NULL) ? L"Global" : pIntfContext->wszGuid));
  374. if (pIntfContext == NULL)
  375. {
  376. dwErr = ERROR_INVALID_PARAMETER;
  377. goto exit;
  378. }
  379. if (pIntfContext->wszGuid != NULL)
  380. dwGuidLen = wcslen(pIntfContext->wszGuid) + 1;
  381. if (hkRoot == NULL)
  382. {
  383. // if no root has been provided allocate space for the absolute path to WZC params,
  384. // the relative path to the interfaces location, the guid plus 2 '\' and one null terminator
  385. pKeyName = MemCAlloc((
  386. wcslen(WZCREGK_ABS_PARAMS) +
  387. dwGuidLen +
  388. wcslen(WZCREGK_REL_INTF) +
  389. 2)*sizeof(WCHAR));
  390. if (pKeyName == 0)
  391. {
  392. dwErr = GetLastError();
  393. goto exit;
  394. }
  395. if (dwGuidLen != 0)
  396. wsprintf(pKeyName,L"%s\\%s\\%s", WZCREGK_ABS_PARAMS, WZCREGK_REL_INTF, pIntfContext->wszGuid);
  397. else
  398. wsprintf(pKeyName,L"%s\\%s", WZCREGK_ABS_PARAMS, WZCREGK_REL_INTF);
  399. hkRoot = HKEY_LOCAL_MACHINE;
  400. }
  401. else
  402. {
  403. // if a root has been provided, allocate space just for the "Interfaces\{guid}"
  404. // add 2 wchars: one for the '\' after 'Interfaces' and one for the null terminator
  405. pKeyName = MemCAlloc((dwGuidLen + wcslen(WZCREGK_REL_INTF) + 1)*sizeof(WCHAR));
  406. if (pKeyName == NULL)
  407. {
  408. dwErr = GetLastError();
  409. goto exit;
  410. }
  411. // create the local key name
  412. if (dwGuidLen != 0)
  413. wsprintf(pKeyName,L"%s\\%s", WZCREGK_REL_INTF, pIntfContext->wszGuid);
  414. else
  415. wsprintf(pKeyName,L"%s", WZCREGK_REL_INTF);
  416. }
  417. // open the interface's key first
  418. dwErr = RegCreateKeyExW(
  419. hkRoot,
  420. pKeyName,
  421. 0,
  422. NULL,
  423. 0,
  424. KEY_QUERY_VALUE | KEY_WRITE,
  425. NULL,
  426. &hkIntf,
  427. NULL);
  428. // failure at this point breaks the function
  429. if (dwErr != ERROR_SUCCESS)
  430. goto exit;
  431. // set the registry layout version value
  432. dwErr = RegSetValueEx(
  433. hkIntf,
  434. WZCREGV_VERSION,
  435. 0,
  436. REG_DWORD,
  437. (LPBYTE)&dwLayoutVer,
  438. sizeof(DWORD));
  439. DbgAssert((dwErr == ERROR_SUCCESS, "Can't write %S=%d to the registry", WZCREGV_VERSION, dwLayoutVer));
  440. // set the interface's control flags only if they are not volatile
  441. dwCtlFlags = pIntfContext->dwCtlFlags;
  442. if (!(dwCtlFlags & INTFCTL_VOLATILE))
  443. {
  444. dwCtlFlags &= ~INTFCTL_OIDSSUPP;
  445. dwErr = RegSetValueEx(
  446. hkIntf,
  447. WZCREGV_CTLFLAGS,
  448. 0,
  449. REG_DWORD,
  450. (LPBYTE)&dwCtlFlags,
  451. sizeof(DWORD));
  452. DbgAssert((dwErr == ERROR_SUCCESS, "Can't write %S=0x%08x to the registry", WZCREGV_CTLFLAGS, pIntfContext->dwCtlFlags));
  453. }
  454. // we're done here, write the current WZC configuration to the registry
  455. dwErr = StoSaveWZCConfig(
  456. hkIntf,
  457. WZCREGV_INTFSETTINGS,
  458. &pIntfContext->wzcCurrent,
  459. &rdBuffer);
  460. DbgAssert((dwErr == ERROR_SUCCESS, "Can't save active settings"));
  461. // update the list of static configurations
  462. dwErr = StoUpdateStaticConfigs(
  463. hkIntf,
  464. pIntfContext,
  465. &rdBuffer);
  466. DbgAssert((dwErr == ERROR_SUCCESS, "Can't update the list of static configurations"));
  467. exit:
  468. if (hkIntf != NULL)
  469. RegCloseKey(hkIntf);
  470. MemFree(pKeyName);
  471. MemFree(rdBuffer.pData);
  472. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoSaveIntfConfig]=%d", dwErr));
  473. return dwErr;
  474. }
  475. //-----------------------------------------------------------
  476. // Updates the list of static configurations for the given interface in the
  477. // persistant storage. The new list is saved, whatever configuration was removed
  478. // is taken out of the persistant storage.
  479. // Parameters:
  480. // hkRoot
  481. // [in] Opened registry key to the "...WZCSVC\Parameters\Interfaces\{guid}" location
  482. // pIntf
  483. // [in] Interface context to take the static list from
  484. // prdBuffer
  485. // [in/out] buffer to be used for preparing the registry blobs
  486. // Returned value:
  487. // Win32 error code
  488. DWORD
  489. StoUpdateStaticConfigs(
  490. HKEY hkIntf,
  491. PINTF_CONTEXT pIntfContext,
  492. PRAW_DATA prdBuffer)
  493. {
  494. DWORD dwErr = ERROR_SUCCESS;
  495. DWORD dwLocalErr = ERROR_SUCCESS;
  496. UINT nEntries, nIdx;
  497. WCHAR wszStConfigName[sizeof(WZCREGV_STSETTINGS)/sizeof(WCHAR)];
  498. LPWSTR pwszStConfigNum;
  499. DbgPrint((TRC_TRACK|TRC_STORAGE,"[StoUpdateStaticConfigs"));
  500. // get the initial number of values in this registry key
  501. dwErr = RegQueryInfoKey(
  502. hkIntf, // handle to key
  503. NULL, // class buffer
  504. NULL, // size of class buffer
  505. NULL, // reserved
  506. NULL, // number of subkeys
  507. NULL, // longest subkey name
  508. NULL, // longest class string
  509. &nEntries, // number of value entries
  510. NULL, // longest value name
  511. NULL, // longest value data
  512. NULL, // descriptor length
  513. NULL); // last write time
  514. if (dwErr != ERROR_SUCCESS)
  515. goto exit;
  516. // build the prefix for the static configuration's name
  517. wcscpy(wszStConfigName, WZCREGV_STSETTINGS);
  518. pwszStConfigNum = wcschr(wszStConfigName, REG_STSET_DELIM);
  519. nIdx = 0;
  520. if (pIntfContext->pwzcPList != NULL)
  521. {
  522. UINT i;
  523. for (i = 0;
  524. i < pIntfContext->pwzcPList->NumberOfItems && i < REG_STSET_MAX;
  525. i++)
  526. {
  527. if (pIntfContext->pwzcPList->Config[i].dwCtlFlags & WZCCTL_VOLATILE)
  528. continue;
  529. // complete the configuration's name
  530. wsprintf(pwszStConfigNum, L"%04x", nIdx++);
  531. // save the configuration to the registry
  532. dwLocalErr = StoSaveWZCConfig(
  533. hkIntf,
  534. wszStConfigName,
  535. &(pIntfContext->pwzcPList->Config[i]),
  536. prdBuffer);
  537. DbgAssert((dwLocalErr == ERROR_SUCCESS,
  538. "Failed to save static configuration 0x%x. err=%d",
  539. i, dwLocalErr));
  540. if (dwErr == ERROR_SUCCESS && dwLocalErr != ERROR_SUCCESS)
  541. dwErr = dwLocalErr;
  542. }
  543. }
  544. // delete now whatever remaining static
  545. // configurations might still be in the registry
  546. do
  547. {
  548. // complete the configuration's name
  549. wsprintf(pwszStConfigNum, L"%04x", nIdx);
  550. // and attempt to delete it - at some point
  551. // we should get back ERROR_FILE_NOT_FOUND
  552. dwLocalErr = RegDeleteValue(
  553. hkIntf,
  554. wszStConfigName);
  555. nIdx++;
  556. } while (nIdx < nEntries);
  557. exit:
  558. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoUpdateStaticConfigs]=%d", dwErr));
  559. return dwErr;
  560. }
  561. // externalities from 802.1X
  562. DWORD
  563. ElSetInterfaceParams (
  564. IN WCHAR *pwszGUID,
  565. IN EAPOL_INTF_PARAMS *pIntfParams
  566. );
  567. DWORD
  568. ElGetInterfaceParams (
  569. IN WCHAR *pwszGUID,
  570. IN OUT EAPOL_INTF_PARAMS *pIntfParams
  571. );
  572. //-----------------------------------------------------------
  573. // Loads from the registry a WZC Configuration, un-protects the WEP key field
  574. // and stores the result in the output param pWzcCfg.
  575. // Parameters:
  576. // hkCfg
  577. // [in] Opened registry key to load the WZC configuration from
  578. // dwRegLayoutVer,
  579. // [in] registry layout version
  580. // wszCfgName
  581. // [in] registry entry name for the WZC configuration
  582. // pWzcCfg
  583. // [out] pointer to a WZC_WLAN_CONFIG object that receives the registry data
  584. // prdBuffer
  585. // [in] allocated buffer, assumed large enough for getting the registry data!
  586. DWORD
  587. StoLoadWZCConfig(
  588. HKEY hkCfg,
  589. LPWSTR wszGuid,
  590. DWORD dwRegLayoutVer,
  591. LPWSTR wszCfgName,
  592. PWZC_WLAN_CONFIG pWzcCfg,
  593. PRAW_DATA prdBuffer)
  594. {
  595. DWORD dwErr = ERROR_SUCCESS;
  596. UINT nType, nLength;
  597. DbgPrint((TRC_TRACK|TRC_STORAGE,"[StoLoadWZCConfig(\"%S\")", wszCfgName));
  598. DbgAssert((prdBuffer != NULL, "No buffer provided for loading the registry blob!"));
  599. // zero out the buffer and get the value from the registry
  600. ZeroMemory(prdBuffer->pData, prdBuffer->dwDataLen);
  601. nLength = prdBuffer->dwDataLen;
  602. dwErr = RegQueryValueEx(
  603. hkCfg,
  604. wszCfgName,
  605. 0,
  606. &nType,
  607. prdBuffer->pData,
  608. &nLength);
  609. if (dwErr == ERROR_SUCCESS)
  610. {
  611. switch(dwRegLayoutVer)
  612. {
  613. case REG_LAYOUT_LEGACY_1:
  614. // first legacy code (WinXP Beta2)
  615. if (nType == REG_BINARY && nLength == FIELD_OFFSET(WZC_WLAN_CONFIG, rdUserData))
  616. {
  617. memcpy(pWzcCfg, prdBuffer->pData, nLength);
  618. if (pWzcCfg->Length == nLength)
  619. {
  620. pWzcCfg->Length = sizeof(WZC_WLAN_CONFIG);
  621. pWzcCfg->AuthenticationMode = NWB_GET_AUTHMODE(pWzcCfg);
  622. pWzcCfg->Reserved[0] = pWzcCfg->Reserved[1] = 0;
  623. }
  624. else
  625. dwErr = ERROR_INVALID_DATA;
  626. }
  627. else
  628. dwErr = ERROR_INVALID_DATA;
  629. break;
  630. case REG_LAYOUT_LEGACY_2:
  631. // second legacy code (WinXP 2473)
  632. if (nType == REG_BINARY && nLength == sizeof(WZC_WLAN_CONFIG))
  633. {
  634. memcpy(pWzcCfg, prdBuffer->pData, nLength);
  635. if (pWzcCfg->Length != nLength)
  636. dwErr = ERROR_INVALID_DATA;
  637. }
  638. break;
  639. case REG_LAYOUT_LEGACY_3:
  640. case REG_LAYOUT_VERSION:
  641. // revert the logic: assume failure (ERROR_INVALID_DATA) and
  642. // explictly set success if the case is
  643. dwErr = ERROR_INVALID_DATA;
  644. if (nType == REG_BINARY && nLength > sizeof(WZC_WLAN_CONFIG))
  645. {
  646. memcpy(pWzcCfg, prdBuffer->pData, sizeof(WZC_WLAN_CONFIG));
  647. if (pWzcCfg->Length == sizeof(WZC_WLAN_CONFIG))
  648. {
  649. DATA_BLOB blobIn, blobOut;
  650. blobIn.cbData = nLength - sizeof(WZC_WLAN_CONFIG);
  651. blobIn.pbData = prdBuffer->pData + sizeof(WZC_WLAN_CONFIG);
  652. blobOut.cbData = 0;
  653. blobOut.pbData = NULL;
  654. if (CryptUnprotectData(
  655. &blobIn,
  656. NULL,
  657. NULL,
  658. NULL,
  659. NULL,
  660. 0,
  661. &blobOut) &&
  662. blobOut.cbData == WZCCTL_MAX_WEPK_MATERIAL)
  663. {
  664. memcpy(pWzcCfg->KeyMaterial, blobOut.pbData, blobOut.cbData);
  665. // now this is success
  666. dwErr = ERROR_SUCCESS;
  667. }
  668. if (blobOut.pbData != NULL)
  669. {
  670. RtlSecureZeroMemory(blobOut.pbData, blobOut.cbData);
  671. LocalFree(blobOut.pbData);
  672. }
  673. }
  674. }
  675. // for now don't read anything - rely on defaults;
  676. break;
  677. default:
  678. dwErr = ERROR_BAD_FORMAT;
  679. }
  680. }
  681. // if everything went up fine and this is an infrastructure network and
  682. // we're in some legacy registry layout.. make sure to disable 802.1X in
  683. // the following cases:
  684. if (dwErr == ERROR_SUCCESS &&
  685. dwRegLayoutVer <= REG_LAYOUT_LEGACY_3 &&
  686. pWzcCfg->InfrastructureMode != Ndis802_11IBSS &&
  687. wszGuid != NULL)
  688. {
  689. BOOL bDisableOneX = FALSE;
  690. // the Infrastructure network being loaded doesn't require privacy
  691. bDisableOneX = bDisableOneX || (pWzcCfg->Privacy == 0);
  692. // it is Infrastructure with privacy, but some explicit key is also provided..
  693. bDisableOneX = bDisableOneX || (pWzcCfg->dwCtlFlags & WZCCTL_WEPK_PRESENT);
  694. if (bDisableOneX == TRUE)
  695. {
  696. EAPOL_INTF_PARAMS elIntfParams = {0};
  697. elIntfParams.dwSizeOfSSID = pWzcCfg->Ssid.SsidLength;
  698. memcpy(&elIntfParams.bSSID, &pWzcCfg->Ssid.Ssid, pWzcCfg->Ssid.SsidLength);
  699. dwErr = ElGetInterfaceParams (
  700. wszGuid, // wsz GUID
  701. &elIntfParams);
  702. if (dwErr == ERROR_SUCCESS)
  703. {
  704. elIntfParams.dwEapFlags &= ~EAPOL_ENABLED;
  705. dwErr = ElSetInterfaceParams (
  706. wszGuid, // wsz GUID
  707. &elIntfParams);
  708. }
  709. }
  710. }
  711. // if everything went ok so far it means we have loaded pWzcCfg with
  712. // data from the registry.
  713. // Lets check this data is consistent!
  714. if (dwErr == ERROR_SUCCESS)
  715. {
  716. // as the first thing - make sure the configuration's control
  717. // flags don't show it as "Volatile" - such a configuration shouldn't be
  718. // in the registry in the first instance. On upgrade, it might happen to
  719. // have this bit set since once it had a different meaning (the config contains
  720. // a 40bit WEP key) which is now obsolete.
  721. pWzcCfg->dwCtlFlags &= ~WZCCTL_VOLATILE;
  722. // since dwErr is ERROR_SUCCESS, it is guaranteed pWzcCfg
  723. // points to at least the Length field.
  724. dwErr = WZCSvcCheckConfig(pWzcCfg, pWzcCfg->Length);
  725. }
  726. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoLoadWZCConfig]=%d", dwErr));
  727. return dwErr;
  728. }
  729. //-----------------------------------------------------------
  730. // Takes the input param pWzcCfg, protects the WEP key field and stores the
  731. // resulting BLOB into the registry.
  732. // Parameters:
  733. // hkCfg
  734. // [in] Opened registry key to load the WZC configuration from
  735. // wszCfgName
  736. // [in] registry entry name for the WZC configuration
  737. // pWzcCfg
  738. // [in] WZC_WLAN_CONFIG object that is written to the registry
  739. // prdBuffer
  740. // [in/out] allocated buffer, assumed large enough for getting the registry data!
  741. DWORD
  742. StoSaveWZCConfig(
  743. HKEY hkCfg,
  744. LPWSTR wszCfgName,
  745. PWZC_WLAN_CONFIG pWzcCfg,
  746. PRAW_DATA prdBuffer)
  747. {
  748. DWORD dwErr = ERROR_SUCCESS;
  749. DATA_BLOB blobIn, blobOut;
  750. DbgPrint((TRC_TRACK|TRC_STORAGE,"[StoSaveWZCConfig(\"%S\")", wszCfgName));
  751. DbgAssert((prdBuffer != NULL, "No buffer provided for creating the registry blob!"));
  752. blobIn.cbData = WZCCTL_MAX_WEPK_MATERIAL;
  753. blobIn.pbData = &(pWzcCfg->KeyMaterial[0]);
  754. blobOut.cbData = 0;
  755. blobOut.pbData = NULL;
  756. if (!CryptProtectData(
  757. &blobIn, // DATA_BLOB *pDataIn,
  758. L"", // LPCWSTR szDataDescr,
  759. NULL, // DATA_BLOB *pOptionalEntropy,
  760. NULL, // PVOID pvReserved,
  761. NULL, // CRYPTPROTECT_PROMPTSTRUCT *pPromptStrct,
  762. 0, // DWORD dwFlags,
  763. &blobOut)) // DATA_BLOB *pDataOut
  764. dwErr = GetLastError();
  765. DbgAssert((dwErr == ERROR_SUCCESS, "CryptProtectData failed with err=%d", dwErr));
  766. // if crypting the wep key went fine, check if we have enough storage to prepare
  767. // the blob for the registry. If not, allocate as much as needed.
  768. if (dwErr == ERROR_SUCCESS &&
  769. prdBuffer->dwDataLen < sizeof(WZC_WLAN_CONFIG) + blobOut.cbData)
  770. {
  771. MemFree(prdBuffer->pData);
  772. prdBuffer->dwDataLen = 0;
  773. prdBuffer->pData = NULL;
  774. prdBuffer->pData = MemCAlloc(sizeof(WZC_WLAN_CONFIG) + blobOut.cbData);
  775. if (prdBuffer->pData == NULL)
  776. dwErr = GetLastError();
  777. else
  778. prdBuffer->dwDataLen = sizeof(WZC_WLAN_CONFIG) + blobOut.cbData;
  779. }
  780. // now we have the buffer, all what remains is to:
  781. // - copy the WZC_WLAN_CONFIG object into the blob that goes into the registry
  782. // - clean the "clear" WEP key from that blob
  783. // - append the encrypted WEP key to the blob going into the registry
  784. // - write the blob to the registry
  785. if (dwErr == ERROR_SUCCESS)
  786. {
  787. PWZC_WLAN_CONFIG pRegCfg;
  788. memcpy(prdBuffer->pData, pWzcCfg, sizeof(WZC_WLAN_CONFIG));
  789. pRegCfg = (PWZC_WLAN_CONFIG)prdBuffer->pData;
  790. ZeroMemory(pRegCfg->KeyMaterial, WZCCTL_MAX_WEPK_MATERIAL);
  791. memcpy(prdBuffer->pData+sizeof(WZC_WLAN_CONFIG), blobOut.pbData, blobOut.cbData);
  792. dwErr = RegSetValueEx(
  793. hkCfg,
  794. wszCfgName,
  795. 0,
  796. REG_BINARY,
  797. prdBuffer->pData,
  798. prdBuffer->dwDataLen);
  799. }
  800. // cleanup whatever CryptProtectData might have allocated.
  801. if (blobOut.pbData != NULL)
  802. LocalFree(blobOut.pbData);
  803. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoSaveWZCConfig]=%d", dwErr));
  804. return dwErr;
  805. }
  806. // StoLoadWZCContext:
  807. // Description: Loads a context from the registry
  808. // Parameters:
  809. // [out] pwzvCtxt: pointer to a WZC_CONTEXT allocated by user, initialised
  810. // with WZCContextInit. On success, contains values from registry.
  811. // [in] hkRoot, a handle to "...WZCSVC\Parameters"
  812. // Returns: win32 error
  813. DWORD StoLoadWZCContext(HKEY hkRoot, PWZC_CONTEXT pwzcCtxt)
  814. {
  815. BOOL bCloseKey = FALSE;
  816. DWORD dwErr = ERROR_SUCCESS;
  817. DWORD dwcbSize = sizeof(WZC_CONTEXT);
  818. DWORD dwType = REG_BINARY;
  819. WZC_CONTEXT wzcTempCtxt;
  820. DbgPrint((TRC_TRACK|TRC_STORAGE, "[StoLoadWZCContext"));
  821. if (pwzcCtxt == NULL)
  822. {
  823. dwErr = ERROR_INVALID_PARAMETER;
  824. goto exit;
  825. }
  826. if (hkRoot == NULL)
  827. {
  828. // open the root key first
  829. dwErr = RegOpenKeyEx(
  830. HKEY_LOCAL_MACHINE,
  831. WZCREGK_ABS_PARAMS,
  832. 0,
  833. KEY_READ,
  834. &hkRoot);
  835. // if we couldn't find the WZC key, no problem, this is not
  836. // a failure - we'll just have to rely on the default values
  837. if (dwErr == ERROR_FILE_NOT_FOUND)
  838. {
  839. dwErr = ERROR_SUCCESS;
  840. goto exit;
  841. }
  842. // failure at this point breaks the function
  843. if (dwErr != ERROR_SUCCESS)
  844. goto exit;
  845. bCloseKey = TRUE;
  846. }
  847. dwErr = RegQueryValueEx(
  848. hkRoot,
  849. WZCREGV_CONTEXT,
  850. NULL,
  851. &dwType,
  852. (LPBYTE)&wzcTempCtxt,
  853. &dwcbSize);
  854. switch(dwErr)
  855. {
  856. case ERROR_FILE_NOT_FOUND:
  857. /* If there is no registry entry, this is not an error - we rely
  858. * on the defaults. Translate this case to ERROR_SUCCESS.
  859. */
  860. DbgPrint((TRC_STORAGE, "No service context present in the registry!"));
  861. dwErr = ERROR_SUCCESS;
  862. break;
  863. case ERROR_SUCCESS:
  864. // we got our registry values, copy them in the running memory.
  865. memcpy(pwzcCtxt, &wzcTempCtxt, sizeof(WZC_CONTEXT));
  866. break;
  867. default:
  868. // for any other error, it will be bubbled up
  869. DbgAssert((FALSE,"Error %d loading the service's context.", dwErr));
  870. }
  871. exit:
  872. if (TRUE == bCloseKey)
  873. RegCloseKey(hkRoot);
  874. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoLoadWZCContext]=%d", dwErr));
  875. return dwErr;
  876. }
  877. // StoSaveWZCContext:
  878. // Description: Saves a context to the registry. Does not check values. If
  879. // the registry key dosent exist, it is created.
  880. // Parameters: [in] pwzcCtxt, pointer to a valid WZC_CONTEXT
  881. // [in] hkRoot, a handle to "...WZCSVC\Parameters"
  882. // Returns: win32 error
  883. DWORD StoSaveWZCContext(HKEY hkRoot, PWZC_CONTEXT pwzcCtxt)
  884. {
  885. BOOL bCloseKey = FALSE;
  886. DWORD dwErr = ERROR_SUCCESS;
  887. DbgPrint((TRC_TRACK|TRC_STORAGE, "[StoSaveWZCContext"));
  888. if (pwzcCtxt == NULL)
  889. {
  890. dwErr = ERROR_INVALID_PARAMETER;
  891. goto exit;
  892. }
  893. if (NULL == hkRoot)
  894. {
  895. // open the root key first
  896. dwErr = RegOpenKeyEx(
  897. HKEY_LOCAL_MACHINE,
  898. WZCREGK_ABS_PARAMS,
  899. 0,
  900. KEY_READ|KEY_SET_VALUE,
  901. &hkRoot);
  902. // if we couldn't find the WZC key, no problem, this is not
  903. // a failure - we'll just have to rely on the default values
  904. if (dwErr == ERROR_FILE_NOT_FOUND)
  905. {
  906. dwErr = ERROR_SUCCESS;
  907. goto exit;
  908. }
  909. // failure at this point breaks the function
  910. if (dwErr != ERROR_SUCCESS)
  911. goto exit;
  912. bCloseKey = TRUE;
  913. }
  914. dwErr = RegSetValueEx(
  915. hkRoot,
  916. WZCREGV_CONTEXT,
  917. 0,
  918. REG_BINARY,
  919. (LPBYTE) pwzcCtxt,
  920. sizeof(WZC_CONTEXT));
  921. DbgAssert((dwErr == ERROR_SUCCESS, "Error %d saving the service's context.", dwErr));
  922. exit:
  923. if (TRUE == bCloseKey)
  924. RegCloseKey(hkRoot);
  925. DbgPrint((TRC_TRACK|TRC_STORAGE,"StoSaveWZCContext]=%d", dwErr));
  926. return dwErr;
  927. }