/************************************************************************* Windows Sockets PING Client Application Written by John A. Junod, 267 Hillwood St., Martinez, GA, 30907 93.10.01 C$:72321,366 Released into the public domain with no restrictions other than to give me some of the credit if you use this code in other applications. Some code concepts based on code published in UNIX Network Programming by W. Richard Stevens or on BSD networking source code. Note that MOST Windows Sockets DLL's do not support RAW_SOCKETS. This does work with Trumpet's Windows Sockets DLL Alpha 15. Purpose of this program was to see how a PING program could be implemented under Windows Sockets. This program uses either blocking or async socket calls to perform its magic. *************************************************************************/ //---------------------- #include "ws_glob.h" #include "WS_ping.H" #include "ip_icmp.h" //---------------------- BOOL bSpecified=FALSE; int nPktLength=50; int nNumPkts=10; int nTimeOut=10; extern int nTransmitted,nReceived; int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // MSG structure to store your messages int nRc; // return value from Register Classes long nWndunits; // window units for size and location int nX; // the resulting starting point (x, y) int nY; int nWidth; // the resulting width and height for this int nHeight; // window int err; strcpy(szAppName, "WS_PING"); hInst = hInstance; if(!hPrevInstance) { if ((nRc = nCwRegisterClasses()) == -1) { MessageBox(NULL, "Window creation failed", NULL, MB_ICONEXCLAMATION); return nRc; } } // Create a device independant size and location nWndunits = GetDialogBaseUnits(); nWndx = LOWORD(nWndunits); nWndy = HIWORD(nWndunits); nX = ((18 * nWndx) / 4); nY = ((18 * nWndy) / 8); nWidth = ((247 * nWndx) / 4); nHeight = ((218 * nWndy) / 8); // create application's Main window hWndMain = CreateWindow( szAppName, "WinSock_PING", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN | WS_OVERLAPPED, nX,nY, nWidth, nHeight, NULL, NULL, hInst, NULL); if(hWndMain == NULL) { MessageBox(NULL, "Error registering class", NULL, MB_ICONEXCLAMATION); return 2; } if(lstrlen((LPSTR)lpszCmdLine)>0) { bSpecified=TRUE; strcpy(szRemoteHost,lpszCmdLine); } if (err = WSAStartup( 0x0101, &WSAData)) // register task with { // winsock tcp/ip API ReportWSError(err); } else { GetLocalInfo(); ShowWindow(hWndMain, nCmdShow); // display main window while(GetMessage(&msg, NULL, 0, 0)) // Until WM_QUIT message { TranslateMessage(&msg); DispatchMessage(&msg); } WSACleanup(); ReleaseDisplayMem(); } // Do clean up before exiting from the application CwUnRegisterClasses(); return msg.wParam; } #define WM_RESETCURSOR WM_USER+10 // Main window message processing LONG FAR PASCAL WndProc(HWND hWnd,WORD Message,WORD wParam,LONG lParam) { int nIndex,nRC,nBytesRecv; static int saFromAddrLen; static struct sockaddr_in saDestAddr; static struct sockaddr_in saFromAddr; static struct hostent HostEntry , *pHostEntry; static struct protoent ProtoEntry, *pProtoEntry; static HANDLE hATHhost; static HANDLE hATHprot; switch (Message) { case WM_CREATE: hStdCursor=LoadCursor(NULL,IDC_ARROW); hWaitCursor=LoadCursor(NULL,IDC_WAIT); if(!bSpecified) GetPrivateProfileString("WS_PING", "HOSTNAME", "129.29.64.246",szRemoteHost,79,szIniFile); else PostMessage(hWnd,WM_COMMAND,IDM_ASYNC_CONNECT,0L); break; case WM_TIMER: switch(wParam) { case 10: DoPrintf("[Timer-TIMEOUT] "); KillTimer(hWnd,10); if(WSAIsBlocking()) { bAborted=TRUE; WSACancelBlockingCall(); } break; case 20: DoPrintf("[Timer-ASYNC_SEND] "); if(nTransmittedh_addr, pHostEntry->h_length); else { DoPrintf("can't get \"%s\" host entry.",szRemoteHost); SendMessage(hWnd,WM_RESETCURSOR,0,0l); break; } } if((pProtoEntry=getprotobyname("icmp"))==NULL) { DoPrintf("unknown protocol: icmp"); SendMessage(hWnd,WM_RESETCURSOR,0,0l); break; } if((ping_socket=socket(saDestAddr.sin_family,SOCK_RAW, pProtoEntry->p_proto)) ==INVALID_SOCKET) { DoPrintf("can't create raw socket %s", ReturnWSError(WSAGetLastError(),NULL)); SendMessage(hWnd,WM_RESETCURSOR,0,0l); break; } nTransmitted=0; nReceived=0; DoPrintf("[%u] raw socket created",ping_socket); PrintHeader(&saDestAddr,nPktLength); SetTimer(hWnd,30,1000,NULL); break; case IDM_ABOUT: { FARPROC lpfnMsgProc; lpfnMsgProc = MakeProcInstance((FARPROC)WS_AboutMsgProc, hInst); DialogBox(hInst, (LPSTR)"DLG_ABOUT", hWnd, lpfnMsgProc); FreeProcInstance(lpfnMsgProc); } break; default: return DefWindowProc(hWnd, Message, wParam, lParam); } break; case WM_PING_HOST: DoPrintf("[WM_PING_HOST] "); if(WSAGETASYNCERROR(lParam)!=0) { ReportWSError(WSAGETASYNCERROR(lParam)); SendMessage(hWnd,WM_RESETCURSOR,0,0l); } else { memcpy(&HostEntry,szMsgBuf,sizeof(struct hostent)); memcpy(&saDestAddr.sin_addr,HostEntry.h_addr,HostEntry.h_length); hATHhost=0; if(hATHprot==0) SendMessage(hWnd,WM_PING_CAS,0,0l); } break; case WM_PING_PROTO: DoPrintf("[WM_PING_PROTO] "); if(WSAGETASYNCERROR(lParam)!=0) { ReportWSError(WSAGETASYNCERROR(lParam)); SendMessage(hWnd,WM_RESETCURSOR,0,0l); } else { memcpy(&ProtoEntry,&szMsgBuf[MAXGETHOSTSTRUCT], sizeof(struct protoent)); hATHprot=0; if(hATHhost==0) SendMessage(hWnd,WM_PING_CAS,0,0l); } break; case WM_PING_CAS: PrintHeader(&saDestAddr,nPktLength+SIZE_ICMP_HDR); ping_socket=socket(saDestAddr.sin_family,SOCK_RAW, ProtoEntry.p_proto); if(ping_socket==INVALID_SOCKET) { DoPrintf("can't create raw socket: %s", ReturnWSError(WSAGetLastError(),NULL)); SendMessage(hWnd,WM_RESETCURSOR,0,0l); } else { if(WSAAsyncSelect(ping_socket,hWnd,WM_PING_RECEIVE,FD_READ) ==SOCKET_ERROR) { DoPrintf("asyncselect: %s",ReturnWSError(WSAGetLastError(),NULL)); ping_socket=DoClose(ping_socket); SendMessage(hWnd,WM_RESETCURSOR,0,0l); } else { nTransmitted=nReceived=0; SetTimer(hWndMain,20,1000,NULL); } } break; case WM_PING_RECEIVE: DoPrintf("[WM_PING_RECEIVE] "); saFromAddrLen=sizeof(struct sockaddr); nBytesRecv=recvfrom(ping_socket,szString,MAXPACKET,0, (struct sockaddr *)&saFromAddr, &saFromAddrLen); if(nBytesRecv!=SOCKET_ERROR || WSAGetLastError()!=WSAEINTR) { if(nBytesRecv==SOCKET_ERROR) { DoPrintf("[recvfrom] %s",ReturnWSError(WSAGetLastError(),NULL)); } else PrintPkt(szString,nBytesRecv,&saFromAddr,TRUE); } break; case WM_PING_FINISH: ping_socket=DoClose(ping_socket); PrintStats(); case WM_RESETCURSOR: bCmdInProgress=0; SetCursor(hStdCursor); break; case WM_SETCURSOR: if(bCmdInProgress) SetCursor(hWaitCursor); else return DefWindowProc(hWnd, Message, wParam, lParam); break; case WM_PAINT: // code for the window's client area DoPaint(hWnd); break; case WM_VSCROLL: switch(wParam) { case SB_LINEDOWN: if(sVPos<(ptrhGMem-1)) sVPos++; break; case SB_LINEUP: if(sVPos>0) --sVPos; break; case SB_THUMBPOSITION: sVPos = min(ptrhGMem, LOWORD(lParam)); break; case SB_PAGEUP: if(sVPos>10) sVPos-=10; else sVPos=0; break; case SB_PAGEDOWN: if(sVPos<(ptrhGMem-10)) sVPos+=10; else sVPos=ptrhGMem; break; default: return FALSE; } SetScrollPos(hWnd,SB_VERT,sVPos,TRUE); InvalidateRect(hWnd,NULL,TRUE); break; case WM_CLOSE: // close the window // Destroy child windows, modeless dialogs, then, this window if (hWnd == hWndMain) { if(ping_socket!=INVALID_SOCKET) ping_socket=DoClose(ping_socket); DestroyWindow(hWnd); WritePrivateProfileString("WS_PING", "HOSTNAME",szRemoteHost, szIniFile); PostQuitMessage(0); // Quit the application } else DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, Message, wParam, lParam); } return 0L; } // End of WndProc /************************************************************************/ /* Misc Dialog Window Procedures */ /************************************************************************/ BOOL FAR PASCAL WS_AboutMsgProc(HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch(Message) { case WM_INITDIALOG: cwCenter(hWndDlg, 0); break; case WM_CLOSE: PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L); break; case WM_COMMAND: switch(wParam) { case IDOK: EndDialog(hWndDlg, TRUE); break; case IDCANCEL: EndDialog(hWndDlg, FALSE); break; } break; default: return FALSE; } return TRUE; } BOOL FAR PASCAL WS_HostMsgProc(HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { BOOL lpfTranslated; switch(Message) { case WM_INITDIALOG: SetDlgItemText(hWndDlg,DLG_HOST_NAME,szRemoteHost); SetDlgItemInt(hWndDlg,DLG_HOST_NUMPKTS,nNumPkts,FALSE); SetDlgItemInt(hWndDlg,DLG_HOST_PKTLENGTH,nPktLength,FALSE); SetDlgItemInt(hWndDlg,DLG_HOST_TIMEOUT,nTimeOut,FALSE); CheckDlgButton(hWndDlg,DLG_HOST_VERBOSE,bVerbose); cwCenter(hWndDlg, 0); break; case WM_CLOSE: PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L); break; case WM_COMMAND: switch(wParam) { case IDOK: GetDlgItemText(hWndDlg,DLG_HOST_NAME,szRemoteHost,70); nNumPkts=GetDlgItemInt(hWndDlg,DLG_HOST_NUMPKTS, &lpfTranslated,FALSE); nPktLength=GetDlgItemInt(hWndDlg,DLG_HOST_PKTLENGTH, &lpfTranslated,FALSE); nTimeOut=GetDlgItemInt(hWndDlg,DLG_HOST_TIMEOUT, &lpfTranslated,FALSE); bVerbose=IsDlgButtonChecked(hWndDlg,DLG_HOST_VERBOSE); if((nPktLength+SIZE_ICMP_HDR)>512) nPktLength=512-SIZE_ICMP_HDR; EndDialog(hWndDlg, TRUE); break; case IDCANCEL: EndDialog(hWndDlg, FALSE); break; } break; default: return FALSE; } return TRUE; } BOOL FAR PASCAL WS_InputMsgProc(HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch(Message) { case WM_INITDIALOG: SetDlgItemText(hWndDlg,DLG_PROMPT,szDlgPrompt); SetDlgItemText(hWndDlg,DLG_EDIT,szDlgEdit); cwCenter(hWndDlg, 0); break; case WM_CLOSE: PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L); break; case WM_COMMAND: switch(wParam) { case IDOK: GetDlgItemText(hWndDlg,DLG_EDIT,szDlgEdit,70); EndDialog(hWndDlg, TRUE); break; case IDCANCEL: EndDialog(hWndDlg, FALSE); break; } break; default: return FALSE; } return TRUE; } int nCwRegisterClasses(void) { WNDCLASS wndclass; // struct to define a window class memset(&wndclass, 0x00, sizeof(WNDCLASS)); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInst; wndclass.hIcon = LoadIcon(hInst, "WS_PING"); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) CreateSolidBrush(RGB(128, 128, 128)); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if(!RegisterClass(&wndclass)) return -1; return(0); } void cwCenter(hWnd, top) HWND hWnd; int top; { POINT pt; RECT swp; RECT rParent; int iwidth; int iheight; GetWindowRect(hWnd, &swp); GetClientRect(hWndMain, &rParent); iwidth = swp.right - swp.left; iheight = swp.bottom - swp.top; pt.x = (rParent.right - rParent.left) / 2; pt.y = (rParent.bottom - rParent.top) / 2; ClientToScreen(hWndMain, &pt); pt.x = pt.x - (iwidth / 2); pt.y = pt.y - (iheight / 2); if(top) pt.y = pt.y + top; MoveWindow(hWnd, pt.x, pt.y, iwidth, iheight, FALSE); } void CwUnRegisterClasses(void) { WNDCLASS wndclass; memset(&wndclass, 0x00, sizeof(WNDCLASS)); GetClassInfo(hInst, szAppName, &wndclass); DeleteObject(wndclass.hbrBackground); UnregisterClass(szAppName, hInst); }