Chris De Herrera's Windows CE Website

About
Discuss.Pocket PC FAQ Forum
Add Pocket PC FAQ to your Favorites
RSS    RSS Feeds
Wiki    Lost?
Subscribe    Print

Developer

Miscellaneous
Table of Contents
Mobile Format

[an error occurred while processing this directive]


 
Pocket PC Magazine Best Site

Website Awards
Website Updates

By Chris De Herrera 
Copyright 1998-2007
 All Rights Reserved
A member of the Talksites Family of Websites

Windows and Windows CE are trademarks of Microsoft
Corporation
and are used
under license from owner.
CEWindows.NET is not
associated with Microsoft 
Corporation.

All Trademarks are owned
by their respective companies.

Internet
By Terence "Dr. CE" Goggin
Copyright 2000, 2001 Terence Goggin
 Version 1.00  Revised 4/20/01

[an error occurred while processing this directive]

Topics

1. What kind of Internet-related support does CE offer to developers?
2. What about MFC's socket classes? Can I use them?
3. How can I do a PING in CE?
4. What version of Winsock is supported on CE?
5. How can I launch pmail.exe with parameters?



1. What kind of Internet-related support does CE offer to developers?
CE supports Winsock 1.1, which is (basically) a cut above
Berkeley sockets. CE does not support Winsock 2.0, and as
far as I know, there aren't any plans to add it anytime soon.

CE also offers a reasonably complete subset of the WinInet API.



2. What about MFC's socket classes? Can I use them?
Yes, but they're riddled with problems. I have heard of several
different projects where they just finally gave up and went
direct to the Winsock API or created their own classes.



3. How can I do a PING in CE?
Here's some code that appeared on the newsgroups recently.

/*
* P I N G . C
*
* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
* measure round-trip-delays and packet loss across network paths.
*
* Author -
* Mike Muuss
* U. S. Army Ballistic Research Laboratory
* December, 1983
* Modified at Uc Berkeley
* Record Route and verbose headers - Phil Dykstra, BRL, March 1988.
* Multicast options (ttl, if, loop) - Steve Deering, Stanford, August 1988.
* ttl, duplicate detection - Cliff Frost, UCB, April 1989
* Pad pattern - Cliff Frost (from Tom Ferrin, UCSF), April 1989
* Wait for dribbles, option decoding, pkt compare - vjs@sgi.com, May 1989
*
* Status -
* Public Domain.   Distribution Unlimited.
*
* Bugs -
* More statistics could always be gathered.
* This program has to run SUID to ROOT to access the ICMP socket.
*/


#include < stdio.h>
#include < errno.h>
#include < sys/time.h>
#include < sys/signal.h>

#include < sys/param.h>
#include < sys/socket.h>
#include < sys/file.h>

#include < netinet/in_systm.h>
#include < netinet/in.h>
#include < netinet/ip.h>
#include < netinet/ip_icmp.h>
#include < netinet/ip_var.h>
#include < ctype.h>
#include < netdb.h>

#define MAXWAIT 10 /* max time to wait for response, sec. */
#define MAXPACKET (65536-60-8) /* max packet size */
#define VERBOSE 1 /* verbose flag */
#define QUIET 2 /* quiet flag */
#define FLOOD 4 /* floodping flag */
#define RROUTE 8 /* record route flag */
#define PING_FILLED         16           /* is buffer filled? */
#define NUMERIC 32 /* don't do gethostbyaddr() calls */
#define INTERVAL 64 /* did user specify interval? */
#define NROUTES 9 /* number of record route slots */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif

#define MULTICAST_NOLOOP 1 /* multicast options */
#define MULTICAST_TTL 2
#define MULTICAST_IF 4

/* MAX_DUP_CHK is the number of bits in received table, ie the */
/*           maximum number of received sequence numbers we can keep track of. */
/*           Change 128 to 8192 for complete accuracy... */

#define MAX_DUP_CHK         8 * 128
int         mx_dup_ck = MAX_DUP_CHK;
char       rcvd_tbl[ MAX_DUP_CHK / 8 ];
int         nrepeats = 0;

