/////////////////////////////////////////////////////////////////////////////// // // 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 #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; }