/////////////////////////////////////////////////////////////////////////////
//  Copyright (C) 2002-2013 UltraVNC Team Members. All Rights Reserved.
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
//  USA.
//
// If the source code for the program is not available from the place from
// which you received this file, check 
// http://www.uvnc.com/
//
////////////////////////////////////////////////////////////////////////////

#include <algorithm>
#include "stdhdrs.h"
#include "inifile.h"
#include <string>
#include <cctype>

#ifndef ULTRAVNC_VEYON_SUPPORT
//  We first use shellexecute with "runas"
//  This way we can use UAC and user/passwd
//	Runas is standard OS, so no security risk

const char winvncSettings[]				= "-settings";
const char winvncStopservice[]			= "-stopservice";
const char winvncStartservice[]			= "-startservice";
const char winvncInstallService[]		= "-install";
const char winvncUnInstallService[]		= "-uninstall";
const char winvncSecurityEditor[]		= "-securityeditor";

extern char service_name[];

/////////////////////////////////////////////////////////////////////
void
Set_settings_as_admin(char *mycommand)
{
	char exe_file_name[MAX_PATH];
	char commanline[MAX_PATH];
	GetModuleFileName(0, exe_file_name, MAX_PATH);

	strcpy_s(commanline, winvncSettings);
	strcat_s(commanline, ":");
	strcat_s(commanline, 260, mycommand);

	SHELLEXECUTEINFO shExecInfo;
	shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	shExecInfo.fMask = NULL;
	shExecInfo.hwnd = GetForegroundWindow();
	shExecInfo.lpVerb = "runas";
	shExecInfo.lpFile = exe_file_name;
	shExecInfo.lpParameters = commanline;
	shExecInfo.lpDirectory = NULL;
	shExecInfo.nShow = SW_SHOWNORMAL;
	shExecInfo.hInstApp = NULL;
	ShellExecuteEx(&shExecInfo);
}

