|
Also to call Abort shutdown Method my service first needs to know that a shutdown signal was received. So kindly tell me how my service will come to know about that a shutdown signal was received and where should I place a call to abortshutdown ?
Regards,
Kushagra
|
|
|
|
|
To catch the Shutdown-Event you have to handle SERVICE_CONTROL_SHUTDOWN or SERVICE_CONTROL_PRESHUTDOWN
event in your HandlerEx callback function you registered with RegisterServiceCtrlHandlerEx.
(To use this, you need to say the system that your service supports shutdown events.
An other possibility is to use the SetConsoleCtrlHandler function where you handle the CTRL_SHUTDOWN_EVENT event in your HandlerRoutine.
After you catched the shutdown-event you have to use the function AbortSystemShutdown or just
delay your service-shutdown for example with the status SERVICE_STOP_PENDING.
|
|
|
|
|
Thanks Covean,
I will try todo this and will let u know as I think this should actually work out
Regards,
Kushagra
|
|
|
|
|
Covean wrote: An other possibility is to use the SetConsoleCtrlHandler function...
Isn't this for console applications?
"Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
|
|
|
|
|
See http://msdn.microsoft.com/en-us/library/ms683240(VS.85).aspx
Its also a good reference about service shutdown.
"Services can also use the SetConsoleCtrlHandler function to receive shutdown notification. This notification is received when the running applications are shutting down, which occurs before services are shut down."
|
|
|
|
|
Hello Covean,
As per your suggesstion I did the folowing things:
In ServiceMain of my service I did the following code :
m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
if (m_hServiceStatus == NULL)
{
LogEvent(_T("Handler not installed"));
return;
}
and here is the code for _Handler function :
void WINAPI CServiceModule::_Handler(DWORD dwOpcode)
{
char chComputerName[512];
DWORD dwBuff = 512;
GetComputerName(chComputerName,&dwBuff);
if (dwOpcode == SERVICE_CONTROL_SHUTDOWN)
{
AbortShutdown(chComputerName);
}
_Module.Handler(dwOpcode);
}
and abortshutdown does the following functionality
BOOL AbortShutdown(LPTSTR lpMachineName)
{
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))
{
// TRACE("OpenProcessToken failed.\n");
return false;
}
// Get the LUID for shutdown privilege.
LookupPrivilegeValue(lpMachineName, 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)
{
//TRACE("AdjustTokenPrivileges(setting) enable failed.\n");
return false;
}
// Prevent the system from shutting down.
fResult = AbortSystemShutdown(lpMachineName);
if (!fResult)
{
//TRACE("AbortSystemShutdown failed.\n");
return false;
}
else
{
Cxcutter objexe;
}
//m_bIsShuttingDown = false; // Reset shut down flag
// Disable shutdown privilege.
tkp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
{
// TRACE("AdjustTokenPrivileges(re-setting) disable failed.\n");
return false;
}
return true;
}
But some how the when shutdown is done then the control never comes to this and windows shuts down normailly
Please suggest some thing If I am going wrong somewhere.
Regards,
Kushagra
modified on Thursday, October 22, 2009 11:35 AM
|
|
|
|
|
Does your service get the shutdown notification SERVICE_CONTROL_SHUTDOWN or does AbortSystemShutdown not abort the shutdown?
I would say its easier to test the version with SetConsoleCtrl..., after that you should try th service version.
Edit:
In my first answer I said, that you have to say the system that your service supports SHUTDOWN events.
Now I found what i meant. You have to use SetServiceStatus with a SERVICE_STATUS where dwControlsAccepted is a least SERVICE_ACCEPT_SHUTDOWN.
modified on Thursday, October 22, 2009 12:02 PM
|
|
|
|
|
Ok , I will try with this and attempt achieve the same
|
|
|
|
|
Covean wrote: . You have to use SetServiceStatus with a SERVICE_STATUS where dwControlsAccepted is a least SERVICE_ACCEPT_SHUTDOWN.
As per ur suggestion I tried to do the same but seems the control never reaches my code , I am quite confused actually as I think I am doing every thing which I think is right .Here is what I am doing after calling RegisterserverEx:
::SetServiceStatus(m_hServiceStatus, &m_status);
Where m_status is of SERVICE_STATUS type and initialized by :
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
m_status.dwCurrentState = SERVICE_STOPPED;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
m_status.dwWin32ExitCode = 0;
m_status.dwServiceSpecificExitCode = 0;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;
and in Handler function of my Service handle SERVICE_CONTROL_SHUTDOWN which has following code
char chComputerName[512];
DWORD dwBuff = 512;
GetComputerName(chComputerName,&dwBuff);
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
SetServiceStatus(SERVICE_STOP_PENDING);
Alive = true;
iscmcontrol = 3;
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
break;
case SERVICE_CONTROL_PAUSE:
Alive = false;
iscmcontrol = 1;
break;
case SERVICE_CONTROL_CONTINUE:
Alive = false;
iscmcontrol = 0;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
CoInitialize( NULL );
AbortShutdown(chComputerName);
CoUninitialize();
Alive = true;
iscmcontrol = 2;
break;
default:
LogEvent(_T("Bad service request"));
}
If you want the sample code and personally see what is the problem please let me know your email address I will send it to you .
Regards,
Kushagra
|
|
|
|
|
Hello Covean,
Did you recieve my mail having the sample code??
Kushagra
|
|
|
|
|
Yes I received your code and after some changes (for VS2008 and Vista) I has installed it. Now I'm try to get it to work.
|
|
|
|
|
Ok . I hope it works
Kushagra
|
|
|
|
|
Any luck with the code?
Regards,
Kushagra
|
|
|
|
|
What OS to you use? Cause on Vista I do not find any way to block the shutdown (ShutdownBlockReasonCreate needs a window...).
But the service itself works fine.
Here some eventlog-output:
SetServiceStatus Succeed
Service started
SetServiceStatus Succeed
SERVICE_CONTROL_SHUTDOWN (<- shutdown event caught)
AbortSystemShutdown failed! Error=1115 (<- means shutdown already in progress, very funny errorcode )
The only thing left is to stop the shutdown.
On WinXP your code should work. How do you test your service?
You can just catch this event if your app really runs as service
in debug mode you will never see this event.
Here some code-changes I made (but nothing very special):
1. The "problem" that your SetServiceStatus always "fails":
void ...SetServiceStatus(DWORD dwState)
{
if (::SetServiceStatus(m_hServiceStatus, &m_status) == TRUE)
{
LogEvent(TEXT("SetServiceStatus Failed"));
}
else
{
LogEvent(TEXT("SetServiceStatus Failed"));
}
}
---> copy & paste is not always your friend.
2. In "...::Handler(...)" I made some changes to get more eventlog entries:
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
LogEvent(_T("SERVICE_CONTROL_STOP"));
break;
case SERVICE_CONTROL_PAUSE:
LogEvent(_T("SERVICE_CONTROL_PAUSE"));
break;
case SERVICE_CONTROL_CONTINUE:
LogEvent(_T("SERVICE_CONTROL_CONTINUE"));
break;
case SERVICE_CONTROL_INTERROGATE:
LogEvent(_T("SERVICE_CONTROL_INTERROGATE"));
break;
case SERVICE_CONTROL_SHUTDOWN:
LogEvent(_T("SERVICE_CONTROL_SHUTDOWN"));
AbortShutdown(chComputerName);
break;
}
3. AbortShutdown changes: (AbortShutdown is now part of your Module class, just for LogEvent)
BOOL ...::AbortShutdown(LPTSTR lpMachineName)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL fResult;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
LogEvent(TEXT("OpenProcessToken failed"));
return false;
}
if(!LookupPrivilegeValue(lpMachineName, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid))
{
LogEvent(TEXT("LookupPrivilegeValue failed"));
return false;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
{
LogEvent(TEXT("AdjustTokenPrivileges failed"));
return false;
}
LogEvent(TEXT("AbortSystemShutdown"));
fResult = AbortSystemShutdown(NULL);
if (!fResult)
{
wchar_t test[512];
swprintf((wchar_t*)&test, TEXT("AbortSystemShutdown failed! Error=%d"), (DWORD)GetLastError());
LogEvent((LPCWSTR)&test);
return false;
}
else
{
LogEvent(TEXT("AbortSystemShutdown succeed"));
}
tkp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
{
return false;
}
return true;
}
Like you see I never changed something special and your service gets the SHUTDOWN notification.
Now its just the question how to abort the shutdown? Maybe this code works on WinXP.
I would say, at first try out some more logging to the eventlog just to find out if your service
catches the event SERVICE_CONTROL_SHUTDOWN. If so then you have to find out where an error occurs.
And make sure every time you test your service really runs as service.
Let me you know what you find out, cause your code is fine.
Greetings Covean
|
|
|
|
|
Yup you are right ...some time a minute error can take the hell out of ..hehehe
I am working on the code presently will let you know on the progress .
Cheers,
Kushagra 
|
|
|
|
|
I was able to abort shutdown and execute my scripts when the user was logged on to the system by making the service as an interactive service but in case when user was logged off and the shutdown was scheduled , the shutdown was aborted but no scripts were executed.Please suggest what to do in this case when no user is logged on to the system and shutdown was made a scheduled task.
Regards,
Kushagra
|
|
|
|
|
Sorry but after I read some information on this, I don't believe, that you will be able to abort this kind of shutdown.
But maybe someone else has an idea.
|
|
|
|
|
Even I couldn't find any way to do the same .
Windows can be harsh to us some times .
Still I am looking for some tweaks to achieve it .
Will let you know if I found some .
Regards,
Kushagra
|
|
|
|
|
Hi ALL,
I have a strange problem with me..... I have an application(vc++) in which i am taking login to SYBASE database.For that i am using Sybase SDk.My code is working fine with MS-2000 OS,But when i am working the same code in vista machine i am getting login crash when I enter wrong password/username....But working successfully with correct details...
I have code like this...
_dbproc = dbConnect (&_loginfo, _T("Phoenix")); (this is calling of my function)
Called Function:
DBPROCESS NEAR * CALLBACK dbConnect (LPLOGINFO li, LPSTR app)
{
DBPROCESS NEAR *dbproc;
LOGINREC *login;
if ((login = dblogin ()) == NULL)
return (DBPROCESS NEAR *) NULL;
DBSETLHOST (login, _dbhost); //for host
DBSETLUSER (login, li->dbid); //for username
DBSETLPWD (login, li->dbpwd);//for password
DBSETLAPP (login, app); //for application name
dbproc = dbopen (login, li->dbsrv); (My Login crashes here when i enter wrong username/password)
dbfreelogin (login);
if (dbproc != (DBPROCESS NEAR *) NULL)
dbuse (dbproc, li->dbdb);
return dbproc;
}
As i said above dblogin() is a function that returns LOGINREC structure pointer when we provide correct login details otherwise FALSE...
And dbopen() function takes the LOGINREC as a first input argument and tries to open the application...
But not returning back when i enter incorrect login details.....There it is crashing...
Can anybody helps in this..
Thanks in advance
|
|
|
|
|
Looks like a deja-vu to me...
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Hello,
So I have Visual C++ 2008 Express, won't be buying Std edition any time soon, and I'm very annoyed to find out the Express doesn't have all the libraries, like the MFC libraries.
So I had this problem where my program would not compile because it couldn't find "winres.h" I just renamed "winresrc.h" to "winres.h" to get it to compile. I don't know if that is going to work out or not.
So, I'm guessing winres.h just isn't part of the Windows SDK, instead it is included in the MFC libraries?
My next step is to get the Windows Template Library, and see if that helps.
Does anyone have knowledge about these issues?
|
|
|
|
|
mtthw wrote: Visual C++ Express, No MFC? Does that matter?
That's actually a feature.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Oh, thanks, Reading the instructions and manuals, I don't know
what I am reading half the time. But eventually it makes sense.
I appreciate the reply.
|
|
|
|
|
Express is free... be happy with that.
This signature was proudly tested on animals.
|
|
|
|
|
Thanks for replying.
Yes, I'm glad MS offers this tool to learn about windows development. I think its
awesome.
|
|
|
|
|