@Brock, thank you.
Code: Select all// MyService.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "resource.h"
#include <Windows.h>
#include <WtsApi32.h>
#include <UserEnv.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <winternl.h>
#include <psapi.h>
#include <iostream>
#include <stdio.h>
using namespace std;
#pragma comment(lib, "WtsApi32.lib")
#pragma comment(lib, "UserEnv.lib")
#pragma comment(lib, "shlwapi.lib")
#define MY_SERVICE_NAME L"MyService"
#define MY_SERVICE_DESCRIPTOR L"MyService description"
#define MY_SERVICE_BIN_NAME L"MyService.exe"
#define MY_APPLICATION_BIN_NAME L"Project1.exe"
enum WINSTA0_DESKTOP
{
WINSTA0_DEFAULT,
WINSTA0_WINLOGON
};
BOOL StartSystemUserProcess(
wchar_t *pszCmd,
wchar_t *pszParam,
WINSTA0_DESKTOP winstaDesktop,
DWORD *pdwExitCode,
BOOL bWaitTerm,
DWORD dwWaitMs)
{
wchar_t szCmd[MAX_PATH];
DWORD dwDirSize = sizeof(szCmd);
STARTUPINFO si;
BOOL bResult = FALSE;
BOOL bReturn = FALSE;
DWORD dwSessionId = 0xf, winlogonPid = 0xf;
HANDLE hUserToken, hUserTokenDup, hPToken, hProcess;
DWORD dwCreationFlags;
PROCESSENTRY32 procEntry;
PROCESS_INFORMATION pi;
StringCchPrintf(szCmd, MAX_PATH, L"\"%s\" %s", pszCmd, pszParam);
dwSessionId = WTSGetActiveConsoleSessionId();
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE) return FALSE;
procEntry.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnap, &procEntry)) return FALSE;
do {
if (_wcsicmp(procEntry.szExeFile, L"winlogon.exe") == 0) {
DWORD winlogonSessId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId)
&& winlogonSessId == dwSessionId) {
winlogonPid = procEntry.th32ProcessID;
break;
}
}
} while (Process32Next(hSnap, &procEntry));
WTSQueryUserToken(dwSessionId, &hUserToken);
dwCreationFlags = DEBUG_PROCESS;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
switch (winstaDesktop) {
case WINSTA0_DEFAULT:
si.lpDesktop = L"winsta0\\default";
break;
case WINSTA0_WINLOGON:
si.lpDesktop = L"winsta0\\WinLogon";
break;
default:
si.lpDesktop = L"winsta0\\default";
break;
}
ZeroMemory(&pi, sizeof(pi));
TOKEN_PRIVILEGES tp;
LUID luid;
hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid);
bResult = OpenProcessToken(
hProcess,
TOKEN_ADJUST_PRIVILEGES |
TOKEN_QUERY |
TOKEN_DUPLICATE |
TOKEN_ASSIGN_PRIMARY |
TOKEN_ADJUST_SESSIONID |
TOKEN_READ |
TOKEN_WRITE,
&hPToken);
if (!bResult) {
printf("\n OpenProcessToken error - %d \n", GetLastError());
}
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
printf("\n LookupPrivilegeValue error - %d \n", GetLastError());
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hUserTokenDup);
SetTokenInformation(hUserTokenDup, TokenSessionId, (void*)dwSessionId, sizeof(DWORD));
bResult = AdjustTokenPrivileges(
hUserTokenDup,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
NULL);
if (!bResult) {
printf("\n AdjustTokenPrivileges error - %d \n", GetLastError());
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
printf("\n ERROR_NOT_ALL_ASSIGNED: Token does not have the privilege. \n");
}
LPVOID pEnv = NULL;
if (CreateEnvironmentBlock(&pEnv, hUserTokenDup, TRUE)) {
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
}
else {
pEnv = NULL;
}
bResult = CreateProcessAsUser(
hUserTokenDup,
NULL,
szCmd,
NULL,
NULL,
FALSE,
dwCreationFlags,
pEnv,
NULL,
&si,
&pi);
bReturn = bResult ? TRUE : FALSE;
if (bWaitTerm == TRUE) {
if (WaitForSingleObject(pi.hProcess, dwWaitMs) == WAIT_OBJECT_0) {
if (pdwExitCode) {
GetExitCodeProcess(pi.hProcess, pdwExitCode);
}
}
}
CloseHandle(pi.hThread);
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);
//===========================================================================================================================================
int Stop = 0;
DEBUG_EVENT DebugEv = { 0 };
DWORD dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
while (!Stop)
{
WaitForDebugEvent(&DebugEv, INFINITE);
switch (DebugEv.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
{
switch (DebugEv.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
break;
case EXCEPTION_BREAKPOINT:
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
break;
case EXCEPTION_SINGLE_STEP:
break;
case DBG_CONTROL_C:
break;
default:
break;
}
break;
}
case CREATE_THREAD_DEBUG_EVENT:
break;
case CREATE_PROCESS_DEBUG_EVENT:
{
if (DebugEv.u.CreateProcessInfo.hFile)
CloseHandle(DebugEv.u.CreateProcessInfo.hFile);
}
break;
case EXIT_THREAD_DEBUG_EVENT:
break;
case EXIT_PROCESS_DEBUG_EVENT:
Stop = 1;
break;
case LOAD_DLL_DEBUG_EVENT:
{
if (DebugEv.u.LoadDll.hFile)
CloseHandle(DebugEv.u.LoadDll.hFile);
}
break;
case UNLOAD_DLL_DEBUG_EVENT:
break;
case OUTPUT_DEBUG_STRING_EVENT:
break;
}
ContinueDebugEvent(DebugEv.dwProcessId, DebugEv.dwThreadId, dwContinueStatus);
}
CloseHandle(pi.hProcess);
return bReturn;
}
BOOL InstallMyService()
{
WCHAR strServ[MAX_PATH] = { 0 };
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPCTSTR lpszBinaryPathName;
GetModuleFileName(NULL, strServ, MAX_PATH);
PathRemoveFileSpec(strServ);
wcscat(strServ, L"\\"MY_SERVICE_BIN_NAME);
if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
return (TRUE);
lpszBinaryPathName = strServ;
schService = CreateService(schSCManager, MY_SERVICE_NAME, MY_SERVICE_DESCRIPTOR,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
lpszBinaryPathName, NULL, NULL, NULL, NULL, NULL);
if (schService == NULL)
return (FALSE);
if (schService)
{
StartService(schService, 0, NULL);
}
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return (TRUE);
}
BOOL DeleteMyService()
{
SC_HANDLE schSCManager;
SC_HANDLE hService;
if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
return (FALSE);
if ((hService = OpenService(schSCManager, MY_SERVICE_NAME, SERVICE_ALL_ACCESS)) == NULL)
return (FALSE);
if (!DeleteService(hService))
return (FALSE);
if (!CloseServiceHandle(hService))
return (FALSE);
if (!CloseServiceHandle(schSCManager))
return (FALSE);
return (TRUE);
}
bool IsServiceInstalled(LPWSTR ServiceName)
{
bool serviceInstalled = false;
SC_HANDLE scm_handle = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
if (scm_handle)
{
SC_HANDLE service_handle = OpenService(scm_handle, ServiceName, SERVICE_INTERROGATE);
if (service_handle != NULL)
{
wprintf(L"Service Installed\n");
serviceInstalled = true;
CloseServiceHandle(service_handle);
}
else
{
wprintf(_T("OpenService failed - service not installed\n"));
}
CloseServiceHandle(scm_handle);
}
else
wprintf(_T("OpenService couldn't open - service not installed\n"));
return serviceInstalled;
}
SERVICE_STATUS g_ServiceStatus;
SERVICE_STATUS_HANDLE g_ServiceStatusHandle;
BOOL bRunning = true;
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
switch (Opcode)
{
case SERVICE_CONTROL_PAUSE:
g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
bRunning = false;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
g_ServiceStatus.dwServiceType = SERVICE_WIN32;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
g_ServiceStatusHandle = RegisterServiceCtrlHandler(MY_SERVICE_NAME, ServiceCtrlHandler);
if (g_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
return;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
//============================================================================================
WCHAR strApp[MAX_PATH] = { 0 };
GetModuleFileName(NULL, strApp, MAX_PATH);
PathRemoveFileSpec(strApp);
wcscat(strApp, L"\\"MY_APPLICATION_BIN_NAME);
StartSystemUserProcess(strApp, L"", WINSTA0_DESKTOP::WINSTA0_DEFAULT, 0, FALSE, 0);
//============================================================================================
bRunning = true;
while (bRunning)
{
Sleep(3000);
}
}
int main(int argc, char* argv[])
{
HWND hWnd = GetConsoleWindow();
ShowWindow(hWnd, SW_HIDE);
if (!IsServiceInstalled(MY_SERVICE_NAME)){
if (InstallMyService())
printf("\nService correctly installed\n");
else
printf("\nService uncorrectly installed\n");
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[] = { { MY_SERVICE_NAME, ServiceMain }, { NULL, NULL } };
StartServiceCtrlDispatcher(DispatchTable);
}
return (EXIT_SUCCESS);
}