void Copy_to_Secure_from_temp_helper(char *lpCmdLine)
{
IniFile myIniFile_In;
IniFile myIniFile_Out;
myIniFile_Out.IniFileSetSecure();
myIniFile_In.IniFileSetTemp(lpCmdLine);

TCHAR *group1=new char[150];
TCHAR *group2=new char[150];
TCHAR *group3=new char[150];
BOOL BUseRegistry;
LONG Secure;
LONG MSLogonRequired;
LONG NewMSLogon;
LONG locdom1;
LONG locdom2;
LONG locdom3;
LONG DebugMode=2;
LONG Avilog=0;
LONG DebugLevel=10;
LONG DisableTrayIcon = 0;
LONG Rdpmode=0;
LONG NoScreensaver=0;
LONG LoopbackOnly;
LONG UseDSMPlugin;
LONG AllowLoopback=1;
LONG AuthRequired;
LONG ConnectPriority;

char DSMPlugin[128];
char *authhosts=new char[150];

LONG AllowShutdown=1;
LONG AllowProperties=1;
LONG AllowInjection=0;
LONG AllowEditClients=1;

LONG FileTransferEnabled=0;
LONG FTUserImpersonation=1;
LONG BlankMonitorEnabled=1;
LONG BlankInputsOnly=0; //PGM
LONG DefaultScale=1;

LONG SocketConnect=1;
LONG HTTPConnect;
LONG AutoPortSelect=1;
LONG PortNumber;
LONG HttpPortNumber;
LONG IdleTimeout;
LONG IdleInputTimeout;

LONG RemoveWallpaper=0;
LONG RemoveAero=0;

LONG QuerySetting=1;
LONG QueryTimeout=10;
LONG QueryDisableTime=0;
LONG QueryAccept;
LONG QueryIfNoLogon;

LONG EnableRemoteInputs=1;
LONG LockSettings=0;
LONG DisableLocalInputs=0;
LONG EnableJapInput=0;
LONG EnableUnicodeInput=0;
LONG EnableWin8Helper=0;
LONG kickrdp=0;
LONG clearconsole=0;

#define MAXPWLEN 8
char passwd[MAXPWLEN];

LONG TurboMode=1;
LONG PollUnderCursor=0;
LONG PollForeground=0;
LONG PollFullScreen=1;
LONG PollConsoleOnly=0;
LONG PollOnEventOnly=0;
LONG Driver=0;
LONG Hook=1;
LONG Virtual;
LONG SingleWindow=0;
char SingleWindowName[32];
char path[512];
char accept_reject_mesg[512];
LONG MaxCpu=100;
LONG MaxFPS = 25;

//adzm 2010-05-30 - dsmplugin config
char DSMPluginConfig[512];
*DSMPluginConfig = '\0';

LONG Primary=1;
LONG Secondary=0;

BUseRegistry = myIniFile_In.ReadInt("admin", "UseRegistry", 99);
if (BUseRegistry==99)
{
	//Failed to read, don't write anything to avoid a factoery reset
	return;
}


if (!myIniFile_Out.WriteInt("admin", "UseRegistry", BUseRegistry))
{
		//error
		DWORD error=GetLastError();
		MessageBoxSecure(NULL,"Permission denied:Uncheck [_] Protect my computer... in run as dialog or use user with write permission." ,myIniFile_Out.myInifile,MB_ICONERROR);
		return;
}

BOOL setextramouse = myIniFile_In.ReadInt("admin", "SendExtraMouse", 1);
myIniFile_Out.WriteInt("admin", "SendExtraMouse", setextramouse);

Secure = myIniFile_In.ReadInt("admin", "Secure", false);
myIniFile_Out.WriteInt("admin", "Secure", Secure);
MSLogonRequired=myIniFile_In.ReadInt("admin", "MSLogonRequired", false);
myIniFile_Out.WriteInt("admin", "MSLogonRequired", MSLogonRequired);
NewMSLogon=myIniFile_In.ReadInt("admin", "NewMSLogon", false);
myIniFile_Out.WriteInt("admin", "NewMSLogon", NewMSLogon);

myIniFile_In.ReadString("admin_auth","group1",group1,150);
myIniFile_In.ReadString("admin_auth","group2",group2,150);
myIniFile_In.ReadString("admin_auth","group3",group3,150);
myIniFile_Out.WriteString("admin_auth", "group1",group1);
myIniFile_Out.WriteString("admin_auth", "group2",group2);
myIniFile_Out.WriteString("admin_auth", "group3",group3);

locdom1=myIniFile_In.ReadInt("admin_auth", "locdom1",0);
locdom2=myIniFile_In.ReadInt("admin_auth", "locdom2",0);
locdom3=myIniFile_In.ReadInt("admin_auth", "locdom3",0);
myIniFile_Out.WriteInt("admin_auth", "locdom1", locdom1);
myIniFile_Out.WriteInt("admin_auth", "locdom2", locdom2);
myIniFile_Out.WriteInt("admin_auth", "locdom3", locdom3);

DebugMode=myIniFile_In.ReadInt("admin", "DebugMode", 0);
Avilog=myIniFile_In.ReadInt("admin", "Avilog", 0);
myIniFile_In.ReadString("admin", "path", path,512);
myIniFile_In.ReadString("admin", "accept_reject_mesg", accept_reject_mesg,512);
DebugLevel=myIniFile_In.ReadInt("admin", "DebugLevel", 0);
DisableTrayIcon=myIniFile_In.ReadInt("admin", "DisableTrayIcon", false);
Rdpmode = myIniFile_In.ReadInt("admin", "rdpmode", 0);
NoScreensaver = myIniFile_In.ReadInt("admin", "noscreensaver", 0);
LoopbackOnly=myIniFile_In.ReadInt("admin", "LoopbackOnly", false);

myIniFile_Out.WriteInt("admin", "DebugMode", DebugMode);
myIniFile_Out.WriteInt("admin", "Avilog", Avilog);
myIniFile_Out.WriteString("admin", "path", path);
myIniFile_Out.WriteString("admin", "accept_reject_mesg", accept_reject_mesg);
myIniFile_Out.WriteInt("admin", "DebugLevel", DebugLevel);
myIniFile_Out.WriteInt("admin", "DisableTrayIcon", DisableTrayIcon);
myIniFile_Out.WriteInt("admin", "rdpmode", Rdpmode);
myIniFile_Out.WriteInt("admin", "noscreensaver", NoScreensaver);
myIniFile_Out.WriteInt("admin", "LoopbackOnly", LoopbackOnly);

UseDSMPlugin=myIniFile_In.ReadInt("admin", "UseDSMPlugin", false);
AllowLoopback=myIniFile_In.ReadInt("admin", "AllowLoopback", true);
AuthRequired=myIniFile_In.ReadInt("admin", "AuthRequired", true);
ConnectPriority=myIniFile_In.ReadInt("admin", "ConnectPriority", 0);

myIniFile_Out.WriteInt("admin", "UseDSMPlugin", UseDSMPlugin);
myIniFile_Out.WriteInt("admin", "AllowLoopback", AllowLoopback);
myIniFile_Out.WriteInt("admin", "AuthRequired", AuthRequired);
myIniFile_Out.WriteInt("admin", "ConnectPriority", ConnectPriority);

myIniFile_In.ReadString("admin", "DSMPlugin",DSMPlugin,128);
myIniFile_In.ReadString("admin", "AuthHosts",authhosts,150);

myIniFile_Out.WriteString("admin", "DSMPlugin",DSMPlugin);
myIniFile_Out.WriteString("admin", "AuthHosts",authhosts);

//adzm 2010-05-30 - dsmplugin config
myIniFile_In.ReadString("admin", "DSMPluginConfig",DSMPluginConfig,512);
myIniFile_Out.WriteString("admin", "DSMPluginConfig",DSMPluginConfig);

AllowShutdown=myIniFile_In.ReadInt("admin", "AllowShutdown", true);
AllowProperties=myIniFile_In.ReadInt("admin", "AllowProperties", true);
AllowInjection=myIniFile_In.ReadInt("admin", "AllowInjection", false);
AllowEditClients=myIniFile_In.ReadInt("admin", "AllowEditClients", true);
myIniFile_Out.WriteInt("admin", "AllowShutdown" ,AllowShutdown);
myIniFile_Out.WriteInt("admin", "AllowProperties" ,AllowProperties);
myIniFile_Out.WriteInt("admin", "AllowInjection" ,AllowInjection);
myIniFile_Out.WriteInt("admin", "AllowEditClients" ,AllowEditClients);

FileTransferEnabled=myIniFile_In.ReadInt("admin", "FileTransferEnabled", true);
FTUserImpersonation=myIniFile_In.ReadInt("admin", "FTUserImpersonation", true);
BlankMonitorEnabled = myIniFile_In.ReadInt("admin", "BlankMonitorEnabled", true);
BlankInputsOnly = myIniFile_In.ReadInt("admin", "BlankInputsOnly", false); //PGM
DefaultScale = myIniFile_In.ReadInt("admin", "DefaultScale", 1);

Primary = myIniFile_In.ReadInt("admin", "primary", true);
Secondary = myIniFile_In.ReadInt("admin", "secondary", false);

myIniFile_Out.WriteInt("admin", "FileTransferEnabled", FileTransferEnabled);
myIniFile_Out.WriteInt("admin", "FTUserImpersonation", FTUserImpersonation);
myIniFile_Out.WriteInt("admin", "BlankMonitorEnabled", BlankMonitorEnabled);
myIniFile_Out.WriteInt("admin", "BlankInputsOnly", BlankInputsOnly); //PGM
myIniFile_Out.WriteInt("admin", "DefaultScale", DefaultScale);

myIniFile_Out.WriteInt("admin", "primary", Primary);
myIniFile_Out.WriteInt("admin", "secondary", Secondary);

	// Connection prefs
SocketConnect=myIniFile_In.ReadInt("admin", "SocketConnect", true);
HTTPConnect=myIniFile_In.ReadInt("admin", "HTTPConnect", true);
AutoPortSelect=myIniFile_In.ReadInt("admin", "AutoPortSelect", true);
PortNumber=myIniFile_In.ReadInt("admin", "PortNumber", 0);
HttpPortNumber=myIniFile_In.ReadInt("admin", "HTTPPortNumber",0);
IdleTimeout=myIniFile_In.ReadInt("admin", "IdleTimeout", 0);
IdleInputTimeout = myIniFile_In.ReadInt("admin", "IdleInputTimeout", 0);
myIniFile_Out.WriteInt("admin", "SocketConnect", SocketConnect);
myIniFile_Out.WriteInt("admin", "HTTPConnect", HTTPConnect);
myIniFile_Out.WriteInt("admin", "AutoPortSelect", AutoPortSelect);
myIniFile_Out.WriteInt("admin", "PortNumber", PortNumber);
myIniFile_Out.WriteInt("admin", "HTTPPortNumber", HttpPortNumber);
myIniFile_Out.WriteInt("admin", "IdleTimeout", IdleTimeout);
myIniFile_Out.WriteInt("admin", "IdleInputTimeout", IdleInputTimeout);

RemoveWallpaper=myIniFile_In.ReadInt("admin", "RemoveWallpaper", 0);
RemoveAero=myIniFile_In.ReadInt("admin", "RemoveAero", 0);
myIniFile_Out.WriteInt("admin", "RemoveWallpaper", RemoveWallpaper);
myIniFile_Out.WriteInt("admin", "RemoveAero", RemoveAero);

	// Connection querying settings
QuerySetting=myIniFile_In.ReadInt("admin", "QuerySetting", 0);
QueryTimeout=myIniFile_In.ReadInt("admin", "QueryTimeout", 0);
QueryDisableTime=myIniFile_In.ReadInt("admin", "QueryDisableTime", 0);
QueryAccept=myIniFile_In.ReadInt("admin", "QueryAccept", 0);
QueryIfNoLogon=myIniFile_In.ReadInt("admin", "QueryIfNoLogon", 0);
myIniFile_Out.WriteInt("admin", "QuerySetting", QuerySetting);
myIniFile_Out.WriteInt("admin", "QueryTimeout", QueryTimeout);
myIniFile_Out.WriteInt("admin", "QueryDisableTime", QueryDisableTime);
myIniFile_Out.WriteInt("admin", "QueryAccept", QueryAccept);
myIniFile_Out.WriteInt("admin", "QueryIfNoLogon", QueryIfNoLogon);

myIniFile_In.ReadPassword(passwd,MAXPWLEN);
myIniFile_Out.WritePassword(passwd);
memset(passwd, '\0', MAXPWLEN); //PGM
myIniFile_In.ReadPassword2(passwd,MAXPWLEN); //PGM
myIniFile_Out.WritePassword2(passwd); //PGM

EnableRemoteInputs=myIniFile_In.ReadInt("admin", "InputsEnabled", 0);
LockSettings=myIniFile_In.ReadInt("admin", "LockSetting", 0);
DisableLocalInputs=myIniFile_In.ReadInt("admin", "LocalInputsDisabled", 0);
EnableJapInput=myIniFile_In.ReadInt("admin", "EnableJapInput", 0);
EnableUnicodeInput=myIniFile_In.ReadInt("admin", "EnableUnicodeInput", 0);
EnableWin8Helper=myIniFile_In.ReadInt("admin", "EnableWin8Helper", 0);
kickrdp=myIniFile_In.ReadInt("admin", "kickrdp", 0);
clearconsole=myIniFile_In.ReadInt("admin", "clearconsole", 0);

myIniFile_Out.WriteInt("admin", "InputsEnabled", EnableRemoteInputs);
myIniFile_Out.WriteInt("admin", "LockSetting", LockSettings);
myIniFile_Out.WriteInt("admin", "LocalInputsDisabled", DisableLocalInputs);
myIniFile_Out.WriteInt("admin", "EnableJapInput", EnableJapInput);
myIniFile_Out.WriteInt("admin", "EnableUnicodeInput", EnableUnicodeInput);
myIniFile_Out.WriteInt("admin", "EnableWin8Helper", EnableWin8Helper);
myIniFile_Out.WriteInt("admin", "kickrdp", kickrdp);
myIniFile_Out.WriteInt("admin", "clearconsole", clearconsole);

TurboMode = myIniFile_In.ReadInt("poll", "TurboMode", 0);
PollUnderCursor=myIniFile_In.ReadInt("poll", "PollUnderCursor", 0);
PollForeground=myIniFile_In.ReadInt("poll", "PollForeground", 0);
PollFullScreen=myIniFile_In.ReadInt("poll", "PollFullScreen", 0);
PollConsoleOnly=myIniFile_In.ReadInt("poll", "OnlyPollConsole", 0);
PollOnEventOnly=myIniFile_In.ReadInt("poll", "OnlyPollOnEvent", 0);
MaxCpu=myIniFile_In.ReadInt("poll", "MaxCpu2", 0);
MaxFPS = myIniFile_In.ReadInt("poll", "MaxFPS", 0);
Driver=myIniFile_In.ReadInt("poll", "EnableDriver", 0);
Hook=myIniFile_In.ReadInt("poll", "EnableHook", 0);
Virtual=myIniFile_In.ReadInt("poll", "EnableVirtual", 0);

SingleWindow=myIniFile_In.ReadInt("poll","SingleWindow",SingleWindow);
myIniFile_In.ReadString("poll", "SingleWindowName", SingleWindowName,32);

myIniFile_Out.WriteInt("poll", "TurboMode", TurboMode);
myIniFile_Out.WriteInt("poll", "PollUnderCursor", PollUnderCursor);
myIniFile_Out.WriteInt("poll", "PollForeground", PollForeground);
myIniFile_Out.WriteInt("poll", "PollFullScreen", PollFullScreen);
myIniFile_Out.WriteInt("poll", "OnlyPollConsole",PollConsoleOnly);
myIniFile_Out.WriteInt("poll", "OnlyPollOnEvent", PollOnEventOnly);
myIniFile_Out.WriteInt("poll", "MaxCpu2", MaxCpu);
myIniFile_Out.WriteInt("poll", "MaxFPS", MaxFPS);
myIniFile_Out.WriteInt("poll", "EnableDriver", Driver);
myIniFile_Out.WriteInt("poll", "EnableHook", Hook);
myIniFile_Out.WriteInt("poll", "EnableVirtual", Virtual);

myIniFile_Out.WriteInt("poll", "SingleWindow", SingleWindow);
myIniFile_Out.WriteString("poll", "SingleWindowName", SingleWindowName);

myIniFile_Out.WriteInt("poll", "MaxCpu2", MaxCpu);
myIniFile_Out.WriteInt("poll", "MaxFPS", MaxFPS);

DeleteFile(lpCmdLine);
}
void
Real_settings(char *mycommand)
{
Copy_to_Secure_from_temp_helper(mycommand);
}

