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.

874 lines
31 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2001.
  5. //
  6. // File: N A M I N G . C P P
  7. //
  8. // Contents: Generates Connection Names Automatically
  9. //
  10. // Notes:
  11. //
  12. // Author: deonb 27 Feb 2001
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "ncnetcfg.h"
  18. #include "netcon.h"
  19. #include "netconp.h"
  20. #include <ntddndis.h>
  21. #include <ndisprv.h>
  22. #include <devioctl.h>
  23. #include <ndispnp.h>
  24. #include "naming.h"
  25. #include <rasapip.h>
  26. #include "wzcsapi.h"
  27. extern const WCHAR c_szBiNdisAtm[];
  28. extern const WCHAR c_szInfId_MS_AtmElan[];
  29. const WCHAR c_szDevice[] = L"\\DEVICE\\";
  30. #define MAX_TYPE_NAME_LEN 45
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Function: CIntelliName::CIntelliName
  34. //
  35. // Purpose: Constructor
  36. //
  37. // Arguments:
  38. // hInstance [in] Resource instance of binary with naming.rc included
  39. //
  40. // pFNDuplicateNameCheck [in] Callback function of duplicate check. Can be NULL \
  41. // or otherwise of the following callback type:
  42. // + typedef BOOL FNDuplicateNameCheck
  43. // + pIntelliName [in] CIntelliName this pointer (for HrGetPseudoMediaTypes callback)
  44. // + szName [in] Name to check for
  45. // + pncm [out] NetCon Media Type of conflicting connection
  46. // + pncms [out] NetCon SubMedia Type of conflicting connection
  47. // + return TRUE - if conflicting found or FALSE if no conflicting connection found
  48. //
  49. // Returns: None
  50. //
  51. // Author: deonb 27 Feb 2001
  52. //
  53. // Notes:
  54. //
  55. CIntelliName::CIntelliName(IN HINSTANCE hInstance, IN FNDuplicateNameCheck *pFNDuplicateNameCheck)
  56. {
  57. m_pFNDuplicateNameCheck = pFNDuplicateNameCheck;
  58. m_hInstance = hInstance;
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Function: CIntelliName::NameExists
  63. //
  64. // Purpose: Check if a name already exists
  65. //
  66. // Arguments:
  67. // szName [in] Name to check for
  68. // pncm [out] NetCon Media Type of conflicting connection
  69. // pncms [out] NetCon SubMedia Type of conflicting connection
  70. //
  71. // Returns: TRUE if exists, FALSE if not
  72. //
  73. // Author: deonb 27 Feb 2001
  74. //
  75. // Notes:
  76. //
  77. BOOL CIntelliName::NameExists(IN LPCWSTR szName, OUT NETCON_MEDIATYPE *pncm, OUT NETCON_SUBMEDIATYPE *pncms) const
  78. {
  79. if (m_pFNDuplicateNameCheck)
  80. {
  81. Assert(pncm);
  82. Assert(pncms);
  83. if (IsReservedName(szName))
  84. {
  85. return TRUE;
  86. }
  87. return (*m_pFNDuplicateNameCheck)(this, szName, pncm, pncms);
  88. }
  89. return FALSE;
  90. }
  91. //+---------------------------------------------------------------------------
  92. //
  93. // Function: CIntelliName::IsReservedName
  94. //
  95. // Purpose: Check if a name is a reserved name
  96. //
  97. // Arguments:
  98. // szName [in] Name to check for
  99. //
  100. // Returns: TRUE if reserved, FALSE if not
  101. //
  102. // Author: deonb 12 Mar 2001
  103. //
  104. // Notes:
  105. //
  106. BOOL CIntelliName::IsReservedName(IN LPCWSTR szName) const
  107. {
  108. UINT uiReservedNames[] = {IDS_RESERVED_INCOMING,
  109. IDS_RESERVED_NCW,
  110. IDS_RESERVED_HNW};
  111. for (int x = 0; x < celems(uiReservedNames); x++)
  112. {
  113. WCHAR szReservedName[MAX_PATH];
  114. int nSiz = LoadString (m_hInstance, uiReservedNames[x], szReservedName, MAX_PATH);
  115. if (nSiz)
  116. {
  117. if (0 == lstrcmpi(szName, szReservedName))
  118. {
  119. return TRUE;
  120. }
  121. }
  122. }
  123. return FALSE;
  124. }
  125. //+---------------------------------------------------------------------------
  126. //
  127. // Function: CIntelliName::GenerateNameRenameOnConflict
  128. //
  129. // Purpose: Generate a name, rename if it conflicts with an existing name
  130. //
  131. // Arguments:
  132. // guid [in] GUID of connection
  133. // ncm [in] NetCon Media Type of Connection
  134. // dwCharacteristics [in] NCCF_ Characteristics of Connection (Pass 0 if you don't know)
  135. // szHintName [in] Hint of name (will use as is if not conflicting)
  136. // szHintType [in] String of NetCon Media Type
  137. // szName [out] Resulting connection name - free with CoTaskMemFree
  138. //
  139. // Returns: HRESULT
  140. //
  141. // Author: deonb 27 Feb 2001
  142. //
  143. // Notes:
  144. //
  145. HRESULT CIntelliName::GenerateNameRenameOnConflict(IN REFGUID guid,
  146. IN NETCON_MEDIATYPE ncm,
  147. IN DWORD dwCharacteristics,
  148. IN LPCWSTR szHintName,
  149. IN LPCWSTR szHintType,
  150. OUT LPWSTR* szName) const
  151. {
  152. HRESULT hr = S_OK;
  153. WCHAR szTemp[NETCON_MAX_NAME_LEN];
  154. WCHAR szBaseName[NETCON_MAX_NAME_LEN];
  155. Assert(szName)
  156. *szName = NULL;
  157. lstrcpynW(szTemp, szHintName, celems(szTemp) - MAX_TYPE_NAME_LEN); // reserve bytes at end to include specialized info.
  158. DWORD dwInstance = 2;
  159. lstrcpynW(szBaseName, szTemp, celems(szBaseName) );
  160. NETCON_MEDIATYPE ncmdup;
  161. NETCON_SUBMEDIATYPE ncmsdup;
  162. if (NameExists(szTemp, &ncmdup, &ncmsdup))
  163. {
  164. BOOL fHasTypeAlready = FALSE;
  165. if ( (ncmdup == ncm) || (NCM_LAN == ncm) )
  166. {
  167. fHasTypeAlready = TRUE;
  168. }
  169. if (!fHasTypeAlready)
  170. {
  171. if (DwFormatString(L"%1!s! (%2!s!)", szTemp, celems(szTemp), szBaseName, szHintType))
  172. {
  173. lstrcpynW(szBaseName, szTemp, celems(szBaseName));
  174. }
  175. else
  176. {
  177. hr = HrFromLastWin32Error();
  178. }
  179. }
  180. else
  181. {
  182. if (!DwFormatString(L"%1!s! %2!d!", szTemp, celems(szTemp), szBaseName, dwInstance))
  183. {
  184. hr = HrFromLastWin32Error();
  185. }
  186. dwInstance++;
  187. }
  188. while ( SUCCEEDED(hr) && NameExists(szTemp, &ncmdup, &ncmsdup) && (dwInstance < 65535) )
  189. {
  190. if (!DwFormatString(L"%1!s! %2!d!", szTemp, celems(szTemp), szBaseName, dwInstance))
  191. {
  192. hr = HrFromLastWin32Error();
  193. }
  194. dwInstance++;
  195. }
  196. if ( SUCCEEDED(hr) && (dwInstance >= 65535) && NameExists(szTemp, &ncmdup, &ncmsdup) )
  197. {
  198. hr = E_FAIL;
  199. }
  200. }
  201. if (S_OK == hr)
  202. {
  203. hr = HrCoTaskMemAllocAndDupSz(szTemp, szName, NETCON_MAX_NAME_LEN);
  204. }
  205. return hr;
  206. }
  207. //+---------------------------------------------------------------------------
  208. //
  209. // Function: CIntelliName::GenerateNameFromResource
  210. //
  211. // Purpose: Generate a name, rename if it conflicts with an existing name
  212. //
  213. // Arguments:
  214. // guid [in] GUID of connection
  215. // ncm [in] NetCon Media Type of Connection
  216. // dwCharacteristics [in] NCCF_ Characteristics of Connection (Pass 0 if you don't know)
  217. // szHintName [in] Hint of name (will use as is if not conflicting)
  218. // uiNameID [in] Resource id of default name
  219. // uiTypeId [in] Resource id of default type
  220. // szName [out] Resulting connection name - free with CoTaskMemFree
  221. //
  222. // Returns: HRESULT
  223. //
  224. // Author: deonb 27 Feb 2001
  225. //
  226. // Notes:
  227. //
  228. HRESULT CIntelliName::GenerateNameFromResource(IN REFGUID guid,
  229. IN NETCON_MEDIATYPE ncm,
  230. IN DWORD dwCharacteristics,
  231. IN LPCWSTR szHint,
  232. IN UINT uiNameID,
  233. IN UINT uiTypeId,
  234. OUT LPWSTR* szName) const
  235. {
  236. Assert(szName);
  237. *szName = NULL;
  238. WCHAR szHintName[NETCON_MAX_NAME_LEN];
  239. WCHAR szTypeName[MAX_TYPE_NAME_LEN - 3]; // - 3 as this is put later into a MAX_TYPE_NAME_LEN character
  240. // buffer with ' (%s)' at the end
  241. if (!szHint || *szHint == L'\0')
  242. {
  243. int nSiz = LoadString (m_hInstance, uiNameID, szHintName, celems(szHintName) );
  244. AssertSz(nSiz, "Resource string not found");
  245. }
  246. else
  247. {
  248. lstrcpynW(szHintName, szHint, celems(szHintName) );
  249. }
  250. int nSiz = LoadString (m_hInstance, uiTypeId, szTypeName, celems(szTypeName) );
  251. AssertSz(nSiz, "Resource string not found");
  252. return GenerateNameRenameOnConflict(guid, ncm, dwCharacteristics, szHintName, szTypeName, szName);
  253. }
  254. //+---------------------------------------------------------------------------
  255. //
  256. // Function: CIntelliName::HrGetPseudoMediaTypes
  257. //
  258. // Purpose: Generate a name, rename if it conflicts with an existing name
  259. //
  260. // Arguments:
  261. // guid [in] GUID of connection
  262. // pncm [out] Pseudo-NetCon Media Type of Connection (Only NCM_PHONE or NCM_LAN)
  263. // pncms [out] SubMedia Type for LAN connections
  264. //
  265. // Returns: HRESULT
  266. //
  267. // Author: deonb 27 Feb 2001
  268. //
  269. // Notes:
  270. //
  271. HRESULT CIntelliName::HrGetPseudoMediaTypes(IN REFGUID guid,
  272. OUT NETCON_MEDIATYPE* pncm,
  273. OUT NETCON_SUBMEDIATYPE* pncms) const
  274. {
  275. Assert(pncms);
  276. Assert(pncm);
  277. Assert(guid != GUID_NULL);
  278. HRESULT hr;
  279. *pncms = NCSM_NONE;
  280. INetCfg* pNetCfg;
  281. hr = CoCreateInstance(
  282. CLSID_CNetCfg,
  283. NULL,
  284. CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  285. IID_INetCfg,
  286. reinterpret_cast<LPVOID *>(&pNetCfg));
  287. if (SUCCEEDED(hr))
  288. {
  289. hr = pNetCfg->Initialize(NULL);
  290. if (SUCCEEDED(hr))
  291. {
  292. CIterNetCfgComponent nccIter(pNetCfg, &GUID_DEVCLASS_NET);
  293. INetCfgComponent* pnccAdapter = NULL;
  294. BOOL fFound = FALSE;
  295. while (!fFound && SUCCEEDED(hr) &&
  296. (S_OK == (hr = nccIter.HrNext(&pnccAdapter))))
  297. {
  298. GUID guidDev;
  299. hr = pnccAdapter->GetInstanceGuid(&guidDev);
  300. if (S_OK == hr)
  301. {
  302. if (guid == guidDev)
  303. {
  304. hr = HrIsLanCapableAdapter(pnccAdapter);
  305. Assert(SUCCEEDED(hr));
  306. if (SUCCEEDED(hr))
  307. {
  308. fFound = TRUE;
  309. if (S_FALSE == hr)
  310. {
  311. *pncm = NCM_PHONE;
  312. }
  313. else if (S_OK == hr)
  314. {
  315. *pncm = NCM_LAN;
  316. BOOL bRet;
  317. DWORD dwMediaType;
  318. DWORD dwMediaTypeSize = sizeof(DWORD);
  319. hr = HrQueryNDISAdapterOID(guid,
  320. OID_GEN_PHYSICAL_MEDIUM,
  321. &dwMediaTypeSize,
  322. &dwMediaType);
  323. if (S_OK == hr)
  324. {
  325. switch (dwMediaType)
  326. {
  327. case NdisPhysicalMedium1394:
  328. *pncms = NCSM_1394;
  329. break;
  330. default:
  331. hr = S_FALSE;
  332. break;
  333. }
  334. }
  335. if (S_OK != hr) // Couldn't determine the Physical Media type. Try bindings next.
  336. {
  337. HRESULT hrPhysicalMedia = hr;
  338. *pncms = NCSM_LAN;
  339. INetCfgComponentBindings* pnccb;
  340. hr = pnccAdapter->QueryInterface(IID_INetCfgComponentBindings,
  341. reinterpret_cast<LPVOID *>(&pnccb));
  342. if (SUCCEEDED(hr))
  343. {
  344. hr = pnccb->SupportsBindingInterface(NCF_UPPER, c_szBiNdisAtm);
  345. if (S_OK == hr)
  346. {
  347. *pncms = NCSM_ATM;
  348. }
  349. pnccb->Release();
  350. }
  351. if (NCSM_ATM != *pncms)
  352. {
  353. // Not ATM
  354. PWSTR pszwCompId;
  355. hr = pnccAdapter->GetId(&pszwCompId);
  356. if (SUCCEEDED(hr))
  357. {
  358. if (0 == lstrcmpiW(c_szInfId_MS_AtmElan, pszwCompId))
  359. {
  360. // ATM Elan
  361. *pncms = NCSM_ELAN;
  362. }
  363. CoTaskMemFree(pszwCompId);
  364. }
  365. }
  366. if ( (FAILED(hrPhysicalMedia)) &&
  367. (NCSM_LAN == *pncms) )
  368. {
  369. // Couldn't determine anything specific from the bindings.
  370. // Return the hr from the Physical Media call if it was an error
  371. hr = hrPhysicalMedia;
  372. }
  373. }
  374. if (NCSM_LAN == *pncms)
  375. {
  376. // Could still be wireless... Check with Zero Config:
  377. if (IsMediaWireless(NCM_LAN, guid))
  378. {
  379. *pncms = NCSM_WIRELESS;
  380. }
  381. }
  382. }
  383. } // HrIsLanCapableAdapter SUCCEEDED
  384. } // guid == guidDev
  385. } // SUCCEEDED(pnccAdapter->GetInstanceGuid(&guidDev)
  386. else
  387. {
  388. AssertSz(FALSE, "Could not get instance GUID for Adapter");
  389. }
  390. pnccAdapter->Release();
  391. } // while loop
  392. HRESULT hrT = pNetCfg->Uninitialize();
  393. TraceError("INetCfg failed to uninitialize", hrT);
  394. } // SUCCEEDED(pNetConfig->Initialize(NULL))
  395. pNetCfg->Release();
  396. } // SUCCEEDED(CoCreateInstance(pNetCfg))
  397. else
  398. {
  399. AssertSz(FALSE, "Could not create INetCfg");
  400. }
  401. TraceErrorOptional("HrGetPseudoMediaTypes", hr, (S_FALSE == hr));
  402. return hr;
  403. }
  404. //+---------------------------------------------------------------------------
  405. //
  406. // Function: CIntelliName::GenerateName
  407. //
  408. // Purpose: Generate a name based on a hint
  409. //
  410. // Arguments:
  411. // guid [in] GUID of connection
  412. // ncm [in] NetCon Media Type of Connection
  413. // dwCharacteristics [in] NCCF_ Characteristics of Connection (Pass 0 if you don't know)
  414. // szHintName [in] Hint of name (will use as is if not conflicting)
  415. // szName [out] Resulting connection name - free with CoTaskMemFree
  416. //
  417. // Returns: HRESULT
  418. //
  419. // Author: deonb 27 Feb 2001
  420. //
  421. // Notes:
  422. //
  423. HRESULT CIntelliName::GenerateName(IN REFGUID guid,
  424. IN NETCON_MEDIATYPE ncm,
  425. IN DWORD dwCharacteristics,
  426. IN LPCWSTR szHint,
  427. OUT LPWSTR* szName) const
  428. {
  429. Assert(szName);
  430. *szName = NULL;
  431. HRESULT hr = S_OK;
  432. if (dwCharacteristics & NCCF_INCOMING_ONLY)
  433. {
  434. WCHAR szIncomingName[MAX_PATH];
  435. int nSiz = LoadString(m_hInstance, IDS_DEFAULT_IncomingName, szIncomingName, MAX_PATH);
  436. AssertSz(nSiz, "Resource string IDS_DEFAULT_IncomingName not found");
  437. if (nSiz)
  438. {
  439. hr = HrCoTaskMemAllocAndDupSz(szIncomingName, szName, NETCON_MAX_NAME_LEN);
  440. }
  441. else
  442. {
  443. hr = E_FAIL;
  444. }
  445. }
  446. else
  447. {
  448. switch (ncm)
  449. {
  450. case NCM_NONE:
  451. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_IncomingName, IDS_DEFAULT_IncomingName_Type, szName);
  452. break;
  453. case NCM_ISDN:
  454. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_ISDNName, IDS_DEFAULT_ISDNName_Type, szName);
  455. break;
  456. case NCM_DIRECT:
  457. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_DIRECTName, IDS_DEFAULT_DIRECTName_Type, szName);
  458. break;
  459. case NCM_PHONE:
  460. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_PHONEName, IDS_DEFAULT_PHONEName_Type, szName);
  461. break;
  462. case NCM_TUNNEL:
  463. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_VPNName, IDS_DEFAULT_VPNName_Type, szName);
  464. break;
  465. case NCM_PPPOE:
  466. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_PPPOEName, IDS_DEFAULT_PPPOEName_Type, szName);
  467. break;
  468. case NCM_BRIDGE:
  469. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_BRIDGEName, IDS_DEFAULT_BRIDGEName_Type, szName);
  470. break;
  471. case NCM_SHAREDACCESSHOST_LAN:
  472. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_SAHLANName, IDS_DEFAULT_SAHLANName_Type, szName);
  473. break;
  474. case NCM_SHAREDACCESSHOST_RAS:
  475. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_SAHRASName, IDS_DEFAULT_SAHRASName_Type, szName);
  476. break;
  477. case NCM_LAN:
  478. NETCON_MEDIATYPE ncmCheck;
  479. NETCON_SUBMEDIATYPE pncms;
  480. {
  481. DWORD dwRetries = 15;
  482. HRESULT hrT;
  483. do
  484. {
  485. hrT = HrGetPseudoMediaTypes(guid, &ncmCheck, &pncms);
  486. if (FAILED(hrT))
  487. {
  488. Sleep(500); // This is probably being called during device install, so give the adapter some
  489. // time to get itself enabled first.
  490. if (dwRetries > 1)
  491. {
  492. TraceTag(ttidError, "HrGetPseudoMediaTypes failed during device name initialization. Retrying...");
  493. }
  494. else
  495. {
  496. TraceTag(ttidError, "HrGetPseudoMediaTypes failed during device name initialization. Giving up.");
  497. }
  498. }
  499. } while (FAILED(hrT) && --dwRetries);
  500. if (SUCCEEDED(hrT))
  501. {
  502. AssertSz(ncmCheck == NCM_LAN, "This LAN adapter thinks it's something else");
  503. }
  504. else
  505. {
  506. pncms = NCSM_LAN; // If we run out of time, just give up and assume LAN.
  507. TraceTag(ttidError, "Could not determine the exact Media SubType for this adapter. Assuming LAN (and naming it such).");
  508. }
  509. switch (pncms)
  510. {
  511. case NCSM_NONE:
  512. AssertSz(FALSE, "LAN Connections should not be NCSM_NONE");
  513. hr = E_FAIL;
  514. break;
  515. case NCSM_LAN:
  516. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_LANName, IDS_DEFAULT_LANName_Type, szName);
  517. break;
  518. case NCSM_ATM:
  519. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_ATMName, IDS_DEFAULT_ATMName_Type, szName);
  520. break;
  521. case NCSM_ELAN:
  522. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_ELANName, IDS_DEFAULT_ELANName_Type, szName);
  523. break;
  524. case NCSM_WIRELESS:
  525. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_WirelessName, IDS_DEFAULT_WirelessName_Type, szName);
  526. break;
  527. case NCSM_1394:
  528. hr = GenerateNameFromResource(guid, ncm, dwCharacteristics, szHint, IDS_DEFAULT_1394Name, IDS_DEFAULT_1394Name_Type, szName);
  529. break;
  530. default:
  531. AssertSz(FALSE, "Unknown submedia type");
  532. hr = E_FAIL;
  533. break;
  534. }
  535. }
  536. break;
  537. default:
  538. AssertSz(FALSE, "Unknown media type");
  539. hr= E_FAIL;
  540. }
  541. }
  542. return hr;
  543. }
  544. //+---------------------------------------------------------------------------
  545. //
  546. // Function: OpenDevice
  547. //
  548. // Purpose: Open a Driver
  549. //
  550. // Arguments:
  551. // DeviceName [in] Name of device
  552. //
  553. // Returns: HANDLE of Device or NULL
  554. //
  555. // Author: deonb 27 Feb 2001
  556. //
  557. // Notes: Use GetLastError() for error info
  558. //
  559. HANDLE OpenDevice(IN PUNICODE_STRING DeviceName)
  560. {
  561. OBJECT_ATTRIBUTES ObjAttr;
  562. NTSTATUS Status;
  563. IO_STATUS_BLOCK IoStsBlk;
  564. HANDLE Handle;
  565. InitializeObjectAttributes(&ObjAttr, // Object
  566. DeviceName, // Object Name
  567. OBJ_CASE_INSENSITIVE, // Attributes
  568. NULL, // root directory
  569. NULL); // security descriptor
  570. Status = NtOpenFile(&Handle,
  571. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  572. &ObjAttr,
  573. &IoStsBlk,
  574. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  575. FILE_SYNCHRONOUS_IO_NONALERT);
  576. if (Status != STATUS_SUCCESS)
  577. {
  578. SetLastError(RtlNtStatusToDosError(Status));
  579. }
  580. return(Handle);
  581. }
  582. //+---------------------------------------------------------------------------
  583. //
  584. // Function: HrQueryDeviceOIDByName
  585. //
  586. // Purpose: Query an driver for an IOCTL & OID
  587. //
  588. // Arguments:
  589. // szDeviceName [in] Name of device
  590. // dwIoControlCode [in] Device IO Control code
  591. // Oid [in] OID to query for
  592. // pnSize [in out] pnSize - size of buffer, returns size filled into buffer
  593. // pBuffer [out] Buffer
  594. //
  595. // Returns: HRESULT
  596. //
  597. // Author: deonb 4 April 2001
  598. //
  599. // Notes:
  600. //
  601. HRESULT HrQueryDeviceOIDByName(IN LPCWSTR szDeviceName,
  602. IN DWORD dwIoControlCode,
  603. IN ULONG Oid,
  604. IN OUT LPDWORD pnSize,
  605. OUT LPVOID pbValue)
  606. {
  607. HRESULT hr = S_OK;
  608. NDIS_STATISTICS_VALUE StatsBuf;
  609. HANDLE hDevice;
  610. BOOL fResult = FALSE;
  611. UNICODE_STRING ustrDevice;
  612. ::RtlInitUnicodeString(&ustrDevice, szDeviceName);
  613. Assert(pbValue);
  614. ZeroMemory(pbValue, *pnSize);
  615. hDevice = OpenDevice(&ustrDevice);
  616. if (hDevice != NULL)
  617. {
  618. ULONG cb;
  619. DWORD dwStatsBufLen = sizeof(NDIS_STATISTICS_VALUE) - sizeof(UCHAR) + *pnSize;
  620. PNDIS_STATISTICS_VALUE pStatsBuf = reinterpret_cast<PNDIS_STATISTICS_VALUE>(new BYTE[dwStatsBufLen]);
  621. if (pStatsBuf)
  622. {
  623. fResult = DeviceIoControl(hDevice,
  624. dwIoControlCode, // IOCTL code
  625. &Oid, // input buffer
  626. sizeof(ULONG), // input buffer size
  627. pStatsBuf, // output buffer
  628. dwStatsBufLen, // output buffer size
  629. &cb, // bytes returned
  630. NULL); // OVERLAPPED structure
  631. if (fResult)
  632. {
  633. *pnSize = cb;
  634. if (0 == cb)
  635. {
  636. hr = S_FALSE;
  637. }
  638. else
  639. {
  640. if (pStatsBuf->DataLength > *pnSize)
  641. {
  642. AssertSz(FALSE, "Pass a larger buffer for this OID");
  643. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  644. *pnSize = 0;
  645. }
  646. else
  647. {
  648. memcpy(pbValue, &(pStatsBuf->Data), pStatsBuf->DataLength);
  649. }
  650. }
  651. }
  652. else
  653. {
  654. hr = HrFromLastWin32Error();
  655. }
  656. delete pStatsBuf;
  657. }
  658. else
  659. {
  660. hr = E_OUTOFMEMORY;
  661. }
  662. CloseHandle(hDevice);
  663. }
  664. else
  665. {
  666. hr = HrFromLastWin32Error();
  667. }
  668. TraceHr(ttidError, FAL, hr, S_FALSE == hr, "HrQueryDeviceOIDByName could not read the device properties for device %S", szDeviceName);
  669. return hr;
  670. }
  671. //+---------------------------------------------------------------------------
  672. //
  673. // Function: HrQueryNDISAdapterOID
  674. //
  675. // Purpose: Query an NDIS Driver for an OID
  676. //
  677. // Arguments:
  678. // guidId [in] Guid of device
  679. // Oid [in] OID to query for
  680. // pnSize [in out] pnSize - size of buffer, returns size filled into buffer
  681. // pbValue [out] Buffer
  682. //
  683. // Returns: HRESULT
  684. //
  685. // Author: deonb 4 April 2001
  686. //
  687. // Notes:
  688. //
  689. HRESULT HrQueryNDISAdapterOID(IN REFGUID guidId,
  690. IN NDIS_OID Oid,
  691. IN OUT LPDWORD pnSize,
  692. OUT LPVOID pbValue)
  693. {
  694. WCHAR szDeviceName[c_cchGuidWithTerm + celems(c_szDevice)];
  695. lstrcpynW(szDeviceName, c_szDevice, celems(szDeviceName) );
  696. ::StringFromGUID2(guidId, szDeviceName + (celems(c_szDevice)-1), c_cchGuidWithTerm);
  697. Assert(wcslen(szDeviceName) < c_cchGuidWithTerm + celems(c_szDevice));
  698. return HrQueryDeviceOIDByName(szDeviceName, IOCTL_NDIS_QUERY_SELECTED_STATS, Oid, pnSize, pbValue);
  699. }
  700. //+---------------------------------------------------------------------------
  701. //
  702. // Function: CIntelliName::IsMediaWireless
  703. //
  704. // Purpose: Queries a LAN Card to see if it's 802.1x
  705. //
  706. // Arguments:
  707. // ncm [in] Media type (if not NCM_LAN) function will return false
  708. // gdDevice [in] GUID of Network Card
  709. //
  710. // Returns: TRUE if WireLess, FALSE if not or error
  711. //
  712. // Author: deonb 27 Feb 2001
  713. //
  714. // Notes:
  715. //
  716. BOOL IsMediaWireless(IN NETCON_MEDIATYPE ncm,
  717. IN const GUID & gdDevice)
  718. {
  719. BOOL bRet;
  720. Assert(gdDevice != GUID_NULL);
  721. bRet = FALSE;
  722. // Prime the structure
  723. switch( ncm )
  724. {
  725. case NCM_LAN:
  726. INTF_ENTRY intfEntry;
  727. ZeroMemory(&intfEntry, sizeof(INTF_ENTRY));
  728. LPOLESTR lpszClsId = NULL;
  729. HRESULT hr = StringFromCLSID(gdDevice, &lpszClsId);
  730. if (S_OK == hr)
  731. {
  732. intfEntry.wszGuid = lpszClsId;
  733. DWORD dwErr = WZCQueryInterface(NULL, INTF_OIDSSUPP, &intfEntry, NULL);
  734. hr = HRESULT_FROM_WIN32(dwErr);
  735. if (S_OK == hr)
  736. {
  737. if (intfEntry.dwCtlFlags & INTFCTL_OIDSSUPP)
  738. {
  739. bRet = TRUE;
  740. }
  741. }
  742. CoTaskMemFree(lpszClsId);
  743. }
  744. TraceErrorOptional("IsMediaWireless failed with", hr, (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) );
  745. }
  746. return bRet;
  747. }
  748. //+---------------------------------------------------------------------------
  749. //
  750. // Function: CIntelliName::IsMedia1394
  751. //
  752. // Purpose: Queries a LAN Card to see if it's 1394 (FireWire / iLink)
  753. //
  754. // Arguments:
  755. // ncm [in] Media type (if not NCM_LAN) function will return false
  756. // gdDevice [in] GUID of Network Card
  757. //
  758. // Returns: TRUE if WireLess, FALSE if not or error
  759. //
  760. // Author: deonb 27 Feb 2001
  761. //
  762. // Notes:
  763. //
  764. BOOL IsMedia1394(IN NETCON_MEDIATYPE ncm,
  765. IN const GUID & gdDevice)
  766. {
  767. BOOL bRet;
  768. Assert(gdDevice != GUID_NULL);
  769. bRet = FALSE;
  770. // Prime the structure
  771. switch( ncm )
  772. {
  773. case NCM_LAN:
  774. // Retrieve the statistics
  775. DWORD dwMediaType;
  776. DWORD dwMediaTypeSize = sizeof(DWORD);
  777. HRESULT hr = HrQueryNDISAdapterOID(gdDevice,
  778. OID_GEN_PHYSICAL_MEDIUM,
  779. &dwMediaTypeSize,
  780. &dwMediaType);
  781. if (SUCCEEDED(hr))
  782. {
  783. bRet = (dwMediaType == NdisPhysicalMedium1394);
  784. }
  785. }
  786. return bRet;
  787. }