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.

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