SERVICE.CPP

/////////////////////////////////////////////////////////////////////////////// 
//
// File Name
// SERVICE.CPP
//
// Description
// This is the file where the entry point is (WinMain).
// Here we also implement the registration and unregistration of
// the RPC server.
// The server register its services with NAMED PIPES as the exposed
// protocol sequence for RPC calls. This server can only be run on
// Windows NT platforms. Windows 95 does not support the creation of
// named pipes.
// This is where we register the NT service with the Service control
// manager and where the service control handler is implemented
//
// The WinMain, function can take certain paramenters from the command
// line to control the action of the executable
//
// Argument Action
// ======== ======
// <None> If normally started by the Service control manager,
// the WINDS NT Service starts and it is ready to accept
// request from WINDS MAPI service providers and from
// the WINDS administrator.
// If started as an application, a message dialog will
// come up to allow interactive install and removal of
// the service.
//
// APP Start the service as an APPLICATION EXECUTABLE, as
// opposed to an NT SERVICE. This is useful for
// debugging the WINDS server.
//
// INSTALL Adds the WINDS NT Service to the Service Control
// Manager list, modify the registry entries and starts
// the NT services normally.
//
// REMOVE Remove the WINDS NT service from the Service
// control list, and stops the WINDS service, halting
// services WINDS MAPI providers and WINDS administrators
//
// Author
// Irving De la Cruz
//
// Revision: 1.7
//
// Written for Microsoft Windows Developer Support
// Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
//
#include "_WINDS.H"
#include <WINDOWSX.H>
#include "WRAP3D.H"
#include <RPC.H>
#include "WINDS.H" // Header file generated by the MIDL compiler
#include "WDSADM.H" // Header file generated by the MIDL compiler
#include "COMMON.H"

extern "C"
{
BOOL WINAPI InitRPCServer
();
BOOL WINAPI TerminateAllRPCServer
();
void WINAPI RegisterWindsPrivateClass
();
void WindsServiceMain
(DWORD dwArgc,
LPTSTR * pszArgv);
void WindsServiceCtrlHandler
(DWORD dwControlCode);
void WINAPI TerminateService
(HRESULT hErrror);
HRESULT WINAPI SendStatusToSCM
(DWORD dwServiceState,
HRESULT hError,
DWORD dwCheckPoint,
DWORD dwWait);
HRESULT WINAPI InstallWindsService
(DWORD dwStartType,
LPTSTR szFullPathToServiceExe,
BOOL fStartImmediately);
HRESULT WINAPI RemoveWindsService
();
HRESULT WINAPI InitWindsService
();
void WINAPI PauseWindsService
();
void WINAPI ResumeWindsService
();
void WINAPI StopWindsService
();
BOOL CALLBACK GenericDlgProc
(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam);
BOOL CALLBACK InstallDlgProc
(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam);
LRESULT CALLBACK PrivateDlgClassProc
(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam);

TCHAR g_szAppTitle[] = TEXT("WINDS Messaging Host");
HINSTANCE ghInstance = NULL;
HANDLE ghHeap = NULL;
IOTHREADINFO g_IOInfo = { 0 };
TCHAR g_szDataFile[MAX_PATH] = { 0 };
HRESULT g_hServerState = HRESULT_FROM_WIN32(ERROR_BUSY);
CRITICAL_SECTION g_csIOInfo;
CRITICAL_SECTION g_csNotifLinks;
CRITICAL_SECTION g_csServiceState;
CRITICAL_SECTION g_csPipeID;
DWORD g_dwNextPipeID = MIN_PIPE_NUMBER;

SERVICE_STATUS_HANDLE g_ssHandle = NULL;
HANDLE g_hTerminateEvent = NULL;
LPVOID g_pctl3d = NULL;
};

CObjectList GlobalObjectMap;

#define WINDS_SERVICE_NAME TEXT("WINDS Messaging Host")
#define WINDS_SERVICE_NAME_SHORT TEXT("WindsMessagingHost")
#define WINDS_SERVICE_EXECUTABLE TEXT("\\WINDSSRV.EXE")