#define A(bit)                   rcvd_tbl[ (bit> > 3) ]       /* identify byte in array */
#define B(bit)                   ( 1 < <   (bit & 0x07) )     /* identify bit in byte */
#define SET(bit)               A(bit) |= B(bit)
#define CLR(bit)               A(bit) &= (~B(bit))
#define TST(bit)               (A(bit) & B(bit))


char *malloc();

u_char *packet;
int packlen;
int i, pingflags = 0, options, moptions;
extern int errno;

int s; /* Socket file descriptor */
struct hostent *hp; /* Pointer to host info */
struct timezone tz; /* leftover */

struct sockaddr whereto; /* Who to ping */
int datalen = 64-8; /* How much data */

#if defined(MULTICAST)
char usage[] = "Usage: \
ping [-dfnqrvRL] [-c count] [-s size] [-l preload] [-p pattern] [-i
interval]\n\
        [-T ttl] [-I addr] [-h] host\n";

#else
char usage[] = "Usage: \
ping [-dfnqrvR] [-c count] [-s size] [-l preload] [-p pattern] [-i
interval]\n\
        [-h] host\n";

#endif /* MULTICAST */

char *hostname;
char hnamebuf[MAXHOSTNAMELEN];

static u_char outpack[MAXPACKET];

int npackets=0;
int preload = 0; /* number of packets to "preload" */
int ntransmitted = 0; /* sequence # for outbound packets = #sent */
int ident;
unsigned interval=1; /* interval between packets */

int nreceived = 0; /* # of packets we got back */
int timing = 0;
int tmin = 999999999;
int tmax = 0;
int tsum = 0; /* sum of all times, for doing average */
int finish(), catcher();
int bufspace = 48*1024;
int prefinish();
char *pr_addr();
char rspace[3+4*NROUTES+1]; /* record route space */

/*
* M A I N
*/

