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

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // ALG.cpp : Implementation of WinMain
  4. //
  5. //
  6. // JPDup - 2000.12.15
  7. //
  8. //
  9. #include "PreComp.h"
  10. #include "AlgController.h"
  11. #include "ApplicationGatewayServices.h"
  12. #include "PrimaryControlChannel.h"
  13. #include "SecondaryControlChannel.h"
  14. #include "PendingProxyConnection.h"
  15. #include "DataChannel.h"
  16. #include "AdapterInfo.h"
  17. #include "PersistentDataChannel.h"
  18. #include <initguid.h>
  19. #include "..\ALG_FTP\MyALG.h"
  20. //
  21. // GLOBALS
  22. //
  23. MYTRACE_ENABLE; // Define Tracing globals see MyTrace.h
  24. CComModule _Module;
  25. HINSTANCE g_hInstance=NULL;
  26. HANDLE g_EventKeepAlive=NULL;
  27. HANDLE g_EventRegUpdates=NULL;
  28. SERVICE_STATUS g_MyServiceStatus;
  29. SERVICE_STATUS_HANDLE g_MyServiceStatusHandle;
  30. BEGIN_OBJECT_MAP(ObjectMap)
  31. OBJECT_ENTRY(CLSID_AlgController, CAlgController)
  32. OBJECT_ENTRY(CLSID_ApplicationGatewayServices, CApplicationGatewayServices)
  33. OBJECT_ENTRY(CLSID_PrimaryControlChannel, CPrimaryControlChannel)
  34. OBJECT_ENTRY(CLSID_SecondaryControlChannel, CSecondaryControlChannel)
  35. OBJECT_ENTRY(CLSID_PendingProxyConnection, CPendingProxyConnection)
  36. OBJECT_ENTRY(CLSID_DataChannel, CDataChannel)
  37. OBJECT_ENTRY(CLSID_AdapterInfo, CAdapterInfo)
  38. OBJECT_ENTRY(CLSID_PersistentDataChannel, CPersistentDataChannel)
  39. OBJECT_ENTRY(CLSID_AlgFTP, CAlgFTP)
  40. // OBJECT_ENTRY(CLSID_AlgICQ, CAlgICQ)
  41. END_OBJECT_MAP()
  42. //
  43. ///
  44. //
  45. VOID
  46. MyServiceCtrlHandler(
  47. DWORD Opcode
  48. )
  49. {
  50. MYTRACE_ENTER("ALG.exe::MyServiceCtrlHandler");
  51. DWORD status;
  52. switch(Opcode)
  53. {
  54. case SERVICE_CONTROL_PAUSE:
  55. MYTRACE("SERVICE_CONTROL_PAUSE");
  56. // Do whatever it takes to pause here.
  57. g_MyServiceStatus.dwCurrentState = SERVICE_PAUSED;
  58. break;
  59. case SERVICE_CONTROL_CONTINUE:
  60. MYTRACE("SERVICE_CONTROL_CONTINUE");
  61. // Do whatever it takes to continue here.
  62. g_MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
  63. break;
  64. case SERVICE_CONTROL_STOP:
  65. MYTRACE("SERVICE_CONTROL_STOP");
  66. // Do whatever it takes to stop here.
  67. g_MyServiceStatus.dwWin32ExitCode = 0;
  68. g_MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
  69. g_MyServiceStatus.dwCheckPoint = 0;
  70. g_MyServiceStatus.dwWaitHint = 0;
  71. if (!SetServiceStatus(g_MyServiceStatusHandle, &g_MyServiceStatus))
  72. {
  73. MYTRACE_ERROR("SetServiceStatus ",0);
  74. }
  75. MYTRACE("Leaving MyService");
  76. return;
  77. case SERVICE_CONTROL_INTERROGATE:
  78. MYTRACE("SERVICE_CONTROL_STOP");
  79. break;
  80. default:
  81. MYTRACE("Unrecognized opcode %ld", Opcode);
  82. }
  83. // Send current status.
  84. if (!SetServiceStatus (g_MyServiceStatusHandle, &g_MyServiceStatus))
  85. {
  86. MYTRACE_ERROR("SetServiceStatus error ",0);
  87. }
  88. return;
  89. }
  90. //
  91. // Stub initialization function.
  92. //
  93. DWORD
  94. MyServiceInitialization(
  95. DWORD argc,
  96. LPTSTR* argv
  97. )
  98. {
  99. MYTRACE_ENTER("ALG.exe::MyServiceInitialization");
  100. DWORD status;
  101. DWORD specificError;
  102. g_MyServiceStatus.dwServiceType = SERVICE_WIN32;
  103. g_MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  104. g_MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;// | SERVICE_ACCEPT_PAUSE_CONTINUE;
  105. g_MyServiceStatus.dwWin32ExitCode = 0;
  106. g_MyServiceStatus.dwServiceSpecificExitCode = 0;
  107. g_MyServiceStatus.dwCheckPoint = 0;
  108. g_MyServiceStatus.dwWaitHint = 0;
  109. g_MyServiceStatusHandle = RegisterServiceCtrlHandler(TEXT("ALG"), MyServiceCtrlHandler);
  110. if ( g_MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0 )
  111. {
  112. MYTRACE_ERROR("RegisterServiceCtrlHandler",0);
  113. return GetLastError();
  114. }
  115. /*
  116. // Handle error condition
  117. if (status != NO_ERROR)
  118. {
  119. g_MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
  120. g_MyServiceStatus.dwCheckPoint = 0;
  121. g_MyServiceStatus.dwWaitHint = 0;
  122. g_MyServiceStatus.dwWin32ExitCode = status;
  123. g_MyServiceStatus.dwServiceSpecificExitCode = specificError;
  124. SetServiceStatus (g_MyServiceStatusHandle, &g_MyServiceStatus);
  125. return;
  126. }
  127. */
  128. //
  129. // Initialise COM
  130. //
  131. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  132. _ASSERTE(SUCCEEDED(hr));
  133. _Module.Init(
  134. ObjectMap,
  135. g_hInstance,
  136. &LIBID_ALGLib
  137. );
  138. //
  139. // Register the CLASS with the ROT
  140. //
  141. MYTRACE(">>>>>> RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE)");
  142. hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
  143. _ASSERTE(SUCCEEDED(hr));
  144. if ( FAILED(hr) )
  145. {
  146. MYTRACE_ERROR("RegisterClassObject", hr);
  147. }
  148. // Initialization complete - report running status.
  149. g_MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
  150. g_MyServiceStatus.dwCheckPoint = 0;
  151. g_MyServiceStatus.dwWaitHint = 0;
  152. if (!SetServiceStatus (g_MyServiceStatusHandle, &g_MyServiceStatus))
  153. {
  154. MYTRACE_ERROR("SetServiceStatus error",0);
  155. return GetLastError();
  156. }
  157. return NO_ERROR;
  158. }
  159. //
  160. // Since the RegNotifyChangeKeyValue is call at two place in MyServiceMain
  161. // I created a function to clean up the code.
  162. //
  163. void
  164. SetRegNotifyEvent(
  165. CRegKey& RegKeyToWatch
  166. )
  167. {
  168. MYTRACE_ENTER("ALG.exe::SetRegNotifyEvent");
  169. //
  170. // Watch the registry key for a change of value.
  171. //
  172. LONG nError = RegNotifyChangeKeyValue(
  173. RegKeyToWatch,
  174. TRUE,
  175. REG_NOTIFY_CHANGE_LAST_SET,
  176. g_EventRegUpdates,
  177. TRUE
  178. );
  179. if ( ERROR_SUCCESS != nError )
  180. {
  181. MYTRACE_ERROR("Error calling RegNotifyChangeKeyValue", nError);
  182. return;
  183. }
  184. }
  185. //
  186. // This is the entry point call by the Service Control manager
  187. // This EXE stays loaded until the AlgController->Stop is invoke by rmALG-ICS it does that via a event
  188. // and this is the thread that wait for that event to be signal
  189. //
  190. void
  191. MyServiceMain(
  192. DWORD argc,
  193. LPTSTR* argv
  194. )
  195. {
  196. MYTRACE_ENTER("ALG.exe::MyServiceMain");
  197. //
  198. // This will satisfy the Service control mananager and also initialise COM
  199. //
  200. MyServiceInitialization(argc, argv);
  201. //
  202. // Open a key to be watch doged on
  203. //
  204. CRegKey KeyAlgISV;
  205. LONG nError = KeyAlgISV.Open(HKEY_LOCAL_MACHINE, REGKEY_ALG_ISV, KEY_NOTIFY);
  206. if (ERROR_SUCCESS != nError)
  207. {
  208. MYTRACE_ERROR("Error in opening ALG_ISV regkey", GetLastError());
  209. goto cleanup;
  210. }
  211. //
  212. // Create an events.
  213. //
  214. g_EventKeepAlive = CreateEvent(NULL, false, false, NULL);
  215. g_EventRegUpdates= CreateEvent(NULL, false, false, NULL);
  216. if ( !g_EventKeepAlive || !g_EventRegUpdates )
  217. {
  218. MYTRACE_ERROR("Error in CreateEvent", GetLastError());
  219. goto cleanup;
  220. }
  221. //
  222. // Ok no problem we set a registry notification
  223. //
  224. SetRegNotifyEvent(KeyAlgISV);
  225. //
  226. // These are the event we will wait for.
  227. //
  228. HANDLE hArrayOfEvent[] = {g_EventKeepAlive, g_EventRegUpdates};
  229. //
  230. // Main wait loop
  231. //
  232. while ( true )
  233. {
  234. MYTRACE("");
  235. MYTRACE("(-(-(-(- Waiting for Shutdown or Registry update-)-)-)-)\n");
  236. DWORD nRet = WaitForMultipleObjects(
  237. sizeof(hArrayOfEvent)/sizeof(HANDLE), // number of handles in array
  238. hArrayOfEvent, // object-handle array
  239. false, // wait option, FALSE mean then can be signal individualy
  240. INFINITE // time-out interval
  241. );
  242. //
  243. // We are no longet waiting, let's see what trigger this wake up
  244. //
  245. if ( WAIT_FAILED == nRet ) // Had a problem wainting
  246. {
  247. MYTRACE_ERROR("Main thread could not WaitForMulipleObject got a WAIT_FAILED",0);
  248. break;
  249. }
  250. else
  251. if ( WAIT_OBJECT_0 + 1 == nRet ) // g_EventRegUpdate got signaled
  252. {
  253. //
  254. // Some changes occured in the Registry we need to reload or disables some ALG modules
  255. //
  256. MYTRACE("");
  257. MYTRACE(")-)-) got signal Registry Changed (-(-(\n");
  258. if ( g_pAlgController )
  259. g_pAlgController->ConfigurationUpdated();
  260. SetRegNotifyEvent(KeyAlgISV);
  261. }
  262. else
  263. if ( WAIT_OBJECT_0 + 0 == nRet ) // g_EventKeepAlive got signaled
  264. {
  265. //
  266. // Signal to terminate this process
  267. //
  268. MYTRACE("");
  269. MYTRACE(")-)-) got signal Shutdown (-(-(\n");
  270. break;
  271. }
  272. }
  273. cleanup:
  274. MYTRACE("CleanUp*******************");
  275. //
  276. // We are done no COm object will be supported by ALG.exe anymore
  277. // the RevokeClassObjects could be done sooner Like just after the CAlgControl::Initialize is done
  278. // since only the IPNATHLP can call use and is consuming this only once
  279. // be because of the hosting of the ALG_ICQ and ALG_FTP we need o have the ROT class available
  280. // even after we are initialize.
  281. //
  282. MYTRACE("<<<<< RevokeClassObjects");
  283. _Module.RevokeClassObjects();
  284. //
  285. // Close the event handles.
  286. //
  287. if (g_EventKeepAlive)
  288. {
  289. CloseHandle(g_EventKeepAlive);
  290. }
  291. if (g_EventRegUpdates)
  292. {
  293. CloseHandle(g_EventRegUpdates);
  294. }
  295. Sleep(500); // Give the AlgController->Release() called by rmALG the time to cleanup
  296. //
  297. // We are done with COM
  298. //
  299. _Module.Term();
  300. CoUninitialize();
  301. //
  302. // we are all done here time to stop the Service
  303. //
  304. MYTRACE("SetServiceStatus 'SERVICE_STOPPED'");
  305. g_MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
  306. g_MyServiceStatus.dwCheckPoint = 0;
  307. g_MyServiceStatus.dwWaitHint = 0;
  308. if (!SetServiceStatus(g_MyServiceStatusHandle, &g_MyServiceStatus))
  309. {
  310. MYTRACE_ERROR("SetServiceStatus error for SERVICE_STOPPED",0);
  311. return;
  312. }
  313. return;
  314. }
  315. /////////////////////////////////////////////////////////////////////////////
  316. //
  317. // Starting point of this process
  318. //
  319. //
  320. extern "C" int WINAPI
  321. _tWinMain(
  322. HINSTANCE hInstance,
  323. HINSTANCE hPrevInstance,
  324. LPTSTR pzCmdLine,
  325. int nShowCmd
  326. )
  327. {
  328. MYTRACE_START(L"ALG");
  329. MYTRACE_ENTER("ALG.exe::WinMain");
  330. g_hInstance = hInstance;
  331. SERVICE_TABLE_ENTRY DispatchTable[] =
  332. {
  333. { TEXT("ALG"), MyServiceMain },
  334. { NULL, NULL }
  335. };
  336. if (!StartServiceCtrlDispatcher(DispatchTable))
  337. {
  338. MYTRACE_ERROR("StartServiceCtrlDispatcher error",00);
  339. return 0;
  340. }
  341. MYTRACE("Exiting");
  342. MYTRACE_STOP;
  343. return 0;
  344. }