void
Set_stop_service_as_admin()
{
	char exe_file_name[MAX_PATH];
	GetModuleFileName(0, exe_file_name, MAX_PATH);

	SHELLEXECUTEINFO shExecInfo;

	shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	shExecInfo.fMask = NULL;
	shExecInfo.hwnd = GetForegroundWindow();
	shExecInfo.lpVerb = "runas";
	shExecInfo.lpFile = exe_file_name;
	shExecInfo.lpParameters = winvncStopservice;
	shExecInfo.lpDirectory = NULL;
	shExecInfo.nShow = SW_SHOWNORMAL;
	shExecInfo.hInstApp = NULL;
	ShellExecuteEx(&shExecInfo);
}

void
Real_stop_service()
{
    char command[MAX_PATH + 32]; // 29 January 2008 jdp
    _snprintf_s(command, sizeof command, "net stop \"%s\"", service_name);
	WinExec(command,SW_HIDE);
}

void
Set_start_service_as_admin()
{
	char exe_file_name[MAX_PATH];
	GetModuleFileName(0, exe_file_name, MAX_PATH);

	SHELLEXECUTEINFO shExecInfo;

	shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	shExecInfo.fMask = NULL;
	shExecInfo.hwnd = GetForegroundWindow();
	shExecInfo.lpVerb = "runas";
	shExecInfo.lpFile = exe_file_name;
	shExecInfo.lpParameters = winvncStartservice;
	shExecInfo.lpDirectory = NULL;
	shExecInfo.nShow = SW_SHOWNORMAL;
	shExecInfo.hInstApp = NULL;
	ShellExecuteEx(&shExecInfo);
}

