home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2001 December (DVD) / VPR0112A.ISO / OLS / TCL230JA95 / tcl230ja95.lzh / source.lzh / exe / sntp.c < prev    next >
C/C++ Source or Header  |  2001-02-15  |  18KB  |  704 lines

  1. /*-------------------------------------------------------------
  2.   sntp.c
  3.   KAZUBON 1998-1999
  4.                Special thanks to Tomoaki Nakashima
  5. ---------------------------------------------------------------*/
  6.  
  7. #include "tclock.h"
  8.  
  9. #include <winsock.h>
  10. #include <ras.h>
  11. #include "resource.h"
  12.  
  13. #undef RasEnumConnections
  14. #undef RasGetConnectStatus
  15.  
  16. // globals
  17. HWND hwndSNTP;     // for synchronizing time
  18. HWND hwndSNTPLog;  // for SNTP Log
  19.  
  20. // functions
  21. LRESULT CALLBACK SNTPWndProc(HWND hwnd, UINT message,
  22.     WPARAM wParam, LPARAM lParam);
  23. static BOOL IsConnecting(void);
  24. static void SNTPStart(HWND hwnd, char *buf);
  25. static void OnGetHost(HWND hwnd, WPARAM wParam, LPARAM lParam);
  26. static void SNTPSend(HWND hwnd, unsigned long serveraddr);
  27. static void OnReceive(HWND hwnd, WPARAM wParam, LPARAM lParam);
  28. static void SynchronizeSystemTime(DWORD seconds, DWORD fractions);
  29. static void SocketClose(HWND hwnd, const char *msgbuf);
  30. static int GetServerPort(const char *buf, char *server);
  31. static void Log(const char* msg);
  32. void time2int(int* ph, int* pm, const char* src);
  33.  
  34. // statics
  35. static BOOL bFirst = TRUE;
  36. static BOOL bSendingData = FALSE;
  37. static BOOL bSyncTimer = FALSE;
  38. static BOOL bSyncADay = TRUE;
  39. static int nMinutes = 60;
  40. static BOOL bNoDial = TRUE;
  41. static int nTimeout = 1000;
  42. static int nLastDay = -1;
  43. static int nLastMinute = -1;
  44. static int nHourStart = -1, nMinuteStart = -1,
  45.     nHourEnd = -1, nMinuteEnd = -1;
  46. static int nMinuteDif = 0;
  47. static DWORD dwTickCount = 0;
  48. static DWORD dwTickCountOnGetHost = 0;
  49. static DWORD dwTickCountOnSend = 0;
  50. DWORD (WINAPI *RasEnumConnections)(LPRASCONN, LPDWORD, LPDWORD);
  51. DWORD (WINAPI *RasGetConnectStatus)(HRASCONN, LPRASCONNSTATUS);
  52. static HMODULE hRASAPI = NULL;
  53. static BOOL bNoRasAPI = FALSE;
  54.  
  55. static char* g_pGetHost = NULL; // buffer of host entry
  56. static HANDLE g_hGetHost;       // task handle of WSAAsyncGetHostByName()
  57. static int g_socket;   // socket
  58. static int g_port;     // port numer
  59.  
  60. struct NTP_Packet {          // NTP packet
  61.     unsigned int Control_Word;
  62.     int root_delay;
  63.     int root_dispersion;
  64.     int reference_identifier;
  65.     __int64 reference_timestamp;
  66.     __int64 originate_timestamp;
  67.     __int64 receive_timestamp;
  68.     int transmit_timestamp_seconds;
  69.     int transmit_timestamp_fractions;
  70. };
  71.  
  72. // notification of event to get host
  73. #define WSOCK_GETHOST (WM_USER+1)
  74. // notification of socket event
  75. #define WSOCK_SELECT  (WM_USER+2)
  76.  
  77. /*---------------------------------------------------
  78.     create a window, initialize WinSock
  79. ---------------------------------------------------*/
  80. BOOL InitSyncTime(HWND hwndParent)
  81. {
  82.     char classname[] = "TClockSNTPWnd";
  83.     WNDCLASS wndclass;
  84.     WORD wVersionRequested;
  85.     int  nErrorStatus;
  86.     WSADATA wsaData;
  87.     
  88.     g_socket = -1;
  89.     g_hGetHost = NULL;
  90.     
  91.     // initialize WinSock
  92.     wVersionRequested = MAKEWORD(1, 1);
  93.     nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
  94.     if(nErrorStatus != 0)
  95.     {
  96.         Log("failed to initialize");
  97.         return FALSE;
  98.     }
  99.     
  100.     bNoRasAPI = GetMyRegLong("SNTP", "NoRASAPI", FALSE);
  101.     
  102.     // register a window class and create
  103.     wndclass.style         = 0;
  104.     wndclass.lpfnWndProc   = SNTPWndProc;
  105.     wndclass.cbClsExtra    = 0;
  106.     wndclass.cbWndExtra    = 0;
  107.     wndclass.hInstance     = g_hInst;
  108.     wndclass.hIcon         = NULL;
  109.     wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  110.     wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  111.     wndclass.lpszMenuName  = NULL;
  112.     wndclass.lpszClassName = classname;
  113.     RegisterClass(&wndclass);
  114.     hwndSNTP = CreateWindow(classname, "TClockSNTP",
  115.         WS_CHILD, 0, 0, 0, 0,
  116.         hwndParent, (HMENU)1, g_hInst, NULL);
  117.     
  118.     hwndSNTPLog = CreateWindowEx(WS_EX_CLIENTEDGE, "listbox", "",
  119.         WS_CHILD|WS_VSCROLL|WS_TABSTOP,
  120.         0, 0, 0, 0,
  121.         hwndSNTP, (HMENU)1, g_hInst, NULL);
  122.     
  123.     InitSyncTimeSetting();
  124.     
  125.     return TRUE;
  126. }
  127.  
  128. /*---------------------------------------------------
  129.     window procedure to process WinSock
  130. ---------------------------------------------------*/
  131. LRESULT CALLBACK SNTPWndProc(HWND hwnd, UINT message,
  132.     WPARAM wParam, LPARAM lParam)
  133. {
  134.     switch(message)
  135.     {
  136.         case WSOCK_GETHOST: // get IP address
  137.             OnGetHost(hwnd, wParam, lParam);
  138.             return 0;
  139.         case WSOCK_SELECT:  // receive SNTP data
  140.             OnReceive(hwnd, wParam, lParam);
  141.             return 0;
  142.         case (WM_USER + 10):  // command to start
  143.             SNTPStart(hwnd, (char*)lParam);
  144.             return 0;
  145.     }
  146.     
  147.     return DefWindowProc(hwnd, message, wParam, lParam);
  148. }
  149.  
  150. /*---------------------------------------------------
  151.     load settings for time syncronizing
  152. ---------------------------------------------------*/
  153. void InitSyncTimeSetting(void)
  154. {
  155.     char section[] = "SNTP";
  156.     char s[80];
  157.     
  158.     bSyncTimer = GetMyRegLong(section, "Timer", FALSE);
  159.     bSyncADay = GetMyRegLong(section, "ADay", TRUE);
  160.     nMinutes = GetMyRegLong(section, "Minutes", 60);
  161.     bNoDial = FALSE;
  162.     if(!bNoRasAPI)
  163.         bNoDial = GetMyRegLong(section, "NoDial", TRUE);
  164.     nLastDay = GetMyRegLong(section, "LastDay", -1);
  165.     
  166.     GetMyRegStr(section, "Begin", s, 80, "");
  167.     if(s[0])
  168.     {
  169.         time2int(&nHourStart, &nMinuteStart, s);
  170.         GetMyRegStr(section, "End", s, 80, "");
  171.         if(s[0])
  172.             time2int(&nHourEnd, &nMinuteEnd, s);
  173.         else nHourStart = nMinuteStart = -1;
  174.     }
  175. }
  176.  
  177. /*-------------------------------------------
  178.     called from main window procedure.
  179.     clean up
  180. ---------------------------------------------*/
  181. void EndSyncTime(HWND hwnd)
  182. {
  183.     hwnd = GetDlgItem(hwnd, 1);
  184.     
  185.     SocketClose(hwnd, NULL);
  186.     
  187.     if(hRASAPI) FreeLibrary(hRASAPI);
  188.     hRASAPI = NULL;
  189.     
  190.     WSACleanup();
  191. }
  192.  
  193. /*------------------------------------------------
  194.     called when main window received WM_TIMER.
  195.     determine to start or not every second.
  196. --------------------------------------------------*/
  197. void OnTimerSNTP(HWND hwnd, SYSTEMTIME* st)
  198. {
  199.     BOOL bDo = FALSE;
  200.     
  201.     if(bSendingData) // while sending/receiving
  202.     {
  203.         char msg[80];
  204.         DWORD dif;
  205.         dif = GetTickCount() - dwTickCountOnSend;
  206.         if(dif >= (DWORD)nTimeout)  // check timeout
  207.         {
  208.             wsprintf(msg, "timeout (%04d)", dif);
  209.             SocketClose(GetDlgItem(hwnd, 1), msg);
  210.         }
  211.         return;
  212.     }
  213.     
  214.     if(g_hGetHost) // while getting host address
  215.     {
  216.         DWORD dif;
  217.         dif = GetTickCount() - dwTickCountOnGetHost;
  218.         if(dif >= 10000)
  219.         {
  220.             SocketClose(GetDlgItem(hwnd, 1),
  221.                 "failed to get IP address");
  222.         }
  223.         return;
  224.     }
  225.     
  226.     if(!bSyncTimer) return;
  227.     
  228.     if(g_socket != -1 || g_hGetHost != NULL) return;
  229.     
  230.     if(nHourStart >= 0)
  231.     {
  232.         if((nHourStart <= nHourEnd && 
  233.                 (nHourStart <= st->wHour && st->wHour <= nHourEnd)) ||
  234.            (nHourStart > nHourEnd && 
  235.                 (nHourStart <= st->wHour || st->wHour <= nHourEnd)))
  236.         {
  237.             if(st->wHour == nHourStart &&
  238.                 st->wMinute < nMinuteStart) return;
  239.             if(st->wHour == nHourEnd &&
  240.                 nMinuteEnd < st->wMinute) return;
  241.         }
  242.         else return;
  243.     }
  244.     
  245.     if(bSyncADay)
  246.     {
  247.         if(st->wDay != nLastDay)
  248.         {
  249.             if(!bNoDial || IsConnecting()) bDo = TRUE;
  250.         }
  251.     }
  252.     else
  253.     {
  254.         if(bFirst || 
  255.             (GetTickCount()-dwTickCount >= (DWORD)nMinutes*60*1000))
  256.         {
  257.             if(!bNoDial || (st->wMinute != nLastMinute && IsConnecting()))
  258.                 bDo = TRUE;
  259.         }
  260.     }
  261.     nLastMinute = st->wMinute;
  262.     
  263.     if(bDo)
  264.         StartSyncTime(hwnd, NULL, 0);
  265. }
  266.  
  267. /*---------------------------------------------------
  268.     check RAS connection
  269. ---------------------------------------------------*/
  270. BOOL IsConnecting(void)
  271. {
  272.     RASCONN rc;
  273.     RASCONNSTATUS rcs;
  274.     DWORD cb, cConnections;
  275.     
  276.     // load DLL of RAS API
  277.     if(hRASAPI == NULL && bNoRasAPI == FALSE)
  278.     {
  279.         hRASAPI = LoadLibrary("RASAPI32.dll");
  280.         if(hRASAPI)
  281.         {
  282.             (FARPROC)RasEnumConnections =
  283.                 GetProcAddress(hRASAPI, "RasEnumConnectionsA");
  284.             (FARPROC)RasGetConnectStatus =
  285.                 GetProcAddress(hRASAPI, "RasGetConnectStatusA");
  286.             if(RasEnumConnections == NULL || RasGetConnectStatus == NULL)
  287.             {
  288.                 FreeLibrary(hRASAPI); hRASAPI = NULL;
  289.             }
  290.         }
  291.     }
  292.     if(hRASAPI == NULL) return FALSE;
  293.     
  294.     memset(&rc, 0, sizeof(rc));
  295.     rc.dwSize = sizeof(rc);
  296.     cb = sizeof(rc);
  297.     if(RasEnumConnections(&rc, &cb, &cConnections) == 0 &&
  298.         cConnections > 0)
  299.     {
  300.         memset(&rcs, 0, sizeof(rcs));
  301.         rcs.dwSize = sizeof(rcs);
  302.         if(RasGetConnectStatus(rc.hrasconn, &rcs) == 0 &&
  303.             rcs.rasconnstate == RASCS_Connected) return TRUE;
  304.     }
  305.     return FALSE;
  306. }
  307.  
  308. /*---------------------------------------------------
  309.     command to start syncronizing
  310. ---------------------------------------------------*/
  311. void StartSyncTime(HWND hwndParent, char* pServer, int nto)
  312. {
  313.     HWND hwnd;
  314.     SYSTEMTIME st;
  315.     char section[] = "SNTP";
  316.     char server[80], s[80];
  317.     
  318.     if(g_socket != -1 || g_hGetHost != NULL) return;
  319.     
  320.     if(pServer == NULL || *pServer == 0)
  321.     {
  322.         GetMyRegStr(section, "Server", server, 80, "");
  323.         pServer = server;
  324.     }
  325.     if(nto == 0)
  326.         nto = GetMyRegLong(section, "Timeout", 1000);
  327.     
  328.     if(*pServer == 0) return;
  329.     hwnd = GetDlgItem(hwndParent, 1);
  330.     if(!hwnd) return;
  331.     
  332.     nMinuteDif = 0;
  333.     GetMyRegStr(section, "Dif", s, 80, "");
  334.     if(s[0])
  335.     {
  336.         int h, m;
  337.         time2int(&h, &m, s);
  338.         nMinuteDif = h * 60 + m;
  339.     }
  340.     
  341.     GetLocalTime(&st);
  342.     nLastDay = st.wDay;
  343.     SetMyRegLong(section, "LastDay", nLastDay);
  344.     dwTickCount = GetTickCount();
  345.     bFirst = FALSE;
  346.     
  347.     nTimeout = nto;
  348.     
  349.     SNTPStart(hwnd, pServer);
  350. }
  351.  
  352. /*---------------------------------------------------
  353.     start SNTP session
  354. ---------------------------------------------------*/
  355. void SNTPStart(HWND hwnd, char *buf)
  356. {
  357.     char servername[256];
  358.     unsigned long serveraddr;
  359.     
  360.     if(g_socket != -1 || g_hGetHost != NULL) return;
  361.     
  362.     // get server name and port
  363.     g_port = GetServerPort(buf, servername);
  364.     if(g_port == -1)
  365.     {
  366.         Log("invalid server name"); return;
  367.     }
  368.     
  369.     // make a socket
  370.     g_socket = socket(PF_INET, SOCK_DGRAM, 0);
  371.     if(g_socket == INVALID_SOCKET)
  372.     {
  373.         Log("socket() failed");
  374.         g_socket = -1; return;
  375.     }
  376.     
  377.     serveraddr = inet_addr((char*)servername);
  378.     // if server name is not "XXX.XXX.XXX.XXX"
  379.     if(serveraddr == -1)
  380.     {
  381.         // request IP address
  382.         g_pGetHost = malloc(MAXGETHOSTSTRUCT);
  383.         g_hGetHost = WSAAsyncGetHostByName(hwnd, WSOCK_GETHOST,
  384.             servername, g_pGetHost, MAXGETHOSTSTRUCT);
  385.         if(g_hGetHost == 0)
  386.         {
  387.             SocketClose(hwnd, "WSAAsyncGetHostByName() failed");
  388.             return;
  389.         }
  390.         dwTickCountOnGetHost = GetTickCount();
  391.         return;
  392.     }
  393.     
  394.     // send data
  395.     SNTPSend(hwnd, serveraddr);
  396. }
  397.  
  398. /*---------------------------------------------------
  399.     called when the window received WSOCK_GETHOST.
  400.     get IP address and send data.
  401. ---------------------------------------------------*/
  402. void OnGetHost(HWND hwnd, WPARAM wParam, LPARAM lParam)
  403. {
  404.     struct hostent *pHostEnt;
  405.     unsigned long serveraddr;
  406.     
  407.     if(g_hGetHost == NULL) return;
  408.     
  409.     // success ?
  410.     if(WSAGETASYNCERROR(lParam) != 0)
  411.     {
  412.         SocketClose(hwnd, "failed to get IP address");
  413.         return;
  414.     }
  415.     
  416.     // valid handle ?
  417.     if(g_hGetHost != (HANDLE)wParam) return;
  418.     
  419.     // get IP address
  420.     pHostEnt = (struct hostent *)g_pGetHost;
  421.     serveraddr =  *((unsigned long *)((pHostEnt->h_addr_list)[0]));
  422.     free(g_pGetHost); g_pGetHost = NULL;
  423.     g_hGetHost = NULL;
  424.     
  425.     // send data
  426.     SNTPSend(hwnd, serveraddr);
  427. }
  428.  
  429. /*---------------------------------------------------
  430.     send SNTP data
  431. ---------------------------------------------------*/
  432. void SNTPSend(HWND hwnd, unsigned long serveraddr)
  433. {
  434.     struct sockaddr_in serversockaddr;
  435.     struct NTP_Packet NTP_Send;
  436.     
  437.     // request notification of events
  438.     if(WSAAsyncSelect(g_socket, hwnd, WSOCK_SELECT, FD_READ) == SOCKET_ERROR)
  439.     {
  440.         SocketClose(hwnd, "WSAAsyncSelect() failed");
  441.         return;
  442.     }
  443.     
  444.     // set IP address and port
  445.     serversockaddr.sin_family = AF_INET;
  446.     serversockaddr.sin_addr.s_addr = serveraddr;
  447.     serversockaddr.sin_port = htons((unsigned short)g_port);
  448.     memset(serversockaddr.sin_zero,(int)0,sizeof(serversockaddr.sin_zero));
  449.     
  450.     // init a packet
  451.     memset(&NTP_Send, 0, sizeof(struct NTP_Packet));
  452.     // NTP/SNTP version number = 4
  453.     // Mode = 3 (client)
  454.     NTP_Send.Control_Word = htonl(0x23000000);
  455.     
  456.     // send a packet
  457.     if(sendto(g_socket, (const char *)&NTP_Send, sizeof(NTP_Send), 0, 
  458.         (struct sockaddr *)&serversockaddr,
  459.         sizeof(serversockaddr)) == SOCKET_ERROR)
  460.     {
  461.         SocketClose(hwnd, "sendto() failed");
  462.         return;
  463.     }
  464.     
  465.     
  466.     // save tickcount
  467.     dwTickCountOnSend = GetTickCount();
  468.     bSendingData = TRUE;
  469. }
  470.  
  471. /*---------------------------------------------------
  472.     called when the window received WSOCK_SELECT.
  473.     receive SNTP data and set time.
  474. ---------------------------------------------------*/
  475. void OnReceive(HWND hwnd, WPARAM wParam, LPARAM lParam)
  476. {
  477.     struct sockaddr_in serversockaddr;
  478.     struct NTP_Packet NTP_Recv;
  479.     int sockaddr_Size;
  480.     
  481.     if(g_socket == -1) return;
  482.     if(WSAGETSELECTERROR(lParam))
  483.     {
  484.         SocketClose(hwnd, "failed to receive");
  485.         return;
  486.     }
  487.     if(g_socket != (int)wParam ||
  488.         WSAGETSELECTEVENT(lParam) != FD_READ) return;
  489.     
  490.     // receive data
  491.     sockaddr_Size = sizeof(serversockaddr);
  492.     if(recvfrom(g_socket, (char *)&NTP_Recv, sizeof(NTP_Recv), 0,
  493.         (struct sockaddr *)&serversockaddr, &sockaddr_Size) == SOCKET_ERROR)
  494.     {
  495.         SocketClose(hwnd, "recvfrom() failed");
  496.         return;
  497.     }
  498.     
  499.     // if Leap Indicator is 3
  500.     if(ntohl(NTP_Recv.Control_Word) >> 30 == 3)
  501.     {
  502.         SocketClose(hwnd, "server is unhealthy");
  503.         return;
  504.     }
  505.     
  506.     // set system time
  507.     SynchronizeSystemTime(ntohl(NTP_Recv.transmit_timestamp_seconds),
  508.         ntohl(NTP_Recv.transmit_timestamp_fractions));
  509.     
  510.     // close socket
  511.     SocketClose(hwnd, NULL);
  512. }
  513.  
  514. /*---------------------------------------------------
  515.     set system time to received data
  516. ---------------------------------------------------*/
  517. void SynchronizeSystemTime(DWORD seconds, DWORD fractions)
  518. {
  519.     FILETIME ft, ftold;
  520.     SYSTEMTIME st, st_dif, lt;
  521.     char s[1024];
  522.     DWORD sr_time;
  523.     DWORDLONG dif;
  524.     BOOL b;
  525.     
  526.     // timeout ?
  527.     sr_time = GetTickCount() - dwTickCountOnSend;
  528.     if(sr_time >= (DWORD)nTimeout)
  529.     {
  530.         wsprintf(s, "timeout (%04d)", sr_time);
  531.         Log(s); return;
  532.     }
  533.     
  534.     // current time
  535.     GetSystemTimeAsFileTime(&ftold);
  536.     
  537.     // NTP data -> FILETIME
  538.     *(DWORDLONG*)&ft =
  539.         // seconds from 1900/01/01 → 100 nano-seconds from 1601/01/01
  540.         M32x32to64(seconds, 10000000) + 94354848000000000i64;
  541.     
  542.     // difference
  543.     if(nMinuteDif > 0)
  544.         *(DWORDLONG*)&ft += M32x32to64(nMinuteDif * 60, 10000000);
  545.     else if(nMinuteDif < 0)
  546.         *(DWORDLONG*)&ft -= M32x32to64(-nMinuteDif * 60, 10000000);
  547.     
  548.     // set system time
  549.     b = FileTimeToSystemTime(&ft, &st);
  550.     if(b)
  551.     {
  552.         /* fractions: (2 ** 32 / 1000) */
  553.         st.wMilliseconds = (WORD)(fractions / 4294967);
  554.         b = SetSystemTime(&st);
  555.     }
  556.     if(!b)
  557.     {
  558.         Log("failed to set time"); return;
  559.     }
  560.     
  561.     GetLocalTime(<);
  562.     nLastDay = lt.wDay;
  563.     SetMyRegLong("SNTP", "LastDay", nLastDay);
  564.     
  565.     SystemTimeToFileTime(&st, &ft);
  566.     // delayed or advanced
  567.     b = (*(DWORDLONG*)&ft > *(DWORDLONG*)&ftold);
  568.     // get difference
  569.     if(b) dif = *(DWORDLONG*)&ft - *(DWORDLONG*)&ftold;
  570.     else  dif = *(DWORDLONG*)&ftold - *(DWORDLONG*)&ft;
  571.     FileTimeToSystemTime((FILETIME*)&dif, &st_dif);
  572.     
  573.     // save log
  574.     strcpy(s, "synchronized ");
  575.     if(st_dif.wYear == 1601 && st_dif.wMonth == 1 &&
  576.         st_dif.wDay == 1 && st_dif.wHour == 0)
  577.     {
  578.         strcat(s, b?"+":"-");
  579.         wsprintf(s + strlen(s), "%02d:%02d.%03d ",
  580.             st_dif.wMinute, st_dif.wSecond, st_dif.wMilliseconds);
  581.     }
  582.     wsprintf(s + strlen(s), "(%04d)", sr_time);
  583.     Log(s);
  584.     
  585.     GetMyRegStr("SNTP", "Sound", s, 1024, "");
  586.     PlayFile(g_hwndMain, s, 0);
  587. }
  588.  
  589. /*---------------------------------------------------
  590.     close a socket
  591. ---------------------------------------------------*/
  592. void SocketClose(HWND hwnd, const char *msgbuf)
  593. {
  594.     // cancel task handle of WSAAsyncGetHostByName()
  595.     if(g_hGetHost != NULL) WSACancelAsyncRequest(g_hGetHost);
  596.     g_hGetHost = NULL;
  597.     // free memory
  598.     if(g_pGetHost) free(g_pGetHost);
  599.     g_pGetHost = NULL;
  600.     
  601.     if(g_socket != -1)
  602.     {
  603.         // cancel request of notification
  604.         WSAAsyncSelect(g_socket, hwnd, 0, 0);
  605.         // close socket
  606.         closesocket(g_socket);
  607.     }
  608.     g_socket = -1;
  609.     bSendingData = FALSE;
  610.     
  611.     if(msgbuf) Log(msgbuf);
  612. }
  613.  
  614. /*---------------------------------------------------
  615.     get server name and port number from string
  616.         buf: "ntp.xxxxx.ac.jp:123"
  617. ---------------------------------------------------*/
  618. int GetServerPort(const char *buf, char *server)
  619. {
  620.     char *p;
  621.     int port = 123;
  622.  
  623.     if(strcmp(buf,"") == 0) return -1;
  624.     strcpy(server, buf);
  625.     
  626.     for(p = server; *p != ':' && *p != '\0'; p++);
  627.     if(*p == ':')
  628.     {
  629.         *p = 0; p++; port = 0;
  630.         while(*p)
  631.         {
  632.             if('0' <= *p && *p <= '9')
  633.                 port = port * 10 + *p - '0';
  634.             else
  635.             {
  636.                 port = -1; break;
  637.             }
  638.             p++;
  639.         }
  640.     }
  641.     return port;
  642. }
  643.  
  644. /*-------------------------------------------
  645.     save log data
  646. ---------------------------------------------*/
  647. void Log(const char* msg)
  648. {
  649.     SYSTEMTIME st;
  650.     char s[160];
  651.     int count, index;
  652.     
  653.     GetLocalTime(&st);
  654.     wsprintf(s, "%02d/%02d %02d:%02d:%02d ",
  655.         st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
  656.     strcat(s, msg);
  657.     
  658.     // save to listbox
  659.     count = SendMessage(hwndSNTPLog, LB_GETCOUNT, 0, 0);
  660.     if(count > 100)
  661.         SendMessage(hwndSNTPLog, LB_DELETESTRING, 0, 0);
  662.     index = SendMessage(hwndSNTPLog, LB_ADDSTRING, 0, (LPARAM)s);
  663.     SendMessage(hwndSNTPLog, LB_SETCURSEL, index, 0);
  664.     
  665.     // save to file
  666.     if(GetMyRegLong("SNTP", "SaveLog", TRUE))
  667.     {
  668.         HFILE hf;
  669.         char fname[MAX_PATH];
  670.         
  671.         strcpy(fname, g_mydir);
  672.         add_title(fname, "SNTP.txt");
  673.         hf = _lopen(fname, OF_WRITE);
  674.         if(hf == HFILE_ERROR)
  675.             hf = _lcreat(fname, 0);
  676.         if(hf == HFILE_ERROR) return;
  677.         _llseek(hf, 0, 2);
  678.         _lwrite(hf, s, strlen(s));
  679.         _lwrite(hf, "\x0d\x0a", 2);
  680.         _lclose(hf);
  681.     }
  682. }
  683.  
  684. /*-------------------------------------------
  685.     "XX:XX" -> two integers
  686. ---------------------------------------------*/
  687. void time2int(int* ph, int* pm, const char* src)
  688. {
  689.     const char* p;
  690.     BOOL bminus;
  691.     
  692.     p = src;
  693.     *ph = 0; *pm = 0;
  694.     bminus = FALSE;
  695.     if(*p == '-') { p++; bminus = TRUE; }
  696.     while('0' <= *p && *p <='9')
  697.         *ph = *ph * 10 + *p++ - '0';
  698.     if(bminus) *ph *= -1;
  699.     if(*p == ':') p++; else return;
  700.     while('0' <= *p && *p <='9')
  701.         *pm = *pm * 10 + *p++ - '0';
  702.     if(bminus) *pm *= -1;
  703. }
  704.