xref: /reactos/dll/win32/ws2_32/src/getproto.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS WinSock 2 API
4  * FILE:        dll/win32/ws2_32_new/src/getproto.c
5  * PURPOSE:     GetProtoByY Functions.
6  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 HANDLE
19 WSAAPI
20 GetProtoOpenNetworkDatabase(PCHAR Name)
21 {
22     PCHAR ExpandedPath;
23     PCHAR DatabasePath;
24     INT ErrorCode;
25     HKEY DatabaseKey;
26     DWORD RegType;
27     DWORD RegSize = 0;
28     HANDLE ret;
29 
30     ExpandedPath = HeapAlloc(WsSockHeap, 0, MAX_PATH);
31     if (!ExpandedPath)
32         return INVALID_HANDLE_VALUE;
33 
34     /* Open the database path key */
35     ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
36                              "System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
37                              0,
38                              KEY_READ,
39                              &DatabaseKey);
40     if (ErrorCode == NO_ERROR)
41     {
42         /* Read the actual path */
43         ErrorCode = RegQueryValueEx(DatabaseKey,
44                                     "DatabasePath",
45                                     NULL,
46                                     &RegType,
47                                     NULL,
48                                     &RegSize);
49 
50         DatabasePath = HeapAlloc(WsSockHeap, 0, RegSize);
51         if (!DatabasePath)
52         {
53             HeapFree(WsSockHeap, 0, ExpandedPath);
54             return INVALID_HANDLE_VALUE;
55         }
56 
57         /* Read the actual path */
58         ErrorCode = RegQueryValueEx(DatabaseKey,
59                                     "DatabasePath",
60                                     NULL,
61                                     &RegType,
62                                     (LPBYTE)DatabasePath,
63                                     &RegSize);
64 
65 
66         /* Close the key */
67         RegCloseKey(DatabaseKey);
68 
69         /* Expand the name */
70         ExpandEnvironmentStrings(DatabasePath, ExpandedPath, MAX_PATH);
71 
72         HeapFree(WsSockHeap, 0, DatabasePath);
73     }
74     else
75     {
76         /* Use default path */
77         GetSystemDirectory(ExpandedPath, MAX_PATH);
78         if (ExpandedPath[strlen(ExpandedPath) - 1] != '\\')
79         {
80             /* It isn't, so add it ourselves */
81             strncat(ExpandedPath, "\\", MAX_PATH);
82         }
83         strncat(ExpandedPath, "DRIVERS\\ETC\\", MAX_PATH);
84     }
85 
86     /* Make sure that the path is backslash-terminated */
87     if (ExpandedPath[strlen(ExpandedPath) - 1] != '\\')
88     {
89         /* It isn't, so add it ourselves */
90         strncat(ExpandedPath, "\\", MAX_PATH);
91     }
92 
93     /* Add the database name */
94     strncat(ExpandedPath, Name, MAX_PATH);
95 
96     /* Return a handle to the file */
97     ret = CreateFile(ExpandedPath,
98                       FILE_READ_ACCESS,
99                       0,
100                       NULL,
101                       OPEN_EXISTING,
102                       FILE_ATTRIBUTE_NORMAL,
103                       NULL);
104 
105     HeapFree(WsSockHeap, 0, ExpandedPath);
106     return ret;
107 }
108 
109 PCHAR
110 WSAAPI
111 GetProtoPatternMatch(IN PCHAR Buffer,
112                      IN PCHAR Lookup)
113 {
114     CHAR ScanChar;
115 
116     /* Loop as long as we have data */
117     while ((ScanChar = *Buffer))
118     {
119         /* Check for a match and return its pointer if found */
120         if (strchr(Lookup, ScanChar)) return Buffer;
121 
122         /* Keep going */
123         Buffer++;
124     }
125 
126     /* Nothing found */
127     return NULL;
128 }
129 
130 PPROTOENT
131 WSAAPI
132 GetProtoGetNextEnt(IN HANDLE DbHandle,
133                    IN PWSPROTO_BUFFER Buffer)
134 {
135     DWORD Read;
136     LONG n;
137     PCHAR p, p1, Entry, *Aliases;
138     PPROTOENT ReturnedProtoent;
139 
140     /* Find out where we currently are in the file */
141     n = SetFilePointer(DbHandle, 0, 0, FILE_CURRENT);
142 
143     while (TRUE)
144     {
145         /* Read 512 bytes */
146         if (!ReadFile(DbHandle,
147                       Buffer->LineBuffer,
148                       sizeof(Buffer->LineBuffer) - 1,
149                       &Read,
150                       NULL)) return NULL;
151 
152         /* Find out where the line ends */
153         p1 = Buffer->LineBuffer;
154         Buffer->LineBuffer[Read] = ANSI_NULL;
155         p = strchr(Buffer->LineBuffer, '\n');
156 
157         /* Bail out if the file is parsed */
158         if (!p) return NULL;
159 
160         /* Calculate our new position */
161         n += (LONG)(p - p1) + 1;
162 
163         /* Make it so we read from there next time */
164         SetFilePointer(DbHandle, n, 0, FILE_BEGIN);
165 
166         /* Null-terminate the buffer so it only contains this line */
167         *p = ANSI_NULL;
168 
169         /* If this line is a comment, skip it */
170         if (*p1 == '#') continue;
171 
172         /* Get the entry in this line and null-terminate it */
173         Entry = GetProtoPatternMatch(p1, "#\n");
174         if (!Entry) continue;
175         *Entry = ANSI_NULL;
176 
177         /* Start with the name */
178         Buffer->Protoent.p_name = p1;
179 
180         /* Get the first tab and null-terminate */
181         Entry = GetProtoPatternMatch(p1, " \t");
182         if (!Entry) continue;
183         *Entry++ = ANSI_NULL;
184 
185         /* Handle remaining tabs or spaces */
186         while (*Entry == ' ' || *Entry == '\t') Entry++;
187 
188         /* Now move our read pointer */
189         p1 = GetProtoPatternMatch(Entry, " \t");
190         if (p1) *p1++ = ANSI_NULL;
191 
192         /* This is where the address is */
193         Buffer->Protoent.p_proto = (short)atoi(Entry);
194 
195         /* Setup the alias buffer */
196         Buffer->Protoent.p_aliases = Buffer->Aliases;
197         Aliases = Buffer->Protoent.p_aliases;
198 
199         /* Check if the pointer is stil valid */
200         if (p1)
201         {
202             /* The first entry is here */
203             Entry = p1;
204 
205             /* Loop while there are non-null entries */
206             while (Entry && *Entry)
207             {
208                 /* Handle tabs and spaces */
209                 while (*Entry == ' ' || *Entry == '\t') Entry++;
210 
211                 /* Make sure we don't go over the buffer */
212                 if (Aliases < &Buffer->Protoent.p_aliases[MAXALIASES - 1])
213                 {
214                     /* Write the alias */
215                     *Aliases++ = Entry;
216                 }
217 
218                 /* Get to the next entry */
219                 Entry = GetProtoPatternMatch(Entry, " \t");
220                 if (Entry) *Entry++ = ANSI_NULL;
221             }
222         }
223 
224         /* Terminate the list */
225         *Aliases = NULL;
226 
227         /* Return to caller */
228         ReturnedProtoent = &Buffer->Protoent;
229         break;
230     }
231 
232     /* Return whatever we got */
233     return ReturnedProtoent;
234 }
235 
236 /*
237  * @implemented
238  */
239 LPPROTOENT
240 WSAAPI
241 getprotobynumber(IN INT number)
242 {
243     PWSPROCESS Process;
244     PWSTHREAD Thread;
245     INT ErrorCode;
246     PPROTOENT Protoent;
247     PVOID GetProtoBuffer;
248     HANDLE DbHandle;
249     DPRINT("getprotobynumber: %lx\n", number);
250 
251     /* Enter prolog */
252     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
253     {
254         /* Leave now */
255         SetLastError(ErrorCode);
256         return NULL;
257     }
258 
259     /* Get our buffer */
260     GetProtoBuffer = WsThreadGetProtoBuffer(Thread);
261     if (!GetProtoBuffer)
262     {
263         /* Fail */
264         SetLastError(WSANO_DATA);
265         return NULL;
266     }
267 
268     /* Open the network database */
269     DbHandle = GetProtoOpenNetworkDatabase("protocol");
270     if (DbHandle == INVALID_HANDLE_VALUE)
271     {
272         /* Couldn't open the DB; fail */
273         SetLastError(WSANO_DATA);
274         return NULL;
275     }
276 
277     /* Start the scan loop */
278     while (TRUE)
279     {
280         /* Get a protoent entry */
281         Protoent = GetProtoGetNextEnt(DbHandle, GetProtoBuffer);
282 
283         /* Break if we didn't get any new one */
284         if (!Protoent) break;
285 
286         /* Break if we have a match */
287         if (Protoent->p_proto == number) break;
288     }
289 
290     /* Close the network database */
291     CloseHandle(DbHandle);
292 
293     /* Set error if we don't have a protoent */
294     if (!Protoent) SetLastError(WSANO_DATA);
295 
296     /* Return it */
297     return Protoent;
298 }
299 
300 /*
301  * @implemented
302  */
303 LPPROTOENT
304 WSAAPI
305 getprotobyname(IN CONST CHAR FAR *name)
306 {
307     PWSPROCESS Process;
308     PWSTHREAD Thread;
309     INT ErrorCode;
310     PPROTOENT Protoent;
311     PVOID GetProtoBuffer;
312     HANDLE DbHandle;
313     DPRINT("getprotobyname: %s\n", name);
314 
315     /* Enter prolog */
316     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
317     {
318         /* Leave now */
319         SetLastError(ErrorCode);
320         return NULL;
321     }
322 
323     /* Get our buffer */
324     GetProtoBuffer = WsThreadGetProtoBuffer(Thread);
325     if (!GetProtoBuffer)
326     {
327         /* Fail */
328         SetLastError(WSANO_DATA);
329         return NULL;
330     }
331 
332     /* Open the network database */
333     DbHandle = GetProtoOpenNetworkDatabase("protocol");
334     if (DbHandle == INVALID_HANDLE_VALUE)
335     {
336         /* Couldn't open the DB; fail */
337         SetLastError(WSANO_DATA);
338         return NULL;
339     }
340 
341     /* Start the scan loop */
342     while (TRUE)
343     {
344         /* Get a protoent entry */
345         Protoent = GetProtoGetNextEnt(DbHandle, GetProtoBuffer);
346 
347         /* Break if we didn't get any new one */
348         if (!Protoent) break;
349 
350         /* Break if we have a match */
351         if (!_stricmp(Protoent->p_name, name)) break;
352     }
353 
354     /* Close the network database */
355     CloseHandle(DbHandle);
356 
357     /* Set error if we don't have a protoent */
358     if (!Protoent) SetLastError(WSANO_DATA);
359 
360     /* Return it */
361     return Protoent;
362 }
363