Author: cgutman
 Date: Sun Aug 22 22:22:27 2010
 New Revision: 48593
 URL: 
http://svn.reactos.org/svn/reactos?rev=48593&view=rev
 Log:
 [DHCPCSVC]
 - Write the DNS servers in a REG_MULTI_SZ value
 [IPHLPAPI]
 - Rewrite the registry reading code
 - Use HeapFree to free memory from the allocated from heap
 Modified:
     trunk/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c
     trunk/reactos/dll/win32/iphlpapi/iphlpapi_private.h
     trunk/reactos/dll/win32/iphlpapi/registry.c
     trunk/reactos/dll/win32/iphlpapi/resinfo_reactos.c
 Modified: trunk/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c
 URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/dhcpcsvc/dhcp/dh…
 ==============================================================================
 --- trunk/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c [iso-8859-1] (original)
 +++ trunk/reactos/dll/win32/dhcpcsvc/dhcp/dhclient.c [iso-8859-1] Sun Aug 22 22:22:27
2010
 @@ -507,24 +507,25 @@
          char *nsbuf;
          int i, addrs =
              new_lease->options[DHO_DOMAIN_NAME_SERVERS].len / sizeof(ULONG);
 -
 -        nsbuf = malloc( addrs * sizeof(IP_ADDRESS_STRING) );
 +        int len = 0;
 +
 +        nsbuf = malloc( addrs * sizeof(IP_ADDRESS_STRING) + 1 );
          if( nsbuf) {
 -            nsbuf[0] = 0;
 +            memset(nsbuf, 0, addrs * sizeof(IP_ADDRESS_STRING) + 1);
              for( i = 0; i < addrs; i++ ) {
                  nameserver.len = sizeof(ULONG);
                  memcpy( nameserver.iabuf,
                          new_lease->options[DHO_DOMAIN_NAME_SERVERS].data +
                          (i * sizeof(ULONG)), sizeof(ULONG) );
                  strcat( nsbuf, piaddr(nameserver) );
 -                if( i != addrs-1 ) strcat( nsbuf, "," );
 +                len += strlen(nsbuf) + 1;
              }
              DH_DbgPrint(MID_TRACE,("Setting DhcpNameserver: %s\n", nsbuf));
 -            RegSetValueExA( RegKey, "DhcpNameServer", 0, REG_SZ,
 -                           (LPBYTE)nsbuf, strlen(nsbuf) + 1 );
 +            RegSetValueExA( RegKey, "DhcpNameServer", 0, REG_MULTI_SZ,
 +                           (LPBYTE)nsbuf, len + 1 );
              free( nsbuf );
          }
 Modified: trunk/reactos/dll/win32/iphlpapi/iphlpapi_private.h
 URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/iphlpapi/iphlpap…
 ==============================================================================
 --- trunk/reactos/dll/win32/iphlpapi/iphlpapi_private.h [iso-8859-1] (original)
 +++ trunk/reactos/dll/win32/iphlpapi/iphlpapi_private.h [iso-8859-1] Sun Aug 22 22:22:27
