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.

505 lines
13 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2001.
  5. //
  6. // File: T R Y T O F I X . C P P
  7. //
  8. // Contents: Code for the "repair" command
  9. //
  10. // Notes:
  11. //
  12. // Author: nsun Jan 2001
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "wzcsapi.h"
  18. #include "nsbase.h"
  19. #include "ncstring.h"
  20. #include "nsres.h"
  21. #include "ncperms.h"
  22. #include "ncnetcon.h"
  23. #include "repair.h"
  24. extern "C"
  25. {
  26. #include <dhcpcapi.h>
  27. extern DWORD DhcpStaticRefreshParams(IN LPWSTR Adapter);
  28. extern DWORD DhcpAcquireParametersByBroadcast(IN LPWSTR AdapterName);
  29. }
  30. #include <dnsapi.h>
  31. #include "nbtioctl.h"
  32. HRESULT HrGetAdapterSettings(LPCWSTR pszGuid, BOOL * pfDhcp, DWORD * pdwIndex);
  33. HRESULT PurgeNbt(HANDLE NbtHandle);
  34. HRESULT ReleaseRefreshNetBt(HANDLE NbtHandle);
  35. //+---------------------------------------------------------------------------
  36. //
  37. // Function: HrTryToFix
  38. //
  39. // Purpose: Do the fix
  40. //
  41. // Arguments:
  42. // guidConnection [in] guid of the connection to fix
  43. // strMessage [out] the message containing the results
  44. //
  45. // Returns:
  46. // S_OK succeeded
  47. // S_FALSE some fix operation failed
  48. //
  49. HRESULT HrTryToFix(GUID & guidConnection, tstring & strMessage)
  50. {
  51. HRESULT hr = S_OK;
  52. DWORD dwRet = ERROR_SUCCESS;
  53. BOOL fRet = TRUE;
  54. WCHAR wszGuid[c_cchGuidWithTerm] = {0};
  55. tstring strFailures = L"";
  56. strMessage = L"";
  57. ::StringFromGUID2(guidConnection,
  58. wszGuid,
  59. c_cchGuidWithTerm);
  60. BOOL fDhcp = FALSE;
  61. DWORD dwIfIndex = 0;
  62. //re-autheticate for 802.1X. This is a asynchronous call and there is
  63. //no meaningful return value. So ignore the return value
  64. WZCEapolReAuthenticate(NULL, wszGuid);
  65. //only do the fix when TCP/IP is enabled for this connection
  66. //also get the interface index that is needed when flushing Arp table
  67. hr = HrGetAdapterSettings(wszGuid, &fDhcp, &dwIfIndex);
  68. if (FAILED(hr))
  69. {
  70. strMessage = SzLoadIds((HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) ?
  71. IDS_FIX_NO_TCP : IDS_FIX_TCP_FAIL);
  72. return S_FALSE;
  73. }
  74. //renew the lease if DHCP is enabled
  75. if (fDhcp)
  76. {
  77. dwRet = DhcpAcquireParametersByBroadcast(wszGuid);
  78. if (ERROR_SUCCESS != dwRet)
  79. {
  80. TraceError("DhcpAcquireParametersByBroadcast", HRESULT_FROM_WIN32(dwRet));
  81. strFailures += SzLoadIds(IDS_FIX_ERR_RENEW_DHCP);
  82. hr = S_FALSE;
  83. }
  84. }
  85. //purge the ARP table if the user is admin or Netcfg Ops
  86. //Other user are not allowed to do this
  87. if (FIsUserAdmin() || FIsUserNetworkConfigOps())
  88. {
  89. dwRet = FlushIpNetTable(dwIfIndex);
  90. if (NO_ERROR != dwRet)
  91. {
  92. TraceError("FlushIpNetTable", HRESULT_FROM_WIN32(dwRet));
  93. strFailures += SzLoadIds(IDS_FIX_ERR_FLUSH_ARP);
  94. hr = S_FALSE;
  95. }
  96. }
  97. //puge the NetBT table and Renew name registration
  98. HANDLE NbtHandle = INVALID_HANDLE_VALUE;
  99. if (SUCCEEDED(OpenNbt(wszGuid, &NbtHandle)))
  100. {
  101. if (FAILED(PurgeNbt(NbtHandle)))
  102. {
  103. strFailures += SzLoadIds(IDS_FIX_ERR_PURGE_NBT);
  104. hr = S_FALSE;
  105. }
  106. if (FAILED(ReleaseRefreshNetBt(NbtHandle)))
  107. {
  108. strFailures += SzLoadIds(IDS_FIX_ERR_RR_NBT);
  109. hr = S_FALSE;
  110. }
  111. NtClose(NbtHandle);
  112. NbtHandle = INVALID_HANDLE_VALUE;
  113. }
  114. else
  115. {
  116. strFailures += SzLoadIds(IDS_FIX_ERR_PURGE_NBT);
  117. strFailures += SzLoadIds(IDS_FIX_ERR_RR_NBT);
  118. hr = S_FALSE;
  119. }
  120. //flush DNS cache
  121. fRet = DnsFlushResolverCache();
  122. if (!fRet)
  123. {
  124. strFailures += SzLoadIds(IDS_FIX_ERR_FLUSH_DNS);
  125. hr = S_FALSE;
  126. }
  127. //re-register DNS name
  128. dwRet = DhcpStaticRefreshParams(NULL);
  129. if (ERROR_SUCCESS != dwRet)
  130. {
  131. strFailures += SzLoadIds(IDS_FIX_ERR_REG_DNS);
  132. hr = S_FALSE;
  133. }
  134. if (S_OK == hr)
  135. {
  136. strMessage = SzLoadIds(IDS_FIX_SUCCEED);
  137. }
  138. else
  139. {
  140. PCWSTR pszFormat = SzLoadIds(IDS_FIX_ERROR_FORMAT);
  141. PWSTR pszText = NULL;
  142. LPCWSTR pcszFailures = strFailures.c_str();
  143. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  144. pszFormat, 0, 0, (PWSTR)&pszText, 0, (va_list *)&pcszFailures);
  145. if (pszText)
  146. {
  147. strMessage = pszText;
  148. LocalFree(pszText);
  149. }
  150. else
  151. {
  152. strMessage = SzLoadIds(IDS_FIX_ERROR);
  153. }
  154. }
  155. return hr;
  156. }
  157. //+---------------------------------------------------------------------------
  158. //
  159. // Function: OpenNbt
  160. //
  161. // Purpose: Open the NetBT driver
  162. //
  163. // Arguments:
  164. // pwszGuid [in] guid of the adapter
  165. // pHandle [out] contains the handle of the Netbt driver
  166. //
  167. // Returns:
  168. //
  169. HRESULT OpenNbt(
  170. LPWSTR pwszGuid,
  171. HANDLE * pHandle)
  172. {
  173. const WCHAR c_szNbtDevicePrefix[] = L"\\Device\\NetBT_Tcpip_";
  174. HRESULT hr = S_OK;
  175. tstring strDevice;
  176. HANDLE StreamHandle = NULL;
  177. OBJECT_ATTRIBUTES ObjectAttributes;
  178. IO_STATUS_BLOCK IoStatusBlock;
  179. UNICODE_STRING uc_name_string;
  180. NTSTATUS status;
  181. Assert(pHandle);
  182. Assert(pwszGuid);
  183. strDevice = c_szNbtDevicePrefix;
  184. strDevice += pwszGuid;
  185. RtlInitUnicodeString(&uc_name_string, strDevice.c_str());
  186. InitializeObjectAttributes (&ObjectAttributes,
  187. &uc_name_string,
  188. OBJ_CASE_INSENSITIVE,
  189. (HANDLE) NULL,
  190. (PSECURITY_DESCRIPTOR) NULL);
  191. status = NtCreateFile (&StreamHandle,
  192. SYNCHRONIZE | GENERIC_EXECUTE,
  193. &ObjectAttributes,
  194. &IoStatusBlock,
  195. NULL,
  196. FILE_ATTRIBUTE_NORMAL,
  197. FILE_SHARE_READ | FILE_SHARE_WRITE,
  198. FILE_OPEN_IF,
  199. 0,
  200. NULL,
  201. 0);
  202. if (NT_SUCCESS(status))
  203. {
  204. *pHandle = StreamHandle;
  205. }
  206. else
  207. {
  208. *pHandle = INVALID_HANDLE_VALUE;
  209. hr = E_FAIL;
  210. }
  211. TraceError("OpenNbt", hr);
  212. return hr;
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // Function: PurgeNbt
  217. //
  218. // Purpose: Purge the NetBt cache
  219. //
  220. // Arguments: NbtHandle [in] handle of the Netbt driver
  221. //
  222. // Returns:
  223. //
  224. HRESULT PurgeNbt(HANDLE NbtHandle)
  225. {
  226. HRESULT hr = S_OK;
  227. CHAR Buffer = 0;
  228. DWORD dwBytesOut = 0;
  229. if (!DeviceIoControl(NbtHandle,
  230. IOCTL_NETBT_PURGE_CACHE,
  231. NULL,
  232. 0,
  233. &Buffer,
  234. 1,
  235. &dwBytesOut,
  236. NULL))
  237. {
  238. hr = HRESULT_FROM_WIN32(GetLastError());
  239. }
  240. TraceError("PurgeNbt", hr);
  241. return hr;
  242. }
  243. //+---------------------------------------------------------------------------
  244. //
  245. // Function: ReleaseRefreshNetBt
  246. //
  247. // Purpose: release and then refresh the name on the WINS server
  248. //
  249. // Arguments: NbtHandle [in] handle of the Netbt driver
  250. //
  251. // Returns:
  252. //
  253. HRESULT ReleaseRefreshNetBt(HANDLE NbtHandle)
  254. {
  255. HRESULT hr = S_OK;
  256. CHAR Buffer = 0;
  257. DWORD dwBytesOut = 0;
  258. if (!DeviceIoControl(NbtHandle,
  259. IOCTL_NETBT_NAME_RELEASE_REFRESH,
  260. NULL,
  261. 0,
  262. &Buffer,
  263. 1,
  264. &dwBytesOut,
  265. NULL))
  266. {
  267. DWORD dwErr = GetLastError();
  268. //RELEASE_REFRESH can at most do every two minutes
  269. //So if the user perform 2 RELEASE_REFRESH within 2 minutes, the 2nd
  270. //one will fail with ERROR_SEM_TIMEOUT. We ignore this particular error
  271. if (ERROR_SEM_TIMEOUT != dwErr)
  272. {
  273. hr = HRESULT_FROM_WIN32(dwErr);
  274. }
  275. }
  276. TraceError("ReleaseRefreshNetBt", hr);
  277. return hr;
  278. }
  279. //+---------------------------------------------------------------------------
  280. //
  281. // Function: HrGetAdapterSettings
  282. //
  283. // Purpose: Query the stack to know whether dhcp is enabled
  284. //
  285. // Arguments: pszGuid [in] guid of the adapter
  286. // pfDhcp [out] contains whether dhcp is enabled
  287. // pdwIndex [out] contains the index of this adapter
  288. //
  289. // Returns:
  290. //
  291. HRESULT HrGetAdapterSettings(LPCWSTR pszGuid, BOOL * pfDhcp, DWORD * pdwIndex)
  292. {
  293. HRESULT hr = S_OK;
  294. PIP_ADAPTER_INFO pAdapterInfo = NULL;
  295. DWORD dwOutBufLen = 0;
  296. DWORD dwRet = ERROR_SUCCESS;
  297. Assert(pfDhcp);
  298. Assert(pszGuid);
  299. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  300. if (dwRet == ERROR_BUFFER_OVERFLOW)
  301. {
  302. pAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc(dwOutBufLen);
  303. if (NULL == pAdapterInfo)
  304. return E_OUTOFMEMORY;
  305. }
  306. else if (ERROR_SUCCESS == dwRet)
  307. {
  308. return E_FAIL;
  309. }
  310. else
  311. {
  312. return HRESULT_FROM_WIN32(dwRet);
  313. }
  314. dwRet = GetAdaptersInfo(pAdapterInfo, &dwOutBufLen);
  315. if (ERROR_SUCCESS != dwRet)
  316. {
  317. CoTaskMemFree(pAdapterInfo);
  318. return HRESULT_FROM_WIN32(dwRet);
  319. }
  320. BOOL fFound = FALSE;
  321. PIP_ADAPTER_INFO pAdapterInfoEnum = pAdapterInfo;
  322. while (pAdapterInfoEnum)
  323. {
  324. USES_CONVERSION;
  325. if (lstrcmp(pszGuid, A2W(pAdapterInfoEnum->AdapterName)) == 0)
  326. {
  327. if (pdwIndex)
  328. {
  329. *pdwIndex = pAdapterInfoEnum->Index;
  330. }
  331. *pfDhcp = pAdapterInfoEnum->DhcpEnabled;
  332. fFound = TRUE;
  333. break;
  334. }
  335. pAdapterInfoEnum = pAdapterInfoEnum->Next;
  336. }
  337. CoTaskMemFree(pAdapterInfo);
  338. if (!fFound)
  339. {
  340. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  341. }
  342. return hr;
  343. }
  344. HRESULT RepairConnectionInternal(
  345. GUID & guidConnection,
  346. LPWSTR * ppszMessage)
  347. {
  348. if (NULL != ppszMessage &&
  349. IsBadWritePtr(ppszMessage, sizeof(LPWSTR)))
  350. {
  351. return E_INVALIDARG;
  352. }
  353. if (ppszMessage)
  354. {
  355. *ppszMessage = NULL;
  356. }
  357. if (!FHasPermission(NCPERM_Repair))
  358. {
  359. return E_ACCESSDENIED;
  360. }
  361. // Get the net connection manager
  362. CComPtr<INetConnectionManager> spConnMan;
  363. HRESULT hr = S_OK;
  364. hr = CoCreateInstance(CLSID_ConnectionManager, NULL,
  365. CLSCTX_ALL,
  366. IID_INetConnectionManager,
  367. (LPVOID *)&spConnMan);
  368. if (FAILED(hr))
  369. {
  370. return hr;
  371. }
  372. Assert(spConnMan.p);
  373. NcSetProxyBlanket(spConnMan);
  374. CComPtr<IEnumNetConnection> spEnum;
  375. hr = spConnMan->EnumConnections(NCME_DEFAULT, &spEnum);
  376. spConnMan = NULL;
  377. if (FAILED(hr))
  378. {
  379. return hr;
  380. }
  381. Assert(spEnum.p);
  382. BOOL fFound = FALSE;
  383. ULONG ulCount = 0;
  384. INetConnection * pConn = NULL;
  385. spEnum->Reset();
  386. do
  387. {
  388. NETCON_PROPERTIES* pProps = NULL;
  389. hr = spEnum->Next(1, &pConn, &ulCount);
  390. if (SUCCEEDED(hr) && 1 == ulCount)
  391. {
  392. NcSetProxyBlanket(pConn);
  393. hr = pConn->GetProperties(&pProps);
  394. if (S_OK == hr)
  395. {
  396. if (IsEqualGUID(pProps->guidId, guidConnection))
  397. {
  398. fFound = TRUE;
  399. //we only support LAN and Bridge adapters
  400. if (NCM_LAN != pProps->MediaType && NCM_BRIDGE != pProps->MediaType)
  401. {
  402. hr = CO_E_NOT_SUPPORTED;
  403. }
  404. break;
  405. }
  406. FreeNetconProperties(pProps);
  407. }
  408. pConn->Release();
  409. pConn = NULL;
  410. }
  411. }while (SUCCEEDED(hr) && 1 == ulCount);
  412. if (!fFound)
  413. {
  414. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  415. }
  416. if (FAILED(hr))
  417. {
  418. return hr;
  419. }
  420. LPWSTR psz = NULL;
  421. tstring strMessage;
  422. hr = HrTryToFix(guidConnection, strMessage);
  423. if (ppszMessage && S_OK != hr && strMessage.length())
  424. {
  425. psz = (LPWSTR) LocalAlloc(LPTR, (strMessage.length() + 1) * sizeof(WCHAR));
  426. lstrcpy(psz, strMessage.c_str());
  427. *ppszMessage = psz;
  428. }
  429. return hr;
  430. }