Handle WM_CHARs and pass them to TREEVIEW_ProcessLetterKeys. See also
[wine] / dlls / wsock32 / socket.c
1 /*
2  * WSOCK32 specific functions
3  *
4  * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5  */
6
7
8 /*
9   FIXME: This hack is fixing a problem in WsControl.  When we call socket(),
10          it is supposed to call into ws2_32's WSOCK32_socket.
11          The problem is that socket() is predefined in a linux system header that 
12          we are including, which is different from the WINE definition.
13          (cdecl vs. stdapi)  The result is stack corruption.
14
15          The correct answer to this problem is to make winsock.h not dependent 
16          on system headers, that way all of our functions are defined consistently.
17          Until that happens we need this hack.
18 */
19 #define socket  linux_socket
20 /* */
21
22 #include "config.h"
23
24 #include <string.h>
25 #include <sys/types.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "debugtools.h"
29 #include "winsock2.h"
30 #include "winnt.h"
31 #include "wscontrol.h"
32 #include <ctype.h>
33 #include <sys/ioctl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #ifdef HAVE_SYS_SOCKIO_H
38 # include <sys/sockio.h>
39 #endif
40 #ifdef HAVE_NET_IF_H
41 # include <net/if.h>
42 #endif
43
44
45 /* FIXME: The rest of the socket() cdecl<->stdapi stack corruption problem
46           discussed above. */
47 #undef socket
48 extern SOCKET WINAPI socket(INT af, INT type, INT protocol);
49 /* */
50
51
52 DEFAULT_DEBUG_CHANNEL(winsock);
53
54
55 /***********************************************************************
56  *      WsControl()
57  *
58  * WsControl seems to be an undocumented Win95 function. A lot of 
59  * discussion about WsControl can be found on the net, e.g.
60  * Subject:      Re: WSOCK32.DLL WsControl Exported Function
61  * From:         "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
62  * Date:         1997/08/17
63  *
64  * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
65  * on observing the behaviour of WsControl with an app in 
66  * Windows 98.  It is not fully implemented, and there could
67  * be (are?) errors due to incorrect assumptions made.
68  *
69  *
70  * WsControl returns WSCTL_SUCCESS on success.
71  * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
72  * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
73  *
74  * It doesn't seem to generate errors that can be retrieved by 
75  * WSAGetLastError().
76  *
77  */
78
79 DWORD WINAPI WsControl(DWORD protocoll,
80                        DWORD action,
81                        LPVOID pRequestInfo,
82                        LPDWORD pcbRequestInfoLen,
83                        LPVOID pResponseInfo,
84                        LPDWORD pcbResponseInfoLen) 
85 {
86    /* Get the command structure into a pointer we can use,
87       rather than void */
88    TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
89   
90    TRACE ("   WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
91           pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
92           pcommand->toi_class, pcommand->toi_type );
93   
94
95
96    switch (action) 
97    {
98       case WSCNTL_TCPIP_QUERY_INFO: 
99       {
100          switch (pcommand->toi_id)
101          {
102             /* 
103                ENTITY_LIST_ID seems to get number of adapters in the system.
104                (almost like an index to be used when calling other WsControl options)
105             */
106             case ENTITY_LIST_ID: 
107             {
108                TDIEntityID *baseptr = pResponseInfo;
109                int numInt = 0, i;
110
111                if (pcommand->toi_class != INFO_CLASS_GENERIC &&
112                    pcommand->toi_type != INFO_TYPE_PROVIDER) 
113                { 
114                   FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
115                        pcommand->toi_class, pcommand->toi_type);
116                   return (WSAEOPNOTSUPP); 
117                }
118            
119                numInt = WSCNTL_GetInterfaceCount(); 
120                if (numInt < 0)
121                {
122                   ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
123                   return (-1); 
124                }
125
126                if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) ) 
127                {
128                   return (STATUS_BUFFER_TOO_SMALL);
129                }
130            
131                /* 0 it out first */
132                memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2)); 
133                
134                for (i=0; i<numInt; i++)
135                {
136                   /* tei_instance is an network interface identifier.
137                      I'm not quite sure what the difference is between tei_entity values of 
138                      CL_NL_ENTITY and IF_ENTITY */
139                   baseptr->tei_entity = CL_NL_ENTITY;  baseptr->tei_instance = i; baseptr++;
140                   baseptr->tei_entity = IF_ENTITY;     baseptr->tei_instance = i; baseptr++; 
141                }
142
143                /* Calculate size of out buffer */
144                *pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
145             
146                break;
147             }
148           
149           
150             /* ENTITY_TYPE_ID is used to obtain simple information about a 
151                network card, such as MAC Address, description, interface type,
152                number of network addresses, etc. */
153             case ENTITY_TYPE_ID:  /* ALSO: IP_MIB_STATS_ID */
154             {
155                if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER) 
156                {
157                   if (pcommand->toi_entity.tei_entity == IF_ENTITY)
158                   {
159                      * ((ULONG *)pResponseInfo) = IF_MIB; 
160
161                      /* Calculate size of out buffer */
162                      *pcbResponseInfoLen = sizeof (ULONG);
163
164                   }
165                   else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY) 
166                   {
167                      * ((ULONG *)pResponseInfo) = CL_NL_IP;  
168
169                      /* Calculate size of out buffer */
170                      *pcbResponseInfoLen = sizeof (ULONG); 
171                   }
172                }
173                else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
174                         pcommand->toi_type == INFO_TYPE_PROVIDER)
175                {
176                   if (pcommand->toi_entity.tei_entity == IF_ENTITY)
177                   {
178                      /* In this case, we are requesting specific information about a 
179                         a particular network adapter. (MAC Address, speed, data transmitted/received,
180                         etc.)
181                      */ 
182                      IFEntry *IntInfo = (IFEntry *) pResponseInfo;
183                      char ifName[512];
184                      struct ifreq ifInfo;
185                      SOCKET sock;
186
187                      
188                      if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
189                      {
190                         ERR ("Unable to parse /proc filesystem!\n");
191                         return (-1);
192                      }
193                
194                      /* Get a socket so that we can use ioctl */
195                      if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
196                      {
197                         ERR ("Error creating socket!\n");
198                         return (-1);
199                      }
200                    
201                      /* 0 out return structure first */
202                      memset (IntInfo, 0, sizeof(IFEntry));
203                      
204                      /* Interface ID */
205                      IntInfo->if_index = pcommand->toi_entity.tei_instance;
206                      
207                      /* MAC Address - Let's try to do this in a cross-platform way... */
208                      #if defined(SIOCGIFHWADDR) /* Linux */
209                         strcpy(ifInfo.ifr_name, ifName);
210                         if (ioctlsocket(sock, SIOCGIFHWADDR, (ULONG*)&ifInfo) < 0)
211                         {
212                            ERR ("Error obtaining MAC Address!\n");
213                            closesocket(sock);
214                            return (-1);
215                         }
216                         else
217                         {
218                            /* FIXME: Is it correct to assume size of 6? */
219                            memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
220                            IntInfo->if_physaddrlen=6;
221                         }
222                      #elif defined(SIOCGENADDR) /* Solaris */
223                         if (ioctlsocket(sock, SIOCGENADDR, (ULONG*)&ifInfo) < 0)
224                         {
225                            ERR ("Error obtaining MAC Address!\n");
226                            closesocket(sock);
227                            return (-1);
228                         }
229                         else
230                         {
231                            /* FIXME: Is it correct to assume size of 6? */
232                            memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
233                            IntInfo->if_physaddrlen=6;
234                         }
235                      #else
236                         memset (IntInfo->if_physaddr, 0, 6);
237                         ERR ("Unable to determine MAC Address on your platform!\n");
238                      #endif
239
240                      
241                      /* Interface name and length */
242                      strcpy (IntInfo->if_descr, ifName);
243                      IntInfo->if_descrlen= strlen (IntInfo->if_descr);
244                      
245                      /* Obtain bytes transmitted/received for interface */
246                      if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance, 
247                            &IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
248                      {
249                         ERR ("Error obtaining transmit/receive stats for the network interface!\n");
250                         closesocket(sock);
251                         return (-1);
252                      }
253                      
254                      
255                      /* FIXME: How should the below be properly calculated? ******************/
256                      IntInfo->if_type =  0x6; /* Ethernet (?) */
257                      IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
258                      /************************************************************************/
259
260                      closesocket(sock);
261                      *pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen; 
262                   }
263                   else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY) 
264                   {
265                      IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
266                      int numInt;
267                      
268                      /* This case is used to obtain general statistics about the 
269                         network */
270                      
271                      if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
272                      {
273                         return (STATUS_BUFFER_TOO_SMALL);
274                      }
275                      else
276                      {
277                         /* 0 it out first */
278                         memset(infoStruc, 0, sizeof(IPSNMPInfo));
279             
280                         /* Get the number of interfaces */
281                         numInt = WSCNTL_GetInterfaceCount(); 
282                         if (numInt < 0)
283                         {
284                            ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
285                            return (-1); 
286                         }
287
288                         infoStruc->ipsi_numif           = numInt; /* # of interfaces */
289                         infoStruc->ipsi_numaddr         = numInt; /* # of addresses */
290                         infoStruc->ipsi_numroutes       = numInt; /* # of routes ~ FIXME - Is this right? */
291
292                         /* FIXME: How should the below be properly calculated? ******************/
293                         infoStruc->ipsi_forwarding      = 0x0;
294                         infoStruc->ipsi_defaultttl      = 0x0;
295                         infoStruc->ipsi_inreceives      = 0x0;
296                         infoStruc->ipsi_inhdrerrors     = 0x0;
297                         infoStruc->ipsi_inaddrerrors    = 0x0;
298                         infoStruc->ipsi_forwdatagrams   = 0x0;
299                         infoStruc->ipsi_inunknownprotos = 0x0;
300                         infoStruc->ipsi_indiscards      = 0x0;
301                         infoStruc->ipsi_indelivers      = 0x0;
302                         infoStruc->ipsi_outrequests     = 0x0;
303                         infoStruc->ipsi_routingdiscards = 0x0;
304                         infoStruc->ipsi_outdiscards     = 0x0;
305                         infoStruc->ipsi_outnoroutes     = 0x0;
306                         infoStruc->ipsi_reasmtimeout    = 0x0;
307                         infoStruc->ipsi_reasmreqds      = 0x0;
308                         infoStruc->ipsi_reasmoks        = 0x0;
309                         infoStruc->ipsi_reasmfails      = 0x0;
310                         infoStruc->ipsi_fragoks         = 0x0;
311                         infoStruc->ipsi_fragfails       = 0x0;
312                         infoStruc->ipsi_fragcreates     = 0x0;
313                         /************************************************************************/
314                       
315                         /* Calculate size of out buffer */
316                         *pcbResponseInfoLen = sizeof(IPSNMPInfo);
317                      }
318                   }
319                }
320                else
321                {
322                   FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
323                        pcommand->toi_class, pcommand->toi_type);
324                   
325                   return (WSAEOPNOTSUPP); 
326                }
327
328                break;
329             }
330
331
332             /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a 
333                particular network adapter */
334             case IP_MIB_ADDRTABLE_ENTRY_ID: 
335             {
336                IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
337                char ifName[512];
338                struct ifreq ifInfo;
339                SOCKET sock;
340
341                if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
342                {
343                   return (STATUS_BUFFER_TOO_SMALL); 
344                }
345                
346                if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
347                {
348                   ERR ("Unable to parse /proc filesystem!\n");
349                   return (-1);
350                }
351                
352                
353                /* Get a socket so we can use ioctl */
354                if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
355                {
356                   ERR ("Error creating socket!\n");
357                   return (-1);
358                }
359                
360                /* 0 it out first */
361                memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
362                
363                /* Interface Id */
364                baseIPInfo->iae_index     = pcommand->toi_entity.tei_instance;
365                
366                /* IP Address */
367                strcpy (ifInfo.ifr_name, ifName);
368                ifInfo.ifr_addr.sa_family = AF_INET;
369                if (ioctlsocket(sock, SIOCGIFADDR, (ULONG*)&ifInfo) < 0) 
370                {
371                   baseIPInfo->iae_addr = 0x0;
372                }
373                else
374                {
375                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
376                   baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
377                }
378                
379                /* Broadcast Address */
380                strcpy (ifInfo.ifr_name, ifName);
381                if (ioctlsocket(sock, SIOCGIFBRDADDR, (ULONG *)&ifInfo) < 0)
382                {
383                   baseIPInfo->iae_bcastaddr = 0x0;
384                }
385                else
386                {
387                   struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
388                   baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr; 
389                }
390
391                /* Subnet Mask */
392                strcpy(ifInfo.ifr_name, ifName);
393                if (ioctlsocket(sock, SIOCGIFNETMASK, (ULONG *)&ifInfo) < 0)
394                {
395                   baseIPInfo->iae_mask = 0x0;
396                }
397                else
398                {
399                   /* Trying to avoid some compile problems across platforms.
400                      (Linux, FreeBSD, Solaris...) */
401                   #ifndef ifr_netmask
402                      #ifndef ifr_addr
403                         baseIPInfo->iae_mask = 0;
404                         ERR ("Unable to determine Netmask on your platform!\n");
405                      #else
406                         struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
407                         baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr; 
408                      #endif
409                   #else  
410                      struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
411                      baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr; 
412                   #endif
413                }
414
415                /* FIXME: How should the below be properly calculated? ******************/
416                baseIPInfo->iae_reasmsize = 0x0;
417                baseIPInfo->iae_context   = 0x0;
418                baseIPInfo->iae_pad       = 0x0;
419                /************************************************************************/
420              
421                /* Calculate size of out buffer */
422                *pcbResponseInfoLen = sizeof(IPAddrEntry);
423                closesocket(sock);
424                break;
425             }
426
427             case 0x101:
428                 FIXME ("Command ID Unknown but used by winipcfg.exe\n");
429                 break;
430
431
432             default: 
433             {
434                FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx, toi_type=0x%lx\n",
435                        pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance, 
436                        pcommand->toi_class, pcommand->toi_type);
437               
438                return (WSAEOPNOTSUPP); 
439             }
440          }
441       
442          break;
443       }
444     
445       case WSCNTL_TCPIP_ICMP_ECHO:
446       {
447          unsigned int addr = *(unsigned int*)pRequestInfo;
448          #if 0
449             int timeout= *(unsigned int*)(inbuf+4);
450             short x1 = *(unsigned short*)(inbuf+8);
451             short sendbufsize = *(unsigned short*)(inbuf+10);
452             char x2 = *(unsigned char*)(inbuf+12);
453             char ttl = *(unsigned char*)(inbuf+13);
454             char service = *(unsigned char*)(inbuf+14);
455             char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
456          #endif      
457       
458          FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
459          break;
460       }
461
462       default:
463       {
464          FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
465                protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
466       
467          return (WSAEOPNOTSUPP); 
468       }
469    }
470    
471    
472    return (WSCTL_SUCCESS); 
473 }
474
475
476
477 /* 
478   Helper function for WsControl - Get count of the number of interfaces
479   by parsing /proc filesystem.
480 */
481 int WSCNTL_GetInterfaceCount(void)
482 {
483    FILE *procfs;
484    char buf[512];  /* Size doesn't matter, something big */
485    int  intcnt=0;
486  
487  
488    /* Open /proc filesystem file for network devices */ 
489    procfs = fopen(PROCFS_NETDEV_FILE, "r");
490    if (!procfs) 
491    {
492       /* If we can't open the file, return an error */
493       return (-1);
494    }
495    
496    /* Omit first two lines, they are only headers */
497    fgets(buf, sizeof buf, procfs);      
498    fgets(buf, sizeof buf, procfs);
499
500    while (fgets(buf, sizeof buf, procfs)) 
501    {
502       /* Each line in the file represents a network interface */
503       intcnt++;
504    }
505
506    fclose(procfs);
507    return(intcnt);
508 }
509
510
511 /*
512    Helper function for WsControl - Get name of device from interface number
513    by parsing /proc filesystem.
514 */
515 int WSCNTL_GetInterfaceName(int intNumber, char *intName)
516 {
517    FILE *procfs;
518    char buf[512]; /* Size doesn't matter, something big */
519    int  i;
520
521    /* Open /proc filesystem file for network devices */ 
522    procfs = fopen(PROCFS_NETDEV_FILE, "r");
523    if (!procfs) 
524    {
525       /* If we can't open the file, return an error */
526       return (-1);
527    }
528    
529    /* Omit first two lines, they are only headers */
530    fgets(buf, sizeof(buf), procfs);     
531    fgets(buf, sizeof(buf), procfs);
532
533    for (i=0; i<intNumber; i++)
534    {
535       /* Skip the lines that don't interest us. */
536       fgets(buf, sizeof(buf), procfs);
537    }
538    fgets(buf, sizeof(buf), procfs); /* This is the line we want */
539
540    
541    /* Parse out the line, grabbing only the name of the device
542       to the intName variable 
543       
544       The Line comes in like this: (we only care about the device name)
545       lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
546    */
547    i=0; 
548    while (isspace(buf[i])) /* Skip initial space(s) */
549    {
550       i++;
551    }
552
553    while (buf[i]) 
554    {
555       if (isspace(buf[i]))
556       {
557          break;
558       }
559       
560       if (buf[i] == ':')  /* FIXME: Not sure if this block (alias detection) works properly */
561       {
562          /* This interface could be an alias... */
563          int hold = i;
564          char *dotname = intName;
565          *intName++ = buf[i++];
566          
567          while (isdigit(buf[i]))
568          {
569             *intName++ = buf[i++];
570          }
571          
572          if (buf[i] != ':') 
573          {
574             /* ... It wasn't, so back up */
575             i = hold;
576             intName = dotname;
577          }
578  
579          if (buf[i] == '\0')
580          {
581             fclose(procfs);
582             return(FALSE);
583          }
584          
585          i++;
586          break;
587       }
588       
589       *intName++ = buf[i++];
590    }
591    *intName++ = '\0';
592
593    fclose(procfs);
594    return(TRUE);
595 }
596
597
598 /*
599    Helper function for WsControl - This function returns the bytes (octets) transmitted
600    and received for the supplied interface number from the /proc fs. 
601 */
602 int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
603 {
604    FILE *procfs;
605    char buf[512], result[512]; /* Size doesn't matter, something big */
606    int  i, bufPos, resultPos;
607
608    /* Open /proc filesystem file for network devices */ 
609    procfs = fopen(PROCFS_NETDEV_FILE, "r");
610    if (!procfs) 
611    {
612       /* If we can't open the file, return an error */
613       return (-1);
614    }
615    
616    /* Omit first two lines, they are only headers */
617    fgets(buf, sizeof(buf), procfs);     
618    fgets(buf, sizeof(buf), procfs);
619
620    for (i=0; i<intNumber; i++)
621    {
622       /* Skip the lines that don't interest us. */
623       fgets(buf, sizeof(buf), procfs);
624    }
625    fgets(buf, sizeof(buf), procfs); /* This is the line we want */
626
627
628
629    /* Parse out the line, grabbing the number of bytes transmitted
630       and received on the interface.
631       
632       The Line comes in like this: (we care about columns 2 and 10)
633       lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
634    */
635
636    /* Start at character 0 in the buffer */
637    bufPos=0;
638    
639    /* Skip initial space(s) */ 
640    while (isspace(buf[bufPos])) 
641       bufPos++;
642
643
644    /* Skip the name and its trailing spaces (if any) */
645    while (buf[bufPos]) 
646    {
647       if (isspace(buf[bufPos]))
648          break;
649  
650       if (buf[bufPos] == ':') /* Could be an alias */
651       {
652          int hold = bufPos;
653
654          while(isdigit (buf[bufPos]))
655             bufPos++;
656          if (buf[bufPos] != ':')
657             bufPos = hold;
658          if (buf[bufPos] == '\0')
659          {
660             fclose(procfs);
661             return(FALSE);
662          }
663          
664          bufPos++;
665          break;
666       }
667
668       bufPos++;
669    }
670    while (isspace(buf[bufPos]))
671       bufPos++;
672
673
674    /* This column (#2) is the number of bytes received. */
675    resultPos = 0;
676    while (!isspace(buf[bufPos]))
677    {
678       result[resultPos] = buf[bufPos];
679       result[resultPos+1]='\0';
680       resultPos++; bufPos++;
681    }
682    *recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
683
684    
685    /* Skip columns #3 to #9 (Don't need them) */
686    for  (i=0; i<7; i++)
687    {
688       while (isspace(buf[bufPos]))
689          bufPos++;
690       while (!isspace(buf[bufPos])) 
691          bufPos++;
692    }
693
694
695    /* This column (#10) is the number of bytes transmitted */
696    while (isspace(buf[bufPos]))
697        bufPos++;
698
699    resultPos = 0;
700    while (!isspace(buf[bufPos]))
701    {
702       result[resultPos] = buf[bufPos];
703       result[resultPos+1]='\0';
704       resultPos++; bufPos++;
705    }
706    *transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
707
708
709    fclose(procfs);
710    return(TRUE);
711 }
712
713
714 /***********************************************************************
715  *              WSARecvEx()                     (WSOCK32.1107)
716  *
717  * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
718  * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
719  * into the flags parameter when a partial packet is read. This only applies to
720  * sockets using the datagram protocol. This method does not seem to be implemented
721  * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
722  * flag when a fragmented packet arrives.
723  */
724 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags)
725 {
726     FIXME("(WSARecvEx) partial packet return value not set \n");
727     return recv(s, buf, len, *flags);
728 }
729
730
731 /***********************************************************************
732  *       WS_s_perror         (WSOCK32.1108)
733  */
734 void WINAPI WS_s_perror(LPCSTR message)
735 {
736     FIXME("(%s): stub\n",message);
737     return;
738 }