1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32/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
GetProtoOpenNetworkDatabase(PCHAR Name)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
GetProtoPatternMatch(IN PCHAR Buffer,IN PCHAR Lookup)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
GetProtoGetNextEnt(IN HANDLE DbHandle,IN PWSPROTO_BUFFER Buffer)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
getprotobynumber(IN INT number)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
getprotobyname(IN CONST CHAR FAR * name)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