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.

470 lines
11 KiB

  1. /************************************************************************
  2. * *
  3. * ports.c -- port api's for mprapi.dll *
  4. * *
  5. * Copyright (c) 1991-1999, Microsoft Corp. All rights reserved. *
  6. * *
  7. ************************************************************************/
  8. #include <nt.h>
  9. #include <ntrtl.h>
  10. #include <nturtl.h>
  11. #include <windows.h>
  12. #include <mprapi.h>
  13. #include <mprapip.h>
  14. #include <stdio.h>
  15. // Constants in the registry
  16. //
  17. static const WCHAR pszRegkeyNetAdapters[] =
  18. L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
  19. static const WCHAR pszRegkeyModems[] =
  20. L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E96D-E325-11CE-BFC1-08002BE10318}";
  21. static const WCHAR pszRegkeyMdmconfig[] =
  22. L"Clients\\Ras";
  23. static const WCHAR pszRegvalDialinUsage[] = L"EnableForRas";
  24. static const WCHAR pszRegvalRouterUsage[] = L"EnableForRouting";
  25. static const WCHAR pszWanEndpoints[] = L"WanEndpoints";
  26. //
  27. // Definitions that specify what registry key is being enumerated
  28. //
  29. #define MPRPORT_F_Adapters 1
  30. #define MPRPORT_F_Modems 2
  31. //
  32. // Callback definition for function that will have ras ports
  33. // enumerated to it.
  34. //
  35. typedef
  36. DWORD
  37. (* RTRUPG_PORT_ENUM_FUNC)(
  38. IN HKEY hkPort,
  39. IN HANDLE hData);
  40. //
  41. // Defines data provided to the PortGetConfigKey function
  42. //
  43. typedef struct _PORTGETCONFIGKEYDATA
  44. {
  45. DWORD dwRootId; // See PORT_REGKEY_* values
  46. RTRUPG_PORT_ENUM_FUNC pEnum; // cb provided to PortEnumPorts
  47. HANDLE hData; // data provided to PortEnumPorts
  48. } PORTGETCONFIGKEYDATA;
  49. //
  50. // Typedef for callback functions for enumerating registry sub keys.
  51. // Return NO_ERROR to continue, error code to stop.
  52. //
  53. // See PortEnumRegistrySubKeys.
  54. //
  55. typedef
  56. DWORD
  57. (*REG_KEY_ENUM_FUNC_PTR)(
  58. IN PWCHAR pszName, // sub key name
  59. IN HKEY hKey, // sub key
  60. IN HANDLE hData);
  61. //
  62. // Sends debug trace
  63. //
  64. DWORD
  65. PortTrace(
  66. IN LPSTR pszTrace, ...)
  67. {
  68. #if DBG
  69. va_list arglist;
  70. char szBuffer[1024], szTemp[1024];
  71. va_start(arglist, pszTrace);
  72. vsprintf(szTemp, pszTrace, arglist);
  73. va_end(arglist);
  74. sprintf(szBuffer, "MprPort: %s\n", szTemp);
  75. OutputDebugStringA(szBuffer);
  76. #endif
  77. return NO_ERROR;
  78. }
  79. //
  80. // Allocation routine for port functions
  81. //
  82. PVOID
  83. PortAlloc (
  84. IN DWORD dwSize,
  85. IN BOOL bZero)
  86. {
  87. return LocalAlloc ((bZero) ? LPTR : LMEM_FIXED, dwSize);
  88. }
  89. //
  90. // Free routine for port functions
  91. //
  92. VOID
  93. PortFree (
  94. IN PVOID pvData)
  95. {
  96. LocalFree (pvData);
  97. }
  98. //
  99. // Enumerates all of the registry subkeys of a given key
  100. //
  101. DWORD
  102. PortEnumRegistrySubKeys(
  103. IN HKEY hkRoot,
  104. IN PWCHAR pszPath,
  105. IN REG_KEY_ENUM_FUNC_PTR pCallback,
  106. IN HANDLE hData)
  107. {
  108. DWORD dwErr = NO_ERROR, i, dwNameSize = 0, dwCurSize = 0;
  109. DWORD dwCount = 0;
  110. HKEY hkKey = NULL, hkCurKey = NULL;
  111. PWCHAR pszName = NULL;
  112. BOOL bCloseKey = FALSE;
  113. do
  114. {
  115. if (pszPath)
  116. {
  117. bCloseKey = TRUE;
  118. // Open the key to enumerate
  119. //
  120. dwErr = RegOpenKeyExW(
  121. hkRoot,
  122. pszPath,
  123. 0,
  124. KEY_ALL_ACCESS,
  125. &hkKey);
  126. if (dwErr != NO_ERROR)
  127. {
  128. break;
  129. }
  130. }
  131. else
  132. {
  133. bCloseKey = FALSE;
  134. hkKey = hkRoot;
  135. }
  136. // Find out how many sub keys there are
  137. //
  138. dwErr = RegQueryInfoKeyW(
  139. hkKey,
  140. NULL,
  141. NULL,
  142. NULL,
  143. &dwCount,
  144. &dwNameSize,
  145. NULL,
  146. NULL,
  147. NULL,
  148. NULL,
  149. NULL,
  150. NULL);
  151. if (dwErr != ERROR_SUCCESS)
  152. {
  153. return dwErr;
  154. }
  155. dwNameSize++;
  156. // Allocate the name buffer
  157. //
  158. pszName = (PWCHAR) PortAlloc(dwNameSize * sizeof(WCHAR), TRUE);
  159. if (pszName == NULL)
  160. {
  161. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  162. break;
  163. }
  164. // Loop through the keys
  165. //
  166. for (i = 0; i < dwCount; i++)
  167. {
  168. dwCurSize = dwNameSize;
  169. // Get the name of the current key
  170. //
  171. dwErr = RegEnumKeyExW(
  172. hkKey,
  173. i,
  174. pszName,
  175. &dwCurSize,
  176. 0,
  177. NULL,
  178. NULL,
  179. NULL);
  180. if (dwErr != ERROR_SUCCESS)
  181. {
  182. continue;
  183. }
  184. // Open the subkey
  185. //
  186. dwErr = RegOpenKeyExW(
  187. hkKey,
  188. pszName,
  189. 0,
  190. KEY_ALL_ACCESS,
  191. &hkCurKey);
  192. if (dwErr != ERROR_SUCCESS)
  193. {
  194. continue;
  195. }
  196. // Call the callback
  197. //
  198. dwErr = pCallback(pszName, hkCurKey, hData);
  199. RegCloseKey(hkCurKey);
  200. if (dwErr != NO_ERROR)
  201. {
  202. break;
  203. }
  204. }
  205. } while (FALSE);
  206. // Cleanup
  207. {
  208. if ((hkKey != NULL) && (bCloseKey))
  209. {
  210. RegCloseKey(hkKey);
  211. }
  212. if (pszName)
  213. {
  214. PortFree(pszName);
  215. }
  216. }
  217. return dwErr;
  218. }
  219. //
  220. // Sets the usage of the given port
  221. //
  222. DWORD
  223. PortSetUsage(
  224. IN HKEY hkPort,
  225. IN HANDLE hData)
  226. {
  227. DWORD dwErr = NO_ERROR, dwOne = 1;
  228. DWORD dwUsage = *((DWORD*)hData);
  229. PWCHAR pszVal = NULL;
  230. do
  231. {
  232. // Determine which value to set
  233. //
  234. if (dwUsage & MPRFLAG_PORT_Router)
  235. {
  236. pszVal = (PWCHAR)pszRegvalRouterUsage;
  237. }
  238. else if (dwUsage & MPRFLAG_PORT_Dialin)
  239. {
  240. pszVal = (PWCHAR)pszRegvalDialinUsage;
  241. }
  242. else
  243. {
  244. dwErr = ERROR_CAN_NOT_COMPLETE;
  245. break;
  246. }
  247. PortTrace("PortSetUsage: Setting: %ls", pszVal);
  248. // Set the value
  249. //
  250. dwErr = RegSetValueExW(
  251. hkPort,
  252. pszVal,
  253. 0,
  254. REG_DWORD,
  255. (BYTE*)&dwOne,
  256. sizeof(dwOne));
  257. if (dwErr != NO_ERROR)
  258. {
  259. break;
  260. }
  261. } while (FALSE);
  262. // Cleanup
  263. {
  264. }
  265. return dwErr;
  266. }
  267. //
  268. // Callback function for PortEnumRegistrySubKeys that finds the
  269. // key in the registry suitable to have its port usage manipulated.
  270. //
  271. DWORD
  272. PortGetConfigKey(
  273. IN PWCHAR pszName, // sub key name
  274. IN HKEY hKey, // sub key
  275. IN HANDLE hData)
  276. {
  277. PORTGETCONFIGKEYDATA* pData = (PORTGETCONFIGKEYDATA*)hData;
  278. HKEY hkChild = NULL;
  279. DWORD dwErr = NO_ERROR;
  280. PortTrace("PortGetConfigKey: Entered: %ls", pszName);
  281. switch (pData->dwRootId)
  282. {
  283. case MPRPORT_F_Adapters:
  284. {
  285. // We only want devices with WanEndPoints, otherwise
  286. // they aren't ras capable.
  287. //
  288. dwErr = RegQueryValueExW(
  289. hKey,
  290. (PWCHAR) pszWanEndpoints,
  291. NULL,
  292. NULL,
  293. NULL,
  294. NULL);
  295. if (dwErr != ERROR_SUCCESS)
  296. {
  297. dwErr = NO_ERROR;
  298. break;
  299. }
  300. // Call the callback.
  301. pData->pEnum(hKey, pData->hData);
  302. }
  303. break;
  304. case MPRPORT_F_Modems:
  305. {
  306. DWORD dwDisposition;
  307. // Open the appropriate child key
  308. //
  309. dwErr = RegCreateKeyEx(
  310. hKey,
  311. pszRegkeyMdmconfig,
  312. 0,
  313. NULL,
  314. REG_OPTION_NON_VOLATILE,
  315. KEY_ALL_ACCESS,
  316. NULL,
  317. &hkChild,
  318. &dwDisposition);
  319. if (dwErr != ERROR_SUCCESS)
  320. {
  321. dwErr = NO_ERROR;
  322. break;
  323. }
  324. // Call the callback
  325. pData->pEnum(hkChild, pData->hData);
  326. }
  327. break;
  328. }
  329. // Cleanup
  330. {
  331. if (hkChild)
  332. {
  333. RegCloseKey(hkChild);
  334. }
  335. }
  336. return dwErr;
  337. }
  338. //
  339. // Enumerates all ports
  340. //
  341. DWORD
  342. PortEnumPorts(
  343. IN RTRUPG_PORT_ENUM_FUNC pEnum,
  344. IN DWORD dwPortFlags,
  345. IN HANDLE hData)
  346. {
  347. DWORD dwErr = NO_ERROR;
  348. PORTGETCONFIGKEYDATA PortData, *pData = &PortData;
  349. PortTrace("PortEnumPorts entered");
  350. do
  351. {
  352. // Initialize
  353. ZeroMemory(pData, sizeof(PORTGETCONFIGKEYDATA));
  354. pData->pEnum = pEnum;
  355. pData->hData = hData;
  356. if (dwPortFlags & MPRPORT_F_Adapters)
  357. {
  358. // Set usage on the network adapters (pptp, l2tp will have
  359. // their port usages set through this)
  360. //
  361. PortTrace("PortEnumPorts: Enumerating adapters:");
  362. pData->dwRootId = MPRPORT_F_Adapters;
  363. dwErr = PortEnumRegistrySubKeys(
  364. HKEY_LOCAL_MACHINE,
  365. (PWCHAR)pszRegkeyNetAdapters,
  366. PortGetConfigKey,
  367. (HANDLE)pData);
  368. if (dwErr != NO_ERROR)
  369. {
  370. break;
  371. }
  372. }
  373. if (dwPortFlags & MPRPORT_F_Modems)
  374. {
  375. // Set usage on modem devices
  376. //
  377. PortTrace("PortEnumPorts: Enumerating modems:");
  378. pData->dwRootId = MPRPORT_F_Modems;
  379. dwErr = PortEnumRegistrySubKeys(
  380. HKEY_LOCAL_MACHINE,
  381. (PWCHAR)pszRegkeyModems,
  382. PortGetConfigKey,
  383. (HANDLE)pData);
  384. if (dwErr != NO_ERROR)
  385. {
  386. break;
  387. }
  388. }
  389. } while (FALSE);
  390. // Cleanup
  391. {
  392. }
  393. return dwErr;
  394. }
  395. //
  396. // Sets all ports on the machine to the given usage
  397. //
  398. DWORD
  399. APIENTRY
  400. MprPortSetUsage(
  401. IN DWORD dwUsage)
  402. {
  403. DWORD dwPortFlags = MPRPORT_F_Adapters | MPRPORT_F_Modems;
  404. if (dwUsage == MPRFLAG_PORT_NonVpnDialin)
  405. {
  406. dwPortFlags = MPRPORT_F_Modems;
  407. dwUsage = MPRFLAG_PORT_Dialin;
  408. }
  409. return PortEnumPorts(PortSetUsage, dwPortFlags, (HANDLE)&dwUsage);
  410. }