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.

2488 lines
74 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. // TEST globals
  18. PVOID g_QueryBinding;
  19. PVOID g_TempBuf;
  20. PVOID g_ItfBuffer;
  21. PVOID g_Buf;
  22. DWORD g_ItfBufferSize;
  23. DWORD g_BreakAt;
  24. extern
  25. VOID
  26. ElUserLogonDetection (
  27. PVOID pvContext
  28. );
  29. //
  30. // ElMediaInit
  31. //
  32. // Description:
  33. //
  34. // Called on EAPOL service startup to initialize all the media related events
  35. // and callback functions
  36. //
  37. //
  38. // Arguments:
  39. //
  40. // Return Values:
  41. //
  42. DWORD
  43. ElMediaInit (
  44. )
  45. {
  46. DWORD dwIndex = 0;
  47. DWORD dwRetCode = NO_ERROR;
  48. TRACE0 (INIT, "ElMediaInit: Entered");
  49. do
  50. {
  51. // --ft:12/04/00: Initialize locks as the first thing to do. Otherwise, EAPOL registers
  52. // with WMI and if a notification comes in before getting to initialize the lock this can
  53. // result in an AV.
  54. // Stress failure reported an AV on the following stack:
  55. // ntdll!RtlpWaitForCriticalSection+0xb1 [z:\nt\base\ntdll\resource.c @ 1631]
  56. // ntdll!RtlEnterCriticalSection+0x46 [Z:\nt\base\ntdll\i386\critsect.asm @ 157]
  57. // netman!AcquireWriteLock+0xf [z:\nt\net\config\netman\eapol\service\elsync.c @ 137]
  58. // netman!ElMediaSenseCallbackWorker+0x15c [z:\nt\net\config\netman\eapol\service\eldeviceio.c @ 937]
  59. //
  60. // The CRITICAL_SECTION looked like below:
  61. // 75e226c4 00000000 00000001 00000000 00000000
  62. // 75e226d4 00001990
  63. //
  64. // The (null) DebugInfo shows the object not being initialized successfully.
  65. //
  66. if (dwRetCode = CREATE_READ_WRITE_LOCK(&(g_ITFLock), "ITF") != NO_ERROR)
  67. {
  68. TRACE1(EAPOL, "ElMediaInit: Error (%ld) in creating g_ITFLock read-write-lock", dwRetCode);
  69. break;
  70. }
  71. // Initialize NLA locks
  72. if (dwRetCode = CREATE_READ_WRITE_LOCK(&(g_NLALock), "NLA") != NO_ERROR)
  73. {
  74. TRACE1(EAPOL, "ElMediaInit: Error (%ld) in creating g_NLALock read-write-lock", dwRetCode);
  75. break;
  76. }
  77. // Register for Media Sense detection of MEDIA_CONNECT and
  78. // MEDIA_DISCONNECT of interfaces
  79. // This is done before anything else, so that no MEDIA events are lost
  80. if ((dwRetCode = ElMediaSenseRegister (TRUE)) != NO_ERROR)
  81. {
  82. TRACE1(INIT, "ElMediaInit: ElMediaSenseRegister failed with dwRetCode = %d",
  83. dwRetCode );
  84. break;
  85. }
  86. else
  87. {
  88. g_dwModulesStarted |= WMI_MODULE_STARTED;
  89. TRACE0(INIT, "ElMediaInit: ElMediaSenseRegister successful");
  90. }
  91. // Register for device notifications. We are interested in LAN
  92. // interfaces coming and going.
  93. if ((dwRetCode = ElDeviceNotificationRegister (TRUE)) != NO_ERROR)
  94. {
  95. TRACE1(INIT, "ElMediaInit: ElDeviceNotificationRegister failed with dwRetCode = %d",
  96. dwRetCode );
  97. break;
  98. }
  99. else
  100. {
  101. g_dwModulesStarted |= DEVICE_NOTIF_STARTED;
  102. TRACE0(INIT, "ElMediaInit: ElDeviceNotificationRegister successful");
  103. }
  104. // Initialize EAPOL structures
  105. if ((dwRetCode = ElInitializeEAPOL()) != NO_ERROR)
  106. {
  107. TRACE1(INIT, "ElMediaInit: ElInitializeEAPOL failed with dwRetCode = %d",
  108. dwRetCode );
  109. break;
  110. }
  111. else
  112. {
  113. TRACE0(INIT, "ElMediaInit: ElInitializeEAPOL successful");
  114. g_dwModulesStarted |= EAPOL_MODULE_STARTED;
  115. }
  116. // Watch and update change in global registry parameters
  117. if (!QueueUserWorkItem (
  118. (LPTHREAD_START_ROUTINE)ElWatchGlobalRegistryParams,
  119. NULL,
  120. WT_EXECUTELONGFUNCTION))
  121. {
  122. dwRetCode = GetLastError();
  123. TRACE1 (DEVICE, "ElMediaInit: Critical error: QueueUserWorkItem failed for ElWatchGlobalRegistryParams with error %ld",
  124. dwRetCode);
  125. break;
  126. }
  127. // Watch changes in EAP config params by checking on
  128. // ..\EAPOL\Interfaces key
  129. if (!QueueUserWorkItem (
  130. (LPTHREAD_START_ROUTINE)ElWatchEapConfigRegistryParams,
  131. NULL,
  132. WT_EXECUTELONGFUNCTION
  133. ))
  134. {
  135. dwRetCode = GetLastError();
  136. TRACE1 (DEVICE, "ElMediaInit: Critical error: QueueUserWorkItem failed for ElWatchEapConfigRegistryParams with error %ld",
  137. dwRetCode);
  138. break;
  139. }
  140. // Use task bar window for getting login notifications
  141. if (!QueueUserWorkItem (
  142. (LPTHREAD_START_ROUTINE)ElUserLogonDetection,
  143. NULL,
  144. WT_EXECUTELONGFUNCTION))
  145. {
  146. dwRetCode = GetLastError();
  147. TRACE1 (DEVICE, "Critical error: QueueUserWorkItem failed for ElUserLogonDetection with error %ld",
  148. dwRetCode);
  149. break;
  150. }
  151. // Initialize interface hash bucket table
  152. g_ITFTable.pITFBuckets = (ITF_BUCKET *) MALLOC (INTF_TABLE_BUCKETS * sizeof (ITF_BUCKET));
  153. if (g_ITFTable.pITFBuckets == NULL)
  154. {
  155. TRACE0 (DEVICE, "Error in allocation memory for ITF buckets");
  156. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  157. break;
  158. }
  159. for (dwIndex=0; dwIndex < INTF_TABLE_BUCKETS; dwIndex++)
  160. {
  161. g_ITFTable.pITFBuckets[dwIndex].pItf=NULL;
  162. }
  163. ACQUIRE_WRITE_LOCK (&g_ITFLock)
  164. // Enumerate all the interfaces and start EAPOL state machine
  165. // on interfaces which are of LAN type
  166. if ((dwRetCode = ElEnumAndOpenInterfaces (NULL, NULL)) != NO_ERROR)
  167. {
  168. TRACE1(INIT, "ElMediaInit: ElEnumAndOpenInterfaces failed with dwRetCode = %d",
  169. dwRetCode );
  170. RELEASE_WRITE_LOCK (&g_ITFLock);
  171. break;
  172. }
  173. else
  174. {
  175. RELEASE_WRITE_LOCK (&g_ITFLock);
  176. TRACE0(INIT, "ElMediaInit: ElEnumAndOpenInterfaces successful");
  177. }
  178. } while (FALSE);
  179. if (dwRetCode == NO_ERROR)
  180. {
  181. TRACE0(INIT, "ElMediaInit successful");
  182. }
  183. else
  184. {
  185. }
  186. return dwRetCode;
  187. }
  188. //
  189. // ElMediaDeInit
  190. //
  191. // Description:
  192. //
  193. // Called on EAPOL service shutdown to de-initialize all the media
  194. // related events and callback functions
  195. //
  196. //
  197. // Arguments:
  198. //
  199. // Return Values:
  200. //
  201. DWORD
  202. ElMediaDeInit (
  203. )
  204. {
  205. DWORD dwRetCode = NO_ERROR;
  206. TRACE0 (INIT, "ElMediaDeInit: Entered");
  207. // DeRegister Media Sense detection of MEDIA_CONNECT and MEDIA_DISCONNECT
  208. // of interfaces
  209. if (g_dwModulesStarted & WMI_MODULE_STARTED)
  210. {
  211. if ((dwRetCode = ElMediaSenseRegister (FALSE)) != NO_ERROR )
  212. {
  213. TRACE1(INIT, "ElMediaDeInit: ElMediaSenseRegister failed with dwRetCode = %d",
  214. dwRetCode );
  215. // log
  216. }
  217. else
  218. {
  219. TRACE0(INIT, "ElMediaDeInit: ElMediaSenseRegister successful");
  220. }
  221. g_dwModulesStarted &= ~WMI_MODULE_STARTED;
  222. }
  223. // Deregister device notifications that may have been posted
  224. if (g_dwModulesStarted & DEVICE_NOTIF_STARTED)
  225. {
  226. if ((dwRetCode = ElDeviceNotificationRegister (FALSE)) != NO_ERROR)
  227. {
  228. TRACE1(INIT, "ElMediaDeInit: ElDeviceNotificationRegister failed with dwRetCode = %d",
  229. dwRetCode );
  230. // log
  231. }
  232. else
  233. {
  234. TRACE0(INIT, "ElMediaDeInit: ElDeviceNotificationRegister successful");
  235. }
  236. g_dwModulesStarted &= ~DEVICE_NOTIF_STARTED;
  237. }
  238. // Shutdown EAPOL state machine
  239. if (g_dwModulesStarted & EAPOL_MODULE_STARTED)
  240. {
  241. if ((dwRetCode = ElEAPOLDeInit()) != NO_ERROR)
  242. {
  243. TRACE1(INIT, "ElMediaDeInit: ElEAPOLDeInit failed with dwRetCode = %d",
  244. dwRetCode );
  245. // log
  246. }
  247. else
  248. {
  249. TRACE0(INIT, "ElMediaDeInit: ElEAPOLDeInit successful");
  250. }
  251. g_dwModulesStarted &= ~EAPOL_MODULE_STARTED;
  252. }
  253. // Free the interface table
  254. if (READ_WRITE_LOCK_CREATED(&(g_ITFLock)))
  255. {
  256. ACQUIRE_WRITE_LOCK (&(g_ITFLock));
  257. #if 0
  258. if (!FREE(g_ITFTable.pITFBuckets))
  259. {
  260. TRACE0 (EAPOL, "ElMediaDeInit: Error in freeing ITF table memory");
  261. dwRetCode = GetLastError();
  262. }
  263. #endif
  264. FREE(g_ITFTable.pITFBuckets);
  265. ZeroMemory (&g_ITFTable, sizeof (g_ITFTable));
  266. RELEASE_WRITE_LOCK (&(g_ITFLock));
  267. // Delete ITF table lock
  268. DELETE_READ_WRITE_LOCK(&(g_ITFLock));
  269. // Delete NLA lock
  270. DELETE_READ_WRITE_LOCK(&(g_NLALock));
  271. }
  272. TRACE0(INIT, "ElMediaDeInit completed");
  273. return dwRetCode;
  274. }
  275. //
  276. // Description:
  277. //
  278. // Function called to register CallBack function with WMI
  279. // for MEDIA_CONNECT/MEDIA_DISCONNECT events
  280. //
  281. // Arguments:
  282. // fRegister - True = Register for Media Sense
  283. // False = Deregister Media Sense requests
  284. // Return values:
  285. // NO_ERROR - Successful
  286. // non-zero - Error
  287. //
  288. DWORD
  289. ElMediaSenseRegister (
  290. IN BOOL fRegister
  291. )
  292. {
  293. DWORD dwRetCode = NO_ERROR;
  294. PVOID pvDeliveryInfo = ElMediaSenseCallback;
  295. dwRetCode = WmiNotificationRegistrationA(
  296. (LPGUID)(&GUID_NDIS_STATUS_MEDIA_CONNECT),
  297. (BOOLEAN)fRegister,
  298. pvDeliveryInfo,
  299. (ULONG_PTR)NULL,
  300. NOTIFICATION_CALLBACK_DIRECT );
  301. if (dwRetCode != NO_ERROR)
  302. {
  303. TRACE1(INIT, "ElMediaSenseRegister: Error %d in WmiNotificationRegistration:GUID_NDIS_STATUS_MEDIA_CONNECT", dwRetCode);
  304. return( dwRetCode );
  305. }
  306. dwRetCode = WmiNotificationRegistrationA(
  307. (LPGUID)(&GUID_NDIS_STATUS_MEDIA_DISCONNECT),
  308. (BOOLEAN)fRegister,
  309. pvDeliveryInfo,
  310. (ULONG_PTR)NULL,
  311. NOTIFICATION_CALLBACK_DIRECT );
  312. if (dwRetCode != NO_ERROR)
  313. {
  314. TRACE1(INIT, "ElMediaSenseRegister: Error %d in WmiNotificationRegistration:GUID_NDIS_STATUS_MEDIA_DISCONNECT", dwRetCode);
  315. return( dwRetCode );
  316. }
  317. TRACE1 (INIT, "ElMediaSenseRegister - completed with RetCode %d", dwRetCode);
  318. return( dwRetCode );
  319. }
  320. //
  321. // ElDeviceNotificationRegister
  322. //
  323. // Description:
  324. //
  325. // Function called to register for device addition/removal notifications
  326. //
  327. // Arguments:
  328. // fRegister - True = Register for Device Notifications
  329. // False = Deregister Device Notifications
  330. //
  331. // Return values:
  332. // NO_ERROR - Successful
  333. // non-zero - Error
  334. //
  335. DWORD
  336. ElDeviceNotificationRegister (
  337. IN BOOL fRegister
  338. )
  339. {
  340. HANDLE hDeviceNotification = NULL;
  341. DWORD dwRetCode = NO_ERROR;
  342. #ifdef EAPOL_SERVICE
  343. DEV_BROADCAST_DEVICEINTERFACE PnPFilter;
  344. ZeroMemory (&PnPFilter, sizeof(PnPFilter));
  345. PnPFilter.dbcc_size = sizeof(PnPFilter);
  346. PnPFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  347. PnPFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  348. // NOTE:
  349. // EAPOL service is only working with ANSI strings, hence the ANSI calls
  350. hDeviceNotification = RegisterDeviceNotificationA(
  351. (HANDLE)g_hServiceStatus,
  352. &PnPFilter,
  353. DEVICE_NOTIFY_SERVICE_HANDLE );
  354. if (hDeviceNotification == NULL)
  355. {
  356. dwRetCode = GetLastError();
  357. TRACE1 (DEVICE, "ElDeviceNotificationRegister failed with error %ld",
  358. dwRetCode);
  359. }
  360. #endif
  361. return dwRetCode;
  362. }
  363. //
  364. // ElDeviceNotificationHandler
  365. //
  366. // Description:
  367. //
  368. // Function called to handle device notifications for interface addition/
  369. // removal
  370. //
  371. // Arguments:
  372. // lpEventData - interface information
  373. // dwEventType - notification type
  374. //
  375. DWORD
  376. ElDeviceNotificationHandler (
  377. IN VOID *lpEventData,
  378. IN DWORD dwEventType
  379. )
  380. {
  381. DWORD dwEventStatus = 0;
  382. DEV_BROADCAST_DEVICEINTERFACE *pInfo =
  383. (DEV_BROADCAST_DEVICEINTERFACE *) lpEventData;
  384. PVOID pvBuffer = NULL;
  385. DWORD dwRetCode = NO_ERROR;
  386. TRACE0 (DEVICE, "ElDeviceNotificationHandler entered");
  387. do
  388. {
  389. if (g_hEventTerminateEAPOL == NULL)
  390. {
  391. break;
  392. }
  393. // Check if have already gone through EAPOLCleanUp before
  394. if ((dwEventStatus = WaitForSingleObject (
  395. g_hEventTerminateEAPOL,
  396. 0)) == WAIT_FAILED)
  397. {
  398. dwRetCode = GetLastError ();
  399. TRACE1(INIT, "ElDeviceNotificationHandler: WaitForSingleObject failed with error %ld, Terminating !!!",
  400. dwRetCode);
  401. // log
  402. break;
  403. }
  404. if (dwEventStatus == WAIT_OBJECT_0)
  405. {
  406. TRACE0(INIT, "ElDeviceNotificationHandler: g_hEventTerminateEAPOL already signaled, returning");
  407. break;
  408. }
  409. if (lpEventData == NULL)
  410. {
  411. dwRetCode = ERROR_INVALID_DATA;
  412. TRACE0 (DEVICE, "ElDeviceNotificationHandler: lpEventData == NULL");
  413. break;
  414. }
  415. if (pInfo->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
  416. {
  417. TRACE0 (DEVICE, "ElDeviceNotificationHandler: Event for Interface type");
  418. if ((pvBuffer = MALLOC (pInfo->dbcc_size + 8)) == NULL)
  419. {
  420. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  421. TRACE0 (DEVICE, "ElDeviceNotificationHandler: MALLOC failed for pvBuffer");
  422. break;
  423. }
  424. *((DWORD *)pvBuffer) = dwEventType;
  425. memcpy ((PBYTE)pvBuffer + 8, (PBYTE)pInfo, pInfo->dbcc_size);
  426. if (!QueueUserWorkItem (
  427. (LPTHREAD_START_ROUTINE)ElDeviceNotificationHandlerWorker,
  428. pvBuffer,
  429. WT_EXECUTELONGFUNCTION))
  430. {
  431. dwRetCode = GetLastError();
  432. TRACE1 (DEVICE, "ElDeviceNotificationHandler: QueueUserWorkItem failed with error %ld",
  433. dwRetCode);
  434. break;
  435. }
  436. }
  437. else
  438. {
  439. TRACE0 (DEVICE, "ElDeviceNotificationHandler: Event NOT for Interface type");
  440. }
  441. }
  442. while (FALSE);
  443. TRACE1 (DEVICE, "ElDeviceNotificationHandler completed with error %ld",
  444. dwRetCode);
  445. if (dwRetCode != NO_ERROR)
  446. {
  447. if (pvBuffer != NULL)
  448. {
  449. FREE (pvBuffer);
  450. }
  451. }
  452. return dwRetCode;
  453. }
  454. //
  455. // ElDeviceNotificationHandlerWorker
  456. //
  457. // Description:
  458. //
  459. // Worker function for ElDeviceNotificationHandlerWorker
  460. //
  461. // Arguments:
  462. // pvContext - interface information
  463. //
  464. VOID
  465. ElDeviceNotificationHandlerWorker (
  466. IN PVOID pvContext
  467. )
  468. {
  469. EAPOL_PCB *pPCB = NULL;
  470. EAPOL_ITF *pITF = NULL;
  471. HANDLE hDevice = NULL;
  472. DEV_BROADCAST_DEVICEINTERFACE *pInfo = NULL;
  473. DWORD dwEventType = 0;
  474. DWORD dwRetCode = NO_ERROR;
  475. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Entered");
  476. do
  477. {
  478. if (pvContext == NULL)
  479. {
  480. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: pvContext == NULL");
  481. break;
  482. }
  483. dwEventType = *((DWORD *) pvContext);
  484. pInfo = (DEV_BROADCAST_DEVICEINTERFACE*)((PBYTE)pvContext + 8);
  485. if ((dwEventType == DBT_DEVICEARRIVAL) ||
  486. (dwEventType == DBT_DEVICEREMOVECOMPLETE))
  487. {
  488. // Extract GUID from the \Device\GUID string
  489. WCHAR *pwszGUIDStart = NULL;
  490. WCHAR *pwszGUIDEnd = NULL;
  491. CHAR *pszGUIDStart = NULL;
  492. WCHAR chGUIDSaveLast;
  493. WCHAR Buffer1[256];
  494. CHAR Buffer2[256];
  495. UNICODE_STRING UnicodeGUID;
  496. ANSI_STRING AnsiGUID;
  497. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Interface arr/rem");
  498. pwszGUIDStart = wcsrchr( pInfo->dbcc_name, L'{' );
  499. pwszGUIDEnd = wcsrchr( pInfo->dbcc_name, L'}' );
  500. if ((pwszGUIDStart != NULL) && (pwszGUIDEnd != NULL))
  501. {
  502. chGUIDSaveLast = *(pwszGUIDEnd+1);
  503. // Ignore the leading '{' and the trailing '}'
  504. // in the GUID
  505. *(pwszGUIDEnd) = L'\0';
  506. pwszGUIDStart ++;
  507. UnicodeGUID.Buffer = Buffer1;
  508. UnicodeGUID.MaximumLength = 256*sizeof(WCHAR);
  509. RtlInitUnicodeString (&UnicodeGUID, pwszGUIDStart);
  510. // Will not fail since memory is already allocated for the
  511. // conversion
  512. AnsiGUID.Buffer = Buffer2;
  513. AnsiGUID.MaximumLength = 256;
  514. RtlUnicodeStringToAnsiString (&AnsiGUID,
  515. &UnicodeGUID, FALSE);
  516. AnsiGUID.Buffer[AnsiGUID.Length] = '\0';
  517. pszGUIDStart = AnsiGUID.Buffer;
  518. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: For interface %s",
  519. pszGUIDStart);
  520. // Interface was added
  521. if (dwEventType == DBT_DEVICEARRIVAL)
  522. {
  523. ACQUIRE_WRITE_LOCK (&g_ITFLock);
  524. TRACE0(DEVICE, "ElDeviceNotificationHandlerWorker: Callback for device addition");
  525. if ((dwRetCode = ElEnumAndOpenInterfaces (NULL,
  526. pszGUIDStart))
  527. != NO_ERROR)
  528. {
  529. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: ElEnumAndOpenInterfaces returned error %ld",
  530. dwRetCode);
  531. }
  532. RELEASE_WRITE_LOCK (&g_ITFLock);
  533. }
  534. else
  535. {
  536. TRACE0(DEVICE, "ElDeviceNotificationHandlerWorker: Callback for device removal");
  537. ACQUIRE_WRITE_LOCK (&(g_ITFLock));
  538. // Check if EAPOL was actually started on this interface
  539. // Verify by checking existence of corresponding
  540. // entry in hash table
  541. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  542. if ((pPCB = ElGetPCBPointerFromPortGUID(pszGUIDStart))
  543. != NULL)
  544. {
  545. RELEASE_WRITE_LOCK (&(g_PCBLock));
  546. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Found PCB entry for interface");
  547. if ((pITF = ElGetITFPointerFromInterfaceDesc(
  548. pPCB->pszFriendlyName))
  549. == NULL)
  550. {
  551. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Did not find ITF entry when PCB exits, HOW BIZARRE !!!");
  552. }
  553. if ((dwRetCode = ElDeletePort (
  554. pszGUIDStart,
  555. &hDevice)) != NO_ERROR)
  556. {
  557. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: Error in deleting port for %s",
  558. pPCB->pszDeviceGUID);
  559. }
  560. //
  561. // Remove interface entry from interface table
  562. //
  563. if (pITF != NULL)
  564. {
  565. ElRemoveITFFromTable(pITF);
  566. if (pITF->pszInterfaceDesc)
  567. {
  568. FREE (pITF->pszInterfaceDesc);
  569. }
  570. if (pITF->pszInterfaceGUID)
  571. {
  572. FREE (pITF->pszInterfaceGUID);
  573. }
  574. if (pITF)
  575. {
  576. FREE (pITF);
  577. }
  578. }
  579. // Close the handle to the NDISUIO driver
  580. if (hDevice != NULL)
  581. {
  582. if ((dwRetCode = ElCloseInterfaceHandle (hDevice))
  583. != NO_ERROR)
  584. {
  585. TRACE1 (DEVICE,
  586. "ElDeviceNotificationHandlerWorker: Error in ElCloseInterfaceHandle %d",
  587. dwRetCode);
  588. }
  589. }
  590. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker: Port deleted %s",
  591. pszGUIDStart);
  592. }
  593. else
  594. {
  595. RELEASE_WRITE_LOCK (&(g_PCBLock));
  596. // Ignore device removal
  597. //
  598. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: ElGetPCBPointerFromPortGUID did not find any matching entry, ignoring DEVICE REMOVAL");
  599. }
  600. RELEASE_WRITE_LOCK (&g_ITFLock);
  601. }
  602. }
  603. }
  604. else
  605. {
  606. TRACE0 (DEVICE, "ElDeviceNotificationHandlerWorker: Event type is is NOT device arr/rem");
  607. }
  608. }
  609. while (FALSE);
  610. if (pvContext != NULL)
  611. {
  612. FREE (pvContext);
  613. }
  614. TRACE1 (DEVICE, "ElDeviceNotificationHandlerWorker completed with error %ld",
  615. dwRetCode);
  616. return;
  617. }
  618. //
  619. // ElMediaSenseCallback
  620. //
  621. // Description:
  622. //
  623. // Callback function called by WMI on MEDIA_CONNECT/MEDIA_DISCONNECT
  624. // events
  625. //
  626. // Arguments:
  627. // pWnodeHeader - Pointer to information returned by the event
  628. // uiNotificationContext - unused
  629. //
  630. // Return values:
  631. // NO_ERROR - Success
  632. // non-zero - Error
  633. //
  634. VOID
  635. CALLBACK
  636. ElMediaSenseCallback (
  637. IN PWNODE_HEADER pWnodeHeader,
  638. IN UINT_PTR uiNotificationContext
  639. )
  640. {
  641. DWORD dwEventStatus = 0;
  642. PVOID pvBuffer = NULL;
  643. DWORD dwRetCode = NO_ERROR;
  644. TRACE0 (DEVICE, "ElMediaSenseCallback: Entered");
  645. do
  646. {
  647. if (g_hEventTerminateEAPOL == NULL)
  648. {
  649. dwRetCode = NO_ERROR;
  650. break;
  651. }
  652. // Check if have already gone through EAPOLCleanUp before
  653. if (( dwEventStatus = WaitForSingleObject (
  654. g_hEventTerminateEAPOL,
  655. 0)) == WAIT_FAILED)
  656. {
  657. dwRetCode = GetLastError ();
  658. TRACE1 (INIT, "ElMediaSenseCallback: WaitForSingleObject failed with error %ld, Terminating !!!",
  659. dwRetCode);
  660. // log
  661. break;
  662. }
  663. if (dwEventStatus == WAIT_OBJECT_0)
  664. {
  665. dwRetCode = NO_ERROR;
  666. TRACE0 (INIT, "ElMediaSenseCallback: g_hEventTerminateEAPOL already signaled, returning");
  667. break;
  668. }
  669. if (pWnodeHeader == NULL)
  670. {
  671. dwRetCode = ERROR_INVALID_DATA;
  672. TRACE0 (DEVICE, "ElMediaSenseCallback: pWnodeHeader == NULL");
  673. break;
  674. }
  675. if ((pvBuffer = MALLOC (pWnodeHeader->BufferSize)) == NULL)
  676. {
  677. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  678. TRACE0 (DEVICE, "ElMediaSenseCallback: MALLOC failed for pvBuffer");
  679. break;
  680. }
  681. memcpy ((PVOID)pvBuffer, (PVOID)pWnodeHeader, pWnodeHeader->BufferSize);
  682. if (!QueueUserWorkItem (
  683. (LPTHREAD_START_ROUTINE)ElMediaSenseCallbackWorker,
  684. pvBuffer,
  685. WT_EXECUTELONGFUNCTION))
  686. {
  687. dwRetCode = GetLastError();
  688. TRACE1 (DEVICE, "ElMediaSenseCallback: QueueUserWorkItem failed with error %ld",
  689. dwRetCode);
  690. ASSERT (0);
  691. }
  692. }
  693. while (FALSE);
  694. if (dwRetCode != NO_ERROR)
  695. {
  696. TRACE1 (DEVICE, "ElMediaSenseCallback: Failed with error %ld",
  697. dwRetCode);
  698. if (pvBuffer != NULL)
  699. {
  700. FREE (pvBuffer);
  701. }
  702. }
  703. }
  704. //
  705. // ElMediaSenseCallbackWorker
  706. //
  707. // Description:
  708. //
  709. // Worker function for ElMediaSenseCallback and executes in a separate
  710. // thread
  711. //
  712. // Arguments:
  713. // pvContext - Pointer to information returned by the media-sense event
  714. //
  715. // Return values:
  716. // NO_ERROR - Success
  717. // non-zero - Error
  718. //
  719. VOID
  720. ElMediaSenseCallbackWorker (
  721. IN PVOID pvContext
  722. )
  723. {
  724. PWNODE_HEADER pWnodeHeader = (PWNODE_HEADER)pvContext;
  725. PWNODE_SINGLE_INSTANCE pWnode = (PWNODE_SINGLE_INSTANCE)pWnodeHeader;
  726. LPWSTR lpwsName;
  727. CHAR *psName;
  728. CHAR *psDeviceName = NULL;
  729. CHAR psLength;
  730. USHORT cpsLength;
  731. CHAR *psNameEnd;
  732. LPWSTR lpwsDeviceName = NULL;
  733. HANDLE hDevice = NULL;
  734. UNICODE_STRING uInterfaceDescription;
  735. ANSI_STRING InterfaceDescription;
  736. PCHAR pszInterfaceDescription;
  737. UCHAR Buffer[256];
  738. CHAR *pszInterfaceDesc = NULL;
  739. DWORD dwIndex;
  740. EAPOL_ITF *pITF;
  741. ULONG i = 0;
  742. EAPOL_PCB *pPCB = NULL;
  743. DWORD dwRetCode = NO_ERROR;
  744. do
  745. {
  746. #ifdef EAPOL_SERVICE
  747. if ((g_ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  748. ||
  749. (g_ServiceStatus.dwCurrentState == SERVICE_STOPPED))
  750. {
  751. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: Callback received while service was stopping");
  752. break;
  753. }
  754. #endif // EAPOL_SERVICE
  755. if (pWnodeHeader == NULL)
  756. {
  757. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: Callback received with NULL NDIS interface details");
  758. break;
  759. }
  760. psName = (PCHAR)RtlOffsetToPointer(
  761. pWnode,
  762. pWnode->OffsetInstanceName );
  763. // Get the length of the string
  764. // Null terminate it
  765. cpsLength = (SHORT)( *((SHORT *)psName) );
  766. if (!(psDeviceName = (CHAR *) MALLOC ((cpsLength+1)*sizeof(CHAR))))
  767. {
  768. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: Error in Memory allocation for psDeviceName");
  769. break;
  770. }
  771. memcpy ((CHAR *)psDeviceName, (CHAR *)psName+sizeof(SHORT), cpsLength);
  772. psDeviceName[cpsLength] = '\0';
  773. RtlInitAnsiString (&InterfaceDescription, psDeviceName);
  774. InterfaceDescription.Buffer[cpsLength] = '\0';
  775. TRACE3(DEVICE, "ElMediaSenseCallbackWorker: For interface ANSI %s, true= %s, lengt of block = %d",
  776. InterfaceDescription.Buffer, psDeviceName, cpsLength);
  777. pszInterfaceDescription = InterfaceDescription.Buffer;
  778. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: Interface desc = %s",
  779. pszInterfaceDescription);
  780. //
  781. // Get the information for the media disconnect.
  782. //
  783. if (memcmp( &(pWnodeHeader->Guid),
  784. &GUID_NDIS_STATUS_MEDIA_DISCONNECT,
  785. sizeof(GUID)) == 0)
  786. {
  787. // MEDIA DISCONNECT callback
  788. TRACE0(DEVICE, "ElMediaSenseCallbackWorker: Callback for sense disconnect");
  789. ACQUIRE_WRITE_LOCK (&(g_ITFLock))
  790. // Check if EAPOL was actually started on this interface
  791. // Verify by checking existence of corresponding entry in hash table
  792. if ((pITF = ElGetITFPointerFromInterfaceDesc(pszInterfaceDescription))
  793. != NULL)
  794. {
  795. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: Found ITF entry for interface");
  796. #if 0
  797. if ((dwRetCode = ElDeletePort (pITF->pszInterfaceGUID, &hDevice)) != NO_ERROR)
  798. {
  799. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: Error in deleting port for %s",
  800. pITF->pszInterfaceGUID);
  801. }
  802. // Remove interface entry from interface table
  803. ElRemoveITFFromTable(pITF);
  804. if (pITF->pszInterfaceDesc)
  805. {
  806. FREE (pITF->pszInterfaceDesc);
  807. pITF->pszInterfaceDesc = NULL;
  808. }
  809. if (pITF->pszInterfaceGUID)
  810. {
  811. FREE (pITF->pszInterfaceGUID);
  812. pITF->pszInterfaceGUID = NULL;
  813. }
  814. if (pITF)
  815. {
  816. FREE (pITF);
  817. pITF = NULL;
  818. }
  819. // Close the handle to the NDISUIO driver
  820. if ((dwRetCode = ElCloseInterfaceHandle (hDevice)) != NO_ERROR)
  821. {
  822. TRACE1 (DEVICE,
  823. "ElMediaSenseCallbackWorker: Error in ElCloseInterfaceHandle %d",
  824. dwRetCode);
  825. }
  826. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: Port deleted %s",
  827. pszInterfaceDescription);
  828. #endif
  829. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  830. pPCB = ElGetPCBPointerFromPortGUID (pITF->pszInterfaceGUID);
  831. if (pPCB != NULL)
  832. {
  833. ACQUIRE_WRITE_LOCK (&(pPCB->rwLock));
  834. if ((dwRetCode = FSMDisconnected (pPCB)) != NO_ERROR)
  835. {
  836. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: FSMDisconnected failed with error %ld",
  837. dwRetCode);
  838. }
  839. RELEASE_WRITE_LOCK (&(pPCB->rwLock));
  840. }
  841. RELEASE_WRITE_LOCK (&(g_PCBLock));
  842. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: Port marked disconnected %s",
  843. pszInterfaceDescription);
  844. }
  845. else
  846. {
  847. // Ignore MEDIA DISCONNECT
  848. TRACE0 (DEVICE, "ElMediaSenseCallbackWorker: ElHashInterfaceDescToBucket did not find any matching entry, ignoring MEDIA_DISCONNECT");
  849. }
  850. RELEASE_WRITE_LOCK (&g_ITFLock);
  851. }
  852. else
  853. {
  854. if (memcmp( &(pWnodeHeader->Guid),
  855. &GUID_NDIS_STATUS_MEDIA_CONNECT,
  856. sizeof(GUID)) == 0)
  857. {
  858. // MEDIA CONNECT callback
  859. ACQUIRE_WRITE_LOCK (&g_ITFLock)
  860. TRACE0(DEVICE, "ElMediaSenseCallbackWorker: Callback for sense connect");
  861. if ((dwRetCode = ElEnumAndOpenInterfaces (
  862. pszInterfaceDescription, NULL))
  863. != NO_ERROR)
  864. {
  865. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: ElEnumAndOpenInterfaces returned error %ld",
  866. dwRetCode);
  867. }
  868. RELEASE_WRITE_LOCK (&g_ITFLock);
  869. }
  870. }
  871. }
  872. while (FALSE);
  873. TRACE1 (DEVICE, "ElMediaSenseCallbackWorker: processed, RetCode = %ld", dwRetCode);
  874. if (pWnodeHeader != NULL)
  875. {
  876. FREE (pWnodeHeader);
  877. }
  878. if (psDeviceName != NULL)
  879. {
  880. FREE (psDeviceName);
  881. }
  882. return;
  883. }
  884. //
  885. // ElEnumAndOpenInterfaces
  886. //
  887. // Description:
  888. //
  889. // Enumerates interfaces and intializes EAPOL on desired ones.
  890. //
  891. // If EAPOL is to be started on an interface, it opens a handle to
  892. // the NDISUIO driver, calls EAPOL to create and initialize PCB for the
  893. // interface, and finally adds an entry to the interface hashtable.
  894. //
  895. // If pszDesiredGUID is not NULL, all interfaces are enumerated, but
  896. // EAPOL will be initialized only on the interface whose GUID matches.
  897. //
  898. // If pszDescription is not NULL, all interfaces are enumerated, but
  899. // EAPOL will be initialized only on the interface whose description matches.
  900. //
  901. // If pszDesiredGUID and pszDescription are both NULL, all interfaces are
  902. // enumerated. EAPOL will be initialized only on all interfaces that
  903. // does have an entry in the interface hashtable.
  904. //
  905. //
  906. // Arguments:
  907. // pszDesiredDescription - Interface Description on which EAPOL is to
  908. // be started
  909. // pszDesiredGUID - Interface GUID on which EAPOL is to be started
  910. //
  911. // Return values:
  912. // NO_ERROR - Success
  913. // non-zero - Error
  914. //
  915. DWORD
  916. ElEnumAndOpenInterfaces (
  917. CHAR *pszDesiredDescription,
  918. CHAR *pszDesiredGUID
  919. )
  920. {
  921. CHAR EnumerateBuffer[256];
  922. PNDIS_ENUM_INTF Interfaces = NULL;
  923. BYTE *pbNdisuioEnumBuffer = NULL;
  924. DWORD dwNdisuioEnumBufferSize = 0;
  925. DWORD dwNicCardStatus = 0;
  926. DWORD dwMediaType = 0;
  927. HANDLE hDevice = NULL;
  928. EAPOL_ITF *pNewITF = NULL;
  929. DWORD dwIndex = 0;
  930. UCHAR csCurrMacAddress[6];
  931. UCHAR csPermMacAddress[6];
  932. UCHAR csOidVendData[16];
  933. BOOL fSearchByDescription = FALSE;
  934. BOOL fSearchByGUID = FALSE;
  935. DWORD dwEapTypeToBeUsed = DEFAULT_EAP_TYPE;
  936. DWORD dwEapolEnabled = DEFAULT_EAPOL_STATE;
  937. CHAR csDummyBuffer[256];
  938. UNICODE_STRING TempUString;
  939. CHAR *pszGUIDStart = NULL;
  940. EAPOL_PCB *pPCB = NULL;
  941. BOOL fPCBExists = FALSE;
  942. DWORD dwAvailableInterfaces = 0;
  943. DWORD dwRetCode = NO_ERROR;
  944. TRACE2 (DEVICE, "ElEnumAndOpenInterfaces: DeviceDesc = %s, GUID = %s",
  945. pszDesiredDescription, pszDesiredGUID);
  946. if (pszDesiredGUID == NULL)
  947. {
  948. if (pszDesiredDescription != NULL)
  949. {
  950. fSearchByDescription = TRUE;
  951. }
  952. }
  953. else
  954. {
  955. if (pszDesiredDescription != NULL)
  956. {
  957. return ERROR;
  958. }
  959. fSearchByGUID = TRUE;
  960. }
  961. ZeroMemory (EnumerateBuffer, 256);
  962. Interfaces = (PNDIS_ENUM_INTF)EnumerateBuffer;
  963. //
  964. // Allocate amount of memory as instructed by NdisEnumerateInterfaces
  965. // once the API allows querying of bytes required
  966. //
  967. Interfaces->TotalInterfaces = 0;
  968. Interfaces->AvailableInterfaces = 0;
  969. Interfaces->BytesNeeded = 0;
  970. if (!NdisEnumerateInterfaces(Interfaces, 256))
  971. {
  972. dwRetCode = GetLastError ();
  973. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: NdisEnumerateInterfaces failed with error %ld",
  974. dwRetCode);
  975. return dwRetCode;
  976. }
  977. TRACE3 (DEVICE, "ElEnumAndOpenInterfaces: TotalInterfaces = %ld, AvailInt = %ld, Bytes needed = %ld",
  978. Interfaces->TotalInterfaces,
  979. Interfaces->AvailableInterfaces,
  980. Interfaces->BytesNeeded);
  981. dwAvailableInterfaces = Interfaces->AvailableInterfaces;
  982. dwNdisuioEnumBufferSize = (Interfaces->BytesNeeded + 7) & ~7;
  983. if (dwNdisuioEnumBufferSize == 0) {
  984. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: MALLOC skipped for zero length pbNdisuioEnumBuffer");
  985. dwRetCode = NO_ERROR;
  986. return dwRetCode;
  987. }
  988. pbNdisuioEnumBuffer = (BYTE *) MALLOC (4*dwNdisuioEnumBufferSize);
  989. if (pbNdisuioEnumBuffer == NULL)
  990. {
  991. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: MALLOC failed for pbNdisuioEnumBuffer");
  992. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  993. return dwRetCode;
  994. }
  995. Interfaces = (PNDIS_ENUM_INTF)pbNdisuioEnumBuffer;
  996. // Enumerate all the interfaces present on the machine
  997. if ((dwRetCode = ElNdisuioEnumerateInterfaces (
  998. Interfaces,
  999. dwAvailableInterfaces,
  1000. 4*dwNdisuioEnumBufferSize)) == NO_ERROR)
  1001. {
  1002. ANSI_STRING InterfaceName;
  1003. ANSI_STRING InterfaceDescription;
  1004. UNICODE_STRING UInterfaceName;
  1005. UCHAR Buffer1[256];
  1006. UCHAR Buffer2[256];
  1007. WCHAR Buffer3[256];
  1008. DWORD i;
  1009. InterfaceName.MaximumLength = 256;
  1010. InterfaceName.Buffer = Buffer1;
  1011. InterfaceDescription.MaximumLength = 256;
  1012. InterfaceDescription.Buffer = Buffer2;
  1013. TRACE1 (DEVICE, "TotalInterfaces=%ld", Interfaces->TotalInterfaces);
  1014. // Update the interface list in the registry that NDISUIO has bound to.
  1015. // The current interface list is just overwritten into the registry.
  1016. if ((dwRetCode = ElUpdateRegistryInterfaceList (Interfaces))
  1017. != NO_ERROR)
  1018. {
  1019. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: ElUpdateInterfaceList failed with error =%ld",
  1020. dwRetCode);
  1021. // log
  1022. }
  1023. for (i=0; i < Interfaces->TotalInterfaces; i++)
  1024. {
  1025. if (Interfaces->Interface[i].DeviceName.Buffer != NULL)
  1026. {
  1027. InterfaceName.Length = 0;
  1028. InterfaceName.MaximumLength = 256;
  1029. if (RtlUnicodeStringToAnsiString(&InterfaceName,
  1030. &Interfaces->Interface[i].DeviceName, FALSE) != STATUS_SUCCESS)
  1031. {
  1032. TRACE0 (INIT, "Error in RtlUnicodeStringToAnsiString for DeviceName");
  1033. }
  1034. InterfaceName.Buffer[InterfaceName.Length] = '\0';
  1035. }
  1036. else
  1037. {
  1038. TRACE0(INIT, "NdisEnumerateInterfaces: Device Name was NULL");
  1039. continue;
  1040. }
  1041. TRACE1(INIT, "Device: %s", InterfaceName.Buffer);
  1042. // BUBUG:
  1043. // Should Device Name be retained in Unicode or converted to ANSI
  1044. InterfaceDescription.Length = 0;
  1045. InterfaceDescription.MaximumLength = 256;
  1046. if (RtlUnicodeStringToAnsiString(&InterfaceDescription,
  1047. &Interfaces->Interface[i].DeviceDescription, FALSE) != STATUS_SUCCESS)
  1048. {
  1049. TRACE0 (INIT, "Error in RtlUnicodeStringToAnsiString for DeviceDescription");
  1050. }
  1051. InterfaceDescription.Buffer[InterfaceDescription.Length] = '\0';
  1052. TRACE1(INIT, "Description: %s", InterfaceDescription.Buffer);
  1053. // Create PCB for interface and start EAPOL state machine
  1054. // EAPOL requested be started only a particular
  1055. // interface
  1056. if (fSearchByDescription)
  1057. {
  1058. if (strcmp (InterfaceDescription.Buffer,
  1059. pszDesiredDescription)
  1060. != 0)
  1061. {
  1062. // No match, continue with next interface
  1063. continue;
  1064. }
  1065. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Found interface after enumeration %s", InterfaceDescription.Buffer);
  1066. }
  1067. if (fSearchByGUID)
  1068. {
  1069. if (strstr (InterfaceName.Buffer,
  1070. pszDesiredGUID)
  1071. == NULL)
  1072. {
  1073. // No match, continue with next interface
  1074. continue;
  1075. }
  1076. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Found interface after enumeration %s", InterfaceName.Buffer);
  1077. }
  1078. {
  1079. // Extract GUID-string out of device name
  1080. CHAR *pszGUIDEnd;
  1081. CHAR *pszGUID;
  1082. CHAR chGUIDSaveLast;
  1083. pszGUID = InterfaceName.Buffer;
  1084. pszGUIDStart = strchr( pszGUID, '{' );
  1085. pszGUIDEnd = strchr( pszGUID, '}' );
  1086. if (RtlAnsiStringToUnicodeString (
  1087. &TempUString,
  1088. &InterfaceName,
  1089. TRUE))
  1090. {
  1091. TRACE0 (DEVICE, "Error in RtlAnsiStringToUnicodeString for TempUString");
  1092. }
  1093. // Query MAC address for the interface
  1094. if (!NdisQueryHwAddress (
  1095. &TempUString,
  1096. csCurrMacAddress,
  1097. csPermMacAddress,
  1098. csOidVendData))
  1099. {
  1100. RtlFreeUnicodeString (&TempUString);
  1101. dwRetCode = GetLastError();
  1102. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Error in NdisQueryHwAddress = %d", dwRetCode);
  1103. dwRetCode = NO_ERROR;
  1104. continue;
  1105. }
  1106. RtlFreeUnicodeString (&TempUString);
  1107. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: NdisQueryHwAddress successful");
  1108. if (pszGUIDStart != NULL)
  1109. {
  1110. chGUIDSaveLast = *(pszGUIDEnd);
  1111. // Ignore the leading '{' and the trailing '}'
  1112. // in the GUID
  1113. *(pszGUIDEnd) = (CHAR)NULL;
  1114. pszGUIDStart ++;
  1115. }
  1116. // Verify if a PCB already exists for the interface
  1117. // This is possible if no media disconnect was received
  1118. // after the initial media connect
  1119. ACQUIRE_WRITE_LOCK (&g_PCBLock);
  1120. pPCB = ElGetPCBPointerFromPortGUID (pszGUIDStart);
  1121. RELEASE_WRITE_LOCK (&g_PCBLock);
  1122. // Restore interface buffer
  1123. *(pszGUIDEnd) = chGUIDSaveLast;
  1124. if (pPCB != NULL)
  1125. {
  1126. // Point to existing handle
  1127. hDevice = pPCB->hPort;
  1128. fPCBExists = TRUE;
  1129. dwRetCode = NO_ERROR;
  1130. TRACE0 (INIT, "ElEnumAndOpenInterfaces: Found PCB already existing for interface");
  1131. }
  1132. else
  1133. {
  1134. TRACE0 (INIT, "ElEnumAndOpenInterfaces: Did NOT find PCB already existing for interface");
  1135. // Open handle to ndisuio driver
  1136. if ((dwRetCode = ElOpenInterfaceHandle (
  1137. InterfaceName.Buffer,
  1138. &hDevice
  1139. )) != NO_ERROR)
  1140. {
  1141. TRACE1 (INIT, "ElEnumAndOpenInterfaces: ElOpenInterfaceHandle failed with error = %d\n",
  1142. dwRetCode );
  1143. }
  1144. }
  1145. *(pszGUIDEnd) = (CHAR)NULL;
  1146. }
  1147. if (dwRetCode != NO_ERROR)
  1148. {
  1149. TRACE0 (INIT, "ElEnumAndOpenInterfaces: Failed to open handle");
  1150. dwRetCode = NO_ERROR;
  1151. continue;
  1152. }
  1153. else
  1154. {
  1155. // Verify if EAPOL is to be started on the interface
  1156. // at all
  1157. if ((dwRetCode = ElGetInterfaceParams (
  1158. pszGUIDStart,
  1159. &dwEapTypeToBeUsed,
  1160. csDummyBuffer,
  1161. &dwEapolEnabled
  1162. )) != NO_ERROR)
  1163. {
  1164. TRACE2 (INIT, "ElEnumAndOpenInterfaces: ElGetInterfaceParams failed with error %ld for interface %s",
  1165. dwRetCode, pszDesiredGUID);
  1166. dwEapTypeToBeUsed = DEFAULT_EAP_TYPE;
  1167. dwEapolEnabled = DEFAULT_EAPOL_STATE;
  1168. if (dwEapolEnabled)
  1169. {
  1170. dwRetCode = NO_ERROR;
  1171. }
  1172. else
  1173. {
  1174. // Close the handle to the ndisuio driver
  1175. if ((dwRetCode = ElCloseInterfaceHandle (hDevice))
  1176. != NO_ERROR)
  1177. {
  1178. TRACE1 (DEVICE,
  1179. "ElEnumAndOpenInterfaces: Error in ElCloseInterfaceHandle %d",
  1180. dwRetCode);
  1181. }
  1182. dwRetCode = NO_ERROR;
  1183. TRACE1 (INIT, "EAPOL will not be started on %s", InterfaceName.Buffer);
  1184. // Continue with other interfaces
  1185. continue;
  1186. }
  1187. }
  1188. if (dwEapolEnabled != EAPOL_ENABLED)
  1189. {
  1190. TRACE1 (INIT, "EAPOL not to be started on interface %s",
  1191. pszDesiredGUID);
  1192. // Close the handle to the ndisuio driver
  1193. if ((dwRetCode = ElCloseInterfaceHandle (hDevice))
  1194. != NO_ERROR)
  1195. {
  1196. TRACE1 (DEVICE,
  1197. "ElEnumAndOpenInterfaces: Error in ElCloseInterfaceHandle %d",
  1198. dwRetCode);
  1199. }
  1200. // Continue with the next interface
  1201. dwRetCode = NO_ERROR;
  1202. continue;
  1203. }
  1204. // ISSUE:
  1205. // What MAC address should we pass to CreatePort
  1206. // perm or cur
  1207. // Create EAPOL PCB and start state machine
  1208. if ((dwRetCode = ElCreatePort (
  1209. hDevice,
  1210. pszGUIDStart,
  1211. InterfaceDescription.Buffer,
  1212. csCurrMacAddress
  1213. )) != NO_ERROR)
  1214. {
  1215. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Error in CreatePort = %d", dwRetCode);
  1216. // Close the handle to the ndisuio driver
  1217. if ((dwRetCode = ElCloseInterfaceHandle (hDevice)) != NO_ERROR)
  1218. {
  1219. TRACE1 (DEVICE,
  1220. "ElEnumAndOpenInterfaces: Error in ElCloseInterfaceHandle %d",
  1221. dwRetCode);
  1222. }
  1223. // Continue with the next interface
  1224. dwRetCode = NO_ERROR;
  1225. continue;
  1226. }
  1227. else
  1228. {
  1229. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: CreatePort successful");
  1230. // If PCB already existed, do not add to the hash
  1231. // table
  1232. if (fPCBExists == TRUE)
  1233. {
  1234. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: PCB already existed, skipping Interface hash table addition");
  1235. fPCBExists = FALSE;
  1236. dwRetCode = NO_ERROR;
  1237. continue;
  1238. }
  1239. // Add entry to Interface hash table
  1240. dwIndex = ElHashInterfaceDescToBucket (
  1241. InterfaceDescription.Buffer);
  1242. pNewITF = (PEAPOL_ITF)
  1243. MALLOC (sizeof (EAPOL_ITF));
  1244. if (pNewITF != NULL)
  1245. {
  1246. pNewITF->pszInterfaceGUID =
  1247. (CHAR *) MALLOC (strlen(pszGUIDStart) + 1);
  1248. if (pNewITF->pszInterfaceGUID != NULL)
  1249. {
  1250. memcpy (pNewITF->pszInterfaceGUID,
  1251. pszGUIDStart,
  1252. strlen (pszGUIDStart));
  1253. pNewITF->pszInterfaceGUID[strlen (pszGUIDStart)] = '\0';
  1254. }
  1255. pNewITF->pszInterfaceDesc =
  1256. (CHAR *) MALLOC (strlen(InterfaceDescription.Buffer) + 1);
  1257. if (pNewITF->pszInterfaceDesc != NULL)
  1258. {
  1259. memcpy (pNewITF->pszInterfaceDesc,
  1260. InterfaceDescription.Buffer,
  1261. strlen (InterfaceDescription.Buffer));
  1262. pNewITF->pszInterfaceDesc[strlen (InterfaceDescription.Buffer)] = '\0';
  1263. }
  1264. pNewITF->pNext =
  1265. g_ITFTable.pITFBuckets[dwIndex].pItf;
  1266. g_ITFTable.pITFBuckets[dwIndex].pItf = pNewITF;
  1267. if ( (pNewITF->pszInterfaceGUID == NULL) ||
  1268. (pNewITF->pszInterfaceDesc == NULL))
  1269. {
  1270. ElRemoveITFFromTable (pNewITF);
  1271. if (pNewITF->pszInterfaceDesc)
  1272. {
  1273. FREE (pNewITF->pszInterfaceDesc);
  1274. }
  1275. if (pNewITF->pszInterfaceGUID)
  1276. {
  1277. FREE (pNewITF->pszInterfaceGUID);
  1278. }
  1279. if (pNewITF)
  1280. {
  1281. FREE (pNewITF);
  1282. }
  1283. pNewITF = NULL;
  1284. TRACE0 (DEVICE, "ElEnumAndOpenInterfaces: Error in memory allocation, ITF structure not created");
  1285. }
  1286. }
  1287. // Could not create new interface entry
  1288. // Delete Port entry created for this GUID
  1289. if (pNewITF == NULL)
  1290. {
  1291. if ((dwRetCode = ElDeletePort (
  1292. pszGUIDStart,
  1293. &hDevice)) != NO_ERROR)
  1294. {
  1295. TRACE1 (DEVICE, "ElEnumAndOpenInterfaces: Error in deleting port for %s",
  1296. pszGUIDStart);
  1297. // log
  1298. }
  1299. // Close the handle to the NDISUIO driver
  1300. if ((dwRetCode = ElCloseInterfaceHandle (
  1301. hDevice)) != NO_ERROR)
  1302. {
  1303. TRACE1 (DEVICE,
  1304. "ElMediaSenseCallback: Error in ElCloseInterfaceHandle %d",
  1305. dwRetCode);
  1306. // log
  1307. }
  1308. }
  1309. else
  1310. {
  1311. TRACE3 (DEVICE, "ElEnumAndOpenInterfaces: Added to hash table GUID= %s : Desc= %s at Index=%d",
  1312. pNewITF->pszInterfaceGUID,
  1313. pNewITF->pszInterfaceDesc,
  1314. dwIndex
  1315. );
  1316. //
  1317. // Interface Handle created successfully
  1318. // Notify Zero Config about it
  1319. //
  1320. }
  1321. }
  1322. }
  1323. } // for (i=0; i < Interfaces
  1324. }
  1325. else
  1326. {
  1327. TRACE1(INIT, "ElEnumAndOpenInterfaces: ElNdisuioEnumerateInterfaces failed with error %d",
  1328. dwRetCode);
  1329. }
  1330. TRACE1(INIT, "ElEnumAndOpenInterfaces: Completed with retcode = %d",
  1331. dwRetCode);
  1332. if (pbNdisuioEnumBuffer != NULL)
  1333. {
  1334. FREE(pbNdisuioEnumBuffer);
  1335. }
  1336. return dwRetCode;
  1337. }
  1338. //
  1339. // ElGetCardStatus
  1340. //
  1341. // Function to query the media information for an interface
  1342. //
  1343. // Input arguments:
  1344. // pDeviceName - Unicode device name
  1345. //
  1346. // Return values:
  1347. // pdwNetCardStatus - Media state
  1348. // pdwMediaType - Media type as exposed to NDIS e.g. 802.3
  1349. //
  1350. DWORD
  1351. ElGetCardStatus (
  1352. PUNICODE_STRING pDeviceName,
  1353. DWORD *pdwNetCardStatus,
  1354. DWORD *pdwMediaType
  1355. )
  1356. {
  1357. NIC_STATISTICS Stats;
  1358. DWORD dwNicStatus = 0;
  1359. DWORD dwRetCode = NO_ERROR;
  1360. Stats.Size = sizeof(NIC_STATISTICS);
  1361. if (NdisQueryStatistics(pDeviceName, &Stats))
  1362. {
  1363. switch (Stats.MediaState)
  1364. {
  1365. case MEDIA_STATE_CONNECTED:
  1366. dwNicStatus = MEDIA_STATE_CONNECTED;
  1367. TRACE0(INIT, "ElGetCardStatus: dwNicStatus = NETCARD_CONNECTED\n");
  1368. break;
  1369. case MEDIA_STATE_DISCONNECTED:
  1370. dwNicStatus = MEDIA_STATE_DISCONNECTED;
  1371. TRACE0(INIT, "ElGetCardStatus: dwNicStatus = NETCARD_DISCONNECTED\n");
  1372. break;
  1373. default:
  1374. dwNicStatus = MEDIA_STATE_UNKNOWN;
  1375. TRACE0(INIT, "ElGetCardStatus: dwNicStatus = NETCARD_STATUS_UNKNOWN\n");
  1376. break;
  1377. }
  1378. switch (Stats.MediaType)
  1379. {
  1380. case NdisMedium802_3:
  1381. TRACE0 (INIT, "ElGetCardStatus: MediaType is 802.3");
  1382. break;
  1383. default:
  1384. TRACE0 (INIT, "ElGetCardStatus: MediaType is NOT *802.3*");
  1385. break;
  1386. }
  1387. *pdwMediaType = Stats.MediaType;
  1388. }
  1389. else
  1390. {
  1391. dwRetCode = GetLastError ();
  1392. TRACE1(INIT, "ElGetCardStatus: NdisQueryStatistics failed with error %d\n", dwRetCode);
  1393. }
  1394. *pdwNetCardStatus = dwNicStatus;
  1395. return dwRetCode;
  1396. }
  1397. //
  1398. // ElOpenInterfaceHandle
  1399. //
  1400. // Description:
  1401. //
  1402. // Function called to open handle to the NDISUIO driver for an interface.
  1403. //
  1404. // Arguments:
  1405. // DeviceName - Identifier for the interface is of the
  1406. // form \Device\{GUID String}
  1407. // phDevice - Output pointer to handle of NDISUIO driver for
  1408. // the interface
  1409. //
  1410. // Return values:
  1411. // NO_ERROR - success
  1412. // non-zero - error
  1413. //
  1414. DWORD
  1415. ElOpenInterfaceHandle (
  1416. IN CHAR *pszDeviceName,
  1417. OUT HANDLE *phDevice
  1418. )
  1419. {
  1420. DWORD dwDesiredAccess;
  1421. DWORD dwShareMode;
  1422. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  1423. DWORD dwCreationDistribution;
  1424. DWORD dwFlagsAndAttributes;
  1425. HANDLE hTemplateFile;
  1426. HANDLE hHandle;
  1427. DWORD dwRetCode = NO_ERROR;
  1428. WCHAR wNdisDeviceName[MAX_NDIS_DEVICE_NAME_LEN];
  1429. INT wNameLength;
  1430. INT NameLength = strlen(pszDeviceName);
  1431. DWORD dwBytesReturned;
  1432. USHORT wEthernetType=0x8081;
  1433. INT i;
  1434. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  1435. dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  1436. dwCreationDistribution = OPEN_EXISTING;
  1437. dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
  1438. hTemplateFile = (HANDLE)INVALID_HANDLE_VALUE;
  1439. TRACE1 (INIT, "ElOpenInterfaceHandle: Opening handle for %s", pszDeviceName);
  1440. do
  1441. {
  1442. hHandle = CreateFileA(
  1443. pNdisuioDevice,
  1444. dwDesiredAccess,
  1445. dwShareMode,
  1446. lpSecurityAttributes,
  1447. dwCreationDistribution,
  1448. dwFlagsAndAttributes,
  1449. hTemplateFile
  1450. );
  1451. if (hHandle == INVALID_HANDLE_VALUE)
  1452. {
  1453. *phDevice = NULL;
  1454. dwRetCode = GetLastError();
  1455. TRACE1 (INIT, "ElOpenInterfaceHandle: Failed in CreateFile with error %d", dwRetCode);
  1456. break;
  1457. }
  1458. else
  1459. {
  1460. *phDevice = hHandle;
  1461. }
  1462. // Convert to unicode string - non-localized...
  1463. wNameLength = 0;
  1464. for (i = 0; i < NameLength && i < MAX_NDIS_DEVICE_NAME_LEN-1; i++)
  1465. {
  1466. wNdisDeviceName[i] = (WCHAR)pszDeviceName[i];
  1467. wNameLength++;
  1468. }
  1469. wNdisDeviceName[i] = L'\0';
  1470. TRACE1(DEVICE, "ElOpenInterfaceHandle: Trying to access NDIS Device: %ws\n",
  1471. wNdisDeviceName);
  1472. if (!(DeviceIoControl(
  1473. *phDevice,
  1474. IOCTL_NDISUIO_OPEN_DEVICE,
  1475. (LPVOID)&wNdisDeviceName[0],
  1476. wNameLength*sizeof(WCHAR),
  1477. NULL,
  1478. 0,
  1479. &dwBytesReturned,
  1480. NULL)))
  1481. {
  1482. *phDevice = NULL;
  1483. if ((dwRetCode = GetLastError()) == 0)
  1484. {
  1485. dwRetCode = ERROR_IO_DEVICE;
  1486. }
  1487. TRACE1(DEVICE, "ElOpenInterfaceHandle: Error in accessing NDIS Device: %ws", wNdisDeviceName);
  1488. break;
  1489. }
  1490. // IOCTL down the Ethernet type
  1491. if (!(DeviceIoControl(
  1492. *phDevice,
  1493. IOCTL_NDISUIO_SET_ETHER_TYPE,
  1494. (LPVOID)&wEthernetType,
  1495. sizeof(USHORT),
  1496. NULL,
  1497. 0,
  1498. &dwBytesReturned,
  1499. NULL)))
  1500. {
  1501. *phDevice = NULL;
  1502. if ((dwRetCode = GetLastError()) == 0)
  1503. {
  1504. dwRetCode = ERROR_IO_DEVICE;
  1505. }
  1506. TRACE1(DEVICE, "ElOpenInterfaceHandle: Error in ioctling ETHER type : %ws", wNdisDeviceName);
  1507. break;
  1508. }
  1509. // Bind for asynchronous I/O handling of Read/Write data
  1510. // Depending on whether it is completion for Readfile() or WriteFile()
  1511. // ElIoCompletionRoutine will call ElReadCompletionRoutine
  1512. // or ElWriteCompletionRoutine
  1513. if (!BindIoCompletionCallback(
  1514. *phDevice,
  1515. ElIoCompletionRoutine,
  1516. 0
  1517. ))
  1518. {
  1519. *phDevice = NULL;
  1520. dwRetCode = GetLastError();
  1521. TRACE1 (DEVICE, "ElOpenInterfaceHandle: Error in BindIoCompletionCallBac %d", dwRetCode);
  1522. break;
  1523. }
  1524. } while (FALSE);
  1525. // Cleanup if there is error
  1526. if (dwRetCode != NO_ERROR)
  1527. {
  1528. if (hHandle != INVALID_HANDLE_VALUE)
  1529. {
  1530. if (!CloseHandle(hHandle))
  1531. {
  1532. dwRetCode = GetLastError();
  1533. TRACE1 (INIT, "ElOpenInterfaceHandle: Error in CloseHandle %d", dwRetCode);
  1534. }
  1535. }
  1536. }
  1537. TRACE2 (INIT, "ElOpenInterfaceHandle: Opened handle %p with dwRetCode %d", *phDevice, dwRetCode);
  1538. return (dwRetCode);
  1539. }
  1540. //
  1541. // ElCloseInterfaceHandle
  1542. //
  1543. // Description:
  1544. //
  1545. // Function called to close handle to NDISUIO driver for an interface
  1546. //
  1547. // Arguments:
  1548. // hDevice - Handle to NDISUIO device for the interface
  1549. //
  1550. // Return values:
  1551. // NO_ERROR - success
  1552. // non-zero - error
  1553. //
  1554. DWORD
  1555. ElCloseInterfaceHandle (
  1556. IN HANDLE hDevice
  1557. )
  1558. {
  1559. DWORD dwRetCode = NO_ERROR;
  1560. TRACE0 (DEVICE, "ElCloseInterfaceHandle entered");
  1561. if (!CloseHandle(hDevice))
  1562. {
  1563. dwRetCode = GetLastError();
  1564. TRACE1 (INIT, "ElCloseInterfaceHandle: Error in CloseHandle %d",
  1565. dwRetCode);
  1566. }
  1567. return dwRetCode;
  1568. }
  1569. //
  1570. // ElReadFromInterface
  1571. //
  1572. // Description:
  1573. //
  1574. // Function called to perform Overlapped read on handle to NDISUIO driver
  1575. //
  1576. // Arguments:
  1577. // hDevice - Handle to NDISUIO driver for this interface
  1578. // pElBuffer - Context buffer
  1579. // dwBufferLength - Bytes to be read
  1580. //
  1581. // Return values:
  1582. // NO_ERROR - success
  1583. // non-zero - error
  1584. //
  1585. DWORD
  1586. ElReadFromInterface (
  1587. IN HANDLE hDevice,
  1588. IN PEAPOL_BUFFER pElBuffer,
  1589. IN DWORD dwBufferLength
  1590. )
  1591. {
  1592. DWORD dwRetCode = NO_ERROR;
  1593. if (!ReadFile (
  1594. hDevice,
  1595. pElBuffer->pBuffer,
  1596. dwBufferLength,
  1597. NULL,
  1598. &pElBuffer->Overlapped
  1599. ))
  1600. {
  1601. dwRetCode = GetLastError();
  1602. if (dwRetCode == ERROR_IO_PENDING)
  1603. {
  1604. // Pending status is fine, we are doing OVERLAPPED read
  1605. dwRetCode = NO_ERROR;
  1606. }
  1607. else
  1608. {
  1609. TRACE1 (DEVICE, "ElReadFromInterface: ReadFile failed with error %d",
  1610. dwRetCode);
  1611. }
  1612. }
  1613. return dwRetCode;
  1614. }
  1615. //
  1616. // ElWriteToInterface
  1617. //
  1618. // Description:
  1619. //
  1620. // Function called to perform Overlapped write on handle to NDISUIO driver
  1621. //
  1622. // Arguments:
  1623. // hDevice - Handle to NDISUIO device for this interface
  1624. // pElBuffer - Context buffer
  1625. // dwBufferLength - Bytes to be written
  1626. //
  1627. // Return values:
  1628. // NO_ERROR - success
  1629. // non-zero - error
  1630. //
  1631. DWORD
  1632. ElWriteToInterface (
  1633. IN HANDLE hDevice,
  1634. IN PEAPOL_BUFFER pElBuffer,
  1635. IN DWORD dwBufferLength
  1636. )
  1637. {
  1638. DWORD dwRetCode = NO_ERROR;
  1639. TRACE0 (DEVICE, "ElWriteToInterface entered");
  1640. if (!WriteFile (
  1641. hDevice,
  1642. pElBuffer->pBuffer,
  1643. dwBufferLength,
  1644. NULL,
  1645. &pElBuffer->Overlapped
  1646. ))
  1647. {
  1648. dwRetCode = GetLastError();
  1649. if (dwRetCode == ERROR_IO_PENDING)
  1650. {
  1651. // Pending status is fine, we are doing OVERLAPPED write
  1652. dwRetCode = NO_ERROR;
  1653. }
  1654. else
  1655. {
  1656. TRACE1 (DEVICE, "ElWriteToInterface: WriteFile failed with error %d",
  1657. dwRetCode);
  1658. }
  1659. }
  1660. TRACE1 (DEVICE, "ElWriteToInterface completed, dwRetCode = %d", dwRetCode);
  1661. return dwRetCode;
  1662. }
  1663. //
  1664. // ElHashInterfaceDescToBucket
  1665. //
  1666. // Description:
  1667. //
  1668. // Function called to convert Friendly name of interface into interface hash
  1669. // table index.
  1670. //
  1671. // Arguments:
  1672. // pszInterfaceDesc - Friendly name of the interface
  1673. //
  1674. // Return values:
  1675. // Hash table index between from 0 to INTF_TABLE_BUCKETS-1
  1676. //
  1677. DWORD
  1678. ElHashInterfaceDescToBucket (
  1679. IN CHAR *pszInterfaceDesc
  1680. )
  1681. {
  1682. return ((DWORD)((atol(pszInterfaceDesc)) % INTF_TABLE_BUCKETS));
  1683. }
  1684. //
  1685. // ElGetITFPointerFromInterfaceDesc
  1686. //
  1687. // Description:
  1688. //
  1689. // Function called to convert Friendly name of interface to ITF entry pointer
  1690. //
  1691. // Arguments:
  1692. // pszInterfaceDesc - Friendly name of the interface
  1693. //
  1694. // Return values:
  1695. // Pointer to interface entry in hash table
  1696. //
  1697. PEAPOL_ITF
  1698. ElGetITFPointerFromInterfaceDesc (
  1699. IN CHAR *pszInterfaceDesc
  1700. )
  1701. {
  1702. EAPOL_ITF *pITFWalker = NULL;
  1703. DWORD dwIndex;
  1704. INT i=0;
  1705. TRACE1 (DEVICE, "ElGetITFPointerFromInterfaceDesc: Desc = %s", pszInterfaceDesc);
  1706. if (pszInterfaceDesc == NULL)
  1707. {
  1708. return (NULL);
  1709. }
  1710. dwIndex = ElHashInterfaceDescToBucket (pszInterfaceDesc);
  1711. TRACE1 (DEVICE, "ElGetITFPointerFromItfDesc: Index %d", dwIndex);
  1712. for (pITFWalker = g_ITFTable.pITFBuckets[dwIndex].pItf;
  1713. pITFWalker != NULL;
  1714. pITFWalker = pITFWalker->pNext
  1715. )
  1716. {
  1717. if (strncmp (pITFWalker->pszInterfaceDesc, pszInterfaceDesc, strlen(pszInterfaceDesc)) == 0)
  1718. {
  1719. return pITFWalker;
  1720. }
  1721. }
  1722. return (NULL);
  1723. }
  1724. //
  1725. // ElRemoveITFFromTable
  1726. //
  1727. // Description:
  1728. //
  1729. // Function called to remove an interface entry from the interface hash
  1730. // table
  1731. //
  1732. // Arguments:
  1733. // pITF - Point to the Interface entry in the hash table
  1734. //
  1735. // Return values:
  1736. //
  1737. VOID
  1738. ElRemoveITFFromTable (
  1739. IN EAPOL_ITF *pITF
  1740. )
  1741. {
  1742. DWORD dwIndex;
  1743. EAPOL_ITF *pITFWalker = NULL;
  1744. EAPOL_ITF *pITFTemp = NULL;
  1745. if (pITF == NULL)
  1746. {
  1747. TRACE0 (EAPOL, "ElRemoveITFFromTable: Deleting NULL ITF, returning");
  1748. return;
  1749. }
  1750. dwIndex = ElHashInterfaceDescToBucket (pITF->pszInterfaceDesc);
  1751. pITFWalker = g_ITFTable.pITFBuckets[dwIndex].pItf;
  1752. pITFTemp = pITFWalker;
  1753. while (pITFTemp != NULL)
  1754. {
  1755. if (strncmp (pITFTemp->pszInterfaceGUID,
  1756. pITF->pszInterfaceGUID, strlen(pITF->pszInterfaceGUID)) == 0)
  1757. {
  1758. // Entry is at head of list in table
  1759. if (pITFTemp == g_ITFTable.pITFBuckets[dwIndex].pItf)
  1760. {
  1761. g_ITFTable.pITFBuckets[dwIndex].pItf = pITFTemp->pNext;
  1762. }
  1763. else
  1764. {
  1765. // Entry is inside list in table
  1766. pITFWalker->pNext = pITFTemp->pNext;
  1767. }
  1768. break;
  1769. }
  1770. pITFWalker = pITFTemp;
  1771. pITFTemp = pITFWalker->pNext;
  1772. }
  1773. return;
  1774. }
  1775. //
  1776. // ElNdisuioEnumerateInterfaces
  1777. //
  1778. // Description:
  1779. //
  1780. // Function called to enumerate the interfaces on which NDISUIO is bound
  1781. //
  1782. // Arguments:
  1783. // pBuffer - Pointer to buffer which will hold interface details
  1784. // dwAvailableInterfaces - Number of interfaces for which details can
  1785. // be held in pItfBuffer
  1786. // dwBufferSize - Number of bytes in pItfBuffer
  1787. //
  1788. // Return values:
  1789. //
  1790. DWORD
  1791. ElNdisuioEnumerateInterfaces (
  1792. IN OUT PNDIS_ENUM_INTF pItfBuffer,
  1793. IN DWORD dwAvailableInterfaces,
  1794. IN DWORD dwBufferSize
  1795. )
  1796. {
  1797. DWORD dwDesiredAccess;
  1798. DWORD dwShareMode;
  1799. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  1800. DWORD dwCreationDistribution;
  1801. DWORD dwFlagsAndAttributes;
  1802. HANDLE hTemplateFile;
  1803. HANDLE hHandle;
  1804. DWORD dwBytesReturned = 0;
  1805. INT i;
  1806. CHAR Buf[1024];
  1807. DWORD BufLength = sizeof(Buf);
  1808. DWORD BytesWritten = 0;
  1809. PNDISUIO_QUERY_BINDING pQueryBinding = NULL;
  1810. PCHAR pTempBuf = NULL;
  1811. DWORD dwRetCode = NO_ERROR;
  1812. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  1813. dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
  1814. dwCreationDistribution = OPEN_EXISTING;
  1815. dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;
  1816. hTemplateFile = (HANDLE)INVALID_HANDLE_VALUE;
  1817. TRACE0 (DEVICE, "ElNdisuioEnumerateInterfaces: Opening handle");
  1818. do
  1819. {
  1820. hHandle = CreateFileA (
  1821. pNdisuioDevice,
  1822. dwDesiredAccess,
  1823. dwShareMode,
  1824. lpSecurityAttributes,
  1825. dwCreationDistribution,
  1826. 0,
  1827. NULL
  1828. );
  1829. if (hHandle == INVALID_HANDLE_VALUE)
  1830. {
  1831. dwRetCode = GetLastError();
  1832. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: Failed in CreateFile with error %d", dwRetCode);
  1833. break;
  1834. }
  1835. // Send IOCTL to ensure NDISUIO binds to all relevant interfaces
  1836. if (!DeviceIoControl (
  1837. hHandle,
  1838. IOCTL_NDISUIO_BIND_WAIT,
  1839. NULL,
  1840. 0,
  1841. NULL,
  1842. 0,
  1843. &dwBytesReturned,
  1844. NULL))
  1845. {
  1846. dwRetCode = GetLastError();
  1847. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: Failed in DeviceIoCoontrol NDISUIO_BIND_WAIT with error %d", dwRetCode);
  1848. break;
  1849. }
  1850. pQueryBinding = (PNDISUIO_QUERY_BINDING)Buf;
  1851. pTempBuf = (PBYTE)pItfBuffer + dwBufferSize;
  1852. i = 0;
  1853. for (pQueryBinding->BindingIndex = i;
  1854. pQueryBinding->BindingIndex < dwAvailableInterfaces;
  1855. pQueryBinding->BindingIndex = ++i)
  1856. {
  1857. Try_Again:
  1858. g_QueryBinding = NULL;
  1859. g_TempBuf = NULL;
  1860. g_ItfBuffer = NULL;
  1861. g_Buf = NULL;
  1862. g_ItfBufferSize = 0;
  1863. g_BreakAt = 1;
  1864. // Query for one interface at a time
  1865. if (DeviceIoControl (
  1866. hHandle,
  1867. IOCTL_NDISUIO_QUERY_BINDING,
  1868. pQueryBinding,
  1869. sizeof(NDISUIO_QUERY_BINDING),
  1870. Buf,
  1871. BufLength,
  1872. &BytesWritten,
  1873. NULL))
  1874. {
  1875. TRACE3 (DEVICE, "NdisuioEnumerateInterfaces: NDISUIO bound to: %2d. %ws\n - %ws\n",
  1876. pQueryBinding->BindingIndex,
  1877. (PUCHAR)pQueryBinding + pQueryBinding->DeviceNameOffset,
  1878. (PUCHAR)pQueryBinding + pQueryBinding->DeviceDescrOffset);
  1879. g_QueryBinding = (PVOID)pQueryBinding;
  1880. g_TempBuf = (PVOID)pTempBuf;
  1881. g_ItfBuffer = (PVOID)pItfBuffer;
  1882. g_ItfBufferSize = dwBufferSize;
  1883. g_Buf = (PVOID)Buf;
  1884. g_BreakAt = 1;
  1885. pTempBuf = pTempBuf - ((pQueryBinding->DeviceNameLength + 7) & 0xfffffff8);
  1886. if (((PBYTE)pTempBuf - (PBYTE)&pItfBuffer->Interface[pItfBuffer->TotalInterfaces]) <= 0)
  1887. {
  1888. // Going beyond start of buffer, Error
  1889. TRACE0 (DEVICE, "NdisuioEnumerateInterfaces: DeviceName: Memory being corrupted !!!");
  1890. DebugBreak ();
  1891. goto Try_Again;
  1892. }
  1893. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.Buffer = (PWCHAR) pTempBuf;
  1894. memcpy ((BYTE *)(pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.Buffer), (BYTE *)((PUCHAR)pQueryBinding + pQueryBinding->DeviceNameOffset), (pQueryBinding->DeviceNameLength - sizeof(WCHAR)));
  1895. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.Length = (SHORT) ( pQueryBinding->DeviceNameLength - sizeof(WCHAR));
  1896. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceName.MaximumLength = (SHORT) ( pQueryBinding->DeviceNameLength - sizeof(WCHAR));
  1897. pTempBuf = pTempBuf - ((pQueryBinding->DeviceDescrLength + 7) & 0xfffffff8);;
  1898. g_BreakAt = 2;
  1899. if (((PBYTE)pTempBuf - (PBYTE)&pItfBuffer->Interface[pItfBuffer->TotalInterfaces]) <= 0)
  1900. {
  1901. // Going beyond start of buffer, Error
  1902. TRACE0 (DEVICE, "NdisuioEnumerateInterfaces: DeviceDescr: Memory being corrupted !!!");
  1903. DebugBreak ();
  1904. goto Try_Again;
  1905. }
  1906. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.Buffer = (PWCHAR) pTempBuf;
  1907. memcpy ((pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.Buffer), (PWCHAR)((PUCHAR)pQueryBinding + pQueryBinding->DeviceDescrOffset), (pQueryBinding->DeviceDescrLength - sizeof(WCHAR)));
  1908. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.Length = (SHORT) (pQueryBinding->DeviceDescrLength - sizeof(WCHAR));
  1909. pItfBuffer->Interface[pItfBuffer->TotalInterfaces].DeviceDescription.MaximumLength = (SHORT) (pQueryBinding->DeviceDescrLength - sizeof(WCHAR));
  1910. pItfBuffer->TotalInterfaces++;
  1911. memset(Buf, 0, BufLength);
  1912. }
  1913. else
  1914. {
  1915. dwRetCode = GetLastError ();
  1916. if (dwRetCode != ERROR_NO_MORE_ITEMS)
  1917. {
  1918. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: DeviceIoControl terminated for with IOCTL_NDISUIO_QUERY_BINDING with error %ld",
  1919. dwRetCode);
  1920. }
  1921. else
  1922. {
  1923. // Reset error, since it only indicates end-of-list
  1924. dwRetCode = NO_ERROR;
  1925. TRACE0 (DEVICE, "ElNdisuioEnumerateInterfaces: DeviceIoControl IOCTL_NDISUIO_QUERY_BINDING has no more entries");
  1926. }
  1927. break;
  1928. }
  1929. }
  1930. } while (FALSE);
  1931. // Cleanup
  1932. if (hHandle != INVALID_HANDLE_VALUE)
  1933. {
  1934. if (!CloseHandle(hHandle))
  1935. {
  1936. dwRetCode = GetLastError();
  1937. TRACE1 (DEVICE, "ElNdisuioEnumerateInterfaces: Error in CloseHandle %d", dwRetCode);
  1938. }
  1939. }
  1940. TRACE2 (DEVICE, "ElNdisuioEnumerateInterfaces: Opened handle %p with dwRetCode %d",
  1941. hHandle, dwRetCode);
  1942. return dwRetCode;
  1943. }
  1944. //
  1945. // ElShutdownInterface
  1946. //
  1947. // Description:
  1948. //
  1949. // Function called to stop EAPOL state machine, close handle to NDISUIO and
  1950. // remove existence of the interface from the module
  1951. //
  1952. // Arguments:
  1953. // pszGUID - Pointer to interface GUID
  1954. //
  1955. // Return values:
  1956. // NO_ERROR - success
  1957. // non-zero - error
  1958. //
  1959. DWORD
  1960. ElShutdownInterface (
  1961. IN CHAR *pszGUID
  1962. )
  1963. {
  1964. EAPOL_PCB *pPCB = NULL;
  1965. EAPOL_ITF *pITF = NULL;
  1966. HANDLE hDevice = NULL;
  1967. DWORD dwRetCode = NO_ERROR;
  1968. do
  1969. {
  1970. TRACE0(DEVICE, "ElShutdownInterface: Called for interface removal");
  1971. ACQUIRE_WRITE_LOCK (&(g_ITFLock));
  1972. // Check if EAPOL was actually started on this interface
  1973. // Verify by checking existence of corresponding
  1974. // entry in hash table
  1975. ACQUIRE_WRITE_LOCK (&(g_PCBLock));
  1976. if ((pPCB = ElGetPCBPointerFromPortGUID(pszGUID))
  1977. != NULL)
  1978. {
  1979. RELEASE_WRITE_LOCK (&(g_PCBLock));
  1980. TRACE0 (DEVICE, "ElShutdownInterface: Found PCB entry for interface");
  1981. if ((pITF = ElGetITFPointerFromInterfaceDesc(
  1982. pPCB->pszFriendlyName))
  1983. == NULL)
  1984. {
  1985. TRACE0 (DEVICE, "ElShutdownInterface: Did not find ITF entry when PCB exits, HOW BIZARRE !!!");
  1986. }
  1987. if ((dwRetCode = ElDeletePort (
  1988. pszGUID,
  1989. &hDevice)) != NO_ERROR)
  1990. {
  1991. TRACE1 (DEVICE, "ElShutdownInterface: Error in deleting port for %s",
  1992. pPCB->pszDeviceGUID);
  1993. }
  1994. // Remove interface entry from interface table
  1995. if (pITF != NULL)
  1996. {
  1997. ElRemoveITFFromTable(pITF);
  1998. if (pITF->pszInterfaceDesc)
  1999. {
  2000. FREE (pITF->pszInterfaceDesc);
  2001. }
  2002. if (pITF->pszInterfaceGUID)
  2003. {
  2004. FREE (pITF->pszInterfaceGUID);
  2005. }
  2006. if (pITF)
  2007. {
  2008. FREE (pITF);
  2009. }
  2010. }
  2011. // Close the handle to the NDISUIO driver
  2012. if (hDevice != NULL)
  2013. {
  2014. if ((dwRetCode = ElCloseInterfaceHandle (hDevice))
  2015. != NO_ERROR)
  2016. {
  2017. TRACE1 (DEVICE,
  2018. "ElShutdownInterface: Error in ElCloseInterfaceHandle %d",
  2019. dwRetCode);
  2020. }
  2021. }
  2022. TRACE1 (DEVICE, "ElShutdownInterface: Port deleted %s",
  2023. pszGUID);
  2024. }
  2025. else
  2026. {
  2027. RELEASE_WRITE_LOCK (&(g_PCBLock));
  2028. // Ignore device removal
  2029. TRACE0 (DEVICE, "ElShutdownInterface: ElGetPCBPointerFromPortGUID did not find any matching entry, ignoring interface REMOVAL");
  2030. }
  2031. RELEASE_WRITE_LOCK (&g_ITFLock);
  2032. } while (FALSE);
  2033. return dwRetCode;
  2034. }