Run an executable as service in C++ - c++

I created a Win32Console application using MSVS2013 and it was compiled successfully. Now I tried creating a service using CreateService and binary path was set to the path of the above produced executable. Though I was able to create the service, I cannot start it using StartService. The error code 1053 is thrown each time. I tried using sc.exe and also tried to start the service manually from Services. The same error is shown. How can I solve it now?

You must create a ServiceMain.
Here is a sample.
If you want to execute a non-service application you can use psexec.

You have collision with SC- manager and your function inside application start service
your name of the function service dispatcher table for service;)
prevent from error 1053 if call was send not from SC - manager
C++ code:
if(argc < 2)
{
if(!Service_Dispatcher_Table())
{
std::cout<<"ERROR :"<< GetLastError();
}
}
else
{
//your command line "argc"
}
//here your commands or function : startservice();

Related

How do I run a program from cpp the same way as I would do it via launch as admin in explorer?

I'm unpacking a executable from my UWP application and storing them in the LocalState folder. Then I launch a dedicated fullTrust utility and try to execute this program as administrator. This fails.
If and only if I launch the same exe via the explorer, by clicking on "Run as administrator" it works.
With other exe which are lying in different folders it works flawless.
The code I'm using to launch is:
SHELLEXECUTEINFO shExInfo;
ZeroMemory(&shExInfo, sizeof(shExInfo));
shExInfo.cbSize = sizeof(shExInfo); // structure size
shExInfo.fMask = mask; // execution flags
shExInfo.lpVerb = _T("runas"); // run elevated
shExInfo.lpFile = szExe; // application to start
shExInfo.lpParameters = params; // some params
shExInfo.lpDirectory = nullptr; // current working directory
shExInfo.nShow = show; // show/hide the application
ShellExecuteEx(&shExInfo) // This returns false, thus meaning a failure to start the exe
Why is it failing if I launch it as administrator from my cpp, but not from explorer. And how do I solve this problem?
Turns out my code works the way I expected it, the problem was that it was parsing the path incorrectly, thus failing to launch it.

CryptAcquireContext failing with ERROR_FILE_NOT_FOUND (2L) when user not logged on Windows 8.1

