Source code of Windows XP (NT5)
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.

2850 lines
82 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. eldeviceio.c
  5. Abstract:
  6. This module contains implementations for media-management and device I/O.
  7. The routines declared here operate asynchronously on the handles
  8. associated with an I/O completion port opened on the ndis uio driver.
  9. Revision History:
  10. sachins, Apr 23 2000, Created
  11. --*/
  12. #include "pcheapol.h"
  13. #pragma hdrstop
  14. // NDISUIO constants
  15. CHAR NdisuioDevice[] = "\\\\.\\\\Ndisuio";
  16. CHAR * pNdisuioDevice = &NdisuioDevice[0];
  17. WCHAR cwszNDISUIOProtocolName[] = L"NDISUIO";
  18. WORD g_wEtherType8021X= 0x8E88;
  19. //
  20. // ElMediaInit
  21. //
  22. // Description:
  23. //
  24. // Called on EAPOL service startup to initialize all the media related events
  25. // and callback functions
  26. //
  27. //
  28. // Arguments:
  29. //
  30. // Return Values:
  31. //
  32. DWORD
  33. ElMediaInit (
  34. )
  35. {
  36. DWORD dwIndex = 0;
  37. DWORD dwRetCode = NO_ERROR;
  38. TRACE0 (INIT, "ElMediaInit: Entered");
  39. do
  40. {
  41. // Create Global Interface lock
  42. if (dwRetCode = CREATE_READ_WRITE_LOCK(&(g_ITFLock), "ITF") != NO_ERROR)
  43. {
  44. TRACE1(EAPOL, "ElMediaInit: Error (%ld) in creating g_ITFLock read-write-lock", dwRetCode);
  45. break;
  46. }
  47. // Initialize NLA locks
  48. if (dwRetCode = CREATE_READ_WRITE_LOCK(&(g_NLALock), "NLA") != NO_ERROR)
  49. {
  50. TRACE1(EAPOL, "ElMediaInit: Error (%ld) in creating g_NLALock read-write-lock", dwRetCode);
  51. break;
  52. }
  53. // Initialize EAPOL structures
  54. if ((dwRetCode = ElInitializeEAPOL()) != NO_ERROR)
  55. {
  56. TRACE1(INIT, "ElMediaInit: ElInitializeEAPOL failed with dwRetCode = %d",
  57. dwRetCode );
  58. break;
  59. }
  60. else
  61. {
  62. // TRACE0(INIT, "ElMediaInit: ElInitializeEAPOL successful");
  63. g_dwModulesStarted |= EAPOL_MODULE_STARTED;
  64. }
  65. // Initialize interface hash bucket table
  66. g_ITFTable.pITFBuckets = (ITF_BUCKET *) MALLOC (INTF_TABLE_BUCKETS * sizeof (ITF_BUCKET));
  67. if (g_ITFTable.pITFBuckets == NULL)
  68. {
  69. TRACE0 (DEVICE, "Error in allocation memory for ITF buckets");
  70. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  71. break;
  72. }
  73. for (dwIndex=0; dwIndex < INTF_TABLE_BUCKETS; dwIndex++)
  74. {
  75. g_ITFTable.pITFBuckets[dwIndex].pItf=NULL;
  76. }
  77. // Indicate logon/logoff notifications can be accepted
  78. g_dwModulesStarted |= LOGON_MODULE_STARTED;
  79. // Check if service was delayed in starting, start user logon
  80. ElCheckUserLoggedOn ();
  81. // Check if the user-context process is ready to be notified
  82. if ((dwRetCode = ElCheckUserModuleReady ()) == ERROR_BAD_IMPERSONATION_LEVEL)
  83. {
  84. break;
  85. }
  86. // Enumerate all the interfaces and start EAPOL state machine
  87. // on interfaces which are of LAN type
  88. if ((dwRetCode = ElEnumAndOpenInterfaces (NULL, NULL, 0, NULL)) != NO_ERROR)
  89. {
  90. TRACE1(INIT, "ElMediaInit: ElEnumAndOpenInterfaces failed with dwRetCode = %d",
  91. dwRetCode );
  92. break;
  93. }
  94. else
  95. {
  96. // TRACE0(INIT, "ElMediaInit: ElEnumAndOpenInterfaces successful");
  97. }
  98. #ifndef ZEROCONFIG_LINKED
  99. // Register for Media Sense detection of MEDIA_CONNECT and
  100. // MEDIA_DISCONNECT of interfaces
  101. if ((dwRetCode = ElMediaSenseRegister (TRUE)) != NO_ERROR)
  102. {
  103. TRACE1(INIT, "ElMediaInit: ElMediaSenseRegister failed with dwRetCode = %d",
  104. dwRetCode );
  105. break;
  106. }
  107. else
  108. {
  109. g_dwModulesStarted |= WMI_MODULE_STARTED;
  110. // TRACE0(INIT, "ElMediaInit: ElMediaSenseRegister successful");
  111. }
  112. // Register for detecting protocol BIND and UNBIND
  113. if ((dwRetCode = ElBindingsNotificationRegister (TRUE)) != NO_ERROR)
  114. {
  115. TRACE1(INIT, "ElMediaInit: ElBindingsNotificationRegister failed with dwRetCode = %d",
  116. dwRetCode );
  117. break;
  118. }
  119. else
  120. {
  121. g_dwModulesStarted |= BINDINGS_MODULE_STARTED;
  122. // TRACE0(INIT, "ElMediaInit: ElBindingsNotificationRegister successful");
  123. }
  124. // Register for device notifications. We are interested in LAN
  125. // interfaces coming and going.
  126. if ((dwRetCode = ElDeviceNotificationRegister (TRUE)) != NO_ERROR)
  127. {
  128. TRACE1(INIT, "ElMediaInit: ElDeviceNotificationRegister failed with dwRetCode = %d",
  129. dwRetCode );
  130. break;
  131. }
  132. else
  133. {
  134. g_dwModulesStarted |= DEVICE_NOTIF_STARTED;
  135. // TRACE0(INIT, "ElMediaInit: ElDeviceNotificationRegister successful");
  136. }
  137. #endif // ZEROCONFIG_LINKED
  138. } while (FALSE);
  139. if (dwRetCode == NO_ERROR)
  140. {
  141. TRACE0(INIT, "ElMediaInit successful");
  142. }
  143. else
  144. {
  145. TRACE1(INIT, "ElMediaInit failed with error %ld",
  146. dwRetCode);
  147. }
  148. return dwRetCode;
  149. }
  150. //
  151. // ElMediaDeInit
  152. //
  153. // Description:
  154. //
  155. // Called on EAPOL service shutdown to de-initialize all the media
  156. // related events and callback functions
  157. //
  158. //
  159. // Arguments:
  160. //
  161. // Return Values:
  162. //
  163. DWORD
  164. ElMediaDeInit (
  165. )
  166. {
  167. LONG lLocalWorkerThreads = 0;
  168. DWORD dwIndex = 0;
  169. EAPOL_ITF *pITFWalker = NULL, *pITF = NULL;
  170. DWORD dwRetCode = NO_ERROR;
  171. TRACE0 (INIT, "ElMediaDeInit: Entered");
  172. // Indicate logon/logoff notifications will not be accepted anymore
  173. g_dwModulesStarted &= ~LOGON_MODULE_STARTED;
  174. #ifndef ZEROCONFIG_LINKED
  175. // DeRegister Media Sense detection of MEDIA_CONNECT and MEDIA_DISCONNECT
  176. // of interfaces
  177. if (g_dwModulesStarted & WMI_MODULE_STARTED)
  178. {
  179. if ((dwRetCode = ElMediaSenseRegister (FALSE)) != NO_ERROR )
  180. {
  181. TRACE1(INIT, "ElMediaDeInit: ElMediaSenseRegister failed with dwRetCode = %d",
  182. dwRetCode );
  183. // log
  184. }
  185. else
  186. {
  187. // TRACE0(INIT, "ElMediaDeInit: ElMediaSenseRegister successful");
  188. }
  189. g_dwModulesStarted &= ~WMI_MODULE_STARTED;
  190. }
  191. // Deregister detecting protocol BIND and UNBIND
  192. if (g_dwModulesStarted & BINDINGS_MODULE_STARTED)
  193. {
  194. if ((dwRetCode = ElBindingsNotificationRegister (FALSE)) != NO_ERROR)
  195. {
  196. TRACE1(INIT, "ElMediaDeInit: ElBindingsNotificationRegister failed with dwRetCode = %d",
  197. dwRetCode );
  198. // log
  199. }
  200. else
  201. {
  202. g_dwModulesStarted &= ~BINDINGS_MODULE_STARTED;
  203. // TRACE0(INIT, "ElMediaDeInit: ElBindingsNotificationRegister successful");
  204. }
  205. }
  206. // Deregister device notifications that may have been posted
  207. if (g_dwModulesStarted & DEVICE_NOTIF_STARTED)
  208. {
  209. if ((dwRetCode = ElDeviceNotificationRegister (FALSE)) != NO_ERROR)
  210. {
  211. TRACE1(INIT, "ElMediaDeInit: ElDeviceNotificationRegister failed with dwRetCode = %d",
  212. dwRetCode );
  213. // log
  214. }
  215. else
  216. {
  217. // TRACE0(INIT, "ElMediaDeInit: ElDeviceNotificationRegister successful");
  218. }
  219. g_dwModulesStarted &= ~DEVICE_NOTIF_STARTED;
  220. }
  221. #endif // ZEROCONFIG_LINKED
  222. // Wait for all the related threads to die
  223. // viz. MediaSense, BindingsNotification, DeviceNotification,
  224. // Registry-watch for EAP-configuration change,
  225. // Registry-watch for EAPOL-parameter change
  226. do
  227. {
  228. lLocalWorkerThreads = 0;
  229. lLocalWorkerThreads = InterlockedCompareExchange (
  230. &g_lWorkerThreads,
  231. 0,
  232. 0);
  233. if (lLocalWorkerThreads == 0)
  234. {
  235. TRACE0 (INIT, "ElMediaDeInit: No worker threads alive, exiting");
  236. TRACE2 (INIT, "ElMediaDeInit: (%ld) - (%ld) worker threads still alive",
  237. lLocalWorkerThreads, g_lWorkerThreads);
  238. break;
  239. }
  240. TRACE2 (INIT, "ElMediaDeInit: (%ld) - (%ld) worker threads still alive, sleeping zzz... ",
  241. lLocalWorkerThreads, g_lWorkerThreads);
  242. Sleep (1000);
  243. }
  244. while (TRUE);
  245. // Shutdown EAPOL state machine
  246. if (g_dwModulesStarted & EAPOL_MODULE_STARTED)
  247. {
  248. if ((dwRetCode = ElEAPOLDeInit()) != NO_ERROR)
  249. {
  250. TRACE1(INIT, "ElMediaDeInit: ElEAPOLDeInit failed with dwRetCode = %d",
  251. dwRetCode );
  252. // log
  253. }
  254. else
  255. {
  256. TRACE0(INIT, "ElMediaDeInit: ElEAPOLDeInit successful");
  257. }
  258. g_dwModulesStarted &= ~EAPOL_MODULE_STARTED;
  259. }
  260. // Free the interface table
  261. if (READ_WRITE_LOCK_CREATED(&(g_ITFLock)))
  262. {
  263. ACQUIRE_WRITE_LOCK (&(g_ITFLock));
  264. if (g_ITFTable.pITFBuckets != NULL)
  265. {
  266. for (dwIndex = 0; dwIndex < INTF_TABLE_BUCKETS; dwIndex++)
  267. {
  268. for (pITFWalker = g_ITFTable.pITFBuckets[dwIndex].pItf;
  269. pITFWalker != NULL;
  270. /* NOTHING */
  271. )
  272. {
  273. pITF = pITFWalker;
  274. pITFWalker = pITFWalker->pNext;
  275. if (pITF->pwszInterfaceDesc)
  276. {
  277. FREE (pITF->pwszInterfaceDesc);
  278. }
  279. if (pITF->pwszInterfaceGUID)
  280. {
  281. FREE (pITF->pwszInterfaceGUID);
  282. }
  283. if (pITF)
  284. {
  285. FREE (pITF);
  286. }
  287. }
  288. }
  289. FREE(g_ITFTable.pITFBuckets);
  290. }
  291. ZeroMemory (&g_ITFTable, sizeof (g_ITFTable));
  292. RELEASE_WRITE_LOCK (&(g_ITFLock));
  293. // Delete ITF table lock
  294. DELETE_READ_WRITE_LOCK(&(g_ITFLock));
  295. }
  296. if (READ_WRITE_LOCK_CREATED(&(g_NLALock)))
  297. {
  298. // Delete NLA lock
  299. DELETE_READ_WRITE_LOCK(&(g_NLALock));
  300. }
  301. TRACE0(INIT, "ElMediaDeInit completed");
  302. return dwRetCode;
  303. }
  304. #ifdef ZEROCONFIG_LINKED
  305. //
  306. // ElMediaEventsHandler
  307. //
  308. // Description:
  309. //
  310. // Function called by WZC Service to signal various media events
  311. //
  312. // Arguments:
  313. // pwzcDeviceNotif - Pointer to WZC_DEVICE_NOTIF structure
  314. //
  315. // Return values:
  316. // NO_ERROR - Successful
  317. // non-zero - Error
  318. //
  319. DWORD
  320. ElMediaEventsHandler (
  321. IN PWZC_DEVICE_NOTIF pwzcDeviceNotif
  322. )
  323. {
  324. DWORD dwDummyValue = NO_ERROR;
  325. DWORD dwRetCode = NO_ERROR;
  326. do
  327. {
  328. TRACE0 (DEVICE, "ElMediaEventsHandler entered");
  329. if (pwzcDeviceNotif == NULL)
  330. {
  331. break;
  332. }
  333. switch (pwzcDeviceNotif->dwEventType)
  334. {
  335. case WZCNOTIF_DEVICE_ARRIVAL:
  336. TRACE0 (DEVICE, "ElMediaEventsHandler: Calling ElDeviceNotificationHandler ");
  337. ElDeviceNotificationHandler (
  338. (VOID *)&(pwzcDeviceNotif->dbDeviceIntf),
  339. DBT_DEVICEARRIVAL
  340. );
  341. break;
  342. case WZCNOTIF_DEVICE_REMOVAL:
  343. TRACE0 (DEVICE, "ElMediaEventsHandler: Calling ElDeviceNotificationHandler ");
  344. ElDeviceNotificationHandler (
  345. (VOID *)&(pwzcDeviceNotif->dbDeviceIntf),
  346. DBT_DEVICEREMOVECOMPLETE
  347. );
  348. break;
  349. case WZCNOTIF_ADAPTER_BIND:
  350. TRACE0 (DEVICE, "ElMediaEventsHandler: Calling ElBindingsNotificationCallback ");
  351. ElBindingsNotificationCallback (
  352. &(pwzcDeviceNotif->wmiNodeHdr),
  353. 0
  354. );
  355. break;
  356. case WZCNOTIF_ADAPTER_UNBIND:
  357. TRACE0 (DEVICE, "ElMediaEventsHandler: Calling ElBindingsNotificationCallback ");
  358. ElBindingsNotificationCallback (
  359. &(pwzcDeviceNotif->wmiNodeHdr),
  360. 0
  361. );
  362. break;
  363. case WZCNOTIF_MEDIA_CONNECT:
  364. TRACE0 (DEVICE, "ElMediaEventsHandler: Calling ElMediaSenseCallback ");
  365. ElMediaSenseCallback (
  366. &(pwzcDeviceNotif->wmiNodeHdr),
  367. 0
  368. );
  369. break;
  370. case WZCNOTIF_MEDIA_DISCONNECT:
  371. TRACE0 (DEVICE, "ElMediaEventsHandler: Calling ElMediaSenseCallback ");
  372. ElMediaSenseCallback (
  373. &(pwzcDeviceNotif->wmiNodeHdr),
  374. 0
  375. );
  376. break;
  377. case WZCNOTIF_WZC_CONNECT:
  378. TRACE0 (DEVICE, "ElMediaEventsHandler: Calling ElZeroConfigEvent ");
  379. ElZeroConfigEvent (
  380. pwzcDeviceNotif->wzcConfig.dwSessionHdl,
  381. pwzcDeviceNotif->wzcConfig.wszGuid,
  382. pwzcDeviceNotif->wzcConfig.ndSSID,
  383. &(pwzcDeviceNotif->wzcConfig.rdEventData)
  384. );
  385. break;
  386. default:
  387. break;
  388. }
  389. }
  390. while (FALSE);
  391. return dwRetCode;
  392. }
  393. #endif // ZEROCONFIG_LINKED
  394. //
  395. // ElMediaSenseRegister
  396. //
  397. // Description:
  398. //
  399. // Function called to register CallBack function with WMI
  400. // for MEDIA_CONNECT/MEDIA_DISCONNECT events
  401. //
  402. // Arguments:
  403. // fRegister - True = Register for Media Sense
  404. // False = Deregister Media Sense requests
  405. // Return values:
  406. // NO_ERROR - Successful
  407. // non-zero - Error
  408. //
  409. DWORD
  410. ElMediaSenseRegister (
  411. IN BOOL fRegister
  412. )
  413. {
  414. DWORD dwRetCode = NO_ERROR;
  415. PVOID pvDeliveryInfo = ElMediaSenseCallback;
  416. dwRetCode = WmiNotificationRegistration (
  417. (LPGUID)(&GUID_NDIS_STATUS_MEDIA_CONNECT),
  418. (BOOLEAN)fRegister,
  419. pvDeliveryInfo,
  420. (ULONG_PTR)NULL,
  421. NOTIFICATION_CALLBACK_DIRECT );
  422. if (dwRetCode != NO_ERROR)
  423. {
  424. TRACE1(INIT, "ElMediaSenseRegister: Error %d in WmiNotificationRegistration:GUID_NDIS_STATUS_MEDIA_CONNECT", dwRetCode);
  425. return( dwRetCode );
  426. }
  427. dwRetCode = WmiNotificationRegistration (
  428. (LPGUID)(&GUID_NDIS_STATUS_MEDIA_DISCONNECT),
  429. (BOOLEAN)fRegister,
  430. pvDeliveryInfo,
  431. (ULONG_PTR)NULL,
  432. NOTIFICATION_CALLBACK_DIRECT );
  433. if (dwRetCode != NO_ERROR)
  434. {
  435. TRACE1(INIT, "ElMediaSenseRegister: Error %d in WmiNotificationRegistration:GUID_NDIS_STATUS_MEDIA_DISCONNECT", dwRetCode);
  436. return( dwRetCode );
  437. }
  438. TRACE1 (INIT, "ElMediaSenseRegister - completed with RetCode %d", dwRetCode);
  439. return( dwRetCode );
  440. }
  441. //
  442. // ElDeviceNotificationRegister
  443. //
  444. // Description:
  445. //
  446. // Function called to register for device addition/removal notifications
  447. //
  448. // Arguments:
  449. // fRegister - True = Register for Device Notifications
  450. // False = Deregister Device Notifications
  451. //
  452. // Return values:
  453. // NO_ERROR - Successful
  454. // non-zero - Error
  455. //
  456. DWORD
  457. ElDeviceNotificationRegister (
  458. IN BOOL fRegister
  459. )
  460. {
  461. HANDLE hDeviceNotification = NULL;
  462. DWORD dwRetCode = NO_ERROR;
  463. #ifdef EAPOL_SERVICE
  464. DEV_BROADCAST_DEVICEINTERFACE PnPFilter;
  465. if (fRegister)
  466. {
  467. ZeroMemory (&PnPFilter, sizeof(PnPFilter));
  468. PnPFilter.dbcc_size = sizeof(PnPFilter);
  469. PnPFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  470. PnPFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  471. g_hDeviceNotification = RegisterDeviceNotification (
  472. (HANDLE)g_hServiceStatus,
  473. &PnPFilter,
  474. DEVICE_NOTIFY_SERVICE_HANDLE );
  475. if (g_hDeviceNotification == NULL)
  476. {
  477. dwRetCode = GetLastError();
  478. TRACE1 (DEVICE, "ElDeviceNotificationRegister failed with error %ld",
  479. dwRetCode);
  480. }
  481. }
  482. else
  483. {
  484. if (g_hDeviceNotification != NULL)
  485. {
  486. if (!UnregisterDeviceNotification (
  487. g_hDeviceNotification
  488. ))
  489. {
  490. dwRetCode = GetLastError();
  491. TRACE1 (DEVICE, "ElDeviceNotificationRegister: Unregister failed with error (%ld)",
  492. dwRetCode);
  493. }
  494. }
  495. }
  496. #endif
  497. return dwRetCode;
  498. }
  499. //
  500. // ElBindingsNotificationRegister
  501. //
  502. // Description:
  503. //
  504. // Function called to register CallBack function with WMI
  505. // for protocol bind/unbind
  506. //
  507. // Arguments:
  508. // fRegister - True = Register for Media Sense
  509. // False = Deregister Media Sense requests
  510. // Return values:
  511. // NO_ERROR - Successful
  512. // non-zero - Error
  513. //
  514. DWORD
  515. ElBindingsNotificationRegister (
  516. IN BOOL fRegister
  517. )
  518. {
  519. DWORD dwRetCode = NO_ERROR;
  520. PVOID pvDeliveryInfo = ElBindingsNotificationCallback;
  521. dwRetCode = WmiNotificationRegistration (
  522. (LPGUID)(&GUID_NDIS_NOTIFY_BIND),
  523. (BOOLEAN)fRegister,
  524. pvDeliveryInfo,
  525. (ULONG_PTR)NULL,
  526. NOTIFICATION_CALLBACK_DIRECT );
  527. if (dwRetCode != NO_ERROR)
  528. {
  529. TRACE1(INIT, "ElBindingsNotificationRegister: Error %d in WmiNotificationRegistration:GUID_NDIS_NOTIFY_BIND", dwRetCode);
  530. return( dwRetCode );
  531. }
  532. dwRetCode = WmiNotificationRegistration (
  533. (LPGUID)(&GUID_NDIS_NOTIFY_UNBIND),
  534. (BOOLEAN)fRegister,
  535. pvDeliveryInfo,
  536. (ULONG_PTR)NULL,
  537. NOTIFICATION_CALLBACK_DIRECT );
  538. if (dwRetCode != NO_ERROR)
  539. {
  540. TRACE1(INIT, "ElBindingsNotificationRegister: Error %d in WmiNotificationRegistration:GUID_NDIS_NOTIFY_BIND", dwRetCode);
  541. return( dwRetCode );
  542. }
  543. TRACE1 (INIT, "ElBindingsNotificationRegister - completed with RetCode %d", dwRetCode);
  544. return( dwRetCode );
  545. }
  546. //
  547. // ElDeviceNotificationHandler
  548. //
  549. // Description:
  550. //
  551. // Function called to handle device notifications for interface addition/
  552. // removal
  553. //
  554. // Arguments:
  555. // lpEventData - interface information
  556. // dwEventType - notification type
  557. //
  558. DWORD
  559. ElDeviceNotificationHandler (
  560. IN VOID *lpEventData,
  561. IN DWORD dwEventType
  562. )
  563. {
  564. DWORD dwEventStatus = 0;
  565. DEV_BROADCAST_DEVICEINTERFACE *pInfo =
  566. (DEV_BROADCAST_DEVICEINTERFACE *) lpEventData;
  567. PVOID pvBuffer = NULL;
  568. BOOLEAN fDecrWorkerThreadCount = TRUE;
  569. DWORD dwRetCode = NO_ERROR;
  570. InterlockedIncrement (&g_lWorkerThreads);
  571. TRACE0 (DEVICE, "ElDeviceNotificationHandler entered");
  572. do
  573. {
  574. if (g_hEventTerminateEAPOL == NULL)
  575. {
  576. break;
  577. }
  578. if (!(g_dwModulesStarted & ALL_MODULES_STARTED))
  579. {
  580. TRACE0 (DEVICE, "ElDeviceNotificationHandler: Received notification before module started");
  581. break;
  582. }
  583. // Check if have already gone through EAPOLCleanUp before
  584. if ((dwEventStatus = WaitForSingleObject (
  585. g_hEventTerminateEAPOL,
  586. 0)) == WAIT_FAILED)
  587. {
  588. dwRetCode = GetLastError ();
  589. TRACE1(INIT, "ElDeviceNotificationHandler: WaitForSingleObject failed with error %ld, Terminating !!!",
  590. dwRetCode);
  591. // log
  592. break;
  593. }
  594. if (dwEventStatus == WAIT_OBJECT_0)
  595. {
  596. TRACE0(INIT, "ElDeviceNotificationHandler: g_hEventTerminateEAPOL already signaled, returning");
  597. break;
  598. }
  599. if (lpEventData == NULL)
  600. {
  601. dwRetCode = ERROR_INVALID_DATA;
  602. TRACE0 (DEVICE, "ElDeviceNotificationHandler: lpEventData == NULL");
  603. break;
  604. }
  605. if (pInfo->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
  606. {
  607. TRACE0 (DEVICE, "ElDeviceNotificationHandler: Event for Interface type");
  608. if ((pvBuffer = MALLOC (pInfo->dbcc_size + 16)) == NULL)
  609. {
  610. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  611. TRACE0 (DEVICE, "ElDeviceNotificationHandler: MALLOC failed for pvBuffer");
  612. break;
  613. }
  614. *((DWORD *)pvBuffer) = dwEventType;
  615. memcpy ((PBYTE)pvBuffer + 8, (PBYTE)pInfo, pInfo->dbcc_size);
  616. if (!QueueUserWorkItem (
  617. (LPTHREAD_START_ROUTINE)ElDeviceNotificationHandlerWorker,
  618. pvBuffer,
  619. WT_EXECUTELONGFUNCTION))
  620. {
  621. dwRetCode = GetLastError();
  622. TRACE1 (DEVICE, "ElDeviceNotificationHandler: QueueUserWorkItem failed with error %ld",
  623. dwRetCode);
  624. break;
  625. }
  626. else
  627. {
  628. fDecrWorkerThreadCount = FALSE;
  629. }
  630. }
  631. else
  632. {
  633. TRACE0 (DEVICE, "ElDeviceNotificationHandler: Event NOT for Interface type");
  634. }
  635. }
  636. while (FALSE);
  637. TRACE1 (DEVICE, "ElDeviceNotificationHandler completed with retcode %ld",
  638. dwRetCode);
  639. if (dwRetCode != NO_ERROR)
  640. {
  641. if (pvBuffer != NULL)
  642. {
  643. FREE (pvBuffer);
  644. }
  645. }
  646. if (fDecrWorkerThreadCount)
  647. {
  648. InterlockedDecrement (&g_lWorkerThreads);
  649. }
  650. return dwRetCode;
  651. }
  652. //
  653. // ElDeviceNotificationHandlerWorker
  654. //
  655. // Description:
  656. //
  657. // Worker function for ElDeviceNotificationHandlerWorker
  658. //
  659. // Arguments:
  660. // pvContext - interface information
  661. //
  662. DWORD
  663. WINAPI
  664. ElDeviceNotificationHandlerWorker (
  665. IN PVOID pvContext
  666. )
  667. {
  668. HANDLE hDevice = NULL;
  669. DEV_BROADCAST_DEVICEINTERFACE *pInfo = NULL;
  670. DWORD dwEventType = 0;
  671. DWORD dwRetCode = NO_ERROR;
  672. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Entered");
  673. do
  674. {
  675. if (pvContext == NULL)
  676. {
  677. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: pvContext == NULL");
  678. break;
  679. }
  680. if (!(g_dwModulesStarted & ALL_MODULES_STARTED))
  681. {
  682. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Received notification before module started");
  683. break;
  684. }
  685. dwEventType = *((DWORD *) pvContext);
  686. pInfo = (DEV_BROADCAST_DEVICEINTERFACE*)((PBYTE)pvContext + 8);
  687. if ((dwEventType == DBT_DEVICEARRIVAL) ||
  688. (dwEventType == DBT_DEVICEREMOVECOMPLETE))
  689. {
  690. // Extract GUID from the \Device\GUID string
  691. WCHAR *pwszGUIDStart = NULL;
  692. WCHAR *pwszGUIDEnd = NULL;
  693. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Interface arr/rem");
  694. pwszGUIDStart = wcsrchr( pInfo->dbcc_name, L'{' );
  695. pwszGUIDEnd = wcsrchr( pInfo->dbcc_name, L'}' );
  696. if ((pwszGUIDStart != NULL) && (pwszGUIDEnd != NULL) &&
  697. ((pwszGUIDEnd- pwszGUIDStart) == (GUID_STRING_LEN_WITH_TERM-2)))
  698. {
  699. *(pwszGUIDEnd + 1) = L'\0';
  700. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: For interface %ws",
  701. pwszGUIDStart);
  702. // Interface was added
  703. if (dwEventType == DBT_DEVICEARRIVAL)
  704. {
  705. TRACE0(DEVICE, "ElDeviceNotificationHandlerWorker: Callback for device addition");
  706. if ((dwRetCode = ElEnumAndOpenInterfaces (
  707. NULL, pwszGUIDStart, 0, NULL)) != NO_ERROR)
  708. {
  709. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: ElEnumAndOpenInterfaces returned error %ld",
  710. dwRetCode);
  711. }
  712. }
  713. else
  714. {
  715. TRACE0(DEVICE, "ElDeviceNotificationHandlerWorker: Callback for device removal");
  716. if ((dwRetCode = ElShutdownInterface (pwszGUIDStart))
  717. != NO_ERROR)
  718. {
  719. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: ElShutdownInterface failed with error %ld",
  720. dwRetCode);
  721. }
  722. if ((dwRetCode = ElEnumAndUpdateRegistryInterfaceList ()) != NO_ERROR)
  723. {
  724. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: ElEnumAndUpdateRegistryInterfaceList failed with error %ld",
  725. dwRetCode);
  726. }
  727. }
  728. }
  729. else
  730. {
  731. dwRetCode = ERROR_INVALID_PARAMETER;
  732. break;
  733. }
  734. }
  735. else
  736. {
  737. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Event type is is NOT device arr/rem");
  738. }
  739. }
  740. while (FALSE);
  741. if (pvContext != NULL)
  742. {
  743. FREE (pvContext);
  744. }
  745. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker completed with retcode %ld",
  746. dwRetCode);
  747. InterlockedDecrement (&g_lWorkerThreads);
  748. return 0;
  749. }
  750. //
  751. // ElMediaSenseCallback
  752. //
  753. // Description:
  754. //
  755. // Callback function called by WMI on MEDIA_CONNECT/MEDIA_DISCONNECT
  756. // events
  757. //
  758. // Arguments:
  759. // pWnodeHeader - Pointer to information returned by the event
  760. // uiNotificationContext - unused
  761. //
  762. // Return values:
  763. // NO_ERROR - Success
  764. // non-zero - Error
  765. //
  766. VOID
  767. CALLBACK
  768. ElMediaSenseCallback (
  769. IN PWNODE_HEADER pWnodeHeader,
  770. IN UINT_PTR uiNotificationContext
  771. )
  772. {
  773. DWORD dwEventStatus = 0;
  774. PVOID pvBuffer = NULL;
  775. BOOLEAN fDecrWorkerThreadCount = TRUE;
  776. DWORD dwRetCode = NO_ERROR;
  777. InterlockedIncrement (&g_lWorkerThreads);
  778. TRACE0 (DEVICE, "ElMediaSenseCallback: Entered");
  779. do
  780. {
  781. if (g_hEventTerminateEAPOL == NULL)
  782. {
  783. break;
  784. }
  785. if (!(g_dwModulesStarted & ALL_MODULES_STARTED))
  786. {
  787. TRACE0 (DEVICE, "ElMediaSenseCallback: Received notification before module started");
  788. break;
  789. }
  790. // Check if have already gone through EAPOLCleanUp before
  791. if (( dwEventStatus = WaitForSingleObject (
  792. g_hEventTerminateEAPOL,
  793. 0)) == WAIT_FAILED)
  794. {
  795. dwRetCode = GetLastError ();
  796. TRACE1 (INIT, "ElMediaSenseCallback: WaitForSingleObject failed with error %ld, Terminating !!!",
  797. dwRetCode);
  798. // log
  799. break;
  800. }
  801. if (dwEventStatus == WAIT_OBJECT_0)
  802. {
  803. dwRetCode = NO_ERROR;
  804. TRACE0 (INIT, "ElMediaSenseCallback: g_hEventTerminateEAPOL already signaled, returning");
  805. break;
  806. }
  807. if (pWnodeHeader == NULL)
  808. {
  809. dwRetCode = ERROR_INVALID_DATA;
  810. TRACE0 (DEVICE, "ElMediaSenseCallback: pWnodeHeader == NULL");
  811. break;
  812. }
  813. if ((pvBuffer = MALLOC (pWnodeHeader->BufferSize)) == NULL)
  814. {
  815. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  816. TRACE0 (DEVICE, "ElMediaSenseCallback: MALLOC failed for pvBuffer");
  817. break;
  818. }
  819. memcpy ((PVOID)pvBuffer, (PVOID)pWnodeHeader, pWnodeHeader->BufferSize);
  820. if (!QueueUserWorkItem (
  821. (LPTHREAD_START_ROUTINE)ElMediaSenseCallbackWorker,
  822. pvBuffer,
  823. WT_EXECUTELONGFUNCTION))
  824. {
  825. dwRetCode = GetLastError();
  826. TRACE1 (DEVICE, "ElMediaSenseCallback: QueueUserWorkItem failed with error %ld",
  827. dwRetCode);
  828. // log
  829. break;
  830. }
  831. else
  832. {
  833. fDecrWorkerThreadCount = FALSE;
  834. }
  835. }
  836. while (FALSE);
  837. if (dwRetCode != NO_ERROR)
  838. {
  839. TRACE1 (DEVICE, "ElMediaSenseCallback: Failed with error %ld",
  840. dwRetCode);
  841. if (pvBuffer != NULL)
  842. {
  843. FREE (pvBuffer);
  844. }
  845. }
  846. if (fDecrWorkerThreadCount)
  847. {
  848. InterlockedDecrement (&g_lWorkerThreads);
  849. }
  850. }
  851. //
  852. // ElMediaSenseCallbackWorker
  853. //
  854. // Description:
  855. //
  856. // Worker function for ElMediaSenseCallback and executes in a separate
  857. // thread
  858. //
  859. // Arguments:
  860. // pvContext - Pointer to information returned by the media-sense event
  861. //
  862. // Return values:
  863. // NO_ERROR - Success
  864. // non-zero - Error
  865. //
  866. DWORD
  867. WINAPI
  868. ElMediaSenseCallbackWorker (
  869. IN PVOID pvContext
  870. )
  871. {
  872. PWNODE_HEADER pWnodeHeader = (PWNODE_HEADER)pvContext;
  873. PWNODE_SINGLE_INSTANCE pWnode = (PWNODE_SINGLE_INSTANCE)pWnodeHeader;
  874. WCHAR *pwsName = NULL;
  875. WCHAR *pwszDeviceName = NULL;
  876. WCHAR *pwsGUIDString = NULL;
  877. WCHAR *pwszDeviceGUID = NULL;
  878. WCHAR *pwszGUIDStart = NULL, *pwszGUIDEnd = NULL;
  879. DWORD dwGUIDLen = 0;
  880. USHORT cpsLength;
  881. EAPOL_ITF *pITF;
  882. EAPOL_PCB *pPCB = NULL;
  883. DWORD dwRetCode = NO_ERROR;
  884. do
  885. {
  886. #ifdef EAPOL_SERVICE
  887. if ((g_ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  888. ||
  889. (g_ServiceStatus.dwCurrentState == SERVICE_STOPPED))
  890. {
  891. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: Callback received while service was stopping");
  892. break;
  893. }
  894. #endif // EAPOL_SERVICE
  895. if (pWnodeHeader == NULL)
  896. {
  897. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: Callback received with NULL NDIS interface details");
  898. break;
  899. }
  900. pwsName = (PWCHAR)RtlOffsetToPointer(
  901. pWnode,
  902. pWnode->OffsetInstanceName );
  903. pwsGUIDString = (PWCHAR)RtlOffsetToPointer(
  904. pWnode,
  905. pWnode->DataBlockOffset );
  906. cpsLength = (SHORT)( *((SHORT *)pwsName) );
  907. if (!(pwszDeviceName = (WCHAR *) MALLOC ((cpsLength+1)*sizeof(WCHAR))))
  908. {
  909. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: Error in Memory allocation for pszDeviceName");
  910. break;
  911. }
  912. memcpy ((CHAR *)pwszDeviceName, (CHAR *)pwsName+sizeof(SHORT), cpsLength);
  913. pwszDeviceName[cpsLength] = L'\0';
  914. pwszGUIDStart = wcschr (pwsGUIDString, L'{');
  915. pwszGUIDEnd = wcschr (pwsGUIDString, L'}');
  916. if ((pwszGUIDStart == NULL) || (pwszGUIDEnd == NULL) || ((pwszGUIDEnd - pwszGUIDStart) != (GUID_STRING_LEN_WITH_TERM-2)))
  917. {
  918. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: GUID not constructed correctly");
  919. dwRetCode = ERROR_INVALID_PARAMETER;
  920. break;
  921. }
  922. dwGUIDLen = GUID_STRING_LEN_WITH_TERM;
  923. pwszDeviceGUID = NULL;
  924. if ((pwszDeviceGUID = MALLOC (dwGUIDLen * sizeof (WCHAR))) == NULL)
  925. {
  926. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: MALLOC failed for pwszDeviceGUID");
  927. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  928. break;
  929. }
  930. memcpy ((VOID *)pwszDeviceGUID, (VOID *)pwszGUIDStart, ((dwGUIDLen-1)*sizeof(WCHAR)));
  931. pwszDeviceGUID[dwGUIDLen-1] = L'\0';
  932. TRACE3 (DEVICE, "ElMediaSenseCallbackWorker: For interface (%ws), GUID (%ws), length of block = %d",
  933. pwszDeviceName, pwszDeviceGUID, cpsLength);
  934. //
  935. // Get the information for the media disconnect.
  936. //
  937. if (memcmp( &(pWnodeHeader->Guid),
  938. &GUID_NDIS_STATUS_MEDIA_DISCONNECT,
  939. sizeof(GUID)) == 0)
  940. {
  941. // MEDIA DISCONNECT callback
  942. DbLogPCBEvent (DBLOG_CATEG_INFO, NULL, EAPOL_MEDIA_DISCONNECT, pwszDeviceName);
  943. // Check if EAPOL was actually started on this interface
  944. // Verify by checking existence of corresponding entry in hash table
  945. TRACE0(DEVICE, "ElMediaSenseCallbackWorker: Callback for sense disconnect");
  946. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  947. pPCB = ElGetPCBPointerFromPortGUID (pwszDeviceGUID);
  948. if (pPCB != NULL)
  949. {
  950. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  951. if ((dwRetCode = FSMDisconnected (pPCB, NULL)) != NO_ERROR)
  952. {
  953. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: FSMDisconnected failed with error %ld",
  954. dwRetCode);
  955. }
  956. else
  957. {
  958. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: Port marked disconnected %ws",
  959. pwszDeviceName);
  960. }
  961. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  962. }
  963. RELEASE_WRITE_LOCK (&(g_PCBLock));
  964. }
  965. else
  966. {
  967. if (memcmp( &(pWnodeHeader->Guid),
  968. &GUID_NDIS_STATUS_MEDIA_CONNECT,
  969. sizeof(GUID)) == 0)
  970. {
  971. // MEDIA CONNECT callback
  972. DbLogPCBEvent (DBLOG_CATEG_INFO, NULL, EAPOL_MEDIA_CONNECT, pwszDeviceName);
  973. TRACE0(DEVICE, "ElMediaSenseCallbackWorker: Callback for sense connect");
  974. if ((dwRetCode = ElEnumAndOpenInterfaces (
  975. NULL, pwszDeviceGUID, 0, NULL))
  976. != NO_ERROR)
  977. {
  978. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: ElEnumAndOpenInterfaces returned error %ld",
  979. dwRetCode);
  980. }
  981. }
  982. }
  983. }
  984. while (FALSE);
  985. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: processed, RetCode = %ld", dwRetCode);
  986. if (pWnodeHeader != NULL)
  987. {
  988. FREE (pWnodeHeader);
  989. }
  990. if (pwszDeviceName != NULL)
  991. {
  992. FREE (pwszDeviceName);
  993. }
  994. if (pwszDeviceGUID != NULL)
  995. {
  996. FREE (pwszDeviceGUID);
  997. }
  998. InterlockedDecrement (&g_lWorkerThreads);
  999. return 0;
  1000. }
  1001. //
  1002. // ElBindingsNotificationCallback
  1003. //
  1004. // Description:
  1005. //
  1006. // Callback function called by WMI on protocol bind/unbind
  1007. // events
  1008. //
  1009. // Arguments:
  1010. // pWnodeHeader - Pointer to information returned by the event
  1011. // uiNotificationContext - unused
  1012. //
  1013. // Return values:
  1014. // NO_ERROR - Success
  1015. // non-zero - Error
  1016. //
  1017. VOID
  1018. CALLBACK
  1019. ElBindingsNotificationCallback (
  1020. IN PWNODE_HEADER pWnodeHeader,
  1021. IN UINT_PTR uiNotificationContext
  1022. )
  1023. {
  1024. DWORD dwEventStatus = 0;
  1025. PVOID pvBuffer = NULL;
  1026. BOOLEAN fDecrWorkerThreadCount = TRUE;
  1027. DWORD dwRetCode = NO_ERROR;
  1028. InterlockedIncrement (&g_lWorkerThreads);
  1029. TRACE0 (DEVICE, "ElBindingsNotificationCallback: Entered");
  1030. do
  1031. {
  1032. if (g_hEventTerminateEAPOL == NULL)
  1033. {
  1034. break;
  1035. }
  1036. if (!(g_dwModulesStarted & ALL_MODULES_STARTED))
  1037. {
  1038. TRACE0 (DEVICE, "ElBindingsNotificationCallback: Received notification before module started");
  1039. break;
  1040. }
  1041. // Check if have already gone through EAPOLCleanUp before
  1042. if (( dwEventStatus = WaitForSingleObject (
  1043. g_hEventTerminateEAPOL,
  1044. 0)) == WAIT_FAILED)
  1045. {
  1046. dwRetCode = GetLastError ();
  1047. TRACE1 (INIT, "ElBindingsNotificationCallback: WaitForSingleObject failed with error %ld, Terminating !!!",
  1048. dwRetCode);
  1049. break;
  1050. }
  1051. if (dwEventStatus == WAIT_OBJECT_0)
  1052. {
  1053. dwRetCode = NO_ERROR;
  1054. TRACE0 (INIT, "ElBindingsNotificationCallback: g_hEventTerminateEAPOL already signaled, returning");
  1055. break;
  1056. }
  1057. if (pWnodeHeader == NULL)
  1058. {
  1059. dwRetCode = ERROR_INVALID_DATA;
  1060. TRACE0 (DEVICE, "ElBindingsNotificationCallback: pWnodeHeader == NULL");
  1061. break;
  1062. }
  1063. if ((pvBuffer = MALLOC (pWnodeHeader->BufferSize)) == NULL)
  1064. {
  1065. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1066. TRACE0 (DEVICE, "ElBindingsNotificationCallback: MALLOC failed for pvBuffer");
  1067. break;
  1068. }
  1069. memcpy ((PVOID)pvBuffer, (PVOID)pWnodeHeader, pWnodeHeader->BufferSize);
  1070. if (!QueueUserWorkItem (
  1071. (LPTHREAD_START_ROUTINE)ElBindingsNotificationCallbackWorker,
  1072. pvBuffer,
  1073. WT_EXECUTELONGFUNCTION))
  1074. {
  1075. dwRetCode = GetLastError();
  1076. TRACE1 (DEVICE, "ElBindingsNotificationCallback: QueueUserWorkItem failed with error %ld",
  1077. dwRetCode);
  1078. // log
  1079. break;
  1080. }
  1081. else
  1082. {
  1083. fDecrWorkerThreadCount = FALSE;
  1084. }
  1085. }
  1086. while (FALSE);
  1087. if (dwRetCode != NO_ERROR)
  1088. {
  1089. TRACE1 (DEVICE, "ElBindingsNotificationCallback: Failed with error %ld",
  1090. dwRetCode);
  1091. if (pvBuffer != NULL)
  1092. {
  1093. FREE (pvBuffer);
  1094. }
  1095. }
  1096. if (fDecrWorkerThreadCount)
  1097. {
  1098. InterlockedDecrement (&g_lWorkerThreads);
  1099. }
  1100. }
  1101. //
  1102. // ElBindingsNotificationCallbackWorker
  1103. //
  1104. // Description:
  1105. //
  1106. // Worker function for ElBindingsNotificationCallback and executes in a separate
  1107. // thread
  1108. //
  1109. // Arguments:
  1110. // pvContext - Pointer to information returned by the protocol bind/unbind
  1111. // event
  1112. //
  1113. // Return values:
  1114. // NO_ERROR - Success
  1115. // non-zero - Error
  1116. //
  1117. DWORD
  1118. WINAPI
  1119. ElBindingsNotificationCallbackWorker (
  1120. IN PVOID pvContext
  1121. )
  1122. {
  1123. PWNODE_HEADER pWnodeHeader = (PWNODE_HEADER)pvContext;
  1124. PWNODE_SINGLE_INSTANCE pWnode = (PWNODE_SINGLE_INSTANCE)pWnodeHeader;
  1125. WCHAR *pwsName = NULL;
  1126. WCHAR *pwszDeviceGUID = NULL;
  1127. WCHAR *pwszGUIDStart = NULL, *pwszGUIDEnd = NULL;
  1128. DWORD dwGUIDLen = 0;
  1129. WCHAR *pwsTransportName = NULL;
  1130. WCHAR *pwszDeviceName = NULL;
  1131. USHORT cpsLength;
  1132. EAPOL_ITF *pITF = NULL;
  1133. EAPOL_PCB *pPCB = NULL;
  1134. DWORD dwRetCode = NO_ERROR;
  1135. do
  1136. {
  1137. #ifdef EAPOL_SERVICE
  1138. if ((g_ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  1139. ||
  1140. (g_ServiceStatus.dwCurrentState == SERVICE_STOPPED))
  1141. {
  1142. TRACE0 (DEVICE, "ElBindingsNotificationCallbackWorker: Callback received while service was stopping");
  1143. break;
  1144. }
  1145. #endif // EAPOL_SERVICE
  1146. if (pWnodeHeader == NULL)
  1147. {
  1148. TRACE0 (DEVICE, "ElBindingsNotificationCallbackWorker: Callback received with NULL NDIS interface details");
  1149. break;
  1150. }
  1151. pwsName = (PWCHAR)RtlOffsetToPointer(
  1152. pWnode,
  1153. pWnode->OffsetInstanceName );
  1154. pwsTransportName = (PWCHAR)RtlOffsetToPointer(
  1155. pWnode,
  1156. pWnode->DataBlockOffset );
  1157. if (wcsncmp (cwszNDISUIOProtocolName, pwsTransportName, wcslen (cwszNDISUIOProtocolName)))
  1158. {
  1159. TRACE1 (DEVICE, "ElBindingsNotificationCallbackWorker: Protocol binding (%ws) not for NDISUIO",
  1160. pwsTransportName);
  1161. break;
  1162. }
  1163. // Get the length of the device name string and null terminate it
  1164. cpsLength = (SHORT)( *((SHORT *)pwsName) );
  1165. if (!(pwszDeviceName = (WCHAR *) MALLOC ((cpsLength+1)*sizeof(WCHAR))))
  1166. {
  1167. TRACE0 (DEVICE, "ElBindingsNotificationCallbackWorker: Error in Memory allocation for pwszDeviceName");
  1168. break;
  1169. }
  1170. memcpy ((CHAR *)pwszDeviceName, (CHAR *)pwsName+sizeof(SHORT), cpsLength);
  1171. pwszDeviceName[cpsLength] = L'\0';
  1172. pwszDeviceGUID = pwsTransportName + wcslen(cwszNDISUIOProtocolName) + 1;
  1173. pwszGUIDStart = wcschr (pwszDeviceGUID, L'{');
  1174. pwszGUIDEnd = wcschr (pwszDeviceGUID, L'}');
  1175. pwszDeviceGUID = NULL;
  1176. if ((pwszGUIDStart == NULL) || (pwszGUIDEnd == NULL) || ((pwszGUIDEnd - pwszGUIDStart) != (GUID_STRING_LEN_WITH_TERM-2)))
  1177. {
  1178. TRACE0 (DEVICE, "ElBindingsNotificationCallbackWorker: GUID not constructed correctly");
  1179. dwRetCode = ERROR_INVALID_PARAMETER;
  1180. break;
  1181. }
  1182. dwGUIDLen = GUID_STRING_LEN_WITH_TERM;
  1183. if ((pwszDeviceGUID = MALLOC (dwGUIDLen * sizeof (WCHAR))) == NULL)
  1184. {
  1185. TRACE0 (DEVICE, "ElBindingsNotificationCallbackWorker: MALLOC failed for pwszDeviceGUID");
  1186. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1187. break;
  1188. }
  1189. memcpy ((VOID *)pwszDeviceGUID, (VOID *)pwszGUIDStart, ((dwGUIDLen-1)*sizeof(WCHAR)));
  1190. pwszDeviceGUID[dwGUIDLen-1] = L'\0';
  1191. TRACE2 (DEVICE, "ElBindingsNotificationCallbackWorker: For interface = %ws, guid=%ws",
  1192. pwszDeviceName, pwszDeviceGUID);
  1193. //
  1194. // Get the information for the protocol UNBIND
  1195. //
  1196. if (memcmp( &(pWnodeHeader->Guid),
  1197. &GUID_NDIS_NOTIFY_UNBIND,
  1198. sizeof(GUID)) == 0)
  1199. {
  1200. // Protocol UNBIND callback
  1201. DbLogPCBEvent (DBLOG_CATEG_INFO, NULL, EAPOL_NDISUIO_UNBIND, pwszDeviceName);
  1202. TRACE0(DEVICE, "ElBindingsNotificationCallbackWorker: Callback for protocol unbind");
  1203. if ((dwRetCode = ElShutdownInterface (pwszDeviceGUID)) != ERROR)
  1204. {
  1205. TRACE2 (DEVICE, "ElBindingsNotificationCallbackWorker: ElShutdownInterface failed with error %ld for (%ws)",
  1206. dwRetCode, pwszDeviceGUID);
  1207. }
  1208. if ((dwRetCode = ElEnumAndUpdateRegistryInterfaceList ()) != NO_ERROR)
  1209. {
  1210. TRACE1 (DEVICE, "ElBindingsNotificationCallbackWorker: ElEnumAndUpdateRegistryInterfaceList failed with error %ld",
  1211. dwRetCode);
  1212. }
  1213. }
  1214. else
  1215. {
  1216. if (memcmp( &(pWnodeHeader->Guid),
  1217. &GUID_NDIS_NOTIFY_BIND,
  1218. sizeof(GUID)) == 0)
  1219. {
  1220. // protocol BIND callback
  1221. DbLogPCBEvent (DBLOG_CATEG_INFO, NULL, EAPOL_NDISUIO_BIND, pwszDeviceName);
  1222. TRACE0(DEVICE, "ElBindingsNotificationCallbackWorker: Callback for protocol BIND");
  1223. if ((dwRetCode = ElEnumAndOpenInterfaces (
  1224. NULL, pwszDeviceGUID, 0, NULL))
  1225. != NO_ERROR)
  1226. {
  1227. TRACE1 (DEVICE, "ElBindingsNotificationCallbackWorker: ElEnumAndOpenInterfaces returned error %ld",
  1228. dwRetCode);
  1229. }
  1230. }
  1231. }
  1232. }
  1233. while (FALSE);
  1234. TRACE1 (DEVICE, "ElBindingsNotificationCallbackWorker: processed, RetCode = %ld", dwRetCode);
  1235. if (pWnodeHeader != NULL)
  1236. {
  1237. FREE (pWnodeHeader);
  1238. }
  1239. if (pwszDeviceName != NULL)
  1240. {
  1241. FREE (pwszDeviceName);
  1242. }
  1243. if (pwszDeviceGUID != NULL)
  1244. {
  1245. FREE (pwszDeviceGUID);
  1246. }
  1247. InterlockedDecrement (&g_lWorkerThreads);
  1248. return 0;
  1249. }
  1250. //
  1251. // ElEnumAndOpenInterfaces
  1252. //
  1253. // Description:
  1254. //
  1255. // Enumerates interfaces and intializes EAPOL on desired ones.
  1256. //
  1257. // If EAPOL is to be started on an interface, it opens a handle to
  1258. // the NDISUIO driver, calls EAPOL to create and initialize PCB for the
  1259. // interface, and finally adds an entry to the interface hashtable.
  1260. //
  1261. // If pwszDesiredGUID is not NULL, all interfaces are enumerated, but
  1262. // EAPOL will be initialized only on the interface whose GUID matches.
  1263. //
  1264. // If pwszDesiredDescription is not NULL, all interfaces are enumerated, but
  1265. // EAPOL will be initialized only on the interface whose description matches.
  1266. //
  1267. // If pwszDesiredGUID and pwszDescription are both NULL, all interfaces are
  1268. // enumerated. EAPOL will be initialized only on all interfaces that
  1269. // does have an entry in the interface hashtable.
  1270. //
  1271. //
  1272. // Arguments:
  1273. // pwszDesiredDescription - Interface Description on which EAPOL is to
  1274. // be started
  1275. // pwszDesiredGUID - Interface GUID on which EAPOL is to be started
  1276. //
  1277. // Return values:
  1278. // NO_ERROR - Success
  1279. // non-zero - Error
  1280. //
  1281. DWORD
  1282. ElEnumAndOpenInterfaces (
  1283. WCHAR *pwszDesiredDescription,
  1284. WCHAR *pwszDesiredGUID,
  1285. DWORD dwHandle,
  1286. PRAW_DATA prdUserData
  1287. )
  1288. {
  1289. CHAR EnumerateBuffer[256];
  1290. PNDIS_ENUM_INTF Interfaces = NULL;
  1291. BYTE *pbNdisuioEnumBuffer = NULL;
  1292. DWORD dwNdisuioEnumBufferSize = 0;
  1293. HANDLE hDevice = NULL;
  1294. BOOL fSearchByDescription = FALSE;
  1295. BOOL fSearchByGUID = FALSE;
  1296. DWORD dwEapTypeToBeUsed = DEFAULT_EAP_TYPE;
  1297. WCHAR cwsDummyBuffer[256], *pDummyPtr = NULL;
  1298. WCHAR *pwszGUIDStart = NULL;
  1299. EAPOL_PCB *pPCB = NULL;
  1300. BOOL fPCBExists = FALSE;
  1301. BOOL fPCBReferenced = FALSE;
  1302. DWORD dwAvailableInterfaces = 0;
  1303. EAPOL_INTF_PARAMS EapolIntfParams;
  1304. DWORD dwRetCode = NO_ERROR;
  1305. TRACE2 (DEVICE, "ElEnumAndOpenInterfaces: DeviceDesc = %ws, GUID = %ws",
  1306. pwszDesiredDescription, pwszDesiredGUID);
  1307. ACQUIRE_WRITE_LOCK (&(g_ITFLock));
  1308. if (pwszDesiredGUID == NULL)
  1309. {
  1310. if (pwszDesiredDescription != NULL)
  1311. {
  1312. fSearchByDescription = TRUE;
  1313. }
  1314. }
  1315. else
  1316. {
  1317. if (pwszDesiredDescription != NULL)
  1318. {
  1319. RELEASE_WRITE_LOCK (&(g_ITFLock));
  1320. return ERROR;
  1321. }
  1322. fSearchByGUID = TRUE;
  1323. }
  1324. ZeroMemory (EnumerateBuffer, 256);
  1325. Interfaces = (PNDIS_ENUM_INTF)EnumerateBuffer;
  1326. //
  1327. // Allocate amount of memory as instructed by NdisEnumerateInterfaces
  1328. // once the API allows querying of bytes required
  1329. //
  1330. Interfaces->TotalInterfaces = 0;
  1331. Interfaces->AvailableInterfaces = 0;
  1332. Interfaces->BytesNeeded = 0;
  1333. if (!NdisEnumerateInterfaces(Interfaces, 256))
  1334. {
  1335. RELEASE_WRITE_LOCK (&(g_ITFLock));
  1336. dwRetCode = GetLastError ();
  1337. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: NdisEnumerateInterfaces failed with error %ld",
  1338. dwRetCode);
  1339. return dwRetCode;
  1340. }
  1341. dwNdisuioEnumBufferSize = (Interfaces->BytesNeeded + 7) & 0xfffffff8;
  1342. dwAvailableInterfaces = Interfaces->AvailableInterfaces;
  1343. if (dwNdisuioEnumBufferSize == 0)
  1344. {
  1345. RELEASE_WRITE_LOCK (&(g_ITFLock));
  1346. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: MALLOC skipped for pbNdisuioEnumBuffer as dwNdisuioEnumBufferSize == 0");
  1347. dwRetCode = NO_ERROR;
  1348. return dwRetCode;
  1349. }
  1350. pbNdisuioEnumBuffer = (BYTE *) MALLOC (4*dwNdisuioEnumBufferSize);
  1351. if (pbNdisuioEnumBuffer == NULL)
  1352. {
  1353. RELEASE_WRITE_LOCK (&(g_ITFLock));
  1354. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1355. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: MALLOC failed for pbNdisuioEnumBuffer");
  1356. return dwRetCode;
  1357. }
  1358. Interfaces = (PNDIS_ENUM_INTF)pbNdisuioEnumBuffer;
  1359. // Enumerate all the interfaces present on the machine
  1360. if ((dwRetCode = ElNdisuioEnumerateInterfaces (
  1361. Interfaces,
  1362. dwAvailableInterfaces,
  1363. 4*dwNdisuioEnumBufferSize)) == NO_ERROR)
  1364. {
  1365. UNICODE_STRING *pInterfaceName = NULL;
  1366. UNICODE_STRING *pInterfaceDescription = NULL;
  1367. DWORD i;
  1368. // Update the interface list in the registry that NDISUIO has bound to.
  1369. // The current interface list is just overwritten into the registry.
  1370. if ((dwRetCode = ElUpdateRegistryInterfaceList (Interfaces))
  1371. != NO_ERROR)
  1372. {
  1373. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: ElUpdateInterfaceList failed with error =%ld",
  1374. dwRetCode);
  1375. dwRetCode = NO_ERROR;
  1376. // log
  1377. }
  1378. for (i=0; i < Interfaces->TotalInterfaces; i++)
  1379. {
  1380. fPCBExists = fPCBReferenced = FALSE;
  1381. if ((dwRetCode != NO_ERROR) &&
  1382. (fSearchByDescription || fSearchByGUID))
  1383. {
  1384. break;
  1385. }
  1386. else
  1387. {
  1388. dwRetCode = NO_ERROR;
  1389. }
  1390. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  1391. {
  1392. pInterfaceName = &(Interfaces->Interface[i].DeviceName);
  1393. }
  1394. else
  1395. {
  1396. TRACE0(INIT, "NdisEnumerateInterfaces: Device Name was NULL");
  1397. continue;
  1398. }
  1399. TRACE1(INIT, "Device: %ws", pInterfaceName->Buffer);
  1400. if (Interfaces->Interface[i].DeviceDescription.Buffer != NULL)
  1401. {
  1402. pInterfaceDescription = &(Interfaces->Interface[i].DeviceDescription);
  1403. }
  1404. else
  1405. {
  1406. TRACE0(INIT, "NdisEnumerateInterfaces: Device Description was NULL");
  1407. continue;
  1408. }
  1409. TRACE1(INIT, "Description: %ws", pInterfaceDescription->Buffer);
  1410. // EAPOL requested be started only a particular
  1411. // interface
  1412. if (fSearchByDescription)
  1413. {
  1414. if (wcscmp (pInterfaceDescription->Buffer,
  1415. pwszDesiredDescription)
  1416. != 0)
  1417. {
  1418. // No match, continue with next interface
  1419. continue;
  1420. }
  1421. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Found interface after enumeration %ws", pInterfaceDescription->Buffer);
  1422. }
  1423. if (fSearchByGUID)
  1424. {
  1425. if (wcsstr (pInterfaceName->Buffer,
  1426. pwszDesiredGUID)
  1427. == NULL)
  1428. {
  1429. // No match, continue with next interface
  1430. continue;
  1431. }
  1432. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Found interface after enumeration %ws", pInterfaceName->Buffer);
  1433. }
  1434. {
  1435. // Extract GUID-string out of device name
  1436. WCHAR *pwszGUIDEnd = NULL;
  1437. WCHAR *pwszGUID = NULL;
  1438. WCHAR wchGUIDSaveLast;
  1439. pwszGUID = pInterfaceName->Buffer;
  1440. pwszGUIDStart = wcschr( pwszGUID, L'{' );
  1441. pwszGUIDEnd = wcschr( pwszGUID, L'}' );
  1442. if (pwszGUIDStart != NULL)
  1443. {
  1444. wchGUIDSaveLast = *(pwszGUIDEnd+1);
  1445. *(pwszGUIDEnd+1) = (WCHAR)NULL;
  1446. }
  1447. // Verify if a PCB already exists for the interface
  1448. // This is possible if no media disconnect was received
  1449. // after the initial media connect
  1450. pPCB = NULL;
  1451. hDevice = NULL;
  1452. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  1453. if ((pPCB = ElGetPCBPointerFromPortGUID (pwszGUIDStart)) != NULL)
  1454. {
  1455. if (EAPOL_REFERENCE_PORT (pPCB))
  1456. {
  1457. fPCBReferenced = TRUE;
  1458. }
  1459. }
  1460. RELEASE_WRITE_LOCK (&(g_PCBLock));
  1461. // Restore interface buffer
  1462. *(pwszGUIDEnd+1) = wchGUIDSaveLast;
  1463. if (pPCB != NULL)
  1464. {
  1465. // Point to existing handle
  1466. hDevice = pPCB->hPort;
  1467. fPCBExists = TRUE;
  1468. dwRetCode = NO_ERROR;
  1469. TRACE0 (INIT, "ElEnumAndOpenInterfaces: Found PCB already existing for interface");
  1470. }
  1471. else
  1472. {
  1473. TRACE0 (INIT, "ElEnumAndOpenInterfaces: Did NOT find PCB already existing for interface");
  1474. // Open handle to ndisuio driver
  1475. if ((dwRetCode = ElOpenInterfaceHandle (
  1476. pInterfaceName->Buffer,
  1477. &hDevice
  1478. )) != NO_ERROR)
  1479. {
  1480. TRACE1 (INIT, "ElEnumAndOpenInterfaces: ElOpenInterfaceHandle failed with error = %d\n",
  1481. dwRetCode );
  1482. }
  1483. }
  1484. *(pwszGUIDEnd+1) = (CHAR)NULL;
  1485. }
  1486. if (dwRetCode != NO_ERROR)
  1487. {
  1488. TRACE0 (INIT, "ElEnumAndOpenInterfaces: Failed to open handle");
  1489. continue;
  1490. }
  1491. else
  1492. {
  1493. // Create EAPOL PCB and start state machine
  1494. if ((dwRetCode = ElCreatePort (
  1495. hDevice,
  1496. pwszGUIDStart,
  1497. pInterfaceDescription->Buffer,
  1498. dwHandle,
  1499. prdUserData
  1500. )) != NO_ERROR)
  1501. {
  1502. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Error in CreatePort = %d", dwRetCode);
  1503. if (fPCBExists)
  1504. {
  1505. if (dwRetCode = ElShutdownInterface (
  1506. pPCB->pwszDeviceGUID
  1507. ) != NO_ERROR)
  1508. {
  1509. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: ElShutdownInterface handle 1 failed with error %ld",
  1510. dwRetCode);
  1511. }
  1512. if (fPCBReferenced)
  1513. {
  1514. EAPOL_DEREFERENCE_PORT (pPCB);
  1515. }
  1516. }
  1517. else
  1518. {
  1519. // Close the handle just opened to the ndisuio driver
  1520. if ((dwRetCode = ElCloseInterfaceHandle (
  1521. hDevice,
  1522. pwszGUIDStart)) != NO_ERROR)
  1523. {
  1524. TRACE1 (DEVICE,
  1525. "ElEnumAndOpenInterfaces: Error in ElCloseInterfaceHandle %d",
  1526. dwRetCode);
  1527. }
  1528. }
  1529. // Continue with the next interface
  1530. continue;
  1531. }
  1532. else
  1533. {
  1534. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: CreatePort successful");
  1535. // If PCB already existed, do not add to the hash
  1536. // table
  1537. if (fPCBExists)
  1538. {
  1539. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: PCB already existed, skipping Interface hash table addition");
  1540. fPCBExists = FALSE;
  1541. if (fPCBReferenced)
  1542. {
  1543. EAPOL_DEREFERENCE_PORT (pPCB);
  1544. }
  1545. continue;
  1546. }
  1547. if ((dwRetCode = ElCreateInterfaceEntry (
  1548. pwszGUIDStart,
  1549. pInterfaceDescription->Buffer
  1550. )) != NO_ERROR)
  1551. {
  1552. // Could not create new interface entry
  1553. // Delete Port entry created for this GUID
  1554. if ((dwRetCode = ElDeletePort (
  1555. pwszGUIDStart,
  1556. &hDevice)) != NO_ERROR)
  1557. {
  1558. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Error in deleting port for %ws",
  1559. pwszGUIDStart);
  1560. // log
  1561. }
  1562. // Close the handle to the NDISUIO driver
  1563. if ((dwRetCode = ElCloseInterfaceHandle (
  1564. hDevice,
  1565. pwszGUIDStart)) != NO_ERROR)
  1566. {
  1567. TRACE1 (DEVICE,
  1568. "ElEnumAndOpenInterfaces: Error in ElCloseInterfaceHandle %d",
  1569. dwRetCode);
  1570. // log
  1571. }
  1572. }
  1573. }
  1574. }
  1575. } // for (i=0; i < Interfaces
  1576. }
  1577. else
  1578. {
  1579. TRACE1(INIT, "ElEnumAndOpenInterfaces: ElNdisuioEnumerateInterfaces failed with error %d",
  1580. dwRetCode);
  1581. }
  1582. TRACE1(INIT, "ElEnumAndOpenInterfaces: Completed with retcode = %d",
  1583. dwRetCode);
  1584. if (pbNdisuioEnumBuffer != NULL)
  1585. {
  1586. FREE(pbNdisuioEnumBuffer);
  1587. }
  1588. RELEASE_WRITE_LOCK (&(g_ITFLock));
  1589. return dwRetCode;
  1590. }
  1591. //
  1592. // ElOpenInterfaceHandle
  1593. //
  1594. // Description:
  1595. //
  1596. // Function called to open handle to the NDISUIO driver for an interface.
  1597. //
  1598. // Arguments:
  1599. // DeviceName - Identifier for the interface is of the
  1600. // form \Device\{GUID String}
  1601. // phDevice - Output pointer to handle of NDISUIO driver for
  1602. // the interface
  1603. //
  1604. // Return values:
  1605. // NO_ERROR - success
  1606. // non-zero - error
  1607. //
  1608. DWORD
  1609. ElOpenInterfaceHandle (
  1610. IN WCHAR *pwszDeviceName,
  1611. OUT HANDLE *phDevice
  1612. )
  1613. {
  1614. DWORD dwDesiredAccess;
  1615. DWORD dwShareMode;
  1616. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  1617. DWORD dwCreationDistribution;
  1618. DWORD dwFlagsAndAttributes;
  1619. HANDLE hTemplateFile;
  1620. HANDLE hHandle = INVALID_HANDLE_VALUE;
  1621. DWORD dwRetCode = NO_ERROR;
  1622. WCHAR wNdisDeviceName[MAX_NDIS_DEVICE_NAME_LEN];
  1623. INT wNameLength;
  1624. INT NameLength = wcslen(pwszDeviceName);
  1625. DWORD dwBytesReturned;
  1626. USHORT wEthernetType = g_wEtherType8021X;
  1627. INT i;
  1628. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  1629. dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  1630. dwCreationDistribution = OPEN_EXISTING;
  1631. dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
  1632. hTemplateFile = (HANDLE)INVALID_HANDLE_VALUE;
  1633. TRACE1 (INIT, "ElOpenInterfaceHandle: Opening handle for %ws",
  1634. pwszDeviceName);
  1635. do
  1636. {
  1637. // Convert to unicode string - non-localized...
  1638. wNameLength = 0;
  1639. for (i = 0; (i < NameLength) && (i < MAX_NDIS_DEVICE_NAME_LEN-1); i++)
  1640. {
  1641. wNdisDeviceName[i] = (WCHAR)pwszDeviceName[i];
  1642. wNameLength++;
  1643. }
  1644. wNdisDeviceName[i] = L'\0';
  1645. TRACE1(DEVICE, "ElOpenInterfaceHandle: Trying to access NDIS Device: %ws\n",
  1646. wNdisDeviceName);
  1647. // --ft: Replace these calls to Ndisuio with the calls to the opened handles hash.
  1648. //hHandle = CreateFileA(
  1649. // pNdisuioDevice,
  1650. // dwDesiredAccess,
  1651. // dwShareMode,
  1652. // lpSecurityAttributes,
  1653. // dwCreationDistribution,
  1654. // dwFlagsAndAttributes,
  1655. // hTemplateFile
  1656. // );
  1657. //
  1658. //if (hHandle == INVALID_HANDLE_VALUE)
  1659. //{
  1660. // *phDevice = NULL;
  1661. // dwRetCode = GetLastError();
  1662. // TRACE1 (INIT, "ElOpenInterfaceHandle: Failed in CreateFile with error %d", dwRetCode);
  1663. // break;
  1664. //}
  1665. //else
  1666. //{
  1667. // *phDevice = hHandle;
  1668. //}
  1669. //
  1670. //if (!(DeviceIoControl(
  1671. // *phDevice,
  1672. // IOCTL_NDISUIO_OPEN_DEVICE,
  1673. // (LPVOID)&wNdisDeviceName[0],
  1674. // wNameLength*sizeof(WCHAR),
  1675. // NULL,
  1676. // 0,
  1677. // &dwBytesReturned,
  1678. // NULL)))
  1679. //
  1680. //{
  1681. // *phDevice = NULL;
  1682. // if ((dwRetCode = GetLastError()) == 0)
  1683. // {
  1684. // dwRetCode = ERROR_IO_DEVICE;
  1685. // }
  1686. // TRACE1(DEVICE, "ElOpenInterfaceHandle: Error in accessing NDIS Device: %ws", wNdisDeviceName);
  1687. // break;
  1688. //}
  1689. // The call below goes to the opened handles hash which takes care of
  1690. // sharing the handles. EAPOL doesn't have to care about anyone else
  1691. // using this handle - the sharing hash keeps a ref count for the handle
  1692. // such that the callers can just call OpenIntfHandle & CloseIntfHandle
  1693. // whenever they wish.
  1694. dwRetCode = OpenIntfHandle(
  1695. wNdisDeviceName,
  1696. &hHandle);
  1697. if (dwRetCode != ERROR_SUCCESS)
  1698. {
  1699. TRACE1(DEVICE, "ElOpenInterfaceHandle: Error in OpenIntfHandle(%ws)", wNdisDeviceName);
  1700. break;
  1701. }
  1702. *phDevice = hHandle;
  1703. TRACE2(DEVICE, "ElOpenInterfaceHandle: OpenIntfHandle(%ws) = %d", wNdisDeviceName, *phDevice);
  1704. // IOCTL down the Ethernet type
  1705. if (!(DeviceIoControl(
  1706. *phDevice,
  1707. IOCTL_NDISUIO_SET_ETHER_TYPE,
  1708. (LPVOID)&wEthernetType,
  1709. sizeof(USHORT),
  1710. NULL,
  1711. 0,
  1712. &dwBytesReturned,
  1713. NULL)))
  1714. {
  1715. *phDevice = NULL;
  1716. if ((dwRetCode = GetLastError()) == 0)
  1717. {
  1718. dwRetCode = ERROR_IO_DEVICE;
  1719. }
  1720. TRACE1(DEVICE, "ElOpenInterfaceHandle: Error in ioctling ETHER type : %ws", wNdisDeviceName);
  1721. break;
  1722. }
  1723. // Bind for asynchronous I/O handling of Read/Write data
  1724. // Depending on whether it is completion for Readfile() or WriteFile()
  1725. // ElIoCompletionRoutine will call ElReadCompletionRoutine
  1726. // or ElWriteCompletionRoutine
  1727. if (!BindIoCompletionCallback(
  1728. *phDevice,
  1729. ElIoCompletionRoutine,
  1730. 0
  1731. ))
  1732. {
  1733. dwRetCode = GetLastError();
  1734. if (dwRetCode != ERROR_INVALID_PARAMETER)
  1735. {
  1736. *phDevice = NULL;
  1737. TRACE1 (DEVICE, "ElOpenInterfaceHandle: Error in BindIoCompletionCallBac %d", dwRetCode);
  1738. break;
  1739. }
  1740. else
  1741. {
  1742. TRACE0 (DEVICE, "ElOpenInterfaceHandle: BindIoCompletionCallback already done !!!");
  1743. dwRetCode = NO_ERROR;
  1744. }
  1745. }
  1746. } while (FALSE);
  1747. // Cleanup if there is error
  1748. if (dwRetCode != NO_ERROR)
  1749. {
  1750. if (hHandle != INVALID_HANDLE_VALUE)
  1751. {
  1752. // --ft: if anything bad happened, don't overwrite the dwRetCode - we're interested
  1753. // what the first error was, not the error that might have happened when we
  1754. // tried to close the hHandle.
  1755. // Note: ElCloseInterfaceHandle understands the Guid both decorated and un-decorated
  1756. if (ElCloseInterfaceHandle(hHandle, pwszDeviceName) != ERROR_SUCCESS)
  1757. {
  1758. TRACE1 (INIT, "ElOpenInterfaceHandle: Error in CloseHandle %d", dwRetCode);
  1759. }
  1760. }
  1761. }
  1762. TRACE2 (INIT, "ElOpenInterfaceHandle: Opened handle %p with dwRetCode %d", *phDevice, dwRetCode);
  1763. return (dwRetCode);
  1764. }
  1765. //
  1766. // ElCloseInterfaceHandle
  1767. //
  1768. // Description:
  1769. //
  1770. // Function called to close handle to NDISUIO driver for an interface
  1771. //
  1772. // Arguments:
  1773. // hDevice - Handle to NDISUIO device for the interface
  1774. //
  1775. // Return values:
  1776. // NO_ERROR - success
  1777. // non-zero - error
  1778. //
  1779. DWORD
  1780. ElCloseInterfaceHandle (
  1781. IN HANDLE hDevice,
  1782. IN LPWSTR pwszDeviceGuid
  1783. )
  1784. {
  1785. DWORD dwRetCode = ERROR_SUCCESS;
  1786. WCHAR wNdisDeviceName[MAX_NDIS_DEVICE_NAME_LEN];
  1787. TRACE2 (DEVICE, "ElCloseInterfaceHandle(0x%x,%ws) entered", hDevice, pwszDeviceGuid);
  1788. ZeroMemory (wNdisDeviceName, MAX_NDIS_DEVICE_NAME_LEN);
  1789. // if first char in the Guid is '\' then we assume the GUID format is
  1790. // '\DEVICE\{...}'. We do just the UNICODE conversion then
  1791. if (pwszDeviceGuid[0] == '\\')
  1792. {
  1793. wcscpy (wNdisDeviceName, pwszDeviceGuid);
  1794. }
  1795. // else, we assume the Guid is un-decorated, and we add the decorations.
  1796. else
  1797. {
  1798. wcscpy(wNdisDeviceName, L"\\DEVICE\\");
  1799. wcsncat(wNdisDeviceName, pwszDeviceGuid, MAX_NDIS_DEVICE_NAME_LEN - 8);
  1800. wNdisDeviceName[MAX_NDIS_DEVICE_NAME_LEN-1]=L'\0';
  1801. }
  1802. // --ft: For now, don't go directly to Ndisuio to close handles. Instead,
  1803. // go to the opened handles hash. This takes care of all the handle sharing
  1804. // problem.
  1805. dwRetCode = CloseIntfHandle(wNdisDeviceName);
  1806. //if (!CloseHandle(hDevice))
  1807. //{
  1808. // dwRetCode = GetLastError();
  1809. //}
  1810. if (dwRetCode != ERROR_SUCCESS)
  1811. {
  1812. TRACE1 (INIT, "ElCloseInterfaceHandle: Error in CloseHandle %d",
  1813. dwRetCode);
  1814. }
  1815. return dwRetCode;
  1816. }
  1817. //
  1818. // ElReadFromInterface
  1819. //
  1820. // Description:
  1821. //
  1822. // Function called to perform Overlapped read on handle to NDISUIO driver
  1823. //
  1824. // Arguments:
  1825. // hDevice - Handle to NDISUIO driver for this interface
  1826. // pElBuffer - Context buffer
  1827. // dwBufferLength - Bytes to be read
  1828. //
  1829. // Return values:
  1830. // NO_ERROR - success
  1831. // non-zero - error
  1832. //
  1833. DWORD
  1834. ElReadFromInterface (
  1835. IN HANDLE hDevice,
  1836. IN PEAPOL_BUFFER pElBuffer,
  1837. IN DWORD dwBufferLength
  1838. )
  1839. {
  1840. DWORD dwRetCode = NO_ERROR;
  1841. if (!ReadFile (
  1842. hDevice,
  1843. pElBuffer->pBuffer,
  1844. dwBufferLength,
  1845. NULL,
  1846. &pElBuffer->Overlapped
  1847. ))
  1848. {
  1849. dwRetCode = GetLastError();
  1850. if (dwRetCode == ERROR_IO_PENDING)
  1851. {
  1852. // Pending status is fine, we are doing OVERLAPPED read
  1853. dwRetCode = NO_ERROR;
  1854. }
  1855. else
  1856. {
  1857. TRACE1 (DEVICE, "ElReadFromInterface: ReadFile failed with error %d",
  1858. dwRetCode);
  1859. }
  1860. }
  1861. return dwRetCode;
  1862. }
  1863. //
  1864. // ElWriteToInterface
  1865. //
  1866. // Description:
  1867. //
  1868. // Function called to perform Overlapped write on handle to NDISUIO driver
  1869. //
  1870. // Arguments:
  1871. // hDevice - Handle to NDISUIO device for this interface
  1872. // pElBuffer - Context buffer
  1873. // dwBufferLength - Bytes to be written
  1874. //
  1875. // Return values:
  1876. // NO_ERROR - success
  1877. // non-zero - error
  1878. //
  1879. DWORD
  1880. ElWriteToInterface (
  1881. IN HANDLE hDevice,
  1882. IN PEAPOL_BUFFER pElBuffer,
  1883. IN DWORD dwBufferLength
  1884. )
  1885. {
  1886. DWORD dwRetCode = NO_ERROR;
  1887. TRACE0 (DEVICE, "ElWriteToInterface entered");
  1888. if (!WriteFile (
  1889. hDevice,
  1890. pElBuffer->pBuffer,
  1891. dwBufferLength,
  1892. NULL,
  1893. &pElBuffer->Overlapped
  1894. ))
  1895. {
  1896. dwRetCode = GetLastError();
  1897. if (dwRetCode == ERROR_IO_PENDING)
  1898. {
  1899. // Pending status is fine, we are doing OVERLAPPED write
  1900. dwRetCode = NO_ERROR;
  1901. }
  1902. else
  1903. {
  1904. TRACE1 (DEVICE, "ElWriteToInterface: WriteFile failed with error %d",
  1905. dwRetCode);
  1906. }
  1907. }
  1908. TRACE1 (DEVICE, "ElWriteToInterface completed, RetCode = %d", dwRetCode);
  1909. return dwRetCode;
  1910. }
  1911. //
  1912. // ElHashInterfaceDescToBucket
  1913. //
  1914. // Description:
  1915. //
  1916. // Function called to convert Friendly name of interface into interface hash
  1917. // table index.
  1918. //
  1919. // Arguments:
  1920. // pwszInterfaceDesc - Friendly name of the interface
  1921. //
  1922. // Return values:
  1923. // Hash table index between from 0 to INTF_TABLE_BUCKETS-1
  1924. //
  1925. DWORD
  1926. ElHashInterfaceDescToBucket (
  1927. IN WCHAR *pwszInterfaceDesc
  1928. )
  1929. {
  1930. return ((DWORD)((_wtol(pwszInterfaceDesc)) % INTF_TABLE_BUCKETS));
  1931. }
  1932. //
  1933. // ElGetITFPointerFromInterfaceDesc
  1934. //
  1935. // Description:
  1936. //
  1937. // Function called to convert Friendly name of interface to ITF entry pointer
  1938. //
  1939. // Arguments:
  1940. // pwszInterfaceDesc - Friendly name of the interface
  1941. //
  1942. // Return values:
  1943. // Pointer to interface entry in hash table
  1944. //
  1945. PEAPOL_ITF
  1946. ElGetITFPointerFromInterfaceDesc (
  1947. IN WCHAR *pwszInterfaceDesc
  1948. )
  1949. {
  1950. EAPOL_ITF *pITFWalker = NULL;
  1951. DWORD dwIndex;
  1952. INT i=0;
  1953. TRACE1 (DEVICE, "ElGetITFPointerFromInterfaceDesc: Desc = %ws", pwszInterfaceDesc);
  1954. if (pwszInterfaceDesc == NULL)
  1955. {
  1956. return (NULL);
  1957. }
  1958. dwIndex = ElHashInterfaceDescToBucket (pwszInterfaceDesc);
  1959. TRACE1 (DEVICE, "ElGetITFPointerFromItfDesc: Index %d", dwIndex);
  1960. for (pITFWalker = g_ITFTable.pITFBuckets[dwIndex].pItf;
  1961. pITFWalker != NULL;
  1962. pITFWalker = pITFWalker->pNext
  1963. )
  1964. {
  1965. if (wcsncmp (pITFWalker->pwszInterfaceDesc, pwszInterfaceDesc, wcslen(pwszInterfaceDesc)) == 0)
  1966. {
  1967. return pITFWalker;
  1968. }
  1969. }
  1970. return (NULL);
  1971. }
  1972. //
  1973. // ElRemoveITFFromTable
  1974. //
  1975. // Description:
  1976. //
  1977. // Function called to remove an interface entry from the interface hash
  1978. // table
  1979. //
  1980. // Arguments:
  1981. // pITF - Point to the Interface entry in the hash table
  1982. //
  1983. // Return values:
  1984. //
  1985. VOID
  1986. ElRemoveITFFromTable (
  1987. IN EAPOL_ITF *pITF
  1988. )
  1989. {
  1990. DWORD dwIndex;
  1991. EAPOL_ITF *pITFWalker = NULL;
  1992. EAPOL_ITF *pITFTemp = NULL;
  1993. if (pITF == NULL)
  1994. {
  1995. TRACE0 (EAPOL, "ElRemoveITFFromTable: Deleting NULL ITF, returning");
  1996. return;
  1997. }
  1998. dwIndex = ElHashInterfaceDescToBucket (pITF->pwszInterfaceDesc);
  1999. pITFWalker = g_ITFTable.pITFBuckets[dwIndex].pItf;
  2000. pITFTemp = pITFWalker;
  2001. while (pITFTemp != NULL)
  2002. {
  2003. if (wcsncmp (pITFTemp->pwszInterfaceGUID,
  2004. pITF->pwszInterfaceGUID, wcslen(pITF->pwszInterfaceGUID)) == 0)
  2005. {
  2006. // Entry is at head of list in table
  2007. if (pITFTemp == g_ITFTable.pITFBuckets[dwIndex].pItf)
  2008. {
  2009. g_ITFTable.pITFBuckets[dwIndex].pItf = pITFTemp->pNext;
  2010. }
  2011. else
  2012. {
  2013. // Entry is inside list in table
  2014. pITFWalker->pNext = pITFTemp->pNext;
  2015. }
  2016. break;
  2017. }
  2018. pITFWalker = pITFTemp;
  2019. pITFTemp = pITFWalker->pNext;
  2020. }
  2021. return;
  2022. }
  2023. //
  2024. // ElNdisuioEnumerateInterfaces
  2025. //
  2026. // Description:
  2027. //
  2028. // Function called to enumerate the interfaces on which NDISUIO is bound
  2029. //
  2030. // Arguments:
  2031. // pItfBuffer - Pointer to buffer which will hold interface details
  2032. // dwAvailableInterfaces - Number of interfaces for which details can
  2033. // be held in pItfBuffer
  2034. // dwBufferSize - Number of bytes in pItfBuffer
  2035. //
  2036. // Return values:
  2037. //
  2038. DWORD
  2039. ElNdisuioEnumerateInterfaces (
  2040. IN OUT PNDIS_ENUM_INTF pItfBuffer,
  2041. IN DWORD dwAvailableInterfaces,
  2042. IN DWORD dwBufferSize
  2043. )
  2044. {
  2045. DWORD dwDesiredAccess;
  2046. DWORD dwShareMode;
  2047. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  2048. DWORD dwCreationDistribution;
  2049. DWORD dwFlagsAndAttributes;
  2050. HANDLE hTemplateFile;
  2051. HANDLE hHandle;
  2052. DWORD dwBytesReturned = 0;
  2053. INT i;
  2054. CHAR Buf[1024];
  2055. DWORD BufLength = sizeof(Buf);
  2056. DWORD BytesWritten = 0;
  2057. PNDISUIO_QUERY_BINDING pQueryBinding = NULL;
  2058. PCHAR pTempBuf = NULL;
  2059. DWORD dwRetCode = NO_ERROR;
  2060. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  2061. dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  2062. dwCreationDistribution = OPEN_EXISTING;
  2063. dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
  2064. hTemplateFile = (HANDLE)INVALID_HANDLE_VALUE;
  2065. TRACE0 (DEVICE, "ElNdisuioEnumerateInterfaces: Opening handle");
  2066. do
  2067. {
  2068. hHandle = CreateFileA (
  2069. pNdisuioDevice,
  2070. dwDesiredAccess,
  2071. dwShareMode,
  2072. lpSecurityAttributes,
  2073. dwCreationDistribution,
  2074. 0,
  2075. NULL
  2076. );
  2077. if (hHandle == INVALID_HANDLE_VALUE)
  2078. {
  2079. dwRetCode = GetLastError();
  2080. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: Failed in CreateFile with error %d", dwRetCode);
  2081. break;
  2082. }
  2083. // Send IOCTL to ensure NDISUIO binds to all relevant interfaces
  2084. if (!DeviceIoControl (
  2085. hHandle,
  2086. IOCTL_NDISUIO_BIND_WAIT,
  2087. NULL,
  2088. 0,
  2089. NULL,
  2090. 0,
  2091. &dwBytesReturned,
  2092. NULL))
  2093. {
  2094. dwRetCode = GetLastError();
  2095. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: Failed in DeviceIoCoontrol NDISUIO_BIND_WAIT with error %d", dwRetCode);
  2096. break;
  2097. }
  2098. pQueryBinding = (PNDISUIO_QUERY_BINDING)Buf;
  2099. pTempBuf = (PBYTE)pItfBuffer + dwBufferSize;
  2100. i = 0;
  2101. for (pQueryBinding->BindingIndex = i;
  2102. pQueryBinding->BindingIndex < dwAvailableInterfaces;
  2103. pQueryBinding->BindingIndex = ++i)
  2104. {
  2105. // Query for one interface at a time
  2106. if (DeviceIoControl (
  2107. hHandle,
  2108. IOCTL_NDISUIO_QUERY_BINDING,
  2109. pQueryBinding,
  2110. sizeof(NDISUIO_QUERY_BINDING),
  2111. Buf,
  2112. BufLength,
  2113. &BytesWritten,
  2114. NULL))
  2115. {
  2116. TRACE3 (DEVICE, "NdisuioEnumerateInterfaces: NDISUIO bound to: (%ld) %ws\n - %ws\n",
  2117. pQueryBinding->BindingIndex,
  2118. (PUCHAR)pQueryBinding + pQueryBinding->DeviceNameOffset,
  2119. (PUCHAR)pQueryBinding + pQueryBinding->DeviceDescrOffset);
  2120. pTempBuf = pTempBuf - ((pQueryBinding->DeviceNameLength + 7) & 0xfffffff8);
  2121. if (((PBYTE)pTempBuf - (PBYTE)&pItfBuffer->Interface[pItfBuffer->TotalInterfaces]) <= 0)
  2122. {
  2123. // Going beyond start of buffer, Error
  2124. TRACE0 (DEVICE, "NdisuioEnumerateInterfaces: DeviceName: Memory being corrupted !!!");
  2125. dwRetCode = ERROR_INVALID_DATA;
  2126. break;
  2127. }
  2128. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.Buffer = (PWCHAR) pTempBuf;
  2129. memcpy ((BYTE *)(pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.Buffer), (BYTE *)((PUCHAR)pQueryBinding + pQueryBinding->DeviceNameOffset), (pQueryBinding->DeviceNameLength ));
  2130. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.Length = (SHORT) ( pQueryBinding->DeviceNameLength );
  2131. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.MaximumLength = (SHORT) ( pQueryBinding->DeviceNameLength );
  2132. pTempBuf = pTempBuf - ((pQueryBinding->DeviceDescrLength + 7) & 0xfffffff8);;
  2133. if (((PBYTE)pTempBuf - (PBYTE)&pItfBuffer->Interface[pItfBuffer->TotalInterfaces]) <= 0)
  2134. {
  2135. // Going beyond start of buffer, Error
  2136. TRACE0 (DEVICE, "NdisuioEnumerateInterfaces: DeviceDescr: Memory being corrupted !!!");
  2137. dwRetCode = ERROR_INVALID_DATA;
  2138. break;
  2139. }
  2140. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.Buffer = (PWCHAR) pTempBuf;
  2141. memcpy ((pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.Buffer), (PWCHAR)((PUCHAR)pQueryBinding + pQueryBinding->DeviceDescrOffset), (pQueryBinding->DeviceDescrLength ));
  2142. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.Length = (SHORT) (pQueryBinding->DeviceDescrLength );
  2143. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.MaximumLength = (SHORT) (pQueryBinding->DeviceDescrLength );
  2144. pItfBuffer->TotalInterfaces++;
  2145. memset(Buf, 0, BufLength);
  2146. }
  2147. else
  2148. {
  2149. dwRetCode = GetLastError ();
  2150. if (dwRetCode != ERROR_NO_MORE_ITEMS)
  2151. {
  2152. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: DeviceIoControl terminated for with IOCTL_NDISUIO_QUERY_BINDING with error %ld",
  2153. dwRetCode);
  2154. }
  2155. else
  2156. {
  2157. // Reset error, since it only indicates end-of-list
  2158. dwRetCode = NO_ERROR;
  2159. TRACE0 (DEVICE, "ElNdisuioEnumerateInterfaces: DeviceIoControl IOCTL_NDISUIO_QUERY_BINDING has no more entries");
  2160. }
  2161. break;
  2162. }
  2163. }
  2164. } while (FALSE);
  2165. // Cleanup
  2166. if (hHandle != INVALID_HANDLE_VALUE)
  2167. {
  2168. if (!CloseHandle(hHandle))
  2169. {
  2170. dwRetCode = GetLastError();
  2171. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: Error in CloseHandle %d", dwRetCode);
  2172. }
  2173. }
  2174. return dwRetCode;
  2175. }
  2176. //
  2177. // ElShutdownInterface
  2178. //
  2179. // Description:
  2180. //
  2181. // Function called to stop EAPOL state machine, close handle to NDISUIO and
  2182. // remove existence of the interface from the module
  2183. //
  2184. // Arguments:
  2185. // pwszDeviceGUID - Pointer to interface GUID
  2186. //
  2187. // Return values:
  2188. // NO_ERROR - success
  2189. // non-zero - error
  2190. //
  2191. DWORD
  2192. ElShutdownInterface (
  2193. IN WCHAR *pwszDeviceGUID
  2194. )
  2195. {
  2196. WCHAR *pwszGUID = NULL;
  2197. EAPOL_PCB *pPCB = NULL;
  2198. EAPOL_ITF *pITF = NULL;
  2199. HANDLE hDevice = NULL;
  2200. DWORD dwRetCode = NO_ERROR;
  2201. do
  2202. {
  2203. TRACE1 (DEVICE, "ElShutdownInterface: Called for interface removal for %ws",
  2204. pwszGUID);
  2205. pwszGUID = MALLOC ( (wcslen (pwszDeviceGUID) + 1) * sizeof(WCHAR));
  2206. if (pwszGUID == NULL)
  2207. {
  2208. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2209. TRACE0 (DEVICE, "ElShutdownInterface: MALLOC failed for pwszGUID");
  2210. break;
  2211. }
  2212. wcscpy (pwszGUID, pwszDeviceGUID);
  2213. ACQUIRE_WRITE_LOCK (&(g_ITFLock));
  2214. // Check if EAPOL was actually started on this interface
  2215. // Verify by checking existence of corresponding
  2216. // entry in hash table
  2217. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  2218. if ((pPCB = ElGetPCBPointerFromPortGUID(pwszGUID))
  2219. != NULL)
  2220. {
  2221. RELEASE_WRITE_LOCK (&(g_PCBLock));
  2222. TRACE0 (DEVICE, "ElShutdownInterface: Found PCB entry for interface");
  2223. if ((pITF = ElGetITFPointerFromInterfaceDesc(
  2224. pPCB->pwszFriendlyName))
  2225. == NULL)
  2226. {
  2227. TRACE0 (DEVICE, "ElShutdownInterface: Did not find ITF entry when PCB exits, HOW BIZARRE !!!");
  2228. }
  2229. if ((dwRetCode = ElDeletePort (
  2230. pwszGUID,
  2231. &hDevice)) != NO_ERROR)
  2232. {
  2233. TRACE1 (DEVICE, "ElShutdownInterface: Error in deleting port for %ws",
  2234. pPCB->pwszDeviceGUID);
  2235. }
  2236. // Remove interface entry from interface table
  2237. if (pITF != NULL)
  2238. {
  2239. ElRemoveITFFromTable(pITF);
  2240. if (pITF->pwszInterfaceDesc)
  2241. {
  2242. FREE (pITF->pwszInterfaceDesc);
  2243. }
  2244. if (pITF->pwszInterfaceGUID)
  2245. {
  2246. FREE (pITF->pwszInterfaceGUID);
  2247. }
  2248. if (pITF)
  2249. {
  2250. FREE (pITF);
  2251. }
  2252. }
  2253. // Close the handle to the NDISUIO driver
  2254. if (hDevice != NULL)
  2255. {
  2256. if ((dwRetCode = ElCloseInterfaceHandle (hDevice, pwszGUID))
  2257. != NO_ERROR)
  2258. {
  2259. TRACE1 (DEVICE,
  2260. "ElShutdownInterface: Error in ElCloseInterfaceHandle %d",
  2261. dwRetCode);
  2262. }
  2263. }
  2264. TRACE1 (DEVICE, "ElShutdownInterface: Port deleted (%ws)",
  2265. pwszGUID);
  2266. }
  2267. else
  2268. {
  2269. RELEASE_WRITE_LOCK (&(g_PCBLock));
  2270. // Ignore device removal
  2271. TRACE0 (DEVICE, "ElShutdownInterface: ElGetPCBPointerFromPortGUID did not find any matching entry, ignoring interface REMOVAL");
  2272. }
  2273. RELEASE_WRITE_LOCK (&(g_ITFLock));
  2274. } while (FALSE);
  2275. if (pwszGUID != NULL)
  2276. {
  2277. FREE (pwszGUID);
  2278. }
  2279. return dwRetCode;
  2280. }
  2281. //
  2282. // ElCreateInterfaceEntry
  2283. //
  2284. // Description:
  2285. //
  2286. // Function called to create an entry in the global interface table
  2287. //
  2288. // Arguments:
  2289. // pwszInterfaceGUID - Pointer to interface GUID
  2290. // pwszInterfaceDescription - Pointer to interface Description
  2291. //
  2292. // Return values:
  2293. // NO_ERROR - success
  2294. // non-zero - error
  2295. //
  2296. DWORD
  2297. ElCreateInterfaceEntry (
  2298. IN WCHAR *pwszInterfaceGUID,
  2299. IN WCHAR *pwszInterfaceDescription
  2300. )
  2301. {
  2302. EAPOL_ITF * pNewITF = NULL;
  2303. DWORD dwIndex = 0;
  2304. DWORD dwRetCode = NO_ERROR;
  2305. do
  2306. {
  2307. dwIndex = ElHashInterfaceDescToBucket (pwszInterfaceDescription);
  2308. pNewITF = (PEAPOL_ITF) MALLOC (sizeof (EAPOL_ITF));
  2309. if (pNewITF == NULL)
  2310. {
  2311. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2312. break;
  2313. }
  2314. pNewITF->pwszInterfaceGUID =
  2315. (WCHAR *) MALLOC ((wcslen(pwszInterfaceGUID) + 1)*sizeof(WCHAR));
  2316. if (pNewITF->pwszInterfaceGUID == NULL)
  2317. {
  2318. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2319. break;
  2320. }
  2321. pNewITF->pwszInterfaceDesc =
  2322. (WCHAR *) MALLOC ((wcslen(pwszInterfaceDescription) + 1)*sizeof(WCHAR));
  2323. if (pNewITF->pwszInterfaceDesc == NULL)
  2324. {
  2325. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2326. break;
  2327. }
  2328. wcscpy (pNewITF->pwszInterfaceGUID, pwszInterfaceGUID);
  2329. wcscpy (pNewITF->pwszInterfaceDesc, pwszInterfaceDescription);
  2330. pNewITF->pNext = g_ITFTable.pITFBuckets[dwIndex].pItf;
  2331. g_ITFTable.pITFBuckets[dwIndex].pItf = pNewITF;
  2332. TRACE3 (DEVICE, "ElCreateInterfaceEntry: Added to hash table GUID= %ws : Desc= %ws at Index=%d",
  2333. pNewITF->pwszInterfaceGUID,
  2334. pNewITF->pwszInterfaceDesc,
  2335. dwIndex
  2336. );
  2337. }
  2338. while (FALSE);
  2339. if (dwRetCode != NO_ERROR)
  2340. {
  2341. if (pNewITF)
  2342. {
  2343. if (pNewITF->pwszInterfaceDesc)
  2344. {
  2345. FREE (pNewITF->pwszInterfaceDesc);
  2346. }
  2347. if (pNewITF->pwszInterfaceGUID)
  2348. {
  2349. FREE (pNewITF->pwszInterfaceGUID);
  2350. }
  2351. FREE (pNewITF);
  2352. }
  2353. }
  2354. return dwRetCode;
  2355. }