CreateService or StartService hangs on windows 7 x64 - windows

CreateService or StartService hangs on windows 7 x64 when i trying to use it to register new service from service.
In service control manager my service, which i try to run, has status 'Starting'.
Code that try to create and run service:
SC_HANDLE hSCManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if(!hSCManager)
throw ::GetLastError();
SC_HANDLE hService = ::OpenService(hSCManager,
TEXT("ProcessManager"),
SERVICE_ALL_ACCESS);
if(!hService && ::GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
{
hService = ::CreateService(hSCManager, TEXT("ProcessManager"),
TEXT("ProcessManager"), SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, TEXT("C:\\processmanager.sys"),
NULL, NULL, NULL, NULL, NULL);
}
if(!hService ||
(!::StartService(hService, 0, NULL) && ::GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
{
::CloseServiceHandle(hSCManager);
if(hService)
::CloseServiceHandle(hService);
DWORD err = ::GetLastError();
throw err;
}
Please help :)

From the documentation for ServiceMain:
Do not attempt to start another service in the ServiceMain function.
and
The SCM locks the service control database during initialization, so if a service attempts to call StartService during initialization, the call will block. When the service reports to the SCM that it has successfully started, it can call StartService. If the service requires another service to be running, the service should set the required dependencies.
So, there's your problem: your program is deadlocking because it is calling StartService while the service control database is locked. (Actually, it is probably deadlocking on the CreateService call first; the documentation doesn't explicitly mention it, but the same restriction applies there too.)
Install the device driver at the same time that you install your service, rather than trying to install it from your service.

Related

Open a JobObject created in a service from a user session process

I have a windows service that creates a JobObject that i need to keep alive as long as the machine is turned on - the goal is to manage a few user session processes that can terminate/start at any time with this JobObject. I am creating it in a service to make sure the process is running at startup, and that it can't be killed by regular users.
However, i don't seem to be able to open a handle to this JobObject from the user session, I always get an access denied (5) error, despite going as far as creating it with a NULL DACL.
I have found a somewhat related question here: Open an Event object created by my service from my application, but for me, even with the NULL DACL, when asking for a JOB_OBJECT_ASSIGN_PROCESS right, i get access denied (asking for SYNCHRONIZE works for example).
The service code:
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(psd, TRUE, NULL, FALSE);
SECURITY_ATTRIBUTES secAttr= {0};
secAttr.nLength = sizeof(secAttr);
secAttr.bInheritHandle = false;
secAttr.lpSecurityDescriptor = psd;
hJobObject = CreateJobObject(&secAttr, SCL_JOBOBJECTNAME);
LocalFree(psd);
The user session code:
hJobObject = OpenJobObject(JOB_OBJECT_ASSIGN_PROCESS, FALSE, SCL_JOBOBJECTNAME);
if (hJobObject == NULL)
{
DWORD wError = GetLastError();
printf("Error: %d\n", wError); // this always pops 5
return 1;
}
Any ideas? As a test, i tried spawning a user session process from within the service, and assign the JobObject via the service code, and that worked,.. so i'm fairly certain its related to security settings i am missing, despite the NULL DACL.
if you create Job in service - this object by default will be have WinSystemLabelSid label SID: S-1-16-16384 - System Mandatory Level. (i just check this) so you need not only set Dacl but Sacl too. for example:
ULONG cb = MAX_SID_SIZE;
PSID LowLabelSid = (PSID)alloca(MAX_SID_SIZE);
if (CreateWellKnownSid(WinLowLabelSid, 0, LowLabelSid, &cb))
{
PACL Sacl = (PACL)alloca(cb += sizeof(ACL) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
InitializeAcl(Sacl, cb, ACL_REVISION);
if (AddMandatoryAce(Sacl, ACL_REVISION, 0, 0, LowLabelSid))
{
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
SetSecurityDescriptorSacl(&sd, TRUE, Sacl, FALSE);
SECURITY_ATTRIBUTES sa= { sizeof(sa), &sd, FALSE };
if (HANDLE hJob = CreateJobObject(&sa, L"Global\\{58BFC6DB-BE93-4cdb-919C-4C713ACB5A32}"))
{
CloseHandle(hJob);
}
}
}

windows service, can't have network access until user logon

I am trying to write a simple window service on window 7 64bit. The user account for the service is LocalSystem.
What I want to do is just a basic server/client socket program and the server exists in a windows service. The service just does a simple thing. When it starts, it creates a thread to listen on a port and wait for client connecting using window socket apis. But the problem is the client can't connect to the server until a user login the machine on which the service is running.
Below is my code for installing the service.
wchar_t szPath[MAX_PATH];
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath);
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
schService = CreateService(
schSCManager,
L"msdcontrol",
L"msd control",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
szPath,
NULL,
NULL,
NULL,
NULL,
NULL
);
What am i doing wrong?

CreateService Failing on windows 7

I am trying to install a service using CreateService API in Windows 7 64 bit.When CreateService API is called, it fails with Error code 1314 which is "A required privilege is not held by the client. ".
I am running Visual studio in Administrator mode. Any idea why it still failing when service is getting created by a process running in admin mode.
Also I am trying to create service with ACCESS_SYSTEM_SECURITY as one of desired access flag.CreateService is failing only when ACCESS_SYSTEM_SECURITY is passed otherwise its working fine.
Here is code
LUID luidSecurityPriv;
HANDLE hTokenProcCur;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenProcCur))
{
if (LookupPrivilegeValue(NULL, L"SeSecurityPrivilege", &luidSecurityPriv))
{
TOKEN_PRIVILEGES tp;
DWORD cbSinglePriv= sizeof(TOKEN_PRIVILEGES);
tp.PrivilegeCount= 1;
tp.Privileges[0].Luid= luidSecurityPriv;
tp.Privileges[0].Attributes= SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(hTokenProcCur,
FALSE,
&tp,
cbSinglePriv,
NULL,
NULL))
{
// actually register the NanoService with the OS here
SC_HANDLE schService = CreateService(schSCManager,
_T(SERVICE_NAME),
(LPCTSTR)strServiceName,
SERVICE_QUERY_STATUS | SERVICE_CHANGE_CONFIG | SERVICE_START | READ_CONTROL | WRITE_DAC | ACCESS_SYSTEM_SECURITY, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
strServicePath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService)
{
MessageBox(NULL,"CreateService Succeeded",L"",MB_OK);
}
else
MessageBox(NULL,"CreateService failed",L"",MB_OK);
}
}
}
The description for ACCESS_SYSTEM_SECURITY states the requirements for this access right:
The proper way to obtain this access is to enable the SE_SECURITY_NAME privilege in the caller's current access token, open the handle for ACCESS_SYSTEM_SECURITY access, and then disable the privilege.

