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

1113 lines
36 KiB

  1. #include <precomp.h>
  2. #include "tracing.h"
  3. #include "utils.h"
  4. #include "intflist.h"
  5. #include "deviceio.h"
  6. #include "intfhdl.h"
  7. //------------------------------------------------------
  8. // Open a handle to Ndisuio and returns it to the caller
  9. DWORD
  10. DevioGetNdisuioHandle (
  11. PHANDLE pHandle) // OUT opened handle to Ndisuio
  12. {
  13. DWORD dwErr = ERROR_SUCCESS;
  14. HANDLE hHandle;
  15. DWORD dwOutSize;
  16. DbgAssert((pHandle != NULL, "NULL pointer to output handle?"));
  17. hHandle = CreateFileA(
  18. "\\\\.\\\\Ndisuio",
  19. GENERIC_READ | GENERIC_WRITE,
  20. FILE_SHARE_READ | FILE_SHARE_WRITE,
  21. NULL,
  22. OPEN_EXISTING,
  23. 0,
  24. NULL);
  25. if (hHandle == INVALID_HANDLE_VALUE)
  26. {
  27. dwErr = GetLastError();
  28. DbgPrint((TRC_ERR,"Err: Open Ndisuio->%d", dwErr));
  29. goto exit;
  30. }
  31. // make sure NDISUIO binds to all relevant interfaces
  32. if (!DeviceIoControl(
  33. hHandle,
  34. IOCTL_NDISUIO_BIND_WAIT,
  35. NULL,
  36. 0,
  37. NULL,
  38. 0,
  39. &dwOutSize,
  40. NULL))
  41. {
  42. dwErr = GetLastError();
  43. DbgPrint((TRC_ERR,"Err: IOCTL_NDISUIO_BIND_WAIT->%d", dwErr));
  44. goto exit;
  45. }
  46. *pHandle = hHandle;
  47. exit:
  48. return dwErr;
  49. }
  50. //------------------------------------------------------
  51. // Checks the NDISUIO_QUERY_BINDING object for consistency
  52. // against the length for this binding as returned by NDISUIO.
  53. DWORD
  54. DevioCheckNdisBinding(
  55. PNDISUIO_QUERY_BINDING pndBinding,
  56. ULONG nBindingLen)
  57. {
  58. DWORD dwErr = ERROR_SUCCESS;
  59. // check for the data to contain at least the NDISUIO_QUERY_BINDING
  60. // header (that is offsets & lengths fields should be there)
  61. if (nBindingLen < sizeof(NDISUIO_QUERY_BINDING))
  62. dwErr = ERROR_INVALID_DATA;
  63. // check the offsets are correctly set over the NDISUIO_QUERY_BINDING header
  64. // and within the length indicated by nBindingLen
  65. if (dwErr == ERROR_SUCCESS &&
  66. ((pndBinding->DeviceNameOffset < sizeof(NDISUIO_QUERY_BINDING)) ||
  67. (pndBinding->DeviceNameOffset > nBindingLen) ||
  68. (pndBinding->DeviceDescrOffset < sizeof(NDISUIO_QUERY_BINDING)) ||
  69. (pndBinding->DeviceDescrOffset > nBindingLen)
  70. )
  71. )
  72. dwErr = ERROR_INVALID_DATA;
  73. // check whether the lengths are correctly set within the limits
  74. if (dwErr == ERROR_SUCCESS &&
  75. ((pndBinding->DeviceNameLength > nBindingLen - pndBinding->DeviceNameOffset) ||
  76. (pndBinding->DeviceDescrLength > nBindingLen - pndBinding->DeviceDescrOffset)
  77. )
  78. )
  79. dwErr = ERROR_INVALID_DATA;
  80. return dwErr;
  81. }
  82. //------------------------------------------------------
  83. // Get the NDISUIO_QUERY_BINDING for the interface index nIntfIndex.
  84. // If hNdisuio is valid, this handle is used, otherwise a local handle
  85. // is opened, used and closed before returning.
  86. DWORD
  87. DevioGetIntfBindingByIndex(
  88. HANDLE hNdisuio, // IN opened handle to NDISUIO. If INVALID_HANDLE_VALUE, open one locally
  89. UINT nIntfIndex, // IN interface index to look for
  90. PRAW_DATA prdOutput) // OUT result of the IOCTL
  91. {
  92. DWORD dwErr = ERROR_SUCCESS;
  93. BOOL bLocalHandle = FALSE;
  94. DbgPrint((TRC_TRACK,"[DevioGetIntfBindingByIndex(%d..)", nIntfIndex));
  95. // assert what are the expected valid parameters
  96. DbgAssert((prdOutput != NULL &&
  97. prdOutput->dwDataLen > sizeof(NDISUIO_QUERY_BINDING),
  98. "Invalid input parameters"));
  99. // see if Ndisuio should be opened locally
  100. if (hNdisuio == INVALID_HANDLE_VALUE)
  101. {
  102. dwErr = DevioGetNdisuioHandle(&hNdisuio);
  103. bLocalHandle = (dwErr == ERROR_SUCCESS);
  104. }
  105. // if everything went well, go query the driver for the Binding structure
  106. if (dwErr == ERROR_SUCCESS)
  107. {
  108. PNDISUIO_QUERY_BINDING pndBinding;
  109. DWORD dwOutSize;
  110. ZeroMemory(prdOutput->pData, prdOutput->dwDataLen);
  111. pndBinding = (PNDISUIO_QUERY_BINDING)prdOutput->pData;
  112. pndBinding->BindingIndex = nIntfIndex;
  113. if (!DeviceIoControl(
  114. hNdisuio,
  115. IOCTL_NDISUIO_QUERY_BINDING,
  116. prdOutput->pData,
  117. prdOutput->dwDataLen,
  118. prdOutput->pData,
  119. prdOutput->dwDataLen,
  120. &dwOutSize,
  121. NULL))
  122. {
  123. // if the index is over the number of interfaces
  124. // we'll have here ERROR_NO_MORE_ITEMS which will be carried out
  125. // to the caller
  126. dwErr = GetLastError();
  127. DbgPrint((TRC_ERR,"Err: IOCTL_NDISUIO_QUERY_BINDING->%d", dwErr));
  128. }
  129. else
  130. {
  131. dwErr = DevioCheckNdisBinding(pndBinding, dwOutSize);
  132. }
  133. }
  134. // close the handle if it was opened locally
  135. if (bLocalHandle)
  136. CloseHandle(hNdisuio);
  137. DbgPrint((TRC_TRACK,"DevioGetIntfBindingByIndex]=%d", dwErr));
  138. return dwErr;
  139. }
  140. //------------------------------------------------------
  141. // Get the NDISUIO_QUERY_BINDING for the interface having
  142. // the GUID wszGuid. If hNdisuio is INVALID_HANDLE_VALUE
  143. // a local handle is opened, used and closed at the end
  144. DWORD
  145. DevioGetInterfaceBindingByGuid(
  146. HANDLE hNdisuio, // IN opened handle to NDISUIO
  147. LPWSTR wszGuid, // IN interface GUID as "{guid}"
  148. PRAW_DATA prdOutput) // OUT result of the IOCTL
  149. {
  150. DWORD dwErr = ERROR_SUCCESS;
  151. BOOL bLocalHandle = FALSE;
  152. INT i;
  153. // assert what are the expected valid parameters
  154. DbgAssert((wszGuid != NULL &&
  155. prdOutput != NULL &&
  156. prdOutput->dwDataLen > sizeof(NDISUIO_QUERY_BINDING),
  157. "Invalid input parameter"));
  158. DbgPrint((TRC_TRACK,"[DevioGetInterfaceBindingByGuid(%S..)", wszGuid));
  159. // see if Ndisuio should be opened locally
  160. if (hNdisuio == INVALID_HANDLE_VALUE)
  161. {
  162. dwErr = DevioGetNdisuioHandle(&hNdisuio);
  163. bLocalHandle = (dwErr == ERROR_SUCCESS);
  164. }
  165. // iterate through all the interfaces, one by one!! No other better way to do this
  166. for (i = 0; dwErr == ERROR_SUCCESS; i++)
  167. {
  168. PNDISUIO_QUERY_BINDING pndBinding;
  169. DWORD dwOutSize;
  170. LPWSTR wsName;
  171. ZeroMemory(prdOutput->pData, prdOutput->dwDataLen);
  172. pndBinding = (PNDISUIO_QUERY_BINDING)prdOutput->pData;
  173. pndBinding->BindingIndex = i;
  174. if (!DeviceIoControl(
  175. hNdisuio,
  176. IOCTL_NDISUIO_QUERY_BINDING,
  177. prdOutput->pData,
  178. prdOutput->dwDataLen,
  179. prdOutput->pData,
  180. prdOutput->dwDataLen,
  181. &dwOutSize,
  182. NULL))
  183. {
  184. // if the IOCTL failed, get the error code
  185. dwErr = GetLastError();
  186. // translate the NO_MORE_ITEMS error in FILE_NOT_FOUND
  187. // since the caller is not iterating, is searching for a specific adapter
  188. if (dwErr == ERROR_NO_MORE_ITEMS)
  189. dwErr = ERROR_FILE_NOT_FOUND;
  190. }
  191. else
  192. {
  193. dwErr = DevioCheckNdisBinding(pndBinding, dwOutSize);
  194. }
  195. if (dwErr == ERROR_SUCCESS)
  196. {
  197. // Device name is "\DEVICE\{guid}" and is L'\0' terminated
  198. // wszGuid is "{guid}"
  199. wsName = (LPWSTR)((LPBYTE)pndBinding + pndBinding->DeviceNameOffset);
  200. // if the GUID matches, this is the adapter we were looking for
  201. if (wcsstr(wsName, wszGuid) != NULL)
  202. {
  203. // the adapter's BINDING record is already filled in
  204. // prdOutput - so just get out of here.
  205. dwErr = ERROR_SUCCESS;
  206. break;
  207. }
  208. }
  209. }
  210. // if handle was opened locally, close it here
  211. if (bLocalHandle)
  212. CloseHandle(hNdisuio);
  213. DbgPrint((TRC_TRACK,"DevioGetInterfaceBindingByGuid]=%d", dwErr));
  214. return dwErr;
  215. }
  216. DWORD
  217. DevioGetIntfStats(PINTF_CONTEXT pIntf)
  218. {
  219. DWORD dwErr = ERROR_SUCCESS;
  220. WCHAR ndisDeviceString[128];
  221. NIC_STATISTICS ndisStats;
  222. UNICODE_STRING uniIntfGuid;
  223. DbgPrint((TRC_TRACK,"[DevioGetIntfStats(0x%p)", pIntf));
  224. wcscpy(ndisDeviceString, L"\\DEVICE\\");
  225. wcscat(ndisDeviceString, pIntf->wszGuid);
  226. RtlInitUnicodeString(&uniIntfGuid, ndisDeviceString);
  227. ZeroMemory(&ndisStats, sizeof(NIC_STATISTICS));
  228. ndisStats.Size = sizeof(NIC_STATISTICS);
  229. if (!NdisQueryStatistics(&uniIntfGuid, &ndisStats))
  230. {
  231. dwErr = GetLastError();
  232. }
  233. else
  234. {
  235. pIntf->ulMediaState = ndisStats.MediaState;
  236. pIntf->ulMediaType = ndisStats.MediaType;
  237. pIntf->ulPhysicalMediaType = ndisStats.PhysicalMediaType;
  238. }
  239. DbgPrint((TRC_TRACK,"DevioGetIntfStats]=%d", dwErr));
  240. return dwErr;
  241. }
  242. DWORD
  243. DevioGetIntfMac(PINTF_CONTEXT pIntf)
  244. {
  245. DWORD dwErr = ERROR_SUCCESS;
  246. RAW_DATA rdBuffer = {0, NULL};
  247. DbgPrint((TRC_TRACK,"[DevioGetIntfMac(0x%p)", pIntf));
  248. dwErr = DevioRefreshIntfOIDs(
  249. pIntf,
  250. INTF_HANDLE,
  251. NULL);
  252. if (dwErr == ERROR_SUCCESS)
  253. {
  254. dwErr = DevioQueryBinaryOID(
  255. pIntf->hIntf,
  256. OID_802_3_CURRENT_ADDRESS,
  257. &rdBuffer,
  258. sizeof(NDIS_802_11_MAC_ADDRESS));
  259. }
  260. if (dwErr == ERROR_SUCCESS)
  261. {
  262. if (rdBuffer.dwDataLen == sizeof(NDIS_802_11_MAC_ADDRESS))
  263. {
  264. memcpy(&(pIntf->ndLocalMac), rdBuffer.pData, sizeof(NDIS_802_11_MAC_ADDRESS));
  265. }
  266. else
  267. {
  268. dwErr = ERROR_INVALID_DATA;
  269. }
  270. MemFree(rdBuffer.pData);
  271. }
  272. DbgPrint((TRC_TRACK,"DevioGetIntfMac]=%d", dwErr));
  273. return dwErr;
  274. }
  275. //------------------------------------------------------
  276. // Notify dependent components the wireless configuration has failed.
  277. // Specifically this notification goes to TCP allowing TCP to generate
  278. // the NetReady notification asap (instead of waiting for an IP address
  279. // to be plumbed down, which might never happen anyhow).
  280. DWORD
  281. DevioNotifyFailure(
  282. LPWSTR wszIntfGuid)
  283. {
  284. DWORD dwErr = ERROR_SUCCESS;
  285. WCHAR ndisDeviceString[128];
  286. UNICODE_STRING UpperComponent;
  287. UNICODE_STRING LowerComponent;
  288. UNICODE_STRING BindList;
  289. struct
  290. {
  291. IP_PNP_RECONFIG_REQUEST Reconfig;
  292. IP_PNP_INIT_COMPLETE InitComplete;
  293. } Request;
  294. DbgPrint((TRC_TRACK,"[DevioNotifyFailure(%S)", wszIntfGuid));
  295. wcscpy(ndisDeviceString, L"\\DEVICE\\");
  296. wcscat(ndisDeviceString, wszIntfGuid);
  297. RtlInitUnicodeString(&UpperComponent, L"Tcpip");
  298. RtlInitUnicodeString(&LowerComponent, ndisDeviceString);
  299. RtlInitUnicodeString(&BindList, NULL);
  300. ZeroMemory(&Request, sizeof(Request));
  301. Request.Reconfig.version = IP_PNP_RECONFIG_VERSION;
  302. Request.Reconfig.NextEntryOffset = (USHORT)((PUCHAR)&Request.InitComplete - (PUCHAR)&Request.Reconfig);
  303. Request.InitComplete.Header.EntryType = IPPnPInitCompleteEntryType;
  304. dwErr = NdisHandlePnPEvent(
  305. NDIS,
  306. RECONFIGURE,
  307. &LowerComponent,
  308. &UpperComponent,
  309. &BindList,
  310. &Request,
  311. sizeof(Request));
  312. DbgPrint((TRC_TRACK,"DevioNotifyFailure]=%d", dwErr));
  313. return dwErr;
  314. }
  315. DWORD
  316. DevioOpenIntfHandle(LPWSTR wszIntfGuid, PHANDLE phIntf)
  317. {
  318. DWORD dwErr = ERROR_SUCCESS;
  319. WCHAR ndisDeviceString[128];
  320. DbgPrint((TRC_TRACK,"[DevioOpenIntfHandle(%S)", wszIntfGuid));
  321. DbgAssert((phIntf!=NULL, "Invalid out param in DevioOpenIntfHandle"));
  322. wcscpy(ndisDeviceString, L"\\DEVICE\\");
  323. wcscat(ndisDeviceString, wszIntfGuid);
  324. dwErr = OpenIntfHandle(ndisDeviceString, phIntf);
  325. DbgPrint((TRC_TRACK,"DevioOpenIntfHandle]=%d", dwErr));
  326. return dwErr;
  327. }
  328. DWORD
  329. DevioCloseIntfHandle(PINTF_CONTEXT pIntf)
  330. {
  331. DWORD dwErr = ERROR_SUCCESS;
  332. DbgPrint((TRC_TRACK,"[DevioCloseIntfHandle(0x%p)", pIntf));
  333. // destroy the handle only if we did have one in the first instance. Otherwise
  334. // based only on the GUID we might mess the ref counter on a handle opened by
  335. // some other app (i.e. 802.1x)
  336. if (pIntf != NULL && pIntf->hIntf != INVALID_HANDLE_VALUE)
  337. {
  338. WCHAR ndisDeviceString[128];
  339. wcscpy(ndisDeviceString, L"\\DEVICE\\");
  340. wcscat(ndisDeviceString, pIntf->wszGuid);
  341. dwErr = CloseIntfHandle(ndisDeviceString);
  342. pIntf->hIntf = INVALID_HANDLE_VALUE;
  343. }
  344. DbgPrint((TRC_TRACK,"DevioCloseIntfHandle]=%d", dwErr));
  345. return dwErr;
  346. }
  347. DWORD
  348. DevioSetIntfOIDs(
  349. PINTF_CONTEXT pIntfContext,
  350. PINTF_ENTRY pIntfEntry,
  351. DWORD dwInFlags,
  352. PDWORD pdwOutFlags)
  353. {
  354. DWORD dwErr = ERROR_SUCCESS;
  355. DWORD dwLErr = ERROR_SUCCESS;
  356. DWORD dwOutFlags = 0;
  357. DbgPrint((TRC_TRACK,"[DevioSetIntfOIDs(0x%p, 0x%p)", pIntfContext, pIntfEntry));
  358. if (pIntfContext == NULL || pIntfEntry == NULL)
  359. {
  360. dwErr = ERROR_INVALID_PARAMETER;
  361. goto exit;
  362. }
  363. // Set the Infrastructure Mode, if requested
  364. if (dwInFlags & INTF_INFRAMODE)
  365. {
  366. dwLErr = DevioSetEnumOID(
  367. pIntfContext->hIntf,
  368. OID_802_11_INFRASTRUCTURE_MODE,
  369. pIntfEntry->nInfraMode);
  370. if (dwLErr != ERROR_SUCCESS)
  371. {
  372. // set the mode in the client's structure to what it
  373. // is currently set in the driver
  374. pIntfEntry->nInfraMode = pIntfContext->wzcCurrent.InfrastructureMode;
  375. }
  376. else
  377. {
  378. pIntfContext->wzcCurrent.InfrastructureMode = pIntfEntry->nInfraMode;
  379. dwOutFlags |= INTF_INFRAMODE;
  380. }
  381. if (dwErr == ERROR_SUCCESS)
  382. dwErr = dwLErr;
  383. }
  384. // Set the Authentication mode if requested
  385. if (dwInFlags & INTF_AUTHMODE)
  386. {
  387. dwLErr = DevioSetEnumOID(
  388. pIntfContext->hIntf,
  389. OID_802_11_AUTHENTICATION_MODE,
  390. pIntfEntry->nAuthMode);
  391. if (dwLErr != ERROR_SUCCESS)
  392. {
  393. // set the mode in the client's structure to what it
  394. // is currently set in the driver
  395. pIntfEntry->nAuthMode = pIntfContext->wzcCurrent.AuthenticationMode;
  396. }
  397. else
  398. {
  399. pIntfContext->wzcCurrent.AuthenticationMode = pIntfEntry->nAuthMode;
  400. dwOutFlags |= INTF_AUTHMODE;
  401. }
  402. if (dwErr == ERROR_SUCCESS)
  403. dwErr = dwLErr;
  404. }
  405. // Ask the driver to reload the default WEP key if requested
  406. if (dwInFlags & INTF_LDDEFWKEY)
  407. {
  408. dwLErr = DevioSetEnumOID(
  409. pIntfContext->hIntf,
  410. OID_802_11_RELOAD_DEFAULTS,
  411. (DWORD)Ndis802_11ReloadWEPKeys);
  412. if (dwLErr == ERROR_SUCCESS)
  413. dwOutFlags |= INTF_LDDEFWKEY;
  414. if (dwErr == ERROR_SUCCESS)
  415. dwErr = dwLErr;
  416. }
  417. // Add the WEP key if requested
  418. if (dwInFlags & INTF_ADDWEPKEY)
  419. {
  420. // the call below takes care of the case rdCtrlData is bogus
  421. dwLErr = DevioSetBinaryOID(
  422. pIntfContext->hIntf,
  423. OID_802_11_ADD_WEP,
  424. &pIntfEntry->rdCtrlData);
  425. if (dwLErr == ERROR_SUCCESS)
  426. dwOutFlags |= INTF_ADDWEPKEY;
  427. if (dwErr == ERROR_SUCCESS)
  428. dwErr = dwLErr;
  429. }
  430. // Remove the WEP key if requested
  431. if (dwInFlags & INTF_REMWEPKEY)
  432. {
  433. if (pIntfEntry->rdCtrlData.dwDataLen >= sizeof(NDIS_802_11_WEP) &&
  434. pIntfEntry->rdCtrlData.pData != NULL)
  435. {
  436. PNDIS_802_11_WEP pndWepKey = (PNDIS_802_11_WEP)pIntfEntry->rdCtrlData.pData;
  437. dwLErr = DevioSetEnumOID(
  438. pIntfContext->hIntf,
  439. OID_802_11_REMOVE_WEP,
  440. pndWepKey->KeyIndex);
  441. if (dwLErr == ERROR_SUCCESS)
  442. dwOutFlags |= INTF_REMWEPKEY;
  443. }
  444. else
  445. {
  446. dwLErr = ERROR_INVALID_PARAMETER;
  447. }
  448. if (dwErr == ERROR_SUCCESS)
  449. dwErr = dwLErr;
  450. }
  451. // Set the WEP Status if requested
  452. if (dwInFlags & INTF_WEPSTATUS)
  453. {
  454. dwLErr = DevioSetEnumOID(
  455. pIntfContext->hIntf,
  456. OID_802_11_WEP_STATUS,
  457. pIntfEntry->nWepStatus);
  458. if (dwLErr != ERROR_SUCCESS)
  459. {
  460. // set the mode in the client's structure to what it
  461. // is currently set in the driver
  462. pIntfEntry->nWepStatus = pIntfContext->wzcCurrent.Privacy;
  463. }
  464. else
  465. {
  466. pIntfContext->wzcCurrent.Privacy = pIntfEntry->nWepStatus;
  467. dwOutFlags |= INTF_WEPSTATUS;
  468. }
  469. if (dwErr == ERROR_SUCCESS)
  470. dwErr = dwLErr;
  471. }
  472. // Plumb the new SSID down to the driver. If success, copy this new
  473. // SSID into the interface's context
  474. if (dwInFlags & INTF_SSID)
  475. {
  476. // ntddndis.h defines NDIS_802_11_SSID with a maximum of
  477. // 32 UCHARs for the SSID name
  478. if (pIntfEntry->rdSSID.dwDataLen > 32)
  479. {
  480. dwLErr = ERROR_INVALID_PARAMETER;
  481. }
  482. else
  483. {
  484. NDIS_802_11_SSID ndSSID = {0};
  485. RAW_DATA rdBuffer;
  486. ndSSID.SsidLength = pIntfEntry->rdSSID.dwDataLen;
  487. memcpy(&ndSSID.Ssid, pIntfEntry->rdSSID.pData, ndSSID.SsidLength);
  488. rdBuffer.dwDataLen = sizeof(NDIS_802_11_SSID);
  489. rdBuffer.pData = (LPBYTE)&ndSSID;
  490. dwLErr = DevioSetBinaryOID(
  491. pIntfContext->hIntf,
  492. OID_802_11_SSID,
  493. &rdBuffer);
  494. if (dwLErr == ERROR_SUCCESS)
  495. {
  496. // copy over the new SSID into the interface's context
  497. CopyMemory(&pIntfContext->wzcCurrent.Ssid, &ndSSID, sizeof(NDIS_802_11_SSID));
  498. dwOutFlags |= INTF_SSID;
  499. // on the same time, if a new SSID has been set, it means we broke whatever association
  500. // we had before, hence the BSSID field can no longer be correct:
  501. ZeroMemory(&pIntfContext->wzcCurrent.MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS));
  502. }
  503. }
  504. if (dwErr == ERROR_SUCCESS)
  505. dwErr = dwLErr;
  506. }
  507. // set the new BSSID to the driver. If this succeeds, copy
  508. // the data that was passed down to the interface's context (allocate
  509. // space for it if not already allocated).
  510. if (dwInFlags & INTF_BSSID)
  511. {
  512. dwLErr = DevioSetBinaryOID(
  513. pIntfContext->hIntf,
  514. OID_802_11_BSSID,
  515. &pIntfEntry->rdBSSID);
  516. // if the BSSID is not a MAC address, the call above should fail!
  517. if (dwLErr == ERROR_SUCCESS)
  518. {
  519. DbgAssert((pIntfEntry->rdBSSID.dwDataLen == sizeof(NDIS_802_11_MAC_ADDRESS),
  520. "Data to be set is %d bytes, which is not a MAC address!",
  521. pIntfEntry->rdBSSID.dwDataLen));
  522. memcpy(&pIntfContext->wzcCurrent.MacAddress, pIntfEntry->rdBSSID.pData, sizeof(NDIS_802_11_MAC_ADDRESS));
  523. dwOutFlags |= INTF_BSSID;
  524. }
  525. if (dwErr == ERROR_SUCCESS)
  526. dwErr = dwLErr;
  527. }
  528. exit:
  529. if (pdwOutFlags != NULL)
  530. *pdwOutFlags = dwOutFlags;
  531. DbgPrint((TRC_TRACK,"DevioSetIntfOIDs]=%d", dwErr));
  532. return dwErr;
  533. }
  534. DWORD
  535. DevioRefreshIntfOIDs(
  536. PINTF_CONTEXT pIntf,
  537. DWORD dwInFlags,
  538. PDWORD pdwOutFlags)
  539. {
  540. DWORD dwErr = ERROR_SUCCESS;
  541. DWORD dwLErr = ERROR_SUCCESS;
  542. DWORD dwOutFlags = 0;
  543. RAW_DATA rdBuffer;
  544. DbgPrint((TRC_TRACK,"[DevioRefreshIntfOIDs(0x%p)", pIntf));
  545. if (pIntf == NULL)
  546. {
  547. dwErr = ERROR_INVALID_PARAMETER;
  548. goto exit;
  549. }
  550. // if the interface handle is invalid or there is an explicit requested
  551. // to reopen the interface's handle do it as the first thing
  552. if (pIntf->hIntf == INVALID_HANDLE_VALUE || dwInFlags & INTF_HANDLE)
  553. {
  554. if (pIntf->hIntf != INVALID_HANDLE_VALUE)
  555. {
  556. dwErr = DevioCloseIntfHandle(pIntf);
  557. DbgAssert((dwErr == ERROR_SUCCESS,
  558. "Couldn't close handle for Intf %S",
  559. pIntf->wszGuid));
  560. }
  561. dwErr = DevioOpenIntfHandle(pIntf->wszGuid, &pIntf->hIntf);
  562. DbgAssert((dwErr == ERROR_SUCCESS,
  563. "DevioOpenIntfHandle failed for Intf context 0x%p",
  564. pIntf));
  565. if (dwErr == ERROR_SUCCESS && (dwInFlags & INTF_HANDLE))
  566. dwOutFlags |= INTF_HANDLE;
  567. }
  568. // if failed to refresh the interface's handle (this is the only way
  569. // dwErr could not be success) then we already have a closed handle
  570. // so there's no point in going further
  571. if (dwErr != ERROR_SUCCESS)
  572. goto exit;
  573. // if requested to scan the interface's BSSID list, do it as
  574. // the next thing. Note however that rescanning is asynchronous.
  575. // Querying for the BSSID_LIST in the same shot with forcing a rescan
  576. // might not result in getting the most up to date list.
  577. if (dwInFlags & INTF_LIST_SCAN)
  578. {
  579. // indicate to the driver to rescan the BSSID_LIST for this adapter
  580. dwLErr = DevioSetEnumOID(
  581. pIntf->hIntf,
  582. OID_802_11_BSSID_LIST_SCAN,
  583. 0);
  584. DbgAssert((dwLErr == ERROR_SUCCESS,
  585. "DevioSetEnumOID(BSSID_LIST_SCAN) failed for Intf hdl 0x%x",
  586. pIntf->hIntf));
  587. if (dwLErr == ERROR_SUCCESS)
  588. dwOutFlags |= INTF_LIST_SCAN;
  589. else if (dwErr == ERROR_SUCCESS)
  590. dwErr = dwLErr;
  591. }
  592. if (dwInFlags & INTF_AUTHMODE)
  593. {
  594. // query the authentication mode for the interface
  595. dwLErr = DevioQueryEnumOID(
  596. pIntf->hIntf,
  597. OID_802_11_AUTHENTICATION_MODE,
  598. (LPDWORD)&pIntf->wzcCurrent.AuthenticationMode);
  599. DbgAssert((dwLErr == ERROR_SUCCESS,
  600. "DevioQueryEnumOID(AUTH_MODE) failed for Intf hdl 0x%x",
  601. pIntf->hIntf));
  602. if (dwLErr == ERROR_SUCCESS)
  603. dwOutFlags |= INTF_AUTHMODE;
  604. else if (dwErr == ERROR_SUCCESS)
  605. dwErr = dwLErr;
  606. }
  607. if (dwInFlags & INTF_INFRAMODE)
  608. {
  609. // query the infrastructure mode for the interface
  610. dwLErr = DevioQueryEnumOID(
  611. pIntf->hIntf,
  612. OID_802_11_INFRASTRUCTURE_MODE,
  613. (LPDWORD)&pIntf->wzcCurrent.InfrastructureMode);
  614. DbgAssert((dwLErr == ERROR_SUCCESS,
  615. "DevioQueryEnumOID(INFRA_MODE) failed for Intf hdl 0x%x",
  616. pIntf->hIntf));
  617. if (dwLErr == ERROR_SUCCESS)
  618. dwOutFlags |= INTF_INFRAMODE;
  619. else if (dwErr == ERROR_SUCCESS)
  620. dwErr = dwLErr;
  621. }
  622. if (dwInFlags & INTF_WEPSTATUS)
  623. {
  624. // query the WEP_STATUS for the interface
  625. dwLErr = DevioQueryEnumOID(
  626. pIntf->hIntf,
  627. OID_802_11_WEP_STATUS,
  628. (LPDWORD)&pIntf->wzcCurrent.Privacy);
  629. DbgAssert((dwLErr == ERROR_SUCCESS,
  630. "DevioQueryEnumOID(WEP_STATUS) failed for Intf hdl 0x%x",
  631. pIntf->hIntf));
  632. if (dwLErr == ERROR_SUCCESS)
  633. dwOutFlags |= INTF_WEPSTATUS;
  634. else if (dwErr == ERROR_SUCCESS)
  635. dwErr = dwLErr;
  636. }
  637. if (dwInFlags & INTF_BSSID)
  638. {
  639. // query the BSSID (MAC address) for the interface
  640. rdBuffer.dwDataLen = 0;
  641. rdBuffer.pData = NULL;
  642. dwLErr = DevioQueryBinaryOID(
  643. pIntf->hIntf,
  644. OID_802_11_BSSID,
  645. &rdBuffer,
  646. 6);
  647. DbgAssert((dwLErr == ERROR_SUCCESS,
  648. "DevioQueryBinaryOID(BSSID) failed for Intf hdl 0x%x",
  649. pIntf->hIntf));
  650. // if the call above succeeded...
  651. if (dwLErr == ERROR_SUCCESS)
  652. {
  653. DbgAssert((rdBuffer.dwDataLen == 6, "BSSID len %d is not a MAC address len??", rdBuffer.dwDataLen));
  654. // ...and returned correctly a MAC address
  655. if (rdBuffer.dwDataLen == sizeof(NDIS_802_11_MAC_ADDRESS))
  656. {
  657. // copy it in the interface's context
  658. memcpy(&pIntf->wzcCurrent.MacAddress, rdBuffer.pData, rdBuffer.dwDataLen);
  659. }
  660. else
  661. {
  662. ZeroMemory(&pIntf->wzcCurrent.MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS));
  663. dwLErr = ERROR_INVALID_DATA;
  664. }
  665. }
  666. // free whatever might have had been allocated in DevioQueryBinaryOID
  667. MemFree(rdBuffer.pData);
  668. if (dwLErr == ERROR_SUCCESS)
  669. dwOutFlags |= INTF_BSSID;
  670. else if (dwErr == ERROR_SUCCESS)
  671. dwErr = dwLErr;
  672. }
  673. if (dwInFlags & INTF_SSID)
  674. {
  675. PNDIS_802_11_SSID pndSSID;
  676. // query the SSID for the interface
  677. rdBuffer.dwDataLen = 0;
  678. rdBuffer.pData = NULL;
  679. dwLErr = DevioQueryBinaryOID(
  680. pIntf->hIntf,
  681. OID_802_11_SSID,
  682. &rdBuffer,
  683. sizeof(NDIS_802_11_SSID));
  684. DbgAssert((dwLErr == ERROR_SUCCESS,
  685. "DevioQueryBinaryOID(SSID) failed for Intf hdl 0x%x",
  686. pIntf->hIntf));
  687. // if we succeeded up to here then we can't fail further for this OID
  688. if (dwLErr == ERROR_SUCCESS)
  689. dwOutFlags |= INTF_SSID;
  690. else if (dwErr == ERROR_SUCCESS)
  691. dwErr = dwLErr;
  692. // copy the pointer to the buffer that was allocated in Query call
  693. pndSSID = (PNDIS_802_11_SSID)rdBuffer.pData;
  694. if (pndSSID != NULL)
  695. {
  696. // HACK - if the driver doesn't return the NDIS_802_11_SSID structure but just
  697. // the SSID itself, correct this!
  698. if (pndSSID->SsidLength > 32)
  699. {
  700. DbgAssert((FALSE,"Driver returns SSID instead of NDIS_802_11_SSID structure"));
  701. // we have enough space in the buffer to slide the data up (it was shifted down
  702. // in DevioQueryBinaryOID.
  703. MoveMemory(pndSSID->Ssid, pndSSID, rdBuffer.dwDataLen);
  704. pndSSID->SsidLength = rdBuffer.dwDataLen;
  705. }
  706. // copy over the current SSID into the interface's context if there was no error
  707. CopyMemory(&pIntf->wzcCurrent.Ssid, pndSSID, sizeof(NDIS_802_11_SSID));
  708. }
  709. // free whatever might have been allocated in DevioQueryBinaryOID
  710. MemFree(pndSSID);
  711. }
  712. if (dwInFlags & INTF_BSSIDLIST)
  713. {
  714. rdBuffer.dwDataLen = 0;
  715. rdBuffer.pData = NULL;
  716. // estimate a buffer large enough for 20 SSIDs.
  717. dwLErr = DevioQueryBinaryOID(
  718. pIntf->hIntf,
  719. OID_802_11_BSSID_LIST,
  720. &rdBuffer,
  721. sizeof(NDIS_802_11_BSSID_LIST) + 19*sizeof(NDIS_WLAN_BSSID));
  722. DbgAssert((dwLErr == ERROR_SUCCESS,
  723. "DevioQueryBinaryOID(BSSID_LIST) failed for Intf hdl 0x%x",
  724. pIntf->hIntf));
  725. // if we succeeded getting the visible list we should have a valid
  726. // rdBuffer.pData, even if it shows '0 entries'
  727. if (dwLErr == ERROR_SUCCESS)
  728. {
  729. PWZC_802_11_CONFIG_LIST pNewVList;
  730. pNewVList = WzcNdisToWzc((PNDIS_802_11_BSSID_LIST)rdBuffer.pData);
  731. if (rdBuffer.pData == NULL || pNewVList != NULL)
  732. {
  733. // cleanup whatever we might have had before
  734. MemFree(pIntf->pwzcVList);
  735. // copy the new visible list we got
  736. pIntf->pwzcVList = pNewVList;
  737. dwOutFlags |= INTF_BSSIDLIST;
  738. }
  739. else
  740. dwLErr = GetLastError();
  741. // whatever the outcome is, free the buffer returned from the driver
  742. MemFree(rdBuffer.pData);
  743. }
  744. // if any error happened here, save it unless some other error has already
  745. // been saved
  746. if (dwErr == ERROR_SUCCESS)
  747. dwErr = dwLErr;
  748. }
  749. exit:
  750. if (pdwOutFlags != NULL)
  751. *pdwOutFlags = dwOutFlags;
  752. DbgPrint((TRC_TRACK,"DevioRefreshIntfOIDs]=%d", dwErr));
  753. return dwErr;
  754. }
  755. DWORD
  756. DevioQueryEnumOID(
  757. HANDLE hIntf,
  758. NDIS_OID Oid,
  759. DWORD *pdwEnumValue)
  760. {
  761. DWORD dwErr = ERROR_SUCCESS;
  762. NDISUIO_QUERY_OID QueryOid;
  763. DWORD dwBytesReturned = 0;
  764. DbgPrint((TRC_TRACK,"[DevioQueryEnumOID(0x%x, 0x%x)", hIntf, Oid));
  765. DbgAssert((pdwEnumValue != NULL, "Invalid out param in DevioQueryEnumOID"));
  766. if (hIntf == INVALID_HANDLE_VALUE || pdwEnumValue == NULL)
  767. {
  768. dwErr = ERROR_INVALID_PARAMETER;
  769. goto exit;
  770. }
  771. // the NDISUIO_QUERY_OID includes data for 1 dword, sufficient for getting
  772. // an enumerative value from the driver. This spares us of an additional
  773. // allocation.
  774. ZeroMemory(&QueryOid, sizeof(NDISUIO_QUERY_OID));
  775. QueryOid.Oid = Oid;
  776. if (!DeviceIoControl (
  777. hIntf,
  778. IOCTL_NDISUIO_QUERY_OID_VALUE,
  779. (LPVOID)&QueryOid,
  780. sizeof(NDISUIO_QUERY_OID),
  781. (LPVOID)&QueryOid,
  782. sizeof(NDISUIO_QUERY_OID),
  783. &dwBytesReturned,
  784. NULL)) // no overlapping routine
  785. {
  786. dwErr = GetLastError();
  787. DbgPrint((TRC_ERR, "Err: IOCTL_NDISUIO_QUERY_OID_VALUE->%d", dwErr));
  788. goto exit;
  789. }
  790. //dwErr = GetLastError();
  791. //DbgAssert((dwErr == ERROR_SUCCESS, "DeviceIoControl suceeded, but GetLastError() is =0x%x", dwErr));
  792. dwErr = ERROR_SUCCESS;
  793. *pdwEnumValue = *(LPDWORD)QueryOid.Data;
  794. exit:
  795. DbgPrint((TRC_TRACK,"DevioQueryEnumOID]=%d", dwErr));
  796. return dwErr;
  797. }
  798. DWORD
  799. DevioSetEnumOID(
  800. HANDLE hIntf,
  801. NDIS_OID Oid,
  802. DWORD dwEnumValue)
  803. {
  804. DWORD dwErr = ERROR_SUCCESS;
  805. NDISUIO_SET_OID SetOid;
  806. DWORD dwBytesReturned = 0;
  807. DbgPrint((TRC_TRACK,"[DevioSetEnumOID(0x%x, 0x%x, %d)", hIntf, Oid, dwEnumValue));
  808. if (hIntf == INVALID_HANDLE_VALUE)
  809. {
  810. dwErr = ERROR_INVALID_PARAMETER;
  811. goto exit;
  812. }
  813. // the NDISUIO_SET_OID includes data for 1 dword, sufficient for setting
  814. // an enumerative value from the driver. This spares us of an additional
  815. // allocation.
  816. SetOid.Oid = Oid;
  817. *(LPDWORD)SetOid.Data = dwEnumValue;
  818. if (!DeviceIoControl (
  819. hIntf,
  820. IOCTL_NDISUIO_SET_OID_VALUE,
  821. (LPVOID)&SetOid,
  822. sizeof(NDISUIO_SET_OID),
  823. NULL,
  824. 0,
  825. &dwBytesReturned,
  826. NULL)) // no overlapping routine
  827. {
  828. dwErr = GetLastError();
  829. DbgPrint((TRC_ERR, "Err: IOCTL_NDISUIO_SET_OID_VALUE->%d", dwErr));
  830. goto exit;
  831. }
  832. //dwErr = GetLastError();
  833. //DbgAssert((dwErr == ERROR_SUCCESS, "DeviceIoControl suceeded, but GetLastError() is =0x%x", dwErr));
  834. dwErr = ERROR_SUCCESS;
  835. exit:
  836. DbgPrint((TRC_TRACK,"DevioSetEnumOID]=%d", dwErr));
  837. return dwErr;
  838. }
  839. #define DATA_MEM_MIN 32 // the minimum mem block to be sent out to the ioctl
  840. #define DATA_MEM_MAX 65536 // the maximum mem block that will be sent out to the ioctl (64K)
  841. #define DATA_MEM_INC 512 // increment the existent block in 512 bytes increment
  842. DWORD
  843. DevioQueryBinaryOID(
  844. HANDLE hIntf,
  845. NDIS_OID Oid,
  846. PRAW_DATA pRawData, // buffer is internally allocated
  847. DWORD dwMemEstimate) // how much memory is estimated the result needs
  848. {
  849. DWORD dwErr = ERROR_SUCCESS;
  850. PNDISUIO_QUERY_OID pQueryOid=NULL;
  851. DbgPrint((TRC_TRACK, "[DevioQueryBinaryOID(0x%x, 0x%x)", hIntf, Oid));
  852. if (hIntf == INVALID_HANDLE_VALUE ||
  853. pRawData == NULL)
  854. {
  855. dwErr = ERROR_INVALID_PARAMETER;
  856. goto exit;
  857. }
  858. if (dwMemEstimate < DATA_MEM_MIN)
  859. dwMemEstimate = DATA_MEM_MIN;
  860. do
  861. {
  862. DWORD dwBuffSize;
  863. DWORD dwBytesReturned;
  864. MemFree(pQueryOid);
  865. if (dwMemEstimate > DATA_MEM_MAX)
  866. dwMemEstimate = DATA_MEM_MAX;
  867. dwBuffSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + dwMemEstimate;
  868. pQueryOid = (PNDISUIO_QUERY_OID) MemCAlloc(dwBuffSize);
  869. if (pQueryOid == NULL)
  870. {
  871. dwErr = GetLastError();
  872. break;
  873. }
  874. pQueryOid->Oid = Oid;
  875. if (DeviceIoControl (
  876. hIntf,
  877. IOCTL_NDISUIO_QUERY_OID_VALUE,
  878. (LPVOID)pQueryOid,
  879. dwBuffSize,
  880. (LPVOID)pQueryOid,
  881. dwBuffSize,
  882. &dwBytesReturned,
  883. NULL))
  884. {
  885. DbgAssert((
  886. dwBytesReturned <= dwBuffSize,
  887. "DeviceIoControl returned %d > %d that was passed down!",
  888. dwBytesReturned,
  889. dwBuffSize));
  890. pRawData->pData = (LPBYTE)pQueryOid;
  891. pRawData->dwDataLen = dwBytesReturned - FIELD_OFFSET(NDISUIO_QUERY_OID, Data);
  892. if (pRawData->dwDataLen != 0)
  893. {
  894. MoveMemory(pQueryOid, pQueryOid->Data, pRawData->dwDataLen);
  895. }
  896. else
  897. {
  898. pRawData->pData = NULL;
  899. MemFree(pQueryOid);
  900. pQueryOid = NULL;
  901. }
  902. dwErr = ERROR_SUCCESS;
  903. break;
  904. }
  905. dwErr = GetLastError();
  906. if (((dwErr == ERROR_INSUFFICIENT_BUFFER) || (dwErr == ERROR_INVALID_USER_BUFFER)) &&
  907. (dwMemEstimate < DATA_MEM_MAX))
  908. {
  909. dwMemEstimate += DATA_MEM_INC;
  910. dwErr = ERROR_SUCCESS;
  911. }
  912. } while (dwErr == ERROR_SUCCESS);
  913. exit:
  914. if (dwErr != ERROR_SUCCESS)
  915. {
  916. MemFree(pQueryOid);
  917. pRawData->pData= NULL;
  918. pRawData->dwDataLen = 0;
  919. }
  920. DbgPrint((TRC_TRACK, "DevioQueryBinaryOID]=%d", dwErr));
  921. return dwErr;
  922. }
  923. DWORD
  924. DevioSetBinaryOID(
  925. HANDLE hIntf,
  926. NDIS_OID Oid,
  927. PRAW_DATA pRawData)
  928. {
  929. DWORD dwErr = ERROR_SUCCESS;
  930. PNDISUIO_SET_OID pSetOid = NULL;
  931. DWORD dwBytesReturned = 0;
  932. DWORD dwBufferSize;
  933. DbgPrint((TRC_TRACK,"[DevioSetBinaryOID(0x%x,0x%x,...)", hIntf, Oid));
  934. if (hIntf == INVALID_HANDLE_VALUE ||
  935. pRawData == NULL ||
  936. pRawData->dwDataLen == 0 ||
  937. pRawData->pData == NULL)
  938. {
  939. dwErr = ERROR_INVALID_PARAMETER;
  940. goto exit;
  941. }
  942. dwBufferSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + pRawData->dwDataLen;
  943. pSetOid = (PNDISUIO_SET_OID) MemCAlloc(dwBufferSize);
  944. if (pSetOid == NULL)
  945. {
  946. dwErr = GetLastError();
  947. goto exit;
  948. }
  949. pSetOid->Oid = Oid;
  950. CopyMemory(pSetOid->Data, pRawData->pData, pRawData->dwDataLen);
  951. if (!DeviceIoControl (
  952. hIntf,
  953. IOCTL_NDISUIO_SET_OID_VALUE,
  954. (LPVOID)pSetOid,
  955. dwBufferSize,
  956. NULL,
  957. 0,
  958. &dwBytesReturned,
  959. NULL)) // no overlapping routine
  960. {
  961. dwErr = GetLastError();
  962. DbgPrint((TRC_ERR, "Err: IOCTL_NDISUIO_SET_OID_VALUE->%d", dwErr));
  963. goto exit;
  964. }
  965. //dwErr = GetLastError();
  966. //DbgAssert((dwErr == ERROR_SUCCESS, "DeviceIoControl suceeded, but GetLastError() is 0x%x", dwErr));
  967. dwErr = ERROR_SUCCESS;
  968. exit:
  969. MemFree(pSetOid);
  970. DbgPrint((TRC_TRACK,"DevioSetBinaryOID]=%d", dwErr));
  971. return dwErr;
  972. }