Source code of Windows XP (NT5)
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.

596 lines
14 KiB

  1. /*++
  2. Copyright (c) 1992-1997 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. Contains routines for manipulating registry parameters.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. 10-Feb-1997 DonRyan
  11. Rewrote to implement SNMPv2 support.
  12. --*/
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // //
  15. // Include files //
  16. // //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include "globals.h"
  19. #include "registry.h"
  20. #include "contexts.h"
  21. #include "regions.h"
  22. #include "trapmgrs.h"
  23. #include "snmpmgrs.h"
  24. #include "snmpmgmt.h"
  25. ///////////////////////////////////////////////////////////////////////////////
  26. // //
  27. // Private procedures //
  28. // //
  29. ///////////////////////////////////////////////////////////////////////////////
  30. ///////////////////////////////////////////////////////////////////////////////
  31. // //
  32. // Public procedures //
  33. // //
  34. ///////////////////////////////////////////////////////////////////////////////
  35. INT
  36. InitRegistryNotifiers(
  37. )
  38. /*++
  39. Routine Description:
  40. Setup registry notifiers
  41. Arguments:
  42. None.
  43. Return Values:
  44. Returns the number of events that have been registered successfully
  45. --*/
  46. {
  47. DWORD nEvents = 0;
  48. // on first call only create the default notifier
  49. if (g_hDefaultRegNotifier == NULL)
  50. g_hDefaultRegNotifier = CreateEvent(NULL, FALSE, FALSE, NULL);
  51. if (g_hDefaultKey == NULL)
  52. {
  53. RegOpenKeyEx(
  54. HKEY_LOCAL_MACHINE,
  55. REG_KEY_SNMP_PARAMETERS,
  56. 0,
  57. KEY_READ,
  58. &g_hDefaultKey
  59. );
  60. }
  61. // setup the default registry notifier
  62. if (g_hDefaultRegNotifier &&
  63. g_hDefaultKey &&
  64. RegNotifyChangeKeyValue(
  65. g_hDefaultKey,
  66. TRUE,
  67. REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
  68. g_hDefaultRegNotifier,
  69. TRUE
  70. ) == ERROR_SUCCESS)
  71. {
  72. SNMPDBG((SNMP_LOG_TRACE,
  73. "SNMP: REG: Default reg notifier initialized successfully.\n"));
  74. nEvents++;
  75. }
  76. #ifdef _POLICY
  77. // on first call only create the policy notifier
  78. if (g_hPolicyRegNotifier == NULL)
  79. g_hPolicyRegNotifier = CreateEvent(NULL, FALSE, FALSE, NULL);
  80. if (g_hPolicyKey == NULL)
  81. {
  82. RegOpenKeyEx(
  83. HKEY_LOCAL_MACHINE,
  84. REG_POLICY_ROOT,
  85. 0,
  86. KEY_READ,
  87. &g_hPolicyKey
  88. );
  89. }
  90. // setup the policy registry notifier
  91. if (g_hPolicyRegNotifier &&
  92. g_hPolicyKey &&
  93. RegNotifyChangeKeyValue(
  94. g_hPolicyKey,
  95. TRUE,
  96. REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
  97. g_hPolicyRegNotifier,
  98. TRUE
  99. ) == ERROR_SUCCESS)
  100. {
  101. SNMPDBG((SNMP_LOG_TRACE,
  102. "SNMP: REG: Policy reg notifier initialized successfully.\n"));
  103. nEvents++;
  104. }
  105. SNMPDBG((SNMP_LOG_TRACE,
  106. "SNMP: REG: Initialized notifiers ... %d.\n", nEvents));
  107. #endif
  108. return nEvents;
  109. }
  110. BOOL UnloadRegistryNotifiers();
  111. INT
  112. WaitOnRegNotification(
  113. )
  114. /*++
  115. Routine Description:
  116. Blocking call - waits for a notification that one of the registry parameters has change
  117. Arguments:
  118. None.
  119. Return Values:
  120. Returns the notifyer index (0 for the termination event, !=0 for parameter change)
  121. --*/
  122. {
  123. HANDLE hNotifiers[3]; // hack - we now (hardcoded) that we are not going to wait for more than three events.
  124. DWORD dwNotifiers = 0;
  125. DWORD retCode;
  126. hNotifiers[dwNotifiers++] = g_hTerminationEvent;
  127. if (g_hDefaultRegNotifier != NULL)
  128. hNotifiers[dwNotifiers++] = g_hDefaultRegNotifier;
  129. #ifdef _POLICY
  130. if (g_hPolicyRegNotifier != NULL)
  131. hNotifiers[dwNotifiers++] = g_hPolicyRegNotifier;
  132. #endif
  133. SNMPDBG((SNMP_LOG_WARNING,
  134. "SNMP: REG: Will listen for params changes on %d notifiers.\n",
  135. dwNotifiers));
  136. retCode = WaitForMultipleObjects(
  137. dwNotifiers,
  138. hNotifiers,
  139. FALSE,
  140. INFINITE);
  141. UnloadRegistryNotifiers();
  142. return retCode;
  143. }
  144. /*++
  145. Inplace parser for the string formatted OID.
  146. It is done in O(n) where n is the length of the string formatted OID (two passes)
  147. --*/
  148. BOOL
  149. ConvStringToOid(
  150. LPTSTR pStr,
  151. AsnObjectIdentifier *pOid)
  152. {
  153. LPTSTR pDup;
  154. int iComp;
  155. DWORD dwCompValue;
  156. enum
  157. { DOT,
  158. DIGIT
  159. } state = DIGIT;
  160. // no need to check for parameters consistency (internal call->correct call :o)
  161. // check the consistency and determine the number of components
  162. pOid->idLength = 0;
  163. if (*pStr == _T('.')) // skip a possible leading '.'
  164. pStr++;
  165. for (pDup = pStr; *pDup != _T('\0'); pDup++)
  166. {
  167. switch(state)
  168. {
  169. case DOT:
  170. // note: a trailing dot results in a trailing 0
  171. if (*pDup == _T('.'))
  172. {
  173. pOid->idLength++;
  174. state = DIGIT;
  175. break;
  176. }
  177. // intentionally missing 'break'
  178. case DIGIT:
  179. if (*pDup < _T('0') || *pDup > _T('9'))
  180. return FALSE;
  181. state = DOT;
  182. break;
  183. }
  184. }
  185. // add one to the id length as a trailing dot might not be present
  186. pOid->idLength++;
  187. // accept oids with two components at least;
  188. // alloc memory and check for success;
  189. if (pOid->idLength < 2 ||
  190. (pOid->ids = SnmpUtilMemAlloc(pOid->idLength * sizeof(UINT))) == NULL)
  191. return FALSE;
  192. // we have now enough buffer and a correct input string. Just convert it to OID
  193. iComp = 0;
  194. dwCompValue = 0;
  195. for (pDup = pStr; *pDup != _T('\0'); pDup++)
  196. {
  197. if (*pDup == _T('.'))
  198. {
  199. pOid->ids[iComp++] = dwCompValue;
  200. dwCompValue = 0;
  201. }
  202. else
  203. {
  204. dwCompValue = dwCompValue * 10 + (*pDup - _T('0'));
  205. }
  206. }
  207. pOid->ids[iComp] = dwCompValue;
  208. return TRUE;
  209. }
  210. BOOL
  211. LoadScalarParameters(
  212. )
  213. /*++
  214. Routine Description:
  215. Reads authentication trap flags key and manager timeout value.
  216. Arguments:
  217. None.
  218. Return Values:
  219. Returns true if successful.
  220. --*/
  221. {
  222. HKEY hKey;
  223. LONG lStatus;
  224. DWORD dwIndex;
  225. DWORD dwNameSize;
  226. DWORD dwValueSize;
  227. DWORD dwValueType;
  228. TCHAR szName[MAX_PATH];
  229. TCHAR szValue[MAX_PATH];
  230. LPTSTR pszKey = REG_KEY_SNMP_PARAMETERS;
  231. BOOL bChangedSysID = FALSE;
  232. // default value for the IsnmpNameResolutionRetries counter
  233. // an address will resist to no more than MGRADDR_DYING (16 by default)
  234. // consecutive name resolution failures.
  235. snmpMgmtBase.AsnIntegerPool[IsnmpNameResolutionRetries].asnValue.number = MGRADDR_DYING;
  236. // open registry subkey
  237. lStatus = RegOpenKeyEx(
  238. HKEY_LOCAL_MACHINE,
  239. pszKey,
  240. 0,
  241. KEY_READ,
  242. &hKey
  243. );
  244. // validate return code
  245. if (lStatus == ERROR_SUCCESS)
  246. {
  247. // initialize
  248. dwIndex = 0;
  249. // loop until error or end of list
  250. while (lStatus == ERROR_SUCCESS)
  251. {
  252. // initialize buffer sizes
  253. dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
  254. dwValueSize = sizeof(szValue); // size in number of bytes
  255. // read next value
  256. lStatus = RegEnumValue(
  257. hKey,
  258. dwIndex,
  259. szName,
  260. &dwNameSize,
  261. NULL,
  262. &dwValueType,
  263. (LPBYTE)szValue,
  264. &dwValueSize
  265. );
  266. // validate return code
  267. if (lStatus == ERROR_SUCCESS)
  268. {
  269. // validate name of value
  270. if (!lstrcmpi(szName, REG_VALUE_AUTH_TRAPS))
  271. {
  272. // set the 'EnableAuthenTraps' in the internal management structure
  273. mgmtISet(IsnmpEnableAuthenTraps, *((PDWORD)&szValue));
  274. }
  275. else if (!lstrcmpi(szName, REG_VALUE_MGRRES_COUNTER))
  276. {
  277. // set the 'NameResolutionRetries' in the internal management structure
  278. mgmtISet(IsnmpNameResolutionRetries, *((PDWORD)&szValue));
  279. }
  280. // next
  281. dwIndex++;
  282. }
  283. }
  284. RegCloseKey(hKey);
  285. }
  286. // look into MIB2 subtree ..SNMP\Parameters\RFC1156Agent for sysObjectID parameter
  287. lStatus = RegOpenKeyEx(
  288. HKEY_LOCAL_MACHINE,
  289. REG_KEY_MIB2,
  290. 0,
  291. KEY_READ,
  292. &hKey
  293. );
  294. // validate return code
  295. if (lStatus == ERROR_SUCCESS)
  296. {
  297. LPTSTR pszOid = szValue;
  298. dwValueSize = sizeof(szValue); // size in number of bytes
  299. // first, get the size of the buffer required for the sysObjectID parameter
  300. lStatus = RegQueryValueEx(
  301. hKey,
  302. REG_VALUE_SYS_OBJECTID,
  303. 0,
  304. &dwValueType,
  305. (LPBYTE)pszOid,
  306. &dwValueSize);
  307. // the ERROR_MORE_DATA is the only error code we expect at this point
  308. if (lStatus == ERROR_MORE_DATA)
  309. {
  310. pszOid = SnmpUtilMemAlloc(dwValueSize);
  311. // if a buffer was set up correctly, go an read the oid value
  312. if (pszOid != NULL)
  313. {
  314. lStatus = RegQueryValueEx(
  315. hKey,
  316. REG_VALUE_SYS_OBJECTID,
  317. 0,
  318. &dwValueType,
  319. (LPBYTE)pszOid,
  320. &dwValueSize);
  321. }
  322. }
  323. // at this point we should succeed
  324. if (lStatus == ERROR_SUCCESS)
  325. {
  326. AsnObjectIdentifier sysObjectID;
  327. // we have the string representation of the oid, convert it now to an AsnObjectIdentifier
  328. // implement the convertion here, as I don't want to make this a public function in SNMPAPI.DLL
  329. // otherwise I'll be forced to handle a lot of useless limit cases..
  330. if (dwValueType == REG_SZ &&
  331. ConvStringToOid(pszOid, &sysObjectID))
  332. {
  333. // don't free what has been alocated in ConvStringToOid as the buffer will be passed
  334. // to the management variable below.
  335. bChangedSysID = (mgmtOSet(OsnmpSysObjectID, &sysObjectID, FALSE) == ERROR_SUCCESS);
  336. }
  337. else
  338. {
  339. SNMPDBG((SNMP_LOG_WARNING,
  340. "SNMP: SVC: LoadScalarParameters() - invalid type or value for sysObjectID param.\n"));
  341. ReportSnmpEvent(
  342. SNMP_EVENT_INVALID_ENTERPRISEOID,
  343. 0,
  344. NULL,
  345. 0);
  346. }
  347. }
  348. // cleanup the buffer if it was dynamically allocated
  349. if (pszOid != szValue)
  350. SnmpUtilMemFree(pszOid);
  351. // cleanup the registry key
  352. RegCloseKey(hKey);
  353. }
  354. if (!bChangedSysID)
  355. {
  356. mgmtOSet(OsnmpSysObjectID, SnmpSvcGetEnterpriseOID(), TRUE);
  357. }
  358. // all parameters here have default values, so there is no reason for this function to fail
  359. // if a parameter could not be found into the registry, its default value will be considered.
  360. return TRUE;
  361. }
  362. ///////////////////////////////////////////////////////////////////////////////
  363. // //
  364. // Public procedures //
  365. // //
  366. ///////////////////////////////////////////////////////////////////////////////
  367. BOOL
  368. LoadRegistryParameters(
  369. )
  370. /*++
  371. Routine Description:
  372. Loads registry parameters.
  373. Arguments:
  374. None.
  375. Return Values:
  376. Returns true if successful.
  377. --*/
  378. {
  379. // first thing to do is to setup the registry notifiers. If we don't do this before reading
  380. // the registry values we might not sense an initial change of the registry.
  381. InitRegistryNotifiers();
  382. // need to load first the scalar parameters especially to know how
  383. // to handle further the name resolution
  384. LoadScalarParameters();
  385. // load managers
  386. LoadPermittedManagers(TRUE);
  387. // load trap destinations
  388. LoadTrapDestinations(TRUE);
  389. // load communities with dynamic update
  390. LoadValidCommunities(TRUE);
  391. // load subagents
  392. LoadSubagents();
  393. // determine regions
  394. LoadSupportedRegions();
  395. return TRUE;
  396. }
  397. BOOL
  398. UnloadRegistryNotifiers(
  399. )
  400. /*++
  401. Routine Description:
  402. Unloads registry notifiers
  403. Arguments:
  404. None.
  405. Return Values:
  406. Returns TRUE
  407. --*/
  408. {
  409. if (g_hDefaultRegNotifier != NULL)
  410. {
  411. CloseHandle(g_hDefaultRegNotifier);
  412. g_hDefaultRegNotifier = NULL;
  413. }
  414. #ifdef _POLICY
  415. if (g_hPolicyRegNotifier != NULL)
  416. {
  417. CloseHandle(g_hPolicyRegNotifier);
  418. g_hPolicyRegNotifier = NULL;
  419. }
  420. #endif
  421. if (g_hDefaultKey != NULL)
  422. {
  423. RegCloseKey(g_hDefaultKey);
  424. g_hDefaultKey = NULL;
  425. }
  426. #ifdef _POLICY
  427. if (g_hPolicyKey != NULL)
  428. {
  429. RegCloseKey(g_hPolicyKey);
  430. g_hPolicyKey = NULL;
  431. }
  432. #endif
  433. return TRUE;
  434. }
  435. BOOL
  436. UnloadRegistryParameters(
  437. )
  438. /*++
  439. Routine Description:
  440. Unloads registry parameters.
  441. Arguments:
  442. None.
  443. Return Values:
  444. Returns true if successful.
  445. --*/
  446. {
  447. // unload the registry notifiers as the first thing to do
  448. UnloadRegistryNotifiers();
  449. // unload managers
  450. UnloadPermittedManagers();
  451. // unload trap destinations
  452. UnloadTrapDestinations();
  453. // unload communities
  454. UnloadValidCommunities();
  455. // unload subagents
  456. UnloadSubagents();
  457. // unload mib regions
  458. UnloadSupportedRegions();
  459. return TRUE;
  460. }