reshuffling of dlls
[reactos.git] / reactos / dll / 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 INT ret, len;
324 LPWSTR szTemp;
325 LPWSAPROTOCOL_INFOW lpProtoInfoW = NULL;
326
327 len = MultiByteToWideChar( CP_ACP, 0, AddressString, -1, NULL, 0 );
328 szTemp = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
329 MultiByteToWideChar( CP_ACP, 0, AddressString, -1, szTemp, len );
330
331 if (lpProtocolInfo)
332 {
333 len = WSAPROTOCOL_LEN+1;
334 lpProtoInfoW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
335
336 memcpy( lpProtoInfoW, lpProtocolInfo, sizeof(LPWSAPROTOCOL_INFOA));
337
338 MultiByteToWideChar( CP_ACP, 0, lpProtocolInfo->szProtocol, -1, lpProtoInfoW->szProtocol, len );
339 }
340
341 ret = WSAStringToAddressW(szTemp, AddressFamily, lpProtoInfoW, lpAddress, lpAddressLength);
342
343 HeapFree( GetProcessHeap(), 0, szTemp );
344
345 if (lpProtocolInfo)
346 HeapFree( GetProcessHeap(), 0, lpProtoInfoW );
347
348 WSASetLastError(ret);
349 return ret;
350 }
351
352
353
354 /*
355 * @implement
356 */
357 INT
358 EXPORT
359 WSAStringToAddressW(
360 IN LPWSTR AddressString,
361 IN INT AddressFamily,
362 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
363 OUT LPSOCKADDR lpAddress,
364 IN OUT LPINT lpAddressLength)
365 {
366 int pos=0;
367 int res=0;
368 LONG inetaddr = 0;
369 LPWSTR *bp=NULL;
370
371 SOCKADDR_IN *sockaddr = (SOCKADDR_IN *) lpAddress;
372
373 if (!lpAddressLength || !lpAddress)
374 return SOCKET_ERROR;
375
376 if (AddressString==NULL)
377 return WSAEINVAL;
378
379 /* Set right adress family */
380 if (lpProtocolInfo!=NULL)
381 sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
382
383 else sockaddr->sin_family = AddressFamily;
384
385 /* Report size */
386 if (AddressFamily == AF_INET)
387 {
388 if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
389 {
390 *lpAddressLength = sizeof(SOCKADDR_IN);
391 res = WSAEFAULT;
392 }
393 else
394 {
395 if (!lpAddress)
396 res = WSAEINVAL;
397 else
398 {
399 // translate now ip string to ip
400
401 /* rest sockaddr.sin_addr.s_addr
402 for we need to be sure it is zero when we come to while */
403 memset(lpAddress,0,sizeof(SOCKADDR_IN));
404
405 /* Set right adress family */
406 sockaddr->sin_family = AF_INET;
407
408 /* Get port number */
409 pos = wcscspn(AddressString,L":") + 1;
410 if (pos < (int)wcslen(AddressString))
411 sockaddr->sin_port = wcstol(&AddressString[pos],bp,10);
412
413 else
414 sockaddr->sin_port = 0;
415
416 /* Get ip number */
417 pos=0;
418 inetaddr=0;
419
420 while (pos < (int)wcslen(AddressString))
421 {
422 inetaddr = (inetaddr<<8) + ((UCHAR)wcstol(&AddressString[pos],bp,10));
423 pos += wcscspn( &AddressString[pos],L".") +1 ;
424 }
425
426 res = 0;
427 sockaddr->sin_addr.s_addr = inetaddr;
428 }
429
430 }
431 }
432
433 WSASetLastError(res);
434 if (!res) return 0;
435 return SOCKET_ERROR;
436 }
437
438 void check_hostent(struct hostent **he) {
439 struct hostent *new_he;
440 WS_DbgPrint(MID_TRACE,("*he: %x\n",*he));
441 if(!*he) {
442 new_he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent) + MAX_HOSTNAME_LEN + 1);
443 new_he->h_name = (PCHAR)(new_he + 1);
444 new_he->h_aliases = 0;
445 new_he->h_addrtype = 0; // AF_INET
446 new_he->h_length = 0; // sizeof(in_addr)
447 new_he->h_addr_list = HeapAlloc(GlobalHeap, 0, sizeof(char *) * 2);
448 RtlZeroMemory(new_he->h_addr_list, sizeof(char *) * 2);
449 *he = new_he;
450 }
451 }
452
453 void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr) {
454 ASSERT(he);
455 //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
456 //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
457 strncpy(he->h_name, name, MAX_HOSTNAME_LEN);
458 he->h_aliases = 0;
459 he->h_addrtype = AF_INET;
460 he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr);
461 if( he->h_addr_list[0] ) HeapFree( GlobalHeap, 0, he->h_addr_list[0] );
462 he->h_addr_list[0] = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
463 WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0]));
464 RtlCopyMemory(he->h_addr_list[0], (char*)&addr.IpAddress,
465 sizeof(addr.IpAddress));
466 he->h_addr_list[1] = 0;
467 }
468
469
470 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
471 void free_hostent(struct hostent *he) {
472 if(he) {
473 HFREE(he->h_name);
474 char *next = he->h_aliases[0];
475 while(next) { HFREE(next); next++; }
476 next = he->h_addr_list[0];
477 while(next) { HFREE(next); next++; }
478 HFREE(he->h_addr_list);
479 HFREE(he);
480 }
481 }
482
483 /* WinSock 1.1 compatible name resolution APIs */
484
485 /*
486 * @unimplemented
487 */
488 LPHOSTENT
489 EXPORT
490 gethostbyaddr(
491 IN CONST CHAR FAR* addr,
492 IN INT len,
493 IN INT type)
494 {
495 UNIMPLEMENTED
496
497 return (LPHOSTENT)NULL;
498 }
499
500 /*
501 Assumes rfc 1123 - adam *
502 addr[1] = 0;
503 addr[0] = inet_addr(name);
504 strcpy( hostname, name );
505 if(addr[0] == 0xffffffff) return NULL;
506 he.h_addr_list = (void *)addr;
507 he.h_name = hostname;
508 he.h_aliases = NULL;
509 he.h_addrtype = AF_INET;
510 he.h_length = sizeof(addr);
511 return &he;
512
513 <RANT>
514 From the MSDN Platform SDK: Windows Sockets 2
515 "The gethostbyname function cannot resolve IP address strings passed to it.
516 Such a request is treated exactly as if an unknown host name were passed."
517 </RANT>
518
519 Defferring to the the documented behaviour, rather than the unix behaviour
520 What if the hostname is in the HOSTS file? see getservbyname
521
522 * @implemented
523 */
524
525 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
526 /* see ws2_32.h, winsock2.h*/
527 /*getnetworkparameters - iphlp api */
528 /*
529 REFERENCES
530
531 servent -- w32api/include/winsock2.h
532 PWINSOCK_THREAD_BLOCK -- ws2_32.h
533 dllmain.c -- threadlocal memory allocation / deallocation
534 lib/dnsapi
535
536
537 */
538 /* lib/adns/src/adns.h XXX */
539
540
541 /*
542 struct hostent {
543 char *h_name;
544 char **h_aliases;
545 short h_addrtype;
546 short h_length;
547 char **h_addr_list;
548 #define h_addr h_addr_list[0]
549 };
550 struct servent {
551 char *s_name;
552 char **s_aliases;
553 short s_port;
554 char *s_proto;
555 };
556
557
558 struct hostent defined in w32api/include/winsock2.h
559 */
560
561 void free_servent(struct servent* s) {
562 HFREE(s->s_name);
563 char* next = s->s_aliases[0];
564 while(next) { HFREE(next); next++; }
565 s->s_port = 0;
566 HFREE(s->s_proto);
567 HFREE(s);
568 }
569
570
571
572 LPHOSTENT
573 EXPORT
574 gethostbyname(
575 IN CONST CHAR FAR* name)
576 {
577 enum addr_type{ GH_INVALID, GH_IPV6, GH_IPV4, GH_RFC1123_DNS };
578 typedef enum addr_type addr_type;
579 addr_type addr;
580 int ret = 0;
581 char* found = 0;
582 DNS_STATUS dns_status = {0};
583 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
584 PDNS_RECORD dp = 0;
585
586 addr = GH_INVALID;
587
588 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
589
590 if( !p ) {
591 WSASetLastError( WSANOTINITIALISED );
592 return NULL;
593 }
594
595 check_hostent(&p->Hostent); /*XXX alloc_hostent*/
596
597 /* Hostname NULL - behave like gethostname */
598 if(name == NULL) {
599 ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
600 return p->Hostent;
601 }
602
603 if(ret) {
604 WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA ??
605 return NULL;
606 }
607
608 /* Is it an IPv6 address? */
609 found = strstr(name, ":");
610 if( found != NULL ) {
611 addr = GH_IPV6;
612 goto act;
613 }
614
615 /* Is it an IPv4 address? */
616 if (!isalpha(name[0])) {
617 addr = GH_IPV4;
618 goto act;
619 }
620
621 addr = GH_RFC1123_DNS;
622
623 /* Broken out in case we want to get fancy later */
624 act:
625 switch(addr){
626 case GH_IPV6:
627 WSASetLastError(STATUS_NOT_IMPLEMENTED);
628 return NULL;
629 break;
630
631 case GH_INVALID:
632 WSASetLastError(WSAEFAULT);
633 return NULL;
634 break;
635
636 /* Note: If passed an IP address, MSDN says that gethostbyname()
637 treats it as an unknown host.
638 This is different from the unix implementation. Use inet_addr()
639 */
640 case GH_IPV4:
641 case GH_RFC1123_DNS:
642 /* DNS_TYPE_A: include/WinDNS.h */
643 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
644 dns_status = DnsQuery_A ( name, DNS_TYPE_A, DNS_QUERY_STANDARD,
645 0, /* extra dns servers */ &dp, 0 );
646
647 if(dns_status == 0) {
648 //ASSERT(dp->wType == DNS_TYPE_A);
649 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
650 PDNS_RECORD curr;
651 for(curr=dp;
652 curr != NULL && curr->wType != DNS_TYPE_A;
653 curr = curr->pNext ) {
654 WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
655 /*empty */
656 }
657
658 if(curr) {
659 WS_DbgPrint(MID_TRACE,("populating hostent\n"));
660 WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
661 populate_hostent(p->Hostent, (PCHAR)curr->pName, curr->Data.A);
662 DnsRecordListFree(dp, DnsFreeRecordList);
663 return p->Hostent;
664 } else {
665 DnsRecordListFree(dp, DnsFreeRecordList);
666 }
667 }
668
669 WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
670 dns_status));
671 WSASetLastError(WSAHOST_NOT_FOUND);
672 return NULL;
673
674 break;
675
676 default:
677 WSASetLastError(WSANO_RECOVERY);
678 return NULL;
679 break;
680 }
681
682 WSASetLastError(WSANO_RECOVERY);
683 return NULL;
684 }
685
686 /*
687 * @implemented
688 */
689 INT
690 EXPORT
691 gethostname(
692 OUT CHAR FAR* name,
693 IN INT namelen)
694 {
695 DWORD size = namelen;
696
697 int ret = GetComputerNameExA(ComputerNameDnsHostname, name, &size);
698 if(ret == 0) {
699 WSASetLastError(WSAEFAULT);
700 return SOCKET_ERROR;
701 } else {
702 name[namelen-1] = '\0';
703 return 0;
704 }
705 }
706
707
708 /*
709 * XXX arty -- Partial implementation pending a better one. This one will
710 * do for normal purposes.#include <ws2_32.h>
711 *
712 * Return the address of a static LPPROTOENT corresponding to the named
713 * protocol. These structs aren't very interesting, so I'm not too ashamed
714 * to have this function work on builtins for now.
715 *
716 * @unimplemented
717 */
718 LPPROTOENT
719 EXPORT
720 getprotobyname(
721 IN CONST CHAR FAR* name)
722 {
723 static CHAR *udp_aliases = 0;
724 static PROTOENT udp = { "udp", &udp_aliases, 17 };
725 static CHAR *tcp_aliases = 0;
726 static PROTOENT tcp = { "tcp", &tcp_aliases, 6 };
727 if( !_stricmp( name, "udp" ) ) {
728 return &udp;
729 } else if( !_stricmp( name, "tcp" ) ) {
730 return &tcp;
731 }
732
733 return 0;
734 }
735
736 /*
737 * @unimplemented
738 */
739 LPPROTOENT
740 EXPORT
741 getprotobynumber(
742 IN INT number)
743 {
744 UNIMPLEMENTED
745
746 return (LPPROTOENT)NULL;
747 }
748
749 #define SKIPWS(ptr,act) \
750 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
751 #define SKIPANDMARKSTR(ptr,act) \
752 {while(*ptr && !isspace(*ptr)) ptr++; \
753 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
754
755
756 static BOOL DecodeServEntFromString( IN PCHAR ServiceString,
757 OUT PCHAR *ServiceName,
758 OUT PCHAR *PortNumberStr,
759 OUT PCHAR *ProtocolStr,
760 IN PCHAR *Aliases,
761 IN DWORD MaxAlias ) {
762 UINT NAliases = 0;
763
764 WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
765
766 SKIPWS(ServiceString, return FALSE);
767 *ServiceName = ServiceString;
768 SKIPANDMARKSTR(ServiceString, return FALSE);
769 SKIPWS(ServiceString, return FALSE);
770 *PortNumberStr = ServiceString;
771 SKIPANDMARKSTR(ServiceString, ;);
772
773 while( *ServiceString && NAliases < MaxAlias - 1 ) {
774 SKIPWS(ServiceString, break);
775 if( *ServiceString ) {
776 SKIPANDMARKSTR(ServiceString, ;);
777 if( strlen(ServiceString) ) {
778 WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
779 *Aliases++ = ServiceString;
780 NAliases++;
781 }
782 }
783 }
784 *Aliases = NULL;
785
786 *ProtocolStr = strchr(*PortNumberStr,'/');
787 if( !*ProtocolStr ) return FALSE;
788 **ProtocolStr = 0; (*ProtocolStr)++;
789
790 WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
791 *ServiceName, *ProtocolStr, *PortNumberStr,
792 NAliases));
793
794 return TRUE;
795 }
796
797 #define ADJ_PTR(p,b1,b2) p = (p - b1) + b2
798
799 /*
800 * @implemented
801 */
802 LPSERVENT
803 EXPORT
804 getservbyname(
805
806 IN CONST CHAR FAR* name,
807 IN CONST CHAR FAR* proto)
808 {
809 BOOL Found = FALSE;
810 HANDLE ServicesFile;
811 CHAR ServiceDBData[BUFSIZ] = { 0 };
812 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
813 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
814 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
815 ProtocolStr = 0, Comment = 0;
816 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
817 UINT i,SizeNeeded = 0,
818 SystemDirSize = sizeof(ServiceDBData) - 1;
819 DWORD ReadSize = 0, ValidData = 0;
820 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
821
822 if( !p ) {
823 WSASetLastError( WSANOTINITIALISED );
824 return NULL;
825 }
826
827 if( !name ) {
828 WSASetLastError( WSANO_RECOVERY );
829 return NULL;
830 }
831
832 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) {
833 WSASetLastError( WSANO_RECOVERY );
834 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
835 return NULL; /* Can't get system directory */
836 }
837
838 strncat( SystemDirectory, ServicesFileLocation, SystemDirSize );
839
840 ServicesFile = CreateFileA( SystemDirectory,
841 GENERIC_READ,
842 FILE_SHARE_READ,
843 NULL,
844 OPEN_EXISTING,
845 FILE_ATTRIBUTE_NORMAL |
846 FILE_FLAG_SEQUENTIAL_SCAN,
847 NULL );
848
849 if( ServicesFile == INVALID_HANDLE_VALUE ) {
850 WSASetLastError( WSANO_RECOVERY );
851 return NULL;
852 }
853
854 /* Scan the services file ...
855 *
856 * We will read up to BUFSIZ bytes per pass, until the buffer does not
857 * contain a full line, then we will try to read more.
858 *
859 * We fall from the loop if the buffer does not have a line terminator.
860 */
861
862 /* Initial Read */
863 while( !Found &&
864 ReadFile( ServicesFile, ServiceDBData + ValidData,
865 sizeof( ServiceDBData ) - ValidData,
866 &ReadSize, NULL ) ) {
867 ValidData += ReadSize;
868 ReadSize = 0;
869 NextLine = ThisLine = ServiceDBData;
870
871 /* Find the beginning of the next line */
872 while( NextLine < ServiceDBData + ValidData &&
873 *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
874
875 /* Zero and skip, so we can treat what we have as a string */
876 if( NextLine >= ServiceDBData + ValidData )
877 break;
878
879 *NextLine = 0; NextLine++;
880
881 Comment = strchr( ThisLine, '#' );
882 if( Comment ) *Comment = 0; /* Terminate at comment start */
883
884 if( DecodeServEntFromString( ThisLine,
885 &ServiceName,
886 &PortNumberStr,
887 &ProtocolStr,
888 Aliases,
889 WS2_INTERNAL_MAX_ALIAS ) &&
890 !strcmp( ServiceName, name ) &&
891 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) {
892
893 WS_DbgPrint(MAX_TRACE,("Found the service entry.\n"));
894 Found = TRUE;
895 SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) +
896 (NextLine - ThisLine);
897 break;
898 }
899
900 /* Get rid of everything we read so far */
901 while( NextLine <= ServiceDBData + ValidData &&
902 isspace( *NextLine ) ) NextLine++;
903
904 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
905 ServiceDBData + ValidData - NextLine));
906
907 memmove( ServiceDBData, NextLine,
908 ServiceDBData + ValidData - NextLine );
909 ValidData -= NextLine - ServiceDBData;
910 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
911 }
912
913 /* This we'll do no matter what */
914 CloseHandle( ServicesFile );
915
916 if( !Found ) {
917 WS_DbgPrint(MAX_TRACE,("Not found\n"));
918 WSASetLastError( WSANO_DATA );
919 return NULL;
920 }
921
922 if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded ) {
923 /* Free previous getservbyname buffer, allocate bigger */
924 if( p->Getservbyname )
925 HeapFree(GlobalHeap, 0, p->Getservbyname);
926 p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded);
927 if( !p->Getservbyname ) {
928 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
929 SizeNeeded));
930 WSASetLastError( WSATRY_AGAIN );
931 return NULL;
932 }
933 p->Getservbyname->Size = SizeNeeded;
934 }
935
936 /* Copy the data */
937 memmove( p->Getservbyname->Data,
938 ThisLine,
939 NextLine - ThisLine );
940
941 ADJ_PTR(ServiceName,ThisLine,p->Getservbyname->Data);
942 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyname->Data);
943 WS_DbgPrint(MAX_TRACE,
944 ("ServiceName: %s, Protocol: %s\n", ServiceName, ProtocolStr));
945
946 for( i = 0; Aliases[i]; i++ ) {
947 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data);
948 WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i]));
949 }
950
951 memcpy(p->Getservbyname,Aliases,sizeof(Aliases));
952
953 /* Create the struct proper */
954 p->Getservbyname->ServerEntry.s_name = ServiceName;
955 p->Getservbyname->ServerEntry.s_aliases = p->Getservbyname->Aliases;
956 p->Getservbyname->ServerEntry.s_port = htons(atoi(PortNumberStr));
957 p->Getservbyname->ServerEntry.s_proto = ProtocolStr;
958
959 return &p->Getservbyname->ServerEntry;
960 }
961
962
963 /*
964 * @implemented
965 */
966 LPSERVENT
967 EXPORT
968 getservbyport(
969 IN INT port,
970 IN CONST CHAR FAR* proto)
971 {
972 BOOL Found = FALSE;
973 HANDLE ServicesFile;
974 CHAR ServiceDBData[BUFSIZ] = { 0 };
975 PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
976 PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
977 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
978 ProtocolStr = 0, Comment = 0;
979 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
980 UINT i,SizeNeeded = 0,
981 SystemDirSize = sizeof(ServiceDBData) - 1;
982 DWORD ReadSize = 0, ValidData = 0;
983 PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
984
985 if( !p ) {
986 WSASetLastError( WSANOTINITIALISED );
987 return NULL;
988 }
989
990 if ( !port ) {
991 WSASetLastError( WSANO_RECOVERY );
992 return NULL;
993 }
994
995 if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) {
996 WSASetLastError( WSANO_RECOVERY );
997 WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
998 return NULL; /* Can't get system directory */
999 }
1000
1001 strncat( SystemDirectory, ServicesFileLocation, SystemDirSize );
1002
1003 ServicesFile = CreateFileA( SystemDirectory,
1004 GENERIC_READ,
1005 FILE_SHARE_READ,
1006 NULL,
1007 OPEN_EXISTING,
1008 FILE_ATTRIBUTE_NORMAL |
1009 FILE_FLAG_SEQUENTIAL_SCAN,
1010 NULL );
1011
1012 if( ServicesFile == INVALID_HANDLE_VALUE ) {
1013 WSASetLastError( WSANO_RECOVERY );
1014 return NULL;
1015 }
1016
1017 /* Scan the services file ...
1018 *
1019 * We will read up to BUFSIZ bytes per pass, until the buffer does not
1020 * contain a full line, then we will try to read more.
1021 *
1022 * We fall from the loop if the buffer does not have a line terminator.
1023 */
1024
1025 /* Initial Read */
1026 while( !Found &&
1027 ReadFile( ServicesFile, ServiceDBData + ValidData,
1028 sizeof( ServiceDBData ) - ValidData,
1029 &ReadSize, NULL ) ) {
1030 ValidData += ReadSize;
1031 ReadSize = 0;
1032 NextLine = ThisLine = ServiceDBData;
1033
1034 /* Find the beginning of the next line */
1035 while( NextLine < ServiceDBData + ValidData &&
1036 *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
1037
1038 /* Zero and skip, so we can treat what we have as a string */
1039 if( NextLine >= ServiceDBData + ValidData )
1040 break;
1041
1042 *NextLine = 0; NextLine++;
1043
1044 Comment = strchr( ThisLine, '#' );
1045 if( Comment ) *Comment = 0; /* Terminate at comment start */
1046
1047 if( DecodeServEntFromString( ThisLine,
1048 &ServiceName,
1049 &PortNumberStr,
1050 &ProtocolStr,
1051 Aliases,
1052 WS2_INTERNAL_MAX_ALIAS ) &&
1053 (htons(atoi( PortNumberStr )) == port ) &&
1054 (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) {
1055
1056 WS_DbgPrint(MAX_TRACE,("Found the port entry.\n"));
1057
1058 Found = TRUE;
1059 SizeNeeded = sizeof(WINSOCK_GETSERVBYPORT_CACHE) +
1060 (NextLine - ThisLine);
1061 break;
1062 }
1063
1064 /* Get rid of everything we read so far */
1065 while( NextLine <= ServiceDBData + ValidData &&
1066 isspace( *NextLine ) ) NextLine++;
1067
1068 WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
1069 ServiceDBData + ValidData - NextLine));
1070
1071 memmove( ServiceDBData, NextLine,
1072 ServiceDBData + ValidData - NextLine );
1073 ValidData -= NextLine - ServiceDBData;
1074 WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
1075 }
1076
1077 /* This we'll do no matter what */
1078 CloseHandle( ServicesFile );
1079
1080 if( !Found ) {
1081 WS_DbgPrint(MAX_TRACE,("Not found\n"));
1082 WSASetLastError( WSANO_DATA );
1083 return NULL;
1084 }
1085
1086 if( !p->Getservbyport || p->Getservbyport->Size < SizeNeeded ) {
1087 /* Free previous getservbyport buffer, allocate bigger */
1088 if( p->Getservbyport )
1089 HeapFree(GlobalHeap, 0, p->Getservbyport);
1090 p->Getservbyport = HeapAlloc(GlobalHeap, 0, SizeNeeded);
1091 if( !p->Getservbyport ) {
1092 WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
1093 SizeNeeded));
1094 WSASetLastError( WSATRY_AGAIN );
1095 return NULL;
1096 }
1097 p->Getservbyport->Size = SizeNeeded;
1098 }
1099 /* Copy the data */
1100 memmove( p->Getservbyport->Data,
1101 ThisLine,
1102 NextLine - ThisLine );
1103
1104 ADJ_PTR(PortNumberStr,ThisLine,p->Getservbyport->Data);
1105 ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyport->Data);
1106 WS_DbgPrint(MAX_TRACE,
1107 ("Port Number: %s, Protocol: %s\n", PortNumberStr, ProtocolStr));
1108
1109 for( i = 0; Aliases[i]; i++ ) {
1110 ADJ_PTR(Aliases[i],ThisLine,p->Getservbyport->Data);
1111 WS_DbgPrint(MAX_TRACE,("Aliases %d: %s\n", i, Aliases[i]));
1112 }
1113
1114 memcpy(p->Getservbyport,Aliases,sizeof(Aliases));
1115
1116 /* Create the struct proper */
1117 p->Getservbyport->ServerEntry.s_name = ServiceName;
1118 p->Getservbyport->ServerEntry.s_aliases = p->Getservbyport->Aliases;
1119 p->Getservbyport->ServerEntry.s_port = port;
1120 p->Getservbyport->ServerEntry.s_proto = ProtocolStr;
1121
1122 WS_DbgPrint(MID_TRACE,("s_name: %s\n", ServiceName));
1123
1124 return &p->Getservbyport->ServerEntry;
1125
1126 }
1127
1128
1129 /*
1130 * @implemented
1131 */
1132 ULONG
1133 EXPORT
1134 inet_addr(
1135 IN CONST CHAR FAR* cp)
1136 /*
1137 * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
1138 * ARGUMENTS:
1139 * cp = Pointer to string with address to convert
1140 * RETURNS:
1141 * Binary representation of IPv4 address, or INADDR_NONE
1142 */
1143 {
1144 UINT i;
1145 PCHAR p;
1146 ULONG u = 0;
1147
1148 p = (PCHAR)cp;
1149
1150 if (strlen(p) == 0)
1151 return INADDR_NONE;
1152
1153 if (strcmp(p, " ") == 0)
1154 return 0;
1155
1156 for (i = 0; i <= 3; i++) {
1157 u += (strtoul(p, &p, 0) << (i * 8));
1158
1159 if (strlen(p) == 0)
1160 return u;
1161
1162 if (p[0] != '.')
1163 return INADDR_NONE;
1164
1165 p++;
1166 }
1167
1168 return u;
1169 }
1170
1171
1172 /*
1173 * @implemented
1174 */
1175 CHAR FAR*
1176 EXPORT
1177 inet_ntoa(
1178 IN IN_ADDR in)
1179 {
1180 CHAR b[10];
1181 PCHAR p;
1182
1183 p = ((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Intoa;
1184 _itoa(in.S_un.S_addr & 0xFF, b, 10);
1185 strcpy(p, b);
1186 _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10);
1187 strcat(p, ".");
1188 strcat(p, b);
1189 _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10);
1190 strcat(p, ".");
1191 strcat(p, b);
1192 _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
1193 strcat(p, ".");
1194 strcat(p, b);
1195 return (CHAR FAR*)p;
1196 }
1197
1198
1199 /*
1200 * @unimplemented
1201 */
1202 HANDLE
1203 EXPORT
1204 WSAAsyncGetHostByAddr(
1205 IN HWND hWnd,
1206 IN UINT wMsg,
1207 IN CONST CHAR FAR* addr,
1208 IN INT len,
1209 IN INT type,
1210 OUT CHAR FAR* buf,
1211 IN INT buflen)
1212 {
1213 UNIMPLEMENTED
1214
1215 return (HANDLE)0;
1216 }
1217
1218
1219 /*
1220 * @unimplemented
1221 */
1222 HANDLE
1223 EXPORT
1224 WSAAsyncGetHostByName(
1225 IN HWND hWnd,
1226 IN UINT wMsg,
1227 IN CONST CHAR FAR* name,
1228 OUT CHAR FAR* buf,
1229 IN INT buflen)
1230 {
1231 UNIMPLEMENTED
1232
1233 return (HANDLE)0;
1234 }
1235
1236
1237 /*
1238 * @unimplemented
1239 */
1240 HANDLE
1241 EXPORT
1242 WSAAsyncGetProtoByName(
1243 IN HWND hWnd,
1244 IN UINT wMsg,
1245 IN CONST CHAR FAR* name,
1246 OUT CHAR FAR* buf,
1247 IN INT buflen)
1248 {
1249 UNIMPLEMENTED
1250
1251 return (HANDLE)0;
1252 }
1253
1254
1255 /*
1256 * @unimplemented
1257 */
1258 HANDLE
1259 EXPORT
1260 WSAAsyncGetProtoByNumber(
1261 IN HWND hWnd,
1262 IN UINT wMsg,
1263 IN INT number,
1264 OUT CHAR FAR* buf,
1265 IN INT buflen)
1266 {
1267 UNIMPLEMENTED
1268
1269 return (HANDLE)0;
1270 }
1271
1272 /*
1273 * @unimplemented
1274 */
1275 HANDLE
1276 EXPORT
1277 WSAAsyncGetServByName(
1278 IN HWND hWnd,
1279 IN UINT wMsg,
1280 IN CONST CHAR FAR* name,
1281 IN CONST CHAR FAR* proto,
1282 OUT CHAR FAR* buf,
1283 IN INT buflen)
1284 {
1285 UNIMPLEMENTED
1286
1287 return (HANDLE)0;
1288 }
1289
1290
1291 /*
1292 * @unimplemented
1293 */
1294 HANDLE
1295 EXPORT
1296 WSAAsyncGetServByPort(
1297 IN HWND hWnd,
1298 IN UINT wMsg,
1299 IN INT port,
1300 IN CONST CHAR FAR* proto,
1301 OUT CHAR FAR* buf,
1302 IN INT buflen)
1303 {
1304 UNIMPLEMENTED
1305
1306 return (HANDLE)0;
1307 }
1308
1309 /* EOF */
1310