main(argc, argv)
char *argv[];
{
struct sockaddr_in from;
/* char **av = argv; */
struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
int c, k, on = 1, hostind = 0;
struct protoent *proto;
static u_char *datap = &outpack[8+sizeof(struct timeval)];
unsigned char ttl, loop;
struct in_addr ifaddr;
extern int optind;
extern char *optarg;

while ((c = getopt(argc, argv, "c:dfh:i:l:np:qrs:vRLT:I:")) != EOF)
switch(c) {
case 'c':
npackets = atoi(optarg);
break;
case 'd':
options |= SO_DEBUG;
break;
case 'f':
pingflags |= FLOOD;
break;
case 'h':
hostind = optind-1;
break;
                                              case 'i':             /* wait between sending packets */
interval = atoi(optarg);
if (interval == 0)
interval = 1;
pingflags |= INTERVAL;
                                                              break;
case 'l':
preload = atoi(optarg);
break;
case 'n':
pingflags |= NUMERIC;
break;
                                              case 'p':             /* fill buffer with user pattern */
                                                              pingflags |= PING_FILLED;
fill((char *)datap, optarg);
                                                              break;
case 'q':
pingflags |= QUIET;
break;
case 'r':
options |= SO_DONTROUTE;
break;
                                              case 's':             /* size of packet to send */
datalen = atoi(optarg);
                                                              break;
case 'v':
pingflags |= VERBOSE;
break;
case 'R':
pingflags |= RROUTE;
break;
#ifdef MULTICAST
case 'L':
moptions |= MULTICAST_NOLOOP;
loop = 0;
break;
case 'T':
moptions |= MULTICAST_TTL;
ttl = atoi(optarg);
if (ttl >   255 || ttl < = 0) {
printf("%s: ttl %s out of range\n",
      argv[0], optarg);
exit(1);
}
break;
case 'I':
moptions |= MULTICAST_IF;
ifaddr.s_addr = inet_addr(optarg);
if (ifaddr.s_addr == (unsigned)-1) {
hp = gethostbyname(optarg);
if (hp) {
bcopy(hp-> h_addr,
          (caddr_t)&ifaddr,
          hp-> h_length);
} else {
printf("%s: bad address '%s'\n",
      argv[0],
      optarg);
exit(1);
}
}
break;
#endif /* MULTICAST */
default:
printf(usage);
exit(1);
}

if (hostind == 0) {
if (optind != argc-1) {
fprintf(stderr, usage);
exit(1);
} else hostind = optind;
}

bzero((char *)&whereto, sizeof(struct sockaddr) );
to-> sin_family = AF_INET;
to-> sin_addr.s_addr = inet_addr(argv[hostind]);
if(to-> sin_addr.s_addr != (unsigned)-1) {
strcpy(hnamebuf, argv[hostind]);
hostname = hnamebuf;
} else {
hp = gethostbyname(argv[hostind]);
if (hp) {
to-> sin_family = hp-> h_addrtype;
bcopy(hp-> h_addr, (caddr_t)&to-> sin_addr, hp-> h_length);
strncpy( hnamebuf, hp-> h_name, sizeof(hnamebuf)-1 );
hostname = hnamebuf;
} else {
printf("%s: unknown host %s\n", argv[0], argv[hostind]);
exit(1);
}
}

if ( (pingflags & FLOOD) && (pingflags & INTERVAL) ) {
fprintf(stderr, "ping: -f and -i incompatible options\n");
exit(1);
}

if (datalen >   MAXPACKET) {
fprintf(stderr, "ping: packet size too large\n");
exit(1);
}
if (datalen > = sizeof(struct timeval)) /* can we time 'em? */
timing = 1;
packlen = datalen + 60 + 76; /* MAXIP + MAXICMP */
if( (packet = (u_char *)malloc((unsigned)packlen)) == NULL ) {
fprintf( stderr, "ping: malloc failed\n" );
exit(1);
}

if (!(pingflags & PING_FILLED)) {
                              for( k=8; k< datalen; k++) *datap++ = k;
              }

ident = getpid() & 0xFFFF;

if ((proto = getprotobyname("icmp")) == NULL) {
fprintf(stderr, "icmp: unknown protocol\n");
exit(10);
}
if ((s = socket(AF_INET, SOCK_RAW, proto-> p_proto)) <   0) {
perror("ping: socket");
exit(5);
}
if (options & SO_DEBUG) {
(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &on, sizeof(on));
}
if (options & SO_DONTROUTE) {
(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on));
}
/* Record Route option */
if( pingflags & RROUTE ) {
#ifdef IP_OPTIONS
rspace[IPOPT_OPTVAL] = IPOPT_RR;
rspace[IPOPT_OLEN] = sizeof(rspace)-1;
rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
if( setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) <   0 ) {
perror( "Record route" );
exit( 42 );
}
#else
fprintf( stderr, "ping: record route not available on this machine.\n" );
exit( 42 );
#endif IP_OPTIONS
}

#ifdef MULTICAST
if (moptions & MULTICAST_NOLOOP) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
&loop, 1) == -1) {
perror ("can't disable multicast loopback");
exit(92);
}
}
if (moptions & MULTICAST_TTL) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, 1) == -1) {
perror ("can't set multicast time-to-live");
exit(93);
}
}
if (moptions & MULTICAST_IF) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
&ifaddr, sizeof(ifaddr)) == -1) {
perror ("can't set multicast source interface");
exit(94);
}
}
#endif MULTICAST

if(to-> sin_family == AF_INET) {
printf("PING %s (%s): %d data bytes\n", hostname,
  inet_ntoa(*(struct in_addr *)&to-> sin_addr.s_addr), datalen);
} else {
printf("PING %s: %d data bytes\n", hostname, datalen );
}
/* When pinging the broadcast address, you can get a lot
* of answers.   Doing something so evil is useful if you
* are trying to stress the ethernet, or just want to
* fill the arp cache to get some stuff for /etc/ethers.
*/

(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace,
sizeof(bufspace));

signal( SIGINT, prefinish );
signal(SIGALRM, catcher);