I am having a hard time migrating a C++ CryptoAPI-based application that currently runs on Windows Server 2008 to Windows 8.1. The scenario is:
This application is eventually triggered by WatchDog.exe, which in its turn is triggered when the computer is started by Windows' Task Scheduler.
Task Scheduler uses the following rules to start the WatchDog.exe:
A Administrator User Account;
Run Whether user is logged on or not;
UNCHECKED: Do not store password. The task will only have access to
local resources;
Run with Highest Privileges;
Configure for Win 8.1;
Triggered at system startup.
The server sits there, nobody logged, until in a given scenario WatchDog.exe starts the application. Application log confirms that the owner of the process (GetUserName) is the very same user Task Scheduler used to trigger WatchDog.exe.
It turns out that this application works fine in Windows Server 2008, but in windows 8.1 a call to CryptAcquireContext fails with return code ERROR_FILE_NOT_FOUND (2L). The odd thing is that the application will NOT fail if, when started, the user is physically logged onthe machine, although it was not the user who started the application manually.
I took a look at the documentation and found:
"The profile of the user is not loaded and cannot be found. This
happens when the application impersonates a user, for example, the
IUSR_ComputerName account."
I had never heard of impersonification, so I made a research and found the APIs LogonUser, ImpersonateLoggedOnUser and RevertToSelf. I then updated the application in this way:
...
HANDLE hToken;
if (! LogonUser(L"admin", L".", L"XXXXXXXX", LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hToken))
{
logger->log (_T("Error logging on."));
}
else
{
logger->log (PMLOG_LEVEL_TRACE, _T("Logged on."));
if (! ImpersonateLoggedOnUser(hToken))
{
logger->log (_T("Error impersonating."));
}
else
{
logger->log (_T("Impersonated."));
err = XXXXXXXXX(); // calls function which will execute CryptAcquireContext
if (! RevertToSelf())
{
logger->log (_T("Error reverting."));
}
else
{
logger->log (_T("Reverted."));
}
}
}
...
Excerpt with the call to CryptAcquireContext:
...
//---------------------------------------------------------------
// Get the handle to the default provider.
if(! CryptAcquireContext(&hCryptProv, cryptContainerName, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
DWORD e = GetLastError();
_stprintf_s (logMsg, 1000, _T("Error %ld acquiring cryptographic provider."), e);
cRSALogger->log (logMsg);
return ERR_CCRYPT_NO_KEY_CONTAINER;
}
cRSALogger->log (_T("Cryptographic provider acquired."));
...
As the result, I got the log:
...
[2015/01/08 20:53:25-TRACE] Logged on.
[2015/01/08 20:53:25-TRACE] Impersonated.
...
[2015/01/08 20:53:26-ERROR] Error 2 acquiring cryptographic provider.
...
[2015/01/08 20:53:26-TRACE] Reverted.
...
That seems to show that impersonation is working properly, but still I get Error 2 (ERROR_FILE_NOT_FOUND) on CryptAcquireContext.
Summary:
On Windows Server 2008, the very same application runs properly even
without the calls to LogonUser/Impersonate/Revert.
On Windows 8.1, the application, with or without the calls to
LogonUser/Impersonate/Revert, will only work properly if the user is logged on (which is not acceptable).
Any thoughts where I can run to in order to get this working on windows 8.1?
Thank in advance,
Dan

.vbs file not working properly from windows service

I created a windows service in C++ which runs a VBScript file on a particular event. This works fine when I do this from a Win32 application in C++, but doesn't work the same way from windows service.
Code of CPP file:
SHELLEXECUTEINFO ExecuteInfo;
memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
ExecuteInfo.cbSize = sizeof(ExecuteInfo);
ExecuteInfo.fMask = 0;
ExecuteInfo.hwnd = 0;
ExecuteInfo.lpVerb = _T("open"); // Operation to perform
ExecuteInfo.lpFile = _T("D:\\demo.vbs"); // Application name
ExecuteInfo.lpParameters = 0; // Additional parameters
ExecuteInfo.lpDirectory = 0; // Default directory
ExecuteInfo.nShow = SW_SHOW;
ExecuteInfo.hInstApp = 0;
if(ShellExecuteEx(&ExecuteInfo) == FALSE)
{
}
Assuming objShell.Windows is an instance of "Shell.Application", what you get is according to msdn
ShellWindows object: Represents a collection of the open windows that
belong to the Shell. Methods associated with this objects can control
and execute commands within the Shell, and obtain other Shell-related
objects.
The critical part is that belong to the Shell. Your problem is that the shell in your desktop is different from the shell that the services in your machine have.
Services run in a separate session.
So, your script is correctly working. It doesn't return any shell window because there is no one in the session where the services are running.
I created a normal exe instead of windows service and added that to windows startup registory.
That way i was able to achieve desired.

Issue with CQN registration getting dropped implictly

Using custom C++ OCI wrappers, I can successful register a CQN C++ callback-based registration, but it appears that somehow the subscription is dropped right away, behind my back. I get no call back on simple DMLs. If I try to unregister that subscription, for which register() worked just fine, I get ORA-29970: Specified registration id does not exist.
I'm running this test on a Win7 (64-bit) box, running a local 11.2.0.1.0 Oracle Server, and I connect with a C++ client app built against instantclient-11.2.0.2.0 that runs on that same machine.
I tried setting OCI_ATTR_SUBSCR_TIMEOUT explicitly to 0, to no avail.
I checked the job_queue_processes instance param to make sure it's not 0 (it's 1000).
Of course, the user/schema I'm connecting with has been granted CHANGE NOTIFICATION
I'm running out of ideas on this issue, and I would appreciate some insights on what else I could try or check.
I'm starting to wonder if CQN needs to be activated somehow. My DBA skills are close to nonexistent, this is a stock install of 11gR1 on Windows using the installer, with no special configurations or customization done at all.
Thanks, --DD
Update #1
A colleague successfully ran that same test, and he ran it using the server-provided oci.dll. I tried that (I build using instantclient, but forced the PATH at runtime: Path=D:\oracle\product\11.2.0\dbhome_1\BIN;$(Path) in VS Property Page> Debugging> Environment), and indeed the CQN test works! We still haven't figured out whether the slight version difference between client and server, or using instantclient (the Light variant by the way) vs a full client vs a server install is the real culprit.
But it is bad news that a newer instantclient does not support CQN...
Update #2
I've tried all 6 combinations of instantclient Light (65 MB) or Normal (150 MB) in versions 12.2.0.(1|2|3).0 on Win64, and none of them worked. Haven't tested the Full Client yet, nor have we tested on Linux just yet.
Environment_var cqn_env = Environment::create(OCI_EVENTS + OCI_OBJECT);
Connection_var cqn_conn = Connection::logon2(...);
Subscription sub(cqn_conn, "cqn_test", OCI_SUBSCR_NAMESPACE_DBCHANGE);
sub.set<attr::SUBSCR_CALLBACK>( &cqn_callback_func );
sub.set<attr::SUBSCR_CQ_QOSFLAGS>( OCI_SUBSCR_CQ_QOS_QUERY );
try {
sub.register_self();
} catch (const OracleException& ex) {
BOOST_REQUIRE(ex.error_code && *ex.error_code == 29972);
cerr << "\nSKIPPED: test requires CHANGE NOTIFICATION privilege" << endl;
return;
}

