Whenever I try to stop my service through the services manager, I get the following error and the service stays in a started state. "Could not stop the service on Local Computer. The service did not return an error. This could be an internal Windows error or an internal service error."
I've had such trouble with this issue that I tried to follow the logic from Microsoft as best as I could.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb540474(v=vs.85).aspx
There is a similar issue with this in .Net 1.1 that you'll find if you search; however, I'm not using the framweork at all.
void WINAPI serviceCtrlHandler(DWORD dwCtrl )
{
switch(dwCtrl)
{
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
SetEvent(stopEvent);
ReportSvcStatus(serviceStatus->dwCurrentState, NO_ERROR, 0);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
void WINAPI startMain(DWORD argc, LPTSTR *argv)
{
serviceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, serviceCtrlHandler);
serviceStatus->dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus->dwServiceSpecificExitCode = NO_ERROR;
if (serviceStatusHandle == 0)
{
debug->DebugMessage(L"RegisterServiceCtrlHandler() failed, error: " + Error::GetErrorMessageW(GetLastError()));
return;
}
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
if (!SetServiceStatus(serviceStatusHandle, serviceStatus))
{
//debug->DebugMessage(L"SetserviceStatus() failed, error: " + Error::GetErrorMessageW(GetLastError()));
//return;
}
stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
boost::thread dust_main_thread(dust_main);
while(1)
{
WaitForSingleObject(stopEvent, INFINITE);
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
}
VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
serviceStatus->dwCurrentState = dwCurrentState;
serviceStatus->dwWin32ExitCode = dwWin32ExitCode;
serviceStatus->dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
serviceStatus->dwControlsAccepted = 0;
else serviceStatus->dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
serviceStatus->dwCheckPoint = 0;
else
serviceStatus->dwCheckPoint = dwCheckPoint++;
SetServiceStatus(serviceStatusHandle, serviceStatus);
}
Run the service and then attach the debugger to the running process. Put a breakpoint at the serviceCtrlHandler and after the WaitForSingleObject(stopEvent, INFINITE) -- make sure what you think should happen does.
Related
How can I use NotifyServiceStatusChange properly so I can get notified when the service specified is deleted? My current code successfully stops the service and marks it for deletion. However, I want to be notified when the service is fully deleted.
Here are the main points of my code:
SC_HANDLE SCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
HANDLE EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
SERVICE_NOTIFY ServiceNotify;
ServiceNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
ServiceNotify.pszServiceNames = ServiceName;
ServiceNotify.pContext = &EventHandle;
ServiceNotify.pfnNotifyCallback = (PFN_SC_NOTIFY_CALLBACK)CallbackFunction;
DWORD status = NotifyServiceStatusChangeW(SCManager, SERVICE_NOTIFY_DELETED, &ServiceNotify);
WaitForSingleObject(EventHandle, INFINITE);
CloseServiceHandle(SCManager);
CloseHandle(EventHandle);
(ServiceName is WCHAR*)
CallbackFunction code:
VOID CALLBACK CallbackFunction(IN PVOID pParameter) {
SERVICE_NOTIFY* ServiceNotify = pParameter;
HANDLE EventHandle = *(HANDLE*)ServiceNotify->pContext;
SetEvent(EventHandle);
}
NotifyServiceStatusChange is returning ERROR_SUCCESS (0). However, my callback function is not being called at all. How can I fix this?
Edit:
Here is minimal reproducible code:
void ErrorExit(char* FunctionName, unsigned long ErrorCode) {
char* ErrorMessage;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, ErrorCode, LANG_USER_DEFAULT, (LPTSTR)&ErrorMessage, 0, NULL);
int MessageSize = (strlen(ErrorMessage) + strlen(FunctionName) + 50) * sizeof(char);
char* FullMessage = malloc(MessageSize);
sprintf_s(FullMessage, MessageSize, "%s failed with error %d: %s", FunctionName, ErrorCode, ErrorMessage);
MessageBoxA(NULL, FullMessage, "Error", MB_OK);
ExitProcess(ErrorCode);
}
PFN_SC_NOTIFY_CALLBACK CallbackFunction(PVOID pParameter) {
printf("CallbackFunction has been called.\r\n");
SERVICE_NOTIFY* ServiceNotify = pParameter;
HANDLE EventHandle = ServiceNotify->pContext;
if (!SetEvent(EventHandle)) {
ErrorExit("SetEvent", GetLastError());
}
}
int main()
{
WCHAR* ServiceName = L"SERVICE NAME"; // Input service name here
SC_HANDLE SCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
if (!SCManager) {
ErrorExit("OpenSCManagerW", GetLastError());
}
SC_HANDLE ServiceHandle = OpenServiceW(SCManager, ServiceName,
SERVICE_ENUMERATE_DEPENDENTS | SERVICE_STOP | DELETE);
if (!ServiceHandle) {
ErrorExit("ServiceHandle", GetLastError());
}
if (!DeleteService(ServiceHandle)) {
ErrorExit("DeleteService", GetLastError());
}
if (!CloseServiceHandle(ServiceHandle)) {
ErrorExit("CloseServiceHandle", GetLastError());
}
HANDLE EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!EventHandle) {
ErrorExit("CreateEventW", GetLastError());
}
SERVICE_NOTIFY ServiceNotify;
ServiceNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
ServiceNotify.pszServiceNames = ServiceName;
ServiceNotify.pContext = EventHandle;
ServiceNotify.pfnNotifyCallback = CallbackFunction;
DWORD status = NotifyServiceStatusChangeW(SCManager, SERVICE_NOTIFY_DELETED, &ServiceNotify);
if (status != ERROR_SUCCESS) {
ErrorExit("NotifyServiceStatusChangeW", GetLastError());
}
status = WaitForSingleObjectEx(EventHandle, INFINITE, TRUE);
if (status == WAIT_FAILED) {
ErrorExit("WaitForSingleObjectEx", GetLastError());
}
printf("WaitForSingleObjectEx Result: %lu\r\n", status);
system("pause");
return 0;
}
When I run this, no other service depends on the service being deleted, and the service being deleted is already stopped. My error handling function "ErrorExit" is never called. Nothing is printed on the screen. My program simply pauses, which I assume is from WaitForSingleObjectEx.
I know the service is being deleted because I have ProcessHacker open, and it is giving me notifications that the service is being deleted.
NotifyServiceStatusChange is returning ERROR_SUCCESS (0). However, my callback function is not being called at all.
The NotifyServiceStatusChangeW documentation says:
When the service status changes, the system invokes the specified callback function as an asynchronous procedure call (APC) queued to the calling thread. The calling thread must enter an alertable wait (for example, by calling the SleepEx function) to receive notification. For more information, see Asynchronous Procedure Calls.
So, make sure you are actually processing APC notifications while you wait. WaitForSingleObject() will not do that for you.
Use WaitForSingleObjectEx() instead. It has a bAlertable parameter you can set to TRUE. You will have to call it in a loop, since it will return when any APC call is processed by the calling thread, which may not be the one you are expecting.
You also need to call NotifyServiceStatusChangeW() in a loop, too. The documentation does not mention this, but the callback will be called only 1 time per use. Once the callback is called, you need to call NotifyServiceStatusChangeW() again to receive another notification if the current one is not the event you are expecting.
With that said, try something more like this:
struct MyCallbackInfo {
HANDLE EventHandle;
LPCWSTR pszServiceName;
bool bDeleted;
};
...
VOID CALLBACK CallbackFunction(PVOID pParameter) {
SERVICE_NOTIFYW* ServiceNotify = (SERVICE_NOTIFYW*) pParameter;
MyCallbackInfo *ci = (MyCallbackInfo*) ServiceNotify->pContext;
if (ServiceNotify->dwNotificationStatus == ERROR_SUCCESS) {
LPWSTR pServiceName = ServiceNotify->pszServiceNames;
while (*pServiceName != L'\0') {
if (lstrcmpW(pServiceName, ci->pszServiceName) == 0) {
ci.bDeleted = true;
break;
}
pServiceName += (lstrlenW(pServiceName) + 1);
}
LocalFree(ServiceNotify->pszServiceNames);
}
SetEvent(ci->EventHandle);
}
...
MyCallbackInfo ci;
ci.EventHandle = CreateEventW(NULL, TRUE, FALSE, NULL);
ci.pszServiceName = ServiceName;
ci.bDeleted = false;
if (!ci.EventHandle) {
// error handling...
}
SC_HANDLE SCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
if (!SCManager) {
// error handling...
}
SERVICE_NOTIFYW ServiceNotify = {};
ServiceNotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
ServiceNotify.pContext = &ci;
ServiceNotify.pfnNotifyCallback = CallbackFunction;
DWORD status;
do {
status = NotifyServiceStatusChangeW(SCManager, SERVICE_NOTIFY_DELETED, &ServiceNotify);
if (status != ERROR_SUCCESS) {
// error handling...
}
while ((status = WaitForSingleObjectEx(ci.EventHandle, INFINITE, TRUE)) == WAIT_IO_COMPLETION);
if (status == WAIT_FAILED) {
// error handling...
}
if (ci.bDeleted) {
// service has been deleted ...
break;
}
ResetEvent(ci.EventHandle);
}
while (true);
CloseServiceHandle(SCManager);
CloseHandle(ci.EventHandle);
I am creating an application which track the System startup time.
I tried GetTickcount() method and WMI query.In both cases I got the same solution.
But the time that I obtained is different from actual startup time.
By researching I found that because of fast startup option enabled in power option the system is not going for boot when we shutdown it.
Thing that I needed is time actual startup time.How can we get the actual startup time using C++?
I shut downed the system and turned ON it on 24-Jun-20, 8:22:05 AM but boot time that I got is 22-Jun-20, 5:11:05 PM
When the fast startup option enabled, click start menu -> shutdown will put the machine into sleep mode/hibernation instead of shutdown. But restart menu isn't affected. (And shutting down from command line isn't affected too as my test). So, boot time will not be reset.
You could try the following methods:
Turn off the "fast startup" option.
Add a task to the task schedule to log the time when the system start.
Read the Windows Event Log:
Event ID 27 records the kernel boot events. As you can see in the picture, boot type 0x1 means it was a fast startup. You could just read the newest one and get the create time.
Sample(Refer to this sample document: Querying for Events):
#include <windows.h>
#include <sddl.h>
#include <stdio.h>
#include <winevt.h>
#pragma comment(lib, "wevtapi.lib")
#define ARRAY_SIZE 1
#define TIMEOUT 1000 // 1 second; Set and use in place of INFINITE in EvtNext call
DWORD PrintResults(EVT_HANDLE hResults);
DWORD PrintEvent(EVT_HANDLE hEvent); // Shown in the Rendering Events topic
void main(void)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hResults = NULL;
LPCWSTR pwsPath = L"System";
LPCWSTR pwsQuery = L"Event/System[EventID=27]";
hResults = EvtQuery(NULL, pwsPath, pwsQuery, EvtQueryChannelPath | EvtQueryReverseDirection);
if (NULL == hResults)
{
status = GetLastError();
if (ERROR_EVT_CHANNEL_NOT_FOUND == status)
wprintf(L"The channel was not found.\n");
else if (ERROR_EVT_INVALID_QUERY == status)
// You can call the EvtGetExtendedStatus function to try to get
// additional information as to what is wrong with the query.
wprintf(L"The query is not valid.\n");
else
wprintf(L"EvtQuery failed with %lu.\n", status);
goto cleanup;
}
PrintResults(hResults);
cleanup:
if (hResults)
EvtClose(hResults);
}
// Enumerate all the events in the result set.
DWORD PrintResults(EVT_HANDLE hResults)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hEvents[ARRAY_SIZE];
DWORD dwReturned = 0;
// Get a block of events from the result set.
if (!EvtNext(hResults, ARRAY_SIZE, hEvents, INFINITE, 0, &dwReturned))
{
if (ERROR_NO_MORE_ITEMS != (status = GetLastError()))
{
wprintf(L"EvtNext failed with %lu\n", status);
}
goto cleanup;
}
// For each event, call the PrintEvent function which renders the
// event for display. PrintEvent is shown in RenderingEvents.
/*for (DWORD i = 0; i < dwReturned; i++)
{
if (ERROR_SUCCESS == (status = PrintEvent(hEvents[i])))
{
EvtClose(hEvents[i]);
hEvents[i] = NULL;
}
else
{
goto cleanup;
}
}*/
if (ERROR_SUCCESS == (status = PrintEvent(hEvents[0])))
{
EvtClose(hEvents[0]);
hEvents[0] = NULL;
}
else
{
goto cleanup;
}
cleanup:
for (DWORD i = 0; i < dwReturned; i++)
{
if (NULL != hEvents[i])
EvtClose(hEvents[i]);
}
return status;
}
DWORD PrintEvent(EVT_HANDLE hEvent)
{
DWORD status = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD dwPropertyCount = 0;
LPWSTR pRenderedContent = NULL;
if (!EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
pRenderedContent = (LPWSTR)malloc(dwBufferSize);
if (pRenderedContent)
{
EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount);
}
else
{
wprintf(L"malloc failed\n");
status = ERROR_OUTOFMEMORY;
goto cleanup;
}
}
if (ERROR_SUCCESS != (status = GetLastError()))
{
wprintf(L"EvtRender failed with %d\n", status);
goto cleanup;
}
}
wprintf(L"%s\n\n", pRenderedContent);
cleanup:
if (pRenderedContent)
free(pRenderedContent);
return status;
}
Result:
I'm trying to change audit settings of a folder.As i was testing my code on different machines i found that SetNamedSecurityInfo call restarts the system.This happened with some machines.A pop up generates which says "Windows has encountered a security issue and will restart in one minute".I'm not able to figure out the reason.Any help will be appreciated!
HANDLE hProcess = GetCurrentProcess();
HANDLE hToken;
DWORD val;
BOOL result;
result = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
if (result == 0)
{
printf("\nBreak After open process");
return 0;
}
else{
printf("\ncontinue after open process");
}
// Used for reading SACL's
result = SetPrivilege(hToken, SE_SECURITY_NAME, TRUE);
if (result == 0)
{
printf("\nBreak After setprivilege");
return 0;
}
else{
printf("\ncontinue after open process");
}
CloseHandle(hToken);
retval = GetNamedSecurityInfo(file, SE_FILE_OBJECT, SACL_SECURITY_INFORMATION, &owner, NULL, NULL, &sacl, &psd);
if(retval != 0)
{
wcout << "GetNamedSecurityInfo failed with error: " << retval << endl;
return -1;
}
printf("\nBuilt trust successfully before");
BuildTrusteeWithSid(ptrust,psd);
printf("\nBuilt trust successfully");
printf("\ntrying to modify ...");
EXPLICIT_ACCESS ea;
PACL pNewSACL = NULL;
ACCESS_MODE AccessMode = SET_AUDIT_SUCCESS; //SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE
DWORD dwAccessRights = 0X410D0060;
DWORD dwInheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = SET_AUDIT_SUCCESS;
ea.grfInheritance = dwInheritance;
ea.Trustee = *(ptrust);
DWORD dwRes = SetEntriesInAcl(1, &ea, sacl, &pNewSACL);
if(dwRes != ERROR_SUCCESS)
{
printf("SetEntriesInAcl() error %u\n", dwRes);
}
else
{
printf("SetEntriesInAcl() is OK\n");
}
dwRes = SetNamedSecurityInfo(file, SE_FILE_OBJECT, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, pNewSACL);
if(dwRes != ERROR_SUCCESS)
{
printf("SetNamedSecurityInfo() error %u\n", dwRes);
}
else
printf("SetNamedSecurityInfo() is OK\n\n");
LocalFree(psd);
There is an global policy entry that controls the shutdown if the system was unable to log security audits.
See:
"Computer Configuration\Windows Settings\Local Policies\Security Options"
"Audit: Shut down system immediately if unable to log security audits"
This could happen in combination with:
"Computer Configuration\Windows Settings\Local Policies\Security Options"
"Audit: Audit the accesss of global system objects"
I have this program that works perfectly in windows 7 but on windows 8 the readprocessmemory seems to be blank when I output it.Get Last error code 299. I Did not create this part of of program for read process but I use it because it was working for windows 7. The game handles and aria location are same on windows 8 machine, I double checked them. and The game handle is found. The address works fine in windows 7.
hGameWindow = FindWindow(L"WFElementClient Window",NULL);
if(hGameWindow) {
GetWindowThreadProcessId( hGameWindow, &dwProcId );
if( dwProcId != 0 ) {
hProcHandle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcId );
if( hProcHandle == INVALID_HANDLE_VALUE || hProcHandle == NULL ) {
GameStatus = "Failed to open process for valid handle";
}else{
GameStatus = "Game Found";
myaddr = FindPointerAddr(hProcHandle, ariaBase, aOffset);
// IsGameAvail = true;
}
}
else GameStatus = "Failed to obtain process id";
}
else GameStatus = "game handle not found";
ReadProcessMemory(hProcHandle, (LPCVOID)myaddr, &buffer, sizeof(buffer), NULL);
int FindPointerAddr(HANDLE pHandle,int baseaddr, DWORD offsets[])
{
int Address = baseaddr;
int offset = 0;
int offsetCount = 5;
for (int i = 0; i < offsetCount; i++)
{
ReadProcessMemory(pHandle, (LPCVOID)Address, &Address , 4, NULL);
Address+=offsets[i];
}
return Address;
}
Security permissions have changed from Windows 7 to Windows 8.
You may need to run as administrator and set SeDebugPrivelage now, when you were not required to on previous versions of Windows. Such as when calling OpenProcess() with PROCESS_ALL_ACCESS because PROCESS_VM_READ requires SeDebugPrivelage
Here is how you set SeDebugPrivelage:
bool SetDebugPrivilege(bool Enable)
{
HANDLE hToken{ nullptr };
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
return false;
TOKEN_PRIVILEGES TokenPrivileges{};
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
if (!LookupPrivilegeValueA(nullptr, "SeDebugPrivilege", &TokenPrivileges.Privileges[0].Luid))
{
CloseHandle(hToken);
return false;
}
if (!AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
{
CloseHandle(hToken);
return false;
}
CloseHandle(hToken);
return true;
}
I have created a Win32 Service using C++ and installed to the Services Successfully.
Now While I try Starting the service from Services.msc , I am getting the Error:
Could not start the Service on Local Computer . Error 2: The system can not find the File specified.
Here is the code snippet I am defining in the Service Entry Point:
#include "stdafx.h"
#include "iostream"
#include "Windows.h"
#include "Winsvc.h"
#include "time.h"
SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
BOOL bRunning=true;
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
void WINAPI ServiceCtrlHandler(DWORD Opcode);
BOOL InstallService();
BOOL DeleteService();
void main(int argc, char* argv[])
{
if(argc>1)
{
if(strcmp(argv[1],"-i")==0)
{
if(InstallService())
printf("\n\nService Installed Sucessfully\n");
else
printf("\n\nError Installing Service\n");
}
else if(strcmp(argv[1],"-u")==0)
{
if(DeleteService())
printf("\n\nService UnInstalled Sucessfully\n");
else
printf("\n\nError UnInstalling Service\n");
}
else
{
printf("\n\nUnknown Switch Usage\n\nFor Install use WindowService -i\n\nFor UnInstall use WindowService -u\n");
}
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[]=
{{"myService",ServiceMain},{NULL,NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
// DeleteService();
//return 0;
}
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
DWORD status;
DWORD specificError;
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
m_ServiceStatusHandle = RegisterServiceCtrlHandler("myService",
ServiceCtrlHandler);
if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))
{
}
system("start c:\\progra~1\\intern~1\\iexplore.exe http://www.google.com");
//strcat("Win1", "1.exe");
/*bRunning=true;
while(bRunning)
{
//Sleep(3000);
//Place Your Code for processing here....
//printf("\nThe Service is Running Now...\n");
}*/
return;
}
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);
bRunning=false;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
}
return;
}
BOOL InstallService()
{
char strDir[1024];
HANDLE schSCManager,schService;
GetCurrentDirectory(1024,strDir);
strcat(strDir,"\\Debug\\WindowService.exe");
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL)
return false;
LPCTSTR lpszBinaryPathName=strDir;
schService = CreateService(schSCManager,"myService",
"my_Service", // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
lpszBinaryPathName, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL)
return false;
CloseServiceHandle(schService);
return true;
}
BOOL DeleteService()
{
HANDLE schSCManager;
SC_HANDLE hService;
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL)
return false;
hService=OpenService(schSCManager,"myService",SERVICE_ALL_ACCESS);
if (hService == NULL)
return false;
if(DeleteService(hService)==0)
return false;
if(CloseServiceHandle(hService)==0)
return false;
return true;
}
I have taken this code sample from codeproject.
Check your service's properties in services.msc to see where your exe is expected to run from, and make sure this matches the physical path of the EXE. Make sure the EXE is actually there. Check the Event Viewer to see if more info is present about the error. make sure the code runs properly when not run as a service - making your code run optionally as service and not as service is likely to be very helpful in this regard. Run thru service installation in the debugger to make sure you are not missing an error code somewhere - did service installation actually work properly end to end?
Where is the location that you have installed your service. DId you check that the service exists in that location.
Are you trying to run it as a network service or local user service.