void Open_homepage()
{
	ShellExecute(0, "open", "http://www.uvnc.com", 0, 0, 1);
}

void Open_forum()
{
	ShellExecute(0, "open", "http://forum.uvnc.com", 0, 0, 1);
}

void
Real_start_service()
{
    char command[MAX_PATH + 32]; // 29 January 2008 jdp
    _snprintf_s(command, sizeof command, "net start \"%s\"", service_name);
	WinExec(command,SW_HIDE);
}

void
Set_install_service_as_admin()
{
	char exe_file_name[MAX_PATH];
	GetModuleFileName(0, exe_file_name, MAX_PATH);

	SHELLEXECUTEINFO shExecInfo;

	shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	shExecInfo.fMask = NULL;
	shExecInfo.hwnd = GetForegroundWindow();
	shExecInfo.lpVerb = "runas";
	shExecInfo.lpFile = exe_file_name;
	shExecInfo.lpParameters = winvncInstallService;
	shExecInfo.lpDirectory = NULL;
	shExecInfo.nShow = SW_SHOWNORMAL;
	shExecInfo.hInstApp = NULL;
	ShellExecuteEx(&shExecInfo);
}

void
Set_uninstall_service_as_admin()
{
	char exe_file_name[MAX_PATH];
	GetModuleFileName(0, exe_file_name, MAX_PATH);

	SHELLEXECUTEINFO shExecInfo;

	shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	shExecInfo.fMask = NULL;
	shExecInfo.hwnd = GetForegroundWindow();
	shExecInfo.lpVerb = "runas";
	shExecInfo.lpFile = exe_file_name;
	shExecInfo.lpParameters = winvncUnInstallService;
	shExecInfo.lpDirectory = NULL;
	shExecInfo.nShow = SW_SHOWNORMAL;
	shExecInfo.hInstApp = NULL;
	ShellExecuteEx(&shExecInfo);
}

