+BOOLEAN ReadIpConfiguration(PIP_INTERFACE Interface)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE ParameterHandle;
+ PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo;
+ WCHAR Buffer[150];
+ UNICODE_STRING IPAddress = RTL_CONSTANT_STRING(L"IPAddress");
+ UNICODE_STRING Netmask = RTL_CONSTANT_STRING(L"SubnetMask");
+ UNICODE_STRING Gateway = RTL_CONSTANT_STRING(L"DefaultGateway");
+ UNICODE_STRING EnableDhcp = RTL_CONSTANT_STRING(L"EnableDHCP");
+ UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\");
+ UNICODE_STRING TcpipRegistryPath;
+ UNICODE_STRING RegistryDataU;
+ ANSI_STRING RegistryDataA;
+ ULONG Unused;
+ NTSTATUS Status;
+ IP_ADDRESS DefaultMask, Router;
+
+ AddrInitIPv4(&DefaultMask, 0);
+
+ TcpipRegistryPath.MaximumLength = sizeof(WCHAR) * 150;
+ TcpipRegistryPath.Length = 0;
+ TcpipRegistryPath.Buffer = Buffer;
+
+ /* Build the registry path */
+ RtlAppendUnicodeStringToString(&TcpipRegistryPath, &Prefix);
+ RtlAppendUnicodeStringToString(&TcpipRegistryPath, &Interface->Name);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &TcpipRegistryPath,
+ OBJ_CASE_INSENSITIVE,
+ 0,
+ NULL);
+
+ /* Open a handle to the adapter parameters */
+ Status = ZwOpenKey(&ParameterHandle, KEY_READ, &ObjectAttributes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return FALSE;
+ }
+ else
+ {
+ KeyValueInfo = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR));
+ if (!KeyValueInfo)
+ {
+ ZwClose(ParameterHandle);
+ return FALSE;
+ }
+
+ /* Read the EnableDHCP entry */
+ Status = ZwQueryValueKey(ParameterHandle,
+ &EnableDhcp,
+ KeyValuePartialInformation,
+ KeyValueInfo,
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG),
+ &Unused);
+ if (NT_SUCCESS(Status) && KeyValueInfo->DataLength == sizeof(ULONG) && (*(PULONG)KeyValueInfo->Data) == 0)
+ {
+ RegistryDataU.MaximumLength = 16 + sizeof(WCHAR);
+ RegistryDataU.Buffer = (PWCHAR)KeyValueInfo->Data;
+
+ /* Read the IP address */
+ Status = ZwQueryValueKey(ParameterHandle,
+ &IPAddress,
+ KeyValuePartialInformation,
+ KeyValueInfo,
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR),
+ &Unused);
+ if (NT_SUCCESS(Status))
+ {
+ RegistryDataU.Length = KeyValueInfo->DataLength;
+
+ RtlUnicodeStringToAnsiString(&RegistryDataA,
+ &RegistryDataU,
+ TRUE);
+
+ AddrInitIPv4(&Interface->Unicast, inet_addr(RegistryDataA.Buffer));
+
+ RtlFreeAnsiString(&RegistryDataA);
+ }
+
+ Status = ZwQueryValueKey(ParameterHandle,
+ &Netmask,
+ KeyValuePartialInformation,
+ KeyValueInfo,
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR),
+ &Unused);
+ if (NT_SUCCESS(Status))
+ {
+ RegistryDataU.Length = KeyValueInfo->DataLength;
+
+ RtlUnicodeStringToAnsiString(&RegistryDataA,
+ &RegistryDataU,
+ TRUE);
+
+ AddrInitIPv4(&Interface->Netmask, inet_addr(RegistryDataA.Buffer));
+
+ RtlFreeAnsiString(&RegistryDataA);
+ }
+
+ /* We have to wait until both IP address and subnet mask
+ * are read to add the interface route, but we must do it
+ * before we add the default gateway */
+ if (!AddrIsUnspecified(&Interface->Unicast) &&
+ !AddrIsUnspecified(&Interface->Netmask))
+ IPAddInterfaceRoute(Interface);
+
+ /* Read default gateway info */
+ Status = ZwQueryValueKey(ParameterHandle,
+ &Gateway,
+ KeyValuePartialInformation,
+ KeyValueInfo,
+ sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 16 * sizeof(WCHAR),
+ &Unused);
+ if (NT_SUCCESS(Status))
+ {
+ RegistryDataU.Length = KeyValueInfo->DataLength;
+
+ RtlUnicodeStringToAnsiString(&RegistryDataA,
+ &RegistryDataU,
+ TRUE);
+
+ AddrInitIPv4(&Router, inet_addr(RegistryDataA.Buffer));
+
+ if (!AddrIsUnspecified(&Router))
+ RouterCreateRoute(&DefaultMask, &DefaultMask, &Router, Interface, 1);
+
+ RtlFreeAnsiString(&RegistryDataA);
+ }
+ }
+
+ ZwClose(ParameterHandle);
+ }
+
+ return TRUE;
+}
+
+BOOLEAN ReconfigureAdapter(PRECONFIGURE_CONTEXT Context)
+{
+ PLAN_ADAPTER Adapter = Context->Adapter;
+ PIP_INTERFACE Interface = Adapter->Context;
+ //NDIS_STATUS NdisStatus;
+ IP_ADDRESS DefaultMask;
+
+ /* Initalize the default unspecified address (0.0.0.0) */
+ AddrInitIPv4(&DefaultMask, 0);
+ if (Context->State == LAN_STATE_STARTED &&
+ !Context->Adapter->CompletingReset)
+ {
+ /* Read the IP configuration */
+ ReadIpConfiguration(Interface);
+
+ /* Compute the broadcast address */
+ Interface->Broadcast.Type = IP_ADDRESS_V4;
+ Interface->Broadcast.Address.IPv4Address = Interface->Unicast.Address.IPv4Address |
+ ~Interface->Netmask.Address.IPv4Address;
+ }
+ else if (!Context->Adapter->CompletingReset)
+ {
+ /* Clear IP configuration */
+ Interface->Unicast = DefaultMask;
+ Interface->Netmask = DefaultMask;
+ Interface->Broadcast = DefaultMask;
+
+ /* Remove all interface routes */
+ RouterRemoveRoutesForInterface(Interface);
+
+ /* Destroy all cached neighbors */
+ NBDestroyNeighborsForInterface(Interface);
+ }
+
+ Context->Adapter->CompletingReset = FALSE;
+
+ /* We're done here if the adapter isn't connected */
+ if (Context->State != LAN_STATE_STARTED)
+ {
+ Adapter->State = Context->State;
+ return TRUE;
+ }
+
+ /* NDIS Bug! */
+#if 0
+ /* Get maximum link speed */
+ NdisStatus = NDISCall(Adapter,
+ NdisRequestQueryInformation,
+ OID_GEN_LINK_SPEED,
+ &Interface->Speed,
+ sizeof(UINT));
+
+ if (!NT_SUCCESS(NdisStatus))
+ Interface->Speed = IP_DEFAULT_LINK_SPEED;
+
+ Adapter->Speed = Interface->Speed * 100L;
+
+ /* Get maximum frame size */
+ NdisStatus = NDISCall(Adapter,
+ NdisRequestQueryInformation,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ &Adapter->MTU,
+ sizeof(UINT));
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
+ return FALSE;
+
+ Interface->MTU = Adapter->MTU;
+
+ /* Get maximum packet size */
+ NdisStatus = NDISCall(Adapter,
+ NdisRequestQueryInformation,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ &Adapter->MaxPacketSize,
+ sizeof(UINT));
+ if (NdisStatus != NDIS_STATUS_SUCCESS)
+ return FALSE;
+#endif
+
+ Adapter->State = Context->State;
+
+ return TRUE;
+}
+
+VOID ReconfigureAdapterWorker(PVOID Context)
+{
+ PRECONFIGURE_CONTEXT ReconfigureContext = Context;
+
+ /* Complete the reconfiguration asynchronously */
+ ReconfigureAdapter(ReconfigureContext);
+
+ /* Free the context */
+ ExFreePool(ReconfigureContext);
+}