///////////////////////////////////////////////////////////////////////////////
// WindsServiceMain()
//
// Parameters
// { Refer to Win32 API documentation on ServiceMain }
//
// Purpose
//
// Return Value
// None
//
void WindsServiceMain (DWORD dwArgc, LPTSTR * pszArgv)
{
g_ssHandle = RegisterServiceCtrlHandler (WINDS_SERVICE_NAME,
(LPHANDLER_FUNCTION)WindsServiceCtrlHandler);
if (NULL == g_ssHandle)
{
TraceResult ("WindsServiceMain: Failed to register the control handle", HRESULT_FROM_WIN32(GetLastError()));
return;
}
HRESULT hResult = SendStatusToSCM (SERVICE_START_PENDING, S_OK, 1, 5);
if (hResult)
{
TerminateService (hResult);
return;
}
g_hTerminateEvent = CreateEvent (0, TRUE, FALSE, 0);
if (NULL == g_hTerminateEvent)
{
hResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("WindsServiceMain: Failed to create terminate event", hResult);
TerminateService (hResult);
return;
}

hResult = SendStatusToSCM (SERVICE_START_PENDING, S_OK, 2, 1);
if (!hResult)
{
hResult = InitWindsService();
if (!hResult)
{
hResult = SendStatusToSCM (SERVICE_RUNNING, S_OK, 0, 0);
// If an error occured, terminate the service
if (hResult)
{
StopWindsService();
}
}
}
if (S_OK == hResult)
{
WaitForSingleObject (g_hTerminateEvent, INFINITE);
}
TerminateService (hResult);

}

///////////////////////////////////////////////////////////////////////////////
// TerminateService()
//
// Parameters
//
// Purpose
//
// Return Value
// None
//
void WINAPI TerminateService (HRESULT hError)
{
if (g_hTerminateEvent)
{
CloseHandle (g_hTerminateEvent);
}
if (g_ssHandle)
{
SendStatusToSCM (SERVICE_STOPPED, hError, 0, 0);
}
}

///////////////////////////////////////////////////////////////////////////////
// SendStatusToSCM()
//
// Parameters
//
// Purpose
//
// Return Value
// None
//
HRESULT WINAPI SendStatusToSCM (DWORD dwServiceState,
HRESULT hError,
DWORD dwCheckPoint,
DWORD dwWait)
{
SERVICE_STATUS ssStatus = { 0 };
ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwCurrentState = dwServiceState;
if (SERVICE_START_PENDING == dwServiceState)
{
ssStatus.dwControlsAccepted = 0;
}
else
{
ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_SHUTDOWN;
}
if (hError)
{
ssStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
ssStatus.dwServiceSpecificExitCode = (DWORD)hError;
}
ssStatus.dwCheckPoint = dwCheckPoint;
ssStatus.dwWaitHint = (dwWait * 1000);

HRESULT hResult = S_OK;
if (!SetServiceStatus (g_ssHandle, &ssStatus))
{
hResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("SendStatusToSCM: Failed to set service status", hResult);
}
return hResult;
}

///////////////////////////////////////////////////////////////////////////////
// WindsServiceCtrlHandler()
//
// Parameters
//
// Purpose
//
// Return Value
// None
//
void WindsServiceCtrlHandler (DWORD dwControlCode)
{
switch (dwControlCode)
{
case SERVICE_CONTROL_SHUTDOWN :
case SERVICE_CONTROL_STOP :
SendStatusToSCM (SERVICE_STOP_PENDING, S_OK, 1, 10);
StopWindsService();
SendStatusToSCM (SERVICE_STOPPED, S_OK, 0, 0);
break;

case SERVICE_CONTROL_PAUSE :
SendStatusToSCM (SERVICE_PAUSE_PENDING, S_OK, 1, 1);
PauseWindsService();
SendStatusToSCM (SERVICE_PAUSED, S_OK, 0, 0);
break;

case SERVICE_CONTROL_CONTINUE :
SendStatusToSCM (SERVICE_CONTINUE_PENDING, S_OK, 1, 1);
ResumeWindsService();
SendStatusToSCM (SERVICE_RUNNING, S_OK, 0, 0);
break;

case SERVICE_CONTROL_INTERROGATE :
SendStatusToSCM (0, S_OK, 0, 0);
break;
}
}