/* fire off them quickies */
for(i=0; i <   preload; i++)
pinger();

if(!(pingflags & FLOOD))
catcher(); /* start things going */

for (;;) {
int fromlen = sizeof (from);
int cc;
struct timeval timeout;
int fdmask = 1 < <   s;

timeout.tv_sec = 0;
timeout.tv_usec = 10000;

if(pingflags & FLOOD) {
pinger();
if( select(32, (fd_set *)&fdmask, (fd_set *)0, (fd_set *)0, &timeout) ==
0)
continue;
}
if ( (cc=recvfrom(s, (char *)packet, packlen, 0, (struct sockaddr *)&from,
&fromlen)) <   0) {
if( errno == EINTR )
continue;
perror("ping: recvfrom");
continue;
}
pr_pack( (char *)packet, cc, &from );
if (npackets && nreceived > = npackets)
finish();
}
/*NOTREACHED*/
}

/*
* C A T C H E R
*
* This routine causes another PING to be transmitted, and then
* schedules another SIGALRM for 1 second from now.
*
* Bug -
* Our sense of time will slowly skew (ie, packets will not be launched
* exactly at 1-second intervals).   This does not affect the quality
* of the delay and loss statistics.
*/

catcher()
{
int waittime;

pinger();
signal(SIGALRM, catcher);
if (npackets == 0 || ntransmitted <   npackets)
alarm(interval);
else {
if (nreceived) {
waittime = 2 * tmax / 1000;
if (waittime == 0)
waittime = 1;
} else
waittime = MAXWAIT;
signal(SIGALRM, finish);
alarm((unsigned)waittime);
}
}

/*
* P I N G E R
*
* Compose and transmit an ICMP ECHO REQUEST packet.   The IP packet
* will be added on by the kernel.   The ID field is our UNIX process ID,
* and the sequence number is an ascending integer.   The first 8 bytes
* of the data portion are used to hold a UNIX "timeval" struct in VAX
* byte-order, to compute the round-trip time.
*/

pinger()
{
register struct icmp *icp = (struct icmp *) outpack;
int i, cc;
register struct timeval *tp = (struct timeval *) &outpack[8];

icp-> icmp_type = ICMP_ECHO;
icp-> icmp_code = 0;
icp-> icmp_cksum = 0;
icp-> icmp_seq = htons((unsigned short)(ntransmitted++));
icp-> icmp_id = ident; /* ID */

              CLR( ntohs(icp-> icmp_seq) % mx_dup_ck );

cc = datalen+8; /* skips ICMP portion */

if (timing)
gettimeofday( tp, &tz );

/* Compute ICMP checksum here */
icp-> icmp_cksum = in_cksum( (u_short *)icp, cc );

/* cc = sendto(s, msg, len, flags, to, tolen) */
i = sendto( s, (char *)outpack, cc, 0, &whereto, sizeof(struct sockaddr) );

if( i <   0 || i != cc )   {
if( i< 0 )   perror("sendto");
printf("ping: wrote %s %d chars, ret=%d\n",
hostname, cc, i );
fflush(stdout);
}
if( pingflags & FLOOD ) {
putchar('.');
fflush(stdout);
}
}

/*
* P R _ P A C K
*
* Print out the packet, if it came from us.   This logic is necessary
* because ALL readers of the ICMP socket get a copy of ALL ICMP packets
* which arrive ('tis only fair).   This permits multiple copies of this
* program to be run without having intermingled output (or statistics!).
*/

