Copy wininet to branch
[reactos.git] / reactos / lib / ws2_32 / misc / ns.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 DLL
4 * FILE: misc/ns.c
5 * PURPOSE: Namespace APIs
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #define __NO_CTYPE_INLINES
11 #include <ctype.h>
12 #include <ws2_32.h>
13 #include <winbase.h>
14
15 #ifndef BUFSIZ
16 #define BUFSIZ 1024
17 #endif/*BUFSIZ*/
18
19 #ifndef MAX_HOSTNAME_LEN
20 #define MAX_HOSTNAME_LEN 256
21 #endif
22
23 /* Name resolution APIs */
24
25 /*
26 * @unimplemented
27 */
28 INT
29 EXPORT
30 WSAAddressToStringA(
31 IN LPSOCKADDR lpsaAddress,
32 IN DWORD dwAddressLength,
33 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
34 OUT LPSTR lpszAddressString,
35 IN OUT LPDWORD lpdwAddressStringLength)
36 {
37 UNIMPLEMENTED
38
39 return 0;
40 }
41
42
43 /*
44 * @unimplemented
45 */
46 INT
47 EXPORT
48 WSAAddressToStringW(
49 IN LPSOCKADDR lpsaAddress,
50 IN DWORD dwAddressLength,
51 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
52 OUT LPWSTR lpszAddressString,
53 IN OUT LPDWORD lpdwAddressStringLength)
54 {
55 UNIMPLEMENTED
56
57 return 0;
58 }
59
60
61 /*
62 * @unimplemented
63 */
64 INT
65 EXPORT
66 WSAEnumNameSpaceProvidersA(
67 IN OUT LPDWORD lpdwBufferLength,
68 OUT LPWSANAMESPACE_INFOA lpnspBuffer)
69 {
70 UNIMPLEMENTED
71
72 return 0;
73 }
74
75
76 /*
77 * @unimplemented
78 */
79 INT
80 EXPORT
81 WSAEnumNameSpaceProvidersW(
82 IN OUT LPDWORD lpdwBufferLength,
83 OUT LPWSANAMESPACE_INFOW lpnspBuffer)
84 {
85 UNIMPLEMENTED
86
87 return 0;
88 }
89
90
91 /*
92 * @unimplemented
93 */
94 INT
95 EXPORT
96 WSAGetServiceClassInfoA(
97 IN LPGUID lpProviderId,
98 IN LPGUID lpServiceClassId,
99 IN OUT LPDWORD lpdwBufferLength,
100 OUT LPWSASERVICECLASSINFOA lpServiceClassInfo)
101 {
102 UNIMPLEMENTED
103
104 return 0;
105 }
106
107
108 /*
109 * @unimplemented
110 */
111 INT
112 EXPORT
113 WSAGetServiceClassInfoW(
114 IN LPGUID lpProviderId,
115 IN LPGUID lpServiceClassId,
116 IN OUT LPDWORD lpdwBufferLength,
117 OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)
118 {
119 UNIMPLEMENTED
120
121 return 0;
122 }
123
124
125 /*
126 * @unimplemented
127 */
128 INT
129 EXPORT
130 WSAGetServiceClassNameByClassIdA(
131 IN LPGUID lpServiceClassId,
132 OUT LPSTR lpszServiceClassName,
133 IN OUT LPDWORD lpdwBufferLength)
134 {
135 UNIMPLEMENTED
136
137 return 0;
138 }
139
140
141 /*
142 * @unimplemented
143 */
144 INT
145 EXPORT
146 WSAGetServiceClassNameByClassIdW(
147 IN LPGUID lpServiceClassId,
148 OUT LPWSTR lpszServiceClassName,
149 IN OUT LPDWORD lpdwBufferLength)
150 {
151 UNIMPLEMENTED
152
153 return 0;
154 }
155
156
157 /*
158 * @unimplemented
159 */
160 INT
161 EXPORT
162 WSAInstallServiceClassA(
163 IN LPWSASERVICECLASSINFOA lpServiceClassInfo)
164 {
165 UNIMPLEMENTED
166
167 return 0;
168 }
169
170
171 /*
172 * @unimplemented
173 */
174 INT
175 EXPORT
176 WSAInstallServiceClassW(
177 IN LPWSASERVICECLASSINFOW lpServiceClassInfo)
178 {
179 UNIMPLEMENTED
180
181 return 0;
182 }
183
184
185 /*
186 * @unimplemented
187 */
188 INT
189 EXPORT
190 WSALookupServiceBeginA(
191 IN LPWSAQUERYSETA lpqsRestrictions,
192 IN DWORD dwControlFlags,
193 OUT LPHANDLE lphLookup)
194 {
195 UNIMPLEMENTED
196
197 return 0;
198 }
199
200
201 /*
202 * @unimplemented
203 */
204 INT
205 EXPORT
206 WSALookupServiceBeginW(
207 IN LPWSAQUERYSETW lpqsRestrictions,
208 IN DWORD dwControlFlags,
209 OUT LPHANDLE lphLookup)
210 {
211 UNIMPLEMENTED
212
213 return 0;
214 }
215
216
217 /*
218 * @unimplemented
219 */
220 INT
221 EXPORT
222 WSALookupServiceEnd(
223 IN HANDLE hLookup)
224 {
225 UNIMPLEMENTED
226
227 return 0;
228 }
229
230
231 /*
232 * @unimplemented
233 */
234 INT
235 EXPORT
236 WSALookupServiceNextA(
237 IN HANDLE hLookup,
238 IN DWORD dwControlFlags,
239 IN OUT LPDWORD lpdwBufferLength,
240 OUT LPWSAQUERYSETA lpqsResults)
241 {
242 UNIMPLEMENTED
243
244 return 0;
245 }
246
247
248 /*
249 * @unimplemented
250 */
251 INT
252 EXPORT
253 WSALookupServiceNextW(
254 IN HANDLE hLookup,
255 IN DWORD dwControlFlags,
256 IN OUT LPDWORD lpdwBufferLength,
257 OUT LPWSAQUERYSETW lpqsResults)
258 {
259 UNIMPLEMENTED
260
261 return 0;
262 }
263
264
265 /*
266 * @unimplemented
267 */
268 INT
269 EXPORT
270 WSARemoveServiceClass(
271 IN LPGUID lpServiceClassId)
272 {
273 UNIMPLEMENTED
274
275 return 0;
276 }
277
278
279 /*
280 * @unimplemented
281 */
282 INT
283 EXPORT
284 WSASetServiceA(
285 IN LPWSAQUERYSETA lpqsRegInfo,
286 IN WSAESETSERVICEOP essOperation,
287 IN DWORD dwControlFlags)
288 {
289 UNIMPLEMENTED
290
291 return 0;
292 }
293
294
295 /*
296 * @unimplemented
297 */
298 INT
299 EXPORT
300 WSASetServiceW(
301 IN LPWSAQUERYSETW lpqsRegInfo,
302 IN WSAESETSERVICEOP essOperation,
303 IN DWORD dwControlFlags)
304 {
305 UNIMPLEMENTED
306
307 return 0;
308 }
309
310
311 /*
312 * @unimplemented
313 */
314 INT
315 EXPORT
316 WSAStringToAddressA(
317 IN LPSTR AddressString,
318 IN INT AddressFamily,
319 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
320 OUT LPSOCKADDR lpAddress,
321 IN OUT LPINT lpAddressLength)
322 {
323 UNIMPLEMENTED
324
325 return 0;
326 }
327
328
329 /*
330 * @unimplemented
331 */
332 INT
333 EXPORT
334 WSAStringToAddressW(
335 IN LPWSTR AddressString,
336 IN INT AddressFamily,
337 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
338 OUT LPSOCKADDR lpAddress,
339 IN OUT LPINT lpAddressLength)
340 {
341 UNIMPLEMENTED
342
343 return 0;
344 }
345
346 void check_hostent(struct hostent **he) {
347 struct hostent *new_he;
348 WS_DbgPrint(MID_TRACE,("*he: %x\n",*he));
349 if(!*he) {
350 new_he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent) + MAX_HOSTNAME_LEN + 1);
351 new_he->h_name = (PCHAR)(new_he + 1);
352 new_he->h_aliases = 0;
353 new_he->h_addrtype = 0; // AF_INET
354 new_he->h_length = 0; // sizeof(in_addr)
355 new_he->h_addr_list = HeapAlloc(GlobalHeap, 0, sizeof(char *) * 2);
356 RtlZeroMemory(new_he->h_addr_list, sizeof(char *) * 2);
357 *he = new_he;
358 }
359 }
360
361 void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr) {
362 ASSERT(he);
363 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
364 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
365 strncpy(he->h_name, name, MAX_HOSTNAME_LEN);
366 he->h_aliases = 0;
367 he->h_addrtype = AF_INET;
368 he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr);
369 if( he->h_addr_list[0] ) HeapFree( GlobalHeap, 0, he->h_addr_list[0] );
370 he->h_addr_list[0] = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
371 WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0]));
372 RtlCopyMemory(he->h_addr_list[0], (char*)&addr.IpAddress,
373 sizeof(addr.IpAddress));
374 he->h_addr_list[1] = 0;
375 }
376
377
378 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
379 void free_hostent(struct hostent *he) {
380 if(he) {
381 HFREE(he->h_name);
382 char *next = he->h_aliases[0];
383 while(next) { HFREE(next); next++; }
384 next = he->h_addr_list[0];
385 while(next) { HFREE(next); next++; }
386 HFREE(he->h_addr_list);
387 HFREE(he);
388 }
389 }
390
391 /* WinSock 1.1 compatible name resolution APIs */
392
393 /*
394 * @unimplemented
395 */
396 LPHOSTENT
397 EXPORT
398 gethostbyaddr(
399 IN CONST CHAR FAR* addr,
400 IN INT len,
401 IN INT type)
402 {
403 UNIMPLEMENTED
404
405 return (LPHOSTENT)NULL;
406 }
407
408 /*
409 Assumes rfc 1123 - adam *
410 addr[1] = 0;
411 addr[0] = inet_addr(name);
412 strcpy( hostname, name );
413 if(addr[0] == 0xffffffff) return NULL;
414 he.h_addr_list = (void *)addr;
415 he.h_name = hostname;
416 he.h_aliases = NULL;
417 he.h_addrtype = AF_INET;
418 he.h_length = sizeof(addr);
419 return &he;
420
421 <RANT>
422 From the MSDN Platform SDK: Windows Sockets 2
423 "The gethostbyname function cannot resolve IP address strings passed to it.
424 Such a request is treated exactly as if an unknown host name were passed."
425 </RANT>
426
427 Defferring to the the documented behaviour, rather than the unix behaviour
428 What if the hostname is in the HOSTS file? see getservbyname
429
430 * @implemented
431 */
432
433 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
434 /* see ws2_32.h, winsock2.h*/
435 /*getnetworkparameters - iphlp api */
436 /*
437 REFERENCES
438
439 servent -- w32api/include/winsock2.h
440 PWINSOCK_THREAD_BLOCK -- ws2_32.h
441 dllmain.c -- threadlocal memory allocation / deallocation
442 lib/dnsapi
443
444
445 */
446 /* lib/adns/src/adns.h XXX */
447
448
449 /*
450 struct hostent {
451 char *h_name;
452 char **h_aliases;
453 short h_addrtype;
454 short h_length;
455 char **h_addr_list;
456 #define h_addr h_addr_list[0]
457 };
458 struct servent {
459 char *s_name;
460 char **s_aliases;
461 short s_port;
462 char *s_proto;
463 };
464
465
466 struct hostent defined in w32api/include/winsock2.h
467 */
468
469 void free_servent(struct servent* s) {
470 HFREE(s->s_name);
471 char* next = s->s_aliases[0];
472 while(next) { HFREE(next); next++; }
473 s->s_port = 0;
474 HFREE(s->s_proto);
475 HFREE(s);
476 }
477
478
479
480 LPHOSTENT
481 EXPORT
482 gethostbyname(
483 IN CONST CHAR FAR* name)
484 {
485 enum addr_type{ GH_INVALID, GH_IPV6, GH_IPV4, GH_RFC1123_DNS };
486 typedef enum addr_type addr_type;
487 addr_type addr;
488 int ret = 0;
489 char* found = 0;
490 DNS_STATUS dns_status = {0};
491 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
492 PDNS_RECORD dp = 0;
493
494 addr = GH_INVALID;
495
496 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
497
498 if( !p ) {
499 WSASetLastError( WSANOTINITIALISED );
500 return NULL;
501 }
502
503 check_hostent(&p->Hostent); /*XXX alloc_hostent*/
504
505 /* Hostname NULL - behave like gethostname */
506 if(name == NULL) {
507 ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
508 return p->Hostent;
509 }
510
511 if(ret) {
512 WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA ??
513 return NULL;
514 }
515
516 /* Is it an IPv6 address? */
517 found = strstr(name, ":");
518 if( found != NULL ) {
519 addr = GH_IPV6;
520 goto act;
521 }
522
523 /* Is it an IPv4 address? */
524 if (!isalpha(name[0])) {
525 addr = GH_IPV4;
526 goto act;
527 }
528
529 addr = GH_RFC1123_DNS;
530
531 /* Broken out in case we want to get fancy later */
532 act:
533 switch(addr){
534 case GH_IPV6:
535 WSASetLastError(STATUS_NOT_IMPLEMENTED);
536 return NULL;
537 break;
538
539 case GH_INVALID:
540 WSASetLastError(WSAEFAULT);
541 return NULL;
542 break;
543
544 /* Note: If passed an IP address, MSDN says that gethostbyname()
545 treats it as an unknown host.
546 This is different from the unix implementation. Use inet_addr()
547 */
548 case GH_IPV4:
549 case GH_RFC1123_DNS:
550 /* DNS_TYPE_A: include/WinDNS.h */
551 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
552 dns_status = DnsQuery_A ( name, DNS_TYPE_A, DNS_QUERY_STANDARD,
553 0, /* extra dns servers */ &dp, 0 );
554
555 if(dns_status == 0) {
556 //ASSERT(dp->wType == DNS_TYPE_A);
557 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
558 PDNS_RECORD curr;
559 for(curr=dp;
560 curr != NULL && curr->wType != DNS_TYPE_A;
561 curr = curr->pNext ) {
562 WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
563 /*empty */
564 }
565
566 if(curr) {
567 WS_DbgPrint(MID_TRACE,("populating hostent\n"));
568 WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
569 populate_hostent(p->Hostent, (PCHAR)curr->pName, curr->Data.A);
570 DnsRecordListFree(dp, DnsFreeRecordList);
571 return p->Hostent;
572 } else {
573 DnsRecordListFree(dp, DnsFreeRecordList);
574 }
575 }
576
577 WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
578 dns_status));
579 WSASetLastError(WSAHOST_NOT_FOUND);
580 return NULL;
581
582 break;
583
584 default:
585 WSASetLastError(WSANO_RECOVERY);
586 return NULL;
587 break;
588 }
589
590 WSASetLastError(WSANO_RECOVERY);
591 return NULL;
592 }
593
594 /*
595 * @implemented
596 */
597 INT
598 EXPORT
599 gethostname(
600 OUT CHAR FAR* name,
601 IN INT namelen)
602 {
603 DWORD size = namelen;
604
605 int ret = GetComputerNameExA(ComputerNameDnsHostname, name, &size);
606 if(ret == 0) {
607 WSASetLastError(WSAEFAULT);
608 return SOCKET_ERROR;
609 } else {
610 name[namelen-1] = '\0';
611 return 0;
612 }
613 }
614
615
616 /*
617 * XXX arty -- Partial implementation pending a better one. This one will
618 * do for normal purposes.#include <ws2_32.h>
619 *
620 * Return the address of a static LPPROTOENT corresponding to the named
621 * protocol. These structs aren't very interesting, so I'm not too ashamed
622 * to have this function work on builtins for now.
623 *
624 * @unimplemented
625 */
626 LPPROTOENT
627 EXPORT
628 getprotobyname(
629 IN CONST CHAR FAR* name)
630 {
631 static CHAR *udp_aliases = 0;
632 static PROTOENT udp = { "udp", &udp_aliases, 17 };
633 static CHAR *tcp_aliases = 0;
634 static PROTOENT tcp = { "tcp", &tcp_aliases, 6 };
635 if( !_stricmp( name, "udp" ) ) {
636 return &udp;
637 } else if( !_stricmp( name, "tcp" ) ) {
638 return &tcp;
639 }
640
641 return 0;
642 }
643
644 /*
645 * @unimplemented
646 */
647 LPPROTOENT
648 EXPORT
649 getprotobynumber(
650 IN INT number)
651 {
652 UNIMPLEMENTED
653
654 return (LPPROTOENT)NULL;
655 }
656
657 #define SKIPWS(ptr,act) \
658 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
659 #define SKIPANDMARKSTR(ptr,act) \
660 {while(*ptr && !isspace(*ptr)) ptr++; \
661 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
662
663
664 static BOOL DecodeServEntFromString( IN PCHAR ServiceString,
665 OUT PCHAR *ServiceName,
666 OUT PCHAR *PortNumberStr,
667 OUT PCHAR *ProtocolStr,
668 IN PCHAR *Aliases,
669 IN DWORD MaxAlias ) {
670 UINT NAliases = 0;
671
672 WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
673
674 SKIPWS(ServiceString, return FALSE);
675 *ServiceName = ServiceString;
676 SKIPANDMARKSTR(ServiceString, return FALSE);
677 SKIPWS(ServiceString, return FALSE);
678 *PortNumberStr = ServiceString;
679 SKIPANDMARKSTR(ServiceString, ;);
680
681 while( *ServiceString && NAliases < MaxAlias - 1 ) {
682 SKIPWS(ServiceString, break);
683 if( *ServiceString ) {
684 SKIPANDMARKSTR(ServiceString, ;);
685 if( strlen(ServiceString) ) {
686 WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
687 *Aliases++ = ServiceString;
688 NAliases++;
689 }
690 }
691 }
692 *Aliases = NULL;
693
694 *ProtocolStr = strchr(*PortNumberStr,'/');
695 if( !*ProtocolStr ) return FALSE;
696 **ProtocolStr = 0; (*ProtocolStr)++;
697
698 WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
699 *ServiceName, *ProtocolStr, *PortNumberStr,
700 NAliases));
701
702 return TRUE;
703 }
704
705 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
706
707 /*
708 * @implemented
709 */
710 LPSERVENT
711 EXPORT
712 getservbyname(
713
714 IN CONST CHAR FAR* name,
715 IN CONST CHAR FAR* proto)
716 {
717 BOOL Found = FALSE;
718 HANDLE ServicesFile;
719 CHAR ServiceDBData[BUFSIZ] = { 0 };
720 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
721 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
722 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
723 ProtocolStr = 0, Comment = 0;
724 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
725 UINT i,SizeNeeded = 0,
726 SystemDirSize = sizeof(ServiceDBData) - 1;
727 DWORD ReadSize = 0, ValidData = 0;
728 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
729
730 if( !p ) {
731 WSASetLastError( WSANOTINITIALISED );
732 return NULL;
733 }
734
735 if( !name ) {
736 WSASetLastError( WSANO_RECOVERY );
737 return NULL;
738 }
739
740 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) {
741 WSASetLastError( WSANO_RECOVERY );
742 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
743 return NULL; /* Can't get system directory */
744 }
745
746 strncat( SystemDirectory, ServicesFileLocation, SystemDirSize );
747
748 ServicesFile = CreateFileA( SystemDirectory,
749 GENERIC_READ,
750 FILE_SHARE_READ,
751 NULL,
752 OPEN_EXISTING,
753 FILE_ATTRIBUTE_NORMAL |
754 FILE_FLAG_SEQUENTIAL_SCAN,
755 NULL );
756
757 if( ServicesFile == INVALID_HANDLE_VALUE ) {
758 WSASetLastError( WSANO_RECOVERY );
759 return NULL;
760 }
761
762 /* Scan the services file ...
763 *
764 * We will read up to BUFSIZ bytes per pass, until the buffer does not
765 * contain a full line, then we will try to read more.
766 *
767 * We fall from the loop if the buffer does not have a line terminator.
768 */
769
770 /* Initial Read */
771 while( !Found &&
772 ReadFile( ServicesFile, ServiceDBData + ValidData,
773 sizeof( ServiceDBData ) - ValidData,
774 &ReadSize, NULL ) ) {
775 ValidData += ReadSize;
776 ReadSize = 0;
777 NextLine = ThisLine = ServiceDBData;
778
779 /* Find the beginning of the next line */
780 while( NextLine < ServiceDBData + ValidData &&
781 *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
782
783 /* Zero and skip, so we can treat what we have as a string */
784 if( NextLine >= ServiceDBData + ValidData )
785 break;
786
787 *NextLine = 0; NextLine++;
788
789 Comment = strchr( ThisLine, '#' );
790 if( Comment ) *Comment = 0; /* Terminate at comment start */
791
792 if( DecodeServEntFromString( ThisLine,
793 &ServiceName,
794 &PortNumberStr,
795 &ProtocolStr,
796 Aliases,
797 WS2_INTERNAL_MAX_ALIAS ) &&
798 !strcmp( ServiceName, name ) &&
799 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) {
800
801 WS_DbgPrint(MAX_TRACE,("Found the service entry.\n"));
802 Found = TRUE;
803 SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) +
804 (NextLine - ThisLine);
805 break;
806 }
807
808 /* Get rid of everything we read so far */
809 while( NextLine <= ServiceDBData + ValidData &&
810 isspace( *NextLine ) ) NextLine++;
811
812 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
813 ServiceDBData + ValidData - NextLine));
814
815 memmove( ServiceDBData, NextLine,
816 ServiceDBData + ValidData - NextLine );
817 ValidData -= NextLine - ServiceDBData;
818 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
819 }
820
821 /* This we'll do no matter what */
822 CloseHandle( ServicesFile );
823
824 if( !Found ) {
825 WS_DbgPrint(MAX_TRACE,("Not found\n"));
826 WSASetLastError( WSANO_DATA );
827 return NULL;
828 }
829
830 if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded ) {
831 /* Free previous getservbyname buffer, allocate bigger */
832 if( p->Getservbyname )
833 HeapFree(GlobalHeap, 0, p->Getservbyname);
834 p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded);
835 if( !p->Getservbyname ) {
836 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
837 SizeNeeded));
838 WSASetLastError( WSATRY_AGAIN );
839 return NULL;
840 }
841 p->Getservbyname->Size = SizeNeeded;
842 }
843
844 /* Copy the data */
845 memmove( p->Getservbyname->Data,
846 ThisLine,
847 NextLine - ThisLine );
848
849 ADJ_PTR(ServiceName,ThisLine,p->Getservbyname->Data);
850 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyname->Data);
851 WS_DbgPrint(MAX_TRACE,
852 ("ServiceName: %s, Protocol: %s\n", ServiceName, ProtocolStr));
853
854 for( i = 0; Aliases[i]; i++ ) {
855 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data);
856 WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i]));
857 }
858
859 memcpy(p->Getservbyname,Aliases,sizeof(Aliases));
860
861 /* Create the struct proper */
862 p->Getservbyname->ServerEntry.s_name = ServiceName;
863 p->Getservbyname->ServerEntry.s_aliases = p->Getservbyname->Aliases;
864 p->Getservbyname->ServerEntry.s_port = htons(atoi(PortNumberStr));
865 p->Getservbyname->ServerEntry.s_proto = ProtocolStr;
866
867 return &p->Getservbyname->ServerEntry;
868 }
869
870
871 /*
872 * @implemented
873 */
874 LPSERVENT
875 EXPORT
876 getservbyport(
877 IN INT port,
878 IN CONST CHAR FAR* proto)
879 {
880 BOOL Found = FALSE;
881 HANDLE ServicesFile;
882 CHAR ServiceDBData[BUFSIZ] = { 0 };
883 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
884 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
885 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
886 ProtocolStr = 0, Comment = 0;
887 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
888 UINT i,SizeNeeded = 0,
889 SystemDirSize = sizeof(ServiceDBData) - 1;
890 DWORD ReadSize = 0, ValidData = 0;
891 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
892
893 if( !p ) {
894 WSASetLastError( WSANOTINITIALISED );
895 return NULL;
896 }
897
898 if ( !port ) {
899 WSASetLastError( WSANO_RECOVERY );
900 return NULL;
901 }
902
903 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) {
904 WSASetLastError( WSANO_RECOVERY );
905 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
906 return NULL; /* Can't get system directory */
907 }
908
909 strncat( SystemDirectory, ServicesFileLocation, SystemDirSize );
910
911 ServicesFile = CreateFileA( SystemDirectory,
912 GENERIC_READ,
913 FILE_SHARE_READ,
914 NULL,
915 OPEN_EXISTING,
916 FILE_ATTRIBUTE_NORMAL |
917 FILE_FLAG_SEQUENTIAL_SCAN,
918 NULL );
919
920 if( ServicesFile == INVALID_HANDLE_VALUE ) {
921 WSASetLastError( WSANO_RECOVERY );
922 return NULL;
923 }
924
925 /* Scan the services file ...
926 *
927 * We will read up to BUFSIZ bytes per pass, until the buffer does not
928 * contain a full line, then we will try to read more.
929 *
930 * We fall from the loop if the buffer does not have a line terminator.
931 */
932
933 /* Initial Read */
934 while( !Found &&
935 ReadFile( ServicesFile, ServiceDBData + ValidData,
936 sizeof( ServiceDBData ) - ValidData,
937 &ReadSize, NULL ) ) {
938 ValidData += ReadSize;
939 ReadSize = 0;
940 NextLine = ThisLine = ServiceDBData;
941
942 /* Find the beginning of the next line */
943 while( NextLine < ServiceDBData + ValidData &&
944 *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
945
946 /* Zero and skip, so we can treat what we have as a string */
947 if( NextLine >= ServiceDBData + ValidData )
948 break;
949
950 *NextLine = 0; NextLine++;
951
952 Comment = strchr( ThisLine, '#' );
953 if( Comment ) *Comment = 0; /* Terminate at comment start */
954
955 if( DecodeServEntFromString( ThisLine,
956 &ServiceName,
957 &PortNumberStr,
958 &ProtocolStr,
959 Aliases,
960 WS2_INTERNAL_MAX_ALIAS ) &&
961 (htons(atoi( PortNumberStr )) == port ) &&
962 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) {
963
964 WS_DbgPrint(MAX_TRACE,("Found the port entry.\n"));
965
966 Found = TRUE;
967 SizeNeeded = sizeof(WINSOCK_GETSERVBYPORT_CACHE) +
968 (NextLine - ThisLine);
969 break;
970 }
971
972 /* Get rid of everything we read so far */
973 while( NextLine <= ServiceDBData + ValidData &&
974 isspace( *NextLine ) ) NextLine++;
975
976 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
977 ServiceDBData + ValidData - NextLine));
978
979 memmove( ServiceDBData, NextLine,
980 ServiceDBData + ValidData - NextLine );
981 ValidData -= NextLine - ServiceDBData;
982 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
983 }
984
985 /* This we'll do no matter what */
986 CloseHandle( ServicesFile );
987
988 if( !Found ) {
989 WS_DbgPrint(MAX_TRACE,("Not found\n"));
990 WSASetLastError( WSANO_DATA );
991 return NULL;
992 }
993
994 if( !p->Getservbyport || p->Getservbyport->Size < SizeNeeded ) {
995 /* Free previous getservbyport buffer, allocate bigger */
996 if( p->Getservbyport )
997 HeapFree(GlobalHeap, 0, p->Getservbyport);
998 p->Getservbyport = HeapAlloc(GlobalHeap, 0, SizeNeeded);
999 if( !p->Getservbyport ) {
1000 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
1001 SizeNeeded));
1002 WSASetLastError( WSATRY_AGAIN );
1003 return NULL;
1004 }
1005 p->Getservbyport->Size = SizeNeeded;
1006 }
1007 /* Copy the data */
1008 memmove( p->Getservbyport->Data,
1009 ThisLine,
1010 NextLine - ThisLine );
1011
1012 ADJ_PTR(PortNumberStr,ThisLine,p->Getservbyport->Data);
1013 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyport->Data);
1014 WS_DbgPrint(MAX_TRACE,
1015 ("Port Number: %s, Protocol: %s\n", PortNumberStr, ProtocolStr));
1016
1017 for( i = 0; Aliases[i]; i++ ) {
1018 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyport->Data);
1019 WS_DbgPrint(MAX_TRACE,("Aliases %d: %s\n", i, Aliases[i]));
1020 }
1021
1022 memcpy(p->Getservbyport,Aliases,sizeof(Aliases));
1023
1024 /* Create the struct proper */
1025 p->Getservbyport->ServerEntry.s_name = ServiceName;
1026 p->Getservbyport->ServerEntry.s_aliases = p->Getservbyport->Aliases;
1027 p->Getservbyport->ServerEntry.s_port = port;
1028 p->Getservbyport->ServerEntry.s_proto = ProtocolStr;
1029
1030 WS_DbgPrint(MID_TRACE,("s_name: %s\n", ServiceName));
1031
1032 return &p->Getservbyport->ServerEntry;
1033
1034 }
1035
1036
1037 /*
1038 * @implemented
1039 */
1040 ULONG
1041 EXPORT
1042 inet_addr(
1043 IN CONST CHAR FAR* cp)
1044 /*
1045 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1046 * ARGUMENTS:
1047 * cp = Pointer to string with address to convert
1048 * RETURNS:
1049 * Binary representation of IPv4 address, or INADDR_NONE
1050 */
1051 {
1052 UINT i;
1053 PCHAR p;
1054 ULONG u = 0;
1055
1056 p = (PCHAR)cp;
1057
1058 if (strlen(p) == 0)
1059 return INADDR_NONE;
1060
1061 if (strcmp(p, " ") == 0)
1062 return 0;
1063
1064 for (i = 0; i <= 3; i++) {
1065 u += (strtoul(p, &p, 0) << (i * 8));
1066
1067 if (strlen(p) == 0)
1068 return u;
1069
1070 if (p[0] != '.')
1071 return INADDR_NONE;
1072
1073 p++;
1074 }
1075
1076 return u;
1077 }
1078
1079
1080 /*
1081 * @implemented
1082 */
1083 CHAR FAR*
1084 EXPORT
1085 inet_ntoa(
1086 IN IN_ADDR in)
1087 {
1088 CHAR b[10];
1089 PCHAR p;
1090
1091 p = ((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Intoa;
1092 _itoa(in.S_un.S_addr & 0xFF, b, 10);
1093 strcpy(p, b);
1094 _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10);
1095 strcat(p, ".");
1096 strcat(p, b);
1097 _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10);
1098 strcat(p, ".");
1099 strcat(p, b);
1100 _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
1101 strcat(p, ".");
1102 strcat(p, b);
1103 return (CHAR FAR*)p;
1104 }
1105
1106
1107 /*
1108 * @unimplemented
1109 */
1110 HANDLE
1111 EXPORT
1112 WSAAsyncGetHostByAddr(
1113 IN HWND hWnd,
1114 IN UINT wMsg,
1115 IN CONST CHAR FAR* addr,
1116 IN INT len,
1117 IN INT type,
1118 OUT CHAR FAR* buf,
1119 IN INT buflen)
1120 {
1121 UNIMPLEMENTED
1122
1123 return (HANDLE)0;
1124 }
1125
1126
1127 /*
1128 * @unimplemented
1129 */
1130 HANDLE
1131 EXPORT
1132 WSAAsyncGetHostByName(
1133 IN HWND hWnd,
1134 IN UINT wMsg,
1135 IN CONST CHAR FAR* name,
1136 OUT CHAR FAR* buf,
1137 IN INT buflen)
1138 {
1139 UNIMPLEMENTED
1140
1141 return (HANDLE)0;
1142 }
1143
1144
1145 /*
1146 * @unimplemented
1147 */
1148 HANDLE
1149 EXPORT
1150 WSAAsyncGetProtoByName(
1151 IN HWND hWnd,
1152 IN UINT wMsg,
1153 IN CONST CHAR FAR* name,
1154 OUT CHAR FAR* buf,
1155 IN INT buflen)
1156 {
1157 UNIMPLEMENTED
1158
1159 return (HANDLE)0;
1160 }
1161
1162
1163 /*
1164 * @unimplemented
1165 */
1166 HANDLE
1167 EXPORT
1168 WSAAsyncGetProtoByNumber(
1169 IN HWND hWnd,
1170 IN UINT wMsg,
1171 IN INT number,
1172 OUT CHAR FAR* buf,
1173 IN INT buflen)
1174 {
1175 UNIMPLEMENTED
1176
1177 return (HANDLE)0;
1178 }
1179
1180 /*
1181 * @unimplemented
1182 */
1183 HANDLE
1184 EXPORT
1185 WSAAsyncGetServByName(
1186 IN HWND hWnd,
1187 IN UINT wMsg,
1188 IN CONST CHAR FAR* name,
1189 IN CONST CHAR FAR* proto,
1190 OUT CHAR FAR* buf,
1191 IN INT buflen)
1192 {
1193 UNIMPLEMENTED
1194
1195 return (HANDLE)0;
1196 }
1197
1198
1199 /*
1200 * @unimplemented
1201 */
1202 HANDLE
1203 EXPORT
1204 WSAAsyncGetServByPort(
1205 IN HWND hWnd,
1206 IN UINT wMsg,
1207 IN INT port,
1208 IN CONST CHAR FAR* proto,
1209 OUT CHAR FAR* buf,
1210 IN INT buflen)
1211 {
1212 UNIMPLEMENTED
1213
1214 return (HANDLE)0;
1215 }
1216
1217 /* EOF */