Calls to a COM Server succeed under administrator account but fail under SYSTEM account

I am trying to query some data from a COM server (actually the Motorola MeshAPI), but it fails to initialize. Using the code snippet below, I get successful data when running on the command line as Administrator, but my actual program using this code runs as a service under the SYSTEM account. Using "psexec -i -s cmd.exe" I ran the snippet under the SYSTEM account, and I get the same errors I saw with the service.
It is the CreateInstance() call that fails, with an error message "Server execution failed" and error code 2148007941 (0x80080005).
Under the Windows Event Viewer, in the System pane I see errors with source "DCOM", event ID 10010, and description "The server {....GUID} did not register with DCOM within the required timeout."
I've tried the tips from this answer https://stackoverflow.com/a/1157331 , but I haven't found anything helpful in solving this.
What would cause this to work under Administrator but fail under SYSTEM, and how can I get it to work when running under SYSTEM?
HRESULT hr=S_OK;
USHORT nLinkResistance;
if (!m_MeshNetInitialised)
{
hr = m_pApiCardInterface.CreateInstance("MeshAPI.MeshNet");// mea interface smart pointer
if (SUCCEEDED(hr))
{
Sleep(1000);
m_MeshNetInitialised = true;
}
}
if (m_MeshNetInitialised)
{
hr = m_pApiCardInterface->GetIAPLinkResistance(&nLinkResistance);
if( SUCCEEDED(hr) )
{
l_retval = nLinkResistance;
}
else
{
std::wcout << L"Error getting IAPLinkResistance" << std::endl;
}
}
if (FAILED(hr))
{
_com_error err(hr);
std::wcout << err.ErrorMessage();
}

How can I add customized strings to the messages displayed by shutdown screen in Windows 7?

How can I add custom text to shutdown screen, like those messages that show when Windows is installing updates before shutting down? For example, you have a backup script that is executed on shutdown, and you want to inform about the progress of the backup just like Windows does when installing updates. Is there any command line tool for that, or some code library, or even something in Windows API?
Note that this is not about how to shutdown a computer, and it is not about whatever way to display a message there in shutdown screen, such as console applications or message boxes. This is not about customizing existing messages either, and it is not about any shutdown dialog that shows before shutdown screen and allows the user to cancel the shutdown or proceed without waiting for the programs to terminate.
This is about understanding how Windows implements the displaying of those messages the way they are displayed there in shutdown, and how to add new messages to be displayed, preferably with progress information. To be clear, below is a screenshot.
There is a function WmsgPostNotifyMessage in wmsgapi.dll which is displaying this message. Undocumented though, but shouldn't be a problem to use.
Here is a C++ code that can shutdown the computer with message.
#include <windows.h>
#pragma comment( lib, "advapi32.lib" )
BOOL MySystemShutdown( LPTSTR lpMsg )
{
HANDLE hToken; // handle to process token
TOKEN_PRIVILEGES tkp; // pointer to token structure
BOOL fResult; // system shutdown flag
// Get the current process token handle so we can get shutdown
// privilege.
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
// Get the LUID for shutdown privilege.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get shutdown privilege for this process.
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
// Cannot test the return value of AdjustTokenPrivileges.
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
// Display the shutdown dialog box and start the countdown.
fResult = InitiateSystemShutdown(
NULL, // shut down local computer
lpMsg, // message for user
30, // time-out period, in seconds
FALSE, // ask user to close apps
TRUE); // reboot after shutdown
if (!fResult)
return FALSE;
// Disable shutdown privilege.
tkp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
return TRUE;
}

Resources