From: Alex Henrie Subject: [PATCH] ws2_32: Read protocol table from a file Message-Id: <20201116072813.230680-1-alexhenrie24@gmail.com> Date: Mon, 16 Nov 2020 00:28:13 -0700 Signed-off-by: Alex Henrie --- I intend to extend read_protocol_table and parse_next_protocol to read and parse the services file as well, since the file formats are nearly identical. --- dlls/ws2_32/protocols.tsv | 39 +++++++++ dlls/ws2_32/socket.c | 163 ++++++++++++++++++++++++++++++-------- dlls/ws2_32/version.rc | 3 + loader/wine.inf.in | 12 ++- 4 files changed, 181 insertions(+), 36 deletions(-) create mode 100644 dlls/ws2_32/protocols.tsv diff --git a/dlls/ws2_32/protocols.tsv b/dlls/ws2_32/protocols.tsv new file mode 100644 index 00000000000..288bd739f15 --- /dev/null +++ b/dlls/ws2_32/protocols.tsv @@ -0,0 +1,39 @@ +# Table of Internet protocols +# +# Copyright (c) 2020 The Wine Project +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +# Format: [...] + +ip 0 IP +icmp 1 ICMP +ggp 3 GGP +tcp 6 TCP +egp 8 EGP +pup 12 PUP +udp 17 UDP +hmp 20 HMP +xns-idp 22 XNS-IDP +rdp 27 RDP +ipv6 41 IPv6 +ipv6-route 43 IPv6-Route +ipv6-frag 44 IPv6-Frag +esp 50 ESP +ah 51 AH +ipv6-icmp 58 IPv6-ICMP +ipv6-nonxt 59 IPv6-NoNxt +ipv6-opts 60 IPv6-Opts +rvd 66 RVD diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 3efa4ebd64f..81f4a998e50 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -182,6 +182,8 @@ #define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2) +#define MAX_NAMES 4 + WINE_DEFAULT_DEBUG_CHANNEL(winsock); WINE_DECLARE_DEBUG_CHANNEL(winediag); @@ -6310,28 +6312,112 @@ struct WS_hostent* WINAPI WS_gethostbyname(const char* name) } -static const struct { int prot; const char *names[3]; } protocols[] = -{ - { 0, { "ip", "IP" }}, - { 1, { "icmp", "ICMP" }}, - { 3, { "ggp", "GGP" }}, - { 6, { "tcp", "TCP" }}, - { 8, { "egp", "EGP" }}, - { 12, { "pup", "PUP" }}, - { 17, { "udp", "UDP" }}, - { 20, { "hmp", "HMP" }}, - { 22, { "xns-idp", "XNS-IDP" }}, - { 27, { "rdp", "RDP" }}, - { 41, { "ipv6", "IPv6" }}, - { 43, { "ipv6-route", "IPv6-Route" }}, - { 44, { "ipv6-frag", "IPv6-Frag" }}, - { 50, { "esp", "ESP" }}, - { 51, { "ah", "AH" }}, - { 58, { "ipv6-icmp", "IPv6-ICMP" }}, - { 59, { "ipv6-nonxt", "IPv6-NoNxt" }}, - { 60, { "ipv6-opts", "IPv6-Opts" }}, - { 66, { "rvd", "RVD" }}, -}; +static char * read_protocol_table(void) +{ + static const WCHAR drivers_etc_protocol[] = {'\\','d','r','i','v','e','r','s', + '\\','e','t','c', + '\\','p','r','o','t','o','c','o','l',0}; + WCHAR table_path[MAX_PATH]; + HANDLE table_file; + DWORD table_len, bytes_read; + BOOL ret; + char *table_text; + + GetSystemDirectoryW(table_path, ARRAY_SIZE(table_path)); + lstrcatW(table_path, drivers_etc_protocol); + + table_file = CreateFileW(table_path, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (table_file == INVALID_HANDLE_VALUE) + return NULL; + + table_len = GetFileSize(table_file, NULL); + if (!table_len) + { + CloseHandle(table_file); + return NULL; + } + + table_text = HeapAlloc(GetProcessHeap(), 0, table_len + 1); + if (!table_text) + { + CloseHandle(table_file); + return NULL; + } + + ret = ReadFile(table_file, table_text, table_len, &bytes_read, NULL); + if (!ret || bytes_read != table_len) + { + CloseHandle(table_file); + HeapFree(GetProcessHeap(), 0, table_text); + return NULL; + } + + CloseHandle(table_file); + table_text[table_len] = 0; + return table_text; +} + +static char * get_field(char *line) +{ + char *field; + /* ignore sequences of whitespace between fields */ + while ((field = strtok(line, " \t\r"))) + { + if (field[0]) + break; + } + return field; +} + +static char * parse_next_protocol(char *current_line, int *number, char *names[MAX_NAMES]) +{ + char *next_line; + char *comment; + int i; + + while (current_line) + { + next_line = strchr(current_line, '\n'); + if (next_line) + { + next_line[0] = 0; + next_line++; + } + + comment = strchr(current_line, '#'); + if (comment) + *comment = 0; + + names[0] = get_field(current_line); + if (!names[0]) + { + /* this line is empty, all whitespace, or a comment */ + current_line = next_line; + continue; + } + + names[1] = get_field(NULL); + if (!names[1]) + { + /* lines that only have one field are ignored too */ + current_line = next_line; + continue; + } + /* if the second field is not actually a number, it is treated as 0 */ + *number = atoi(names[1]); + + for (i = 1;; i++) + { + names[i] = (i == MAX_NAMES - 1 ? NULL : get_field(NULL)); + if (!names[i]) break; + } + + return next_line; + } + + return NULL; +} /*********************************************************************** * getprotobyname (WS2_32.53) @@ -6339,21 +6425,31 @@ static const struct { int prot; const char *names[3]; } protocols[] = struct WS_protoent* WINAPI WS_getprotobyname(const char* name) { struct WS_protoent* retval = NULL; + char *table_text = read_protocol_table(); + char *current_line = table_text; + int row_number; + char *row_names[MAX_NAMES]; unsigned int i; - for (i = 0; i < ARRAY_SIZE(protocols); i++) + while ((current_line = parse_next_protocol( current_line, &row_number, row_names ))) { - if (_strnicmp( protocols[i].names[0], name, -1 )) continue; - retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1, - protocols[i].prot ); - break; + for (i = 0; row_names[i]; i++) + { + if (!_strnicmp( row_names[i], name, -1 )) + { + retval = WS_create_pe( row_names[0], (char **)row_names + 1, row_number ); + goto found; + } + } } if (!retval) { WARN( "protocol %s not found\n", debugstr_a(name) ); SetLastError(WSANO_DATA); } +found: TRACE( "%s ret %p\n", debugstr_a(name), retval ); + if (table_text) HeapFree( GetProcessHeap(), 0, table_text ); return retval; } @@ -6364,13 +6460,15 @@ struct WS_protoent* WINAPI WS_getprotobyname(const char* name) struct WS_protoent* WINAPI WS_getprotobynumber(int number) { struct WS_protoent* retval = NULL; - unsigned int i; + char *table_text = read_protocol_table(); + char *current_line = table_text; + int row_number; + char *row_names[MAX_NAMES]; - for (i = 0; i < ARRAY_SIZE(protocols); i++) + while ((current_line = parse_next_protocol( current_line, &row_number, row_names ))) { - if (protocols[i].prot != number) continue; - retval = WS_create_pe( protocols[i].names[0], (char **)protocols[i].names + 1, - protocols[i].prot ); + if (row_number != number) continue; + retval = WS_create_pe( row_names[0], (char **)row_names + 1, row_number ); break; } if (!retval) @@ -6379,6 +6477,7 @@ struct WS_protoent* WINAPI WS_getprotobynumber(int number) SetLastError(WSANO_DATA); } TRACE("%i ret %p\n", number, retval); + if (table_text) HeapFree( GetProcessHeap(), 0, table_text ); return retval; } diff --git a/dlls/ws2_32/version.rc b/dlls/ws2_32/version.rc index 52dbb1b2c48..a68f9885805 100644 --- a/dlls/ws2_32/version.rc +++ b/dlls/ws2_32/version.rc @@ -16,6 +16,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +/* @makedep: protocols.tsv */ +1 WINE_DATA_FILE protocols.tsv + #define WINE_FILEDESCRIPTION_STR "Wine core dll" #define WINE_FILENAME_STR "ws2_32.dll" #define WINE_FILEVERSION 5,1,2600,5512 diff --git a/loader/wine.inf.in b/loader/wine.inf.in index de62b90fa35..6c6c9ee14e3 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -30,7 +30,7 @@ signature="$CHICAGO$" RegisterDlls=RegisterDllsSection WineFakeDlls=FakeDllsWin32,FakeDlls UpdateInis=SystemIni -CopyFiles=ColorFiles,InfFiles,NlsFiles,SortFiles +CopyFiles=ColorFiles,EtcFiles,InfFiles,NlsFiles,SortFiles AddReg=\ Classes,\ ContentIndex,\ @@ -54,7 +54,7 @@ AddReg=\ RegisterDlls=RegisterDllsSection WineFakeDlls=FakeDllsWin32,FakeDlls UpdateInis=SystemIni -CopyFiles=ColorFiles,InfFiles,NlsFiles,SortFiles +CopyFiles=ColorFiles,EtcFiles,InfFiles,NlsFiles,SortFiles AddReg=\ Classes,\ ContentIndex,\ @@ -80,7 +80,7 @@ RegisterDlls=RegisterDllsSection WineFakeDlls=FakeDllsWin64,FakeDlls WinePreInstall=Wow64 UpdateInis=SystemIni -CopyFiles=ColorFiles,InfFiles,NlsFiles,SortFiles +CopyFiles=ColorFiles,EtcFiles,InfFiles,NlsFiles,SortFiles AddReg=\ Classes,\ ContentIndex,\ @@ -107,7 +107,7 @@ RegisterDlls=RegisterDllsSection WineFakeDlls=FakeDllsWin64,FakeDlls WinePreInstall=Wow64 UpdateInis=SystemIni -CopyFiles=ColorFiles,InfFiles,NlsFiles,SortFiles +CopyFiles=ColorFiles,EtcFiles,InfFiles,NlsFiles,SortFiles AddReg=\ Classes,\ ContentIndex,\ @@ -4073,6 +4073,9 @@ HKLM,Software\Wine\LicenseInformation,"Shell-PremiumInBoxGames-Chess-EnableGame" [ColorFiles] srgb color space profile.icm,"@mscms.dll,-1" +[EtcFiles] +protocol,"@ws2_32.dll,-1" + [InfFiles] winebus.inf,"@winebus.sys,-1" winehid.inf,"@winehid.sys,-1" @@ -4161,6 +4164,7 @@ SortFiles = nls [DestinationDirs] ColorFiles = 23 +EtcFiles = 12,etc InfFiles = 17 NlsFiles = 11 SortFiles = 10,globalization\sorting -- 2.29.2