2020-09-30 17:12:29 +02:00

336 lines
7.8 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
bootvrfy.c
Abstract:
This is a small service that simply calls NotifyBootConfigStatus to
indicate that the boot is acceptable. This service is to go at the
end of the service dependency list.
The assumption is that if we got far enough to start this service, the
the boot must be ok.
Author:
Dan Lafferty (danl) 06 May-1991
Environment:
User Mode -Win32
Revision History:
--*/
//
// Includes
//
#include <nt.h> // DbgPrint prototype
#include <ntrtl.h> // DbgPrint prototype
#include <windef.h>
#include <nturtl.h> // needed for winbase.h
#include <winbase.h>
#include <winsvc.h>
#include <tstr.h> // Unicode string macros
//
// Defines
//
#define SERVICE_WAIT_TIME 0xffffffff // infinite
#define BV_SERVICE_NAME L"BootVerification"
//
// DEBUG MACROS
//
//
// The following allow debug print syntax to look like:
//
// BV_LOG(DEBUG_TRACE, "An error occured %x\n",status)
//
#if DBG
#define STATIC
#define BV_LOG0(level,string) \
if( BvDebugLevel & (DEBUG_ ## level)){ \
DbgPrint("[BootVrfy]"); \
DbgPrint(string); \
}
#define BV_LOG1(level,string,var1) \
if( BvDebugLevel & (DEBUG_ ## level)){ \
DbgPrint("[BootVrfy]"); \
DbgPrint(string,var1); \
}
#define BV_LOG2(level,string,var1,var2) \
if( BvDebugLevel & (DEBUG_ ## level)){ \
DbgPrint("[BootVrfy]"); \
DbgPrint(string,var1,var2); \
}
#else
#define STATIC static
#define BV_LOG0(level,string)
#define BV_LOG1(level,string,var)
#define BV_LOG2(level,string,var1,var2)
#endif
#define DEBUG_NONE 0x00000000
#define DEBUG_ERROR 0x00000001
#define DEBUG_TRACE 0x00000002
#define DEBUG_ALL 0xffffffff
//
// Globals
//
SERVICE_STATUS BootVerificationStatus;
HANDLE BootVerificationDoneEvent;
SERVICE_STATUS_HANDLE BootVerificationStatusHandle;
DWORD BvDebugLevel = DEBUG_ERROR;
//
// Function Prototypes
//
STATIC VOID
BootVerificationStart (
DWORD argc,
LPWSTR *argv
);
STATIC VOID
BootVerificationCtrlHandler (
IN DWORD opcode
);
/****************************************************************************/
VOID _CRTAPI1
main(void)
{
DWORD status;
SERVICE_TABLE_ENTRYW DispatchTable[] = {
{ BV_SERVICE_NAME, BootVerificationStart },
{ NULL, NULL }
};
status = StartServiceCtrlDispatcherW( DispatchTable);
BV_LOG0(TRACE,"The Service Process is Terminating....\n");
ExitProcess(0);
}
/****************************************************************************/
//
// BootVerification will take a long time to respond to pause
//
//
VOID
BootVerificationStart (
DWORD argc,
LPWSTR *argv
)
{
DWORD status;
SC_HANDLE hScManager;
SC_HANDLE hService;
SERVICE_STATUS ServiceStatus;
BV_LOG0(TRACE,"Inside the BootVerification Service Thread\n");
BootVerificationDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
BootVerificationStatus.dwServiceType = SERVICE_WIN32;
BootVerificationStatus.dwCurrentState = SERVICE_RUNNING;
BootVerificationStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
BootVerificationStatus.dwWin32ExitCode = 0;
BootVerificationStatus.dwServiceSpecificExitCode = 0;
BootVerificationStatus.dwCheckPoint = 0;
BootVerificationStatus.dwWaitHint = 0;
//
// Register the Control Handler routine.
//
BV_LOG0(TRACE,"Getting Ready to call RegisterServiceCtrlHandler\n");
BootVerificationStatusHandle = RegisterServiceCtrlHandlerW(
BV_SERVICE_NAME,
BootVerificationCtrlHandler);
if (BootVerificationStatusHandle == (SERVICE_STATUS_HANDLE)0) {
BV_LOG1(ERROR,"RegisterServiceCtrlHandlerW failed %d\n", GetLastError());
}
//
// Return the status
//
if (!SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus)) {
status = GetLastError();
BV_LOG1(ERROR,"SetServiceStatus error %ld\n",status);
}
//
// Tell Service Controller that the Boot is OK.
//
BV_LOG0(TRACE,"Tell Service Controller that the boot is ok\n");
if (!NotifyBootConfigStatus(TRUE)) {
BV_LOG0(ERROR,"NotifyBootConfigStatus Failed\n");
}
////////////////////////////////////////////////////////////////////////
//
// Tell the Service Controller that we want to shut down now.
//
// If anything fails along the way, just exit process, and allow
// the service controller to clean up.
//
BV_LOG0(TRACE,"Send Control to Service Controller to shut down BOOTVFY\n");
hScManager = OpenSCManagerW(
NULL,
NULL,
SC_MANAGER_CONNECT);
if (hScManager == NULL) {
status = GetLastError();
BV_LOG1(ERROR,"OpenSCManager failed %d\n",status);
BootVerificationStatus.dwWin32ExitCode = status;
SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus);
ExitProcess(0);
}
hService = OpenServiceW(
hScManager,
BV_SERVICE_NAME,
SERVICE_STOP);
if (hService == NULL) {
status = GetLastError();
BV_LOG1(ERROR,"OpenService failed %d\n",status);
BootVerificationStatus.dwWin32ExitCode = status;
SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus);
ExitProcess(0);
}
if (!ControlService (hService,SERVICE_CONTROL_STOP,&ServiceStatus)) {
status = GetLastError();
BV_LOG1(ERROR,"OpenService failed %d\n",status);
BootVerificationStatus.dwWin32ExitCode = status;
SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus);
ExitProcess(0);
}
////////////////////////////////////////////////////////////////////////
//
// Wait forever until we are told to terminate.
//
status = WaitForSingleObject (
BootVerificationDoneEvent,
SERVICE_WAIT_TIME);
BV_LOG0(TRACE,"Leaving the BootVerification service\n");
BootVerificationStatus.dwWin32ExitCode = 0;
BootVerificationStatus.dwCurrentState = SERVICE_STOPPED;
if (!SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus)) {
status = GetLastError();
BV_LOG1(ERROR,"SetServiceStatus error %ld\n",status);
}
ExitThread(NO_ERROR);
return;
}
/****************************************************************************/
VOID
BootVerificationCtrlHandler (
IN DWORD Opcode
)
{
DWORD status;
BV_LOG1(TRACE,"opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) {
case SERVICE_CONTROL_PAUSE:
break;
case SERVICE_CONTROL_CONTINUE:
break;
case SERVICE_CONTROL_STOP:
BootVerificationStatus.dwWin32ExitCode = 0;
BootVerificationStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetEvent(BootVerificationDoneEvent);
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
BV_LOG1(ERROR,"Unrecognized opcode %ld\n", Opcode);
}
//
// Send a status response.
//
if (!SetServiceStatus (BootVerificationStatusHandle, &BootVerificationStatus)) {
status = GetLastError();
BV_LOG1(ERROR,"SetServiceStatus error %ld\n",status);
}
return;
}