///////////////////////////////////////////////////////////////////////////////
// InitWindsService()
//
// Parameters
//
// Purpose
//
// Return Value
//
HRESULT WINAPI InitWindsService()
{
HRESULT hResult = S_OK;
LoadSettingsFromRegistry();
SaveSettingsToRegistry();

InitializeCriticalSection (&g_csIOInfo);
InitializeCriticalSection (&g_csPipeID);
InitializeCriticalSection (&g_csNotifLinks);
InitializeCriticalSection (&g_csServiceState);

g_IOInfo.hResumeEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!g_IOInfo.hResumeEvent)
{
hResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("InitWindsService: Failed to create sync object (EVENT)", hResult);
return FALSE;
}

DWORD dwThreadID;
HANDLE hThread = CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE)WorkingIOProc,
NULL,
0,
&dwThreadID);
if (!hThread)
{
hResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("InitWindsService: Failed to create I/O thread", hResult);
ReleaseSyncObj();
return hResult;
}
TraceDebugger ("InitWindsService: IO thread spawned. ID: %X", dwThreadID);
SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST);
CloseHandle (hThread);

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);

if (InitRPCServer())
{
EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_OPEN_STORAGE_FILE;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &hResult;
LeaveCriticalSection (&g_csIOInfo);
WaitForSingleObject (hWaitEvent, INFINITE);
}
else
{
TraceMessage ("InitWindsService: Failed to initialize the RPC server");
hResult = E_FAIL;
}
CloseHandle (hWaitEvent);

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_LOAD_MAILBOX_NAMES;
g_IOInfo.hActionCompleted = NULL;
g_IOInfo.phLastError = NULL;
LeaveCriticalSection (&g_csIOInfo);

return hResult;
}

///////////////////////////////////////////////////////////////////////////////
// PauseWindsService()
//
// Parameters
//
// Purpose
//
// Return Value
//
void WINAPI PauseWindsService()
{
EnterCriticalSection (&g_csServiceState);
g_hServerState = HRESULT_FROM_WIN32(ERROR_SERVICE_CANNOT_ACCEPT_CTRL);
LeaveCriticalSection (&g_csServiceState);
}

///////////////////////////////////////////////////////////////////////////////
// ResumeWindsService()
//
// Parameters
//
// Purpose
//
// Return Value
//
void WINAPI ResumeWindsService()
{
EnterCriticalSection (&g_csServiceState);
g_hServerState = S_OK;
LeaveCriticalSection (&g_csServiceState);
}

///////////////////////////////////////////////////////////////////////////////
// StopWindsService()
//
// Parameters
//
// Purpose
//
// Return Value
//
void WINAPI StopWindsService()
{
HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);

PWINDS_NOTIFICATION pNotif = (PWINDS_NOTIFICATION)HeapAlloc (ghHeap,
HEAP_ZERO_MEMORY,
sizeof(WINDS_NOTIFICATION));
if (pNotif)
{
pNotif->Event = SERVER_IS_SHUTTING_DOWN;
EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_SENT_SHUTDOWN_NOTIFICATION;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.pNotif = pNotif;
g_IOInfo.phLastError = NULL;
LeaveCriticalSection (&g_csIOInfo);
WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
}
else
{
TraceMessage ("StopWindsService: Failed to create structure for shutdown notification");
}
TerminateAllRPCServer();
RemoveAllNotifLinks();

EnterCriticalSection (&g_csIOInfo);
// Resume the thread so that it terminate ifself properly
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.fAppIsTerminating = TRUE;
g_IOInfo.hActionCompleted = hWaitEvent;
LeaveCriticalSection (&g_csIOInfo);
WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);

CloseHandle (hWaitEvent);

UnInitTraces ();

ReleaseSyncObj();
}