pr_pack( buf, cc, from )
char *buf;
int cc;
struct sockaddr_in *from;
{
struct ip *ip;
register struct icmp *icp;
register int i, j;
register u_char *cp,*dp;
static int old_rrlen;
static char old_rr[MAX_IPOPTLEN];
struct timeval tv;
struct timeval *tp;
int hlen, triptime, dupflag;

gettimeofday( &tv, &tz );

/* Check the IP header */
ip = (struct ip *) buf;
hlen = ip-> ip_hl < <   2;
if( cc <   hlen + ICMP_MINLEN ) {
if( pingflags & VERBOSE )
printf("packet too short (%d bytes) from %s\n", cc,
inet_ntoa(*(struct in_addr *)&from-> sin_addr.s_addr));
fflush(stdout);
return;
}

/* Now the ICMP part */
cc -= hlen;
icp = (struct icmp *)(buf + hlen);
if( icp-> icmp_type == ICMP_ECHOREPLY ) {
if( icp-> icmp_id != ident )
return; /* 'Twas not our ECHO */

nreceived++;
if (timing) {
#ifndef icmp_data
tp = (struct timeval *)&icp-> icmp_ip;
#else
tp = (struct timeval *)&icp-> icmp_data[0];
#endif
tvsub( &tv, tp );
triptime = tv.tv_sec*1000+(tv.tv_usec/1000);
tsum += triptime;
if( triptime <   tmin )
tmin = triptime;
if( triptime >   tmax )
tmax = triptime;
}

                              if ( TST(ntohs(icp-> icmp_seq)%mx_dup_ck) ) {
                                            nrepeats++, nreceived--;
dupflag=1;
                              } else {
SET(ntohs(icp-> icmp_seq)%mx_dup_ck);
dupflag=0;
}

if( pingflags & QUIET )
return;

if( pingflags & FLOOD ) {
putchar('\b');
fflush(stdout);
} else {
printf("%d bytes from %s: icmp_seq=%d", cc,
  inet_ntoa(*(struct in_addr *)&from-> sin_addr.s_addr),
  ntohs(icp-> icmp_seq) );
if ( dupflag ) printf(" DUP!");
printf(" ttl=%d", ip-> ip_ttl);
if (timing)
printf(" time=%d ms", triptime );
/* check the data */
cp = (u_char*)&icp-> icmp_data[8];
dp = &outpack[8+sizeof(struct timeval)];
for (i=8; i< datalen; i++, cp++, dp++) {
if (*cp != *dp) {
      printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
i, *dp, *cp);
cp = (u_char*)&icp-> icmp_data[0];
for (i=8; i< datalen; i++, cp++) {
if ((i%32) == 8)
printf("\n\t");
printf("%x ", *cp);
}
break;
}
}

}
} else {
/* We've got something other than an ECHOREPLY */
if( !(pingflags & VERBOSE) )
return;

printf("%d bytes from %s: ",
  cc, pr_addr(from-> sin_addr.s_addr) );
pr_icmph( icp );
}

/* Display any IP options */
cp = (u_char *)buf + sizeof(struct ip);
while (hlen >   sizeof(struct ip) && (hlen > = 0)) { /* !ANSI C will   */
register unsigned long l; /* force hlen to */
switch (*cp) { /* unsigned!         */
case IPOPT_EOL:
hlen = 0;
break;
case IPOPT_LSRR:
printf("\nLSRR: ");
hlen -= 2;
j = *++cp;
++cp;
if (j >   IPOPT_MINOFF) for (;;) {
l = *++cp;
l = (l< < 8) + *++cp;
l = (l< < 8) + *++cp;
l = (l< < 8) + *++cp;
if (l == 0)
printf("\t0.0.0.0");
else
printf("\t%s", pr_addr(ntohl(l)));
hlen -= 4;
j -= 4;
if (j < = IPOPT_MINOFF)
break;
putchar('\n');
}
break;
case IPOPT_RR:
j = *++cp; /* get length */
i = *++cp; /* and pointer */
hlen -= 2;
if (i >   j) i = j;
i -= IPOPT_MINOFF;
if (i < = 0)
continue;
if (i == old_rrlen
      && cp == (u_char *)buf + sizeof(struct ip) + 2
      && !bcmp((char *)cp, old_rr, i)
      && !(pingflags & FLOOD)) {
printf("\t(same route)");
i = ((i+3)/4)*4;
hlen -= i;
cp += i;
break;
}
old_rrlen = i;
bcopy((char *)cp, old_rr, i);
printf("\nRR: ");
for (;;) {
l = *++cp;
l = (l< < 8) + *++cp;
l = (l< < 8) + *++cp;
l = (l< < 8) + *++cp;
if (l == 0)
printf("\t0.0.0.0");
else
printf("\t%s", pr_addr(ntohl(l)));
hlen -= 4;
i -= 4;
if (i < = 0)
break;
putchar('\n');
}
break;
case IPOPT_NOP:
printf("\nNOP");
break;
default:
printf("\nunknown option %x", *cp);
break;
}
hlen--;
cp++;
}
if (!(pingflags & FLOOD))
putchar('\n');
fflush(stdout);
}