2010
 @@ -139,6 +139,7 @@
  PWCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n );
  void ConsumeChildKeyName( PWCHAR Name );
  PWCHAR QueryRegistryValueString( HANDLE RegHandle, PWCHAR ValueName );
 +PWCHAR *QueryRegistryValueStringMulti( HANDLE RegHandle, PWCHAR ValueName );
  void ConsumeRegValueString( PWCHAR NameServer );
  BOOL isInterface( TDIEntityID *if_maybe );
  BOOL hasArp( HANDLE tcpFile, TDIEntityID *arp_maybe );
 Modified: trunk/reactos/dll/win32/iphlpapi/registry.c
 URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/iphlpapi/registr…
 ==============================================================================
 --- trunk/reactos/dll/win32/iphlpapi/registry.c [iso-8859-1] (original)
 +++ trunk/reactos/dll/win32/iphlpapi/registry.c [iso-8859-1] Sun Aug 22 22:22:27 2010
 @@ -66,25 +66,123 @@
    if (Name) HeapFree( GetProcessHeap(), 0, Name );
  }
 -PWCHAR QueryRegistryValueString( HANDLE RegHandle, PWCHAR ValueName ) {
 -  PWCHAR Name;
 -  DWORD ReturnedSize = 0;
 +PVOID QueryRegistryValue(HANDLE RegHandle, PWCHAR ValueName, LPDWORD RegistryType,
LPDWORD Length)
 +{
 +    PVOID ReadValue = NULL;
 +    DWORD Error;
 -  if (RegQueryValueExW( RegHandle, ValueName, NULL, NULL, NULL,
 -                      &ReturnedSize ) != 0) {
 -    return 0;
 -  } else {
 -    Name = malloc( ReturnedSize);
 -    RegQueryValueExW( RegHandle, ValueName, NULL, NULL, (PVOID)Name,
 -                    &ReturnedSize );
 -    return Name;
 -  }
 +    *Length = 0;
 +    *RegistryType = REG_NONE;
 +
 +    while (TRUE)
 +    {
 +        Error = RegQueryValueExW(RegHandle, ValueName, NULL, RegistryType, ReadValue,
Length);
 +        if (Error == ERROR_SUCCESS)
 +        {
 +            if (ReadValue) break;
 +        }
 +        else if (Error == ERROR_MORE_DATA)
 +        {
 +            HeapFree(GetProcessHeap(), 0, ReadValue);
 +        }
 +        else break;
 +
 +        ReadValue = HeapAlloc(GetProcessHeap(), 0, *Length);
 +        if (!ReadValue) return NULL;
 +    }
 +
 +    if (Error != ERROR_SUCCESS)
 +    {
 +        if (ReadValue) HeapFree(GetProcessHeap(), 0, ReadValue);
 +
 +        *Length = 0;
 +        *RegistryType = REG_NONE;
 +        ReadValue = NULL;
 +    }
 +
 +    return ReadValue;
 +}
 +
 +PWCHAR TerminateReadString(PWCHAR String, DWORD Length)
 +{
 +    PWCHAR TerminatedString;
 +
 +    TerminatedString = HeapAlloc(GetProcessHeap(), 0, Length + sizeof(WCHAR));
 +    if (TerminatedString == NULL)
 +        return NULL;
 +
 +    memcpy(TerminatedString, String, Length);
 +
 +    TerminatedString[Length / sizeof(WCHAR)] = UNICODE_NULL;
 +
 +    return TerminatedString;
 +}
 +
 +PWCHAR QueryRegistryValueString( HANDLE RegHandle, PWCHAR ValueName )
 +{
 +    PWCHAR String, TerminatedString;
 +    DWORD Type, Length;
 +
 +    String = QueryRegistryValue(RegHandle, ValueName, &Type, &Length);
 +    if (!String) return NULL;
 +    if (Type != REG_SZ)
 +    {
 +        DbgPrint("Type mismatch for %S (%d != %d)\n", ValueName, Type,
REG_SZ);
 +        //HeapFree(GetProcessHeap(), 0, String);
 +        //return NULL;
 +    }
 +
 +    TerminatedString = TerminateReadString(String, Length);
 +    HeapFree(GetProcessHeap(), 0, String);
 +    if (!TerminatedString) return NULL;
 +
 +    return TerminatedString;
  }
  void ConsumeRegValueString( PWCHAR Value ) {
 -  if (Value) free(Value);
 +  if (Value) HeapFree(GetProcessHeap(), 0, Value);
  }
  PWCHAR *QueryRegistryValueStringMulti( HANDLE RegHandle, PWCHAR ValueName ) {
 -  return 0; /* FIXME if needed */
 +    PWCHAR String, TerminatedString, Tmp;
 +    PWCHAR *Table;
 +    DWORD Type, Length, i, j;
 +
 +    String = QueryRegistryValue(RegHandle, ValueName, &Type, &Length);
 +    if (!String) return NULL;
 +    if (Type != REG_MULTI_SZ)
 +    {
 +        DbgPrint("Type mismatch for %S (%d != %d)\n", ValueName, Type,
REG_MULTI_SZ);
 +        //HeapFree(GetProcessHeap(), 0, String);
 +        //return NULL;
 +    }
 +
 +    TerminatedString = TerminateReadString(String, Length);
 +    HeapFree(GetProcessHeap(), 0, String);
 +    if (!TerminatedString) return NULL;
 +
 +    for (Tmp = TerminatedString, i = 0; *Tmp; Tmp++, i++) while (*Tmp) Tmp++;
 +
 +    Table = HeapAlloc(GetProcessHeap(), 0, (i + 1) * sizeof(PWCHAR));
 +    if (!Table)
 +    {
 +        HeapFree(GetProcessHeap(), 0, TerminatedString);
 +        return NULL;
 +    }
 +
 +    for (Tmp = TerminatedString, j = 0; *Tmp; Tmp++, j++)
 +    {
 +        PWCHAR Orig = Tmp;
 +
 +        for (i = 0; *Tmp; i++, Tmp++);
 +
 +        Table[j] = HeapAlloc(GetProcessHeap(), 0, i * sizeof(WCHAR));
 +        memcpy(Table[j], Orig, i * sizeof(WCHAR));
 +    }
 +
 +    Table[j] = NULL;
 +
 +    HeapFree(GetProcessHeap(), 0, TerminatedString);
 +
 +    return Table;
  }
 Modified: trunk/reactos/dll/win32/iphlpapi/resinfo_reactos.c
 URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/iphlpapi/resinfo…
 ==============================================================================
 --- trunk/reactos/dll/win32/iphlpapi/resinfo_reactos.c [iso-8859-1] (original)
 +++ trunk/reactos/dll/win32/iphlpapi/resinfo_reactos.c [iso-8859-1] Sun Aug 22 22:22:27
2010
 @@ -122,47 +122,24 @@
  void EnumNameServers( HANDLE RegHandle, PWCHAR Interface,
                             PVOID Data, EnumNameServersFunc cb ) {
 -    PWCHAR NameServerString =
 -      QueryRegistryValueString(RegHandle, L"DhcpNameServer");
 +    PWCHAR *NameServerString =
 +      QueryRegistryValueStringMulti(RegHandle, L"DhcpNameServer");
 +    DWORD i;
      if (!NameServerString)
 -              NameServerString = QueryRegistryValueString(RegHandle,
L"NameServer");
 -
 -    if (NameServerString) {
 -    /* Now, count the non-empty comma separated */
 -      DWORD ch;
 -      DWORD LastNameStart = 0;
 -      for (ch = 0; NameServerString[ch]; ch++) {
 -          if (NameServerString[ch] == ',') {
 -              if (ch - LastNameStart > 0) { /* Skip empty entries */
 -                  PWCHAR NameServer =
 -                      malloc(((ch - LastNameStart) + 1) * sizeof(WCHAR));
 -                  if (NameServer) {
 -                      memcpy(NameServer,NameServerString + LastNameStart,
 -                                 (ch - LastNameStart) * sizeof(WCHAR));
 -                      NameServer[ch - LastNameStart] = 0;
 -                      cb( Interface, NameServer, Data );
 -                      free(NameServer);
 -                      LastNameStart = ch +1;
 -                  }
 -              }
 -              LastNameStart = ch + 1; /* The first one after the comma */
 -          }
 -      }
 -      if (ch - LastNameStart > 0) { /* A last name? */
 -          PWCHAR NameServer = malloc(((ch - LastNameStart) + 1) * sizeof(WCHAR));
 -            if (NameServer) {
 -              memcpy(NameServer,NameServerString + LastNameStart,
 -                     (ch - LastNameStart) * sizeof(WCHAR));
 -              NameServer[ch - LastNameStart] = 0;
 -              cb( Interface, NameServer, Data );
 -              free(NameServer);
 -            }
 -      }
 -      ConsumeRegValueString(NameServerString);
 -    }
 -}
 -
 +              NameServerString = QueryRegistryValueStringMulti(RegHandle,
L"NameServer");
 +
 +    if (!NameServerString) return;
 +
 +    for (i = 0; NameServerString[i]; i++)
 +    {
 +        cb(Interface, NameServerString[i], Data);
 +
 +        HeapFree(GetProcessHeap(), 0, NameServerString[i]);
 +    }
 +
 +    HeapFree(GetProcessHeap(), 0, NameServerString);
 +}
  static void CreateNameServerListEnumNamesFuncCount( PWCHAR Interface,
                                                    PWCHAR Server,
                                                    PVOID _Data ) {