/*
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
This is "Sample Code" and is distributable subject to the terms of the end user license agreement.
*/
///////////////////////////////////////////////////////////////////////////////
//
// CMTime.CPP
//
// Connects to a time server using connection manager
//
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock.h>
#include <connmgr.h>
#include <winuserm.h>
#include <commctrl.h>
#include <aygshell.h>
#include "resource.h"
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof((x)[0]))
// some constants
#define HIGHTIME 21968699 // 21968708 // Jan 1, 1900 FILETIME.highTime
#define LOWTIME 4259332096 // 1604626432 // Jan 1, 1900 FILETIME.lowtime
#define EINITFAILED (-1)
// global variables
HINSTANCE g_hInst;
LPCTSTR g_lpctszTitle;
/* *************************************************************************** */
// IP address of "time-a.timefreq.bldrdoc.gov", replace with IP of server running time server. (RFC-868)
// If using the timeserver.exe application supplied in the SDK, set this to the IP address
// of the computer running timeserver.exe
// Note: Accessing time servers on the Internet requires that Port 37 be opened on you router
// or you may need to run special client software depending on your network configuration.
// Talk to your network administrator or help desk for more information
in_addr g_in_addr = { (unsigned char)132,
(unsigned char)163,
(unsigned char)4,
(unsigned char)102 };
/* *************************************************************************** */
typedef struct
{
HWND hwndNetwork; //Network spinner
HANDLE hConnection; //Connection handle
UINT WM_CMEVENT; //Registered Window Message
} SConnection;
static void DestroyConnection(
SConnection *lpConnection
)
{
// If a connection exists, destroy it
if(NULL != lpConnection->hConnection)
{
ConnMgrReleaseConnection(lpConnection->hConnection, FALSE);
lpConnection->hConnection = NULL;
}
}
static HRESULT EstablishConnection(
HWND hDlg,
SConnection *lpConnection
)
{
int iNetwork;
HRESULT hResult = E_FAIL;
// cleanup the old connection
DestroyConnection(lpConnection);
// get the right network to connect to
iNetwork = SendMessage(lpConnection->hwndNetwork, LB_GETCURSEL, 0, 0);
if(LB_ERR != iNetwork)
{
CONNMGR_DESTINATION_INFO DestInfo;
hResult = ConnMgrEnumDestinations(iNetwork, &DestInfo);
if(SUCCEEDED(hResult))
{
// actually try to establish the connection
CONNMGR_CONNECTIONINFO ConnInfo;
ZeroMemory(&ConnInfo, sizeof(ConnInfo));
ConnInfo.cbSize = sizeof(ConnInfo);
ConnInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
ConnInfo.dwPriority = CONNMGR_PRIORITY_USERBACKGROUND;
ConnInfo.guidDestNet = DestInfo.guid;
ConnInfo.hWnd = hDlg;
ConnInfo.uMsg = lpConnection->WM_CMEVENT;
hResult = ConnMgrEstablishConnection(&ConnInfo, &lpConnection->hConnection);
// check to see if the attempt failed
if(FAILED(hResult))
{
TCHAR tszBuffer[256];
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCTSTR)LoadString(g_hInst, IDS_CONNMGR_ESTABLISH_FAILED, 0, 0),
0,
0,
tszBuffer,
ARRAY_LENGTH(tszBuffer),
(va_list*)&hResult);
MessageBox(NULL, tszBuffer, g_lpctszTitle, MB_OK);
}
}
}
return hResult;
}
static BOOL GetTimeFromServer(
DWORD *lpdwTime
)
{
*lpdwTime = 0;
BOOL bReturn= FALSE;
// set up a TCP socket
SOCKET sSock = socket(AF_INET, SOCK_STREAM, 0);
if(INVALID_SOCKET != sSock)
{
struct sockaddr_in sin;
// set up a sockaddr for the destination address
memcpy(&sin.sin_addr, &g_in_addr, sizeof(sin.sin_addr));
sin.sin_family = AF_INET;
sin.sin_port = htons(IPPORT_TIMESERVER);
// try to connect
if(0 == connect(sSock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)))
{
int iResult, iRead;
// Read 4 bytes from the time server
for(iRead = 0; iRead < 4; iRead += iResult)
{
iResult = recv(sSock, (char*)lpdwTime + iRead, 4 - iRead, 0);
if(iResult < 1)
break;
}
if(4 == iRead)
{
// swap the bytes round from Network to Host order
*lpdwTime = ntohl(*lpdwTime);
bReturn = TRUE;
}
}
closesocket(sSock);
}
return bReturn;
}
static BOOL UpdateSysTime(
DWORD dwTime
)
{
UINT64 uiCurTime, uiBaseTime, uiResult;
SYSTEMTIME st;
// January 1, 1900
uiBaseTime = ((UINT64) HIGHTIME << 32) + LOWTIME;
// convert dwTime to 100 nanosecond intervals
uiCurTime = (UINT64)dwTime * (UINT64)10000000;
uiResult = uiBaseTime + uiCurTime;
FileTimeToSystemTime((LPFILETIME)&uiResult, &st);
return SetSystemTime(&st);
}
static BOOL InitDialog(
const HWND hDlg,
UINT nToolBarId
)
{
// Specify that the dialog box should stretch full screen
SHINITDLGINFO shidi;
ZeroMemory(&shidi, sizeof(shidi));
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
shidi.hDlg = hDlg;
// set up Soft Keys menu
SHMENUBARINFO mbi;
ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO);
mbi.hwndParent = hDlg;
mbi.nToolBarId = nToolBarId;
mbi.hInstRes = g_hInst;
// If we could not initialize the dialog box, return an error
if(FALSE == (SHInitDialog(&shidi) && SHCreateMenuBar(&mbi)))
{
return FALSE;
}
// set the title bar
VERIFY(SetWindowText(hDlg, g_lpctszTitle));
// In order to make Back work properly, it's necessary to
// override it and then call the appropriate SH API
(void)SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK,
MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
return TRUE;
}
static BOOL CALLBACK DialogProc(
const HWND hDlg,
const UINT uiMessage,
const WPARAM wParam,
const LPARAM lParam)
{
BOOL bProcessedMsg = TRUE;
SConnection *lpConnection = (SConnection*)GetWindowLong(hDlg, DWL_USER);
switch(uiMessage)
{
case WM_INITDIALOG:
{
int iResult, i;
WSADATA wsaData;
CONNMGR_DESTINATION_INFO DestInfo;
SetWindowLong(hDlg, DWL_USER, lParam);
lpConnection = (SConnection*)lParam;
// make the dialog full screen and init the menubar
if(FALSE == InitDialog(hDlg, IDR_CMTIME_MENUBAR))
{
EndDialog(hDlg, EINITFAILED);
return TRUE;
}
// create a message to use for CM events
if(!(lpConnection->WM_CMEVENT = RegisterWindowMessage(TEXT("CM Event"))))
{
EndDialog(hDlg, EINITFAILED);
return TRUE;
}
// Init network ID control
VERIFY(lpConnection->hwndNetwork = GetDlgItem(hDlg, IDC_CMTIME_NETWORK));
for(i = 0; SUCCEEDED(ConnMgrEnumDestinations(i, &DestInfo)); i++)
{
iResult = SendMessage(lpConnection->hwndNetwork, LB_INSERTSTRING, i, (LPARAM)DestInfo.szDescription);
if(LB_ERR == iResult)
{
EndDialog(hDlg, EINITFAILED);
return TRUE;
}
}
// select the first element of the network control
SendMessage(lpConnection->hwndNetwork, LB_SETCURSEL, 0, 0);
// initialize Winsock
iResult = WSAStartup(MAKEWORD(1, 1), &wsaData);
if (iResult)
{
EndDialog(hDlg, EINITFAILED);
return TRUE;
}
}
break;
case WM_COMMAND:
switch (wParam)
{
case IDM_CMTIME_QUIT:
EndDialog(hDlg, 0);
break;
case IDM_CMTIME_CONNECT:
SetDlgItemText(hDlg, IDC_CMTIME_TSTATUS, NULL);
SetDlgItemText(hDlg, IDC_CMTIME_STATUS, (LPCTSTR)LoadString(g_hInst, IDS_S