/*
* I N _ C K S U M
*
* Checksum routine for Internet Protocol family headers (C Version)
*
*/

in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;

/*
*   Our algorithm is simple, using a 32 bit accumulator (sum),
*   we add sequential 16 bit words to it, and at the end, fold
*   back all the carry bits from the top 16 bits into the lower
*   16 bits.
*/

while( nleft >   1 )   {
sum += *w++;
nleft -= 2;
}

/* mop up an odd byte, if necessary */
if( nleft == 1 ) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}

/*
* add back carry outs from top 16 bits to low 16 bits
*/

sum = (sum > >   16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum > >   16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}

/*
* T V S U B
*
* Subtract 2 timeval structs:   out = out - in.
*
* Out is assumed to be > = in.
*/

tvsub( out, in )
register struct timeval *out, *in;
{
if( (out-> tv_usec -= in-> tv_usec) <   0 )     {
out-> tv_sec--;
out-> tv_usec += 1000000;
}
out-> tv_sec -= in-> tv_sec;
}

/* On the first SIGINT, allow any outstanding packets to dribble in */
prefinish()
{
if (nreceived > = ntransmitted /* quit now if caught up */
      || nreceived == 0) /* or if remote is dead */
finish();
signal(SIGINT, finish); /* do this only the 1st time */
npackets = ntransmitted+1; /* let the normal limit work */
}
/*
* F I N I S H
*
* Print out statistics, and give up.
* Heavily buffered STDIO is used here, so that all the statistics
* will be written with 1 sys-write call.   This is nice when more
* than one copy of the program is running on a terminal;   it prevents
* the statistics output from becomming intermingled.
*/

finish()
{
putchar('\n');
fflush(stdout);
printf("\n----%s PING Statistics----\n", hostname );
printf("%d packets transmitted, ", ntransmitted );
printf("%d packets received, ", nreceived );
              if (nrepeats) printf("+%d duplicates, ", nrepeats );
if (ntransmitted)
if( nreceived >   ntransmitted)
printf("-- somebody's printing up packets!");
else
printf("%d%% packet loss",
  (int) (((ntransmitted-nreceived)*100) /
  ntransmitted));
printf("\n");
if (nreceived && timing)
      printf("round-trip (ms)   min/avg/max = %d/%d/%d\n",
tmin,
tsum / (nreceived + nrepeats),
tmax );
fflush(stdout);
exit(0);
}


/*
*   Print a descriptive string about an ICMP header.
*/

