510 lines
11 KiB
C
510 lines
11 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
faxsvc.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the service specific code.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 16-Jan-1996
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "faxsvc.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#if DBGX
|
|
|
|
//
|
|
// this is bad place to have these defines
|
|
// because they are already in ntexapi.h, but it
|
|
// is difficult to include windows headers and
|
|
// nt headers together. we will just have to be
|
|
// aware that if the global flag definitions in
|
|
// ntexapi.h change, they must also change here.
|
|
//
|
|
#define FLG_SHOW_LDR_SNAPS 0x00000002 // user and kernel mode
|
|
#define FLG_USER_STACK_TRACE_DB 0x00001000 // x86 user mode only
|
|
#define FLG_HEAP_ENABLE_CALL_TRACING 0x00100000 // user mode only
|
|
#define FLG_HEAP_PAGE_ALLOCS 0x02000000 // user mode only
|
|
|
|
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used =
|
|
{
|
|
0, // Reserved
|
|
0, // Reserved
|
|
0, // Reserved
|
|
0, // Reserved
|
|
0, // GlobalFlagsClear
|
|
FLG_USER_STACK_TRACE_DB | FLG_HEAP_ENABLE_CALL_TRACING,
|
|
0, // CriticalSectionTimeout (milliseconds)
|
|
0, // DeCommitFreeBlockThreshold
|
|
0, // DeCommitTotalFreeThreshold
|
|
NULL, // LockPrefixTable
|
|
0, 0, 0, 0, 0, 0, 0 // Reserved
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SERVICE_STATUS FaxServiceStatus;
|
|
SERVICE_STATUS_HANDLE FaxServiceStatusHandle;
|
|
BOOL ServiceDebug;
|
|
HANDLE FaxSvcHeapHandle;
|
|
|
|
SERVICE_TABLE_ENTRY ServiceDispatchTable[] = {
|
|
{ FAX_SERVICE_NAME, FaxServiceMain },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
|
|
int
|
|
WINAPI
|
|
#ifdef UNICODE
|
|
wWinMain(
|
|
#else
|
|
WinMain(
|
|
#endif
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPTSTR lpCmdLine,
|
|
int nShowCmd
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Main entry point for the TIFF image viewer.
|
|
|
|
|
|
Arguments:
|
|
|
|
hInstance - Instance handle
|
|
hPrevInstance - Not used
|
|
lpCmdLine - Command line arguments
|
|
nShowCmd - How to show the window
|
|
|
|
Return Value:
|
|
|
|
Return code, zero for success.
|
|
|
|
--*/
|
|
|
|
{
|
|
int rVal;
|
|
LPTSTR p;
|
|
DWORD Action = 0;
|
|
LPTSTR Username;
|
|
LPTSTR Password;
|
|
|
|
|
|
FaxSvcHeapHandle = HeapInitialize(NULL,NULL,NULL,0);
|
|
|
|
FaxTiffInitialize();
|
|
|
|
for (p=lpCmdLine; *p; p++) {
|
|
if ((*p == TEXT('-')) || (*p == TEXT('/'))) {
|
|
switch( _totlower( p[1] ) ) {
|
|
case TEXT('i'):
|
|
Action = 1;
|
|
p += 2;
|
|
while( *p == TEXT(' ') ) p++;
|
|
Username = p;
|
|
while( *p != TEXT(' ') ) p++;
|
|
while( *p == TEXT(' ') ) p++;
|
|
Password = p;
|
|
while( *p != TEXT(' ') ) p++;
|
|
break;
|
|
|
|
case TEXT('r'):
|
|
Action = 2;
|
|
break;
|
|
|
|
case TEXT('d'):
|
|
Action = 3;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch( Action ) {
|
|
case 1:
|
|
rVal = InstallService( Username, Password );
|
|
if (rVal == 0) {
|
|
LogMessage( MSG_INSTALL_SUCCESS );
|
|
} else {
|
|
LogMessage( MSG_INSTALL_FAIL, GetLastErrorText( rVal ) );
|
|
}
|
|
return rVal;
|
|
|
|
case 2:
|
|
rVal = RemoveService();
|
|
if (rVal == 0) {
|
|
LogMessage( MSG_REMOVE_SUCCESS );
|
|
} else {
|
|
LogMessage( MSG_REMOVE_FAIL, GetLastErrorText( rVal ) );
|
|
}
|
|
return rVal;
|
|
|
|
case 3:
|
|
ServiceDebug = TRUE;
|
|
ConsoleDebugOutput = TRUE;
|
|
return ServiceStart();
|
|
}
|
|
|
|
if (!StartServiceCtrlDispatcher( ServiceDispatchTable)) {
|
|
DebugPrint(( TEXT("StartServiceCtrlDispatcher error =%d"), GetLastError() ));
|
|
return GetLastError();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
DWORD
|
|
InstallService(
|
|
LPTSTR Username,
|
|
LPTSTR Password
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Service installation function. This function just
|
|
calls the service controller to install the FAX service.
|
|
It is required that the FAX service run in the context
|
|
of a user so that the service can access MAPI, files on
|
|
disk, the network, etc.
|
|
|
|
Arguments:
|
|
|
|
Username - User name where the service runs.
|
|
Password - Password for the user name.
|
|
|
|
Return Value:
|
|
|
|
Return code. Return zero for success, all other
|
|
values indicate errors.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD rVal = 0;
|
|
SC_HANDLE hSvcMgr;
|
|
SC_HANDLE hService;
|
|
|
|
hSvcMgr = OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS
|
|
);
|
|
if (!hSvcMgr) {
|
|
rVal = GetLastError();
|
|
DebugPrint(( TEXT("could not open service manager: error code = %u"), rVal ));
|
|
return rVal;
|
|
}
|
|
|
|
hService = CreateService(
|
|
hSvcMgr,
|
|
FAX_SERVICE_NAME,
|
|
FAX_DISPLAY_NAME,
|
|
SERVICE_ALL_ACCESS,
|
|
SERVICE_WIN32_OWN_PROCESS,
|
|
SERVICE_AUTO_START,
|
|
SERVICE_ERROR_NORMAL,
|
|
FAX_IMAGE_NAME,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
Username,
|
|
Password
|
|
);
|
|
if (!hService) {
|
|
rVal = GetLastError();
|
|
DebugPrint(( TEXT("could not create fax service: error code = %u"), rVal ));
|
|
return rVal;
|
|
}
|
|
|
|
CloseServiceHandle( hService );
|
|
CloseServiceHandle( hSvcMgr );
|
|
|
|
return rVal;
|
|
}
|
|
|
|
|
|
DWORD
|
|
RemoveService(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Service removal function. This function just
|
|
calls the service controller to remove the FAX service.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Return code. Return zero for success, all other
|
|
values indicate errors.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD rVal = 0;
|
|
SC_HANDLE hSvcMgr;
|
|
SC_HANDLE hService;
|
|
|
|
|
|
hSvcMgr = OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS
|
|
);
|
|
if (!hSvcMgr) {
|
|
rVal = GetLastError();
|
|
DebugPrint(( TEXT("could not open service manager: error code = %u"), rVal ));
|
|
return rVal;
|
|
}
|
|
|
|
hService = OpenService(
|
|
hSvcMgr,
|
|
FAX_SERVICE_NAME,
|
|
SERVICE_ALL_ACCESS
|
|
);
|
|
if (!hService) {
|
|
rVal = GetLastError();
|
|
DebugPrint(( TEXT("could not open the fax service: error code = %u"), rVal ));
|
|
return rVal;
|
|
}
|
|
|
|
if (ControlService( hService, SERVICE_CONTROL_STOP, &FaxServiceStatus )) {
|
|
//
|
|
// wait for 1 second
|
|
//
|
|
Sleep( 1000 );
|
|
|
|
while( QueryServiceStatus( hService, &FaxServiceStatus ) ) {
|
|
if ( FaxServiceStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
|
|
Sleep( 1000 );
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FaxServiceStatus.dwCurrentState != SERVICE_STOPPED) {
|
|
rVal = GetLastError();
|
|
DebugPrint(( TEXT("could not stop the fax service: error code = %u"), rVal ));
|
|
return rVal;
|
|
}
|
|
}
|
|
|
|
if (!DeleteService( hService )) {
|
|
rVal = GetLastError();
|
|
DebugPrint(( TEXT("could not delete the fax service: error code = %u"), rVal ));
|
|
return rVal;
|
|
}
|
|
|
|
CloseServiceHandle( hService );
|
|
CloseServiceHandle( hSvcMgr );
|
|
|
|
return rVal;
|
|
}
|
|
|
|
|
|
VOID
|
|
FaxServiceMain(
|
|
DWORD argc,
|
|
LPTSTR *argv
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the service main that is called by the
|
|
service controller.
|
|
|
|
Arguments:
|
|
|
|
argc - argument count
|
|
argv - argument array
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Rval;
|
|
|
|
|
|
FaxServiceStatus.dwServiceType = SERVICE_WIN32;
|
|
FaxServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
FaxServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
|
|
FaxServiceStatus.dwWin32ExitCode = 0;
|
|
FaxServiceStatus.dwServiceSpecificExitCode = 0;
|
|
FaxServiceStatus.dwCheckPoint = 0;
|
|
FaxServiceStatus.dwWaitHint = 0;
|
|
|
|
FaxServiceStatusHandle = RegisterServiceCtrlHandler(
|
|
FAX_SERVICE_NAME,
|
|
FaxServiceCtrlHandler
|
|
);
|
|
|
|
if (!FaxServiceStatusHandle) {
|
|
DebugPrint(( TEXT("RegisterServiceCtrlHandler failed %d"), GetLastError() ));
|
|
return;
|
|
}
|
|
|
|
Rval = ServiceStart();
|
|
if (!Rval) {
|
|
//
|
|
// the service failed to start correctly
|
|
//
|
|
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
FaxServiceCtrlHandler(
|
|
DWORD Opcode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the FAX service control dispatch function.
|
|
|
|
Arguments:
|
|
|
|
Opcode - requested control code
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch(Opcode) {
|
|
case SERVICE_CONTROL_PAUSE:
|
|
ReportServiceStatus( SERVICE_PAUSED, 0, 0 );
|
|
break;
|
|
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
ReportServiceStatus( SERVICE_RUNNING, 0, 0 );
|
|
break;
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
EndFaxSvc(FALSE,FAXLOG_LEVEL_NONE);
|
|
return;
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
// fall through to send current status
|
|
break;
|
|
|
|
default:
|
|
DebugPrint(( TEXT("Unrecognized opcode %ld"), Opcode ));
|
|
break;
|
|
}
|
|
|
|
ReportServiceStatus( 0, 0, 0 );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReportServiceStatus(
|
|
DWORD CurrentState,
|
|
DWORD Win32ExitCode,
|
|
DWORD WaitHint
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function updates the service control manager's status information for the FAX service.
|
|
|
|
Arguments:
|
|
|
|
CurrentState - Indicates the current state of the service
|
|
Win32ExitCode - Specifies a Win32 error code that the service uses to
|
|
report an error that occurs when it is starting or stopping.
|
|
WaitHint - Specifies an estimate of the amount of time, in milliseconds,
|
|
that the service expects a pending start, stop, or continue
|
|
operation to take before the service makes its next call to the
|
|
SetServiceStatus function with either an incremented dwCheckPoint
|
|
value or a change in dwCurrentState.
|
|
|
|
Return Value:
|
|
|
|
Return code. Return zero for success, all other
|
|
values indicate errors.
|
|
|
|
--*/
|
|
|
|
{
|
|
static DWORD CheckPoint = 1;
|
|
BOOL rVal;
|
|
|
|
|
|
if (ServiceDebug) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (CurrentState == SERVICE_START_PENDING) {
|
|
FaxServiceStatus.dwControlsAccepted = 0;
|
|
} else {
|
|
FaxServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
|
}
|
|
|
|
if (CurrentState) {
|
|
FaxServiceStatus.dwCurrentState = CurrentState;
|
|
}
|
|
FaxServiceStatus.dwWin32ExitCode = Win32ExitCode;
|
|
FaxServiceStatus.dwWaitHint = WaitHint;
|
|
|
|
if ((FaxServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
|
|
(FaxServiceStatus.dwCurrentState == SERVICE_STOPPED ) ) {
|
|
FaxServiceStatus.dwCheckPoint = 0;
|
|
} else {
|
|
FaxServiceStatus.dwCheckPoint = CheckPoint++;
|
|
}
|
|
|
|
//
|
|
// Report the status of the service to the service control manager.
|
|
//
|
|
rVal = SetServiceStatus( FaxServiceStatusHandle, &FaxServiceStatus );
|
|
if (!rVal) {
|
|
DebugPrint(( TEXT("SetServiceStatus() failed: ec=%d"), GetLastError() ));
|
|
}
|
|
|
|
return rVal;
|
|
}
|