///////////////////////////////////////////////////////////////////////////////
// InstallWindsService()
//
// Parameters
//
// Purpose
//
// Return Value
//
HRESULT WINAPI InstallWindsService (DWORD dwStartType,
LPTSTR szFullPathToServiceExe,
BOOL fStartImmediately)
{
HRESULT hResult = S_OK;
SC_HANDLE schSCM, schWINDS;
schSCM = OpenSCManager (0, 0, SC_MANAGER_CREATE_SERVICE);
if (NULL == schSCM)
{
hResult = HRESULT_FROM_WIN32 (GetLastError());
}
else
{
RestartInstall:
schWINDS = CreateService (schSCM,
WINDS_SERVICE_NAME_SHORT,
WINDS_SERVICE_NAME,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
dwStartType,
SERVICE_ERROR_NORMAL,
szFullPathToServiceExe,
NULL,
NULL,
NULL,
NULL,
NULL);
if (NULL == schWINDS)
{
hResult = HRESULT_FROM_WIN32 (GetLastError());
}
else
{
if (fStartImmediately)
{
StartService (schWINDS, 0, NULL);
}
CloseServiceHandle (schWINDS);
}
if (HRESULT_FROM_WIN32 (ERROR_SERVICE_EXISTS) == hResult)
{
RemoveWindsService();
goto RestartInstall;
}
CloseServiceHandle (schSCM);
}
TraceResult ("InstallWindsService", hResult);
return hResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoveWindsService()
//
// Parameters
//
// Purpose
//
// Return Value
//
HRESULT WINAPI RemoveWindsService()
{
HRESULT hResult = S_OK;
SC_HANDLE schSCM, schWINDS;
schSCM = OpenSCManager (0, 0, SC_MANAGER_CREATE_SERVICE);
if (NULL == schSCM)
{
hResult = HRESULT_FROM_WIN32 (GetLastError());
}
else
{
schWINDS = OpenService (schSCM,
WINDS_SERVICE_NAME_SHORT,
SERVICE_ALL_ACCESS);
if (NULL == schWINDS)
{
hResult = HRESULT_FROM_WIN32 (GetLastError());
}
else
{
SERVICE_STATUS ssState;
ControlService (schWINDS, SERVICE_CONTROL_STOP, &ssState);
DeleteService (schWINDS);
CloseServiceHandle (schWINDS);
}
CloseServiceHandle (schSCM);
}
TraceResult ("RemoveWindsService", hResult);
return hResult;
}

///////////////////////////////////////////////////////////////////////////////
// WinMain()
//
// Parameters
// { Refer to Win32 SDK documentation }
//
// Purpose
// This is the entry function. The application will start executing here.
//
// Return Value
// Return code of the application to the system.
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow)
{
InitTraces (TRACES_NO_ASSERT_DIALOG | TRACES_NO_COM_OUTPUT);
//InitTraces (TRACES_NO_ASSERT_DIALOG);
ghInstance = hInstance;
ghHeap = GetProcessHeap();

if (0 == lstrcmpi ("APP", pszCmdLine))
{
// Check for other instances of this application running. If one is found,
// bring it to the foreground
HWND hOtherInstance = FindWindow (MAINDLGCLASS, NULL);
if (NULL != hOtherInstance)
{
HWND hChildWnd = GetLastActivePopup (hOtherInstance);
if (hChildWnd != hOtherInstance)
{
BringWindowToTop (hOtherInstance);
}
else
{
SetForegroundWindow (hOtherInstance);
}
return 1;
}

RegisterWindsPrivateClass();

if (S_OK != InitWindsService())
{
return -1;
}

DialogBoxParam (ghInstance, MAKEINTRESOURCE(IDD_WINDS_APP), NULL, GenericDlgProc, (LPARAM)TRUE);

StopWindsService();

return 0;
}

if (0 == lstrcmpi ("INSTALL", pszCmdLine))
{
TCHAR szFullPath[_MAX_PATH] = { 0 };
GetCurrentDirectory (_MAX_PATH, szFullPath);
lstrcat (szFullPath, WINDS_SERVICE_EXECUTABLE);
if (S_OK != InstallWindsService (SERVICE_AUTO_START, szFullPath, TRUE))
{
return -1;
}
return 0;
}

if (0 == lstrcmpi ("REMOVE", pszCmdLine))
{
if (S_OK != RemoveWindsService())
{
return -1;
}
return 0;
}

SERVICE_TABLE_ENTRY ServiceTable[] =
{
{ WINDS_SERVICE_NAME,
(LPSERVICE_MAIN_FUNCTION)WindsServiceMain,
},
{ NULL, NULL }
};

if (FALSE == StartServiceCtrlDispatcher (ServiceTable))
{
if (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT == GetLastError())
{
RegisterWindsPrivateClass();
DialogBoxParam (ghInstance, MAKEINTRESOURCE(IDD_WINDS_DIALOG), NULL, GenericDlgProc, (LPARAM)FALSE);
}
}
return 0;
}