pr_icmph( icp )
struct icmp *icp;
{
switch( icp-> icmp_type ) {
case ICMP_ECHOREPLY:
printf("Echo Reply\n");
/* XXX ID + Seq + Data */
break;
case ICMP_UNREACH:
switch( icp-> icmp_code ) {
case ICMP_UNREACH_NET:
printf("Destination Net Unreachable\n");
break;
case ICMP_UNREACH_HOST:
printf("Destination Host Unreachable\n");
break;
case ICMP_UNREACH_PROTOCOL:
printf("Destination Protocol Unreachable\n");
break;
case ICMP_UNREACH_PORT:
printf("Destination Port Unreachable\n");
break;
case ICMP_UNREACH_NEEDFRAG:
printf("frag needed and DF set\n");
break;
case ICMP_UNREACH_SRCFAIL:
printf("Source Route Failed\n");
break;
default:
printf("Dest Unreachable, Bad Code: %d\n", icp-> icmp_code );
break;
}
/* Print returned IP header information */
#ifndef icmp_data
pr_retip( &icp-> icmp_ip );
#else
pr_retip( (struct ip *)icp-> icmp_data );
#endif
break;
case ICMP_SOURCEQUENCH:
printf("Source Quench\n");
#ifndef icmp_data
pr_retip( &icp-> icmp_ip );
#else
pr_retip( (struct ip *)icp-> icmp_data );
#endif
break;
case ICMP_REDIRECT:
switch( icp-> icmp_code ) {
case ICMP_REDIRECT_NET:
printf("Redirect Network");
break;
case ICMP_REDIRECT_HOST:
printf("Redirect Host");
break;
case ICMP_REDIRECT_TOSNET:
printf("Redirect Type of Service and Network");
break;
case ICMP_REDIRECT_TOSHOST:
printf("Redirect Type of Service and Host");
break;
default:
printf("Redirect, Bad Code: %d", icp-> icmp_code );
break;
}
printf(" (New addr: 0x%08x)\n", icp-> icmp_hun.ih_gwaddr );
#ifndef icmp_data
pr_retip( &icp-> icmp_ip );
#else
pr_retip( (struct ip *)icp-> icmp_data );
#endif
break;
case ICMP_ECHO:
printf("Echo Request\n");
/* XXX ID + Seq + Data */
break;
case ICMP_TIMXCEED:
switch( icp-> icmp_code ) {
case ICMP_TIMXCEED_INTRANS:
printf("Time to live exceeded\n");
break;
case ICMP_TIMXCEED_REASS:
printf("Frag reassembly time exceeded\n");
break;
default:
printf("Time exceeded, Bad Code: %d\n", icp-> icmp_code );
break;
}
#ifndef icmp_data
pr_retip( &icp-> icmp_ip );
#else
pr_retip( (struct ip *)icp-> icmp_data );
#endif
break;
case ICMP_PARAMPROB:
printf("Parameter problem: pointer = 0x%02x\n",
icp-> icmp_hun.ih_pptr );
#ifndef icmp_data
pr_retip( &icp-> icmp_ip );
#else
pr_retip( (struct ip *)icp-> icmp_data );
#endif
break;
case ICMP_TSTAMP:
printf("Timestamp\n");
/* XXX ID + Seq + 3 timestamps */
break;
case ICMP_TSTAMPREPLY:
printf("Timestamp Reply\n");
/* XXX ID + Seq + 3 timestamps */
break;
case ICMP_IREQ:
printf("Information Request\n");
/* XXX ID + Seq */
break;
case ICMP_IREQREPLY:
printf("Information Reply\n");
/* XXX ID + Seq */
break;
#ifdef ICMP_MASKREQ
case ICMP_MASKREQ:
printf("Address Mask Request\n");
break;
#endif
#ifdef ICMP_MASKREPLY
case ICMP_MASKREPLY:
printf("Address Mask Reply\n");
break;
#endif
default:
printf("Bad ICMP type: %d\n", icp-> icmp_type);
}
}

/*
*   Print an IP header with options.
*/

pr_iph( ip )
struct ip *ip;
{
int hlen;
unsigned char *cp;

hlen = ip-> ip_hl < <   2;
cp = (unsigned char *)ip + 20; /* point to options */

printf("Vr HL TOS   Len     ID Flg   off TTL Pro   cks           Src           Dst
Data\n")
;
printf(" %1x   %1x   %02x %04x %04x",
ip-> ip_v, ip-> ip_hl, ip-> ip_tos, ip-> ip_len, ip-> ip_id );
printf("     %1x %04x", ((ip-> ip_off)&0xe000)> > 13, (ip-> ip_off)&0x1fff );
printf("   %02x   %02x %04x", ip-> ip_ttl, ip-> ip_p, ip-> ip_sum );
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip-> ip_src.s_addr));
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip-> ip_dst.s_addr));
/* dump and option bytes */
while( hlen-- >   20 ) {
printf( "%02x", *cp++ );
}
printf("\n");
}

