/*******************************************************************

Copyright (c) 2004 Open Mobile Alliance, Ltd.  All Rights Reserved.

This software is made available under the usage and distribution terms 
covered by the Common Public License 1.0 and by using this software you
are bound by the terms and conditions of the same.

EXCEPT AS EXPRESSLY SET FORTH IN THE COMMON PUBLIC LICENSE,
THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, 
ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
   
Each recipient is solely responsible for determining the 
appropriateness of using and distributing this program and assumes 
all risks associated with its exercise of rights under the Common 
Public License, including but not limited to the risks and 
costs of program errors, compliance with applicable laws, 
damage to or loss of data, programs or equipment, and 
unavailability or interruption of operations.

********************************************************************/
// SCTS3DevMan.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "SCTS3DevMan.h"
#include <winsvc.h>


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/* The global main pane */
CSCTS3DevManDlg *mainPane;
CTreeCtrl *navigator;

/* Transport Servers */
SctsHttpTransportServer *httpServer=0;
SctsObexTCPTransportServer *obexTCPServer=0;
SctsObexIRTransportServer *obexIRServer=0;
SctsTransportServerState httpServerState=SERVER_STOPPED;
SctsTransportServerState obexTCPServerState=SERVER_STOPPED;
SctsTransportServerState obexIRServerState=SERVER_STOPPED;
int httpServerPort=80;
int obexTCPServerPort=650;
char *obexIRServerService=strdup("SCTS");

/* File paths */
CString appPath;
CString logPath;
time_t appTimeStamp;

/* Windows enumeration function */
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
	char title[50];
	*(HWND *)lParam=0;
	GetWindowText(hwnd,title,50);
	if (strstr(title,"SyncML Conformance Test Suite") || strstr(title,"SCTS Command Line Interface"))
	{
		*(HWND *)lParam=hwnd;
		return FALSE;
	}
	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// CSCTS3DevManApp

BEGIN_MESSAGE_MAP(CSCTS3DevManApp, CWinApp)
	//{{AFX_MSG_MAP(CSCTS3DevManApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG
	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSCTS3DevManApp construction

CSCTS3DevManApp::CSCTS3DevManApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CSCTS3DevManApp object

CSCTS3DevManApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CSCTS3DevManApp initialization

BOOL CSCTS3DevManApp::InitInstance()
{
	HWND hwnd=0;
	extern void serversUICallback(void *,SctsTransportServer *,SctsTransportServerState);

	if (!AfxSocketInit())
	{
		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
		return FALSE;
	}

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	AfxInitRichEdit();

	CSCTS3DevManDlg dlg;
	mainPane = &dlg;

	/* Check if another instance is running */
	EnumWindows(EnumWindowsProc,(LPARAM)&hwnd);
	if (hwnd)
	{
		::SetForegroundWindow(hwnd);
		return FALSE;
	}

	/* Read registry entries */
	ReadRegistry();

	/* Start transport servers */
	SctsTransportServer::SetUICallback(0,serversUICallback);
	httpServer=new SctsHttpTransportServer(httpServerPort);
	httpServer->Create();

	m_pMainWnd = &dlg;
	SetDialogBkColor(RGB(255,255,255));
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with OK
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with Cancel
	}


	/* Write registry entries */
	WriteRegistry();
	/* Restart irmon service */
	if (sctsRestartIrmon) sctsStartIrmon();
	
	// Since the dialog has been closed, return FALSE so that we exit the
	//  application, rather than start the application's message pump.
	return FALSE;
}

