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.

2951 lines
116 KiB

  1. #include <precomp.h>
  2. #include "wzcsvc.h"
  3. #include "notify.h"
  4. #include "intflist.h"
  5. #include "tracing.h"
  6. #include "utils.h"
  7. #include "deviceio.h"
  8. #include "storage.h"
  9. #include "zcdblog.h"
  10. // global interfaces list. It has to be initialized to {NULL, NULL} just
  11. // to differentiate the case when the list head was never initialized.
  12. HASH g_hshHandles = {0}; // HASH handing GUID<->Handle mapping; Key = "\DEVICE\{guid}"
  13. INTF_HASHES g_lstIntfHashes = {0}; // set of hashes for all INTF_CONTEXTs
  14. HANDLE g_htmQueue = NULL; // global timer queue
  15. //-----------------------------------------------------------
  16. // Synchronization routines
  17. DWORD
  18. LstRccsReference(PINTF_CONTEXT pIntfContext)
  19. {
  20. DWORD dwErr = ERROR_INVALID_PARAMETER;
  21. DbgPrint((TRC_TRACK,"[LstRccsReference(0x%p)", pIntfContext));
  22. if (pIntfContext)
  23. {
  24. DbgPrint((TRC_SYNC," LstRccsReference 0x%p.refCount=%d", pIntfContext, pIntfContext->rccs.nRefCount));
  25. InterlockedIncrement(&(pIntfContext->rccs.nRefCount));
  26. dwErr = ERROR_SUCCESS;
  27. }
  28. DbgPrint((TRC_TRACK,"LstRccsReference]=%d", dwErr));
  29. return dwErr;
  30. }
  31. DWORD
  32. LstRccsLock(PINTF_CONTEXT pIntfContext)
  33. {
  34. DWORD dwErr = ERROR_INVALID_PARAMETER;
  35. DbgPrint((TRC_TRACK,"[LstRccsLock(0x%p)", pIntfContext));
  36. if (pIntfContext)
  37. {
  38. EnterCriticalSection(&(pIntfContext->rccs.csMutex));
  39. dwErr = ERROR_SUCCESS;
  40. }
  41. DbgPrint((TRC_TRACK,"LstRccsLock]=%d", dwErr));
  42. return dwErr;
  43. }
  44. DWORD
  45. LstRccsUnlockUnref(PINTF_CONTEXT pIntfContext)
  46. {
  47. DWORD dwErr = ERROR_INVALID_PARAMETER;
  48. DbgPrint((TRC_TRACK,"[LstRccsUnlockUnref(0x%p)", pIntfContext));
  49. if (pIntfContext)
  50. {
  51. UINT nLastCount;
  52. // before doing anything, while we're still in the critical section,
  53. // decrement the ref counter and store the result in a local variable
  54. nLastCount = InterlockedDecrement(&(pIntfContext->rccs.nRefCount));
  55. LeaveCriticalSection(&(pIntfContext->rccs.csMutex));
  56. // if we were the last to use this context, efectively destroy it.
  57. DbgPrint((TRC_SYNC," LstRccsUnlockUnref 0x%p.refCount=%d", pIntfContext, nLastCount));
  58. if (nLastCount == 0)
  59. LstDestroyIntfContext(pIntfContext);
  60. dwErr = ERROR_SUCCESS;
  61. }
  62. DbgPrint((TRC_TRACK,"LstRccsUnlockUnref]=%d", dwErr));
  63. return dwErr;
  64. }
  65. //-----------------------------------------------------------
  66. // Intializes all the internal interfaces hashes
  67. DWORD
  68. LstInitIntfHashes()
  69. {
  70. DWORD dwErr = ERROR_SUCCESS;
  71. __try
  72. {
  73. InitializeCriticalSection(&g_lstIntfHashes.csMutex);
  74. g_lstIntfHashes.bValid = TRUE;
  75. }
  76. __except(EXCEPTION_EXECUTE_HANDLER)
  77. {
  78. dwErr = GetExceptionCode();
  79. }
  80. g_lstIntfHashes.pHnGUID = NULL;
  81. InitializeListHead(&g_lstIntfHashes.lstIntfs);
  82. g_lstIntfHashes.nNumIntfs = 0;
  83. return dwErr;
  84. }
  85. //-----------------------------------------------------------
  86. // Destructs all the internal data structures - hash & lists
  87. // This call is done after all the threads confirmed they're done.
  88. DWORD
  89. LstDestroyIntfHashes()
  90. {
  91. DWORD dwErr = ERROR_SUCCESS;
  92. DbgPrint((TRC_TRACK,"[LstDestroyIntfHashes"));
  93. // destruct whatever hashes we have
  94. HshDestructor(g_lstIntfHashes.pHnGUID);
  95. while (!IsListEmpty(&g_lstIntfHashes.lstIntfs))
  96. {
  97. PLIST_ENTRY pEntry;
  98. PINTF_CONTEXT pIntfContext;
  99. pEntry = RemoveHeadList(&g_lstIntfHashes.lstIntfs);
  100. pIntfContext = CONTAINING_RECORD(pEntry, INTF_CONTEXT, Link);
  101. // DevioCloseIntfHandle closes the handle only if it is valid.
  102. // Otherwise noop. pIntfContext is created in LstAddIntfToList
  103. // and there, the handle is initialized to HANDLE_INVALID_VALUE.
  104. // So .. attempting to close the handle here is safe.
  105. // also, this call is done after all the threads are terminated
  106. // meaning that all the ref counts should be already balanced (set
  107. // to 1)
  108. LstDestroyIntfContext(pIntfContext);
  109. }
  110. if (g_lstIntfHashes.bValid)
  111. {
  112. g_lstIntfHashes.bValid = FALSE;
  113. DeleteCriticalSection(&g_lstIntfHashes.csMutex);
  114. }
  115. DbgPrint((TRC_TRACK,"LstDestroyIntfHashes]=%d", dwErr));
  116. return dwErr;
  117. }
  118. //-----------------------------------------------------------
  119. // Intializes the global timer queue
  120. DWORD
  121. LstInitTimerQueue()
  122. {
  123. g_htmQueue = CreateTimerQueue();
  124. return (g_htmQueue == NULL) ? GetLastError() : ERROR_SUCCESS;
  125. }
  126. //-----------------------------------------------------------
  127. // Destructs the global timer queue
  128. DWORD
  129. LstDestroyTimerQueue()
  130. {
  131. DbgPrint((TRC_TRACK|TRC_SYNC,"[LstDestroyTimerQueue"));
  132. if (g_htmQueue != NULL)
  133. {
  134. DeleteTimerQueueEx(g_htmQueue, INVALID_HANDLE_VALUE);
  135. g_htmQueue = NULL;
  136. }
  137. DbgPrint((TRC_TRACK|TRC_SYNC,"LstDestroyTimerQueue]"));
  138. return ERROR_SUCCESS;
  139. }
  140. //-----------------------------------------------------------
  141. // Intializes all the internal data structures. Reads the list of interfaces from
  142. // Ndisuio and gets all the parameters & OIDS.
  143. DWORD
  144. LstLoadInterfaces()
  145. {
  146. DWORD dwErr = ERROR_SUCCESS;
  147. HANDLE hNdisuio = INVALID_HANDLE_VALUE;
  148. INT i;
  149. RAW_DATA rdBuffer;
  150. UINT nRequired = QUERY_BUFFER_SIZE;
  151. rdBuffer.dwDataLen = 0;
  152. rdBuffer.pData = NULL;
  153. DbgPrint((TRC_TRACK,"[LstLoadInterfaces"));
  154. // open the handle to Ndisuio. It should be used throughout
  155. // the adapters iteration
  156. dwErr = DevioGetNdisuioHandle(&hNdisuio);
  157. // since we're going to add a bunch of interface contexts,
  158. // lock the hashes first thing to do
  159. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  160. for (i = 0; dwErr == ERROR_SUCCESS; i++)
  161. {
  162. PNDISUIO_QUERY_BINDING pQueryBinding;
  163. PINTF_CONTEXT pIntfContext = NULL;
  164. // allocate as much buffer as needed by DevioGetIntfBindingByIndex
  165. if (rdBuffer.dwDataLen < nRequired)
  166. {
  167. MemFree(rdBuffer.pData);
  168. rdBuffer.pData = MemCAlloc(nRequired);
  169. if (rdBuffer.pData == NULL)
  170. {
  171. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  172. break;
  173. }
  174. rdBuffer.dwDataLen = nRequired;
  175. }
  176. pQueryBinding = (PNDISUIO_QUERY_BINDING)rdBuffer.pData;
  177. // go get the binding structure for this adapter's index
  178. dwErr = DevioGetIntfBindingByIndex(
  179. hNdisuio,
  180. i,
  181. &rdBuffer);
  182. // if Ndisuio says the buffer is not large enough, increase it with 1K
  183. if (dwErr == ERROR_INSUFFICIENT_BUFFER)
  184. {
  185. // increase the buffer only if it is not obscenely large already
  186. // otherwise just skip this index and move to the next.
  187. if (nRequired < QUERY_BUFFER_MAX)
  188. {
  189. nRequired += QUERY_BUFFER_SIZE;
  190. i--;
  191. }
  192. dwErr = ERROR_SUCCESS;
  193. continue;
  194. }
  195. // if we got back NO_MORE_ITEMS then we did our job successfully
  196. if (dwErr == ERROR_NO_MORE_ITEMS)
  197. {
  198. // translate this error to success and break out
  199. dwErr = ERROR_SUCCESS;
  200. break;
  201. }
  202. // in case any other failure was returned from NDISUIO, just break out
  203. // this SHOULDN'T HAPPEN
  204. if (dwErr != ERROR_SUCCESS)
  205. {
  206. DbgAssert((FALSE,
  207. "DevioGetIntfBindingByIndex failed for interface %d with err=%d", i, dwErr));
  208. break;
  209. }
  210. // go build the INTF_CONTEXT structure, based on
  211. // the binding information (key info for the adapter)
  212. dwErr = LstConstructIntfContext(
  213. pQueryBinding,
  214. &pIntfContext);
  215. if (dwErr == ERROR_SUCCESS)
  216. {
  217. // reference and lock this brand new context
  218. LstRccsReference(pIntfContext);
  219. LstRccsLock(pIntfContext);
  220. // add it to the hashes
  221. dwErr = LstAddIntfToHashes(pIntfContext);
  222. if (dwErr == ERROR_SUCCESS)
  223. {
  224. // and dispatch the eEventAdd
  225. dwErr = StateDispatchEvent(
  226. eEventAdd,
  227. pIntfContext,
  228. NULL);
  229. // clear up the INTFCTL_INTERNAL_BLK_MEDIACONN bit since this is not a media sense handler
  230. pIntfContext->dwCtlFlags &= ~INTFCTL_INTERNAL_BLK_MEDIACONN;
  231. }
  232. // if for any reason hashing or dispatching failed, cleanup the context here
  233. if (dwErr != ERROR_SUCCESS)
  234. LstRemoveIntfContext(pIntfContext);
  235. // we're done with this context, unlock & unref it here.
  236. LstRccsUnlockUnref(pIntfContext);
  237. }
  238. // error happened at this point, recover and go to the next interface
  239. dwErr = ERROR_SUCCESS;
  240. }
  241. // unlock the hashes here
  242. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  243. // close the handle to Ndisuio - if it was opened successfully.
  244. if (hNdisuio != INVALID_HANDLE_VALUE)
  245. CloseHandle(hNdisuio);
  246. // free memory (it handles the case when the pointer is NULL)
  247. MemFree(rdBuffer.pData);
  248. DbgPrint((TRC_TRACK,"LstLoadInterfaces]=%d", dwErr));
  249. return dwErr;
  250. }
  251. //-----------------------------------------------------------
  252. // Constructor for the INTF_CONTEXT. Takes as parameter the binding information.
  253. // Interface's GUID constitutes the context's key info.
  254. // This call doesn't insert the new context in any hash or list
  255. DWORD
  256. LstConstructIntfContext(
  257. PNDISUIO_QUERY_BINDING pBinding,
  258. PINTF_CONTEXT *ppIntfContext)
  259. {
  260. DWORD dwErr = ERROR_SUCCESS;
  261. PINTF_CONTEXT pIntfContext;
  262. LPWSTR wszName;
  263. DWORD dwNameLen;
  264. DbgPrint((TRC_TRACK,"[LstConstructIntfContext(0x%p)", pBinding));
  265. DbgAssert((ppIntfContext != NULL, "Invalid in/out parameter"));
  266. // zero the output param
  267. *ppIntfContext = NULL;
  268. // pIntfContext is allocated with zero_init meaning
  269. // all internal pointers are set to null
  270. pIntfContext = MemCAlloc(sizeof(INTF_CONTEXT));
  271. if (pIntfContext == NULL)
  272. {
  273. dwErr = GetLastError();
  274. goto exit;
  275. }
  276. // initialize context's fields, in their definition order..
  277. // Initialize the context specific fields (links, sync, control flags, state)
  278. InitializeListHead(&pIntfContext->Link);
  279. dwErr = RccsInit(&(pIntfContext->rccs)); // reference counter is initially set to 1
  280. if (dwErr != ERROR_SUCCESS)
  281. goto exit;
  282. pIntfContext->dwCtlFlags = (INTFCTL_ENABLED | Ndis802_11AutoUnknown);
  283. // initially, the ncstatus is "DISCONNECTED" (until wzc plumbs it down)
  284. pIntfContext->ncStatus = NCS_MEDIA_DISCONNECTED;
  285. // the state handler is initially set to NULL - it will be set to the
  286. // appropriate state when the context will be added to the state machine through
  287. // dispatching an eEventAdd event.
  288. pIntfContext->pfnStateHandler = NULL;
  289. // init the timer
  290. pIntfContext->hTimer = INVALID_HANDLE_VALUE;
  291. // if we do have a valid NDIS binding for this interface
  292. // otherwise, the following fields gets initialized as below:
  293. // hTimer <- INVALID_HANDLE_VALUE
  294. // dwIndex <- 0
  295. // wszGuid <- NULL
  296. // wszDescr <- NULL
  297. if (pBinding != NULL)
  298. {
  299. // create an inactive timer for this interface.
  300. if (!CreateTimerQueueTimer(
  301. &(pIntfContext->hTimer),
  302. g_htmQueue,
  303. (WAITORTIMERCALLBACK)WZCTimeoutCallback,
  304. pIntfContext,
  305. TMMS_INFINITE,
  306. TMMS_INFINITE,
  307. WT_EXECUTEDEFAULT))
  308. {
  309. dwErr = GetLastError();
  310. goto exit;
  311. }
  312. // initialize the ndis specific fields
  313. pIntfContext->dwIndex = pBinding->BindingIndex;
  314. // Copy the interface's device name.
  315. // Device name is "\DEVICE\{guid}". We keep only the guid
  316. wszName = (LPWSTR)((LPBYTE)pBinding + pBinding->DeviceNameOffset);
  317. // the DeviceNameLength is in bytes and includes the null terminator
  318. dwNameLen = pBinding->DeviceNameLength / sizeof(WCHAR);
  319. if (dwNameLen >= 8 && !_wcsnicmp(wszName, L"\\DEVICE\\", 8)) // 8 is the # of chars in "\\DEVICE\\"
  320. {
  321. wszName += 8;
  322. dwNameLen -= 8;
  323. }
  324. if (dwNameLen > 0)
  325. {
  326. pIntfContext->wszGuid = MemCAlloc(sizeof(WCHAR)*dwNameLen);
  327. if (pIntfContext->wszGuid == NULL)
  328. {
  329. dwErr = GetLastError();
  330. goto exit;
  331. }
  332. wcscpy(pIntfContext->wszGuid, wszName);
  333. }
  334. // Copy the interface's description.name
  335. wszName = (LPWSTR)((LPBYTE)pBinding + pBinding->DeviceDescrOffset);
  336. // the DeviceDescrLength is in bytes and includes the null terminator
  337. dwNameLen = pBinding->DeviceDescrLength;
  338. if (dwNameLen > 0)
  339. {
  340. pIntfContext->wszDescr = MemCAlloc(dwNameLen);
  341. if (pIntfContext->wszDescr == NULL)
  342. {
  343. dwErr = GetLastError();
  344. goto exit;
  345. }
  346. wcscpy(pIntfContext->wszDescr, wszName);
  347. }
  348. }
  349. // ulMediaState, ulMediaType, ulPhysicalMediaType defaults to 0
  350. pIntfContext->hIntf = INVALID_HANDLE_VALUE;
  351. // initialize the 802.11 specific fields
  352. pIntfContext->wzcCurrent.Length = sizeof(WZC_WLAN_CONFIG);
  353. pIntfContext->wzcCurrent.InfrastructureMode = -1;
  354. pIntfContext->wzcCurrent.AuthenticationMode = -1;
  355. pIntfContext->wzcCurrent.Privacy = -1;
  356. // wzcCurrent is all zero-ed out because of how the allocation was done
  357. // pwzcVList, pwzcPList, pwzcSList, pwzcBList all default to NULL
  358. DbgPrint((TRC_GENERIC,
  359. "Intf [%d] %S - %S",
  360. pIntfContext->dwIndex,
  361. pIntfContext->wszGuid,
  362. pIntfContext->wszDescr));
  363. exit:
  364. // if there was any error hit, clear up all resources allocated so far
  365. if (dwErr != ERROR_SUCCESS)
  366. {
  367. if (pIntfContext != NULL)
  368. {
  369. // this was a brand new context so there should be no timer queued for it
  370. if (pIntfContext->hTimer != NULL)
  371. DeleteTimerQueueTimer(g_htmQueue, pIntfContext->hTimer, INVALID_HANDLE_VALUE);
  372. MemFree(pIntfContext->wszDescr);
  373. MemFree(pIntfContext->wszGuid);
  374. }
  375. MemFree(pIntfContext);
  376. }
  377. else
  378. {
  379. // if success, copy out the new context
  380. *ppIntfContext = pIntfContext;
  381. }
  382. DbgPrint((TRC_TRACK,"LstConstructIntfContext(->0x%p)]=%d", *ppIntfContext, dwErr));
  383. return dwErr;
  384. }
  385. //-----------------------------------------------------------
  386. // Prepares a context for the destruction:
  387. // - Deletes any attached timer, making sure no other timer routines will be fired.
  388. // - Removes the context from any hash, making sure no one else will find the context
  389. // - Decrements the reference counter such that the context will be destroyed when unrefed.
  390. // This function is called while holding the critical section on the interface.
  391. DWORD
  392. LstRemoveIntfContext(
  393. PINTF_CONTEXT pIntfContext)
  394. {
  395. DWORD dwErr = ERROR_SUCCESS;
  396. PINTF_CONTEXT pRemovedIntfContext = NULL;
  397. DbgPrint((TRC_TRACK,"[LstRemoveIntfContext(0x%p)", pIntfContext));
  398. // synchronously delete any timer associated with the context.
  399. // Since the timer routine is lightweight there is no risk of deadlock
  400. pIntfContext->dwCtlFlags &= ~INTFCTL_INTERNAL_TM_ON;
  401. if (pIntfContext->hTimer != INVALID_HANDLE_VALUE)
  402. {
  403. HANDLE hTimer = pIntfContext->hTimer;
  404. pIntfContext->hTimer = INVALID_HANDLE_VALUE;
  405. DeleteTimerQueueTimer(g_htmQueue, hTimer, INVALID_HANDLE_VALUE);
  406. }
  407. // do the removal by passing down the guid formatted as "{guid}"
  408. // and expecting back the interface context in pIntfContext
  409. dwErr = LstRemIntfFromHashes(pIntfContext->wszGuid, &pRemovedIntfContext);
  410. DbgAssert((pIntfContext == pRemovedIntfContext, "The context removed from hashes doesn't match!"));
  411. // decrement the reference counter of the interface. This is what will make the context to be
  412. // effectively destroyed when the last thread unreference it.
  413. if (pIntfContext->rccs.nRefCount != 0)
  414. InterlockedDecrement(&(pIntfContext->rccs.nRefCount));
  415. DbgPrint((TRC_TRACK,"LstRemoveIntfContext]=%d", dwErr));
  416. return dwErr;
  417. }
  418. //-----------------------------------------------------------
  419. // Destructs the INTF_CONTEXT clearing all the resources allocated for it
  420. // This call doesn't remove this context from any hash or list
  421. DWORD
  422. LstDestroyIntfContext(PINTF_CONTEXT pIntfContext)
  423. {
  424. DWORD dwErr = ERROR_SUCCESS;;
  425. DbgPrint((TRC_TRACK,"[LstDestroyIntfContext(0x%p)", pIntfContext));
  426. if (pIntfContext == NULL)
  427. {
  428. dwErr = ERROR_INVALID_PARAMETER;
  429. goto exit;
  430. }
  431. // the destroy call is made when it is sure thing the context needs to be
  432. // deleted (either something wrong happened while loading the context or its
  433. // ref counter reached 0). There is no point in testing the ref counter again.
  434. if (pIntfContext->hTimer != INVALID_HANDLE_VALUE)
  435. DeleteTimerQueueTimer(g_htmQueue, pIntfContext->hTimer, NULL);
  436. dwErr = DevioCloseIntfHandle(pIntfContext);
  437. MemFree(pIntfContext->wszGuid);
  438. MemFree(pIntfContext->wszDescr);
  439. MemFree(pIntfContext->pwzcVList);
  440. MemFree(pIntfContext->pwzcPList);
  441. WzcCleanupWzcList(pIntfContext->pwzcSList);
  442. WzcSSKFree(pIntfContext->pSecSessionKeys);
  443. WzcCleanupWzcList(pIntfContext->pwzcBList);
  444. // since rccs.nRefCount reached 0, this means there is absolutely
  445. // no other thread referencing this object and that no one will
  446. // ever be able to reference it again. Getting to 0 means at least
  447. // one thread explicitly called LstDestroyIntfContext after removed
  448. // the object from the internal hashes.
  449. RccsDestroy(&pIntfContext->rccs);
  450. // at the end clear the interface context entirely
  451. MemFree(pIntfContext);
  452. exit:
  453. DbgPrint((TRC_TRACK,"LstDestroyIntfContext]=%d", dwErr));
  454. return dwErr;
  455. }
  456. //-----------------------------------------------------------
  457. // Returns the number of contexts enlisted in the service
  458. DWORD
  459. LstNumInterfaces()
  460. {
  461. return g_lstIntfHashes.nNumIntfs;
  462. }
  463. //-----------------------------------------------------------
  464. // Inserts the given context in all the internal hashes
  465. // This call assumes the hashes are locked by the caller
  466. DWORD
  467. LstAddIntfToHashes(PINTF_CONTEXT pIntf)
  468. {
  469. DWORD dwErr = ERROR_SUCCESS;
  470. DbgPrint((TRC_TRACK,"[LstAddIntfToHashes(0x%p)", pIntf));
  471. DbgAssert((pIntf != NULL, "Cannot insert NULL context into hashes!"))
  472. // Insert this interface in the GUID hash
  473. dwErr = HshInsertObjectRef(
  474. g_lstIntfHashes.pHnGUID,
  475. pIntf->wszGuid,
  476. pIntf,
  477. &g_lstIntfHashes.pHnGUID);
  478. if (dwErr == ERROR_SUCCESS)
  479. {
  480. // inserting to tail insures an ascending ordered list on dwIndex
  481. // not that it matters :o)
  482. InsertTailList(&g_lstIntfHashes.lstIntfs, &(pIntf->Link));
  483. // everything went out successfully, so increment the global number
  484. // of interfaces.
  485. g_lstIntfHashes.nNumIntfs++;
  486. }
  487. DbgPrint((TRC_TRACK,"LstAddIntfToHashes]=%d", dwErr));
  488. return dwErr;
  489. }
  490. //-----------------------------------------------------------
  491. // Removes the context referenced by GUID from all the internal hashes.
  492. // The GUID is expected to be in the format "{guid}"
  493. // Returns in ppIntfContext the object that was removed from all hashes.
  494. // This call assumes the hashes are locked already
  495. DWORD
  496. LstRemIntfFromHashes(LPWSTR wszGuid, PINTF_CONTEXT *ppIntfContext)
  497. {
  498. DWORD dwErr;
  499. PHASH_NODE pNode;
  500. PINTF_CONTEXT pIntfContext = NULL;
  501. DbgPrint((TRC_TRACK,"[LstRemIntfFromHashes(%S)", wszGuid == NULL? L"(null)" : wszGuid));
  502. DbgAssert((wszGuid != NULL, "Cannot clear NULL GUID from hashes!"));
  503. DbgAssert((ppIntfContext != NULL, "Invalid in/out parameter"));
  504. // get to the hash node
  505. dwErr = HshQueryObjectRef(
  506. g_lstIntfHashes.pHnGUID,
  507. wszGuid,
  508. &pNode);
  509. // if there is such a context
  510. // in the current hash, it needs to go away
  511. if (dwErr == ERROR_SUCCESS)
  512. {
  513. // remove this node from the Guid hash. We are already in its critical section
  514. dwErr = HshRemoveObjectRef(
  515. g_lstIntfHashes.pHnGUID,
  516. pNode,
  517. &pIntfContext,
  518. &g_lstIntfHashes.pHnGUID);
  519. // this is expected to succeed
  520. DbgAssert((dwErr == ERROR_SUCCESS,
  521. "Error %d while removing node 0x%p from GUID hash!!",
  522. dwErr,
  523. pNode));
  524. }
  525. // if the context is not in the Guids hash, it is nowhere else
  526. // so go next only in case of success.
  527. if (dwErr == ERROR_SUCCESS)
  528. {
  529. PINTF_CONTEXT pIntfContextDup;
  530. // remove the context from the linked list
  531. RemoveEntryList(&pIntfContext->Link);
  532. // and initialize the pointer.
  533. InitializeListHead(&pIntfContext->Link);
  534. // decrement the global interfaces count
  535. g_lstIntfHashes.nNumIntfs--;
  536. }
  537. *ppIntfContext = pIntfContext;
  538. DbgPrint((TRC_TRACK,"LstRemIntfFromHashes(->0x%p)]=%d",
  539. *ppIntfContext,
  540. dwErr));
  541. return dwErr;
  542. }
  543. //-----------------------------------------------------------
  544. // Returns an array of *pdwNumIntfs INTF_KEY_ENTRY elements.
  545. // The INTF_KEY_ENTRY contains whatever information identifies
  546. // uniquely an adapter. Currently it includes just the GUID in
  547. // the format "{guid}"
  548. DWORD
  549. LstGetIntfsKeyInfo(PINTF_KEY_ENTRY pIntfs, LPDWORD pdwNumIntfs)
  550. {
  551. DWORD dwErr = ERROR_SUCCESS;
  552. UINT nIntfIdx;
  553. PLIST_ENTRY pEntry;
  554. DbgPrint((TRC_TRACK,"[LstGetIntfsKeyInfo(0x%p,%d)", pIntfs, *pdwNumIntfs));
  555. // lock the hash during enumeration
  556. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  557. for (pEntry = g_lstIntfHashes.lstIntfs.Flink, nIntfIdx = 0;
  558. pEntry != &g_lstIntfHashes.lstIntfs && nIntfIdx < *pdwNumIntfs;
  559. pEntry = pEntry->Flink, nIntfIdx++)
  560. {
  561. PINTF_CONTEXT pIntfContext;
  562. // no need to lock this context since we're already holding the hashes.
  563. // no one can destroy the interface context now
  564. pIntfContext = CONTAINING_RECORD(pEntry, INTF_CONTEXT, Link);
  565. if (pIntfContext->wszGuid != NULL)
  566. {
  567. pIntfs[nIntfIdx].wszGuid = RpcCAlloc((wcslen(pIntfContext->wszGuid)+1)*sizeof(WCHAR));
  568. if (pIntfs[nIntfIdx].wszGuid == NULL)
  569. {
  570. dwErr = GetLastError();
  571. goto exit;
  572. }
  573. wcscpy(pIntfs[nIntfIdx].wszGuid, pIntfContext->wszGuid);
  574. }
  575. else
  576. {
  577. pIntfs[nIntfIdx].wszGuid = NULL;
  578. }
  579. }
  580. exit:
  581. // unlock the hash now
  582. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  583. if (dwErr != ERROR_SUCCESS)
  584. {
  585. UINT i;
  586. // if an error occured, rollback whatever we already did
  587. for (i = 0; i<nIntfIdx; i++)
  588. {
  589. // nIntfIdx points to the entry that couldn't be allocated
  590. if (pIntfs[i].wszGuid != NULL)
  591. {
  592. RpcFree(pIntfs[i].wszGuid);
  593. pIntfs[i].wszGuid = NULL;
  594. }
  595. }
  596. }
  597. else
  598. {
  599. // in case of success, update pdwNumIntfs with the actual
  600. // number we could retrieve (it can be only less or equal)
  601. *pdwNumIntfs = nIntfIdx;
  602. }
  603. DbgPrint((TRC_TRACK, "LstGetIntfsKeyInfo]=%d", dwErr));
  604. return dwErr;
  605. }
  606. //-----------------------------------------------------------
  607. // Returns requested information on the specified adapter.
  608. // [in] dwInFlags specifies the information requested. (see
  609. // bitmasks INTF_*
  610. // [in] pIntfEntry should contain the GUID of the adapter
  611. // [out] pIntfEntry contains all the requested information that
  612. // could be successfully retrieved.
  613. // [out] pdwOutFlags provides an indication on the info that
  614. // was successfully retrieved
  615. DWORD
  616. LstQueryInterface(
  617. DWORD dwInFlags,
  618. PINTF_ENTRY pIntfEntry,
  619. LPDWORD pdwOutFlags)
  620. {
  621. DWORD dwErr = ERROR_FILE_NOT_FOUND;
  622. PHASH_NODE pNode = NULL;
  623. PINTF_CONTEXT pIntfContext;
  624. DWORD dwOutFlags = 0;
  625. DbgPrint((TRC_TRACK, "[LstQueryInterface"));
  626. if (g_lstIntfHashes.bValid)
  627. {
  628. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  629. dwErr = HshQueryObjectRef(
  630. g_lstIntfHashes.pHnGUID,
  631. pIntfEntry->wszGuid,
  632. &pNode);
  633. if (dwErr == ERROR_SUCCESS)
  634. {
  635. pIntfContext = pNode->pObject;
  636. // bump up the reference counter since we're going
  637. // to work with this object
  638. LstRccsReference(pIntfContext);
  639. }
  640. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  641. }
  642. else
  643. dwErr = ERROR_ARENA_TRASHED;
  644. // a failure at this point, means there was no context
  645. // to lock so we can safely go to 'exit'
  646. if (dwErr != ERROR_SUCCESS)
  647. goto exit;
  648. // Lock the context now
  649. LstRccsLock(pIntfContext);
  650. // we can safely assume any living INTF_CONTEXT will have the correct
  651. // information for all the NDIS parameters below. So return them
  652. // unconditionally to the caller
  653. if ((dwInFlags & INTF_DESCR) &&
  654. (pIntfContext->wszDescr) != NULL)
  655. {
  656. pIntfEntry->wszDescr = RpcCAlloc(sizeof(WCHAR)*(wcslen(pIntfContext->wszDescr)+1));
  657. if (pIntfEntry->wszDescr != NULL)
  658. {
  659. wcscpy(pIntfEntry->wszDescr, pIntfContext->wszDescr);
  660. dwOutFlags |= INTF_DESCR;
  661. }
  662. else
  663. dwErr = GetLastError();
  664. }
  665. if (dwInFlags & INTF_NDISMEDIA)
  666. {
  667. pIntfEntry->ulMediaState = pIntfContext->ulMediaState;
  668. pIntfEntry->ulMediaType = pIntfContext->ulMediaType;
  669. pIntfEntry->ulPhysicalMediaType = pIntfContext->ulPhysicalMediaType;
  670. dwOutFlags |= INTF_NDISMEDIA;
  671. }
  672. if (dwInFlags & INTF_ALL_FLAGS)
  673. {
  674. DWORD dwActualFlags = dwInFlags & INTF_ALL_FLAGS;
  675. pIntfEntry->dwCtlFlags = pIntfContext->dwCtlFlags & dwActualFlags;
  676. dwOutFlags |= dwActualFlags;
  677. }
  678. // copy out the StSSIDList if requested
  679. if (dwInFlags & INTF_PREFLIST)
  680. {
  681. pIntfEntry->rdStSSIDList.dwDataLen = 0;
  682. pIntfEntry->rdStSSIDList.pData = NULL;
  683. // it could happen we don't have any static entry. If so, dwOutFlags
  684. // needs to be set correctly saying "success"
  685. if (pIntfContext->pwzcPList != NULL)
  686. {
  687. UINT nBytes;
  688. // see how much memory is needed to store all the static SSIDs
  689. nBytes = FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config) +
  690. pIntfContext->pwzcPList->NumberOfItems * sizeof(WZC_WLAN_CONFIG);
  691. // allocate buffer large enough for all static SSIDs
  692. pIntfEntry->rdStSSIDList.pData = RpcCAlloc(nBytes);
  693. if (pIntfEntry->rdStSSIDList.pData != NULL)
  694. {
  695. // set the memory size in this RAW_DATA
  696. pIntfEntry->rdStSSIDList.dwDataLen = nBytes;
  697. // copy the whole WZC_802_11_CONFIG_LIST of static SSIDs
  698. CopyMemory(
  699. pIntfEntry->rdStSSIDList.pData,
  700. pIntfContext->pwzcPList,
  701. nBytes);
  702. // mark "success"
  703. dwOutFlags |= INTF_PREFLIST;
  704. }
  705. else if (dwErr == ERROR_SUCCESS)
  706. dwErr = GetLastError();
  707. }
  708. else
  709. {
  710. // still, if no static SSID defined, this is seen as "success"
  711. dwOutFlags |= INTF_PREFLIST;
  712. }
  713. }
  714. // the 802.11 parameters are valid only if the context's state is not {SSr}
  715. if (pIntfContext->pfnStateHandler != StateSoftResetFn)
  716. {
  717. if (dwInFlags & INTF_INFRAMODE)
  718. {
  719. pIntfEntry->nInfraMode = pIntfContext->wzcCurrent.InfrastructureMode;
  720. dwOutFlags |= INTF_INFRAMODE;
  721. }
  722. if (dwInFlags & INTF_AUTHMODE)
  723. {
  724. pIntfEntry->nAuthMode = pIntfContext->wzcCurrent.AuthenticationMode;
  725. dwOutFlags |= INTF_AUTHMODE;
  726. }
  727. if (dwInFlags & INTF_WEPSTATUS)
  728. {
  729. pIntfEntry->nWepStatus = pIntfContext->wzcCurrent.Privacy;
  730. dwOutFlags |= INTF_WEPSTATUS;
  731. }
  732. // copy out the BSSID if requested
  733. if (dwInFlags & INTF_BSSID)
  734. {
  735. pIntfEntry->rdBSSID.dwDataLen = 0;
  736. pIntfEntry->rdBSSID.pData = RpcCAlloc(sizeof(NDIS_802_11_MAC_ADDRESS));
  737. if (pIntfEntry->rdBSSID.pData != NULL)
  738. {
  739. pIntfEntry->rdBSSID.dwDataLen = sizeof(NDIS_802_11_MAC_ADDRESS);
  740. CopyMemory(
  741. pIntfEntry->rdBSSID.pData,
  742. &pIntfContext->wzcCurrent.MacAddress,
  743. pIntfEntry->rdBSSID.dwDataLen);
  744. dwOutFlags |= INTF_BSSID;
  745. }
  746. else if (dwErr == ERROR_SUCCESS)
  747. dwErr = GetLastError();
  748. }
  749. // copy out the SSID if requested
  750. if (dwInFlags & INTF_SSID)
  751. {
  752. pIntfEntry->rdSSID.dwDataLen = 0;
  753. pIntfEntry->rdSSID.pData = NULL;
  754. // normally there should be an SSID so set the dwOutFlags
  755. // for this field only if it exists
  756. if (pIntfContext->wzcCurrent.Ssid.SsidLength != 0)
  757. {
  758. pIntfEntry->rdSSID.pData = RpcCAlloc(pIntfContext->wzcCurrent.Ssid.SsidLength);
  759. if (pIntfEntry->rdSSID.pData != NULL)
  760. {
  761. pIntfEntry->rdSSID.dwDataLen = pIntfContext->wzcCurrent.Ssid.SsidLength;
  762. CopyMemory(
  763. pIntfEntry->rdSSID.pData,
  764. pIntfContext->wzcCurrent.Ssid.Ssid,
  765. pIntfContext->wzcCurrent.Ssid.SsidLength);
  766. dwOutFlags |= INTF_SSID;
  767. }
  768. else if (dwErr == ERROR_SUCCESS)
  769. dwErr = GetLastError();
  770. }
  771. }
  772. // copy out the BSSIDList if requested
  773. if (dwInFlags & INTF_BSSIDLIST)
  774. {
  775. pIntfEntry->rdBSSIDList.dwDataLen = 0;
  776. pIntfEntry->rdBSSIDList.pData = NULL;
  777. // normally there should be a visible list so set the dwOutFlags
  778. // for this field only if it exists
  779. if (pIntfContext->pwzcVList != NULL)
  780. {
  781. UINT nBytes;
  782. // see how much memory is needed to store all the configurations
  783. nBytes = FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config) +
  784. pIntfContext->pwzcVList->NumberOfItems * sizeof(WZC_WLAN_CONFIG);
  785. // allocate buffer large enough to hold all the configurations
  786. pIntfEntry->rdBSSIDList.pData = RpcCAlloc(nBytes);
  787. if (pIntfEntry->rdBSSIDList.pData != NULL)
  788. {
  789. // set the memory size in this RAW_DATA
  790. pIntfEntry->rdBSSIDList.dwDataLen = nBytes;
  791. // copy the whole WZC_802_11_CONFIG_LIST
  792. CopyMemory(
  793. pIntfEntry->rdBSSIDList.pData,
  794. pIntfContext->pwzcVList,
  795. nBytes);
  796. dwOutFlags |= INTF_BSSIDLIST;
  797. }
  798. else if (dwErr == ERROR_SUCCESS)
  799. dwErr = GetLastError();
  800. }
  801. }
  802. }
  803. // if the context's state is {SSr} and some OIDs are requested, don't fail, but the bits
  804. // corresponding to the OIDs will all be nulled out. This is the indication of "pending"
  805. LstRccsUnlockUnref(pIntfContext);
  806. exit:
  807. if (pdwOutFlags != NULL)
  808. {
  809. *pdwOutFlags = dwOutFlags;
  810. DbgPrint((TRC_GENERIC,"Sending OutFlags = 0x%x", *pdwOutFlags));
  811. }
  812. DbgPrint((TRC_TRACK, "LstQueryInterface]=%d", dwErr));
  813. return dwErr;
  814. }
  815. //-----------------------------------------------------------
  816. // Sets the specified parameters on the specified adapter.
  817. // [in] dwInFlags specifies the parameters to be set. (see
  818. // bitmasks INTF_*
  819. // [in] pIntfEntry should contain the GUID of the adapter and
  820. // all the additional parameters to be set as specified
  821. // in dwInFlags
  822. // [out] pdwOutFlags provides an indication on the params that
  823. // were successfully set to the adapter
  824. // Each parameter for which the driver says that was set successfully
  825. // is copied into the interface's context.
  826. DWORD
  827. LstSetInterface(
  828. DWORD dwInFlags,
  829. PINTF_ENTRY pIntfEntry,
  830. LPDWORD pdwOutFlags)
  831. {
  832. DWORD dwErr = ERROR_SUCCESS;
  833. DWORD dwLErr;
  834. PHASH_NODE pNode = NULL;
  835. PINTF_CONTEXT pIntfContext;
  836. DWORD dwOutFlags = 0;
  837. DbgPrint((TRC_TRACK, "[LstSetInterface"));
  838. if (pIntfEntry->wszGuid == NULL)
  839. {
  840. if (g_wzcInternalCtxt.bValid)
  841. {
  842. EnterCriticalSection(&g_wzcInternalCtxt.csContext);
  843. pIntfContext = g_wzcInternalCtxt.pIntfTemplate;
  844. LstRccsReference(pIntfContext);
  845. LeaveCriticalSection(&g_wzcInternalCtxt.csContext);
  846. }
  847. else
  848. dwErr = ERROR_ARENA_TRASHED;
  849. }
  850. else
  851. {
  852. if (g_lstIntfHashes.bValid)
  853. {
  854. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  855. dwErr = HshQueryObjectRef(
  856. g_lstIntfHashes.pHnGUID,
  857. pIntfEntry->wszGuid,
  858. &pNode);
  859. if (dwErr == ERROR_SUCCESS)
  860. {
  861. pIntfContext = pNode->pObject;
  862. LstRccsReference(pIntfContext);
  863. }
  864. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  865. }
  866. else
  867. dwErr = ERROR_ARENA_TRASHED;
  868. }
  869. // a failure at this point, means there was no context
  870. // to lock so we can safely go to 'exit'
  871. if (dwErr != ERROR_SUCCESS)
  872. goto exit;
  873. LstRccsLock(pIntfContext);
  874. // 1) Set the new public Control flags, if specified
  875. if (dwInFlags & INTF_ALL_FLAGS)
  876. {
  877. DWORD dwActualFlags = dwInFlags & INTF_ALL_FLAGS;
  878. DWORD dwSupp = (pIntfContext->dwCtlFlags & INTFCTL_OIDSSUPP);
  879. pIntfContext->dwCtlFlags &= ~dwActualFlags;
  880. pIntfContext->dwCtlFlags |= pIntfEntry->dwCtlFlags & dwActualFlags;
  881. // retain the original INTFCTL_OIDSSUPP bit
  882. pIntfContext->dwCtlFlags |= dwSupp;
  883. dwOutFlags |= dwActualFlags;
  884. }
  885. // 2) copy the list of Static SSID (if requested to be set) as below:
  886. // Allocate the memory needed for the new static SSIDs list (if needed)
  887. // If successful, copy in the new buffer the new list of static SSIDs, clear up
  888. // whatever old list we had and put the new one in the interface's context
  889. if (dwInFlags & INTF_PREFLIST)
  890. {
  891. PWZC_802_11_CONFIG_LIST pNewPList;
  892. // MemCAlloc handles the case when size is 0 (returns NULL)
  893. pNewPList = (PWZC_802_11_CONFIG_LIST)MemCAlloc(pIntfEntry->rdStSSIDList.dwDataLen);
  894. if (pIntfEntry->rdStSSIDList.dwDataLen != 0 && pNewPList == NULL)
  895. {
  896. dwLErr = GetLastError();
  897. }
  898. else
  899. {
  900. // .. copy the data in the new buffer if there is any
  901. if (pNewPList != NULL)
  902. {
  903. CopyMemory(
  904. pNewPList,
  905. pIntfEntry->rdStSSIDList.pData,
  906. pIntfEntry->rdStSSIDList.dwDataLen);
  907. }
  908. // set the data in the Interface's context
  909. MemFree(pIntfContext->pwzcPList);
  910. pIntfContext->pwzcPList = pNewPList;
  911. // if this is not referring to the template object..
  912. if (pIntfContext->wszGuid != NULL)
  913. {
  914. //..let 802.1X know about the change. (don't care about the return value)
  915. ElWZCCfgChangeHandler(
  916. pIntfContext->wszGuid,
  917. pIntfContext->pwzcPList);
  918. }
  919. dwOutFlags |= INTF_PREFLIST;
  920. dwLErr = ERROR_SUCCESS;
  921. }
  922. if (dwErr == ERROR_SUCCESS)
  923. dwErr = dwLErr;
  924. }
  925. // if there is anything more to set to this interface
  926. if (dwInFlags & ~(INTF_PREFLIST|INTF_ALL_FLAGS))
  927. {
  928. // and the control flag INTFCTL_ENABLED doesn't allow this
  929. if (!(pIntfContext->dwCtlFlags & INTFCTL_ENABLED))
  930. {
  931. // signal "request refused" error
  932. dwLErr = ERROR_REQUEST_REFUSED;
  933. }
  934. else
  935. {
  936. DWORD dwLOutFlags;
  937. // else go and set the oids
  938. dwLErr = DevioSetIntfOIDs(
  939. pIntfContext,
  940. pIntfEntry,
  941. dwInFlags,
  942. &dwLOutFlags);
  943. dwOutFlags |= dwLOutFlags;
  944. }
  945. if (dwErr == ERROR_SUCCESS)
  946. dwErr = dwLErr;
  947. }
  948. // log the user preference
  949. DbLogWzcInfo(WZCSVC_USR_CFGCHANGE, pIntfContext);
  950. // act on the changes..
  951. dwLErr = LstActOnChanges(dwOutFlags, pIntfContext);
  952. if (dwErr == ERROR_SUCCESS)
  953. dwErr = dwLErr;
  954. LstRccsUnlockUnref(pIntfContext);
  955. exit:
  956. if (pdwOutFlags != NULL)
  957. *pdwOutFlags = dwOutFlags;
  958. DbgPrint((TRC_TRACK, "LstSetInterface]=%d", dwErr));
  959. return dwErr;
  960. }
  961. //-----------------------------------------------------------
  962. // Checks whether interface changes should cause the interface to be
  963. // reinserted in the state machine and it does so if needed.
  964. // [in] dwChangedFlags indicates what the changes are. (see
  965. // bitmasks INTF_*)
  966. // [in] pIntfContext context of the interface being changed.
  967. DWORD
  968. LstActOnChanges(
  969. DWORD dwChangedFlags,
  970. PINTF_CONTEXT pIntfContext)
  971. {
  972. DWORD dwErr = ERROR_SUCCESS;
  973. DWORD dwLFlags = INTF_LIST_SCAN;
  974. BOOL bAltered = FALSE;
  975. DbgPrint((TRC_TRACK, "[LstActOnChanges(0x08x, %p)", dwChangedFlags, pIntfContext));
  976. // if the changes involve the list of preferred networks or the control flags
  977. // then we should act on these changes..
  978. if (dwChangedFlags & (INTF_PREFLIST|INTF_ALL_FLAGS))
  979. {
  980. // if this is not the interface template object then just reset this interface
  981. if (pIntfContext->wszGuid != NULL)
  982. {
  983. // some interface changed, apply the template again on top of it
  984. if (g_wzcInternalCtxt.bValid)
  985. {
  986. PINTF_CONTEXT pIntfTContext;
  987. EnterCriticalSection(&g_wzcInternalCtxt.csContext);
  988. pIntfTContext = g_wzcInternalCtxt.pIntfTemplate;
  989. LstRccsReference(pIntfTContext);
  990. LeaveCriticalSection(&g_wzcInternalCtxt.csContext);
  991. LstRccsLock(pIntfTContext);
  992. dwErr = LstApplyTemplate(
  993. pIntfTContext,
  994. pIntfContext,
  995. &bAltered);
  996. LstRccsUnlockUnref(pIntfTContext);
  997. }
  998. // if any of the control flags or the static list changed,
  999. // these settings should go into the registry now
  1000. StoSaveIntfConfig(NULL, pIntfContext);
  1001. // since we're resetting the state machine, turn back on the "signal" flag
  1002. pIntfContext->dwCtlFlags |= INTFCTL_INTERNAL_SIGNAL;
  1003. dwErr = StateDispatchEvent(
  1004. eEventCmdRefresh,
  1005. pIntfContext,
  1006. &dwLFlags);
  1007. // clear up the INTFCTL_INTERNAL_BLK_MEDIACONN bit since this is not a media sense handler
  1008. pIntfContext->dwCtlFlags &= ~INTFCTL_INTERNAL_BLK_MEDIACONN;
  1009. }
  1010. // if this is the interface template, then...
  1011. else
  1012. {
  1013. PLIST_ENTRY pEntry;
  1014. // since the template changed, save it to the registry here
  1015. dwErr = StoSaveIntfConfig(NULL, pIntfContext);
  1016. DbgAssert((dwErr == ERROR_SUCCESS,
  1017. "Error %d while storing the template to registry"));
  1018. // iterate through all the interfaces, apply the changes from the interface template
  1019. // and reset each of them
  1020. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  1021. for (pEntry = g_lstIntfHashes.lstIntfs.Flink;
  1022. pEntry != &g_lstIntfHashes.lstIntfs;
  1023. pEntry = pEntry->Flink)
  1024. {
  1025. PINTF_CONTEXT pIntfLContext = CONTAINING_RECORD(pEntry, INTF_CONTEXT, Link);
  1026. LstRccsReference(pIntfLContext);
  1027. LstRccsLock(pIntfLContext);
  1028. // Merge the template settings into the interface's context
  1029. dwErr = LstApplyTemplate(
  1030. pIntfContext,
  1031. pIntfLContext,
  1032. NULL);
  1033. DbgAssert((dwErr == ERROR_SUCCESS,
  1034. "Error %d while applying template to interface %S",
  1035. dwErr, pIntfLContext->wszGuid));
  1036. // if any of the control flags or the static list changed,
  1037. // these settings should go into the registry now
  1038. StoSaveIntfConfig(NULL, pIntfLContext);
  1039. // since we're resetting the state machine, turn back on the "signal" flag
  1040. pIntfLContext->dwCtlFlags |= INTFCTL_INTERNAL_SIGNAL;
  1041. dwErr = StateDispatchEvent(
  1042. eEventCmdRefresh,
  1043. pIntfLContext,
  1044. &dwLFlags);
  1045. DbgAssert((dwErr == ERROR_SUCCESS,
  1046. "Error %d while resetting interface %S",
  1047. dwErr, pIntfLContext->wszGuid));
  1048. // clear up the INTFCTL_INTERNAL_BLK_MEDIACONN bit since this is not a media sense handler
  1049. pIntfLContext->dwCtlFlags &= ~INTFCTL_INTERNAL_BLK_MEDIACONN;
  1050. LstRccsUnlockUnref(pIntfLContext);
  1051. }
  1052. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  1053. }
  1054. }
  1055. if (dwErr == ERROR_SUCCESS && bAltered)
  1056. dwErr = ERROR_PARTIAL_COPY;
  1057. DbgPrint((TRC_TRACK, "LstActOnChanges]=%d", dwErr));
  1058. return dwErr;
  1059. }
  1060. //-----------------------------------------------------------
  1061. // Applies settings from the template context to the given interface context
  1062. // [in] dwChanges: flags indicating settings that should be applied.
  1063. // [in] pIntfTemplate: Interface template to pick settings from
  1064. // [in] pIntfContext: Interface context to apply template to.
  1065. DWORD
  1066. LstApplyTemplate(
  1067. PINTF_CONTEXT pIntfTemplate,
  1068. PINTF_CONTEXT pIntfContext,
  1069. LPBOOL pbAltered)
  1070. {
  1071. DWORD dwErr = ERROR_SUCCESS;
  1072. PWZC_802_11_CONFIG_LIST pwzcTList = pIntfTemplate->pwzcPList;
  1073. PWZC_802_11_CONFIG_LIST pwzcPList = pIntfContext->pwzcPList;
  1074. PWZC_802_11_CONFIG_LIST pwzcRList = NULL; // resulting list
  1075. ENUM_SELCATEG iCtg;
  1076. UINT i, n, nCnt[7] = {0};
  1077. BOOL bAltered = FALSE;
  1078. PWZC_WLAN_CONFIG pTHInfra = NULL, pTHAdhoc = NULL; // head of Infra/Adhoc groups in the template list
  1079. PWZC_WLAN_CONFIG pPHInfra = NULL, pPHAdhoc = NULL; // head of Infra/Adhoc groups in the preferred list
  1080. PWZC_WLAN_CONFIG pOneTime = NULL; // pointer to the "one time configuration" if any
  1081. DbgPrint((TRC_TRACK,"[LstApplyTemplate(%p->%p)", pIntfTemplate, pIntfContext));
  1082. // apply the flags, if there are any provided
  1083. if (pIntfTemplate->dwCtlFlags & INTF_POLICY)
  1084. {
  1085. DWORD dwPFlags = (pIntfContext->dwCtlFlags & INTF_ALL_FLAGS) & ~(INTF_OIDSSUPP);
  1086. DWORD dwTFlags = (pIntfTemplate->dwCtlFlags & INTF_ALL_FLAGS) & ~(INTF_OIDSSUPP);
  1087. if (dwPFlags != dwTFlags)
  1088. {
  1089. // if the policy flags are different from the interface's flags then
  1090. // copy over just the "user" flag but don't overwrite the OIDSSUPP bit.
  1091. dwPFlags = (pIntfContext->dwCtlFlags & ~INTF_ALL_FLAGS) |
  1092. (pIntfTemplate->dwCtlFlags & INTF_ALL_FLAGS);
  1093. if (pIntfContext->dwCtlFlags & INTF_OIDSSUPP)
  1094. dwPFlags |= INTF_OIDSSUPP;
  1095. else
  1096. dwPFlags &= ~INTF_OIDSSUPP;
  1097. pIntfContext->dwCtlFlags = dwPFlags;
  1098. bAltered = TRUE;
  1099. }
  1100. }
  1101. else
  1102. {
  1103. // currently policy could come only through the template. Consequently,
  1104. // if the template is not policy, local setting should not be policy either.
  1105. // Also, whatever the policy plumbs last, should be persisted.
  1106. pIntfContext->dwCtlFlags &= ~(INTF_POLICY|INTF_VOLATILE);
  1107. }
  1108. // check the interface's list of preferred networks
  1109. if (pwzcPList != NULL)
  1110. {
  1111. for (i = 0; i < pwzcPList->NumberOfItems; i++)
  1112. {
  1113. PWZC_WLAN_CONFIG pPConfig = &(pwzcPList->Config[i]);
  1114. // keep a pointer to the "one time config" if there is one.
  1115. if (i == pwzcPList->Index)
  1116. pOneTime = pPConfig;
  1117. // tag each entry in the preferred list with its respective category
  1118. if (pPConfig->InfrastructureMode == Ndis802_11Infrastructure)
  1119. {
  1120. if (pPHInfra == NULL)
  1121. pPHInfra = pPConfig;
  1122. iCtg = ePI;
  1123. }
  1124. else if (pPConfig->InfrastructureMode == Ndis802_11IBSS)
  1125. {
  1126. if (pPHAdhoc == NULL)
  1127. pPHAdhoc = pPConfig;
  1128. iCtg = ePA;
  1129. }
  1130. else
  1131. iCtg = eN;
  1132. // regardless the above logic, exclude this configuration from the result list in
  1133. // either of the two cases:
  1134. // - the config is marked "shadow": that is, it is irrelevant without a matching template
  1135. // configuration.
  1136. // - the config is marked "volatile": that is, it has to go away unless the template is saying
  1137. // otherwise.
  1138. // This test needs to be done here and not earlier, because we do need pPHInfra and pPHAdhoc
  1139. // to be set up correctly, taking into account all the configurations.
  1140. if (pPConfig->dwCtlFlags & (WZCCTL_INTERNAL_SHADOW|WZCCTL_VOLATILE))
  1141. iCtg = eN;
  1142. NWB_SET_SELCATEG(pPConfig, iCtg);
  1143. nCnt[iCtg]++;
  1144. }
  1145. }
  1146. // check the list of networks enforced by the template
  1147. if (pwzcTList != NULL)
  1148. {
  1149. for (i = 0; i < pwzcTList->NumberOfItems; i++)
  1150. {
  1151. PWZC_WLAN_CONFIG pTConfig = &(pwzcTList->Config[i]);
  1152. PWZC_WLAN_CONFIG pPConfig;
  1153. if (pTConfig->InfrastructureMode == Ndis802_11Infrastructure)
  1154. {
  1155. if (pTHInfra == NULL)
  1156. pTHInfra = pTConfig;
  1157. iCtg = eVPI;
  1158. }
  1159. else if (pTConfig->InfrastructureMode == Ndis802_11IBSS)
  1160. {
  1161. if (pTHAdhoc == NULL)
  1162. pTHAdhoc = pTConfig;
  1163. iCtg = eVPA;
  1164. }
  1165. else
  1166. {
  1167. iCtg = eN;
  1168. continue;
  1169. }
  1170. pPConfig = WzcFindConfig(pwzcPList, pTConfig, 0);
  1171. // if there is an equivalent preference for the given template...
  1172. if (pPConfig != NULL)
  1173. {
  1174. // if the template is policy, it should stomp over the preference
  1175. if (pTConfig->dwCtlFlags & WZCCTL_POLICY)
  1176. {
  1177. BOOL bWepOnlyDiff;
  1178. // if the configurations contents don't match ...
  1179. if (!WzcMatchConfig(pTConfig, pPConfig, &bWepOnlyDiff))
  1180. {
  1181. // even if the configs don't match, we need to pick up the
  1182. // WEP key from the one provided by the user and mark the template
  1183. // configuration as "shadow"-ed.
  1184. pTConfig->KeyIndex = pPConfig->KeyIndex;
  1185. pTConfig->KeyLength = pPConfig->KeyLength;
  1186. // the key length has already been checked!
  1187. DbgAssert((pTConfig->KeyLength <= WZCCTL_MAX_WEPK_MATERIAL, "WEP Key too large!!!"));
  1188. memcpy(pTConfig->KeyMaterial, pPConfig->KeyMaterial, pTConfig->KeyLength);
  1189. pTConfig->dwCtlFlags |= WZCCTL_INTERNAL_SHADOW;
  1190. // signal the user illegally attempted to alter the policy if these
  1191. // changes include more than just the WEP key.
  1192. if (!bWepOnlyDiff)
  1193. bAltered = TRUE;
  1194. }
  1195. // if the configurations do match check the order.
  1196. else
  1197. {
  1198. // if the offsets of the template & preferred in their respective
  1199. // groups are different, then it means the policy configuration have
  1200. // been reordered - not allowed, hence set the "Altered" bit.
  1201. if ((pTConfig->InfrastructureMode == Ndis802_11Infrastructure &&
  1202. (pTConfig - pTHInfra) != (pPConfig - pPHInfra)
  1203. ) ||
  1204. (pTConfig->InfrastructureMode == Ndis802_11IBSS &&
  1205. (pTConfig - pTHAdhoc) != (pPConfig - pPHAdhoc)
  1206. )
  1207. )
  1208. {
  1209. bAltered = TRUE;
  1210. }
  1211. }
  1212. // also, if the policy is substituting the "one time config",
  1213. // make the "one time config" to become the policy config.
  1214. if (pOneTime == pPConfig)
  1215. pOneTime = pTConfig;
  1216. // push the template
  1217. NWB_SET_SELCATEG(pTConfig, iCtg);
  1218. nCnt[iCtg]++;
  1219. // and take out the conflicting preference
  1220. iCtg = NWB_GET_SELCATEG(pPConfig);
  1221. nCnt[iCtg]--;
  1222. NWB_SET_SELCATEG(pPConfig, eN);
  1223. nCnt[eN]++;
  1224. }
  1225. // this non-policy template and already has an equivalent preference.
  1226. // take it out then
  1227. else
  1228. {
  1229. iCtg = eN;
  1230. NWB_SET_SELCATEG(pTConfig, iCtg);
  1231. nCnt[iCtg]++;
  1232. }
  1233. }
  1234. // there is no equivalent preference for the given template...
  1235. else
  1236. {
  1237. // we don't have any preference for this template, so the template
  1238. // is just pumped into the preference list.
  1239. // if the template is a policy, it means the user deleted it and
  1240. // he shouldn't have done so. Set the "Altered" bit then.
  1241. if (pTConfig->dwCtlFlags & WZCCTL_POLICY)
  1242. bAltered = TRUE;
  1243. // just push the template no matter what.
  1244. NWB_SET_SELCATEG(pTConfig, iCtg);
  1245. nCnt[iCtg]++;
  1246. }
  1247. }
  1248. }
  1249. // calculate the number of entries in the resulting list
  1250. n = 0;
  1251. for (iCtg=eVPI; iCtg < eN; iCtg++)
  1252. n += nCnt[iCtg];
  1253. // if there is not a single entry in the resulting list,
  1254. // get out now. pwzcRList is already NULL.
  1255. if (n == 0)
  1256. goto exit;
  1257. // ..allocate the new preferred list
  1258. pwzcRList = (PWZC_802_11_CONFIG_LIST)
  1259. MemCAlloc(FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config) + n * sizeof(WZC_WLAN_CONFIG));
  1260. if (pwzcRList == NULL)
  1261. {
  1262. dwErr = GetLastError();
  1263. goto exit;
  1264. }
  1265. // list is successfully allocated
  1266. pwzcRList->NumberOfItems = n;
  1267. pwzcRList->Index = n;
  1268. // now change the semantic of all counters to mean "indices in the selection list"
  1269. // for their respective group of entries
  1270. for (iCtg = eN-1; iCtg >= eVPI; iCtg--)
  1271. {
  1272. n -= nCnt[iCtg];
  1273. nCnt[iCtg] = n;
  1274. }
  1275. // copy over in the new list the entries enforced by the template
  1276. if (pwzcTList != NULL)
  1277. {
  1278. for (i = 0; i < pwzcTList->NumberOfItems; i++)
  1279. {
  1280. PWZC_WLAN_CONFIG pTConfig = &(pwzcTList->Config[i]);
  1281. iCtg = NWB_GET_SELCATEG(pTConfig);
  1282. if (iCtg != eN)
  1283. {
  1284. PWZC_WLAN_CONFIG pRConfig = &(pwzcRList->Config[nCnt[iCtg]]);
  1285. // copy the whole template configuration to the result list
  1286. memcpy(pRConfig, pTConfig, sizeof(WZC_WLAN_CONFIG));
  1287. // just for making sure, reset the 'deleted' flag as this is a brand new
  1288. // config that was never attempted.
  1289. pRConfig->dwCtlFlags &= ~WZCCTL_INTERNAL_DELETED;
  1290. // if the template configuration is marked as being shadowed..
  1291. if (pTConfig->dwCtlFlags & WZCCTL_INTERNAL_SHADOW)
  1292. {
  1293. // ..set it to the preferred configuration also..
  1294. pRConfig->dwCtlFlags |= WZCCTL_INTERNAL_SHADOW;
  1295. // ..and make sure the preferred configuration gets persisted
  1296. // since it contains user information..
  1297. pRConfig->dwCtlFlags &= ~WZCCTL_VOLATILE;
  1298. // leave the template configuration with the bit "shadow" since
  1299. // it has been altered. This way, if the template is subsequently
  1300. // "applied" the user config won't get the "volatile" bit set back
  1301. // and it will still be marked "shadow".
  1302. }
  1303. // if this is the "one time" config, adjust the Index to point to this entry's index
  1304. if (pOneTime == pTConfig)
  1305. pwzcRList->Index = nCnt[iCtg];
  1306. nCnt[iCtg]++;
  1307. }
  1308. // reset the selection category we have used for this resulting entry
  1309. NWB_SET_SELCATEG(pTConfig, 0);
  1310. }
  1311. }
  1312. // copy over in the new list the entries from the original list
  1313. if (pwzcPList != NULL)
  1314. {
  1315. for (i = 0; i < pwzcPList->NumberOfItems; i++)
  1316. {
  1317. PWZC_WLAN_CONFIG pPConfig = &(pwzcPList->Config[i]);
  1318. iCtg = NWB_GET_SELCATEG(pPConfig);
  1319. if (iCtg != eN)
  1320. {
  1321. PWZC_WLAN_CONFIG pRConfig = &(pwzcRList->Config[nCnt[iCtg]]);
  1322. // copy the whole preferred configuration to the result list
  1323. memcpy(pRConfig, pPConfig, sizeof(WZC_WLAN_CONFIG));
  1324. // just for making sure, reset the 'deleted' flag as this is a brand new
  1325. // config that was never attempted.
  1326. pRConfig->dwCtlFlags &= ~WZCCTL_INTERNAL_DELETED;
  1327. // if this is the "one time" config, adjust the Index to point to this entry's index
  1328. if (pOneTime == pPConfig)
  1329. pwzcRList->Index = nCnt[iCtg];
  1330. nCnt[iCtg]++;
  1331. }
  1332. // reset the selection category we have used for this preferred entry
  1333. NWB_SET_SELCATEG(pPConfig, 0);
  1334. }
  1335. }
  1336. exit:
  1337. if (dwErr == ERROR_SUCCESS)
  1338. {
  1339. // cleanup the original list and put in the new one
  1340. WzcCleanupWzcList(pIntfContext->pwzcPList);
  1341. pIntfContext->pwzcPList = pwzcRList;
  1342. }
  1343. if (pbAltered != NULL)
  1344. *pbAltered = bAltered;
  1345. DbgPrint((TRC_TRACK,"LstApplyTemplate]=%d", dwErr));
  1346. return dwErr;
  1347. }
  1348. //-----------------------------------------------------------
  1349. // Refreshes the specified parameters on the specified adapter.
  1350. // [in] dwInFlags specifies the parameters to be set. (see
  1351. // bitmasks INTF_* and INTF_RFSH_*)
  1352. // [in] pIntfEntry should contain the GUID of the adapter
  1353. // [out] pdwOutFlags provides an indication on the params that
  1354. // were successfully refreshed to the adapter
  1355. // Each parameter for which the driver says that was refreshed
  1356. // successfully is copied into the interface's context.
  1357. DWORD
  1358. LstRefreshInterface(
  1359. DWORD dwInFlags,
  1360. PINTF_ENTRY pIntfEntry,
  1361. LPDWORD pdwOutFlags)
  1362. {
  1363. DWORD dwErr, dwLErr;
  1364. PHASH_NODE pNode = NULL;
  1365. DWORD dwOutFlags = 0;
  1366. PINTF_CONTEXT pIntfContext;
  1367. DbgPrint((TRC_TRACK, "[LstRefreshInterface"));
  1368. if (g_lstIntfHashes.bValid)
  1369. {
  1370. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  1371. dwErr = HshQueryObjectRef(
  1372. g_lstIntfHashes.pHnGUID,
  1373. pIntfEntry->wszGuid,
  1374. &pNode);
  1375. if (dwErr == ERROR_SUCCESS)
  1376. {
  1377. pIntfContext = pNode->pObject;
  1378. LstRccsReference(pIntfContext);
  1379. }
  1380. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  1381. }
  1382. else
  1383. dwErr = ERROR_ARENA_TRASHED;
  1384. // the interface needs to exist in order to refresh it
  1385. if (dwErr == ERROR_SUCCESS)
  1386. {
  1387. LstRccsLock(pIntfContext);
  1388. // if description is requested to be refreshed, do it now
  1389. if (dwInFlags & INTF_DESCR)
  1390. {
  1391. CHAR QueryBuffer[QUERY_BUFFER_SIZE];
  1392. PNDISUIO_QUERY_BINDING pBinding;
  1393. RAW_DATA rdBuffer;
  1394. // get first the binding structure for this interface
  1395. rdBuffer.dwDataLen = sizeof(QueryBuffer);
  1396. rdBuffer.pData = QueryBuffer;
  1397. pBinding = (PNDISUIO_QUERY_BINDING)rdBuffer.pData;
  1398. dwLErr = DevioGetInterfaceBindingByGuid(
  1399. INVALID_HANDLE_VALUE, // the call will open Ndisuio locally
  1400. pIntfContext->wszGuid, // interface GUID as "{guid}"
  1401. &rdBuffer);
  1402. // regardless of success, lets clean the current description
  1403. MemFree(pIntfContext->wszDescr);
  1404. pIntfContext->wszDescr = NULL;
  1405. // if everything went fine
  1406. if (dwLErr == ERROR_SUCCESS)
  1407. {
  1408. LPWSTR wszName;
  1409. DWORD dwNameLen;
  1410. // Copy the interface's description.name
  1411. wszName = (LPWSTR)((LPBYTE)pBinding + pBinding->DeviceDescrOffset);
  1412. // the DeviceDescrLength is in bytes and includes the null terminator
  1413. dwNameLen = pBinding->DeviceDescrLength;
  1414. if (dwNameLen > 0)
  1415. {
  1416. pIntfContext->wszDescr = MemCAlloc(dwNameLen);
  1417. if (pIntfContext->wszGuid == NULL)
  1418. dwErr = GetLastError();
  1419. else
  1420. wcscpy(pIntfContext->wszDescr, wszName);
  1421. }
  1422. }
  1423. // if all went fine, mark it out
  1424. if (dwLErr == ERROR_SUCCESS)
  1425. dwOutFlags |= INTF_DESCR;
  1426. if (dwErr == ERROR_SUCCESS)
  1427. dwErr = dwLErr;
  1428. }
  1429. // refresh any ndis settings if requested
  1430. if (dwInFlags & INTF_NDISMEDIA)
  1431. {
  1432. dwLErr = DevioGetIntfStats(pIntfContext);
  1433. if (dwLErr == ERROR_SUCCESS)
  1434. dwOutFlags |= INTF_NDISMEDIA;
  1435. if (dwErr == ERROR_SUCCESS)
  1436. dwErr = dwLErr;
  1437. }
  1438. if (dwInFlags & INTF_ALL_OIDS)
  1439. {
  1440. DWORD dwLFlags = dwInFlags;
  1441. // feed the state machine with the "refresh command" for this context
  1442. dwLErr = StateDispatchEvent(eEventCmdRefresh, pIntfContext, &dwLFlags);
  1443. // clear up the INTFCTL_INTERNAL_BLK_MEDIACONN bit since this is not a media sense handler
  1444. pIntfContext->dwCtlFlags &= ~INTFCTL_INTERNAL_BLK_MEDIACONN;
  1445. if (dwLErr == ERROR_SUCCESS)
  1446. dwOutFlags |= dwLFlags;
  1447. if (dwErr == ERROR_SUCCESS)
  1448. dwErr = dwLErr;
  1449. }
  1450. LstRccsUnlockUnref(pIntfContext);
  1451. }
  1452. if (pdwOutFlags != NULL)
  1453. *pdwOutFlags = dwOutFlags;
  1454. DbgPrint((TRC_TRACK, "LstRefreshInterface]=%d", dwErr));
  1455. return dwErr;
  1456. }
  1457. //-----------------------------------------------------------
  1458. // Builds the list of configurations to be tried from the list of visible
  1459. // configurations, the list of preferred configurations and based on the
  1460. // interface's mode (Auto/Infra/Adhoc) and flags (is the service enabled?,
  1461. // fallback to visible?).
  1462. // [in] pIntfContext: Interface for which is done the selection
  1463. // [out] ppwzcSList: pointer to the list of selected configurations
  1464. //-----------------------------------------------------------
  1465. // Builds the list of configurations to be tried from the list of visible
  1466. // configurations, the list of preferred configurations and based on the
  1467. // interface's mode (Auto/Infra/Adhoc) and flags (is the service enabled?,
  1468. // fallback to visible?).
  1469. // [in] pIntfContext: Interface for which is done the selection
  1470. // [out] ppwzcSList: pointer to the list of selected configurations
  1471. DWORD
  1472. LstBuildSelectList(
  1473. PINTF_CONTEXT pIntfContext,
  1474. PWZC_802_11_CONFIG_LIST *ppwzcSList)
  1475. {
  1476. DWORD dwErr = ERROR_SUCCESS;
  1477. UINT i, n;
  1478. UINT nCnt[7] = {0};
  1479. ENUM_SELCATEG iVCtg, iPCtg, iCtg;
  1480. PWZC_WLAN_CONFIG pCrtSConfig = NULL;
  1481. DbgPrint((TRC_TRACK,"[LstBuildSelectList(0x%p)", pIntfContext));
  1482. DbgAssert((pIntfContext != NULL, "(null) Interface context in LstBuildSelectList"));
  1483. DbgAssert((ppwzcSList != NULL, "invalid (null) out param"));
  1484. // set the pointer to the selection list to NULL
  1485. (*ppwzcSList) = NULL;
  1486. // for each entry in the visible list (if any), if the entry is probable to be included
  1487. // in the selection set (either as Visible Infra or Visible Adhoc) set the category
  1488. // attribute to point to the corresponding set and ++ the corresponding counter.
  1489. // if the entry is not going to be included, set the same byte to eN (neutral)
  1490. if (pIntfContext->pwzcVList)
  1491. {
  1492. for (i=0; i < pIntfContext->pwzcVList->NumberOfItems; i++)
  1493. {
  1494. PWZC_WLAN_CONFIG pVConfig = &(pIntfContext->pwzcVList->Config[i]);
  1495. // the visible list might contain several APs for the same network.
  1496. // Make sure we exclude the duplicates from the selection list.
  1497. PWZC_WLAN_CONFIG pVDup = WzcFindConfig(pIntfContext->pwzcVList, pVConfig, i+1);
  1498. // don't even consider this visible network if:
  1499. // - another duplicate exists further in the list, or
  1500. // - "automatically connect to non-preferred network" is not selected or
  1501. // - its network type (infra / ad hoc) doesn't match the type selected in the intf config or
  1502. // - the entry is blocked in the "blocked configurations" list (pwzcBList)
  1503. if ((pVDup != NULL) ||
  1504. !(pIntfContext->dwCtlFlags & INTFCTL_FALLBACK) ||
  1505. (((pIntfContext->dwCtlFlags & INTFCTL_CM_MASK) != Ndis802_11AutoUnknown) &&
  1506. ((pIntfContext->dwCtlFlags & INTFCTL_CM_MASK) != pVConfig->InfrastructureMode)) ||
  1507. WzcFindConfig(pIntfContext->pwzcBList, pVConfig, 0) != NULL)
  1508. iVCtg = eN;
  1509. else if (pVConfig->InfrastructureMode == Ndis802_11Infrastructure)
  1510. iVCtg = eVI;
  1511. else if (pVConfig->InfrastructureMode == Ndis802_11IBSS)
  1512. iVCtg = eVA;
  1513. else
  1514. iVCtg = eN;
  1515. NWB_SET_SELCATEG(pVConfig, iVCtg);
  1516. nCnt[iVCtg]++;
  1517. }
  1518. }
  1519. // Locate the current successful configuration (if any) in the preferred list. This config
  1520. // should be marked Visible, regardless it is or not present in the visible list.
  1521. if (pIntfContext->pwzcSList != NULL &&
  1522. pIntfContext->pwzcSList->Index < pIntfContext->pwzcSList->NumberOfItems)
  1523. {
  1524. PWZC_WLAN_CONFIG pCrtConfig;
  1525. pCrtConfig = &(pIntfContext->pwzcSList->Config[pIntfContext->pwzcSList->Index]);
  1526. if (!(pCrtConfig->dwCtlFlags & WZCCTL_INTERNAL_DELETED))
  1527. pCrtSConfig = WzcFindConfig(pIntfContext->pwzcPList, pCrtConfig, 0);
  1528. }
  1529. // for each entry in the preferred list (if any), if the entry matches the interface's mode
  1530. // and is a "visible" one, put it in either eVPI or eVPA category and pull out the corresponding
  1531. // visible entry from eVI or eVA or eN (if that entry was not supposed to be included in the selection).
  1532. // If the entry is not "visible" put it either in ePI (only if the interface doesn't fallback to
  1533. // visible) or in ePA category.
  1534. if (pIntfContext->pwzcPList != NULL)
  1535. {
  1536. for (i=0; i < pIntfContext->pwzcPList->NumberOfItems; i++)
  1537. {
  1538. PWZC_WLAN_CONFIG pPConfig = &(pIntfContext->pwzcPList->Config[i]);
  1539. // don't even consider this preferred network if:
  1540. // - its network type (infra / ad hoc) doesn't match the type selected in the intf config or
  1541. // - the entry is blocked in the "blocked configurations" list (pwzcBList)
  1542. if ((((pIntfContext->dwCtlFlags & INTFCTL_CM_MASK) != Ndis802_11AutoUnknown) &&
  1543. ((pIntfContext->dwCtlFlags & INTFCTL_CM_MASK) != pPConfig->InfrastructureMode)) ||
  1544. WzcFindConfig(pIntfContext->pwzcBList, pPConfig, 0) != NULL)
  1545. {
  1546. iPCtg = eN;
  1547. }
  1548. else
  1549. {
  1550. PWZC_WLAN_CONFIG pVConfig = WzcFindConfig(pIntfContext->pwzcVList, pPConfig, 0);
  1551. if (pPConfig == pCrtSConfig || pVConfig != NULL)
  1552. {
  1553. // this preferred entry is either the current one or visible,
  1554. // so point it either to eVPI or eVPA
  1555. if (pPConfig->InfrastructureMode == Ndis802_11Infrastructure)
  1556. iPCtg = eVPI;
  1557. else if (pPConfig->InfrastructureMode == Ndis802_11IBSS)
  1558. iPCtg = eVPA;
  1559. else
  1560. iPCtg = eN;
  1561. if (pVConfig != NULL)
  1562. {
  1563. // the corresponding visible entry (if any) has to be pulled out from whichever
  1564. // category it was in and has to be put in eN (neutral)
  1565. nCnt[NWB_GET_SELCATEG(pVConfig)]--;
  1566. iVCtg = eN;
  1567. NWB_SET_SELCATEG(pVConfig, iVCtg);
  1568. nCnt[iVCtg]++;
  1569. }
  1570. else
  1571. {
  1572. DbgPrint((TRC_TRACK, "Non-visible crt config raised to visible categ %d.", iPCtg));
  1573. }
  1574. }
  1575. else
  1576. {
  1577. // this preferred entry is not visible, so either point it to ePI or to ePA.
  1578. if (pPConfig->InfrastructureMode == Ndis802_11Infrastructure)
  1579. iPCtg = ePI;
  1580. else if (pPConfig->InfrastructureMode == Ndis802_11IBSS)
  1581. iPCtg = ePA;
  1582. else
  1583. iPCtg = eN;
  1584. }
  1585. }
  1586. NWB_SET_SELCATEG(pPConfig, iPCtg);
  1587. nCnt[iPCtg]++;
  1588. }
  1589. }
  1590. // calculate the number of entries in the selection list
  1591. n = 0;
  1592. for (iCtg=eVPI; iCtg < eN; iCtg++)
  1593. n += nCnt[iCtg];
  1594. // if there are any entries to copy afterall..
  1595. if (n != 0)
  1596. {
  1597. // ..allocate the selection list
  1598. (*ppwzcSList) = (PWZC_802_11_CONFIG_LIST)
  1599. MemCAlloc(FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config) + n * sizeof(WZC_WLAN_CONFIG));
  1600. if ((*ppwzcSList) == NULL)
  1601. {
  1602. dwErr = GetLastError();
  1603. goto exit;
  1604. }
  1605. (*ppwzcSList)->NumberOfItems = n;
  1606. (*ppwzcSList)->Index = n;
  1607. // now change the semantic of all counters to mean "indices in the selection list"
  1608. // for their respective group of entries
  1609. for (iCtg = eN-1; iCtg >= eVPI; iCtg--)
  1610. {
  1611. n -= nCnt[iCtg];
  1612. nCnt[iCtg] = n;
  1613. }
  1614. }
  1615. exit:
  1616. // copy first the entries from the preferred list into the selection list,
  1617. // at the index corresponding to their categories.
  1618. if (pIntfContext->pwzcPList != NULL)
  1619. {
  1620. for (i=0; i < pIntfContext->pwzcPList->NumberOfItems; i++)
  1621. {
  1622. PWZC_WLAN_CONFIG pPConfig = &(pIntfContext->pwzcPList->Config[i]);
  1623. // get the category for this preferred configuration
  1624. iCtg = NWB_GET_SELCATEG(pPConfig);
  1625. // if we have a selection list to copy into, and the entry is supposed
  1626. // to be copied (not neutral) do it here
  1627. if ((*ppwzcSList) != NULL && iCtg != eN)
  1628. {
  1629. PWZC_WLAN_CONFIG pSConfig = &((*ppwzcSList)->Config[nCnt[iCtg]]);
  1630. // copy the whole preferred configuration (including the selection category
  1631. // & authentication mode) to the selection list
  1632. memcpy(pSConfig, pPConfig, sizeof(WZC_WLAN_CONFIG));
  1633. // just for making sure, reset the 'deleted' flag as this is a brand new
  1634. // config that was never attempted.
  1635. pSConfig->dwCtlFlags &= ~WZCCTL_INTERNAL_DELETED;
  1636. // the remaining attributes (selection category, authentication mode) should be
  1637. // left untouched.
  1638. // make sure we propagate the 'start from index' if the preferred list shows like
  1639. // a one time connect is requested
  1640. if (i == pIntfContext->pwzcPList->Index)
  1641. (*ppwzcSList)->Index = nCnt[iCtg];
  1642. nCnt[iCtg]++;
  1643. }
  1644. // reset the selection category we have used for this preferred entry
  1645. NWB_SET_SELCATEG(pPConfig, 0);
  1646. }
  1647. }
  1648. // next, copy the entries from the visible list into the selection list,
  1649. // at the index corresponding to their categories.
  1650. if (pIntfContext->pwzcVList != NULL)
  1651. {
  1652. for (i=0; i < pIntfContext->pwzcVList->NumberOfItems; i++)
  1653. {
  1654. PWZC_WLAN_CONFIG pVConfig = &(pIntfContext->pwzcVList->Config[i]);
  1655. iCtg = NWB_GET_SELCATEG(pVConfig);
  1656. // if we have a selection list to copy into, and the entry is supposed
  1657. // to be copied (not neutral) do it here
  1658. if ((*ppwzcSList) != NULL && iCtg != eN)
  1659. {
  1660. PWZC_WLAN_CONFIG pSConfig = &((*ppwzcSList)->Config[nCnt[iCtg]]);
  1661. // copy the whole visible configuration (including its selection category)
  1662. // to the selection set (for visible entries, authentication mode is 0 by default
  1663. // since this information is not provided by the nic/driver)
  1664. memcpy(pSConfig, pVConfig, sizeof(WZC_WLAN_CONFIG));
  1665. // just for making sure, reset the 'deleted' flag as this is a brand new
  1666. // config that was never attempted.
  1667. pSConfig->dwCtlFlags &= ~WZCCTL_INTERNAL_DELETED;
  1668. // bump up the index for this entry's category
  1669. nCnt[iCtg]++;
  1670. }
  1671. // reset the selection category we have used for this visible entry
  1672. NWB_SET_SELCATEG(pVConfig, 0);
  1673. }
  1674. }
  1675. DbgPrint((TRC_TRACK,"LstBuildSelectList]=%d", dwErr));
  1676. return dwErr;
  1677. }
  1678. //-----------------------------------------------------------
  1679. // Checks whether the list of selected configurations has changed such
  1680. // that it is required to replumb the selection.
  1681. // [in] pIntfContext: Interface for which is done the selection
  1682. // [in] pwzcSList: new selection list to check the configuration against
  1683. // [out] pnSelIdx: if selection changed, provides the index where to start iterate from
  1684. // Returns: TRUE if replumbing is required. In this case, pnSelIdx is
  1685. // set to the configuration to start iterate from.
  1686. BOOL
  1687. LstChangedSelectList(
  1688. PINTF_CONTEXT pIntfContext,
  1689. PWZC_802_11_CONFIG_LIST pwzcNSList,
  1690. LPUINT pnSelIdx)
  1691. {
  1692. BOOL bRet = FALSE;
  1693. DbgPrint((TRC_TRACK,"[LstChangedSelectList(0x%p)", pIntfContext));
  1694. DbgAssert((pnSelIdx != NULL,"invalid (null) pointer to out param"));
  1695. // before anything, zero out the index for the current selected network
  1696. *pnSelIdx = 0;
  1697. // if there is no configuration the current selected list,
  1698. // it means either we're just initializing the context or we failed all the
  1699. // other configs. Either way, we need to replumb the card according to the
  1700. // new selection list (if that one is also empty, we will follow the path
  1701. // {SQ}->{SIter}->{SF})
  1702. if (pIntfContext->pwzcSList == NULL ||
  1703. pIntfContext->pwzcSList->NumberOfItems == 0 ||
  1704. pwzcNSList == NULL ||
  1705. pwzcNSList->NumberOfItems == 0)
  1706. {
  1707. DbgPrint((TRC_STATE, "SelList changed? YES; the current/new selection list is empty"));
  1708. // since we're starting fresh, make sure to propagate the "one time connect" index, if any
  1709. if (pwzcNSList != NULL && pwzcNSList->Index < pwzcNSList->NumberOfItems)
  1710. *pnSelIdx = pwzcNSList->Index;
  1711. bRet = TRUE;
  1712. }
  1713. else // we do have an old SList we need to look at
  1714. {
  1715. PWZC_WLAN_CONFIG pSConfig; // current sucessful configuration
  1716. PWZC_WLAN_CONFIG pNSConfig; // successful configuration in the new selection list
  1717. DbgAssert((pIntfContext->pwzcSList->Index < pIntfContext->pwzcSList->NumberOfItems,
  1718. "Selection index %d points outside SList[0..%d]",
  1719. pIntfContext->pwzcSList->Index,
  1720. pIntfContext->pwzcSList->NumberOfItems));
  1721. // get a pointer to the current successful configuration
  1722. pSConfig = &(pIntfContext->pwzcSList->Config[pIntfContext->pwzcSList->Index]);
  1723. // as the first thing, let's check for the "one time connect". If this is requested,
  1724. // the one time config has to match with the current selected config. Otherwise this
  1725. // is a change already.
  1726. if (pwzcNSList->Index < pwzcNSList->NumberOfItems)
  1727. {
  1728. DbgPrint((TRC_STATE, "SList changed? Yes, \"one time connect\" is requested."));
  1729. // in this case, we do mark this as a "change". Otherwise it is difficult to keep
  1730. // the association to the "one time" connect for more than a scan cycle (other changes
  1731. // will take precedence to the next round, when "one time" connect flag won't be there
  1732. // anymore
  1733. *pnSelIdx = pwzcNSList->Index;
  1734. bRet = TRUE;
  1735. }
  1736. // if it is not decided yet whether it is a change (that is this is not a "one time connect")...
  1737. if (!bRet)
  1738. {
  1739. // search for the crt successful config into the new selection list.
  1740. pNSConfig = WzcFindConfig(pwzcNSList, pSConfig, 0);
  1741. if (pNSConfig == NULL)
  1742. {
  1743. UINT i;
  1744. ENUM_SELCATEG iSCtg;
  1745. DbgPrint((TRC_STATE, "SList changed? Don't know yet. The current config is not in the NSList"));
  1746. // the crt successful config is not in the new selection list. If the crt selection is
  1747. // marked as being of the "preferred" kind, there is no other way it could disappear
  1748. // other than being explicitly removed from the preferred list. In this case, yes,
  1749. // this is a change.
  1750. iSCtg = NWB_GET_SELCATEG(pSConfig);
  1751. if (iSCtg != eVI && iSCtg != eVA)
  1752. {
  1753. DbgPrint((TRC_STATE, "SList changed? Yes. The current preferred network has been removed."));
  1754. bRet = TRUE;
  1755. *pnSelIdx = 0; // iterate from the very beginning.
  1756. }
  1757. // In all the remaining cases (VI or VA), we need to check each of the new selected configurations
  1758. // if it doesn't prevail the current successful one.
  1759. for (i = 0; !bRet && i < pwzcNSList->NumberOfItems; i++)
  1760. {
  1761. PWZC_WLAN_CONFIG pNConfig, pConfig;
  1762. // get the new configuration and search it into the current selection list
  1763. pNConfig = &(pwzcNSList->Config[i]);
  1764. pConfig = WzcFindConfig(pIntfContext->pwzcSList, pNConfig, 0);
  1765. // if the new selected configuration was not tried before either because
  1766. // it just showed up or because we didn't get to try it previously,
  1767. // then it is a potential better candidate
  1768. if (pConfig == NULL || pSConfig < pConfig)
  1769. {
  1770. ENUM_SELCATEG iNSCtg;
  1771. // get the category for the new config
  1772. iNSCtg = NWB_GET_SELCATEG(pNConfig);
  1773. // if the new configuration has a prevailing category, we should
  1774. // definitely replumb starting from here
  1775. if (iNSCtg < iSCtg)
  1776. {
  1777. DbgPrint((TRC_STATE,"SList changed? YES; a config with a better category has been detected."));
  1778. bRet = TRUE;
  1779. *pnSelIdx = i;
  1780. }
  1781. // remember: here, the current selected config can only be VI or VA. That is, if the category of
  1782. // any newcomer in the selection list is even equal or greater that the current category, there
  1783. // is absolutely no point in moving out of here.
  1784. }
  1785. // there is a matching config which we tried before. We do acknowledge
  1786. // a change if the the two configs actually don't have matching content!
  1787. else if (!WzcMatchConfig(pNConfig, pConfig, NULL))
  1788. {
  1789. DbgPrint((TRC_STATE,"SList changed? YES; a better config failed before but it has been altered."));
  1790. bRet = TRUE;
  1791. *pnSelIdx = i;
  1792. }
  1793. }
  1794. }
  1795. else // the current selected network is still in the new selection list (pNSConfig)
  1796. {
  1797. UINT i;
  1798. // for each config in the new selection list, try to match it with an existent
  1799. // configuration in the crt selection list
  1800. for (i = 0; !bRet && i < pwzcNSList->NumberOfItems; i++)
  1801. {
  1802. PWZC_WLAN_CONFIG pNConfig, pConfig;
  1803. ENUM_SELCATEG iNSCtg, iSCtg;
  1804. // if we are already at the current successful configuration this means
  1805. // we didn't find any new config to justify replumbing the interface
  1806. pNConfig = &(pwzcNSList->Config[i]);
  1807. if (pNConfig == pNSConfig)
  1808. {
  1809. bRet = !WzcMatchConfig(pNConfig, pSConfig, NULL);
  1810. if (bRet)
  1811. DbgPrint((TRC_STATE,"SList changed? YES; no better config found, but the current one has been altered."));
  1812. else
  1813. DbgPrint((TRC_STATE, "SList changed? NO; there is no new config that was not tried yet"));
  1814. break;
  1815. }
  1816. // get the category for the config in the new list
  1817. iNSCtg = NWB_GET_SELCATEG(pNConfig);
  1818. // search the configuration from the new selection list into the old selection list
  1819. pConfig = WzcFindConfig(pIntfContext->pwzcSList, pNConfig, 0);
  1820. // if this is either a brand new config, or one that has
  1821. // been raised in front of the current selection...
  1822. if (pConfig == NULL || pSConfig < pConfig)
  1823. {
  1824. // ...if the category is different, or is the same as the one of the successful config
  1825. // but is of a "preferred" kind, then it means the list has changed.
  1826. if (iNSCtg != NWB_GET_SELCATEG(pNSConfig) || (iNSCtg != eVI && iNSCtg != eVA))
  1827. {
  1828. DbgPrint((TRC_STATE,"SList changed? YES: there is a new config of a different or preferred category"));
  1829. bRet = TRUE;
  1830. *pnSelIdx = i;
  1831. }
  1832. }
  1833. else
  1834. {
  1835. // there is a matching entry in the old selection list, in front of the current
  1836. // successful configuration. This means the configuration has been tried before and
  1837. // failed. However, it could happen that the configuration was tried when it was
  1838. // not visible and now it is visible. In such a case, we should attempt replumbing
  1839. iSCtg = NWB_GET_SELCATEG(pConfig);
  1840. if (iNSCtg != iSCtg && (iSCtg == ePI || iSCtg == ePA))
  1841. {
  1842. DbgPrint((TRC_STATE,"SList changed? YES: a better config failed before but its categ changed from %d to %d",
  1843. iSCtg, iNSCtg));
  1844. bRet = TRUE;
  1845. *pnSelIdx = i;
  1846. }
  1847. else if (!WzcMatchConfig(pNConfig, pConfig, NULL))
  1848. {
  1849. DbgPrint((TRC_STATE,"SList changed? YES; a better config failed before but it has been altered."));
  1850. bRet = TRUE;
  1851. *pnSelIdx = i;
  1852. }
  1853. }
  1854. }
  1855. }
  1856. }
  1857. }
  1858. DbgPrint((TRC_TRACK,"LstChangedSelectList]=%s", bRet ? "TRUE" : "FALSE"));
  1859. return bRet;
  1860. }
  1861. // fake WEP key to be used if there is no key set (and obviously web = disabled)
  1862. // and the remote guy requires privacy. This is a 104bit key.
  1863. BYTE g_chFakeKeyMaterial[] = {0x56, 0x09, 0x08, 0x98, 0x4D, 0x08, 0x11, 0x66, 0x42, 0x03, 0x01, 0x67, 0x66};
  1864. //-----------------------------------------------------------
  1865. // Plumbs the interface with the selected configuration as it is pointed
  1866. // out by pwzcSList fields in the pIntfContext. Optional, it can
  1867. // return in ppSelSSID the configuration that was plumbed down
  1868. // [in] pIntfContext: Interface context identifying ctl flags & the selected SSID
  1869. // [out] ppndSelSSID: pointer to the SSID that is being plumbed down.
  1870. DWORD
  1871. LstSetSelectedConfig(
  1872. PINTF_CONTEXT pIntfContext,
  1873. PWZC_WLAN_CONFIG *ppndSelSSID)
  1874. {
  1875. DWORD dwErr = ERROR_SUCCESS;
  1876. PWZC_WLAN_CONFIG pSConfig;
  1877. INTF_ENTRY IntfEntry = {0};
  1878. DWORD dwInFlags, dwOutFlags;
  1879. BYTE chBuffer[sizeof(NDIS_802_11_WEP) + WZCCTL_MAX_WEPK_MATERIAL - 1];
  1880. BOOL bFakeWKey = FALSE; // flag indicating whether the fake WEP key is needed
  1881. DbgPrint((TRC_TRACK, "[LstSetSelectedConfig(0x%p..)", pIntfContext));
  1882. DbgAssert((pIntfContext != NULL, "(null) interface context in LstSetSelectedConfig"));
  1883. if (pIntfContext->pwzcSList == NULL ||
  1884. pIntfContext->pwzcSList->Index >= pIntfContext->pwzcSList->NumberOfItems)
  1885. {
  1886. dwErr = ERROR_INVALID_PARAMETER;
  1887. goto exit;
  1888. }
  1889. // get a pointer to the configuration to set down to the card.
  1890. pSConfig = &(pIntfContext->pwzcSList->Config[pIntfContext->pwzcSList->Index]);
  1891. // build the IntfEntry object that will specify what exactly goes down to the card
  1892. dwInFlags = INTF_AUTHMODE | INTF_INFRAMODE | INTF_SSID;
  1893. // authentication mode
  1894. //IntfEntry.nAuthMode = NWB_GET_AUTHMODE(pSConfig);
  1895. IntfEntry.nAuthMode = pSConfig->AuthenticationMode;
  1896. // infrastructure mode
  1897. IntfEntry.nInfraMode = pSConfig->InfrastructureMode;
  1898. // SSID
  1899. IntfEntry.rdSSID.dwDataLen = pSConfig->Ssid.SsidLength;
  1900. IntfEntry.rdSSID.pData = pSConfig->Ssid.Ssid;
  1901. // if the configuration to be plumbed down requires the presence of a WEP Key...
  1902. if (pSConfig->Privacy || IntfEntry.nAuthMode != Ndis802_11AuthModeOpen)
  1903. {
  1904. // if there is a WEP key provided in this configuration plumb it down
  1905. if (pSConfig->dwCtlFlags & WZCCTL_WEPK_PRESENT)
  1906. {
  1907. PNDIS_802_11_WEP pndUserWKey = (PNDIS_802_11_WEP)chBuffer;
  1908. // build the ndis WEP key structure from the user's key
  1909. // the key is a "transmit" key, regardless the index
  1910. pndUserWKey->KeyIndex = 0x80000000 | pSConfig->KeyIndex;
  1911. pndUserWKey->KeyLength = pSConfig->KeyLength;
  1912. memcpy(pndUserWKey->KeyMaterial, pSConfig->KeyMaterial, WZCCTL_MAX_WEPK_MATERIAL);
  1913. pndUserWKey->Length = sizeof(NDIS_802_11_WEP) + pndUserWKey->KeyLength - 1;
  1914. // TODO: here is where we should decrypt inplace the WEP key
  1915. {
  1916. UINT i;
  1917. for (i = 0; i < WZCCTL_MAX_WEPK_MATERIAL; i++)
  1918. pndUserWKey->KeyMaterial[i] ^= g_chFakeKeyMaterial[(7*i)%13];
  1919. }
  1920. // and ask for it to be set down
  1921. IntfEntry.rdCtrlData.dwDataLen = pndUserWKey->Length;
  1922. IntfEntry.rdCtrlData.pData = (LPBYTE)pndUserWKey;
  1923. dwInFlags |= INTF_ADDWEPKEY;
  1924. DbgPrint((TRC_GENERIC,"Plumbing down the User WEP txKey [idx:%d,len:%d]",
  1925. pSConfig->KeyIndex,
  1926. pSConfig->KeyLength));
  1927. }
  1928. // if a WEP Key is needed but none is provided for this configuration...
  1929. else
  1930. {
  1931. // ...first thing to do is to ask the driver to reload its defaults.
  1932. dwErr = DevioSetEnumOID(
  1933. pIntfContext->hIntf,
  1934. OID_802_11_RELOAD_DEFAULTS,
  1935. (DWORD)Ndis802_11ReloadWEPKeys);
  1936. DbgAssert((dwErr == ERROR_SUCCESS, "Failed setting OID_802_11_RELOAD_DEFAULTS"));
  1937. // need to check if reloading the defaults fixed the issue (not having a key)
  1938. dwErr = DevioRefreshIntfOIDs(
  1939. pIntfContext,
  1940. INTF_WEPSTATUS,
  1941. NULL);
  1942. DbgAssert((dwErr == ERROR_SUCCESS, "Failed refreshing OID_802_11_WEP_STATUS"));
  1943. // if even after reloading the defaults, a key is still absent, then
  1944. // set down the hardcoded key.
  1945. if (dwErr == ERROR_SUCCESS &&
  1946. pIntfContext->wzcCurrent.Privacy == Ndis802_11WEPKeyAbsent)
  1947. {
  1948. PNDIS_802_11_WEP pndFakeWKey = (PNDIS_802_11_WEP)chBuffer;
  1949. // we should set the hardcoded WEP key
  1950. pndFakeWKey->KeyIndex = 0x80000000;
  1951. pndFakeWKey->KeyLength = 5; // the fake key has to be the smallest possible (40bit)
  1952. dwErr = WzcRndGenBuffer(pndFakeWKey->KeyMaterial, pndFakeWKey->KeyLength, 0, 255);
  1953. DbgAssert((dwErr == ERROR_SUCCESS, "Failed to generate the random fake wep key"));
  1954. pndFakeWKey->Length = sizeof(NDIS_802_11_WEP) + pndFakeWKey->KeyLength - 1;
  1955. // and ask for it to be set down
  1956. IntfEntry.rdCtrlData.dwDataLen = pndFakeWKey->Length;
  1957. IntfEntry.rdCtrlData.pData = (LPBYTE)pndFakeWKey;
  1958. dwInFlags |= INTF_ADDWEPKEY;
  1959. bFakeWKey = TRUE;
  1960. DbgPrint((TRC_GENERIC,"Plumbing down the Fake WEP txKey [len:%d]",
  1961. IntfEntry.rdCtrlData.dwDataLen));
  1962. }
  1963. }
  1964. // now enable WEP only if privacy is required and the current settings
  1965. // show the WEP is not enabled
  1966. if (pSConfig->Privacy && pIntfContext->wzcCurrent.Privacy != Ndis802_11WEPEnabled)
  1967. {
  1968. // and also we should enable WEP if it shows as not being
  1969. // already enabled
  1970. IntfEntry.nWepStatus = Ndis802_11WEPEnabled;
  1971. dwInFlags |= INTF_WEPSTATUS;
  1972. }
  1973. }
  1974. // if the configuration to be plumbed doesn't require privacy but currently
  1975. // WEP is enabled, disable it.
  1976. if (!pSConfig->Privacy && pIntfContext->wzcCurrent.Privacy == Ndis802_11WEPEnabled)
  1977. {
  1978. IntfEntry.nWepStatus = Ndis802_11WEPDisabled;
  1979. dwInFlags |= INTF_WEPSTATUS;
  1980. }
  1981. // if everything is fine so far...
  1982. if (dwErr == ERROR_SUCCESS)
  1983. {
  1984. // ...go and plumb the card with the settings below
  1985. dwErr = DevioSetIntfOIDs(
  1986. pIntfContext,
  1987. &IntfEntry,
  1988. dwInFlags,
  1989. &dwOutFlags);
  1990. // if we attempted to change the WEP Key...
  1991. if (dwInFlags & INTF_ADDWEPKEY)
  1992. {
  1993. //.. and the operation succeeded..
  1994. if (dwOutFlags & INTF_ADDWEPKEY)
  1995. {
  1996. // then either set the "fake key" flag - if it was a fake key..
  1997. if (bFakeWKey)
  1998. pIntfContext->dwCtlFlags |= INTFCTL_INTERNAL_FAKE_WKEY;
  1999. //..or reset it if we put a "real" key
  2000. else
  2001. pIntfContext->dwCtlFlags &= ~INTFCTL_INTERNAL_FAKE_WKEY;
  2002. }
  2003. // if plumbing down the key failed, leave the "fake key" flag as
  2004. // it is since there were no changes made.
  2005. }
  2006. // ...or if we didn't need to plumb a WEP key, reset the flag
  2007. else
  2008. {
  2009. pIntfContext->dwCtlFlags &= ~INTFCTL_INTERNAL_FAKE_WKEY;
  2010. }
  2011. }
  2012. if (dwErr != ERROR_SUCCESS)
  2013. DbLogWzcError(WZCSVC_ERR_CFG_PLUMB,
  2014. pIntfContext,
  2015. DbLogFmtSSID(0, &(pSConfig->Ssid)),
  2016. dwErr);
  2017. exit:
  2018. DbgPrint((TRC_TRACK, "LstSetSelectedConfig]=%d", dwErr));
  2019. return dwErr;
  2020. }
  2021. //-----------------------------------------------------------
  2022. // PnP notification handler
  2023. // [in/out] ppIntfContext: Pointer to the Interface context for which
  2024. // the notification was received
  2025. // [in] dwNotifCode: Notification code (WZCNOTIF_*)
  2026. // [in] wszDeviceKey: Key info on the device for which the notification
  2027. // was received
  2028. DWORD
  2029. LstNotificationHandler(
  2030. PINTF_CONTEXT *ppIntfContext,
  2031. DWORD dwNotifCode,
  2032. LPWSTR wszDeviceKey)
  2033. {
  2034. DWORD dwErr = ERROR_SUCCESS;
  2035. PINTF_CONTEXT pIntfContext = *ppIntfContext;
  2036. DbgPrint((TRC_TRACK,"[LstNotificationHandler(0x%p, %d, %S)",
  2037. pIntfContext,
  2038. dwNotifCode,
  2039. wszDeviceKey));
  2040. if ((dwNotifCode == WZCNOTIF_DEVICE_ARRIVAL || dwNotifCode == WZCNOTIF_ADAPTER_BIND) &&
  2041. pIntfContext == NULL)
  2042. {
  2043. CHAR QueryBuffer[QUERY_BUFFER_SIZE];
  2044. PNDISUIO_QUERY_BINDING pQueryBinding;
  2045. RAW_DATA rdBuffer;
  2046. // get first the binding structure for this interface
  2047. rdBuffer.dwDataLen = sizeof(QueryBuffer);
  2048. rdBuffer.pData = QueryBuffer;
  2049. pQueryBinding = (PNDISUIO_QUERY_BINDING)rdBuffer.pData;
  2050. dwErr = DevioGetInterfaceBindingByGuid(
  2051. INVALID_HANDLE_VALUE, // the call will open Ndisuio locally
  2052. wszDeviceKey, // interface GUID as "{guid}"
  2053. &rdBuffer);
  2054. // if everything went fine
  2055. if (dwErr != ERROR_SUCCESS)
  2056. goto exit;
  2057. // go build the INTF_CONTEXT structure, based on
  2058. // the binding information (key info for the adapter)
  2059. dwErr = LstConstructIntfContext(
  2060. pQueryBinding,
  2061. &pIntfContext);
  2062. if (dwErr == ERROR_SUCCESS)
  2063. {
  2064. // increase its ref count and lock it up here
  2065. LstRccsReference(pIntfContext);
  2066. LstRccsLock(pIntfContext);
  2067. // add it to the hashes
  2068. dwErr = LstAddIntfToHashes(pIntfContext);
  2069. if (dwErr == ERROR_SUCCESS)
  2070. {
  2071. dwErr = StateDispatchEvent(
  2072. eEventAdd,
  2073. pIntfContext,
  2074. NULL);
  2075. }
  2076. // if for any reason hashing or dispatching failed, cleanup the context here
  2077. if (dwErr != ERROR_SUCCESS)
  2078. LstRemoveIntfContext(pIntfContext);
  2079. // release the context here
  2080. LstRccsUnlockUnref(pIntfContext);
  2081. }
  2082. // it could happen that a context was created but it turned out to be a non-wireless
  2083. // adapter. In this case all memory has been freed up, but pIntfContext remained
  2084. // non-null. We need to set this pointer back to null as it will be passed up.
  2085. if (dwErr != ERROR_SUCCESS)
  2086. pIntfContext = NULL;
  2087. }
  2088. // either for arrival or removal, we attempt to remove any identical context
  2089. // If it is about an arrival, we shouldn't have any duplicate but who knows
  2090. if ((dwNotifCode == WZCNOTIF_DEVICE_REMOVAL || dwNotifCode == WZCNOTIF_ADAPTER_UNBIND) &&
  2091. pIntfContext != NULL)
  2092. {
  2093. // increase its ref count and lock it up here
  2094. LstRccsReference(pIntfContext);
  2095. LstRccsLock(pIntfContext);
  2096. DbLogWzcInfo(WZCSVC_EVENT_REMOVE, pIntfContext,
  2097. pIntfContext->wszDescr);
  2098. // save the interface's settings to the registry
  2099. dwErr = StoSaveIntfConfig(NULL, pIntfContext);
  2100. DbgAssert((dwErr == ERROR_SUCCESS,
  2101. "StoSaveIntfConfig failed for Intf context 0x%p",
  2102. pIntfContext));
  2103. // prepare this context for destruction
  2104. LstRemoveIntfContext(pIntfContext);
  2105. // at this point, there are no other timer routines that are going to be fired. Whatever
  2106. // has been already fired ++ed the reference counter already so there is no risk to delete
  2107. // the data prematurely (when unref-ing this context). Also the timer has been deleted, but
  2108. // before doing so the timer handle has been set to INVALID_HANDLE_VALUE so there is no risk
  2109. // some other thread is trying to set a deleted timer (besides, we're still holding the
  2110. // context's critical section hence there can be no such other thread competing here).
  2111. // release the context here
  2112. LstRccsUnlockUnref(pIntfContext);
  2113. // since the resulting IntfContext is passed back to the caller,
  2114. // make the local pointer NULL (it will be returned later in the out param)
  2115. pIntfContext = NULL;
  2116. }
  2117. // for media connect & disconnect..
  2118. if (dwNotifCode == WZCNOTIF_MEDIA_CONNECT || dwNotifCode == WZCNOTIF_MEDIA_DISCONNECT)
  2119. {
  2120. // NOTE: keep in mind, pIntfContext is valid because we're in the critical section
  2121. // for the hashes.
  2122. //
  2123. // if there is a context under Zero Conf control, dispatch the event to the
  2124. // state machine
  2125. if (pIntfContext != NULL)
  2126. {
  2127. // first lock the context since the state machine deals only with locked contexts
  2128. LstRccsReference(pIntfContext);
  2129. LstRccsLock(pIntfContext);
  2130. dwErr = StateDispatchEvent(
  2131. dwNotifCode == WZCNOTIF_MEDIA_CONNECT ? eEventConnect : eEventDisconnect,
  2132. pIntfContext,
  2133. NULL);
  2134. LstRccsUnlockUnref(pIntfContext);
  2135. }
  2136. else
  2137. {
  2138. dwErr = ERROR_FILE_NOT_FOUND;
  2139. }
  2140. }
  2141. exit:
  2142. *ppIntfContext = pIntfContext;
  2143. DbgPrint((TRC_TRACK,"LstNotificationHandler]=%d", dwErr));
  2144. return dwErr;
  2145. }
  2146. //-----------------------------------------------------------
  2147. // Application Command call.
  2148. // [in] dwHandle: key for identifying the context (state) to which this cmd is referring
  2149. // [in] dwCmdCode: Command code (one of the WZCCMD_* contants)
  2150. // [in] wszIntfGuid: the guid of the interface to which this cmd is addressed
  2151. // [in] prdUserData: Application data associated to this command
  2152. DWORD
  2153. LstCmdInterface(
  2154. DWORD dwHandle,
  2155. DWORD dwCmdCode,
  2156. LPWSTR wszIntfGuid,
  2157. PRAW_DATA prdUserData)
  2158. {
  2159. DWORD dwErr = ERROR_FILE_NOT_FOUND;
  2160. PHASH_NODE pNode = NULL;
  2161. PINTF_CONTEXT pIntfContext;
  2162. DbgPrint((TRC_TRACK, "[LstCmdInterface(hdl=0x%x, cmd=0x%x,...)", dwHandle, dwCmdCode));
  2163. if (g_lstIntfHashes.bValid)
  2164. {
  2165. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  2166. dwErr = HshQueryObjectRef(
  2167. g_lstIntfHashes.pHnGUID,
  2168. wszIntfGuid,
  2169. &pNode);
  2170. if (dwErr == ERROR_SUCCESS)
  2171. {
  2172. pIntfContext = pNode->pObject;
  2173. // bump up the reference counter since we're going
  2174. // to work with this object
  2175. LstRccsReference(pIntfContext);
  2176. }
  2177. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  2178. }
  2179. else
  2180. dwErr = ERROR_ARENA_TRASHED;
  2181. // a failure at this point, means there was no context
  2182. // to lock so we can safely go to 'exit'
  2183. if (dwErr != ERROR_SUCCESS)
  2184. goto exit;
  2185. // Lock the context now
  2186. LstRccsLock(pIntfContext);
  2187. // don't do any processing if the handle passed down with the
  2188. // command doesn't match the session handle (meaning the command
  2189. // refers to the right iteration loop).
  2190. if (dwCmdCode == WZCCMD_HARD_RESET ||
  2191. dwHandle == pIntfContext->dwSessionHandle)
  2192. {
  2193. ESTATE_EVENT StateEvent;
  2194. BOOL bIgnore = FALSE; // tells whether the state machine needs to be kicked
  2195. // for this command.
  2196. BOOL bCopy = TRUE; // tells whether the user data needs to be copied
  2197. // in the successful config context.
  2198. DWORD dwRefreshOIDs = 0;
  2199. LPVOID pEventData = NULL;
  2200. PWZC_WLAN_CONFIG pSConfig = NULL;
  2201. // translate the command code to the internal event
  2202. switch (dwCmdCode)
  2203. {
  2204. case WZCCMD_HARD_RESET:
  2205. bCopy = FALSE; // no need to copy anything on hard reset!
  2206. StateEvent = eEventCmdReset;
  2207. break;
  2208. case WZCCMD_SOFT_RESET:
  2209. StateEvent = eEventCmdRefresh;
  2210. dwRefreshOIDs = INTF_LIST_SCAN;
  2211. pEventData = &dwRefreshOIDs;
  2212. break;
  2213. case WZCCMD_CFG_NEXT:
  2214. StateEvent = eEventCmdCfgNext;
  2215. break;
  2216. case WZCCMD_CFG_DELETE:
  2217. StateEvent = eEventCmdCfgDelete;
  2218. break;
  2219. case WZCCMD_CFG_NOOP:
  2220. StateEvent = eEventCmdCfgNoop;
  2221. break;
  2222. case WZCCMD_CFG_SETDATA:
  2223. bIgnore = TRUE;
  2224. break;
  2225. case WZCCMD_SKEY_QUERY:
  2226. bIgnore = TRUE; bCopy = FALSE;
  2227. dwErr = ERROR_SUCCESS;
  2228. if (prdUserData == NULL)
  2229. {
  2230. dwErr = ERROR_INVALID_PARAMETER;
  2231. }
  2232. else
  2233. {
  2234. if (pIntfContext->pSecSessionKeys == NULL)
  2235. {
  2236. prdUserData->dwDataLen = 0;
  2237. }
  2238. else if (prdUserData->dwDataLen < sizeof(SESSION_KEYS))
  2239. {
  2240. prdUserData->dwDataLen = sizeof(SESSION_KEYS);
  2241. dwErr = ERROR_MORE_DATA;
  2242. }
  2243. else
  2244. {
  2245. PSESSION_KEYS pSK = (PSESSION_KEYS) prdUserData->pData;
  2246. dwErr = WzcSSKDecrypt(pIntfContext->pSecSessionKeys, pSK);
  2247. }
  2248. }
  2249. break;
  2250. case WZCCMD_SKEY_SET:
  2251. bIgnore = TRUE; bCopy = FALSE;
  2252. dwErr = ERROR_SUCCESS;
  2253. if (prdUserData == NULL)
  2254. {
  2255. WzcSSKFree(pIntfContext->pSecSessionKeys);
  2256. pIntfContext->pSecSessionKeys = NULL;
  2257. }
  2258. else if (prdUserData->dwDataLen != sizeof(SESSION_KEYS))
  2259. {
  2260. dwErr = ERROR_INVALID_PARAMETER;
  2261. }
  2262. else
  2263. {
  2264. if (pIntfContext->pSecSessionKeys == NULL)
  2265. {
  2266. pIntfContext->pSecSessionKeys = MemCAlloc(sizeof(SEC_SESSION_KEYS));
  2267. if (pIntfContext->pSecSessionKeys == NULL)
  2268. dwErr = GetLastError();
  2269. }
  2270. if (dwErr == ERROR_SUCCESS)
  2271. {
  2272. PSESSION_KEYS pSK = (PSESSION_KEYS) prdUserData->pData;
  2273. WzcSSKClean(pIntfContext->pSecSessionKeys);
  2274. dwErr = WzcSSKEncrypt(pIntfContext->pSecSessionKeys, pSK);
  2275. }
  2276. }
  2277. break;
  2278. default:
  2279. // just in case we were just asked to set the BLOB (and we did this already)
  2280. // or some bogus code came in, no event will be dispatched to the state machine
  2281. bIgnore = TRUE;
  2282. break;
  2283. }
  2284. // copy down the user data to the config currently selected
  2285. if (bCopy && pIntfContext->pwzcSList != NULL &&
  2286. pIntfContext->pwzcSList->Index < pIntfContext->pwzcSList->NumberOfItems)
  2287. {
  2288. pSConfig = &(pIntfContext->pwzcSList->Config[pIntfContext->pwzcSList->Index]);
  2289. // if whatever buffer we already have is not large enough, clean it out
  2290. if (prdUserData == NULL || pSConfig->rdUserData.dwDataLen < prdUserData->dwDataLen)
  2291. {
  2292. MemFree(pSConfig->rdUserData.pData);
  2293. pSConfig->rdUserData.pData = NULL;
  2294. pSConfig->rdUserData.dwDataLen = 0;
  2295. }
  2296. // if a new buffer will be needed, allocate it here.
  2297. if (prdUserData != NULL && prdUserData->dwDataLen > pSConfig->rdUserData.dwDataLen)
  2298. {
  2299. pSConfig->rdUserData.pData = MemCAlloc(prdUserData->dwDataLen);
  2300. if (pSConfig->rdUserData.pData == NULL)
  2301. {
  2302. dwErr = GetLastError();
  2303. goto exit;
  2304. }
  2305. pSConfig->rdUserData.dwDataLen = prdUserData->dwDataLen;
  2306. }
  2307. // if there is any user data to store, do it here
  2308. if (prdUserData != NULL && prdUserData->dwDataLen > 0)
  2309. memcpy(pSConfig->rdUserData.pData, prdUserData->pData, prdUserData->dwDataLen);
  2310. }
  2311. // if this command is not to be ignored, dispatch the
  2312. // corresponding state event to the state machine dispatcher.
  2313. if (!bIgnore)
  2314. {
  2315. dwErr = StateDispatchEvent(
  2316. StateEvent,
  2317. pIntfContext,
  2318. pEventData);
  2319. // clear up the INTFCTL_INTERNAL_BLK_MEDIACONN bit since this is not a media sense handler
  2320. pIntfContext->dwCtlFlags &= ~INTFCTL_INTERNAL_BLK_MEDIACONN;
  2321. }
  2322. }
  2323. // Unlock the context now
  2324. LstRccsUnlockUnref(pIntfContext);
  2325. exit:
  2326. DbgPrint((TRC_TRACK, "LstCmdInterface]=%d", dwErr));
  2327. return dwErr;
  2328. }
  2329. //-----------------------------------------------------------
  2330. // Network Connection's status query
  2331. // [in] wszIntfGuid: the guid of the interface to which this cmd is addressed
  2332. // [out] pncs: network connection status, if controlled by WZC.
  2333. HRESULT
  2334. LstQueryGUIDNCStatus(
  2335. LPWSTR wszIntfGuid,
  2336. NETCON_STATUS *pncs)
  2337. {
  2338. DWORD dwErr = ERROR_FILE_NOT_FOUND;
  2339. HRESULT hr = S_FALSE;
  2340. PHASH_NODE pNode = NULL;
  2341. PINTF_CONTEXT pIntfContext;
  2342. DbgPrint((TRC_TRACK, "[LstQueryGUIDNCStatus(%S)", wszIntfGuid));
  2343. if (g_lstIntfHashes.bValid)
  2344. {
  2345. EnterCriticalSection(&g_lstIntfHashes.csMutex);
  2346. dwErr = HshQueryObjectRef(
  2347. g_lstIntfHashes.pHnGUID,
  2348. wszIntfGuid,
  2349. &pNode);
  2350. if (dwErr == ERROR_SUCCESS)
  2351. {
  2352. pIntfContext = pNode->pObject;
  2353. // bump up the reference counter since we're going
  2354. // to work with this object
  2355. LstRccsReference(pIntfContext);
  2356. }
  2357. LeaveCriticalSection(&g_lstIntfHashes.csMutex);
  2358. }
  2359. else
  2360. dwErr = ERROR_ARENA_TRASHED;
  2361. // a failure at this point, means there was no context
  2362. // to lock so we can safely go to 'exit'
  2363. if (dwErr != ERROR_SUCCESS)
  2364. goto exit;
  2365. // Lock the context now
  2366. LstRccsLock(pIntfContext);
  2367. // we control the state only if WZC is enabled and the adapter is
  2368. // anything else but connected. Otherwise the upper layer protocols
  2369. // are in control.
  2370. //
  2371. // For now (WinXP client RTM), Zero Config should report to NETMAN only the
  2372. // disconnected state. This is to fix bug #401130 which is NETSHELL displaying
  2373. // the bogus SSID from the {SF} state, while the IP address is lost and until
  2374. // the media disconnect is received (10 seconds later).
  2375. if (pIntfContext->dwCtlFlags & INTFCTL_ENABLED &&
  2376. pIntfContext->dwCtlFlags & INTFCTL_OIDSSUPP &&
  2377. pIntfContext->ncStatus != NCS_CONNECTED)
  2378. {
  2379. *pncs = NCS_MEDIA_DISCONNECTED;
  2380. hr = S_OK;
  2381. }
  2382. // Unlock the context now
  2383. LstRccsUnlockUnref(pIntfContext);
  2384. exit:
  2385. DbgPrint((TRC_TRACK, "LstQueryGUIDNCStatus]=%d", dwErr));
  2386. return hr;
  2387. }
  2388. //-----------------------------------------------------------
  2389. // Generate the initial dynamic session keys.
  2390. // [in] pIntfContext: Interface context containing the material for initial key generation.
  2391. DWORD
  2392. LstGenInitialSessionKeys(
  2393. PINTF_CONTEXT pIntfContext)
  2394. {
  2395. DWORD dwErr = ERROR_SUCCESS;
  2396. PWZC_WLAN_CONFIG pSConfig = NULL;
  2397. NDIS_802_11_MAC_ADDRESS ndMAC[2] = {0};
  2398. SESSION_KEYS SessionKeys;
  2399. UCHAR KeyMaterial[WZCCTL_MAX_WEPK_MATERIAL];
  2400. if (pIntfContext->pwzcSList != NULL &&
  2401. pIntfContext->pwzcSList->Index < pIntfContext->pwzcSList->NumberOfItems)
  2402. {
  2403. pSConfig = &(pIntfContext->pwzcSList->Config[pIntfContext->pwzcSList->Index]);
  2404. }
  2405. if (pSConfig != NULL && pSConfig->dwCtlFlags & WZCCTL_WEPK_PRESENT)
  2406. {
  2407. // get the random info needed for the key generation (RemoteMAC | LocalMAC ).
  2408. pSConfig = &(pIntfContext->pwzcSList->Config[pIntfContext->pwzcSList->Index]);
  2409. memcpy(&ndMAC[0], &pSConfig->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS));
  2410. memcpy(&ndMAC[1], &pIntfContext->ndLocalMac, sizeof(NDIS_802_11_MAC_ADDRESS));
  2411. // generate dynamic keys starting from unscrambled WEP
  2412. {
  2413. UINT i;
  2414. for (i = 0; i < WZCCTL_MAX_WEPK_MATERIAL; i++)
  2415. KeyMaterial[i] = pSConfig->KeyMaterial[i] ^ g_chFakeKeyMaterial[(7*i)%13];
  2416. }
  2417. dwErr = GenerateDynamicKeys(
  2418. KeyMaterial,
  2419. pSConfig->KeyLength,
  2420. (LPBYTE)&ndMAC[0],
  2421. sizeof(ndMAC),
  2422. pSConfig->KeyLength,
  2423. &SessionKeys);
  2424. if (dwErr == ERROR_SUCCESS)
  2425. {
  2426. WzcSSKFree(pIntfContext->pSecSessionKeys);
  2427. pIntfContext->pSecSessionKeys = MemCAlloc(sizeof(SEC_SESSION_KEYS));
  2428. if (pIntfContext->pSecSessionKeys == NULL)
  2429. {
  2430. dwErr = GetLastError();
  2431. }
  2432. else
  2433. {
  2434. dwErr = WzcSSKEncrypt(pIntfContext->pSecSessionKeys, &SessionKeys);
  2435. }
  2436. }
  2437. }
  2438. return dwErr;
  2439. }
  2440. //-----------------------------------------------------------
  2441. // Updates the list of blocked configurations with the selected configurations
  2442. // that were blocked at this round by the upper layer (marked with WZCCTL_INTERNAL_BLOCKED
  2443. // in the list of selected configurations)
  2444. // [in] pIntfContext: Interface context containing the configurations lists
  2445. DWORD
  2446. LstUpdateBlockedList(
  2447. PINTF_CONTEXT pIntfContext)
  2448. {
  2449. DWORD dwErr = ERROR_SUCCESS;
  2450. UINT i, nBlocked = 0;
  2451. PWZC_802_11_CONFIG_LIST pNewBList = NULL;
  2452. PWZC_WLAN_CONFIG pConfig;
  2453. BOOL bChanged = FALSE;
  2454. DbgPrint((TRC_TRACK, "[LstUpdateBlockedList(0x%p)", pIntfContext));
  2455. // the first thing is to count how many blocked configurations we have
  2456. // check first the current blocked list for blocked configs still "alive"
  2457. if (pIntfContext->pwzcBList != NULL)
  2458. {
  2459. for (i=0; i < pIntfContext->pwzcBList->NumberOfItems; i++)
  2460. {
  2461. if (pIntfContext->pwzcBList->Config[i].Reserved[0] > 0)
  2462. nBlocked++;
  2463. else
  2464. bChanged = TRUE; // this entry is going to be removed!
  2465. }
  2466. }
  2467. // check now how many configs are going to be blocked from the current selection list
  2468. // NOTE: the entries from the SList are guaranteed not to duplicate entries in the BList
  2469. // If an entry is in the BList it means it was excluded from being added to the SList
  2470. // when the SList was created.
  2471. if (pIntfContext->pwzcSList != NULL)
  2472. {
  2473. for (i=0; i < pIntfContext->pwzcSList->NumberOfItems; i++)
  2474. {
  2475. if (pIntfContext->pwzcSList->Config[i].dwCtlFlags & WZCCTL_INTERNAL_BLOCKED)
  2476. {
  2477. nBlocked++;
  2478. bChanged = TRUE; // a new entry becomes blocked
  2479. }
  2480. }
  2481. }
  2482. // if we found there are no blocked entries, nor in the original list not in the current
  2483. // (failed) selection list, just go out successfully - it means the original pwzcBList
  2484. // is already NULL and it should remain this way
  2485. if (nBlocked == 0)
  2486. goto exit;
  2487. pNewBList = (PWZC_802_11_CONFIG_LIST)
  2488. MemCAlloc(FIELD_OFFSET(WZC_802_11_CONFIG_LIST, Config) + nBlocked * sizeof(WZC_WLAN_CONFIG));
  2489. // on memory allocation error, get out with the error code
  2490. if (pNewBList == NULL)
  2491. {
  2492. dwErr = GetLastError();
  2493. goto exit;
  2494. }
  2495. // if originally there were some alive blocked entries, copy them over to the new list
  2496. if (pIntfContext->pwzcBList != NULL)
  2497. {
  2498. for (i=0; i < pIntfContext->pwzcBList->NumberOfItems && nBlocked > 0; i++)
  2499. {
  2500. pConfig = &(pIntfContext->pwzcBList->Config[i]);
  2501. if (pConfig->Reserved[0] > 0)
  2502. {
  2503. memcpy(&(pNewBList->Config[pNewBList->NumberOfItems]),
  2504. pConfig,
  2505. sizeof(WZC_WLAN_CONFIG));
  2506. // make sure the copy doesn't include any "user" data:
  2507. pConfig->rdUserData.pData = NULL;
  2508. pConfig->rdUserData.dwDataLen = 0;
  2509. // don't touch anything from this blocked configuration. TTL goes down
  2510. // by itself with each scan (if network is not available)
  2511. pNewBList->NumberOfItems++;
  2512. // make sure we are breaking the loop if we have no storage for any potential
  2513. // blocked configuration. This shouldn't happen since we were counting these first
  2514. // and the whole context is locked, but ... it doesn't hurt
  2515. nBlocked--;
  2516. }
  2517. }
  2518. }
  2519. // now copy over the new blocked entries, if any
  2520. if (pIntfContext->pwzcSList != NULL)
  2521. {
  2522. for (i=0; i < pIntfContext->pwzcSList->NumberOfItems && nBlocked > 0; i++)
  2523. {
  2524. pConfig = &(pIntfContext->pwzcSList->Config[i]);
  2525. if (pConfig->dwCtlFlags & WZCCTL_INTERNAL_BLOCKED)
  2526. {
  2527. memcpy(&(pNewBList->Config[pNewBList->NumberOfItems]),
  2528. pConfig,
  2529. sizeof(WZC_WLAN_CONFIG));
  2530. // make sure the copy doesn't include any "user" data:
  2531. pConfig->rdUserData.pData = NULL;
  2532. pConfig->rdUserData.dwDataLen = 0;
  2533. // make sure to set the initial TTL for the new blocked configuration
  2534. pNewBList->Config[pNewBList->NumberOfItems].Reserved[0] = WZC_INTERNAL_BLOCKED_TTL;
  2535. pNewBList->NumberOfItems++;
  2536. // make sure we are breaking the loop if we have no storage for any potential
  2537. // blocked configuration. This shouldn't happen since we were counting these first
  2538. // and the whole context is locked, but ... it doesn't hurt
  2539. nBlocked--;
  2540. }
  2541. }
  2542. }
  2543. // everything is ok - nothing can fail further, so make pNewBList the official pBList
  2544. WzcCleanupWzcList(pIntfContext->pwzcBList);
  2545. pIntfContext->pwzcBList = pNewBList;
  2546. if (bChanged)
  2547. {
  2548. DbLogWzcInfo(WZCSVC_BLIST_CHANGED,
  2549. pIntfContext,
  2550. pIntfContext->pwzcBList != NULL ? pIntfContext->pwzcBList->NumberOfItems : 0);
  2551. }
  2552. exit:
  2553. DbgPrint((TRC_TRACK, "LstUpdateBlockedList]=%d", dwErr));
  2554. return dwErr;
  2555. }
  2556. //-----------------------------------------------------------
  2557. // Checks each of the entries in the locked list against the visible list. If the
  2558. // entry is visible, its TTL is reset. If it is not, its TTL is decremented. If the
  2559. // TTL becomes 0, the entry is taken out of the list.
  2560. // [in] pIntfContext: Interface context containing the configurations lists
  2561. DWORD
  2562. LstDeprecateBlockedList(
  2563. PINTF_CONTEXT pIntfContext)
  2564. {
  2565. DWORD dwErr = ERROR_SUCCESS;
  2566. UINT i;
  2567. PWZC_WLAN_CONFIG pConfig, pVConfig;
  2568. BOOL bChanged = FALSE;
  2569. DbgPrint((TRC_TRACK, "[LstDeprecateBlockedList(0x%p)", pIntfContext));
  2570. // nothing to do if there is no list of blocked entries
  2571. if (pIntfContext->pwzcBList == NULL)
  2572. goto exit;
  2573. for (i=0; i < pIntfContext->pwzcBList->NumberOfItems; i++)
  2574. {
  2575. pConfig = &(pIntfContext->pwzcBList->Config[i]);
  2576. // if the blocked entry appears to be visible, reset its TTL
  2577. if (WzcFindConfig(pIntfContext->pwzcVList, pConfig, 0) != NULL)
  2578. pConfig->Reserved[0] = WZC_INTERNAL_BLOCKED_TTL;
  2579. else // else decrement its TTL
  2580. pConfig->Reserved[0]--;
  2581. // if the TTL got to 0, the entry needs to be removed from the list
  2582. // (exchange with the very last one and the list is made 1 entry shorted)
  2583. if (pConfig->Reserved[0] == 0)
  2584. {
  2585. UINT nLastIdx = pIntfContext->pwzcBList->NumberOfItems - 1;
  2586. // if this is not the very last entry, exchange it with the last one
  2587. // but first clean it out since it will be unreachable for WzcCleanupWzcList()
  2588. MemFree(pConfig->rdUserData.pData);
  2589. if (i != nLastIdx)
  2590. {
  2591. memcpy(pConfig, &(pIntfContext->pwzcBList->Config[nLastIdx]), sizeof(WZC_WLAN_CONFIG));
  2592. }
  2593. // make the list one entry shorter since the removed entry is now at the end
  2594. pIntfContext->pwzcBList->NumberOfItems--;
  2595. // next time stay on the same index as at this iteration.
  2596. i--;
  2597. // now since this went away, note the change
  2598. bChanged = TRUE;
  2599. }
  2600. }
  2601. if (bChanged)
  2602. {
  2603. DbLogWzcInfo(WZCSVC_BLIST_CHANGED,
  2604. pIntfContext,
  2605. pIntfContext->pwzcBList->NumberOfItems);
  2606. }
  2607. exit:
  2608. DbgPrint((TRC_TRACK, "LstDeprecateBlockedList]=%d", dwErr));
  2609. return dwErr;
  2610. }