Problem with Custom TFS Web Service Plugin

i'm not sure that what im going to do is the right so i first of all tell you my issue.
I have TFS as Bugtracking System and another system for tracking the worktime. I want that if a workitem status changes the other system changes the status too.
What i did until now is the following.
I wrote a plugin for the TFS web service were i catch the WorkItemChangedEvent.
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs,
out int statusCode, out string
statusMessage, out ExceptionPropertyCollection properties)
{
statusCode = 0;
properties = null;
statusMessage = String.Empty;
try
{
if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
{
WorkItemChangedEvent ev = notificationEventArgs as WorkItemChangedEvent;
EventLog.WriteEntry("WorkItemChangedEventHandler", "WorkItem " + ev.WorkItemTitle + " was modified");
}
}
catch (Exception)
{
}
return EventNotificationStatus.ActionPermitted;
}
I droped the DLL in C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\bin\Plugins
but i looks like the extension is never called. So nothing apears in the event log.
But if i try to debug the service like in this post http://geekswithblogs.net/jakob/archive/2010/10/27/devleoping-and-debugging-server-side-event-handlers-in-tfs-2010.aspx
i cant hook on the process. So debugging does not work.
Why i cant debug the service? And is there a better way to do this?
Not sure if you fixed this but to me it looks like you are missing the Subscription method in the class.
public Type[] SubscribedTypes()
{
return new Type[1] {typeof(WorkItemChangedEvent)};
}
Without this your plugin will never get hit thus you will be unable to debug.
To debug the w3wp.exe process, you need to be running Visual Studio as an administrator.
From the menu, select Debug > Attach to process (or Ctrl-Alt-P)
Select Show processes from all users and Show processes in all sessions.
Find the w3wp.exe process that corresponds to your TFS Application Pool, and attach to it.
I notice that you're using EventLog.WriteEntry() - have you registered the event source previously in your code? To avoid the registration (which requires admin permissions), you might try using the TFS logger:
TeamFoundationApplication.Log("WorkItem " + ev.WorkItemTitle + " was modified", 0, System.Diagnostics.EventLogEntryType.Information);