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.

421 lines
12 KiB

  1. /*++
  2. Copyright (c) 1992-1999 Microsoft Corporation
  3. Module Name:
  4. regthrd.c
  5. Abstract:
  6. Contains routines for thread listening to registry changes.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. Rajat Goel -- 24 Feb 1999
  11. - Creation
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include "globals.h"
  19. #include "contexts.h"
  20. #include "regions.h"
  21. #include "snmpmgrs.h"
  22. #include "trapmgrs.h"
  23. #include "trapthrd.h"
  24. #include "network.h"
  25. #include "varbinds.h"
  26. #include "snmpmgmt.h"
  27. #include "registry.h"
  28. #include <stdio.h>
  29. ///////////////////////////////////////////////////////////////////////////////
  30. // //
  31. // Private procedures //
  32. // //
  33. ///////////////////////////////////////////////////////////////////////////////
  34. DWORD
  35. ProcessSubagentChanges(
  36. )
  37. /*++
  38. Routine Description:
  39. Procedure for checking for any changes in the Extension Agents parameter in
  40. the registry
  41. Arguments:
  42. Return Values:
  43. Returns true if successful.
  44. --*/
  45. {
  46. DWORD retval;
  47. DWORD cnt;
  48. HKEY hExAgentsKey = NULL;
  49. // Open the ..SNMP\Parameters\ExtensionAgents key
  50. retval = RegOpenKeyEx(
  51. HKEY_LOCAL_MACHINE,
  52. REG_KEY_EXTENSION_AGENTS,
  53. 0,
  54. KEY_READ,
  55. &hExAgentsKey
  56. );
  57. cnt = 0;
  58. if (retval != ERROR_SUCCESS)
  59. {
  60. LPTSTR pszKey = REG_KEY_EXTENSION_AGENTS;
  61. ReportSnmpEvent(
  62. SNMP_EVENT_INVALID_REGISTRY_KEY,
  63. 1,
  64. &pszKey,
  65. retval);
  66. return retval;
  67. }
  68. while (retval == ERROR_SUCCESS)
  69. {
  70. DWORD dwNameSize;
  71. DWORD dwValueSize;
  72. DWORD dwValueType;
  73. DWORD dwPathSize;
  74. HKEY hAgentKey = NULL;
  75. TCHAR szName[MAX_PATH];
  76. TCHAR szValue[MAX_PATH];
  77. CHAR szPath[MAX_PATH];
  78. CHAR szExpPath[MAX_PATH];
  79. PSUBAGENT_LIST_ENTRY pSLE = NULL;
  80. dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
  81. dwValueSize = sizeof(szValue); // size in number of bytes
  82. dwPathSize = sizeof(szPath);
  83. // Retrieve the registry path for the Extension Agent DLL key
  84. retval = RegEnumValue(
  85. hExAgentsKey,
  86. cnt,
  87. szName,
  88. &dwNameSize,
  89. NULL,
  90. &dwValueType,
  91. (LPBYTE)szValue,
  92. &dwValueSize
  93. );
  94. // if failed to Enum the registry value, this is serious enough to break the loop
  95. if (retval != ERROR_SUCCESS)
  96. break;
  97. if (dwValueType != REG_SZ)
  98. {
  99. // invalid value type, skip
  100. cnt++;
  101. continue;
  102. }
  103. // Open the registry key for the current extension agent
  104. if (RegOpenKeyEx(
  105. HKEY_LOCAL_MACHINE,
  106. szValue,
  107. 0,
  108. KEY_READ,
  109. &hAgentKey) == ERROR_SUCCESS)
  110. {
  111. // get the full pathname of the extension agent DLL
  112. if (RegQueryValueExA(
  113. hAgentKey,
  114. REG_VALUE_SUBAGENT_PATH,
  115. NULL,
  116. &dwValueType,
  117. szPath,
  118. &dwPathSize
  119. ) == ERROR_SUCCESS &&
  120. (dwValueType == REG_EXPAND_SZ || dwValueType == REG_SZ))
  121. {
  122. DWORD dwRet = 0;
  123. // Expand path
  124. // If the function succeeds, the return value is the number of
  125. // TCHARs stored in the destination buffer, including the
  126. // terminating null character. If the destination buffer is too
  127. // small to hold the expanded string, the return value is the
  128. // required buffer size, in TCHARs.
  129. // If the function fails, the return value is zero. To get
  130. // extended error information, call GetLastError.
  131. dwRet = ExpandEnvironmentStringsA(
  132. szPath,
  133. szExpPath,
  134. sizeof(szExpPath)/sizeof(szExpPath[0]));
  135. if ((dwRet != 0) && (dwRet <= sizeof(szExpPath)/sizeof(szExpPath[0])))
  136. {
  137. // Check if the DLL has already been loaded. If it has,
  138. // mark it. If not load it.
  139. if (FindSubagent(&pSLE, szExpPath))
  140. {
  141. // If this extension agent already exists in the list,
  142. // mark it such that it is not removed further
  143. pSLE->uchFlags |= FLG_SLE_KEEP;
  144. }
  145. else
  146. {
  147. // This is a new DLL, add it to the list and mark it to be kept
  148. // while looking for the extension agents to be removed
  149. if (!AddSubagentByDll(szExpPath, FLG_SLE_KEEP))
  150. {
  151. SNMPDBG((
  152. SNMP_LOG_ERROR,
  153. "SNMP: SVC: unable to load extension agent '%s'.\n",
  154. szExpPath
  155. ));
  156. }
  157. }
  158. }
  159. else
  160. {
  161. SNMPDBG((
  162. SNMP_LOG_ERROR,
  163. "SNMP: SVC: unable to expand extension agent path '%s'.\n",
  164. szPath
  165. ));
  166. }
  167. }
  168. else
  169. {
  170. // we couldn't open the registry key which provides the full path to the DLL.
  171. // report the error but don't break the loop as there might be more subagents to handle
  172. SNMPDBG((
  173. SNMP_LOG_ERROR,
  174. "SNMP: SVC: unable to retrieve extension agent '%s' value.\n",
  175. REG_VALUE_SUBAGENT_PATH
  176. ));
  177. }
  178. RegCloseKey(hAgentKey);
  179. }
  180. else
  181. {
  182. LPTSTR pSzValue = szValue;
  183. SNMPDBG((
  184. SNMP_LOG_ERROR,
  185. "SNMP: SVC: unable to open extension agent %s key.\n", szValue
  186. ));
  187. ReportSnmpEvent(
  188. SNMP_EVENT_INVALID_EXTENSION_AGENT_KEY,
  189. 1,
  190. &pSzValue,
  191. retval);
  192. }
  193. cnt++;
  194. }
  195. // Go through the list of subagents. Unload any DLL's that were not marked
  196. // in the previous loop
  197. {
  198. PLIST_ENTRY pLE;
  199. PSUBAGENT_LIST_ENTRY pSLE;
  200. pLE = g_Subagents.Flink;
  201. while (pLE != &g_Subagents)
  202. {
  203. pSLE = CONTAINING_RECORD(pLE, SUBAGENT_LIST_ENTRY, Link);
  204. if (!(pSLE->uchFlags & FLG_SLE_KEEP))
  205. {
  206. RemoveEntryList(&(pSLE->Link));
  207. pLE = pLE->Flink;
  208. FreeSLE(pSLE);
  209. continue;
  210. }
  211. else
  212. {
  213. // reset the flag for next updates
  214. pSLE->uchFlags ^= FLG_SLE_KEEP;
  215. }
  216. pLE = pLE->Flink;
  217. }
  218. }
  219. if (retval == ERROR_NO_MORE_ITEMS)
  220. retval = ERROR_SUCCESS;
  221. if (hExAgentsKey != NULL)
  222. RegCloseKey(hExAgentsKey);
  223. return retval;
  224. }
  225. ///////////////////////////////////////////////////////////////////////////////
  226. // //
  227. // Public procedures //
  228. // //
  229. ///////////////////////////////////////////////////////////////////////////////
  230. DWORD
  231. ProcessRegistryMessage(
  232. PVOID pParam
  233. )
  234. /*++
  235. Routine Description:
  236. Thread procedure for processing Registry Changes
  237. Arguments:
  238. pParam - unused.
  239. Return Values:
  240. Returns true if successful.
  241. --*/
  242. {
  243. DWORD retval = ERROR_SUCCESS;
  244. do
  245. {
  246. DWORD evntIndex;
  247. BOOL bEvntSetOk;
  248. // Wait for registry change or Main thread termination
  249. evntIndex = WaitOnRegNotification();
  250. // for one change into the registry several notifications occur (key renaming, value addition,
  251. // value change, etc). In order to avoid useless (and counterproductive) notifications, wait
  252. // here for half of SHUTDOWN_WAIT_HINT.
  253. Sleep(SHUTDOWN_WAIT_HINT/2);
  254. // first thing to do is to re initialize the registry notifiers
  255. // otherwise we might miss some changes
  256. InitRegistryNotifiers();
  257. if (evntIndex == WAIT_FAILED)
  258. {
  259. retval = GetLastError();
  260. break;
  261. }
  262. if (evntIndex == WAIT_OBJECT_0)
  263. {
  264. // termination was signaled
  265. SNMPDBG((
  266. SNMP_LOG_TRACE,
  267. "SNMP: SVC: shutting down the registry listener thread.\n"
  268. ));
  269. break;
  270. }
  271. //
  272. // unload and reload the registry parameters
  273. //
  274. // Used in ProcessSnmpMessages->RecvCompletionRoutine
  275. EnterCriticalSection(&g_RegCriticalSectionA);
  276. // Used in ProcessSubagentEvents
  277. EnterCriticalSection(&g_RegCriticalSectionB);
  278. // Used in GenerateTrap
  279. EnterCriticalSection(&g_RegCriticalSectionC);
  280. UnloadPermittedManagers();
  281. UnloadTrapDestinations();
  282. UnloadValidCommunities();
  283. UnloadSupportedRegions();
  284. // start reloading the registry with scalar parameters first
  285. // this is needed in order to know how to perform the name resolution
  286. // when loading PermittedManagers and TrapDestinations.
  287. LoadScalarParameters();
  288. // Check for subagent changes (extension agent dll's)
  289. if (ProcessSubagentChanges() != ERROR_SUCCESS)
  290. SNMPDBG((
  291. SNMP_LOG_TRACE,
  292. "SNMP: SVC: an error occured while trying to track registry subagent changes.\n"
  293. ));
  294. LoadSupportedRegions();
  295. LoadPermittedManagers(FALSE);
  296. LoadTrapDestinations(FALSE);
  297. // don't direct dynamic update for the ValidCommunities at this point!
  298. // if a REG_SZ entry occurs at this time, then it should be left as it is.
  299. LoadValidCommunities(FALSE);
  300. SetEvent(g_hRegistryEvent);
  301. LeaveCriticalSection(&g_RegCriticalSectionC);
  302. LeaveCriticalSection(&g_RegCriticalSectionB);
  303. LeaveCriticalSection(&g_RegCriticalSectionA);
  304. SNMPDBG((
  305. SNMP_LOG_TRACE,
  306. "SNMP: SVC: a registry change was detected.\n"
  307. ));
  308. ReportSnmpEvent(
  309. SNMP_EVENT_CONFIGURATION_UPDATED,
  310. 0,
  311. NULL,
  312. 0);
  313. } while(retval == ERROR_SUCCESS);
  314. if (retval != ERROR_SUCCESS)
  315. {
  316. SNMPDBG((
  317. SNMP_LOG_ERROR,
  318. "SNMP: SVC: ** Failed in listening for registry changes **.\n"
  319. ));
  320. // log an event to system log file - SNMP service is going on but will not update on registry changes
  321. ReportSnmpEvent(
  322. SNMP_EVENT_REGNOTIFY_THREAD_FAILED,
  323. 0,
  324. NULL,
  325. retval);
  326. }
  327. return retval;
  328. }