/*
*   Return an ascii host address
*   as a dotted quad and optionally with a hostname
*/

char *
pr_addr( l )
unsigned long l;
{
struct hostent *hp;
static char buf[80];

if( (pingflags & NUMERIC) || (hp = gethostbyaddr((char *)&l, 4, AF_INET))
== NULL )
sprintf( buf, "%s", inet_ntoa(*(struct in_addr *)&l) );
else
sprintf( buf, "%s (%s)", hp-> h_name, inet_ntoa(*(struct in_addr *)&l) );

return( buf );
}

/*
*   Dump some info on a returned (via ICMP) IP packet.
*/

pr_retip( ip )
struct ip *ip;
{
int hlen;
unsigned char *cp;

pr_iph( ip );
hlen = ip-> ip_hl < <   2;
cp = (unsigned char *)ip + hlen;

if( ip-> ip_p == 6 ) {
printf( "TCP: from port %d, to port %d (decimal)\n",
(*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)) );
} else if( ip-> ip_p == 17 ) {
printf( "UDP: from port %d, to port %d (decimal)\n",
(*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)) );
}
}

fill(bp, patp)
char *bp, *patp;
{
              register int ii,jj,kk;
              char *cp;
              int pat[16];

              for (cp=patp; *cp; cp++)
                              if (!isxdigit(*cp)) {
                                              printf("\"-p %s\" ???: ", patp);
                                              printf("patterns must be specified as hex
digits\n")
;
                                              exit(1);
                              }

              ii = sscanf(patp,
                              "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
                              &pat[0], &pat[1], &pat[2], &pat[3],
                              &pat[4], &pat[5], &pat[6], &pat[7],
                              &pat[8], &pat[9], &pat[10], &pat[11],
                              &pat[12], &pat[13], &pat[14], &pat[15]);

              if (ii >   0)
                              for (kk=0; kk< =MAXPACKET-(8+ii); kk+=ii)
                              for (jj=0; jj< ii; jj++)
                                              bp[jj+kk] = pat[jj];

              if (!(pingflags & QUIET)) {
                              printf("PATTERN: 0x");
                              for (jj=0; jj< ii; jj++)
                                              printf("%02x", bp[jj]&0xFF);
                              printf("\n");
              }

}






4. What version of Winsock is supported on CE?
Winsock 1.1.

This does not include async processing, which arrived with Winsock 2.0.
Currently, there are no plans to upgrade CE's Winsock to 2.0 anytime in the near future.

For more information: http://www.sockets.com/ws_wince.htm

5. How can I launch pmail.exe with parameters?
Well, yeah, like I said, that was the easiest method of creating a new email.. Or at least the easiest to think of...
However, I did just figure it out now (and trust me, I search for quite a while a month or so ago when I had to do the same thing you're trying to do)..

But, like I said, I figured out the params for pmail.exe.. The ones that I've successfully used are:

-to "emailaddresses"
-cc "ccaddresses"
-bcc "bccaddresses"
-subject "subject"
-attach "file_to_attach"


Note that you MUST keep the quotation marks around the parameters for each switch.. I'm assuming that this allows the params to contain spaces (but I've not tested this yet). But you MUST have these, or otherwise it won't recognize it correctly.

The only parameter I can't figure out is whether one exists for the body of an email. I've tried "message", "body", "email", and "text" so far in trying to find that param, and none of those work...

If you're curious how I figured it out, I wrote a small app that just popped up a messagebox with the command line params it was passed. Then I replaced the real pmail.exe with this app, and ran my mailto link through IE.. Of course the app came back with the -to option with my email, and the rest was self explanatory (except for the one I haven't figured out yet)....


[This message has been edited by motbe (edited February 21, 2001).]



Credits: "motbe" on PocketProjects.com

[an error occurred while processing this directive]

Terence Goggin's DoctorCE.com site - Custom Windows CE development/consulting services.

Return to Chris De Herrera's Windows CE Website


Questions? Comments? Suggestions? Email Terence "Dr. CE" Goggin.