///////////////////////////////////////////////////////////////////////////////
// InitRPCServer()
//
// Parameters
//
// Purpose
//
// Return Value
//
BOOL WINAPI InitRPCServer()
{
#define MAX_NUM_OF_CALLS 65536
RPC_STATUS status = RpcServerUseProtseqEp ((WINDS_RPC_STRING)WINDS_RPC_PROTOCOL,
MAX_NUM_OF_CALLS,
(WINDS_RPC_STRING)WINDS_PROVIDERS_RPC_ENDPOINT,
NULL); // Security descriptor
if (status)
{
TraceMessage ("InitRPCServer: RpcServerUseProtseqEp failed (PROVIDER)");
goto ErrorExit;
}

status = RpcServerRegisterIf (WINDSREM_v1_6_s_ifspec, // Interface to register
NULL, // MgrTypeUuid
NULL); // MgrEpv; null means use default
if (status)
{
TraceMessage ("InitRPCServer: RpcServerRegisterIf failed (PROVIDER)");
goto ErrorExit;
}

status = RpcServerUseProtseqEp ((WINDS_RPC_STRING)WINDS_RPC_PROTOCOL,
MAX_NUM_OF_CALLS,
(WINDS_RPC_STRING)WINDS_ADMIN_RPC_ENDPOINT,
NULL); // Security descriptor
if (status)
{
TraceMessage ("InitRPCServer: RpcServerUseProtseqEp failed (ADMIN)");
goto ErrorExit;
}

status = RpcServerRegisterIf (WINDSADM_v1_0_s_ifspec, // Interface to register
NULL, // MgrTypeUuid
NULL); // MgrEpv; null means use default
if (status)
{
TraceMessage ("InitRPCServer: RpcServerRegisterIf failed (ADMIN)");
goto ErrorExit;
}

status = RpcServerListen (1, MAX_NUM_OF_CALLS, TRUE);
if (status)
{
TraceMessage ("InitRPCServer: RpcServerListen failed");
goto ErrorExit;
}
ErrorExit:
if (status)
{
TraceResult ("InitRPCServer", MAKE_HRESULT(1, FACILITY_RPC, status));
return FALSE;
}
return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// TerminateAllRPCServer()
//
// Parameters
//
// Purpose
//
// Return Value
//
BOOL WINAPI TerminateAllRPCServer()
{
RPC_STATUS status = RpcMgmtStopServerListening (NULL);
if (status)
{
TraceMessage ("TerminateRPCServer: RpcMgmtStopServerListening failed");
}
else
{
status = RpcServerUnregisterIf (NULL, NULL, FALSE);
if (status)
{
TraceMessage ("TerminateRPCServer: RpcServerUnregisterIf failed");
}
}
if (status)
{
TraceResult ("TerminateRPCServer", MAKE_HRESULT(1, FACILITY_RPC, status));
return FALSE;
}
return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// GetServiceState()
//
// Parameters
//
// Purpose
//
// Return Value
//
HRESULT WINAPI GetServiceState()
{
HRESULT hServiceState;
EnterCriticalSection (&g_csServiceState);
hServiceState = g_hServerState;
LeaveCriticalSection (&g_csServiceState);
return hServiceState;
}

///////////////////////////////////////////////////////////////////////////////
// PrivateDlgClassProc()
//
// Parameters
// { Refer to Win32 API documentation on dialog procedures }
//
// Purpose
//
// Return Value
//
LRESULT CALLBACK PrivateDlgClassProc (HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
return DefDlgProc (hDlg, message, wParam, lParam);
}

///////////////////////////////////////////////////////////////////////////////
// RegisterWindsPrivateClass()
//
// Parameters
//
// Purpose
//
// Return Value
//
void WINAPI RegisterWindsPrivateClass()
{
WNDCLASS wc = { 0 };
// Register the class for this application
wc.hInstance = ghInstance;
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.lpfnWndProc = PrivateDlgClassProc;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hIcon = LoadIcon (ghInstance, MAKEINTRESOURCE (IDI_WINDSSERVICE));
wc.lpszClassName = MAINDLGCLASS;
if (!RegisterClass (&wc))
{
TraceResult ("RegisterWindsPrivateClass: Failed to register the main class", HRESULT_FROM_WIN32(GetLastError()));
}
}

///////////////////////////////////////////////////////////////////////////////
// GenericDlgProc()
//
// Parameters
// { Refer to Win32 API documentation on dialog procedures }
//
// Purpose
//
// Return Value
// TRUE if message was handled, FALSE if we don't handle the message
//
BOOL CALLBACK GenericDlgProc (HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HRESULT hResult;
switch (message)
{
case WM_INITDIALOG :
if (TRUE == lParam)
{
ShowWindow (hDlg, SW_MINIMIZE);
}
else
{
if (!g_pctl3d)
{
BOOL f;
g_pctl3d = CTL3D_Initialize(ghInstance);
CTL3D_AutoSubclass(g_pctl3d, ghInstance, &f);
}
CenterDialogBox (hDlg);
}
return TRUE;

case WM_COMMAND :
switch (LOWORD(wParam))
{
case IDOK :
case IDCANCEL :
PostMessage (hDlg, WM_SYSCOMMAND, SC_CLOSE, 0);
return TRUE;

case IDC_INSTALL_SERVICE :
DialogBox (ghInstance, MAKEINTRESOURCE(IDD_INSTALL_OPTIONS), hDlg, InstallDlgProc);
break;

case IDC_REMOVE_SERVICE :
hResult = RemoveWindsService();
if (S_OK == hResult)
{
MessageBox (hDlg,
TEXT("Service successfully removed"),
TEXT("WINDS Services - Remove"),
MB_OK | MB_ICONEXCLAMATION);
}
else
{
MessageBox (hDlg,
TEXT("Failed to remove the service"),
TEXT("WINDS Services - Remove"),
MB_OK | MB_ICONSTOP);
}
break;
}
break;

case WM_SYSCOMMAND:
if (wParam == SC_CLOSE)
{
CTL3D_Uninitialize(g_pctl3d);
g_pctl3d = NULL;
EndDialog (hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
}

///////////////////////////////////////////////////////////////////////////////
// InstallDlgProc()
//
// Parameters
// { Refer to Win32 API documentation on dialog procedures }
//
// Purpose
//
// Return Value
// TRUE if message was handled, FALSE if we don't handle the message
//
BOOL CALLBACK InstallDlgProc (HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TCHAR szFullPath[_MAX_PATH];
DWORD dwStart;
BOOL fStartNow;
switch (message)
{
case WM_INITDIALOG :
CenterDialogBox (hDlg);
Edit_LimitText (GetDlgItem (hDlg, IDC_SERVICE_FILEPATH), _MAX_PATH - 1);
GetCurrentDirectory (_MAX_PATH, szFullPath);
lstrcat (szFullPath, WINDS_SERVICE_EXECUTABLE);
SetWindowText (GetDlgItem (hDlg, IDC_SERVICE_FILEPATH), szFullPath);
Button_SetCheck (GetDlgItem (hDlg, IDC_AUTO_START), BST_CHECKED);
Button_SetCheck (GetDlgItem (hDlg, IDC_START_NOW), BST_CHECKED);

return TRUE; 

case WM_COMMAND :
switch (LOWORD(wParam))
{
case IDOK :
GetWindowText (GetDlgItem (hDlg, IDC_SERVICE_FILEPATH), szFullPath, _MAX_PATH);
if (BST_CHECKED == Button_GetCheck (GetDlgItem (hDlg, IDC_AUTO_START)))
{
dwStart = SERVICE_AUTO_START;
}
else
{
dwStart = SERVICE_DEMAND_START;
}
if (BST_CHECKED == Button_GetCheck (GetDlgItem (hDlg, IDC_START_NOW)))
{
fStartNow = TRUE;
}
else
{
fStartNow = FALSE;
}
if (lstrlen (szFullPath) && S_OK == InstallWindsService (dwStart, szFullPath, fStartNow))
{
MessageBox (hDlg,
TEXT("Service successfully installed"),
TEXT("WINDS Services - Install"),
MB_OK | MB_ICONEXCLAMATION);
}
else
{
MessageBox (hDlg,
TEXT("Failed to install the service"),
TEXT("WINDS Services - Install"),
MB_OK | MB_ICONSTOP);
}
// Fall through
case IDCANCEL :
EndDialog (hDlg, TRUE);
return TRUE;
}
}
return FALSE;
}

// End of file for SERVICE.CPP