void CSCTS3DevManApp::ReadRegistry()
{
	CRegKey key;
	CString tempStr;
	DWORD settingSize;
	CFileStatus fileStatus;
	char buffer[1000];

	/* Get the application path */
	tempStr="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\SCTS ";
	tempStr+=SCTS_VERSION;
	if (key.Open(HKEY_LOCAL_MACHINE,tempStr)!=ERROR_SUCCESS) return;
	settingSize=1000;
	if (key.QueryValue(buffer,"path",&settingSize)!=ERROR_SUCCESS)
	{
		key.Close();
		return;
	}
	appPath=buffer;
	/* Open the main key */
	tempStr="SOFTWARE\\SyncML Conformance Test Suite\\";
	tempStr+=SCTS_VERSION;
	if (key.Open(HKEY_LOCAL_MACHINE,tempStr)!=ERROR_SUCCESS) return;
	while (true)
	{
		/* Get log path */
		settingSize=1000;
		if (key.QueryValue(buffer,"LogPath",&settingSize)!=ERROR_SUCCESS) break;
		if (buffer[0] && SetCurrentDirectory(buffer))
			logPath=buffer;
		else
		{
			logPath=appPath;
			SetCurrentDirectory(logPath);
		}
		sctsStatusLogOpen();
		appPath+="\\accounts1.2.dat";
		/* Get last application state */
		if (key.QueryValue(settingSize,"AppState")!=ERROR_SUCCESS) break;
		/* Application wasnt closed properly display info */
		if (settingSize)
		{
			if (key.QueryValue(settingSize,"AppTimestamp")!=ERROR_SUCCESS) break;
			CLoadError loadError(settingSize);
			loadError.DoModal();
		}
		/* Set application state to open */
		appTimeStamp=time(0);
		SCTSASSERT(key.SetValue(1,"AppState")==ERROR_SUCCESS);
		SCTSASSERT(key.SetValue(appTimeStamp,"AppTimestamp")==ERROR_SUCCESS);
		/* Read server settings */
		if (key.QueryValue(settingSize,"HttpServerPort")!=ERROR_SUCCESS) break;
		httpServerPort=settingSize;
		if (key.QueryValue(settingSize,"ObexTCPServerPort")!=ERROR_SUCCESS) break;
		obexTCPServerPort=settingSize;
		settingSize=1000;
		if (key.QueryValue(buffer,"ObexIRServerService",&settingSize)!=ERROR_SUCCESS) break;
		obexIRServerService=strdup(buffer);
		/* Read session timeout */
		if (key.QueryValue(settingSize,"SessionTimeout")!=ERROR_SUCCESS) break;
		sctsSessionTimeout=settingSize;
		/* Validate accounts file */
		if (key.QueryValue(settingSize,"AccountsTimestamp")!=ERROR_SUCCESS) break;
		/* Bypass if it is the first time */
		if (settingSize)
		{
			/* Validate accounts file */
			if (CFile::GetStatus(appPath,fileStatus) && fileStatus.m_mtime!=CTime((time_t)settingSize))
			{
				MessageBox(0,"Accounts file has been modified since last execution of SCTS. All account information has been discarded.","SCTS Account Information",MB_ICONEXCLAMATION);
				CFile::Remove(appPath);
			}
			/* Read last size */
			if (key.QueryValue(settingSize,"LastX")!=ERROR_SUCCESS) break;
			mainPane->lastSize.left=settingSize;
			if (key.QueryValue(settingSize,"LastWidth")!=ERROR_SUCCESS) break;
			mainPane->lastSize.right=settingSize;
			if (key.QueryValue(settingSize,"LastY")!=ERROR_SUCCESS) break;
			mainPane->lastSize.top=settingSize;
			if (key.QueryValue(settingSize,"LastHeight")!=ERROR_SUCCESS) break;
			mainPane->lastSize.bottom=settingSize;
			if (key.QueryValue(settingSize,"LastNavWidth")!=ERROR_SUCCESS) break;
			mainPane->navigatorWidth=settingSize;
		}
		break;
	}
	key.Close();
}

