Click here to Skip to main content
15,894,315 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Is it possible to start a program before user log on to windows?

[In brief]
I have a service installed in my machine? Now from that machine I have to start a process?
Can anyone tell me how to do that? Here is my code, it is failing in ImpersonateLoggedOnUser with error code 6 as I have not called LogonUser(...) and it not possible without passwords.

I am stuck here, can any one give me any idea how to proceed from here!!!

C++
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
using namespace std;
#define ACCESS_FLAG KEY_WOW64_64KEY
TCHAR* serviceName = TEXT("Hello");
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
HANDLE stopServiceEvent = 0;
TCHAR InstallPath[MAX_PATH] = {0};
ofstream logfile;

void WINAPI ServiceControlHandler( DWORD controlCode )
{
	switch ( controlCode )
	{
		case SERVICE_CONTROL_INTERROGATE:
			break;

		case SERVICE_CONTROL_SHUTDOWN:
		case SERVICE_CONTROL_STOP:
			serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
			SetServiceStatus( serviceStatusHandle, &serviceStatus );

			SetEvent( stopServiceEvent );
			return;

		case SERVICE_CONTROL_PAUSE:
			break;

		case SERVICE_CONTROL_CONTINUE:
			break;

		default:
			if ( controlCode >= 128 && controlCode <= 255 )
				// user defined control code
				break;
			else
				// unrecognised control code
				break;
	}

	SetServiceStatus( serviceStatusHandle, &serviceStatus );
}

void WINAPI ServiceMain( DWORD /*argc*/, TCHAR* /*argv*/[] )
{
	// initialise service status
	serviceStatus.dwServiceType = SERVICE_WIN32;
	serviceStatus.dwCurrentState = SERVICE_STOPPED;
	serviceStatus.dwControlsAccepted = 0;
	serviceStatus.dwWin32ExitCode = NO_ERROR;
	serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
	serviceStatus.dwCheckPoint = 0;
	serviceStatus.dwWaitHint = 0;

	serviceStatusHandle = RegisterServiceCtrlHandler( serviceName, ServiceControlHandler );

	if ( serviceStatusHandle )
	{
		// service is starting
		serviceStatus.dwCurrentState = SERVICE_START_PENDING;
		SetServiceStatus( serviceStatusHandle, &serviceStatus );

		// do initialisation here
		stopServiceEvent = CreateEvent( 0, FALSE, FALSE, 0 );

		// running
		serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
		serviceStatus.dwCurrentState = SERVICE_RUNNING;
		SetServiceStatus( serviceStatusHandle, &serviceStatus );
		bool rc = false;
		HANDLE hUserToken = NULL;
		do
		{
			if (!ImpersonateLoggedOnUser(hUserToken))
			{
				DWORD rc = GetLastError();
				CloseHandle(hUserToken);
				logfile << "Error: ImpersonateLoggedOnUser() fail with error code "<< rc << endl;
				break;
			}

			STARTUPINFO             si;
			PROCESS_INFORMATION pi;

			memset(&si, 0, sizeof(si));
			memset(&pi, 0, sizeof(pi));

			si.cb = sizeof(si);

			rc = CreateProcessAsUser(hUserToken,                // user token
									0,                           // app name
									InstallPath,                   // command line
									0,                           // process attributes
									0,                           // thread attributes
									FALSE,                       // don't inherit handles
									DETACHED_PROCESS,            // flags
									0,                           // environment block
									0,                           // current dir
									&si,                         // startup info
									&pi);                        // process info gets put here


			if (!rc)
			{
				DWORD rc = GetLastError();
				RevertToSelf();
				CloseHandle(hUserToken);
				logfile << "Error: CreateProcessAsUser() fail" << endl;
				break;			
			}

			RevertToSelf();
			CloseHandle(hUserToken);
			Sleep(2000);
			rc = false;
			hUserToken = NULL;
		}
		while ( WaitForSingleObject( stopServiceEvent, 5000 ) == WAIT_TIMEOUT );

		// service was stopped
		serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
		SetServiceStatus( serviceStatusHandle, &serviceStatus );

		// do cleanup here
		CloseHandle( stopServiceEvent );
		stopServiceEvent = 0;

		// service is now stopped
		serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
		serviceStatus.dwCurrentState = SERVICE_STOPPED;
		SetServiceStatus( serviceStatusHandle, &serviceStatus );
	}
}