void
winvncSecurityEditorHelper_as_admin()
{
	char exe_file_name[MAX_PATH];
	GetModuleFileName(0, exe_file_name, MAX_PATH);

	SHELLEXECUTEINFO shExecInfo;

	shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	shExecInfo.fMask = NULL;
	shExecInfo.hwnd = GetForegroundWindow();
	shExecInfo.lpVerb = "runas";
	shExecInfo.lpFile = exe_file_name;
	shExecInfo.lpParameters = winvncSecurityEditor;
	shExecInfo.lpDirectory = NULL;
	shExecInfo.nShow = SW_SHOWNORMAL;
	shExecInfo.hInstApp = NULL;
	ShellExecuteEx(&shExecInfo);
}
void make_upper(std::string& str)
{
    // convert to uppercase
    std::transform(str.begin(), str.end(), str.begin(), toupper);//(int(*)(int))
}
//**************************************************************************
// GetServiceName() looks up service by application path. If found, the function
// fills pszServiceName (must be at least 256+1 characters long).
bool GetServiceName(TCHAR *pszAppPath, TCHAR *pszServiceName)
{
    // prepare given application path for matching against service list
    std::string appPath(pszAppPath);
    // convert to uppercase
    make_upper(appPath);

	// connect to serice control manager
    SC_HANDLE hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
    if (!hManager)
        return false;

    DWORD dwBufferSize = 0;
    DWORD dwCount = 0;
    DWORD dwPosition = 0;
    bool bResult = false;

    // call EnumServicesStatus() the first time to receive services array size
    BOOL bOK = EnumServicesStatus(
        hManager,
        SERVICE_WIN32,
        SERVICE_STATE_ALL,
        NULL,
        0,
        &dwBufferSize,
        &dwCount,
        &dwPosition);
    if (!bOK && GetLastError() == ERROR_MORE_DATA)
    {
        // allocate space per results from the first call
        ENUM_SERVICE_STATUS *pServices = (ENUM_SERVICE_STATUS *) new UCHAR[dwBufferSize];
        if (pServices)
        {
            // call EnumServicesStatus() the second time to actually get the services array
            bOK = EnumServicesStatus(
                hManager,
                SERVICE_WIN32,
                SERVICE_STATE_ALL,
                pServices,
                dwBufferSize,
                &dwBufferSize,
                &dwCount,
                &dwPosition);
            if (bOK)
            {
                // iterate through all services returned by EnumServicesStatus()
                for (DWORD i = 0; i < dwCount && !bResult; i++)
                {
                    // open service
                    SC_HANDLE hService = OpenService(hManager,
                        pServices[i].lpServiceName,
                        GENERIC_READ);
                    if (!hService)
                        break;

                    // call QueryServiceConfig() the first time to receive buffer size
                    bOK = QueryServiceConfig(
                        hService,
                        NULL,
                        0,
                        &dwBufferSize);
                    if (!bOK && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
                    {
                        // allocate space per results from the first call
                        QUERY_SERVICE_CONFIG *pServiceConfig = (QUERY_SERVICE_CONFIG *) new UCHAR[dwBufferSize];
                        if (pServiceConfig)
                        {
                            // call EnumServicesStatus() the second time to actually get service config
                            bOK = QueryServiceConfig(
                                hService,
                                pServiceConfig,
                                dwBufferSize,
                                &dwBufferSize);
                            if (bOK)
                            {
                                // match given application name against executable path in the service config
                                std::string servicePath(pServiceConfig->lpBinaryPathName);
                                make_upper(servicePath);
                                if (servicePath.find(appPath.c_str()) != -1)
                                {
                                    bResult = true;
                                    strncpy_s(pszServiceName, 256, pServices[i].lpServiceName, 256);
                                    pszServiceName[255] = 0;
                                }
                            }

                            delete [] (UCHAR *) pServiceConfig;
                        }
                    }

                    CloseServiceHandle(hService);
                }
            }

            delete [] (UCHAR *) pServices;
        }
    }

    // disconnect from serice control manager
    CloseServiceHandle(hManager);

    return bResult;
}
#endif
extern BOOL	m_fRunningFromExternalService;
DWORD MessageBoxSecure(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
{
	DWORD retunvalue;
	if (m_fRunningFromExternalService)
	{
		HDESK desktop=NULL;
		HDESK old_desktop;
		desktop = OpenInputDesktop(0, FALSE,DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
		old_desktop = GetThreadDesktop(GetCurrentThreadId());
		if (desktop && 	old_desktop && old_desktop!=desktop)
			{
					SetThreadDesktop(desktop);
					retunvalue=MessageBox(hWnd,lpText,lpCaption,uType);
					SetThreadDesktop(old_desktop);
					CloseDesktop(desktop);
			}
		else retunvalue=0;
	}
	else
	{
		retunvalue=MessageBox(hWnd,lpText,lpCaption,uType);
	}
	return retunvalue;
}