diff --git a/dll/win32/netcfgx/inetcfgcomp_iface.c b/dll/win32/netcfgx/inetcfgcomp_iface.c index 55c346447ca..4717bf32814 100644 --- a/dll/win32/netcfgx/inetcfgcomp_iface.c +++ b/dll/win32/netcfgx/inetcfgcomp_iface.c @@ -1,15 +1,5 @@ #include "precomp.h" -typedef struct -{ - const INetCfgComponent *lpVtbl; - const INetCfgComponentBindings *lpVtblBindings; - const INetCfgComponentPrivate *lpVtblPrivate; - LONG ref; - NetCfgComponentItem * pItem; - INetCfg * pNCfg; -} INetCfgComponentImpl; - typedef struct { const IEnumNetCfgComponent * lpVtbl; diff --git a/dll/win32/netcfgx/netcfg_iface.c b/dll/win32/netcfgx/netcfg_iface.c index bf33359ddde..8913a927d1a 100644 --- a/dll/win32/netcfgx/netcfg_iface.c +++ b/dll/win32/netcfgx/netcfg_iface.c @@ -705,7 +705,7 @@ ApplyOrCancelChanges( WCHAR szName[200]; LPOLESTR pszGuid; - while(pHead) + while (pHead) { if (pHead->bChanged) { @@ -738,6 +738,8 @@ ApplyOrCancelChanges( INetCfgComponentControl_CancelChanges(pHead->pControl); } } + + pHead->bChanged = FALSE; } pHead = pHead->pNext; } diff --git a/dll/win32/netcfgx/precomp.h b/dll/win32/netcfgx/precomp.h index e4186b2f430..73966e01e78 100644 --- a/dll/win32/netcfgx/precomp.h +++ b/dll/win32/netcfgx/precomp.h @@ -78,6 +78,16 @@ typedef struct NetCfgComponentItem * pProtocol; } INetCfgImpl; +typedef struct +{ + const INetCfgComponent *lpVtbl; + const INetCfgComponentBindings *lpVtblBindings; + const INetCfgComponentPrivate *lpVtblPrivate; + LONG ref; + NetCfgComponentItem * pItem; + INetCfg * pNCfg; +} INetCfgComponentImpl; + /* netcfg_iface.c */ HRESULT WINAPI INetCfg_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv); diff --git a/dll/win32/netcfgx/tcpipconf_notify.c b/dll/win32/netcfgx/tcpipconf_notify.c index 810af07511d..1109d2128e4 100644 --- a/dll/win32/netcfgx/tcpipconf_notify.c +++ b/dll/win32/netcfgx/tcpipconf_notify.c @@ -357,6 +357,11 @@ BuildParametersString( /* Format: "DefGw=;GwMetric=;IfMetric=0;DNS=;WINS=;DynamicUpdate=1;NameRegistration=0;" */ + if (ppszParameters == NULL) + return E_FAIL; + + *ppszParameters = NULL; + /* Count Gateway entries */ dwCount = 0; pAddr = pAdapter->NewGw; @@ -366,58 +371,66 @@ BuildParametersString( pAddr = pAddr->Next; } + TRACE("Gateway count: %lu\n", dwCount); + /* Build Default Gateway string */ - pszDefGateway = CoTaskMemAlloc(dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); - if (pszDefGateway == NULL) + if (dwCount > 0) { - hr = E_OUTOFMEMORY; - goto done; - } - - ZeroMemory(pszDefGateway, dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); - - pString = pszDefGateway; - pAddr = pAdapter->NewGw; - while (pAddr != NULL) - { - if (pString != pszDefGateway) + pszDefGateway = CoTaskMemAlloc(dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); + if (pszDefGateway == NULL) { - *pString = L','; - pString++; + hr = E_OUTOFMEMORY; + goto done; } - Address.S_un.S_addr = htonl(pAddr->u.SubnetMask); - pString = RtlIpv4AddressToStringW(&Address, pString); + ZeroMemory(pszDefGateway, dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); - pAddr = pAddr->Next; + pString = pszDefGateway; + pAddr = pAdapter->NewGw; + while (pAddr != NULL) + { + if (pString != pszDefGateway) + { + *pString = L','; + pString++; + } + + Address.S_un.S_addr = htonl(pAddr->IpAddress); + pString = RtlIpv4AddressToStringW(&Address, pString); + + pAddr = pAddr->Next; + } } TRACE("DefaultGateway %S\n", pszDefGateway); /* Build Gateway Metric string */ - pszGatewayMetric = CoTaskMemAlloc(dwCount * 5 * sizeof(WCHAR)); - if (pszGatewayMetric == NULL) + if (dwCount > 0) { - hr = E_OUTOFMEMORY; - goto done; - } - - ZeroMemory(pszGatewayMetric, dwCount * 5 * sizeof(WCHAR)); - - pString = pszGatewayMetric; - pAddr = pAdapter->NewGw; - while (pAddr != NULL) - { - if (pString != pszGatewayMetric) + pszGatewayMetric = CoTaskMemAlloc(dwCount * 5 * sizeof(WCHAR)); + if (pszGatewayMetric == NULL) { - *pString = L','; - pString++; + hr = E_OUTOFMEMORY; + goto done; } - nLength = _swprintf(pString, L"%hu", pAddr->u.Metric); - pString += nLength; + ZeroMemory(pszGatewayMetric, dwCount * 5 * sizeof(WCHAR)); - pAddr = pAddr->Next; + pString = pszGatewayMetric; + pAddr = pAdapter->NewGw; + while (pAddr != NULL) + { + if (pString != pszGatewayMetric) + { + *pString = L','; + pString++; + } + + nLength = _swprintf(pString, L"%hu", pAddr->u.Metric); + pString += nLength; + + pAddr = pAddr->Next; + } } TRACE("Gateway Metric %S\n", pszGatewayMetric); @@ -431,39 +444,44 @@ BuildParametersString( pAddr = pAddr->Next; } - pszNameServers = CoTaskMemAlloc(dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); - if (pszNameServers == NULL) - { - hr = E_OUTOFMEMORY; - goto done; - } + TRACE("DNS count: %lu\n", dwCount); - ZeroMemory(pszNameServers, dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); - - pString = pszNameServers; - pAddr = pAdapter->NewNs; - while (pAddr != NULL) + if (dwCount > 0) { - if (pString != pszNameServers) + pszNameServers = CoTaskMemAlloc(dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); + if (pszNameServers == NULL) { - *pString = L','; - pString++; + hr = E_OUTOFMEMORY; + goto done; } - Address.S_un.S_addr = htonl(pAddr->IpAddress); - pString = RtlIpv4AddressToStringW(&Address, pString); + ZeroMemory(pszNameServers, dwCount * IP_STRING_MAX_LENGTH * sizeof(WCHAR)); - pAddr = pAddr->Next; + pString = pszNameServers; + pAddr = pAdapter->NewNs; + while (pAddr != NULL) + { + if (pString != pszNameServers) + { + *pString = L','; + pString++; + } + + Address.S_un.S_addr = htonl(pAddr->IpAddress); + pString = RtlIpv4AddressToStringW(&Address, pString); + + pAddr = pAddr->Next; + } } TRACE("Name Servers %S\n", pszNameServers); /* Get the Parameters string length */ nLength = _scwprintf(L"DefGw=%s;GwMetric=%s;IfMetric=%lu;DNS=%s;", - pszDefGateway, - pszGatewayMetric, + pszDefGateway ? pszDefGateway : L"", + pszGatewayMetric ? pszGatewayMetric : L"", pAdapter->NewMetric, - pszNameServers); + pszNameServers ? pszNameServers : L""); TRACE("Param string length %d\n", nLength); if (nLength == -1) @@ -482,10 +500,10 @@ BuildParametersString( /* Fill the Parameters buffer */ _swprintf(pszParameters, L"DefGw=%s;GwMetric=%s;IfMetric=%lu;DNS=%s;", - pszDefGateway, - pszGatewayMetric, + pszDefGateway ? pszDefGateway : L"", + pszGatewayMetric ? pszGatewayMetric : L"", pAdapter->NewMetric, - pszNameServers); + pszNameServers ? pszNameServers : L""); TRACE("Parameters %S\n", pszParameters); @@ -504,6 +522,48 @@ done: return hr; } + +static +PWSTR +ExtractParameterValue( + PWSTR pszParameters, + PWSTR pszParameter) +{ + PWSTR pToken, pStart, pEnd, pBuffer; + INT length = 0; + + ERR("ExtractParameterValue(%S, %S)\n", pszParameters, pszParameter); + + pToken = wcsstr(pszParameters, pszParameter); + if (pToken == NULL) + return NULL; + + pStart = wcschr(pToken, L'='); + if (pStart == NULL) + return NULL; + + pStart++; + pEnd = wcschr(pStart, L';'); + if (pEnd == NULL) + length = wcslen(pStart); + else + length = pEnd - pStart; + TRACE("length %d\n", length); + + if (length == 0) + return NULL; + + pBuffer = (PWSTR)CoTaskMemAlloc((length + 1) * sizeof(WCHAR)); + if (pBuffer) + { + CopyMemory(pBuffer, pStart, length * sizeof(WCHAR)); + pBuffer[length] = UNICODE_NULL; + } + + return pBuffer; +} + + /*************************************************************** * TCP/IP Filter Dialog * @@ -4642,9 +4702,15 @@ ITcpipProperties_fnUnknown2( GUID *pAdapterName, PTCPIP_PROPERTIES pProperties) { + AdapterSettings *pAdapter; + IN_ADDR IpAddress, SubnetMask, Gateway, Dns; + PWSTR pszGateway = NULL, pszMetric = NULL, pszDns = NULL; + DWORD dwMetric; + LPCWSTR Term; + NTSTATUS Status; HRESULT hr = S_OK; - ERR("ITcpipProperties_fnUnknown2(%s %p)\n", wine_dbgstr_guid(pAdapterName), pProperties); + TRACE("ITcpipProperties_fnUnknown2(%s %p)\n", wine_dbgstr_guid(pAdapterName), pProperties); if (pProperties) { @@ -4654,6 +4720,171 @@ ITcpipProperties_fnUnknown2( ERR("pProperties->pszParameters %S\n", pProperties->pszParameters); } + TcpipConfNotifyImpl *This = impl_from_ITcpipProperties(iface); + + pAdapter = GetAdapterByGuid(This, pAdapterName); + if (pAdapter == NULL) + return E_FAIL; + + pAdapter->NewDhcpEnabled = (pProperties->dwDhcp != 0); + if (pAdapter->NewDhcpEnabled) + { + TRACE("DHCP\n"); + pAdapter->NewIp->IpAddress = 0; + pAdapter->NewIp->u.SubnetMask = 0; + } + else + { + TRACE("STATIC\n"); + Status = RtlIpv4StringToAddressW((PCWSTR)pProperties->pszIpAddress, + TRUE, + &Term, + &IpAddress); + if (Status != 0 /*STATUS_SUCCESS*/) + { + hr = E_FAIL; + goto done; + } + + TRACE("IP Address: %u.%u.%u.%u\n", + IpAddress.S_un.S_un_b.s_b1, IpAddress.S_un.S_un_b.s_b2, IpAddress.S_un.S_un_b.s_b3, IpAddress.S_un.S_un_b.s_b4); + + Status = RtlIpv4StringToAddressW((PCWSTR)pProperties->pszSubnetMask, + TRUE, + &Term, + &SubnetMask); + if (Status != 0 /*STATUS_SUCCESS*/) + { + hr = E_FAIL; + goto done; + } + + TRACE("Subnet Mask: %u.%u.%u.%u\n", + SubnetMask.S_un.S_un_b.s_b1, SubnetMask.S_un.S_un_b.s_b2, SubnetMask.S_un.S_un_b.s_b3, SubnetMask.S_un.S_un_b.s_b4); + + TRACE("pAdapter->NewIp %p\n", pAdapter->NewIp); + if (pAdapter->NewIp == NULL) + { + pAdapter->NewIp = CoTaskMemAlloc(sizeof(IP_ADDR)); + if (pAdapter->NewIp == NULL) + { + hr = E_OUTOFMEMORY; + goto done; + } + + ZeroMemory(pAdapter->NewIp, sizeof(IP_ADDR)); + } + + pAdapter->NewIp->IpAddress = ntohl(IpAddress.S_un.S_addr); + pAdapter->NewIp->u.SubnetMask = ntohl(SubnetMask.S_un.S_addr); + } + + /* Parse pszParameters */ + pszGateway = ExtractParameterValue(pProperties->pszParameters, L"DefGw"); + pszMetric = ExtractParameterValue(pProperties->pszParameters, L"GwMetric"); + if (pszGateway != NULL && pszMetric != NULL) + { + TRACE("Gateway: %S\n", pszGateway); + TRACE("Metric: %S\n", pszMetric); + if ((wcslen(pszGateway) == 0) && (wcslen(pszMetric) == 0)) + { + FIXME("Delete Gateway and Metric!\n"); + } + else + { + Status = RtlIpv4StringToAddressW((PCWSTR)pszGateway, + TRUE, + &Term, + &Gateway); + if (Status != 0 /*STATUS_SUCCESS*/) + { + hr = E_FAIL; + goto done; + } + + TRACE("Gateway: %u.%u.%u.%u\n", + Gateway.S_un.S_un_b.s_b1, Gateway.S_un.S_un_b.s_b2, Gateway.S_un.S_un_b.s_b3, Gateway.S_un.S_un_b.s_b4); + + TRACE("pAdapter->NewGw %p\n", pAdapter->NewGw); + if (pAdapter->NewGw == NULL) + { + pAdapter->NewGw = CoTaskMemAlloc(sizeof(IP_ADDR)); + if (pAdapter->NewGw == NULL) + { + hr = E_OUTOFMEMORY; + goto done; + } + + ZeroMemory(pAdapter->NewGw, sizeof(IP_ADDR)); + } + + pAdapter->NewGw->IpAddress = ntohl(Gateway.S_un.S_addr); + + dwMetric = wcstoul(pszMetric, (PWSTR*)&Term, 10); + if (dwMetric > 9999) + dwMetric = 9999; + pAdapter->NewGw->u.Metric = (USHORT)dwMetric; + } + } + + pszDns = ExtractParameterValue(pProperties->pszParameters, L"DNS"); + if (pszDns) + { + TRACE("DNS: %S\n", pszDns); + if (wcslen(pszDns) == 0) + { + FIXME("Delete DNS!\n"); + } + else + { + Status = RtlIpv4StringToAddressW((PCWSTR)pszDns, + TRUE, + &Term, + &Dns); + if (Status != 0 /*STATUS_SUCCESS*/) + { + hr = E_FAIL; + goto done; + } + + TRACE("Dns: %u.%u.%u.%u\n", + Dns.S_un.S_un_b.s_b1, Dns.S_un.S_un_b.s_b2, Dns.S_un.S_un_b.s_b3, Dns.S_un.S_un_b.s_b4); + + TRACE("pAdapter->NewNs %p\n", pAdapter->NewNs); + if (pAdapter->NewNs == NULL) + { + pAdapter->NewNs = CoTaskMemAlloc(sizeof(IP_ADDR)); + if (pAdapter->NewNs == NULL) + { + hr = E_OUTOFMEMORY; + goto done; + } + + ZeroMemory(pAdapter->NewNs, sizeof(IP_ADDR)); + } + + pAdapter->NewNs->IpAddress = ntohl(Dns.S_un.S_addr); + } + } + + /* + TODO: + IfMetric + DynamicUpdate + NameRegistration + */ + + if (This->pNComp) + ((INetCfgComponentImpl *)(This->pNComp))->pItem->bChanged = TRUE; + +done: + if (pszGateway) + CoTaskMemFree(pszGateway); + if (pszMetric) + CoTaskMemFree(pszMetric); + if (pszDns) + CoTaskMemFree(pszDns); + return hr; }