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.

3942 lines
108 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. ntip.c
  5. Abstract:
  6. NT specific routines for loading and configuring the IP driver.
  7. Author:
  8. Mike Massa (mikemas) Aug 13, 1993
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 08-13-93 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #include "iproute.h"
  17. #include "lookup.h"
  18. #include "iprtdef.h"
  19. #include "internaldef.h"
  20. #include "tcp.h"
  21. #include "tcpipbuf.h"
  22. #include "mdlpool.h"
  23. //
  24. // definitions needed by inet_addr.
  25. //
  26. #define INADDR_NONE 0xffffffff
  27. #define INADDR_ANY 0
  28. #define htonl(x) net_long(x)
  29. //
  30. // Other local constants
  31. //
  32. #define WORK_BUFFER_SIZE 256
  33. // size of nte context value in string form
  34. #define NTE_CONTEXT_SIZE (sizeof(uint)*2+2) // 0xAABBCCDD
  35. //
  36. // Configuration defaults
  37. //
  38. #define DEFAULT_IGMP_LEVEL 2
  39. #define DEFAULT_IP_NETS 8
  40. #if MILLEN
  41. // On Win9x, this will help boot time and resume time.
  42. #define DEFAULT_ARPRETRY_COUNT 1
  43. #else // MILLEN
  44. #define DEFAULT_ARPRETRY_COUNT 3
  45. #endif // !MILLEN
  46. //
  47. // Local types
  48. //
  49. typedef struct _PerNetConfigInfo {
  50. uint UseZeroBroadcast;
  51. uint Mtu;
  52. uint NumberOfGateways;
  53. uint MaxForwardPending; // max routing packets pending
  54. } PER_NET_CONFIG_INFO, *PPER_NET_CONFIG_INFO;
  55. //
  56. // Global variables.
  57. //
  58. PDRIVER_OBJECT IPDriverObject;
  59. PDEVICE_OBJECT IPDeviceObject;
  60. HANDLE IPProviderHandle = NULL;
  61. #if IPMCAST
  62. PDEVICE_OBJECT IpMcastDeviceObject;
  63. NTSTATUS
  64. InitializeIpMcast(
  65. IN PDRIVER_OBJECT DriverObject,
  66. IN PUNICODE_STRING RegistryPath,
  67. OUT PDEVICE_OBJECT * ppIpMcastDevice
  68. );
  69. VOID
  70. DeinitializeIpMcast(
  71. IN PDEVICE_OBJECT DeviceObject
  72. );
  73. #endif // IPMCAST
  74. IPConfigInfo *IPConfiguration;
  75. uint ArpUseEtherSnap = FALSE;
  76. uint ArpAlwaysSourceRoute = FALSE;
  77. uint IPAlwaysSourceRoute = TRUE;
  78. extern uint DisableIPSourceRouting;
  79. uint ArpCacheLife = DEFAULT_ARP_CACHE_LIFE;
  80. uint ArpRetryCount = DEFAULT_ARPRETRY_COUNT;
  81. uint ArpMinValidCacheLife = DEFAULT_ARP_MIN_VALID_CACHE_LIFE;
  82. uint DisableMediaSense = 0;
  83. uint DisableMediaSenseEventLog;
  84. uint EnableBcastArpReply = TRUE;
  85. #if MILLEN
  86. // Millennium does not support task offload.
  87. uint DisableTaskOffload = TRUE;
  88. #else // MILLEN
  89. uint DisableTaskOffload = FALSE;
  90. #endif // !MILLEN
  91. uint DisableUserTOS = TRUE;
  92. extern uint MaxRH;
  93. extern uint NET_TABLE_SIZE;
  94. extern uint DampingInterval;
  95. extern uint ConnectDampingInterval;
  96. // Used in the conversion of 100ns times to milliseconds.
  97. static LARGE_INTEGER Magic10000 =
  98. {0xe219652c, 0xd1b71758};
  99. //
  100. // External variables
  101. //
  102. extern LIST_ENTRY PendingEchoList; // def needed for initialization
  103. extern LIST_ENTRY PendingIPSetNTEAddrList; // def needed for initialization
  104. extern LIST_ENTRY PendingIPEventList; // def needed for initialization
  105. extern LIST_ENTRY PendingEnableRouterList; // def needed for initialization
  106. extern LIST_ENTRY PendingArpSendList; // def needed for initialization
  107. extern LIST_ENTRY PendingMediaSenseRequestList;
  108. CTEBlockStruc TcpipUnloadBlock; // Structure for blocking at time of unload
  109. extern CACHE_LINE_KSPIN_LOCK ArpInterfaceListLock;
  110. BOOLEAN fRouteTimerStopping = FALSE;
  111. extern CTETimer IPRouteTimer;
  112. extern LIST_ENTRY ArpInterfaceList;
  113. extern HANDLE IpHeaderPool;
  114. DEFINE_LOCK_STRUCTURE(ArpModuleLock)
  115. extern void FreeFirewallQ(void);
  116. extern VOID TCPUnload(IN PDRIVER_OBJECT DriverObject);
  117. extern uint EnableICMPRedirects;
  118. extern NDIS_HANDLE NdisPacketPool;
  119. extern NDIS_HANDLE TDPacketPool;
  120. extern NDIS_HANDLE TDBufferPool;
  121. extern TDIEntityID* IPEntityList;
  122. extern uint IPEntityCount;
  123. extern PWSTR IPBindList;
  124. KMUTEX NTEContextMutex;
  125. int ARPInit();
  126. //
  127. // Macros
  128. //
  129. //++
  130. //
  131. // LARGE_INTEGER
  132. // CTEConvertMillisecondsTo100ns(
  133. // IN LARGE_INTEGER MsTime
  134. // );
  135. //
  136. // Routine Description:
  137. //
  138. // Converts time expressed in hundreds of nanoseconds to milliseconds.
  139. //
  140. // Arguments:
  141. //
  142. // MsTime - Time in milliseconds.
  143. //
  144. // Return Value:
  145. //
  146. // Time in hundreds of nanoseconds.
  147. //
  148. //--
  149. #define CTEConvertMillisecondsTo100ns(MsTime) \
  150. RtlExtendedIntegerMultiply(MsTime, 10000)
  151. //++
  152. //
  153. // LARGE_INTEGER
  154. // CTEConvert100nsToMilliseconds(
  155. // IN LARGE_INTEGER HnsTime
  156. // );
  157. //
  158. // Routine Description:
  159. //
  160. // Converts time expressed in hundreds of nanoseconds to milliseconds.
  161. //
  162. // Arguments:
  163. //
  164. // HnsTime - Time in hundreds of nanoseconds.
  165. //
  166. // Return Value:
  167. //
  168. // Time in milliseconds.
  169. //
  170. //--
  171. #define SHIFT10000 13
  172. extern LARGE_INTEGER Magic10000;
  173. #define CTEConvert100nsToMilliseconds(HnsTime) \
  174. RtlExtendedMagicDivide((HnsTime), Magic10000, SHIFT10000)
  175. //
  176. // External function prototypes
  177. //
  178. extern int
  179. IPInit(
  180. void
  181. );
  182. long
  183. IPSetInfo(
  184. TDIObjectID * ID,
  185. void *Buffer,
  186. uint Size
  187. );
  188. NTSTATUS
  189. IPDispatch(
  190. IN PDEVICE_OBJECT DeviceObject,
  191. IN PIRP Irp
  192. );
  193. NTSTATUS
  194. OpenRegKey(
  195. PHANDLE HandlePtr,
  196. PWCHAR KeyName
  197. );
  198. NTSTATUS
  199. GetRegDWORDValue(
  200. HANDLE KeyHandle,
  201. PWCHAR ValueName,
  202. PULONG ValueData
  203. );
  204. NTSTATUS
  205. GetRegLARGEINTValue(
  206. HANDLE KeyHandle,
  207. PWCHAR ValueName,
  208. PLARGE_INTEGER ValueData
  209. );
  210. NTSTATUS
  211. SetRegDWORDValue(
  212. HANDLE KeyHandle,
  213. PWCHAR ValueName,
  214. PULONG ValueData
  215. );
  216. NTSTATUS
  217. GetRegSZValue(
  218. HANDLE KeyHandle,
  219. PWCHAR ValueName,
  220. PUNICODE_STRING ValueData,
  221. PULONG ValueType
  222. );
  223. NTSTATUS
  224. GetRegMultiSZValue(
  225. HANDLE KeyHandle,
  226. PWCHAR ValueName,
  227. PUNICODE_STRING ValueData
  228. );
  229. NTSTATUS
  230. GetRegMultiSZValueNew(
  231. HANDLE KeyHandle,
  232. PWCHAR ValueName,
  233. PUNICODE_STRING_NEW ValueData
  234. );
  235. NTSTATUS
  236. InitRegDWORDParameter(
  237. HANDLE RegKey,
  238. PWCHAR ValueName,
  239. ULONG * Value,
  240. ULONG DefaultValue
  241. );
  242. uint
  243. RTReadNext(
  244. void *Context,
  245. void *Buffer
  246. );
  247. uint
  248. RTValidateContext(
  249. void *Context,
  250. uint * Valid
  251. );
  252. extern NTSTATUS
  253. SetRegMultiSZValue(
  254. HANDLE KeyHandle,
  255. PWCHAR ValueName,
  256. PUNICODE_STRING ValueData
  257. );
  258. extern NTSTATUS
  259. SetRegMultiSZValueNew(
  260. HANDLE KeyHandle,
  261. PWCHAR ValueName,
  262. PUNICODE_STRING_NEW ValueData
  263. );
  264. //
  265. // Local funcion prototypes
  266. //
  267. NTSTATUS
  268. IPDriverEntry(
  269. IN PDRIVER_OBJECT DriverObject,
  270. IN PUNICODE_STRING RegistryPath
  271. );
  272. NTSTATUS
  273. IPProcessConfiguration(
  274. VOID
  275. );
  276. NTSTATUS
  277. IPProcessAdapterSection(
  278. WCHAR * DeviceName,
  279. WCHAR * AdapterName
  280. );
  281. uint
  282. GetGeneralIFConfig(
  283. IFGeneralConfig * ConfigInfo,
  284. NDIS_HANDLE Handle,
  285. PNDIS_STRING ConfigName
  286. );
  287. int
  288. IsLLInterfaceValueNull(
  289. NDIS_HANDLE Handle
  290. );
  291. NTSTATUS
  292. GetLLInterfaceValue(
  293. NDIS_HANDLE Handle,
  294. PNDIS_STRING valueString
  295. );
  296. IFAddrList *
  297. GetIFAddrList(
  298. UINT * NumAddr,
  299. NDIS_HANDLE Handle,
  300. UINT * EnableDhcp,
  301. BOOLEAN PppIf,
  302. PNDIS_STRING ConfigName
  303. );
  304. UINT
  305. OpenIFConfig(
  306. PNDIS_STRING ConfigName,
  307. NDIS_HANDLE * Handle
  308. );
  309. VOID
  310. CloseIFConfig(
  311. NDIS_HANDLE Handle
  312. );
  313. IPConfigInfo *
  314. IPGetConfig(
  315. void
  316. );
  317. void
  318. IPFreeConfig(
  319. IPConfigInfo * ConfigInfo
  320. );
  321. ulong
  322. GetGMTDelta(
  323. void
  324. );
  325. ulong
  326. GetTime(
  327. void
  328. );
  329. BOOLEAN
  330. IPConvertStringToAddress(
  331. IN PWCHAR AddressString,
  332. OUT PULONG IpAddress
  333. );
  334. uint
  335. UseEtherSNAP(
  336. PNDIS_STRING Name
  337. );
  338. void
  339. GetAlwaysSourceRoute(
  340. uint * pArpAlwaysSourceRoute,
  341. uint * pIPAlwaysSourceRoute
  342. );
  343. uint
  344. GetArpCacheLife(
  345. void
  346. );
  347. uint
  348. GetArpRetryCount(
  349. void
  350. );
  351. ULONG
  352. RouteMatch(
  353. IN WCHAR * RouteString,
  354. IN IPAddr Address,
  355. IN IPMask Mask,
  356. OUT IPAddr * DestVal,
  357. OUT IPMask * DestMask,
  358. OUT IPAddr * GateVal,
  359. OUT ULONG * Metric
  360. );
  361. VOID
  362. SetPersistentRoutesForNTE(
  363. IPAddr Address,
  364. IPMask Mask,
  365. ULONG IFIndex
  366. );
  367. BOOLEAN
  368. GetTempDHCPAddr(
  369. NDIS_HANDLE Handle,
  370. IPAddr * Tempdhcpaddr,
  371. IPAddr * TempMask,
  372. IPAddr * TempGWAddr,
  373. PNDIS_STRING ConfigName
  374. );
  375. #ifdef ALLOC_PRAGMA
  376. #if !MILLEN
  377. #pragma alloc_text(INIT, IPDriverEntry)
  378. #endif // !MILLEN
  379. #pragma alloc_text(INIT, IPProcessConfiguration)
  380. #pragma alloc_text(INIT, IPProcessAdapterSection)
  381. #pragma alloc_text(INIT, IPGetConfig)
  382. #pragma alloc_text(INIT, IPFreeConfig)
  383. #pragma alloc_text(INIT, GetGMTDelta)
  384. #pragma alloc_text(PAGE, GetGeneralIFConfig)
  385. #pragma alloc_text(PAGE, IsLLInterfaceValueNull)
  386. #pragma alloc_text(PAGE, GetLLInterfaceValue)
  387. #pragma alloc_text(PAGE, GetIFAddrList)
  388. #pragma alloc_text(PAGE, UseEtherSNAP)
  389. #pragma alloc_text(PAGE, GetAlwaysSourceRoute)
  390. #pragma alloc_text(PAGE, GetArpCacheLife)
  391. #pragma alloc_text(PAGE, GetArpRetryCount)
  392. #if !MILLEN
  393. #pragma alloc_text(PAGE, OpenIFConfig)
  394. #pragma alloc_text(PAGE, CloseIFConfig)
  395. #pragma alloc_text(PAGE, RouteMatch)
  396. #pragma alloc_text(PAGE, IPConvertStringToAddress)
  397. #endif // !MILLEN
  398. #endif // ALLOC_PRAGMA
  399. //
  400. // Function definitions
  401. //
  402. NTSTATUS
  403. IPDriverEntry(
  404. IN PDRIVER_OBJECT DriverObject,
  405. IN PUNICODE_STRING RegistryPath
  406. )
  407. /*++
  408. Routine Description:
  409. Initialization routine for the IP driver.
  410. Arguments:
  411. DriverObject - Pointer to the IP driver object created by the system.
  412. DeviceDescription - The name of IP's node in the registry.
  413. Return Value:
  414. The final status from the initialization operation.
  415. --*/
  416. {
  417. NTSTATUS status;
  418. UNICODE_STRING deviceName;
  419. UNICODE_STRING SymbolicDeviceName;
  420. DEBUGMSG(DBG_TRACE && DBG_INIT,
  421. (DTEXT("+IPDriverEntry(%x, %x)\n"),
  422. DriverObject, RegistryPath));
  423. IPDriverObject = DriverObject;
  424. //
  425. // Create the device object. IoCreateDevice zeroes the memory
  426. // occupied by the object.
  427. //
  428. RtlInitUnicodeString(&deviceName, DD_IP_DEVICE_NAME);
  429. RtlInitUnicodeString(&SymbolicDeviceName, DD_IP_SYMBOLIC_DEVICE_NAME);
  430. status = IoCreateDevice(
  431. DriverObject,
  432. 0,
  433. &deviceName,
  434. FILE_DEVICE_NETWORK,
  435. FILE_DEVICE_SECURE_OPEN,
  436. FALSE,
  437. &IPDeviceObject
  438. );
  439. if (!NT_SUCCESS(status)) {
  440. CTELogEvent(
  441. DriverObject,
  442. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  443. 1,
  444. 1,
  445. &deviceName.Buffer,
  446. 0,
  447. NULL
  448. );
  449. DEBUGMSG(DBG_ERROR && DBG_INIT,
  450. (DTEXT("IP init failed. Failure %x to create device object %ws\n"),
  451. status, DD_IP_DEVICE_NAME));
  452. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  453. return (status);
  454. }
  455. status = IoCreateSymbolicLink(&SymbolicDeviceName, &deviceName);
  456. if (!NT_SUCCESS(status)) {
  457. CTELogEvent(
  458. DriverObject,
  459. EVENT_TCPIP_CREATE_DEVICE_FAILED,
  460. 1,
  461. 1,
  462. &deviceName.Buffer,
  463. 0,
  464. NULL
  465. );
  466. DEBUGMSG(DBG_ERROR && DBG_INIT,
  467. (DTEXT("IP init failed. Failure %x to create symbolic device name %ws\n"),
  468. status, DD_IP_SYMBOLIC_DEVICE_NAME));
  469. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  470. return (status);
  471. }
  472. status = TdiRegisterProvider(&deviceName, &IPProviderHandle);
  473. if (!NT_SUCCESS(status)) {
  474. IoDeleteDevice(IPDeviceObject);
  475. DEBUGMSG(DBG_ERROR && DBG_INIT,
  476. (DTEXT("IP init failed. Failure %x to register provider\n"),
  477. status));
  478. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  479. return (status);
  480. }
  481. //
  482. // Intialize the device object.
  483. //
  484. IPDeviceObject->Flags |= DO_DIRECT_IO;
  485. //
  486. // Initialize the list of pending echo request IRPs.
  487. //
  488. InitializeListHead(&PendingEchoList);
  489. InitializeListHead(&PendingArpSendList);
  490. //
  491. // Initialize the list of pending SetAddr request IRPs.
  492. //
  493. InitializeListHead(&PendingIPSetNTEAddrList);
  494. //
  495. // Initialize the list of pending media sense event.
  496. //
  497. InitializeListHead(&PendingIPEventList);
  498. //
  499. // Initialize the list of pending enable-router requests.
  500. //
  501. InitializeListHead(&PendingEnableRouterList);
  502. //
  503. // Initialize the ARP interface list; used in ArpUnload to walk the
  504. // list of ARP IFs so UnBinds can be issued on these.
  505. //
  506. InitializeListHead(&ArpInterfaceList);
  507. //
  508. // Init the lock to protect this list
  509. //
  510. CTEInitLock(&ArpInterfaceListLock.Lock);
  511. //
  512. // Initialize the list of ARP modules
  513. //
  514. InitializeListHead(&ArpModuleList);
  515. CTEInitLock(&ArpModuleLock);
  516. // Initialize media sense request list
  517. InitializeListHead(&PendingMediaSenseRequestList);
  518. //
  519. // Initialize the NTE context-list mutex.
  520. //
  521. KeInitializeMutex(&NTEContextMutex, 0);
  522. //
  523. // Finally, read our configuration parameters from the registry.
  524. //
  525. status = IPProcessConfiguration();
  526. if (status != STATUS_SUCCESS) {
  527. if (IPProviderHandle) {
  528. TdiDeregisterProvider(IPProviderHandle);
  529. }
  530. IoDeleteDevice(IPDeviceObject);
  531. DEBUGMSG(DBG_ERROR && DBG_INIT,
  532. (DTEXT("IPDriverEntry: IPProcessConfiguration failure %x\n"), status));
  533. #if IPMCAST
  534. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  535. return status;
  536. #endif // IPMCAST
  537. }
  538. #if IPMCAST
  539. //
  540. // IP initialized successfully
  541. //
  542. IpMcastDeviceObject = NULL;
  543. status = InitializeIpMcast(DriverObject,
  544. RegistryPath,
  545. &IpMcastDeviceObject);
  546. if (status != STATUS_SUCCESS) {
  547. TCPTRACE(("IP initialization failed: Unable to initialize multicast. Status %x",
  548. status));
  549. /*
  550. CTELogEvent(DriverObject,
  551. EVENT_IPMCAST_INIT_FAILED,
  552. 1,
  553. 1,
  554. &deviceName.Buffer,
  555. 0,
  556. NULL);*/
  557. }
  558. //
  559. // Mcast init failures is not treated as fatal
  560. //
  561. status = STATUS_SUCCESS;
  562. #endif // IPMCAST
  563. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPDriverEntry [%x]\n"), status));
  564. return status;
  565. }
  566. //
  567. // Function definitions
  568. //
  569. NTSTATUS
  570. IPPostDriverEntry(
  571. IN PDRIVER_OBJECT DriverObject,
  572. IN PUNICODE_STRING RegistryPath
  573. )
  574. /*++
  575. Routine Description:
  576. Initialization routine for the IP driver.
  577. Arguments:
  578. DriverObject - Pointer to the IP driver object created by the system.
  579. DeviceDescription - The name of IP's node in the registry.
  580. Return Value:
  581. The final status from the initialization operation.
  582. --*/
  583. {
  584. DEBUGMSG(DBG_TRACE && DBG_INIT,
  585. (DTEXT("+IPPostDriverEntry(%x, %x)\n"), DriverObject, RegistryPath));
  586. if (!ARPInit()) {
  587. DEBUGMSG(DBG_ERROR && DBG_INIT, (DTEXT("IPPostDriverEntry: ARPInit failure.\n")));
  588. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPPostDriverEntry [FAILURE]\n")));
  589. return IP_INIT_FAILURE; // Couldn't initialize ARP.
  590. }
  591. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPPostDriverEntry [SUCCESS]\n")));
  592. return IP_SUCCESS;
  593. }
  594. NTSTATUS
  595. IPProcessConfiguration(
  596. VOID
  597. )
  598. /*++
  599. Routine Description:
  600. Reads the IP configuration information from the registry and constructs
  601. the configuration structure expected by the IP driver.
  602. Arguments:
  603. None.
  604. Return Value:
  605. STATUS_SUCCESS or an error status if an operation fails.
  606. --*/
  607. {
  608. NTSTATUS status;
  609. HANDLE myRegKey = NULL;
  610. UNICODE_STRING bindString;
  611. WCHAR *aName, *endOfString;
  612. WCHAR IPParametersRegistryKey[] =
  613. #if MILLEN
  614. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\VxD\\MSTCP";
  615. #else // MILLEN
  616. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters";
  617. WCHAR IPLinkageRegistryKey[] =
  618. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Linkage";
  619. #endif // !MILLEN
  620. uint ArpTRSingleRoute;
  621. MM_SYSTEMSIZE systemSize;
  622. ULONG ulongValue;
  623. const ULONG DefaultMaxNormLookupMem[] =
  624. {
  625. DEFAULT_MAX_NORM_LOOKUP_MEM_SMALL,
  626. DEFAULT_MAX_NORM_LOOKUP_MEM_MEDIUM,
  627. DEFAULT_MAX_NORM_LOOKUP_MEM_LARGE
  628. };
  629. const ULONG DefaultMaxFastLookupMem[] =
  630. {
  631. DEFAULT_MAX_FAST_LOOKUP_MEM_SMALL,
  632. DEFAULT_MAX_FAST_LOOKUP_MEM_MEDIUM,
  633. DEFAULT_MAX_FAST_LOOKUP_MEM_LARGE
  634. };
  635. const ULONG DefaultFastLookupLevels[] =
  636. {
  637. DEFAULT_EXPN_LEVELS_SMALL,
  638. DEFAULT_EXPN_LEVELS_MEDIUM,
  639. DEFAULT_EXPN_LEVELS_LARGE
  640. };
  641. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("+IPProcessConfiguration()\n")));
  642. bindString.Buffer = NULL;
  643. IPConfiguration = CTEAllocMemBoot(sizeof(IPConfigInfo));
  644. if (IPConfiguration == NULL) {
  645. CTELogEvent(
  646. IPDriverObject,
  647. EVENT_TCPIP_NO_RESOURCES_FOR_INIT,
  648. 1,
  649. 0,
  650. NULL,
  651. 0,
  652. NULL
  653. );
  654. DEBUGMSG(DBG_TRACE && DBG_INIT, (DTEXT("-IPProcessConfiguration [NO_RESOURCES]\n")));
  655. return (STATUS_INSUFFICIENT_RESOURCES);
  656. }
  657. RtlZeroMemory(IPConfiguration, sizeof(IPConfigInfo));
  658. //
  659. // Process the Ip\Parameters section of the registry
  660. //
  661. status = OpenRegKey(&myRegKey, IPParametersRegistryKey);
  662. if (NT_SUCCESS(status)) {
  663. DEBUGMSG(DBG_INFO && DBG_INIT,
  664. (DTEXT("IPProcessConfiguration: Opened registry path %ws, initializing variables.\n"),
  665. IPParametersRegistryKey));
  666. //
  667. // Expected configuration values. We use reasonable defaults if they
  668. // aren't available for some reason.
  669. //
  670. status = GetRegDWORDValue(
  671. myRegKey,
  672. L"IpEnableRouter",
  673. &(IPConfiguration->ici_gateway)
  674. );
  675. #if MILLEN
  676. //
  677. // Backwards compatibility. If 'IpEnableRouter' key is not present, then
  678. // try to read legacy 'EnableRouting' key.
  679. //
  680. if (!NT_SUCCESS(status)) {
  681. status = GetRegDWORDValue(
  682. myRegKey,
  683. L"EnableRouting",
  684. &(IPConfiguration->ici_gateway)
  685. );
  686. }
  687. #endif // MILLEN
  688. if (!NT_SUCCESS(status)) {
  689. TCPTRACE((
  690. "IP: Unable to read IpEnableRouter value from the registry.\n"
  691. " Routing will be disabled.\n"
  692. ));
  693. IPConfiguration->ici_gateway = 0;
  694. }
  695. (VOID) InitRegDWORDParameter(
  696. myRegKey,
  697. L"EnableAddrMaskReply",
  698. &(IPConfiguration->ici_addrmaskreply),
  699. FALSE
  700. );
  701. //
  702. // Optional (hidden) values
  703. //
  704. status = InitRegDWORDParameter(
  705. myRegKey,
  706. L"ForwardBufferMemory",
  707. &(IPConfiguration->ici_fwbufsize),
  708. DEFAULT_FW_BUFSIZE
  709. );
  710. #if MILLEN
  711. //
  712. // Backwards compatibility. If the 'ForwardBufferMemory' value is not
  713. // present, then attempt to read legacy 'RoutingBufSize' value.
  714. //
  715. if (!NT_SUCCESS(status)) {
  716. InitRegDWORDParameter(
  717. myRegKey,
  718. L"RoutingBufSize",
  719. &(IPConfiguration->ici_fwbufsize),
  720. DEFAULT_FW_BUFSIZE
  721. );
  722. }
  723. #endif // MILLEN
  724. status = InitRegDWORDParameter(
  725. myRegKey,
  726. L"MaxForwardBufferMemory",
  727. &(IPConfiguration->ici_maxfwbufsize),
  728. DEFAULT_MAX_FW_BUFSIZE
  729. );
  730. #if MILLEN
  731. //
  732. // Backwards compatibility. If the 'MaxForwardBufferMemory' value is not
  733. // present, then attempt to read legacy 'MaxRoutingBufSize' value.
  734. //
  735. if (!NT_SUCCESS(status)) {
  736. InitRegDWORDParameter(
  737. myRegKey,
  738. L"MaxRoutingBufSize",
  739. &(IPConfiguration->ici_maxfwbufsize),
  740. DEFAULT_MAX_FW_BUFSIZE
  741. );
  742. }
  743. #endif // MILLEN
  744. (VOID) InitRegDWORDParameter(
  745. myRegKey,
  746. L"ForwardBroadcasts",
  747. &(IPConfiguration->ici_fwbcast),
  748. FALSE
  749. );
  750. status = InitRegDWORDParameter(
  751. myRegKey,
  752. L"NumForwardPackets",
  753. &(IPConfiguration->ici_fwpackets),
  754. DEFAULT_FW_PACKETS
  755. );
  756. #if MILLEN
  757. //
  758. // Backwards compatibility. If the 'NumForwardPackets' value is not
  759. // present, then attempt to read legacy 'RoutingPackets' value.
  760. //
  761. if (!NT_SUCCESS(status)) {
  762. InitRegDWORDParameter(
  763. myRegKey,
  764. L"RoutingPackets",
  765. &(IPConfiguration->ici_fwpackets),
  766. DEFAULT_FW_PACKETS
  767. );
  768. }
  769. #endif // MILLEN
  770. status = InitRegDWORDParameter(
  771. myRegKey,
  772. L"MaxNumForwardPackets",
  773. &(IPConfiguration->ici_maxfwpackets),
  774. DEFAULT_MAX_FW_PACKETS
  775. );
  776. #if MILLEN
  777. //
  778. // Backwards compatibility. If the 'MaxNumForwardPackets' value is not
  779. // present, then attempt to read legacy 'MaxRoutingPackets' value.
  780. //
  781. if (!NT_SUCCESS(status)) {
  782. InitRegDWORDParameter(
  783. myRegKey,
  784. L"MaxRoutingPackets",
  785. &(IPConfiguration->ici_maxfwpackets),
  786. DEFAULT_MAX_FW_PACKETS
  787. );
  788. }
  789. #endif // MILLEN
  790. (VOID) InitRegDWORDParameter(
  791. myRegKey,
  792. L"IGMPLevel",
  793. &(IPConfiguration->ici_igmplevel),
  794. DEFAULT_IGMP_LEVEL
  795. );
  796. status = InitRegDWORDParameter(
  797. myRegKey,
  798. L"EnableDeadGWDetect",
  799. &(IPConfiguration->ici_deadgwdetect),
  800. TRUE
  801. );
  802. #if MILLEN
  803. //
  804. // Backwards compatibility. If EnableDeadGWDetect key did not exist, then
  805. // check for the DeadGWDetect key. Same default value.
  806. //
  807. if (!NT_SUCCESS(status)) {
  808. InitRegDWORDParameter(
  809. myRegKey,
  810. L"DeadGWDetect",
  811. &(IPConfiguration->ici_deadgwdetect),
  812. TRUE
  813. );
  814. }
  815. #endif // MILLEN
  816. (VOID) InitRegDWORDParameter(
  817. myRegKey,
  818. L"EnablePMTUDiscovery",
  819. &(IPConfiguration->ici_pmtudiscovery),
  820. TRUE
  821. );
  822. (VOID) InitRegDWORDParameter(
  823. myRegKey,
  824. L"DefaultTTL",
  825. &(IPConfiguration->ici_ttl),
  826. DEFAULT_TTL
  827. );
  828. if (IPConfiguration->ici_ttl == 0) {
  829. IPConfiguration->ici_ttl = DEFAULT_TTL;
  830. }
  831. status = InitRegDWORDParameter(
  832. myRegKey,
  833. L"DefaultTOSValue",
  834. &(IPConfiguration->ici_tos),
  835. DEFAULT_TOS
  836. );
  837. #if MILLEN
  838. //
  839. // Backwards compatibility. Read 'DefaultTOS' if 'DefaultTOSValue' is
  840. // not present.
  841. //
  842. if (!NT_SUCCESS(status)) {
  843. InitRegDWORDParameter(
  844. myRegKey,
  845. L"DefaultTOS",
  846. &(IPConfiguration->ici_tos),
  847. DEFAULT_TOS
  848. );
  849. }
  850. #endif // MILLEN
  851. (VOID) InitRegDWORDParameter(
  852. myRegKey,
  853. L"DisableUserTOSSetting",
  854. &DisableUserTOS,
  855. TRUE
  856. );
  857. (VOID) InitRegDWORDParameter(
  858. myRegKey,
  859. L"EnableICMPRedirect",
  860. &EnableICMPRedirects,
  861. TRUE
  862. );
  863. // Get the system size - SMALL, MEDIUM, LARGE
  864. systemSize = MmQuerySystemSize();
  865. // Get the route lookup memory usage limits
  866. (VOID) InitRegDWORDParameter(
  867. myRegKey,
  868. L"MaxNormLookupMemory",
  869. &(IPConfiguration->ici_maxnormlookupmemory),
  870. DefaultMaxNormLookupMem[systemSize]
  871. );
  872. if (IPConfiguration->ici_maxnormlookupmemory
  873. < MINIMUM_MAX_NORM_LOOKUP_MEM) {
  874. IPConfiguration->ici_maxnormlookupmemory
  875. = MINIMUM_MAX_NORM_LOOKUP_MEM;
  876. }
  877. #if MILLEN
  878. IPConfiguration->ici_fastroutelookup = FALSE;
  879. #else // MILLEN
  880. // Are we a gateway ? Is this a medium or large
  881. // server ? If so, is fast routing enabled ?
  882. if (IPConfiguration->ici_gateway
  883. && MmIsThisAnNtAsSystem()
  884. && (systemSize > MmSmallSystem)) {
  885. (VOID) InitRegDWORDParameter(
  886. myRegKey,
  887. L"EnableFastRouteLookup",
  888. &(IPConfiguration->ici_fastroutelookup),
  889. FALSE
  890. );
  891. } else {
  892. IPConfiguration->ici_fastroutelookup = FALSE;
  893. }
  894. #endif // !MILLEN
  895. // If Fast lookup is enabled, get lookup params
  896. if (IPConfiguration->ici_fastroutelookup) {
  897. (VOID) InitRegDWORDParameter(
  898. myRegKey,
  899. L"FastRouteLookupLevels",
  900. &(IPConfiguration->ici_fastlookuplevels),
  901. DefaultFastLookupLevels[systemSize]
  902. );
  903. (VOID) InitRegDWORDParameter(
  904. myRegKey,
  905. L"MaxFastLookupMemory",
  906. &(IPConfiguration->ici_maxfastlookupmemory),
  907. DefaultMaxFastLookupMem[systemSize]
  908. );
  909. if (IPConfiguration->ici_maxfastlookupmemory
  910. < MINIMUM_MAX_FAST_LOOKUP_MEM) {
  911. IPConfiguration->ici_maxfastlookupmemory
  912. = MINIMUM_MAX_FAST_LOOKUP_MEM;
  913. }
  914. }
  915. (VOID) InitRegDWORDParameter(
  916. myRegKey,
  917. L"MaxEqualCostRoutes",
  918. &ulongValue,
  919. DEFAULT_MAX_EQUAL_COST_ROUTES
  920. );
  921. MaxEqualCostRoutes = (USHORT) ulongValue;
  922. if (MaxEqualCostRoutes > MAXIMUM_MAX_EQUAL_COST_ROUTES) {
  923. MaxEqualCostRoutes = DEFAULT_MAX_EQUAL_COST_ROUTES;
  924. }
  925. #if FFP_SUPPORT
  926. (VOID) InitRegDWORDParameter(
  927. myRegKey,
  928. L"FFPFastForwardingCacheSize",
  929. &FFPRegFastForwardingCacheSize,
  930. DEFAULT_FFP_FFWDCACHE_SIZE
  931. );
  932. (VOID) InitRegDWORDParameter(
  933. myRegKey,
  934. L"FFPControlFlags",
  935. &FFPRegControlFlags,
  936. DEFAULT_FFP_CONTROL_FLAGS
  937. );
  938. #endif // FFP_SUPPORT
  939. (VOID) InitRegDWORDParameter(
  940. myRegKey,
  941. L"TrFunctionalMcastAddress",
  942. &(IPConfiguration->ici_TrFunctionalMcst),
  943. TRUE
  944. );
  945. status = InitRegDWORDParameter(
  946. myRegKey,
  947. L"ArpUseEtherSnap",
  948. &ArpUseEtherSnap,
  949. FALSE
  950. );
  951. #if MILLEN
  952. //
  953. // Backwards compatibility. If the 'ArpUseEtherSnap' key does not exist,
  954. // then try to read the 'EtherSNAP' key.
  955. //
  956. if (!NT_SUCCESS(status)) {
  957. InitRegDWORDParameter(
  958. myRegKey,
  959. L"EtherSNAP",
  960. &ArpUseEtherSnap,
  961. FALSE
  962. );
  963. }
  964. #endif // MILLEN
  965. (VOID) InitRegDWORDParameter(
  966. myRegKey,
  967. L"DisableDHCPMediaSense",
  968. &DisableMediaSense,
  969. 0
  970. );
  971. (VOID) InitRegDWORDParameter(
  972. myRegKey,
  973. L"DisableMediaSenseEventLog",
  974. &DisableMediaSenseEventLog,
  975. #if MILLEN
  976. // This mediasense event log causes issues
  977. // on Windows ME. Since there is no
  978. // event log anyways, disable it.
  979. TRUE
  980. #else // MILLEN
  981. FALSE
  982. #endif // !MILLEN
  983. );
  984. //DisableIPSourceRouting == 2 drop it if SR option
  985. // is rcvd, without forwarding.
  986. (VOID) InitRegDWORDParameter(
  987. myRegKey,
  988. L"DisableIPSourceRouting",
  989. &DisableIPSourceRouting,
  990. 1
  991. );
  992. (VOID) InitRegDWORDParameter(
  993. myRegKey,
  994. L"MaximumReassemblyHeaders",
  995. &MaxRH,
  996. 100
  997. );
  998. (VOID) InitRegDWORDParameter(
  999. myRegKey,
  1000. L"NetHashTableSize",
  1001. &NET_TABLE_SIZE,
  1002. 8
  1003. );
  1004. if (NET_TABLE_SIZE < 8) {
  1005. NET_TABLE_SIZE = 8;
  1006. } else if (NET_TABLE_SIZE > 0xffff) {
  1007. NET_TABLE_SIZE = 512;
  1008. } else {
  1009. NET_TABLE_SIZE = ComputeLargerOrEqualPowerOfTwo(NET_TABLE_SIZE);
  1010. }
  1011. // we check for the return status here because if this parameter was
  1012. // not defined, then we want the default behavior for both arp
  1013. // and ip broadcasts. For arp, the behavior is to not source route
  1014. // and source router alternately. For ip, it is to always source
  1015. // route. If the parameter is defined and is 0, then for arp the
  1016. // behavior does not change. For ip however, we do not source route
  1017. // at all. Ofcourse, when the parameter is set to a non-zero value,
  1018. // we always source route for both.
  1019. //
  1020. status = InitRegDWORDParameter(
  1021. myRegKey,
  1022. L"ArpAlwaysSourceRoute",
  1023. &ArpAlwaysSourceRoute,
  1024. FALSE
  1025. );
  1026. if (NT_SUCCESS(status)) {
  1027. IPAlwaysSourceRoute = ArpAlwaysSourceRoute;
  1028. }
  1029. (VOID) InitRegDWORDParameter(
  1030. myRegKey,
  1031. L"ArpTRSingleRoute",
  1032. &ArpTRSingleRoute,
  1033. FALSE
  1034. );
  1035. if (ArpTRSingleRoute) {
  1036. TrRii = TR_RII_SINGLE;
  1037. } else {
  1038. TrRii = TR_RII_ALL;
  1039. }
  1040. (VOID) InitRegDWORDParameter(
  1041. myRegKey,
  1042. L"ArpCacheLife",
  1043. &ArpCacheLife,
  1044. DEFAULT_ARP_CACHE_LIFE
  1045. );
  1046. (VOID) InitRegDWORDParameter(
  1047. myRegKey,
  1048. L"ArpCacheMinReferencedLife",
  1049. &ArpMinValidCacheLife,
  1050. DEFAULT_ARP_MIN_VALID_CACHE_LIFE
  1051. );
  1052. (VOID) InitRegDWORDParameter(
  1053. myRegKey,
  1054. L"ArpRetryCount",
  1055. &ArpRetryCount,
  1056. DEFAULT_ARPRETRY_COUNT
  1057. );
  1058. if (((int)ArpRetryCount < 0) || (ArpRetryCount > 3)) {
  1059. ArpRetryCount = DEFAULT_ARPRETRY_COUNT;
  1060. }
  1061. (VOID) InitRegDWORDParameter(
  1062. myRegKey,
  1063. L"EnableBcastArpReply",
  1064. &EnableBcastArpReply,
  1065. TRUE
  1066. );
  1067. (VOID) InitRegDWORDParameter(
  1068. myRegKey,
  1069. L"DisableTaskOffload",
  1070. &DisableTaskOffload,
  1071. #if MILLEN
  1072. TRUE
  1073. #else // MILLEN
  1074. FALSE
  1075. #endif // !MILLEN
  1076. );
  1077. (VOID) InitRegDWORDParameter(
  1078. myRegKey,
  1079. L"ConnectDampInterval",
  1080. &ConnectDampingInterval,
  1081. 5
  1082. );
  1083. ConnectDampingInterval = MIN(10, MAX(5, ConnectDampingInterval));
  1084. (VOID) InitRegDWORDParameter(
  1085. myRegKey,
  1086. L"DisconnectDampInterval",
  1087. &DampingInterval,
  1088. 10
  1089. );
  1090. DampingInterval = MIN(10, MAX(5, DampingInterval));
  1091. ZwClose(myRegKey);
  1092. myRegKey = NULL;
  1093. } else {
  1094. //
  1095. // Use reasonable defaults.
  1096. //
  1097. IPConfiguration->ici_fwbcast = 0;
  1098. IPConfiguration->ici_gateway = 0;
  1099. IPConfiguration->ici_addrmaskreply = 0;
  1100. IPConfiguration->ici_fwbufsize = DEFAULT_FW_BUFSIZE;
  1101. IPConfiguration->ici_fwpackets = DEFAULT_FW_PACKETS;
  1102. IPConfiguration->ici_maxfwbufsize = DEFAULT_MAX_FW_BUFSIZE;
  1103. IPConfiguration->ici_maxfwpackets = DEFAULT_MAX_FW_PACKETS;
  1104. IPConfiguration->ici_igmplevel = DEFAULT_IGMP_LEVEL;
  1105. IPConfiguration->ici_deadgwdetect = FALSE;
  1106. IPConfiguration->ici_pmtudiscovery = FALSE;
  1107. IPConfiguration->ici_ttl = DEFAULT_TTL;
  1108. IPConfiguration->ici_tos = DEFAULT_TOS;
  1109. NET_TABLE_SIZE = 8;
  1110. DEBUGMSG(DBG_WARN && DBG_INIT,
  1111. (DTEXT("IPProcessConfiguration: Unable to open registry - using defaults.\n")));
  1112. }
  1113. #if !MILLEN
  1114. //
  1115. // Retrieve and store the binding list from the Linkage key
  1116. //
  1117. status = OpenRegKey(&myRegKey, IPLinkageRegistryKey);
  1118. if (NT_SUCCESS(status)) {
  1119. UNICODE_STRING_NEW BindString;
  1120. BindString.Length = 0;
  1121. BindString.MaximumLength = WORK_BUFFER_SIZE;
  1122. BindString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1123. if (BindString.Buffer) {
  1124. status = GetRegMultiSZValueNew(myRegKey, L"Bind", &BindString);
  1125. if (status == STATUS_SUCCESS) {
  1126. IPBindList = BindString.Buffer;
  1127. } else {
  1128. CTEFreeMem(BindString.Buffer);
  1129. }
  1130. }
  1131. ZwClose(myRegKey);
  1132. myRegKey = NULL;
  1133. }
  1134. #endif
  1135. status = STATUS_SUCCESS;
  1136. if (!IPInit()) {
  1137. CTELogEvent(
  1138. IPDriverObject,
  1139. EVENT_TCPIP_IP_INIT_FAILED,
  1140. 1,
  1141. 0,
  1142. NULL,
  1143. 0,
  1144. NULL
  1145. );
  1146. DEBUGMSG(DBG_ERROR && DBG_INIT,
  1147. (DTEXT("IPProcessConfiguration: IPInit failure.\n")));
  1148. status = STATUS_UNSUCCESSFUL;
  1149. } else {
  1150. status = STATUS_SUCCESS;
  1151. }
  1152. if (myRegKey != NULL) {
  1153. ZwClose(myRegKey);
  1154. }
  1155. if (IPConfiguration != NULL) {
  1156. IPFreeConfig(IPConfiguration);
  1157. }
  1158. return (status);
  1159. }
  1160. uint
  1161. GetDefaultGWList(
  1162. uint * numGW,
  1163. IPAddr * gwList,
  1164. uint * gwMetricList,
  1165. NDIS_HANDLE Handle,
  1166. PNDIS_STRING ConfigName
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. This routine reads the default gateway list from the registry.
  1171. Arguments:
  1172. numberOfGateways - number of gateway entries in the registry.
  1173. gwList - pointer to the gateway list.
  1174. gwMetricList - pointer to the metric for each gateway
  1175. handle - Config handle from OpenIFConfig().
  1176. ConfigName - description string for use in logging failures.
  1177. Return Value:
  1178. TRUE if we got all the required info, FALSE otherwise.
  1179. --*/
  1180. {
  1181. UNICODE_STRING valueString;
  1182. NTSTATUS status;
  1183. ULONG ulAddGateway, ulTemp;
  1184. uint numberOfGateways;
  1185. PAGED_CODE();
  1186. //
  1187. // Process the gateway MultiSZ. The end is signified by a double NULL.
  1188. // This list currently only applies to the first IP address configured
  1189. // on this interface.
  1190. //
  1191. numberOfGateways = 0;
  1192. ulAddGateway = TRUE;
  1193. RtlZeroMemory(gwList, sizeof(IPAddr) * MAX_DEFAULT_GWS);
  1194. RtlZeroMemory(gwMetricList, sizeof(uint) * MAX_DEFAULT_GWS);
  1195. valueString.Length = 0;
  1196. valueString.MaximumLength = WORK_BUFFER_SIZE;
  1197. valueString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1198. if (valueString.Buffer == NULL) {
  1199. return (FALSE);
  1200. }
  1201. ulTemp = 0;
  1202. status = GetRegDWORDValue(Handle,
  1203. L"DontAddDefaultGateway",
  1204. &ulTemp);
  1205. if (NT_SUCCESS(status)) {
  1206. if (ulTemp == 1) {
  1207. ulAddGateway = FALSE;
  1208. }
  1209. }
  1210. if (ulAddGateway) {
  1211. status = GetRegMultiSZValue(
  1212. Handle,
  1213. L"DefaultGateway",
  1214. &valueString
  1215. );
  1216. if (NT_SUCCESS(status)) {
  1217. PWCHAR addressString = valueString.Buffer;
  1218. while (*addressString != UNICODE_NULL) {
  1219. IPAddr addressValue;
  1220. BOOLEAN conversionStatus;
  1221. if (numberOfGateways >= MAX_DEFAULT_GWS) {
  1222. CTELogEvent(
  1223. IPDriverObject,
  1224. EVENT_TCPIP_TOO_MANY_GATEWAYS,
  1225. 1,
  1226. 1,
  1227. &ConfigName->Buffer,
  1228. 0,
  1229. NULL
  1230. );
  1231. break;
  1232. }
  1233. conversionStatus = IPConvertStringToAddress(
  1234. addressString,
  1235. &addressValue
  1236. );
  1237. if (conversionStatus && (addressValue != 0xFFFFFFFF)) {
  1238. if (addressValue != INADDR_ANY) {
  1239. gwList[numberOfGateways++] = addressValue;
  1240. }
  1241. } else {
  1242. PWCHAR stringList[2];
  1243. stringList[0] = addressString;
  1244. stringList[1] = ConfigName->Buffer;
  1245. CTELogEvent(
  1246. IPDriverObject,
  1247. EVENT_TCPIP_INVALID_DEFAULT_GATEWAY,
  1248. 1,
  1249. 2,
  1250. stringList,
  1251. 0,
  1252. NULL
  1253. );
  1254. TCPTRACE((
  1255. "IP: Invalid default gateway address %ws specified for adapter %ws.\n"
  1256. " Remote networks may not be reachable as a result.\n",
  1257. addressString,
  1258. ConfigName->Buffer
  1259. ));
  1260. }
  1261. //
  1262. // Walk over the entry we just processed.
  1263. //
  1264. while (*addressString++ != UNICODE_NULL);
  1265. }
  1266. status = GetRegMultiSZValue(
  1267. Handle,
  1268. L"DefaultGatewayMetric",
  1269. &valueString
  1270. );
  1271. if (NT_SUCCESS(status)) {
  1272. PWCHAR metricBuffer = valueString.Buffer;
  1273. uint metricIndex = 0;
  1274. while (*metricBuffer != UNICODE_NULL) {
  1275. uint metricValue;
  1276. UNICODE_STRING metricString;
  1277. if (metricIndex >= numberOfGateways) {
  1278. break;
  1279. }
  1280. RtlInitUnicodeString(&metricString, metricBuffer);
  1281. status = RtlUnicodeStringToInteger(
  1282. &metricString,
  1283. 10,
  1284. &metricValue
  1285. );
  1286. if (!NT_SUCCESS(status)) {
  1287. break;
  1288. } else {
  1289. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1290. "GetDefaultGWList: read %d\n", metricValue));
  1291. if ((LONG) metricValue < 0) {
  1292. break;
  1293. }
  1294. }
  1295. gwMetricList[metricIndex++] = metricValue;
  1296. //
  1297. // Walk over the entry we just processed.
  1298. //
  1299. while (*metricBuffer++ != UNICODE_NULL);
  1300. }
  1301. }
  1302. } else {
  1303. TCPTRACE((
  1304. "IP: Unable to read DefaultGateway value for adapter %ws.\n"
  1305. " Initialization will continue.\n",
  1306. ConfigName->Buffer
  1307. ));
  1308. }
  1309. }
  1310. *numGW = numberOfGateways;
  1311. if (valueString.Buffer) {
  1312. CTEFreeMem(valueString.Buffer);
  1313. }
  1314. return TRUE;
  1315. }
  1316. void
  1317. GetInterfaceMetric(
  1318. uint * Metric,
  1319. NDIS_HANDLE Handle
  1320. )
  1321. /*++
  1322. Routine Description:
  1323. A routine to retrieve the metric associated with an interface, if any.
  1324. Arguments:
  1325. Metric - receives the metric
  1326. Handle - Config handle from OpenIFConfig().
  1327. Return Value:
  1328. none.
  1329. --*/
  1330. {
  1331. NTSTATUS status;
  1332. status = GetRegDWORDValue(
  1333. Handle,
  1334. L"InterfaceMetric",
  1335. Metric
  1336. );
  1337. if (!NT_SUCCESS(status)) {
  1338. *Metric = 0;
  1339. } else {
  1340. if (*Metric > 9999) {
  1341. *Metric = 9999;
  1342. }
  1343. }
  1344. }
  1345. void
  1346. UpdateTcpParams(
  1347. NDIS_HANDLE Handle,
  1348. Interface *IF
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. A routine to update per-interface specific tcp tuning parametsrs.
  1353. Arguments:
  1354. Handle - Config handle from OpenIFConfig().
  1355. IF - IP Interface which needs to be updated.
  1356. Return Value:
  1357. none.
  1358. --*/
  1359. {
  1360. ULONG ulTemp;
  1361. NTSTATUS status;
  1362. status = GetRegDWORDValue(
  1363. Handle,
  1364. L"TcpWindowSize",
  1365. &ulTemp
  1366. );
  1367. if (NT_SUCCESS(status)) {
  1368. IF->if_TcpWindowSize = ulTemp;
  1369. }
  1370. status = GetRegDWORDValue(
  1371. Handle,
  1372. L"TcpInitialRTT",
  1373. &ulTemp
  1374. );
  1375. if (NT_SUCCESS(status)) {
  1376. IF->if_TcpInitialRTT = ulTemp;
  1377. }
  1378. status = GetRegDWORDValue(
  1379. Handle,
  1380. L"TcpDelAckTicks",
  1381. &ulTemp
  1382. );
  1383. if (NT_SUCCESS(status) && (ulTemp <= MAX_DEL_ACK_TICKS)) {
  1384. IF->if_TcpDelAckTicks = (uchar)ulTemp;
  1385. }
  1386. status = GetRegDWORDValue(
  1387. Handle,
  1388. L"TcpACKFrequency",
  1389. &ulTemp
  1390. );
  1391. if (NT_SUCCESS(status)) {
  1392. IF->if_TcpAckFrequency = (uchar)ulTemp;
  1393. }
  1394. }
  1395. uint
  1396. GetGeneralIFConfig(
  1397. IFGeneralConfig * ConfigInfo,
  1398. NDIS_HANDLE Handle,
  1399. PNDIS_STRING ConfigName
  1400. )
  1401. /*++
  1402. Routine Description:
  1403. A routine to get the general per-interface config info, such as MTU,
  1404. type of broadcast, etc. The caller gives us a structure to be filled in
  1405. and a handle, and we fill in the structure if we can.
  1406. Arguments:
  1407. ConfigInfo - Structure to be filled in.
  1408. Handle - Config handle from OpenIFConfig().
  1409. ConfigName - identification string for logging failures.
  1410. Return Value:
  1411. TRUE if we got all the required info, FALSE otherwise.
  1412. --*/
  1413. {
  1414. UNICODE_STRING valueString;
  1415. NTSTATUS status;
  1416. UINT numberOfGateways = 0;
  1417. UCHAR TempBuffer[WORK_BUFFER_SIZE];
  1418. ULONG ulAddGateway, ulTemp;
  1419. PAGED_CODE();
  1420. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1421. (DTEXT("+GetGeneralIFConfig(%x, %x)\n"), ConfigInfo, Handle));
  1422. if (!GetDefaultGWList(
  1423. &ConfigInfo->igc_numgws,
  1424. ConfigInfo->igc_gw,
  1425. ConfigInfo->igc_gwmetric,
  1426. Handle,
  1427. ConfigName)) {
  1428. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1429. (DTEXT("GetGeneralIFConfig: GetDefaultGWList failure.\n")));
  1430. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-GetGeneralIFConfig [FALSE]\n")));
  1431. return FALSE;
  1432. }
  1433. //
  1434. // Are we using zeros broadcasts?
  1435. //
  1436. status = GetRegDWORDValue(
  1437. Handle,
  1438. L"UseZeroBroadcast",
  1439. &(ConfigInfo->igc_zerobcast)
  1440. );
  1441. #if MILLEN
  1442. //
  1443. // Backwards compatibility. If 'UseZeroBroadcast' value doesn't exist, then
  1444. // attempt to read legacy value: 'ZeroBroadcast'.
  1445. //
  1446. if (!NT_SUCCESS(status)) {
  1447. status = GetRegDWORDValue(
  1448. Handle,
  1449. L"ZeroBroadcast",
  1450. &(ConfigInfo->igc_zerobcast)
  1451. );
  1452. }
  1453. #endif // MILLEN
  1454. if (!NT_SUCCESS(status)) {
  1455. TCPTRACE((
  1456. "IP: Unable to read UseZeroBroadcast value for adapter %ws.\n"
  1457. " All-nets broadcasts will be addressed to 255.255.255.255.\n",
  1458. ConfigName->Buffer
  1459. ));
  1460. ConfigInfo->igc_zerobcast = FALSE; // default to off
  1461. }
  1462. //
  1463. // Has anyone specified an MTU?
  1464. //
  1465. status = GetRegDWORDValue(
  1466. Handle,
  1467. L"MTU",
  1468. &(ConfigInfo->igc_mtu)
  1469. );
  1470. #if MILLEN
  1471. //
  1472. // Backwards compatibility. If 'MTU' value doesn't exist, then
  1473. // attempt to read legacy value: 'MaxMTU'.
  1474. //
  1475. if (!NT_SUCCESS(status)) {
  1476. status = GetRegDWORDValue(
  1477. Handle,
  1478. L"MaxMTU",
  1479. &(ConfigInfo->igc_mtu)
  1480. );
  1481. }
  1482. #endif // !MILLEN
  1483. if (!NT_SUCCESS(status)) {
  1484. ConfigInfo->igc_mtu = 0xFFFFFFF; // The stack will pick one.
  1485. }
  1486. //
  1487. // Have we been configured for more routing packets?
  1488. //
  1489. status = GetRegDWORDValue(
  1490. Handle,
  1491. L"MaxForwardPending",
  1492. &(ConfigInfo->igc_maxpending)
  1493. );
  1494. #if MILLEN
  1495. //
  1496. // Backwards compatibility. If 'MaxForwardPending' value doesn't exist, then
  1497. // attempt to read legacy value: 'MaxFWPending'.
  1498. //
  1499. if (!NT_SUCCESS(status)) {
  1500. status = GetRegDWORDValue(
  1501. Handle,
  1502. L"MaxFWPending",
  1503. &(ConfigInfo->igc_maxpending)
  1504. );
  1505. }
  1506. #endif // !MILLEN
  1507. if (!NT_SUCCESS(status)) {
  1508. ConfigInfo->igc_maxpending = DEFAULT_MAX_PENDING;
  1509. }
  1510. //
  1511. // Has Router Discovery been configured?
  1512. // We accept three values:
  1513. // 0: disable router-discovery
  1514. // 1: enable router-discovery
  1515. // 2: disable router-discovery, and enable it only if the DHCP server
  1516. // sends the 'Perform Router Discovery' option. In this case,
  1517. // we wait for the DHCP client service to tell us to start
  1518. // doing router-discovery.
  1519. //
  1520. status = GetRegDWORDValue(
  1521. Handle,
  1522. L"PerformRouterDiscovery",
  1523. &(ConfigInfo->igc_rtrdiscovery)
  1524. );
  1525. if (!NT_SUCCESS(status)) {
  1526. ConfigInfo->igc_rtrdiscovery = IP_IRDP_DISABLED_USE_DHCP;
  1527. } else if (ConfigInfo->igc_rtrdiscovery != IP_IRDP_DISABLED &&
  1528. ConfigInfo->igc_rtrdiscovery != IP_IRDP_ENABLED &&
  1529. ConfigInfo->igc_rtrdiscovery != IP_IRDP_DISABLED_USE_DHCP) {
  1530. ConfigInfo->igc_rtrdiscovery = IP_IRDP_DISABLED_USE_DHCP;
  1531. }
  1532. //
  1533. // Has Router Discovery Address been configured?
  1534. //
  1535. status = GetRegDWORDValue(
  1536. Handle,
  1537. L"SolicitationAddressBCast",
  1538. &ulTemp
  1539. );
  1540. if (!NT_SUCCESS(status)) {
  1541. ConfigInfo->igc_rtrdiscaddr = ALL_ROUTER_MCAST;
  1542. } else {
  1543. if (ulTemp == 1) {
  1544. ConfigInfo->igc_rtrdiscaddr = 0xffffffff;
  1545. } else {
  1546. ConfigInfo->igc_rtrdiscaddr = ALL_ROUTER_MCAST;
  1547. }
  1548. }
  1549. ConfigInfo->igc_TcpWindowSize = 0;
  1550. ConfigInfo->igc_TcpInitialRTT = 0;
  1551. ConfigInfo->igc_TcpDelAckTicks = DEL_ACK_TICKS;
  1552. ConfigInfo->igc_TcpAckFrequency = 0;
  1553. status = GetRegDWORDValue(
  1554. Handle,
  1555. L"TcpWindowSize",
  1556. &ulTemp
  1557. );
  1558. if (NT_SUCCESS(status)) {
  1559. ConfigInfo->igc_TcpWindowSize = ulTemp;
  1560. }
  1561. status = GetRegDWORDValue(
  1562. Handle,
  1563. L"TcpInitialRTT",
  1564. &ulTemp
  1565. );
  1566. if (NT_SUCCESS(status)) {
  1567. ConfigInfo->igc_TcpInitialRTT = ulTemp;
  1568. }
  1569. status = GetRegDWORDValue(
  1570. Handle,
  1571. L"TcpDelAckTicks",
  1572. &ulTemp
  1573. );
  1574. if (NT_SUCCESS(status) && (ulTemp <= MAX_DEL_ACK_TICKS)) {
  1575. ConfigInfo->igc_TcpDelAckTicks = (uchar)ulTemp;
  1576. }
  1577. status = GetRegDWORDValue(
  1578. Handle,
  1579. L"TcpACKFrequency",
  1580. &ulTemp
  1581. );
  1582. if (NT_SUCCESS(status)) {
  1583. ConfigInfo->igc_TcpAckFrequency = (uchar)ulTemp;
  1584. }
  1585. GetInterfaceMetric(&ConfigInfo->igc_metric, Handle);
  1586. ConfigInfo->igc_iftype = 0; // by default its 0 means both ucast/mcast traffic allowed
  1587. status = GetRegDWORDValue(
  1588. Handle,
  1589. L"TypeofInterface",
  1590. &ulTemp
  1591. );
  1592. if (NT_SUCCESS(status)) {
  1593. ConfigInfo->igc_iftype = (uchar)ulTemp;
  1594. }
  1595. // Use global value by default.
  1596. ConfigInfo->igc_disablemediasense = DisableMediaSense ? TRUE : FALSE;
  1597. #if MILLEN
  1598. // Only Windows ME supports reading the per-interface setting from the
  1599. // registry. The global value is used for Win2000+.
  1600. status = GetRegDWORDValue(
  1601. Handle,
  1602. L"DisableDHCPMediaSense",
  1603. &ulTemp
  1604. );
  1605. if (NT_SUCCESS(status)) {
  1606. ConfigInfo->igc_disablemediasense = ulTemp ? TRUE : FALSE;
  1607. }
  1608. #endif // MILLEN
  1609. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-GetGeneralIFConfig [TRUE]\n")));
  1610. return TRUE;
  1611. }
  1612. NDIS_STATUS
  1613. GetIPConfigValue(
  1614. NDIS_HANDLE Handle,
  1615. PUNICODE_STRING IPConfig
  1616. )
  1617. /*++
  1618. Routine Description:
  1619. Called to get the IPConfig string value
  1620. Arguments:
  1621. Handle - Handle to use for reading config.
  1622. IPConfig - Pointer to Unicode string where IPConfig is stored.
  1623. Return Value:
  1624. Status of the operation.
  1625. --*/
  1626. {
  1627. NTSTATUS status;
  1628. PAGED_CODE();
  1629. IPConfig->MaximumLength = 200;
  1630. IPConfig->Buffer = CTEAllocMemBoot(IPConfig->MaximumLength);
  1631. if (IPConfig->Buffer == NULL) {
  1632. return (STATUS_INSUFFICIENT_RESOURCES);
  1633. }
  1634. status = GetRegMultiSZValue(
  1635. Handle,
  1636. L"IPConfig",
  1637. IPConfig
  1638. );
  1639. return status;
  1640. }
  1641. int
  1642. IsLLInterfaceValueNull(
  1643. NDIS_HANDLE Handle
  1644. )
  1645. /*++
  1646. Routine Description:
  1647. Called to see if the LLInterface value in the registry key for which the
  1648. handle is provided, is NULL or not.
  1649. Arguments:
  1650. Handle - Handle to use for reading config.
  1651. Return Value:
  1652. FALSE if value is not null
  1653. TRUE if it is null
  1654. --*/
  1655. {
  1656. UNICODE_STRING valueString;
  1657. ULONG valueType;
  1658. NTSTATUS status;
  1659. PAGED_CODE();
  1660. valueString.MaximumLength = 200;
  1661. valueString.Buffer = CTEAllocMemBoot(valueString.MaximumLength);
  1662. if (valueString.Buffer == NULL) {
  1663. return (FALSE);
  1664. }
  1665. status = GetRegSZValue(
  1666. Handle,
  1667. L"LLInterface",
  1668. &valueString,
  1669. &valueType
  1670. );
  1671. if (NT_SUCCESS(status) && (*(valueString.Buffer) != UNICODE_NULL)) {
  1672. CTEFreeMem(valueString.Buffer);
  1673. return FALSE;
  1674. } else {
  1675. CTEFreeMem(valueString.Buffer);
  1676. return TRUE;
  1677. }
  1678. }
  1679. NTSTATUS
  1680. GetLLInterfaceValue(
  1681. NDIS_HANDLE Handle,
  1682. PNDIS_STRING pValueString
  1683. )
  1684. /*++
  1685. Routine Description:
  1686. Called to read the LLInterface value in the registry key for which the
  1687. handle is provided.
  1688. Arguments:
  1689. Handle - Handle to use for reading config.
  1690. Return Value:
  1691. value of key
  1692. --*/
  1693. {
  1694. NTSTATUS status;
  1695. ULONG valueType;
  1696. PAGED_CODE();
  1697. status = GetRegSZValue(
  1698. Handle,
  1699. L"LLInterface",
  1700. pValueString,
  1701. &valueType
  1702. );
  1703. return status;
  1704. }
  1705. BOOLEAN
  1706. GetTempDHCPAddr(
  1707. NDIS_HANDLE Handle,
  1708. IPAddr * Tempdhcpaddr,
  1709. IPAddr * TempMask,
  1710. IPAddr * TempGWAddr,
  1711. PNDIS_STRING ConfigName
  1712. )
  1713. /*++
  1714. Routine Description:
  1715. Called to get temp dhcp address if dhcp is enabled
  1716. Arguments:
  1717. Handle - Handle to use for reading config.
  1718. Tempdhcpaddr - temporary addr, mask and gateway
  1719. TempMask
  1720. TempGWAddr
  1721. ConfigName - identifies the interface in logging failures.
  1722. Return Value:
  1723. --*/
  1724. {
  1725. NTSTATUS Status;
  1726. LARGE_INTEGER LeaseTime, systime;
  1727. IPAddr Addr;
  1728. UNICODE_STRING valueString;
  1729. ULONG valueType;
  1730. BOOLEAN ConversionStatus;
  1731. Status = GetRegLARGEINTValue(
  1732. Handle,
  1733. L"TempLeaseExpirationTime",
  1734. &LeaseTime
  1735. );
  1736. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1737. "LargeInt status %x\n", Status));
  1738. if (Status != STATUS_SUCCESS) {
  1739. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "No Lease time\n"));
  1740. return FALSE;
  1741. }
  1742. valueString.Length = 0;
  1743. valueString.MaximumLength = WORK_BUFFER_SIZE;
  1744. valueString.Buffer = (PWCHAR) CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1745. KeQuerySystemTime(&systime);
  1746. if (RtlLargeIntegerGreaterThan(systime, LeaseTime)) {
  1747. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1748. "Leastime > systime no tempdhcp\n"));
  1749. return FALSE;
  1750. }
  1751. Status = GetRegSZValue(
  1752. Handle,
  1753. L"TempIpAddress",
  1754. &valueString,
  1755. &valueType
  1756. );
  1757. if (!NT_SUCCESS(Status) || (*(valueString.Buffer) == UNICODE_NULL)) {
  1758. return FALSE;
  1759. }
  1760. ConversionStatus = IPConvertStringToAddress(
  1761. (valueString.Buffer),
  1762. Tempdhcpaddr
  1763. );
  1764. if (!ConversionStatus) {
  1765. return FALSE;
  1766. }
  1767. Status = GetRegSZValue(
  1768. Handle,
  1769. L"TempMask",
  1770. &valueString,
  1771. &valueType
  1772. );
  1773. if (!NT_SUCCESS(Status) || (*(valueString.Buffer) == UNICODE_NULL)) {
  1774. return FALSE;
  1775. }
  1776. ConversionStatus = IPConvertStringToAddress(
  1777. (valueString.Buffer),
  1778. TempMask
  1779. );
  1780. if (!ConversionStatus) {
  1781. return FALSE;
  1782. }
  1783. Status = GetRegMultiSZValue(
  1784. Handle,
  1785. L"DhcpDefaultGateway",
  1786. &valueString
  1787. );
  1788. if (NT_SUCCESS(Status) && (*(valueString.Buffer) != UNICODE_NULL)) {
  1789. PWCHAR addressString = valueString.Buffer;
  1790. uint numberOfGateways = 0;
  1791. while (*addressString != UNICODE_NULL) {
  1792. IPAddr addressValue;
  1793. BOOLEAN conversionStatus;
  1794. if (numberOfGateways >= MAX_DEFAULT_GWS) {
  1795. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1796. "Exceeded mac_default_gws %d\n", numberOfGateways));
  1797. break;
  1798. }
  1799. conversionStatus = IPConvertStringToAddress(
  1800. addressString,
  1801. &addressValue
  1802. );
  1803. if (conversionStatus && (addressValue != 0xFFFFFFFF)) {
  1804. if (addressValue != INADDR_ANY) {
  1805. TempGWAddr[numberOfGateways++] = addressValue;
  1806. }
  1807. }
  1808. //
  1809. // Walk over the entry we just processed.
  1810. //
  1811. while (*addressString++ != UNICODE_NULL);
  1812. }
  1813. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1814. "Temp gws - %d\n", numberOfGateways));
  1815. }
  1816. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1817. "tempdhcp: %x %x %x\n", Tempdhcpaddr, TempMask, TempGWAddr));
  1818. return TRUE;
  1819. }
  1820. IFAddrList *
  1821. GetIFAddrList(
  1822. UINT * NumAddr,
  1823. NDIS_HANDLE Handle,
  1824. UINT * EnableDhcp,
  1825. BOOLEAN PppIf,
  1826. PNDIS_STRING ConfigName
  1827. )
  1828. /*++
  1829. Routine Description:
  1830. Called to read the list of IF addresses and masks for an interface.
  1831. We'll get the address pointer first, then walk the list counting
  1832. to find out how many addresses we have. Then we allocate memory for the
  1833. list, and walk down the list converting them. After that we'll get
  1834. the mask list and convert it.
  1835. Arguments:
  1836. NumAddr - Where to return number of address we have.
  1837. Handle - Handle to use for reading config.
  1838. EnableDhcp - Whether or not dhcp is enabled.
  1839. ConfigName - identifies the interface in logging failures.
  1840. Return Value:
  1841. Pointer to IF address list if we get one, or NULL otherwise.
  1842. --*/
  1843. {
  1844. UNICODE_STRING_NEW ValueString;
  1845. NTSTATUS Status;
  1846. UINT AddressCount = 0;
  1847. UINT GoodAddresses = 0;
  1848. PWCHAR CurrentAddress;
  1849. PWCHAR CurrentMask;
  1850. PWCHAR AddressString;
  1851. PWCHAR MaskString;
  1852. IFAddrList *AddressList;
  1853. UINT i;
  1854. BOOLEAN ConversionStatus;
  1855. IPAddr AddressValue;
  1856. IPAddr MaskValue;
  1857. UCHAR TempBuffer[WORK_BUFFER_SIZE];
  1858. PAGED_CODE();
  1859. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1860. (DTEXT("+GetIFAddrList(%x, %x, %x)\n"), NumAddr, Handle, EnableDhcp));
  1861. // First, try to read the EnableDhcp Value.
  1862. Status = GetRegDWORDValue(
  1863. Handle,
  1864. L"EnableDHCP",
  1865. EnableDhcp
  1866. );
  1867. if (!NT_SUCCESS(Status)) {
  1868. *EnableDhcp = FALSE;
  1869. }
  1870. ValueString.Length = 0;
  1871. ValueString.MaximumLength = WORK_BUFFER_SIZE;
  1872. ValueString.Buffer = (PWCHAR) CTEAllocMemBoot(WORK_BUFFER_SIZE);
  1873. if (ValueString.Buffer == NULL) {
  1874. CTELogEvent(
  1875. IPDriverObject,
  1876. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  1877. 2,
  1878. 1,
  1879. &ConfigName->Buffer,
  1880. 0,
  1881. NULL
  1882. );
  1883. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1884. (DTEXT("GetIFAddrList: Failure to allocate memory.\n")));
  1885. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1886. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1887. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1888. return NULL;
  1889. }
  1890. // First, try to read the IpAddress string.
  1891. Status = GetRegMultiSZValueNew(
  1892. Handle,
  1893. L"IpAddress",
  1894. &ValueString
  1895. );
  1896. if (!NT_SUCCESS(Status)) {
  1897. CTELogEvent(
  1898. IPDriverObject,
  1899. EVENT_TCPIP_NO_ADDRESS_LIST,
  1900. 1,
  1901. 1,
  1902. &ConfigName->Buffer,
  1903. 0,
  1904. NULL
  1905. );
  1906. ExFreePool(ValueString.Buffer);
  1907. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1908. (DTEXT("GetIFAddrList: unable to read IP address list for adapter %ws.\n"),
  1909. ConfigName->Buffer));
  1910. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1911. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1912. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1913. return NULL;
  1914. }
  1915. AddressString = ExAllocatePoolWithTag(NonPagedPool, ValueString.MaximumLength, 'iPCT');
  1916. if (AddressString == NULL) {
  1917. CTELogEvent(
  1918. IPDriverObject,
  1919. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  1920. 2,
  1921. 1,
  1922. &ConfigName->Buffer,
  1923. 0,
  1924. NULL
  1925. );
  1926. ExFreePool(ValueString.Buffer);
  1927. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1928. (DTEXT("GetIFAddrList: unable to allocate memory for IP address list.\n")));
  1929. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1930. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1931. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1932. return NULL;
  1933. }
  1934. RtlCopyMemory(AddressString, ValueString.Buffer, ValueString.MaximumLength);
  1935. Status = GetRegMultiSZValueNew(
  1936. Handle,
  1937. L"Subnetmask",
  1938. &ValueString
  1939. );
  1940. #if MILLEN
  1941. if (!NT_SUCCESS(Status)) {
  1942. Status = GetRegMultiSZValueNew(
  1943. Handle,
  1944. L"IPMask",
  1945. &ValueString
  1946. );
  1947. }
  1948. #endif // MILLEN
  1949. if (!NT_SUCCESS(Status)) {
  1950. CTELogEvent(
  1951. IPDriverObject,
  1952. EVENT_TCPIP_NO_MASK_LIST,
  1953. 1,
  1954. 1,
  1955. &ConfigName->Buffer,
  1956. 0,
  1957. NULL
  1958. );
  1959. TCPTRACE((
  1960. "IP: Unable to read the subnet mask list for adapter %ws.\n"
  1961. " IP will not be operational on this adapter.\n",
  1962. ConfigName->Buffer
  1963. ));
  1964. ExFreePool(AddressString);
  1965. ExFreePool(ValueString.Buffer);
  1966. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1967. (DTEXT("GetIFAddrList: unable to read subnet mask list for adapter %ws.\n"),
  1968. ConfigName->Buffer));
  1969. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1970. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1971. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1972. return NULL;
  1973. }
  1974. MaskString = ExAllocatePoolWithTag(NonPagedPool, ValueString.MaximumLength, 'iPCT');
  1975. if (MaskString == NULL) {
  1976. CTELogEvent(
  1977. IPDriverObject,
  1978. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  1979. 3,
  1980. 1,
  1981. &ConfigName->Buffer,
  1982. 0,
  1983. NULL
  1984. );
  1985. ExFreePool(AddressString);
  1986. ExFreePool(ValueString.Buffer);
  1987. DEBUGMSG(DBG_ERROR && DBG_PNP,
  1988. (DTEXT("GetIFAddrList: unable to allocate memory for subnet mask list.\n")));
  1989. DEBUGMSG(DBG_TRACE && DBG_PNP,
  1990. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  1991. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  1992. return NULL;
  1993. }
  1994. RtlCopyMemory(MaskString, ValueString.Buffer, ValueString.MaximumLength);
  1995. CurrentAddress = AddressString;
  1996. CurrentMask = MaskString;
  1997. while (*CurrentAddress != UNICODE_NULL &&
  1998. *CurrentMask != UNICODE_NULL) {
  1999. // We have a potential IP address.
  2000. AddressCount++;
  2001. // Skip this one.
  2002. while (*CurrentAddress++ != UNICODE_NULL);
  2003. while (*CurrentMask++ != UNICODE_NULL);
  2004. }
  2005. if (AddressCount == 0) {
  2006. ExFreePool(AddressString);
  2007. ExFreePool(MaskString);
  2008. ExFreePool(ValueString.Buffer);
  2009. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2010. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  2011. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  2012. return NULL;
  2013. }
  2014. // Allocate memory.
  2015. AddressList = CTEAllocMemBoot(sizeof(IFAddrList) * AddressCount);
  2016. if (AddressList == NULL) {
  2017. CTELogEvent(
  2018. IPDriverObject,
  2019. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  2020. 2,
  2021. 1,
  2022. &ConfigName->Buffer,
  2023. 0,
  2024. NULL
  2025. );
  2026. ExFreePool(AddressString);
  2027. ExFreePool(MaskString);
  2028. ExFreePool(ValueString.Buffer);
  2029. DEBUGMSG(DBG_ERROR && DBG_PNP,
  2030. (DTEXT("GetIFAddrList: unable to allocate memory for IP address list.\n")));
  2031. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2032. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  2033. NULL, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  2034. return NULL;
  2035. }
  2036. // Walk the list again, converting each address.
  2037. CurrentAddress = AddressString;
  2038. CurrentMask = MaskString;
  2039. for (i = 0; i < AddressCount; i++) {
  2040. ConversionStatus = IPConvertStringToAddress(
  2041. CurrentAddress,
  2042. &AddressValue
  2043. );
  2044. if (!ConversionStatus || (AddressValue == 0xFFFFFFFF)) {
  2045. PWCHAR stringList[2];
  2046. stringList[0] = CurrentAddress;
  2047. stringList[1] = ConfigName->Buffer;
  2048. CTELogEvent(
  2049. IPDriverObject,
  2050. EVENT_TCPIP_INVALID_ADDRESS,
  2051. 1,
  2052. 2,
  2053. stringList,
  2054. 0,
  2055. NULL
  2056. );
  2057. DEBUGMSG(DBG_WARN && DBG_PNP,
  2058. (DTEXT("IPAddInterface: Invalid IP address %ws specified for \n")
  2059. TEXT("adapter %ws. Interface may not be init.\n"),
  2060. CurrentAddress, ConfigName->Buffer));
  2061. goto nextone;
  2062. }
  2063. // Now do the current mask.
  2064. ConversionStatus = IPConvertStringToAddress(
  2065. CurrentMask,
  2066. &MaskValue
  2067. );
  2068. if (!ConversionStatus) {
  2069. PWCHAR stringList[3];
  2070. stringList[0] = CurrentMask;
  2071. stringList[1] = CurrentAddress;
  2072. stringList[2] = ConfigName->Buffer;
  2073. CTELogEvent(
  2074. IPDriverObject,
  2075. EVENT_TCPIP_INVALID_MASK,
  2076. 1,
  2077. 3,
  2078. stringList,
  2079. 0,
  2080. NULL
  2081. );
  2082. DEBUGMSG(DBG_WARN && DBG_PNP,
  2083. (DTEXT("IPAddInterface: Invalid IP mask %ws specified for \n")
  2084. TEXT("adapter %ws. Interface may not be init.\n"),
  2085. CurrentMask, ConfigName->Buffer));
  2086. } else {
  2087. AddressList[GoodAddresses].ial_addr = AddressValue;
  2088. AddressList[GoodAddresses].ial_mask = MaskValue;
  2089. GoodAddresses++;
  2090. }
  2091. nextone:
  2092. while (*CurrentAddress++ != UNICODE_NULL);
  2093. while (*CurrentMask++ != UNICODE_NULL);
  2094. }
  2095. ExFreePool(AddressString);
  2096. ExFreePool(MaskString);
  2097. ExFreePool(ValueString.Buffer);
  2098. *NumAddr = GoodAddresses;
  2099. if (GoodAddresses == 0) {
  2100. ExFreePool(AddressList);
  2101. AddressList = NULL;
  2102. }
  2103. #if MILLEN
  2104. //
  2105. // So Millennium may not have the EnableDHCP registry key present, but
  2106. // we still may want to detect this. So if EnableDHCP is not set, and
  2107. // there is only one address which is NULL and it is not a PPP interface,
  2108. // then we set EnableDHCP to true.
  2109. //
  2110. if (*EnableDhcp == FALSE &&
  2111. GoodAddresses == 1 &&
  2112. AddressList[0].ial_addr == NULL_IP_ADDR &&
  2113. AddressList[0].ial_mask == NULL_IP_ADDR &&
  2114. PppIf == FALSE
  2115. ) {
  2116. *EnableDhcp = TRUE;
  2117. }
  2118. #endif // MILLEN
  2119. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2120. (DTEXT("-GetIFAddrList [%x] Status %x NumAddr %d, EnableDhcp = %s\n"),
  2121. AddressList, Status, *NumAddr, *EnableDhcp ? TEXT("TRUE") : TEXT("FALSE")));
  2122. return AddressList;
  2123. }
  2124. #if MILLEN
  2125. //* OpenIFConfig - Open our per-IF config. info,
  2126. //
  2127. // Called when we want to open our per-info config info. We do so if we can,
  2128. // otherwise we fail the request.
  2129. //
  2130. // Input: ConfigName - Name of interface to open.
  2131. // Handle - Where to return the handle.
  2132. //
  2133. // Returns: TRUE if we succeed, FALSE if we don't.
  2134. //
  2135. uint
  2136. OpenIFConfig(PNDIS_STRING ConfigName, NDIS_HANDLE * Handle)
  2137. {
  2138. NDIS_STATUS Status; // Status of open attempt.
  2139. HANDLE myRegKey;
  2140. UINT RetStatus = FALSE;
  2141. PWCHAR Config = NULL;
  2142. DEBUGMSG(DBG_TRACE && DBG_PNP,
  2143. (DTEXT("+OpenIFConfig(%x, %x)\n"), ConfigName, Handle));
  2144. *Handle = NULL;
  2145. //
  2146. // We need to ensure that the buffer is NULL terminated since we are passing
  2147. // in just PWCHAR to OpenRegKey.
  2148. //
  2149. Config = ExAllocatePoolWithTag(
  2150. NonPagedPool,
  2151. ConfigName->Length + sizeof(WCHAR),
  2152. 'iPCT');
  2153. if (Config == NULL) {
  2154. goto done;
  2155. }
  2156. // Copy the configuration name into new buffer.
  2157. RtlZeroMemory(Config, ConfigName->Length + sizeof(WCHAR));
  2158. RtlCopyMemory(Config, ConfigName->Buffer, ConfigName->Length);
  2159. Status = OpenRegKey(&myRegKey, Config);
  2160. if (Status == NDIS_STATUS_SUCCESS) {
  2161. *Handle = myRegKey;
  2162. RetStatus = TRUE;
  2163. }
  2164. done:
  2165. if (Config) {
  2166. ExFreePool(Config);
  2167. }
  2168. DEBUGMSG(DBG_TRACE && DBG_PNP, (DTEXT("-OpenIFConfig [%s] Handle %x\n"),
  2169. RetStatus == TRUE ? TEXT("TRUE") : TEXT("FALSE"), *Handle));
  2170. return RetStatus;
  2171. }
  2172. #else // MILLEN
  2173. UINT
  2174. OpenIFConfig(
  2175. PNDIS_STRING ConfigName,
  2176. NDIS_HANDLE * Handle
  2177. )
  2178. /*++
  2179. Routine Description:
  2180. Called when we want to open our per-info config info. We do so if we can,
  2181. otherwise we fail the request.
  2182. Arguments:
  2183. ConfigName - Name of interface to open.
  2184. Handle - Where to return the handle.
  2185. Return Value:
  2186. TRUE if we succeed, FALSE if we don't.
  2187. --*/
  2188. {
  2189. NTSTATUS status;
  2190. HANDLE myRegKey;
  2191. UNICODE_STRING valueString;
  2192. WCHAR ServicesRegistryKey[] =
  2193. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
  2194. UINT RetStatus = FALSE;
  2195. PAGED_CODE();
  2196. valueString.MaximumLength =
  2197. ConfigName->MaximumLength +
  2198. ((wcslen(ServicesRegistryKey) + 2) * sizeof(WCHAR));
  2199. valueString.Buffer = ExAllocatePoolWithTag(
  2200. NonPagedPool,
  2201. valueString.MaximumLength,
  2202. 'iPCT'
  2203. );
  2204. if (valueString.Buffer == NULL) {
  2205. CTELogEvent(
  2206. IPDriverObject,
  2207. EVENT_TCPIP_NO_ADAPTER_RESOURCES,
  2208. 4,
  2209. 1,
  2210. &ConfigName->Buffer,
  2211. 0,
  2212. NULL
  2213. );
  2214. TCPTRACE(("IP: Unable to allocate memory for reg key name\n"));
  2215. return (FALSE);
  2216. }
  2217. RtlZeroMemory(valueString.Buffer,
  2218. valueString.MaximumLength);
  2219. valueString.Length = 0;
  2220. valueString.Buffer[0] = UNICODE_NULL;
  2221. //
  2222. // Build the key name for the tcpip parameters section and open key.
  2223. // Setting Length = 0 and using append is like initializing the string
  2224. //
  2225. status = RtlAppendUnicodeToString(&valueString, ServicesRegistryKey);
  2226. if (!NT_SUCCESS(status)) {
  2227. CTELogEvent(
  2228. IPDriverObject,
  2229. EVENT_TCPIP_ADAPTER_REG_FAILURE,
  2230. 1,
  2231. 1,
  2232. &ConfigName->Buffer,
  2233. 0,
  2234. NULL
  2235. );
  2236. TCPTRACE(("IP: Unable to append services name to key string\n"));
  2237. goto done;
  2238. }
  2239. status = RtlAppendUnicodeStringToString(&valueString,
  2240. ConfigName);
  2241. if (!NT_SUCCESS(status)) {
  2242. CTELogEvent(
  2243. IPDriverObject,
  2244. EVENT_TCPIP_ADAPTER_REG_FAILURE,
  2245. 2,
  2246. 1,
  2247. &ConfigName->Buffer,
  2248. 0,
  2249. NULL
  2250. );
  2251. TCPTRACE(("IP: Unable to append adapter name to key string\n"));
  2252. goto done;
  2253. }
  2254. status = OpenRegKey(&myRegKey, valueString.Buffer);
  2255. if (!NT_SUCCESS(status)) {
  2256. CTELogEvent(
  2257. IPDriverObject,
  2258. EVENT_TCPIP_ADAPTER_REG_FAILURE,
  2259. 4,
  2260. 1,
  2261. &ConfigName->Buffer,
  2262. 0,
  2263. NULL
  2264. );
  2265. TCPTRACE((
  2266. "IP: Unable to open adapter registry key %ws\n",
  2267. valueString.Buffer
  2268. ));
  2269. //ASSERT(FALSE);
  2270. } else {
  2271. RetStatus = TRUE;
  2272. *Handle = myRegKey;
  2273. }
  2274. done:
  2275. ExFreePool(valueString.Buffer);
  2276. return RetStatus;
  2277. }
  2278. #endif // !MILLEN
  2279. VOID
  2280. CloseIFConfig(
  2281. NDIS_HANDLE Handle
  2282. )
  2283. /*++
  2284. Routine Description:
  2285. Close a per-interface config handle opened via OpenIFConfig().
  2286. Arguments:
  2287. Handle - Handle to be closed.
  2288. Return Value:
  2289. --*/
  2290. {
  2291. PAGED_CODE();
  2292. ZwClose(Handle);
  2293. }
  2294. IPConfigInfo *
  2295. IPGetConfig(
  2296. void
  2297. )
  2298. /*++
  2299. Routine Description:
  2300. Provides IP configuration information for the NT environment.
  2301. Arguments:
  2302. None
  2303. Return Value:
  2304. A pointer to a structure containing the configuration information.
  2305. --*/
  2306. {
  2307. return (IPConfiguration);
  2308. }
  2309. void
  2310. IPFreeConfig(
  2311. IPConfigInfo * ConfigInfo
  2312. )
  2313. /*++
  2314. Routine Description:
  2315. Frees the IP configuration structure allocated by IPGetConfig.
  2316. Arguments:
  2317. ConfigInfo - Pointer to the IP configuration information structure to free.
  2318. Return Value:
  2319. None.
  2320. --*/
  2321. {
  2322. int i;
  2323. if (IPConfiguration != NULL) {
  2324. CTEFreeMem(IPConfiguration);
  2325. }
  2326. IPConfiguration = NULL;
  2327. return;
  2328. }
  2329. ulong
  2330. GetGMTDelta(
  2331. void
  2332. )
  2333. /*++
  2334. Routine Description:
  2335. Returns the offset in milliseconds of the time zone of this machine
  2336. from GMT.
  2337. Arguments:
  2338. None.
  2339. Return Value:
  2340. Time in milliseconds between this time zone and GMT.
  2341. --*/
  2342. {
  2343. #if MILLEN
  2344. return (-1); // Error not supported.
  2345. #else // MILLEN
  2346. LARGE_INTEGER localTime, systemTime;
  2347. //
  2348. // Get time zone bias in 100ns.
  2349. //
  2350. localTime.LowPart = 0;
  2351. localTime.HighPart = 0;
  2352. ExLocalTimeToSystemTime(&localTime, &systemTime);
  2353. if ((localTime.LowPart != 0) || (localTime.HighPart != 0)) {
  2354. localTime = CTEConvert100nsToMilliseconds(systemTime);
  2355. }
  2356. ASSERT(localTime.HighPart == 0);
  2357. return (localTime.LowPart);
  2358. #endif // !MILLEN
  2359. }
  2360. ulong
  2361. GetTime(
  2362. void
  2363. )
  2364. /*++
  2365. Routine Description:
  2366. Returns the time in milliseconds since midnight.
  2367. Arguments:
  2368. None.
  2369. Return Value:
  2370. Time in milliseconds since midnight.
  2371. --*/
  2372. {
  2373. LARGE_INTEGER ntTime;
  2374. TIME_FIELDS breakdownTime;
  2375. ulong returnValue;
  2376. KeQuerySystemTime(&ntTime);
  2377. RtlTimeToTimeFields(&ntTime, &breakdownTime);
  2378. returnValue = breakdownTime.Hour * 60;
  2379. returnValue = (returnValue + breakdownTime.Minute) * 60;
  2380. returnValue = (returnValue + breakdownTime.Second) * 1000;
  2381. returnValue = returnValue + breakdownTime.Milliseconds;
  2382. return (returnValue);
  2383. }
  2384. ulong
  2385. GetUnique32BitValue(
  2386. void
  2387. )
  2388. /*++
  2389. Routine Description:
  2390. Returns a reasonably unique 32-bit number based on the system clock.
  2391. In NT, we take the current system time, convert it to milliseconds,
  2392. and return the low 32 bits.
  2393. Arguments:
  2394. None.
  2395. Return Value:
  2396. A reasonably unique 32-bit value.
  2397. --*/
  2398. {
  2399. LARGE_INTEGER ntTime, tmpTime;
  2400. KeQuerySystemTime(&ntTime);
  2401. tmpTime = CTEConvert100nsToMilliseconds(ntTime);
  2402. return (tmpTime.LowPart);
  2403. }
  2404. uint
  2405. UseEtherSNAP(
  2406. PNDIS_STRING Name
  2407. )
  2408. /*++
  2409. Routine Description:
  2410. Determines whether the EtherSNAP protocol should be used on an interface.
  2411. Arguments:
  2412. Name - The device name of the interface in question.
  2413. Return Value:
  2414. Nonzero if SNAP is to be used on the interface. Zero otherwise.
  2415. --*/
  2416. {
  2417. UNREFERENCED_PARAMETER(Name);
  2418. //
  2419. // We currently set this on a global basis.
  2420. //
  2421. return (ArpUseEtherSnap);
  2422. }
  2423. void
  2424. GetAlwaysSourceRoute(
  2425. uint * pArpAlwaysSourceRoute,
  2426. uint * pIPAlwaysSourceRoute
  2427. )
  2428. /*++
  2429. Routine Description:
  2430. Determines whether ARP should always turn on source routing in queries.
  2431. Arguments:
  2432. None.
  2433. Return Value:
  2434. Nonzero if source routing is always to be used. Zero otherwise.
  2435. --*/
  2436. {
  2437. //
  2438. // We currently set this on a global basis.
  2439. //
  2440. *pArpAlwaysSourceRoute = ArpAlwaysSourceRoute;
  2441. *pIPAlwaysSourceRoute = IPAlwaysSourceRoute;
  2442. return;
  2443. }
  2444. uint
  2445. GetArpCacheLife(
  2446. void
  2447. )
  2448. /*++
  2449. Routine Description:
  2450. Get ArpCacheLife in seconds.
  2451. Arguments:
  2452. None.
  2453. Return Value:
  2454. Set to default if not found.
  2455. --*/
  2456. {
  2457. //
  2458. // We currently set this on a global basis.
  2459. //
  2460. return (ArpCacheLife);
  2461. }
  2462. uint
  2463. GetArpRetryCount(
  2464. void
  2465. )
  2466. /*++
  2467. Routine Description:
  2468. Get ArpRetryCount
  2469. Arguments:
  2470. None.
  2471. Return Value:
  2472. Set to default if not found.
  2473. --*/
  2474. {
  2475. //
  2476. // We currently set this on a global basis.
  2477. //
  2478. return (ArpRetryCount);
  2479. }
  2480. #define IP_ADDRESS_STRING_LENGTH (16+2) // +2 for double NULL on MULTI_SZ
  2481. BOOLEAN
  2482. IPConvertStringToAddress(
  2483. IN PWCHAR AddressString,
  2484. OUT PULONG IpAddress
  2485. )
  2486. /*++
  2487. Routine Description
  2488. This function converts an Internet standard 4-octet dotted decimal
  2489. IP address string into a numeric IP address. Unlike inet_addr(), this
  2490. routine does not support address strings of less than 4 octets nor does
  2491. it support octal and hexadecimal octets, and it returns the address
  2492. in host byte order, rather than network byte order.
  2493. Arguments
  2494. AddressString - IP address in dotted decimal notation
  2495. IpAddress - Pointer to a variable to hold the resulting address
  2496. Return Value:
  2497. TRUE if the address string was converted. FALSE otherwise.
  2498. --*/
  2499. {
  2500. #if !MILLEN
  2501. NTSTATUS status;
  2502. PWCHAR endPointer;
  2503. status = RtlIpv4StringToAddressW(AddressString, TRUE, &endPointer,
  2504. (struct in_addr *)IpAddress);
  2505. if (!NT_SUCCESS(status)) {
  2506. return (FALSE);
  2507. }
  2508. *IpAddress = net_long(*IpAddress);
  2509. return (*endPointer == '\0');
  2510. #else // MILLEN
  2511. UNICODE_STRING unicodeString;
  2512. STRING aString;
  2513. UCHAR dataBuffer[IP_ADDRESS_STRING_LENGTH];
  2514. NTSTATUS status;
  2515. PUCHAR addressPtr, cp, startPointer, endPointer;
  2516. ULONG digit, multiplier;
  2517. int i;
  2518. PAGED_CODE();
  2519. aString.Length = 0;
  2520. aString.MaximumLength = IP_ADDRESS_STRING_LENGTH;
  2521. aString.Buffer = dataBuffer;
  2522. RtlInitUnicodeString(&unicodeString, AddressString);
  2523. status = RtlUnicodeStringToAnsiString(
  2524. &aString,
  2525. &unicodeString,
  2526. FALSE
  2527. );
  2528. if (!NT_SUCCESS(status)) {
  2529. return (FALSE);
  2530. }
  2531. *IpAddress = 0;
  2532. addressPtr = (PUCHAR) IpAddress;
  2533. startPointer = dataBuffer;
  2534. endPointer = dataBuffer;
  2535. i = 3;
  2536. while (i >= 0) {
  2537. //
  2538. // Collect the characters up to a '.' or the end of the string.
  2539. //
  2540. while ((*endPointer != '.') && (*endPointer != '\0')) {
  2541. endPointer++;
  2542. }
  2543. if (startPointer == endPointer) {
  2544. return (FALSE);
  2545. }
  2546. //
  2547. // Convert the number.
  2548. //
  2549. for (cp = (endPointer - 1), multiplier = 1, digit = 0;
  2550. cp >= startPointer;
  2551. cp--, multiplier *= 10
  2552. ) {
  2553. if ((*cp < '0') || (*cp > '9') || (multiplier > 100)) {
  2554. return (FALSE);
  2555. }
  2556. digit += (multiplier * ((ULONG) (*cp - '0')));
  2557. }
  2558. if (digit > 255) {
  2559. return (FALSE);
  2560. }
  2561. addressPtr[i] = (UCHAR) digit;
  2562. //
  2563. // We are finished if we have found and converted 4 octets and have
  2564. // no other characters left in the string.
  2565. //
  2566. if ((i-- == 0) &&
  2567. ((*endPointer == '\0') || (*endPointer == ' '))
  2568. ) {
  2569. return (TRUE);
  2570. }
  2571. if (*endPointer == '\0') {
  2572. return (FALSE);
  2573. }
  2574. startPointer = ++endPointer;
  2575. }
  2576. return (FALSE);
  2577. #endif // MILLEN
  2578. }
  2579. ULONG
  2580. RouteMatch(
  2581. IN WCHAR * RouteString,
  2582. IN IPAddr Address,
  2583. IN IPMask Mask,
  2584. OUT IPAddr * DestVal,
  2585. OUT IPMask * DestMask,
  2586. OUT IPAddr * GateVal,
  2587. OUT ULONG * Metric
  2588. )
  2589. /*++
  2590. Routine Description
  2591. This function checks if a perisitent route should be assigned to
  2592. a given interface based on the interface address & mask.
  2593. Arguments
  2594. RouteString - A NULL-terminated route laid out as Dest,Mask,Gate.
  2595. Address - The IP address of the interface being processed.
  2596. Mask - The subnet mask of the interface being processed.
  2597. DestVal - A pointer to the decoded destination IP address.
  2598. DestVal - A pointer to the decoded destination subnet mask.
  2599. DestVal - A pointer to the decoded destination first hop gateway.
  2600. Metric - A pointer to the decoded route metric.
  2601. Return Value:
  2602. The route type, IRE_TYPE_DIRECT or IRE_TYPE_INDIRECT, if the route
  2603. should be added to the interface, IRE_TYPE_INVALID otherwise.
  2604. --*/
  2605. {
  2606. #define ROUTE_SEPARATOR L','
  2607. WCHAR *labelPtr;
  2608. WCHAR *indexPtr = RouteString;
  2609. ULONG i;
  2610. UNICODE_STRING ustring;
  2611. NTSTATUS status;
  2612. BOOLEAN noMetric = FALSE;
  2613. PAGED_CODE();
  2614. //
  2615. // The route is laid out in the string as "Dest,Mask,Gateway,Metric".
  2616. // The metric may not be there if this system was upgraded from
  2617. // NT 3.51.
  2618. //
  2619. // Parse the string and convert each label.
  2620. //
  2621. for (i = 0; i < 4; i++) {
  2622. labelPtr = indexPtr;
  2623. while (1) {
  2624. if (*indexPtr == UNICODE_NULL) {
  2625. if ((i < 2) || (indexPtr == labelPtr)) {
  2626. return (IRE_TYPE_INVALID);
  2627. }
  2628. if (i == 2) {
  2629. //
  2630. // Old route - no metric.
  2631. //
  2632. noMetric = TRUE;
  2633. }
  2634. break;
  2635. }
  2636. if (*indexPtr == ROUTE_SEPARATOR) {
  2637. *indexPtr = UNICODE_NULL;
  2638. break;
  2639. }
  2640. indexPtr++;
  2641. }
  2642. switch (i) {
  2643. case 0:
  2644. if (!IPConvertStringToAddress(labelPtr, DestVal)) {
  2645. return (IRE_TYPE_INVALID);
  2646. }
  2647. break;
  2648. case 1:
  2649. if (!IPConvertStringToAddress(labelPtr, DestMask)) {
  2650. return (IRE_TYPE_INVALID);
  2651. }
  2652. break;
  2653. case 2:
  2654. if (!IPConvertStringToAddress(labelPtr, GateVal)) {
  2655. return (IRE_TYPE_INVALID);
  2656. }
  2657. break;
  2658. case 3:
  2659. RtlInitUnicodeString(&ustring, labelPtr);
  2660. status = RtlUnicodeStringToInteger(
  2661. &ustring,
  2662. 0,
  2663. Metric
  2664. );
  2665. if (!NT_SUCCESS(status)) {
  2666. return (IRE_TYPE_INVALID);
  2667. }
  2668. break;
  2669. default:
  2670. ASSERT(0);
  2671. return (IRE_TYPE_INVALID);
  2672. }
  2673. if (noMetric) {
  2674. //
  2675. // Default to 1.
  2676. //
  2677. *Metric = 1;
  2678. break;
  2679. }
  2680. indexPtr++;
  2681. }
  2682. if (IP_ADDR_EQUAL(*GateVal, Address)) {
  2683. return (IRE_TYPE_DIRECT);
  2684. }
  2685. if (IP_ADDR_EQUAL((*GateVal & Mask), (Address & Mask))) {
  2686. return (IRE_TYPE_INDIRECT);
  2687. }
  2688. return (IRE_TYPE_INVALID);
  2689. }
  2690. VOID
  2691. SetPersistentRoutesForNTE(
  2692. IPAddr Address,
  2693. IPMask Mask,
  2694. ULONG IFIndex
  2695. )
  2696. /*++
  2697. Routine Description
  2698. Adds persistent routes that match an interface. The routes are read
  2699. from a list in the registry.
  2700. Arguments
  2701. Address - The address of the new interface
  2702. Mask - The subnet mask of the new interface.
  2703. IFIndex - The index of the new interface.
  2704. Return Value:
  2705. None.
  2706. --*/
  2707. {
  2708. #define ROUTE_DATA_STRING_SIZE (51 * sizeof(WCHAR))
  2709. #define BASIC_INFO_SIZE (sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR) + ROUTE_DATA_STRING_SIZE)
  2710. #if !MILLEN
  2711. WCHAR IPRoutesRegistryKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\PersistentRoutes";
  2712. #else // !MILLEN
  2713. WCHAR IPRoutesRegistryKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\VxD\\MSTCP\\PersistentRoutes";
  2714. #endif // MILLEN
  2715. UCHAR workbuf[BASIC_INFO_SIZE];
  2716. PKEY_VALUE_BASIC_INFORMATION basicInfo = (PKEY_VALUE_BASIC_INFORMATION) workbuf;
  2717. ULONG resultLength;
  2718. ULONG type;
  2719. HANDLE regKey;
  2720. IPAddr destVal;
  2721. IPMask destMask;
  2722. IPAddr gateVal;
  2723. ULONG metric;
  2724. TDIObjectID id;
  2725. ULONG enumIndex = 0;
  2726. CTELockHandle TableHandle;
  2727. RouteTableEntry *RTE, *TempRTE;
  2728. IPRouteEntry routeEntry;
  2729. NTSTATUS status, setStatus;
  2730. DEBUGMSG(DBG_TRACE && DBG_ROUTE,
  2731. (DTEXT("+SetPersistenRoutesForNTE(%x, %x, %x)\n"),
  2732. Address, Mask, IFIndex));
  2733. //
  2734. // Open the registry key to read list of persistant routes
  2735. //
  2736. status = OpenRegKey(&regKey, IPRoutesRegistryKey);
  2737. DEBUGMSG(DBG_WARN && !NT_SUCCESS(status),
  2738. (DTEXT("SetPersistentRoutesForNTE: failed to open registry key %ls\n"),
  2739. IPRoutesRegistryKey));
  2740. if (NT_SUCCESS(status)) {
  2741. do {
  2742. //
  2743. // Enum each route from the registry list
  2744. //
  2745. status = ZwEnumerateValueKey(
  2746. regKey,
  2747. enumIndex,
  2748. KeyValueBasicInformation,
  2749. basicInfo,
  2750. BASIC_INFO_SIZE - sizeof(WCHAR),
  2751. &resultLength
  2752. );
  2753. if (!NT_SUCCESS(status)) {
  2754. if (status == STATUS_BUFFER_OVERFLOW) {
  2755. continue;
  2756. }
  2757. break;
  2758. }
  2759. #if !MILLEN
  2760. // Millennium seems to return REG_NONE in this case for some reason.
  2761. // Do we really care, since we are just using the name, and not the
  2762. // value?
  2763. if (basicInfo->Type != REG_SZ) {
  2764. DEBUGMSG(DBG_ERROR,
  2765. (DTEXT("SetPersistentRoutesForNTE: !NOT REG_SZ!\n")));
  2766. continue;
  2767. }
  2768. #endif // MILLEN
  2769. DEBUGMSG(DBG_INFO && DBG_ROUTE,
  2770. (DTEXT("SetPersistentRoutesForNTE: read key: %ls\n"),
  2771. basicInfo->Name));
  2772. //
  2773. // Ensure NULL termination
  2774. //
  2775. basicInfo->Name[basicInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
  2776. basicInfo->NameLength += sizeof(WCHAR);
  2777. type = RouteMatch(
  2778. basicInfo->Name,
  2779. Address,
  2780. Mask,
  2781. &destVal,
  2782. &destMask,
  2783. &gateVal,
  2784. &metric
  2785. );
  2786. DEBUGMSG(DBG_WARN && type == IRE_TYPE_INVALID,
  2787. (DTEXT("SetPersistentRoutesForNTE: RouteMatch returned IRE_TYPE_INVALID\n")));
  2788. if (type != IRE_TYPE_INVALID) {
  2789. //
  2790. // Do we already have a route with dest, mask ?
  2791. //
  2792. routeEntry.ire_dest = net_long(destVal);
  2793. routeEntry.ire_mask = net_long(destMask);
  2794. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  2795. RTE = FindMatchingRTE(routeEntry.ire_dest,
  2796. routeEntry.ire_mask,
  2797. 0, 0,
  2798. &TempRTE,
  2799. MATCH_NONE);
  2800. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  2801. DEBUGMSG(DBG_WARN && RTE,
  2802. (DTEXT("SetPersistentRoutesForNTE: route already exists RTE %x\n"),
  2803. RTE));
  2804. if (!RTE) {
  2805. //
  2806. // We do not have a route, so add this one
  2807. //
  2808. id.toi_entity.tei_entity = CL_NL_ENTITY;
  2809. id.toi_entity.tei_instance = 0;
  2810. id.toi_class = INFO_CLASS_PROTOCOL;
  2811. id.toi_type = INFO_TYPE_PROVIDER;
  2812. id.toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  2813. routeEntry.ire_nexthop = net_long(gateVal);
  2814. routeEntry.ire_type = type;
  2815. routeEntry.ire_metric1 = metric;
  2816. routeEntry.ire_index = IFIndex;
  2817. routeEntry.ire_metric2 = (ULONG) - 1;
  2818. routeEntry.ire_metric3 = (ULONG) - 1;
  2819. routeEntry.ire_metric4 = (ULONG) - 1;
  2820. routeEntry.ire_metric5 = (ULONG) - 1;
  2821. routeEntry.ire_proto = IRE_PROTO_PERSIST_LOCAL;
  2822. routeEntry.ire_age = 0;
  2823. setStatus = IPSetInfo(
  2824. &id,
  2825. &routeEntry,
  2826. sizeof(IPRouteEntry)
  2827. );
  2828. DEBUGMSG(DBG_WARN && setStatus != IP_SUCCESS,
  2829. (DTEXT("SetPersistentRoutesForNTE: faile to add route [%x, %x, %x, %d], status %d\n"),
  2830. destVal, destMask, gateVal, metric, setStatus));
  2831. }
  2832. }
  2833. } while (++enumIndex);
  2834. ZwClose(regKey);
  2835. }
  2836. }
  2837. extern NetTableEntry *LoopNTE;
  2838. VOID
  2839. IPUnload(
  2840. IN PDRIVER_OBJECT DriverObject
  2841. )
  2842. /*++
  2843. Routine Description:
  2844. This routine cleans up the IP layer.
  2845. Arguments:
  2846. DriverObject - Pointer to driver object created by the system.
  2847. Return Value:
  2848. None. When the function returns, the driver is unloaded.
  2849. --*/
  2850. {
  2851. PNDIS_BUFFER Buffer;
  2852. PSINGLE_LIST_ENTRY BufferLink;
  2853. PNDIS_PACKET Packet;
  2854. PacketContext *PC;
  2855. struct PCCommon *Common;
  2856. CTELockHandle Handle;
  2857. NdisResEntry *nrEntry;
  2858. NdisResEntry *nextEntry;
  2859. #if IPMCAST
  2860. if(IpMcastDeviceObject != NULL)
  2861. {
  2862. DeinitializeIpMcast(IpMcastDeviceObject);
  2863. }
  2864. #endif // IPMCAST
  2865. //
  2866. // Free up loopback resources
  2867. //
  2868. CTEInitBlockStrucEx(&LoopNTE->nte_timerblock);
  2869. LoopNTE->nte_if->if_flags |= IF_FLAGS_DELETING;
  2870. if ((LoopNTE->nte_flags & NTE_TIMER_STARTED) &&
  2871. !CTEStopTimer(&LoopNTE->nte_timer)) {
  2872. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not stop loopback timer - waiting on unload event\n"));
  2873. (VOID) CTEBlock(&LoopNTE->nte_timerblock);
  2874. KeClearEvent(&LoopNTE->nte_timerblock.cbs_event);
  2875. }
  2876. CTEFreeMem(LoopNTE);
  2877. //
  2878. // Shut down all timers
  2879. // NTE timers are stopped at DelIF time
  2880. //
  2881. CTEInitBlockStrucEx(&TcpipUnloadBlock);
  2882. fRouteTimerStopping = TRUE;
  2883. if (!CTEStopTimer(&IPRouteTimer)) {
  2884. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Could not stop route timer - waiting on unload event\n"));
  2885. #if !MILLEN
  2886. if (KeReadStateEvent(&(TcpipUnloadBlock.cbs_event))) {
  2887. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Event is signaled...\n"));
  2888. }
  2889. #endif // !MILLEN
  2890. (VOID) CTEBlock(&TcpipUnloadBlock);
  2891. KeClearEvent(&TcpipUnloadBlock.cbs_event);
  2892. }
  2893. //
  2894. // Free any residual memory - IP buffer/pkt pools
  2895. //
  2896. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Freeing Header buffer pools...\n"));
  2897. MdpDestroyPool(IpHeaderPool);
  2898. NdisFreePacketPool(NdisPacketPool);
  2899. if (TDBufferPool) {
  2900. NdisFreeBufferPool(TDBufferPool);
  2901. TDBufferPool = NULL;
  2902. }
  2903. if (TDPacketPool) {
  2904. NdisFreePacketPool(TDPacketPool);
  2905. TDPacketPool = NULL;
  2906. }
  2907. if (IPProviderHandle) {
  2908. TdiDeregisterProvider(IPProviderHandle);
  2909. }
  2910. //
  2911. // Free the cached entity-list
  2912. //
  2913. if (IPEntityList) {
  2914. CTEFreeMem(IPEntityList);
  2915. IPEntityList = NULL;
  2916. IPEntityCount = 0;
  2917. }
  2918. //
  2919. // Free the list of bindings
  2920. //
  2921. if (IPBindList) {
  2922. CTEFreeMem(IPBindList);
  2923. IPBindList = NULL;
  2924. }
  2925. //
  2926. // Free firewall-hook resources
  2927. //
  2928. FreeFirewallQ();
  2929. //
  2930. // Call into TCP so it can shut down
  2931. //
  2932. TCPUnload(DriverObject);
  2933. //
  2934. // Delete the IP device
  2935. //
  2936. IoDeleteDevice(IPDeviceObject);
  2937. }
  2938. NTSTATUS
  2939. IPAddNTEContextList(
  2940. HANDLE KeyHandle,
  2941. ushort contextValue,
  2942. uint isPrimary
  2943. )
  2944. /*++
  2945. Routine Description:
  2946. Writes the interface context of the NTE in the registry.
  2947. Arguments:
  2948. KeyHandle - Open handle to the parent key of the value to write.
  2949. contextvalue - The context value of the NTE
  2950. isPrimary -whether or not this is a Primary NTE
  2951. Return Value:
  2952. STATUS_SUCCESS or an appropriate failure code.
  2953. --*/
  2954. {
  2955. UNICODE_STRING_NEW contextString; // buffer holding the nte context list
  2956. NTSTATUS status; // status of this operation
  2957. PWSTR nextContext; // buffer where next context is stored
  2958. int i, nextDigit;
  2959. contextString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE * sizeof(WCHAR));
  2960. if (contextString.Buffer == NULL) {
  2961. CTELogEvent(
  2962. IPDriverObject,
  2963. EVENT_TCPIP_NO_RESOURCES_FOR_INIT,
  2964. 3,
  2965. 0,
  2966. NULL,
  2967. 0,
  2968. NULL
  2969. );
  2970. status = STATUS_INSUFFICIENT_RESOURCES;
  2971. return status;
  2972. }
  2973. RtlZeroMemory(contextString.Buffer, WORK_BUFFER_SIZE * sizeof(WCHAR));
  2974. contextString.Buffer[0] = UNICODE_NULL;
  2975. contextString.Length = 0;
  2976. contextString.MaximumLength = WORK_BUFFER_SIZE * sizeof(WCHAR);
  2977. KeWaitForMutexObject(&NTEContextMutex, Executive, KernelMode, FALSE, NULL);
  2978. if (!isPrimary) {
  2979. status = GetRegMultiSZValueNew(
  2980. KeyHandle,
  2981. L"NTEContextList",
  2982. &contextString
  2983. );
  2984. if (NT_SUCCESS(status)) {
  2985. ASSERT(contextString.Length > 0);
  2986. if (contextString.MaximumLength >= (contextString.Length + (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR))) {
  2987. } else {
  2988. char *newBuf;
  2989. newBuf = CTEAllocMemBoot(contextString.Length + (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR));
  2990. if (!newBuf)
  2991. goto Exit;
  2992. RtlCopyMemory(newBuf, contextString.Buffer, contextString.Length);
  2993. RtlZeroMemory(newBuf + contextString.Length, (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR));
  2994. CTEFreeMem(contextString.Buffer);
  2995. contextString.MaximumLength = contextString.Length + (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR);
  2996. contextString.Buffer = (PWCHAR) newBuf;
  2997. }
  2998. nextContext = (PWCHAR) ((char *)contextString.Buffer + contextString.Length - 1 * sizeof(WCHAR));
  2999. RtlZeroMemory(nextContext, (2 + NTE_CONTEXT_SIZE) * sizeof(WCHAR));
  3000. contextString.Length += 1 * sizeof(WCHAR);
  3001. } else {
  3002. goto Exit;
  3003. }
  3004. } else {
  3005. // this is the first nte of this if.
  3006. // add 2 null chars in the length.
  3007. nextContext = contextString.Buffer;
  3008. contextString.Length += 2 * sizeof(WCHAR);
  3009. }
  3010. for (i = NTE_CONTEXT_SIZE; i >= 2;) {
  3011. nextDigit = contextValue % 16;
  3012. if (nextDigit >= 0 && nextDigit <= 9) {
  3013. nextContext[--i] = L'0' + nextDigit;
  3014. } else {
  3015. nextContext[--i] = L'A' + nextDigit - 10;
  3016. }
  3017. contextValue /= 16;
  3018. }
  3019. // now prepend 0x
  3020. nextContext[0] = L'0';
  3021. nextContext[1] = L'x';
  3022. contextString.Length += NTE_CONTEXT_SIZE * sizeof(WCHAR);
  3023. status = SetRegMultiSZValueNew(
  3024. KeyHandle,
  3025. L"NTEContextList",
  3026. &contextString
  3027. );
  3028. Exit:
  3029. KeReleaseMutex(&NTEContextMutex, FALSE);
  3030. if (contextString.Buffer) {
  3031. CTEFreeMem(contextString.Buffer);
  3032. }
  3033. return status;
  3034. }
  3035. NTSTATUS
  3036. IPDelNTEContextList(
  3037. HANDLE KeyHandle,
  3038. ushort contextValue
  3039. )
  3040. /*++
  3041. Routine Description:
  3042. Writes the interface context of the NTE in the registry.
  3043. Arguments:
  3044. KeyHandle - Open handle to the parent key of the value to write.
  3045. NTE - The pointer to the NTE
  3046. Return Value:
  3047. STATUS_SUCCESS or an appropriate failure code.
  3048. --*/
  3049. {
  3050. UNICODE_STRING_NEW contextString; // buffer holding the nte context list
  3051. NTSTATUS status; // status of this operation
  3052. PWSTR nextContext; // buffer where next context is stored
  3053. int i, nextDigit;
  3054. WCHAR thisContext[NTE_CONTEXT_SIZE];
  3055. contextString.Buffer = CTEAllocMemBoot(WORK_BUFFER_SIZE * sizeof(WCHAR));
  3056. if (contextString.Buffer == NULL) {
  3057. CTELogEvent(
  3058. IPDriverObject,
  3059. EVENT_TCPIP_NO_RESOURCES_FOR_INIT,
  3060. 3,
  3061. 0,
  3062. NULL,
  3063. 0,
  3064. NULL
  3065. );
  3066. status = STATUS_INSUFFICIENT_RESOURCES;
  3067. return status;
  3068. }
  3069. RtlZeroMemory(contextString.Buffer, WORK_BUFFER_SIZE * sizeof(WCHAR));
  3070. contextString.Buffer[0] = UNICODE_NULL;
  3071. contextString.Length = 0;
  3072. contextString.MaximumLength = WORK_BUFFER_SIZE * sizeof(WCHAR);
  3073. // first read the ntecontext list.
  3074. KeWaitForMutexObject(&NTEContextMutex, Executive, KernelMode, FALSE, NULL);
  3075. status = GetRegMultiSZValueNew(
  3076. KeyHandle,
  3077. L"NTEContextList",
  3078. &contextString
  3079. );
  3080. if (NT_SUCCESS(status)) {
  3081. ASSERT(contextString.Length > 0);
  3082. // convert this NTE's context into string so that we can do simple mem compare.
  3083. for (i = NTE_CONTEXT_SIZE; i >= 2;) {
  3084. nextDigit = contextValue % 16;
  3085. if (nextDigit >= 0 && nextDigit <= 9) {
  3086. thisContext[--i] = L'0' + nextDigit;
  3087. } else {
  3088. thisContext[--i] = L'A' + nextDigit - 10;
  3089. }
  3090. contextValue /= 16;
  3091. }
  3092. // now prepend 0x
  3093. thisContext[0] = L'0';
  3094. thisContext[1] = L'x';
  3095. // now find thisContext in the contextlist, remove it off the list
  3096. // and update the contextList in the registry.
  3097. status = STATUS_UNSUCCESSFUL;
  3098. for (i = 0;
  3099. (i + NTE_CONTEXT_SIZE + 1)*sizeof(WCHAR) < contextString.Length &&
  3100. contextString.Buffer[i] != L'\0' &&
  3101. contextString.Buffer[i + NTE_CONTEXT_SIZE] == L'\0';
  3102. i += NTE_CONTEXT_SIZE + 1) {
  3103. nextContext = &contextString.Buffer[i];
  3104. if (RtlEqualMemory(nextContext, thisContext,
  3105. NTE_CONTEXT_SIZE * sizeof(WCHAR))) {
  3106. PWSTR nextNextContext = nextContext + NTE_CONTEXT_SIZE + 1;
  3107. RtlMoveMemory(nextContext,
  3108. nextNextContext,
  3109. contextString.Length -
  3110. ((PSTR)nextNextContext -
  3111. (PSTR)contextString.Buffer));
  3112. contextString.Length -= (NTE_CONTEXT_SIZE + 1) * sizeof(WCHAR);
  3113. status = SetRegMultiSZValueNew(KeyHandle,
  3114. L"NTEContextList",
  3115. &contextString);
  3116. break;
  3117. }
  3118. }
  3119. }
  3120. KeReleaseMutex(&NTEContextMutex, FALSE);
  3121. if (contextString.Buffer) {
  3122. CTEFreeMem(contextString.Buffer);
  3123. }
  3124. return status;
  3125. }
  3126. static const struct {
  3127. IP_STATUS ipStatus;
  3128. NTSTATUS ntStatus;
  3129. } IPStatusMap[] = {
  3130. { IP_SUCCESS, STATUS_SUCCESS },
  3131. { IP_NO_RESOURCES, STATUS_INSUFFICIENT_RESOURCES },
  3132. { IP_DEVICE_DOES_NOT_EXIST, STATUS_DEVICE_DOES_NOT_EXIST },
  3133. { IP_DUPLICATE_ADDRESS, STATUS_DUPLICATE_NAME },
  3134. { IP_PENDING, STATUS_PENDING },
  3135. { IP_DUPLICATE_IPADD, STATUS_DUPLICATE_OBJECTID },
  3136. { IP_GENERAL_FAILURE, STATUS_UNSUCCESSFUL }
  3137. };
  3138. NTSTATUS
  3139. IPStatusToNTStatus(
  3140. IN IP_STATUS ipStatus
  3141. )
  3142. /*++
  3143. Routine Description:
  3144. This routine converts IP_STATUS to NTSTATUS.
  3145. Arguments:
  3146. ipStatus - IP status code.
  3147. Return Value:
  3148. correcponding NTSTATUS
  3149. --*/
  3150. {
  3151. ULONG i;
  3152. for (i = 0; IPStatusMap[i].ipStatus != IP_GENERAL_FAILURE; i++) {
  3153. if (IPStatusMap[i].ipStatus == ipStatus) {
  3154. return IPStatusMap[i].ntStatus;
  3155. }
  3156. }
  3157. return STATUS_UNSUCCESSFUL;
  3158. }