Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

457 lines
12 KiB

///////////////////////////////////////////////////////////////////////////////
//
// ALG.cpp : Implementation of WinMain
//
//
// JPDup - 2000.12.15
//
//
#include "PreComp.h"
#include "AlgController.h"
#include "ApplicationGatewayServices.h"
#include "PrimaryControlChannel.h"
#include "SecondaryControlChannel.h"
#include "PendingProxyConnection.h"
#include "DataChannel.h"
#include "AdapterInfo.h"
#include "PersistentDataChannel.h"
#include <initguid.h>
#include "..\ALG_FTP\MyALG.h"
//
// GLOBALS
//
MYTRACE_ENABLE; // Define Tracing globals see MyTrace.h
CComModule _Module;
HINSTANCE g_hInstance=NULL;
HANDLE g_EventKeepAlive=NULL;
HANDLE g_EventRegUpdates=NULL;
SERVICE_STATUS g_MyServiceStatus;
SERVICE_STATUS_HANDLE g_MyServiceStatusHandle;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_AlgController, CAlgController)
OBJECT_ENTRY(CLSID_ApplicationGatewayServices, CApplicationGatewayServices)
OBJECT_ENTRY(CLSID_PrimaryControlChannel, CPrimaryControlChannel)
OBJECT_ENTRY(CLSID_SecondaryControlChannel, CSecondaryControlChannel)
OBJECT_ENTRY(CLSID_PendingProxyConnection, CPendingProxyConnection)
OBJECT_ENTRY(CLSID_DataChannel, CDataChannel)
OBJECT_ENTRY(CLSID_AdapterInfo, CAdapterInfo)
OBJECT_ENTRY(CLSID_PersistentDataChannel, CPersistentDataChannel)
OBJECT_ENTRY(CLSID_AlgFTP, CAlgFTP)
// OBJECT_ENTRY(CLSID_AlgICQ, CAlgICQ)
END_OBJECT_MAP()
//
///
//
VOID
MyServiceCtrlHandler(
DWORD Opcode
)
{
MYTRACE_ENTER("ALG.exe::MyServiceCtrlHandler");
DWORD status;
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
MYTRACE("SERVICE_CONTROL_PAUSE");
// Do whatever it takes to pause here.
g_MyServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
MYTRACE("SERVICE_CONTROL_CONTINUE");
// Do whatever it takes to continue here.
g_MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
MYTRACE("SERVICE_CONTROL_STOP");
// Do whatever it takes to stop here.
g_MyServiceStatus.dwWin32ExitCode = 0;
g_MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_MyServiceStatus.dwCheckPoint = 0;
g_MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(g_MyServiceStatusHandle, &g_MyServiceStatus))
{
MYTRACE_ERROR("SetServiceStatus ",0);
}
MYTRACE("Leaving MyService");
return;
case SERVICE_CONTROL_INTERROGATE:
MYTRACE("SERVICE_CONTROL_STOP");
break;
default:
MYTRACE("Unrecognized opcode %ld", Opcode);
}
// Send current status.
if (!SetServiceStatus (g_MyServiceStatusHandle, &g_MyServiceStatus))
{
MYTRACE_ERROR("SetServiceStatus error ",0);
}
return;
}
//
// Stub initialization function.
//
DWORD
MyServiceInitialization(
DWORD argc,
LPTSTR* argv
)
{
MYTRACE_ENTER("ALG.exe::MyServiceInitialization");
DWORD status;
DWORD specificError;
g_MyServiceStatus.dwServiceType = SERVICE_WIN32;
g_MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;// | SERVICE_ACCEPT_PAUSE_CONTINUE;
g_MyServiceStatus.dwWin32ExitCode = 0;
g_MyServiceStatus.dwServiceSpecificExitCode = 0;
g_MyServiceStatus.dwCheckPoint = 0;
g_MyServiceStatus.dwWaitHint = 0;
g_MyServiceStatusHandle = RegisterServiceCtrlHandler(TEXT("ALG"), MyServiceCtrlHandler);
if ( g_MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0 )
{
MYTRACE_ERROR("RegisterServiceCtrlHandler",0);
return GetLastError();
}
/*
// Handle error condition
if (status != NO_ERROR)
{
g_MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_MyServiceStatus.dwCheckPoint = 0;
g_MyServiceStatus.dwWaitHint = 0;
g_MyServiceStatus.dwWin32ExitCode = status;
g_MyServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus (g_MyServiceStatusHandle, &g_MyServiceStatus);
return;
}
*/
//
// Initialise COM
//
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hr));
_Module.Init(
ObjectMap,
g_hInstance,
&LIBID_ALGLib
);
//
// Register the CLASS with the ROT
//
MYTRACE(">>>>>> RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE)");
hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hr));
if ( FAILED(hr) )
{
MYTRACE_ERROR("RegisterClassObject", hr);
}
// Initialization complete - report running status.
g_MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_MyServiceStatus.dwCheckPoint = 0;
g_MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (g_MyServiceStatusHandle, &g_MyServiceStatus))
{
MYTRACE_ERROR("SetServiceStatus error",0);
return GetLastError();
}
return NO_ERROR;
}
//
// Since the RegNotifyChangeKeyValue is call at two place in MyServiceMain
// I created a function to clean up the code.
//
void
SetRegNotifyEvent(
CRegKey& RegKeyToWatch
)
{
MYTRACE_ENTER("ALG.exe::SetRegNotifyEvent");
//
// Watch the registry key for a change of value.
//
LONG nError = RegNotifyChangeKeyValue(
RegKeyToWatch,
TRUE,
REG_NOTIFY_CHANGE_LAST_SET,
g_EventRegUpdates,
TRUE
);
if ( ERROR_SUCCESS != nError )
{
MYTRACE_ERROR("Error calling RegNotifyChangeKeyValue", nError);
return;
}
}
//
// This is the entry point call by the Service Control manager
// This EXE stays loaded until the AlgController->Stop is invoke by rmALG-ICS it does that via a event
// and this is the thread that wait for that event to be signal
//
void
MyServiceMain(
DWORD argc,
LPTSTR* argv
)
{
MYTRACE_ENTER("ALG.exe::MyServiceMain");
//
// This will satisfy the Service control mananager and also initialise COM
//
MyServiceInitialization(argc, argv);
//
// Open a key to be watch doged on
//
CRegKey KeyAlgISV;
LONG nError = KeyAlgISV.Open(HKEY_LOCAL_MACHINE, REGKEY_ALG_ISV, KEY_NOTIFY);
if (ERROR_SUCCESS != nError)
{
MYTRACE_ERROR("Error in opening ALG_ISV regkey", GetLastError());
goto cleanup;
}
//
// Create an events.
//
g_EventKeepAlive = CreateEvent(NULL, false, false, NULL);
g_EventRegUpdates= CreateEvent(NULL, false, false, NULL);
if ( !g_EventKeepAlive || !g_EventRegUpdates )
{
MYTRACE_ERROR("Error in CreateEvent", GetLastError());
goto cleanup;
}
//
// Ok no problem we set a registry notification
//
SetRegNotifyEvent(KeyAlgISV);
//
// These are the event we will wait for.
//
HANDLE hArrayOfEvent[] = {g_EventKeepAlive, g_EventRegUpdates};
//
// Main wait loop
//
while ( true )
{
MYTRACE("");
MYTRACE("(-(-(-(- Waiting for Shutdown or Registry update-)-)-)-)\n");
DWORD nRet = WaitForMultipleObjects(
sizeof(hArrayOfEvent)/sizeof(HANDLE), // number of handles in array
hArrayOfEvent, // object-handle array
false, // wait option, FALSE mean then can be signal individualy
INFINITE // time-out interval
);
//
// We are no longet waiting, let's see what trigger this wake up
//
if ( WAIT_FAILED == nRet ) // Had a problem wainting
{
MYTRACE_ERROR("Main thread could not WaitForMulipleObject got a WAIT_FAILED",0);
break;
}
else
if ( WAIT_OBJECT_0 + 1 == nRet ) // g_EventRegUpdate got signaled
{
//
// Some changes occured in the Registry we need to reload or disables some ALG modules
//
MYTRACE("");
MYTRACE(")-)-) got signal Registry Changed (-(-(\n");
if ( g_pAlgController )
g_pAlgController->ConfigurationUpdated();
SetRegNotifyEvent(KeyAlgISV);
}
else
if ( WAIT_OBJECT_0 + 0 == nRet ) // g_EventKeepAlive got signaled
{
//
// Signal to terminate this process
//
MYTRACE("");
MYTRACE(")-)-) got signal Shutdown (-(-(\n");
break;
}
}
cleanup:
MYTRACE("CleanUp*******************");
//
// We are done no COm object will be supported by ALG.exe anymore
// the RevokeClassObjects could be done sooner Like just after the CAlgControl::Initialize is done
// since only the IPNATHLP can call use and is consuming this only once
// be because of the hosting of the ALG_ICQ and ALG_FTP we need o have the ROT class available
// even after we are initialize.
//
MYTRACE("<<<<< RevokeClassObjects");
_Module.RevokeClassObjects();
//
// Close the event handles.
//
if (g_EventKeepAlive)
{
CloseHandle(g_EventKeepAlive);
}
if (g_EventRegUpdates)
{
CloseHandle(g_EventRegUpdates);
}
Sleep(500); // Give the AlgController->Release() called by rmALG the time to cleanup
//
// We are done with COM
//
_Module.Term();
CoUninitialize();
//
// we are all done here time to stop the Service
//
MYTRACE("SetServiceStatus 'SERVICE_STOPPED'");
g_MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_MyServiceStatus.dwCheckPoint = 0;
g_MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(g_MyServiceStatusHandle, &g_MyServiceStatus))
{
MYTRACE_ERROR("SetServiceStatus error for SERVICE_STOPPED",0);
return;
}
return;
}
/////////////////////////////////////////////////////////////////////////////
//
// Starting point of this process
//
//
extern "C" int WINAPI
_tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR pzCmdLine,
int nShowCmd
)
{
MYTRACE_START(L"ALG");
MYTRACE_ENTER("ALG.exe::WinMain");
g_hInstance = hInstance;
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ TEXT("ALG"), MyServiceMain },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
MYTRACE_ERROR("StartServiceCtrlDispatcher error",00);
return 0;
}
MYTRACE("Exiting");
MYTRACE_STOP;
return 0;
}