// SubstSvc NT service.
// Copyright (c) 2004-2011 by Elijah Zarezky,
// All rights reserved.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// EntryPoint.cpp - application entry point

// initially generated by AfxScratch v1.0.2290 on 18.07.2004 at 11:12:43
// visit http://zarezky.spb.ru/projects/afx_scratch.html for more info

//////////////////////////////////////////////////////////////////////////////////////////////
// PCH includes

#include "stdafx.h"

//////////////////////////////////////////////////////////////////////////////////////////////
// resource includes

#include "Resource.h"

//////////////////////////////////////////////////////////////////////////////////////////////
// other includes

#include "SubstSvcApp.h"
#include "ExecLogging.h"

//////////////////////////////////////////////////////////////////////////////////////////////
// unwanted warnings

#if defined(__INTEL_COMPILER)
// remark #177: variable was declared but never referenced
#pragma warning(disable: 177)
// remark #981: operands are evaluated in unspecified order
#pragma warning(disable: 981)
#endif	// __INTEL_COMPILER

//////////////////////////////////////////////////////////////////////////////////////////////
// debugging support

#if defined(_DEBUG)
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif	// _DEBUG

//////////////////////////////////////////////////////////////////////////////////////////////
// the one and only application object

static CSubstSvcApp g_appSubstSvc;

//////////////////////////////////////////////////////////////////////////////////////////////
// entry point

int _tmain(int argc, TCHAR* argv[], TCHAR* /*envp*/[])
{
	// try to initialize MFC
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), SW_HIDE))
	{
		return (-1);
	}

#if defined(_DEBUG)
	// install a client-defined reporting function
	_CrtSetReportHook(LogFile_WriteDbgRpt);
#endif	// _DEBUG

#if defined(_DEBUG)
	CMemoryState memStart, memStop, memDiff;
	// get the initial snapshot of memory
	memStart.Checkpoint();
#endif	// _DEBUG

	// assign registry key
	g_appSubstSvc.SetRegistryKey(IDS_REGISTRY_KEY);

	// start logging
	CWinApp* pApp = AfxGetApp();
	CString strLogName = pApp->GetProfileString(_T("Logging"), _T("TargetPath"));
	if (!strLogName.IsEmpty())
	{
		LogFile_Create(strLogName);
		LogFile_WriteEntry(LL_MINIMAL, IDS_EXE_STARTED, argv[0]);
	}

	// parse command-line arguments
	if (argc > 1)
	{
		SC_HANDLE schManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
		if (::lstrcmpi(argv[1], _T("/Register")) == 0)
		{
			// insert service into the SCM database
			SC_HANDLE schService = ::CreateService(schManager, g_szServiceName, g_szServiceName,
				SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
				SERVICE_ERROR_NORMAL, argv[0], NULL, NULL, NULL, NULL, NULL);
			::CloseServiceHandle(schService);
			LogFile_WriteEntry(LL_MINIMAL, IDS_SERVICE_REGISTERED, g_szServiceName);
		}
		else if (::lstrcmpi(argv[1], _T("/UnRegister")) == 0)
		{
			// remove service from the SCM database
			SC_HANDLE schService = ::OpenService(schManager, g_szServiceName, SERVICE_ALL_ACCESS);
			::DeleteService(schService);
			::CloseServiceHandle(schService);
			LogFile_WriteEntry(LL_MINIMAL, IDS_SERVICE_UNREGISTERED, g_szServiceName);
		}
		else {
			// unrecognized command-line argument
			LogFile_WriteEntry(LL_MINIMAL, IDS_CMDLINE_BAD_ARGUMENT, argv[1]);
		}
		::CloseServiceHandle(schManager);
	}
	else {
		// just start the service
		static SERVICE_TABLE_ENTRY aste[] =
		{
			{ g_szServiceName, ServiceMain },
			{ NULL, NULL }   // end of table - required
		};
		LogFile_WriteEntry(LL_MINIMAL, IDS_SCM_CONNECT);
		::StartServiceCtrlDispatcher(aste);
		LogFile_WriteEntry(LL_MINIMAL, IDS_SCM_DISCONNECTED);
	}

#if defined(_DEBUG)
	// get the final memory state...
	memStop.Checkpoint();
	// ...and then check the leaks
	if (memDiff.Difference(memStart, memStop))
	{
		_CrtMemDumpStatistics(&memDiff.m_memState);
		_CrtDumpMemoryLeaks();
	}
#endif	// _DEBUG
	LogFile_WriteEntry(LL_MINIMAL, IDS_EXE_FINISHED, argv[0]);

	// terminate MFC
#if defined(_DEBUG)
	AfxLockTempMaps();
	AfxUnlockTempMaps(-1);
#endif	// _DEBUG
	AfxWinTerm();

	// return to Windoze
	return (0);
}

// end of file