void CSCTS3DevManApp::WriteRegistry()
{
	CRegKey key;
	CString tempStr;
	CFileStatus fileStatus;
	FILE *fp;

	/* Open the main key */
	tempStr="SOFTWARE\\SyncML Conformance Test Suite\\";
	tempStr+=SCTS_VERSION;
	if (key.Open(HKEY_LOCAL_MACHINE,tempStr)!=ERROR_SUCCESS) return;
	/* Write log path */
	SCTSASSERT(key.SetValue(logPath,"LogPath")==ERROR_SUCCESS);
	/* Write server settings */
	SCTSASSERT(key.SetValue(httpServerPort,"HttpServerPort")==ERROR_SUCCESS);
	SCTSASSERT(key.SetValue(obexTCPServerPort,"ObexTCPServerPort")==ERROR_SUCCESS);
	SCTSASSERT(key.SetValue(obexIRServerService,"ObexIRServerService")==ERROR_SUCCESS);
	/* Write session timeout */
	SCTSASSERT(key.SetValue(sctsSessionTimeout,"SessionTimeout")==ERROR_SUCCESS);
	/* Write last size */
	SCTSASSERT(key.SetValue(mainPane->lastSize.left,"LastX")==ERROR_SUCCESS);
	SCTSASSERT(key.SetValue(mainPane->lastSize.right,"LastWidth")==ERROR_SUCCESS);
	SCTSASSERT(key.SetValue(mainPane->lastSize.top,"LastY")==ERROR_SUCCESS);
	SCTSASSERT(key.SetValue(mainPane->lastSize.bottom,"LastHeight")==ERROR_SUCCESS);
	SCTSASSERT(key.SetValue(mainPane->navigatorWidth,"LastNavWidth")==ERROR_SUCCESS);
	/* Write accounts file */
	fp=fopen(appPath,"wb");
	if (fp)
	{
		SctsDMDevice::SaveAll(fp);
		fclose(fp);
	}
	if (CFile::GetStatus(appPath,fileStatus)) SCTSASSERT(key.SetValue(fileStatus.m_mtime.GetTime(),"AccountsTimestamp")==ERROR_SUCCESS);
	/* Write application state */
	SCTSASSERT(key.SetValue((DWORD)0,"AppState")==ERROR_SUCCESS);
	/* Close key */
	key.Close();
}

/* Functions to start/stop the irmon service */
bool sctsRestartIrmon=false;

bool sctsStopIrmon()
{
	SERVICE_STATUS scIrmonStatus;
	SC_HANDLE scManager;
	SC_HANDLE scIrmon;
	if (sctsRestartIrmon) return true;
	scIrmonStatus.dwCurrentState=SERVICE_STOPPED;
	if ((scManager=OpenSCManager(NULL,NULL,GENERIC_EXECUTE)))
	{
		if ((scIrmon=OpenService(scManager,"irmon",SERVICE_STOP | SERVICE_QUERY_STATUS)))
		{
			if (QueryServiceStatus(scIrmon,&scIrmonStatus) && scIrmonStatus.dwCurrentState==SERVICE_RUNNING)
			{
				if (MessageBox(NULL,"Stop windows service using IAS service name 'OBEX' ?","OBEX/IR Server",MB_ICONQUESTION | MB_YESNO)==IDYES)
				{
					ControlService(scIrmon,SERVICE_CONTROL_STOP,&scIrmonStatus);
					Sleep(3000);
					QueryServiceStatus(scIrmon,&scIrmonStatus);
					sctsRestartIrmon=true;
				}
				else
					scIrmonStatus.dwCurrentState=SERVICE_STOPPED;
			}
			CloseServiceHandle(scIrmon);
		}
		CloseServiceHandle(scManager);
	}
	if (scIrmonStatus.dwCurrentState!=SERVICE_STOPPED)
	{
		MessageBox(NULL,"Could not stop windows service.","OBEX/IR Server",MB_ICONERROR);
		sctsRestartIrmon=false;
		return false;
	}
	return true;
}
	
bool sctsStartIrmon()
{
	SERVICE_STATUS scIrmonStatus;
	SC_HANDLE scManager;
	SC_HANDLE scIrmon;
	if (!sctsRestartIrmon) return true;
	if ((scManager=OpenSCManager(NULL,NULL,GENERIC_EXECUTE)))
	{
		if ((scIrmon=OpenService(scManager,"irmon",SERVICE_START | SERVICE_QUERY_STATUS)))
		{
			if (QueryServiceStatus(scIrmon,&scIrmonStatus) && scIrmonStatus.dwCurrentState==SERVICE_STOPPED)
				StartService(scIrmon,NULL,NULL);
			CloseServiceHandle(scIrmon);
		}
		CloseServiceHandle(scManager);
	}
	return true;
}