void RunService()
{
	SERVICE_TABLE_ENTRY serviceTable[] =
	{
		{ serviceName, ServiceMain },
		{ 0, 0 }
	};

	StartServiceCtrlDispatcher( serviceTable );
}

void InstallService()
{
	//First copy that exe file in program files...
	logfile <<"Installing Service" << endl;
	SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CREATE_SERVICE );

	if ( serviceControlManager )
	{
		TCHAR path[ _MAX_PATH + 1 ], InstallPath[ _MAX_PATH + 1 ] = {0};
		//lstrcpy(InstallPath, L"C:\\Program Files\\WinService\\WinServiceTest.exe");
		
		if ( GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0 )
		{
			//if( 0 == CopyFile(path, InstallPath, FALSE))
			//{
			//	//Fail
			//	MessageBox(NULL, L"Error", L"Please run as Admin", MB_OK);
			//	return ;
			//}

			SC_HANDLE service = CreateService( serviceControlManager,
							serviceName, serviceName,
							SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
							SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path,
							0, 0, 0, 0, 0 );
			if ( service )
				CloseServiceHandle( service );
		}

		CloseServiceHandle( serviceControlManager );
	}
}

void UninstallService()
{
	SC_HANDLE serviceControlManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT );

	if ( serviceControlManager )
	{
		SC_HANDLE service = OpenService( serviceControlManager,
			serviceName, SERVICE_QUERY_STATUS | DELETE );
		if ( service )
		{
			SERVICE_STATUS serviceStatus;
			if ( QueryServiceStatus( service, &serviceStatus ) )
			{
				if ( serviceStatus.dwCurrentState == SERVICE_STOPPED )
					DeleteService( service );
			}

			CloseServiceHandle( service );
		}

		CloseServiceHandle( serviceControlManager );
	}
}

//int _tmain( int argc, TCHAR* argv[] )
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
	logfile.open ("C:\\log.txt");
	ExpandEnvironmentStrings(L"%APPDATA%", InstallPath, MAX_PATH);
	lstrcat(InstallPath, L"\\Test\\");
	//CreateDirectory(InstallPath, NULL);
	lstrcat(InstallPath, L"message.exe");
	logfile << "Install PAth: " << InstallPath;
	HKEY hKey = NULL;
	DWORD dwRegOpenErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
				TEXT("SYSTEM\\CurrentControlSet\\services\\Hello"),
				(DWORD)NULL,
				ACCESS_FLAG | KEY_READ,
				&hKey);
	
	if(ERROR_SUCCESS == dwRegOpenErr)
	{
		RunService();
	}
	else
	{
		//MessageBox(NULL, L"Insatalling", L"installing", MB_OK);
		DWORD ff = GetLastError();
		InstallService();
		RunService();
	}
	//if(0 == strcmp("install", lpCmdLine))
	//	InstallService();

	////if(0 == strcmp("uninstall", lpCmdLine))
	////	UninstallService();

	//if(0 == strcmp("", lpCmdLine))
	//RunService();
	logfile.close();
	return 0;
}
Posted

1 solution

Yes you can start a program before a user is logged in, but the following need to be met:
- You have to have admin access to do the set up. The app will run with admin credentials.
- The app must not have a UI and not do anything to interact with a user.
- The app must not link to any libraries that have UI interaction.
- About a dozen other rules.

From cursory analysis, your program seems to possibly meet these criteria.

Your code:
C++
		HANDLE hUserToken = NULL;
		do
		{
			if (!ImpersonateLoggedOnUser(hUserToken))
			{
				DWORD rc = GetLastError();
				CloseHandle(hUserToken);
				logfile << "Error: ImpersonateLoggedOnUser() fail with error code "<< rc << endl;
				break;
			}
// ...

seems suspect. Reading the documentation on ImpersonateLoggedOnUser, I don't think the token can be NULL; also, this code seems to make sense in the context of a program running after somebody logs in.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900