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.

673 lines
17 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. config.c
  5. Abstract:
  6. This contains all routines necessary for the support of the dynamic
  7. configuration of the ISN Netbios module.
  8. Author:
  9. Adam Barr (adamba) 16-November-1993
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // Local functions used to access the registry.
  16. //
  17. NTSTATUS
  18. NbiGetConfigValue(
  19. IN PWSTR ValueName,
  20. IN ULONG ValueType,
  21. IN PVOID ValueData,
  22. IN ULONG ValueLength,
  23. IN PVOID Context,
  24. IN PVOID EntryContext
  25. );
  26. NTSTATUS
  27. NbiAddBind(
  28. IN PWSTR ValueName,
  29. IN ULONG ValueType,
  30. IN PVOID ValueData,
  31. IN ULONG ValueLength,
  32. IN PVOID Context,
  33. IN PVOID EntryContext
  34. );
  35. NTSTATUS
  36. NbiAddExport(
  37. IN PWSTR ValueName,
  38. IN ULONG ValueType,
  39. IN PVOID ValueData,
  40. IN ULONG ValueLength,
  41. IN PVOID Context,
  42. IN PVOID EntryContext
  43. );
  44. NTSTATUS
  45. NbiReadLinkageInformation(
  46. IN PCONFIG Config
  47. );
  48. #ifdef ALLOC_PRAGMA
  49. #pragma alloc_text(PAGE,NbiGetConfiguration)
  50. #pragma alloc_text(PAGE,NbiFreeConfiguration)
  51. #pragma alloc_text(PAGE,NbiGetConfigValue)
  52. #pragma alloc_text(PAGE,NbiAddBind)
  53. #pragma alloc_text(PAGE,NbiAddExport)
  54. #pragma alloc_text(PAGE,NbiReadLinkageInformation)
  55. #endif
  56. NTSTATUS
  57. NbiGetConfiguration (
  58. IN PDRIVER_OBJECT DriverObject,
  59. IN PUNICODE_STRING RegistryPath,
  60. OUT PCONFIG * ConfigPtr
  61. )
  62. /*++
  63. Routine Description:
  64. This routine is called by Netbios to get information from the configuration
  65. management routines. We read the registry, starting at RegistryPath,
  66. to get the parameters. If they don't exist, we use the defaults
  67. set in ipxcnfg.h file. A list of adapters to bind to is chained
  68. on to the config information.
  69. Arguments:
  70. DriverObject - Used for logging errors.
  71. RegistryPath - The name of Netbios' node in the registry.
  72. ConfigPtr - Returns the configuration information.
  73. Return Value:
  74. Status - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES
  75. otherwise.
  76. --*/
  77. {
  78. PCONFIG Config;
  79. RTL_QUERY_REGISTRY_TABLE QueryTable[CONFIG_PARAMETERS+2];
  80. NTSTATUS Status;
  81. ULONG One = 1;
  82. ULONG Two = 2;
  83. ULONG Three = 3;
  84. ULONG Four = 4;
  85. ULONG Five = 5;
  86. ULONG Eight = 8;
  87. ULONG FortyEight = 48;
  88. ULONG Sixty = 60;
  89. ULONG TwoFifty = 250;
  90. ULONG FiveHundred = 500;
  91. ULONG SevenFifty = 750;
  92. ULONG MaxMTU = 0xffffffff;
  93. PWSTR Parameters = L"Parameters";
  94. struct {
  95. PWSTR KeyName;
  96. PULONG DefaultValue;
  97. } ParameterValues[CONFIG_PARAMETERS] = {
  98. { L"AckDelayTime", &TwoFifty } , // milliseconds
  99. { L"AckWindow", &Two } ,
  100. { L"AckWindowThreshold", &FiveHundred } , // milliseconds
  101. { L"EnablePiggyBackAck", &One } ,
  102. { L"Extensions", &One } ,
  103. { L"RcvWindowMax", &Four } ,
  104. { L"BroadcastCount", &Three } ,
  105. { L"BroadcastTimeout", &SevenFifty} , // milliseconds
  106. { L"ConnectionCount", &Five } ,
  107. { L"ConnectionTimeout", &Two } , // half-seconds
  108. { L"InitPackets", &Eight } ,
  109. { L"MaxPackets", &FortyEight } ,
  110. { L"InitialRetransmissionTime", &FiveHundred } , // milliseconds
  111. { L"Internet", &One } ,
  112. { L"KeepAliveCount", &Eight } ,
  113. { L"KeepAliveTimeout", &Sixty } , // half-seconds
  114. { L"RetransmitMax", &Eight } ,
  115. { L"RouterMTU", &MaxMTU } };
  116. UINT i;
  117. //
  118. // Allocate memory for the main config structure.
  119. //
  120. Config = NbiAllocateMemory (sizeof(CONFIG), MEMORY_CONFIG, "Config");
  121. if (Config == NULL) {
  122. NbiWriteResourceErrorLog ((PVOID)DriverObject, sizeof(CONFIG), MEMORY_CONFIG);
  123. return STATUS_INSUFFICIENT_RESOURCES;
  124. }
  125. Config->DeviceName.Buffer = NULL;
  126. Config->BindName.Buffer = NULL;
  127. Config->RegistryPath.Buffer = NULL;
  128. Config->DriverObject = DriverObject; // save this to log errors
  129. //
  130. // Read in the NDIS binding information (if none is present
  131. // the array will be filled with all known drivers).
  132. //
  133. // NbiReadLinkageInformation expects a null-terminated path,
  134. // so we have to create one from the UNICODE_STRING.
  135. //
  136. Config->RegistryPath.Length = RegistryPath->Length + sizeof(WCHAR);
  137. Config->RegistryPath.Buffer = (PWSTR)NbiAllocateMemory(Config->RegistryPath.Length,
  138. MEMORY_CONFIG, "RegistryPathBuffer");
  139. if (Config->RegistryPath.Buffer == NULL) {
  140. NbiWriteResourceErrorLog ((PVOID)DriverObject, RegistryPath->Length + sizeof(WCHAR), MEMORY_CONFIG);
  141. NbiFreeConfiguration(Config);
  142. return STATUS_INSUFFICIENT_RESOURCES;
  143. }
  144. RtlCopyMemory (Config->RegistryPath.Buffer, RegistryPath->Buffer, RegistryPath->Length);
  145. *(PWCHAR)(((PUCHAR)Config->RegistryPath.Buffer)+RegistryPath->Length) = (WCHAR)'\0';
  146. //
  147. // Determine what name to export and who to bind to.
  148. //
  149. Status = NbiReadLinkageInformation (Config);
  150. if (Status != STATUS_SUCCESS) {
  151. //
  152. // If it failed it logged an error.
  153. //
  154. NbiFreeConfiguration(Config);
  155. return Status;
  156. }
  157. //
  158. // Read the per-transport (as opposed to per-binding)
  159. // parameters.
  160. //
  161. //
  162. // Set up QueryTable to do the following:
  163. //
  164. //
  165. // 1) Switch to the Parameters key below Netbios
  166. //
  167. QueryTable[0].QueryRoutine = NULL;
  168. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  169. QueryTable[0].Name = Parameters;
  170. //
  171. // 2-18) Call NbiSetBindingValue for each of the keys we
  172. // care about.
  173. //
  174. for (i = 0; i < CONFIG_PARAMETERS; i++) {
  175. QueryTable[i+1].QueryRoutine = NbiGetConfigValue;
  176. QueryTable[i+1].Flags = 0;
  177. QueryTable[i+1].Name = ParameterValues[i].KeyName;
  178. QueryTable[i+1].EntryContext = UlongToPtr(i);
  179. QueryTable[i+1].DefaultType = REG_DWORD;
  180. QueryTable[i+1].DefaultData = (PVOID)(ParameterValues[i].DefaultValue);
  181. QueryTable[i+1].DefaultLength = sizeof(ULONG);
  182. }
  183. //
  184. // 19) Stop
  185. //
  186. QueryTable[CONFIG_PARAMETERS+1].QueryRoutine = NULL;
  187. QueryTable[CONFIG_PARAMETERS+1].Flags = 0;
  188. QueryTable[CONFIG_PARAMETERS+1].Name = NULL;
  189. Status = RtlQueryRegistryValues(
  190. RTL_REGISTRY_ABSOLUTE,
  191. Config->RegistryPath.Buffer,
  192. QueryTable,
  193. (PVOID)Config,
  194. NULL);
  195. if (Status != STATUS_SUCCESS) {
  196. NbiFreeConfiguration(Config);
  197. NbiWriteGeneralErrorLog(
  198. (PVOID)DriverObject,
  199. EVENT_IPX_ILLEGAL_CONFIG,
  200. 701,
  201. Status,
  202. Parameters,
  203. 0,
  204. NULL);
  205. return STATUS_DEVICE_CONFIGURATION_ERROR;
  206. }
  207. *ConfigPtr = Config;
  208. // #if DBG
  209. //
  210. // Due to previous Registry entries not being cleanedup properly,
  211. // we can have stale entries for BroadcastTimeout -- if so, handle
  212. // it accordingly
  213. if (Config->Parameters[CONFIG_BROADCAST_TIMEOUT] < 10)
  214. {
  215. Config->Parameters[CONFIG_BROADCAST_TIMEOUT] = SevenFifty;
  216. }
  217. // #endif
  218. return STATUS_SUCCESS;
  219. } /* NbiGetConfiguration */
  220. VOID
  221. NbiFreeConfiguration (
  222. IN PCONFIG Config
  223. )
  224. /*++
  225. Routine Description:
  226. This routine is called by Netbios to get free any storage that was allocated
  227. by NbiGetConfiguration in producing the specified CONFIG structure.
  228. Arguments:
  229. Config - A pointer to the configuration information structure.
  230. Return Value:
  231. None.
  232. --*/
  233. {
  234. if (Config->BindName.Buffer) {
  235. NbiFreeMemory (Config->BindName.Buffer, Config->BindName.MaximumLength, MEMORY_CONFIG, "BindName");
  236. }
  237. if (Config->DeviceName.Buffer) {
  238. NbiFreeMemory (Config->DeviceName.Buffer, Config->DeviceName.MaximumLength, MEMORY_CONFIG, "DeviceName");
  239. }
  240. if (Config->RegistryPath.Buffer)
  241. {
  242. NbiFreeMemory (Config->RegistryPath.Buffer, Config->RegistryPath.Length,MEMORY_CONFIG,"RegistryPathBuffer");
  243. }
  244. NbiFreeMemory (Config, sizeof(CONFIG), MEMORY_CONFIG, "Config");
  245. } /* NbiFreeConfig */
  246. NTSTATUS
  247. NbiGetConfigValue(
  248. IN PWSTR ValueName,
  249. IN ULONG ValueType,
  250. IN PVOID ValueData,
  251. IN ULONG ValueLength,
  252. IN PVOID Context,
  253. IN PVOID EntryContext
  254. )
  255. /*++
  256. Routine Description:
  257. This routine is a callback routine for RtlQueryRegistryValues
  258. It is called for each entry in the Parameters
  259. node to set the config values. The table is set up
  260. so that this function will be called with correct default
  261. values for keys that are not present.
  262. Arguments:
  263. ValueName - The name of the value (ignored).
  264. ValueType - The type of the value (REG_DWORD -- ignored).
  265. ValueData - The data for the value.
  266. ValueLength - The length of ValueData (ignored).
  267. Context - A pointer to the CONFIG structure.
  268. EntryContext - The index in Config->Parameters to save the value.
  269. Return Value:
  270. STATUS_SUCCESS
  271. --*/
  272. {
  273. PCONFIG Config = (PCONFIG)Context;
  274. ULONG Data = *(UNALIGNED ULONG *)ValueData;
  275. UNREFERENCED_PARAMETER(ValueName);
  276. UNREFERENCED_PARAMETER(ValueType);
  277. UNREFERENCED_PARAMETER(ValueLength);
  278. if ((ValueType != REG_DWORD) || (ValueLength != sizeof(ULONG))) {
  279. return STATUS_INVALID_PARAMETER;
  280. }
  281. switch ( (ULONG_PTR) EntryContext ) {
  282. case CONFIG_ROUTER_MTU:
  283. if ( ( Data - sizeof(NB_CONNECTION) - sizeof(IPX_HEADER) ) <= 0 ) {
  284. Config->Parameters[CONFIG_ROUTER_MTU] = 0xffffffff;
  285. NbiWriteGeneralErrorLog(
  286. (PVOID)Config->DriverObject,
  287. EVENT_IPX_ILLEGAL_CONFIG,
  288. 704,
  289. STATUS_INVALID_PARAMETER,
  290. ValueName,
  291. 0,
  292. NULL);
  293. return STATUS_SUCCESS;
  294. }
  295. break;
  296. default:
  297. break;
  298. }
  299. NB_DEBUG2 (CONFIG, ("Config parameter %d, value %lx\n", (ULONG_PTR)EntryContext, Data));
  300. Config->Parameters[(ULONG_PTR)EntryContext] = Data;
  301. return STATUS_SUCCESS;
  302. } /* NbiGetConfigValue */
  303. NTSTATUS
  304. NbiAddBind(
  305. IN PWSTR ValueName,
  306. IN ULONG ValueType,
  307. IN PVOID ValueData,
  308. IN ULONG ValueLength,
  309. IN PVOID Context,
  310. IN PVOID EntryContext
  311. )
  312. /*++
  313. Routine Description:
  314. This routine is a callback routine for RtlQueryRegistryValues
  315. It is called for each piece of the "Bind" multi-string and
  316. saves the information in a Config structure.
  317. Arguments:
  318. ValueName - The name of the value ("Bind" -- ignored).
  319. ValueType - The type of the value (REG_SZ -- ignored).
  320. ValueData - The null-terminated data for the value.
  321. ValueLength - The length of ValueData.
  322. Context - A pointer to the Config structure.
  323. EntryContext - A pointer to a count of binds that is incremented.
  324. Return Value:
  325. STATUS_SUCCESS
  326. --*/
  327. {
  328. PCONFIG Config = (PCONFIG)Context;
  329. PULONG ValueReadOk = ((PULONG)EntryContext);
  330. PWCHAR NameBuffer;
  331. UNREFERENCED_PARAMETER(ValueName);
  332. UNREFERENCED_PARAMETER(ValueType);
  333. if (*ValueReadOk == 0) {
  334. NB_DEBUG2 (CONFIG, ("Read bind value %ws\n", ValueData));
  335. NameBuffer = (PWCHAR)NbiAllocateMemory (ValueLength, MEMORY_CONFIG, "BindName");
  336. if (NameBuffer == NULL) {
  337. NbiWriteResourceErrorLog ((PVOID)Config->DriverObject, ValueLength, MEMORY_CONFIG);
  338. return STATUS_INSUFFICIENT_RESOURCES;
  339. }
  340. RtlCopyMemory (NameBuffer, ValueData, ValueLength);
  341. Config->BindName.Buffer = NameBuffer;
  342. Config->BindName.Length = (USHORT)(ValueLength - sizeof(WCHAR));
  343. Config->BindName.MaximumLength = (USHORT)ValueLength;
  344. //
  345. // Set this to ignore any other callbacks and let the
  346. // caller know we read something.
  347. //
  348. *ValueReadOk = 1;
  349. }
  350. return STATUS_SUCCESS;
  351. } /* NbiAddBind */
  352. NTSTATUS
  353. NbiAddExport(
  354. IN PWSTR ValueName,
  355. IN ULONG ValueType,
  356. IN PVOID ValueData,
  357. IN ULONG ValueLength,
  358. IN PVOID Context,
  359. IN PVOID EntryContext
  360. )
  361. /*++
  362. Routine Description:
  363. This routine is a callback routine for RtlQueryRegistryValues
  364. It is called for each piece of the "Export" multi-string. It
  365. saves the first callback string in the Config structure.
  366. Arguments:
  367. ValueName - The name of the value ("Export" -- ignored).
  368. ValueType - The type of the value (REG_SZ -- ignored).
  369. ValueData - The null-terminated data for the value.
  370. ValueLength - The length of ValueData.
  371. Context - A pointer to the Config structure.
  372. EntryContext - A pointer to a ULONG that goes to 1 after the
  373. first call to this routine (so we know to ignore other ones).
  374. Return Value:
  375. STATUS_SUCCESS
  376. --*/
  377. {
  378. PCONFIG Config = (PCONFIG)Context;
  379. PULONG ValueReadOk = ((PULONG)EntryContext);
  380. PWCHAR NameBuffer;
  381. UNREFERENCED_PARAMETER(ValueName);
  382. UNREFERENCED_PARAMETER(ValueType);
  383. if (*ValueReadOk == 0) {
  384. NB_DEBUG2 (CONFIG, ("Read export value %ws\n", ValueData));
  385. NameBuffer = (PWCHAR)NbiAllocateMemory (ValueLength, MEMORY_CONFIG, "DeviceName");
  386. if (NameBuffer == NULL) {
  387. NbiWriteResourceErrorLog ((PVOID)Config->DriverObject, ValueLength, MEMORY_CONFIG);
  388. return STATUS_INSUFFICIENT_RESOURCES;
  389. }
  390. RtlCopyMemory (NameBuffer, ValueData, ValueLength);
  391. Config->DeviceName.Buffer = NameBuffer;
  392. Config->DeviceName.Length = (USHORT)(ValueLength - sizeof(WCHAR));
  393. Config->DeviceName.MaximumLength = (USHORT)ValueLength;
  394. //
  395. // Set this to ignore any other callbacks and let the
  396. // caller know we read something.
  397. //
  398. *ValueReadOk = 1;
  399. }
  400. return STATUS_SUCCESS;
  401. } /* NbiAddExport */
  402. NTSTATUS
  403. NbiReadLinkageInformation(
  404. IN PCONFIG Config
  405. )
  406. /*++
  407. Routine Description:
  408. This routine is called by Netbios to read its linkage information
  409. from the registry.
  410. Arguments:
  411. Config - The config structure which will have per-binding information
  412. linked on to it.
  413. Return Value:
  414. The status of the operation.
  415. --*/
  416. {
  417. NTSTATUS Status;
  418. RTL_QUERY_REGISTRY_TABLE QueryTable[3];
  419. PWSTR Subkey = L"Linkage";
  420. PWSTR Bind = L"Bind";
  421. PWSTR Export = L"Export";
  422. ULONG ValueReadOk; // set to TRUE when a value is read correctly
  423. //
  424. // Set up QueryTable to do the following:
  425. //
  426. //
  427. // 1) Switch to the Linkage key below Netbios
  428. //
  429. QueryTable[0].QueryRoutine = NULL;
  430. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  431. QueryTable[0].Name = Subkey;
  432. //
  433. // 1) Call NbiAddExport for each string in "Export"
  434. //
  435. QueryTable[1].QueryRoutine = NbiAddExport;
  436. QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  437. QueryTable[1].Name = Export;
  438. QueryTable[1].EntryContext = (PVOID)&ValueReadOk;
  439. QueryTable[1].DefaultType = REG_NONE;
  440. //
  441. // 2) Stop
  442. //
  443. QueryTable[2].QueryRoutine = NULL;
  444. QueryTable[2].Flags = 0;
  445. QueryTable[2].Name = NULL;
  446. ValueReadOk = 0;
  447. Status = RtlQueryRegistryValues(
  448. RTL_REGISTRY_ABSOLUTE,
  449. Config->RegistryPath.Buffer,
  450. QueryTable,
  451. (PVOID)Config,
  452. NULL);
  453. if ((Status != STATUS_SUCCESS) || (ValueReadOk == 0)) {
  454. NbiWriteGeneralErrorLog(
  455. (PVOID)Config->DriverObject,
  456. EVENT_IPX_ILLEGAL_CONFIG,
  457. 702,
  458. Status,
  459. Export,
  460. 0,
  461. NULL);
  462. return STATUS_DEVICE_CONFIGURATION_ERROR;
  463. }
  464. //
  465. // 1) Change to call NbiAddBind for each string in "Bind"
  466. //
  467. QueryTable[1].QueryRoutine = NbiAddBind;
  468. QueryTable[1].Flags = 0; // not required
  469. QueryTable[1].Name = Bind;
  470. QueryTable[1].EntryContext = (PVOID)&ValueReadOk;
  471. QueryTable[1].DefaultType = REG_NONE;
  472. ValueReadOk = 0;
  473. Status = RtlQueryRegistryValues(
  474. RTL_REGISTRY_ABSOLUTE,
  475. Config->RegistryPath.Buffer,
  476. QueryTable,
  477. (PVOID)Config,
  478. NULL);
  479. if ((Status != STATUS_SUCCESS) || (ValueReadOk == 0)) {
  480. NbiWriteGeneralErrorLog(
  481. (PVOID)Config->DriverObject,
  482. EVENT_IPX_ILLEGAL_CONFIG,
  483. 703,
  484. Status,
  485. Bind,
  486. 0,
  487. NULL);
  488. return STATUS_DEVICE_CONFIGURATION_ERROR;
  489. }
  490. return STATUS_SUCCESS;
  491. } /* NbiReadLinkageInformation */