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.

1487 lines
38 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. nbfconfig.c
  5. Abstract:
  6. This contains all routines necessary for the support of the dynamic
  7. configuration of NBF. Note that the parts of this file that are
  8. called at initialization time will be replaced by calls to the configuration manager over time.
  9. Author:
  10. David Beaver (dbeaver) 13-Feb-1991
  11. Revision History:
  12. David Beaver (dbeaver) 1-July-1991
  13. modified to use new tdi interface
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. //
  18. // Local functions used to access the registry.
  19. //
  20. VOID
  21. NbfFreeConfigurationInfo (
  22. IN PCONFIG_DATA ConfigurationInfo
  23. );
  24. NTSTATUS
  25. NbfOpenParametersKey(
  26. IN HANDLE NbfConfigHandle,
  27. OUT PHANDLE ParametersHandle
  28. );
  29. VOID
  30. NbfCloseParametersKey(
  31. IN HANDLE ParametersHandle
  32. );
  33. NTSTATUS
  34. NbfCountEntries(
  35. IN PWSTR ValueName,
  36. IN ULONG ValueType,
  37. IN PVOID ValueData,
  38. IN ULONG ValueLength,
  39. IN PVOID Context,
  40. IN PVOID EntryContext
  41. );
  42. NTSTATUS
  43. NbfAddBind(
  44. IN PWSTR ValueName,
  45. IN ULONG ValueType,
  46. IN PVOID ValueData,
  47. IN ULONG ValueLength,
  48. IN PVOID Context,
  49. IN PVOID EntryContext
  50. );
  51. NTSTATUS
  52. NbfAddExport(
  53. IN PWSTR ValueName,
  54. IN ULONG ValueType,
  55. IN PVOID ValueData,
  56. IN ULONG ValueLength,
  57. IN PVOID Context,
  58. IN PVOID EntryContext
  59. );
  60. VOID
  61. NbfReadLinkageInformation(
  62. IN PWSTR RegistryPathBuffer,
  63. IN PCONFIG_DATA * ConfigurationInfo
  64. );
  65. ULONG
  66. NbfReadSingleParameter(
  67. IN HANDLE ParametersHandle,
  68. IN PWCHAR ValueName,
  69. IN ULONG DefaultValue
  70. );
  71. VOID
  72. NbfWriteSingleParameter(
  73. IN HANDLE ParametersHandle,
  74. IN PWCHAR ValueName,
  75. IN ULONG ValueData
  76. );
  77. UINT
  78. NbfWstrLength(
  79. IN PWSTR Wstr
  80. );
  81. NTSTATUS
  82. NbfMatchBindName(
  83. IN PWSTR ValueName,
  84. IN ULONG ValueType,
  85. IN PVOID ValueData,
  86. IN ULONG ValueLength,
  87. IN PVOID Context,
  88. IN PVOID EntryContext
  89. );
  90. NTSTATUS
  91. NbfExportAtIndex(
  92. IN PWSTR ValueName,
  93. IN ULONG ValueType,
  94. IN PVOID ValueData,
  95. IN ULONG ValueLength,
  96. IN PVOID Context,
  97. IN PVOID EntryContext
  98. );
  99. #ifdef ALLOC_PRAGMA
  100. #pragma alloc_text(PAGE,NbfWstrLength)
  101. #pragma alloc_text(PAGE,NbfConfigureTransport)
  102. #pragma alloc_text(PAGE,NbfFreeConfigurationInfo)
  103. #pragma alloc_text(PAGE,NbfOpenParametersKey)
  104. #pragma alloc_text(PAGE,NbfCloseParametersKey)
  105. #pragma alloc_text(PAGE,NbfCountEntries)
  106. #pragma alloc_text(PAGE,NbfAddBind)
  107. #pragma alloc_text(PAGE,NbfAddExport)
  108. #pragma alloc_text(PAGE,NbfReadLinkageInformation)
  109. #pragma alloc_text(PAGE,NbfReadSingleParameter)
  110. #pragma alloc_text(PAGE,NbfWriteSingleParameter)
  111. #endif
  112. UINT
  113. NbfWstrLength(
  114. IN PWSTR Wstr
  115. )
  116. {
  117. UINT Length = 0;
  118. while (*Wstr++) {
  119. Length += sizeof(WCHAR);
  120. }
  121. return Length;
  122. }
  123. #define InsertAdapter(ConfigurationInfo, Subscript, Name) \
  124. { \
  125. PWSTR _S; \
  126. PWSTR _N = (Name); \
  127. UINT _L = NbfWstrLength(_N)+sizeof(WCHAR); \
  128. _S = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, _L, NBF_MEM_TAG_DEVICE_EXPORT); \
  129. if (_S != NULL) { \
  130. RtlCopyMemory(_S, _N, _L); \
  131. RtlInitUnicodeString (&(ConfigurationInfo)->Names[Subscript], _S); \
  132. } \
  133. }
  134. #define InsertDevice(ConfigurationInfo, Subscript, Name) \
  135. { \
  136. PWSTR _S; \
  137. PWSTR _N = (Name); \
  138. UINT _L = NbfWstrLength(_N)+sizeof(WCHAR); \
  139. _S = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, _L, NBF_MEM_TAG_DEVICE_EXPORT); \
  140. if (_S != NULL) { \
  141. RtlCopyMemory(_S, _N, _L); \
  142. RtlInitUnicodeString (&(ConfigurationInfo)->Names[(ConfigurationInfo)->DevicesOffset+Subscript], _S); \
  143. } \
  144. }
  145. #define RemoveAdapter(ConfigurationInfo, Subscript) \
  146. ExFreePool ((ConfigurationInfo)->Names[Subscript].Buffer)
  147. #define RemoveDevice(ConfigurationInfo, Subscript) \
  148. ExFreePool ((ConfigurationInfo)->Names[(ConfigurationInfo)->DevicesOffset+Subscript].Buffer)
  149. //
  150. // These strings are used in various places by the registry.
  151. //
  152. #define DECLARE_STRING(_str_) WCHAR Str ## _str_[] = L#_str_
  153. #define READ_HIDDEN_CONFIG(_Field) \
  154. { \
  155. ConfigurationInfo->_Field = \
  156. NbfReadSingleParameter( \
  157. ParametersHandle, \
  158. Str ## _Field, \
  159. ConfigurationInfo->_Field); \
  160. }
  161. #define WRITE_HIDDEN_CONFIG(_Field) \
  162. { \
  163. NbfWriteSingleParameter( \
  164. ParametersHandle, \
  165. Str ## _Field, \
  166. ConfigurationInfo->_Field); \
  167. }
  168. NTSTATUS
  169. NbfConfigureTransport (
  170. IN PUNICODE_STRING RegistryPath,
  171. IN PCONFIG_DATA * ConfigurationInfoPtr
  172. )
  173. /*++
  174. Routine Description:
  175. This routine is called by NBF to get information from the configuration
  176. management routines. We read the registry, starting at RegistryPath,
  177. to get the parameters. If they don't exist, we use the defaults
  178. set in nbfcnfg.h file.
  179. Arguments:
  180. RegistryPath - The name of NBF's node in the registry.
  181. ConfigurationInfoPtr - A pointer to the configuration information structure.
  182. Return Value:
  183. Status - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES
  184. otherwise.
  185. --*/
  186. {
  187. NTSTATUS OpenStatus;
  188. HANDLE ParametersHandle;
  189. HANDLE NbfConfigHandle;
  190. NTSTATUS Status;
  191. ULONG Disposition;
  192. PWSTR RegistryPathBuffer;
  193. OBJECT_ATTRIBUTES TmpObjectAttributes;
  194. PCONFIG_DATA ConfigurationInfo;
  195. DECLARE_STRING(InitRequests);
  196. DECLARE_STRING(InitLinks);
  197. DECLARE_STRING(InitConnections);
  198. DECLARE_STRING(InitAddressFiles);
  199. DECLARE_STRING(InitAddresses);
  200. DECLARE_STRING(MaxRequests);
  201. DECLARE_STRING(MaxLinks);
  202. DECLARE_STRING(MaxConnections);
  203. DECLARE_STRING(MaxAddressFiles);
  204. DECLARE_STRING(MaxAddresses);
  205. DECLARE_STRING(InitPackets);
  206. DECLARE_STRING(InitReceivePackets);
  207. DECLARE_STRING(InitReceiveBuffers);
  208. DECLARE_STRING(InitUIFrames);
  209. DECLARE_STRING(SendPacketPoolSize);
  210. DECLARE_STRING(ReceivePacketPoolSize);
  211. DECLARE_STRING(MaxMemoryUsage);
  212. DECLARE_STRING(MinimumT1Timeout);
  213. DECLARE_STRING(DefaultT1Timeout);
  214. DECLARE_STRING(DefaultT2Timeout);
  215. DECLARE_STRING(DefaultTiTimeout);
  216. DECLARE_STRING(LlcRetries);
  217. DECLARE_STRING(LlcMaxWindowSize);
  218. DECLARE_STRING(MaximumIncomingFrames);
  219. DECLARE_STRING(NameQueryRetries);
  220. DECLARE_STRING(NameQueryTimeout);
  221. DECLARE_STRING(AddNameQueryRetries);
  222. DECLARE_STRING(AddNameQueryTimeout);
  223. DECLARE_STRING(GeneralRetries);
  224. DECLARE_STRING(GeneralTimeout);
  225. DECLARE_STRING(WanNameQueryRetries);
  226. DECLARE_STRING(UseDixOverEthernet);
  227. DECLARE_STRING(QueryWithoutSourceRouting);
  228. DECLARE_STRING(AllRoutesNameRecognized);
  229. DECLARE_STRING(MinimumSendWindowLimit);
  230. //
  231. // Open the registry.
  232. //
  233. InitializeObjectAttributes(
  234. &TmpObjectAttributes,
  235. RegistryPath, // name
  236. OBJ_CASE_INSENSITIVE, // attributes
  237. NULL, // root
  238. NULL // security descriptor
  239. );
  240. Status = ZwCreateKey(
  241. &NbfConfigHandle,
  242. KEY_WRITE,
  243. &TmpObjectAttributes,
  244. 0, // title index
  245. NULL, // class
  246. 0, // create options
  247. &Disposition); // disposition
  248. if (!NT_SUCCESS(Status)) {
  249. NbfPrint1("NBF: Could not open/create NBF key: %lx\n", Status);
  250. return Status;
  251. }
  252. IF_NBFDBG (NBF_DEBUG_REGISTRY) {
  253. NbfPrint2("%s NBF key: %lx\n",
  254. (Disposition == REG_CREATED_NEW_KEY) ? "created" : "opened",
  255. NbfConfigHandle);
  256. }
  257. OpenStatus = NbfOpenParametersKey (NbfConfigHandle, &ParametersHandle);
  258. if (OpenStatus != STATUS_SUCCESS) {
  259. return OpenStatus;
  260. }
  261. //
  262. // Read in the NDIS binding information (if none is present
  263. // the array will be filled with all known drivers).
  264. //
  265. // NbfReadLinkageInformation expects a null-terminated path,
  266. // so we have to create one from the UNICODE_STRING.
  267. //
  268. RegistryPathBuffer = (PWSTR)ExAllocatePoolWithTag(
  269. NonPagedPool,
  270. RegistryPath->Length + sizeof(WCHAR),
  271. NBF_MEM_TAG_REGISTRY_PATH);
  272. if (RegistryPathBuffer == NULL) {
  273. NbfCloseParametersKey (ParametersHandle);
  274. return STATUS_INSUFFICIENT_RESOURCES;
  275. }
  276. RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
  277. *(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
  278. NbfReadLinkageInformation (RegistryPathBuffer, ConfigurationInfoPtr);
  279. if (*ConfigurationInfoPtr == NULL) {
  280. ExFreePool (RegistryPathBuffer);
  281. NbfCloseParametersKey (ParametersHandle);
  282. return STATUS_INSUFFICIENT_RESOURCES;
  283. }
  284. ConfigurationInfo = *ConfigurationInfoPtr;
  285. //
  286. // Configure the initial values for some NBF resources.
  287. //
  288. ConfigurationInfo->InitRequests = 1;
  289. ConfigurationInfo->InitLinks = 2;
  290. ConfigurationInfo->InitConnections = 2;
  291. ConfigurationInfo->InitAddressFiles = 0;
  292. ConfigurationInfo->InitAddresses = 0;
  293. //
  294. // These are the initial values; remember that the
  295. // resources above also allocate some of these each
  296. // time they are allocated (shown in the comment).
  297. //
  298. ConfigurationInfo->InitPackets = 30; // + link + 2*conn
  299. ConfigurationInfo->InitReceivePackets = 10; // + link + addr
  300. ConfigurationInfo->InitReceiveBuffers = 5; // + addr
  301. ConfigurationInfo->InitUIFrames = 5; // + addr + conn
  302. //
  303. // Set the size of the packet pools and the total
  304. // allocateable by NBF.
  305. //
  306. ConfigurationInfo->SendPacketPoolSize = 100;
  307. ConfigurationInfo->ReceivePacketPoolSize = 30;
  308. ConfigurationInfo->MaxMemoryUsage = 0; // no limit
  309. //
  310. // Now initialize the timeout etc. values.
  311. //
  312. ConfigurationInfo->MinimumT1Timeout = DLC_MINIMUM_T1;
  313. ConfigurationInfo->DefaultT1Timeout = DLC_DEFAULT_T1;
  314. ConfigurationInfo->DefaultT2Timeout = DLC_DEFAULT_T2;
  315. ConfigurationInfo->DefaultTiTimeout = DLC_DEFAULT_TI;
  316. ConfigurationInfo->LlcRetries = DLC_RETRIES;
  317. ConfigurationInfo->LlcMaxWindowSize = DLC_WINDOW_LIMIT;
  318. ConfigurationInfo->MaximumIncomingFrames = 4;
  319. ConfigurationInfo->NameQueryRetries = NAME_QUERY_RETRIES;
  320. ConfigurationInfo->NameQueryTimeout = NAME_QUERY_TIMEOUT;
  321. ConfigurationInfo->AddNameQueryRetries = ADD_NAME_QUERY_RETRIES;
  322. ConfigurationInfo->AddNameQueryTimeout = ADD_NAME_QUERY_TIMEOUT;
  323. ConfigurationInfo->GeneralRetries = NAME_QUERY_RETRIES;
  324. ConfigurationInfo->GeneralTimeout = NAME_QUERY_TIMEOUT;
  325. ConfigurationInfo->WanNameQueryRetries = WAN_NAME_QUERY_RETRIES;
  326. ConfigurationInfo->UseDixOverEthernet = 0;
  327. ConfigurationInfo->QueryWithoutSourceRouting = 0;
  328. ConfigurationInfo->AllRoutesNameRecognized = 0;
  329. ConfigurationInfo->MinimumSendWindowLimit = 2;
  330. //
  331. // Now read the optional "hidden" parameters; if these do
  332. // not exist then the current values are used. Note that
  333. // the current values will be 0 unless they have been
  334. // explicitly initialized above.
  335. //
  336. // NOTE: These macros expect "ConfigurationInfo" and
  337. // "ParametersHandle" to exist when they are expanded.
  338. //
  339. READ_HIDDEN_CONFIG (InitRequests);
  340. READ_HIDDEN_CONFIG (InitLinks);
  341. READ_HIDDEN_CONFIG (InitConnections);
  342. READ_HIDDEN_CONFIG (InitAddressFiles);
  343. READ_HIDDEN_CONFIG (InitAddresses);
  344. READ_HIDDEN_CONFIG (MaxRequests);
  345. READ_HIDDEN_CONFIG (MaxLinks);
  346. READ_HIDDEN_CONFIG (MaxConnections);
  347. READ_HIDDEN_CONFIG (MaxAddressFiles);
  348. READ_HIDDEN_CONFIG (MaxAddresses);
  349. READ_HIDDEN_CONFIG (InitPackets);
  350. READ_HIDDEN_CONFIG (InitReceivePackets);
  351. READ_HIDDEN_CONFIG (InitReceiveBuffers);
  352. READ_HIDDEN_CONFIG (InitUIFrames);
  353. READ_HIDDEN_CONFIG (SendPacketPoolSize);
  354. READ_HIDDEN_CONFIG (ReceivePacketPoolSize);
  355. READ_HIDDEN_CONFIG (MaxMemoryUsage);
  356. READ_HIDDEN_CONFIG (MinimumT1Timeout);
  357. READ_HIDDEN_CONFIG (DefaultT1Timeout);
  358. READ_HIDDEN_CONFIG (DefaultT2Timeout);
  359. READ_HIDDEN_CONFIG (DefaultTiTimeout);
  360. READ_HIDDEN_CONFIG (LlcRetries);
  361. READ_HIDDEN_CONFIG (LlcMaxWindowSize);
  362. READ_HIDDEN_CONFIG (MaximumIncomingFrames);
  363. READ_HIDDEN_CONFIG (NameQueryRetries);
  364. READ_HIDDEN_CONFIG (NameQueryTimeout);
  365. READ_HIDDEN_CONFIG (AddNameQueryRetries);
  366. READ_HIDDEN_CONFIG (AddNameQueryTimeout);
  367. READ_HIDDEN_CONFIG (GeneralRetries);
  368. READ_HIDDEN_CONFIG (GeneralTimeout);
  369. READ_HIDDEN_CONFIG (WanNameQueryRetries);
  370. READ_HIDDEN_CONFIG (UseDixOverEthernet);
  371. READ_HIDDEN_CONFIG (QueryWithoutSourceRouting);
  372. READ_HIDDEN_CONFIG (AllRoutesNameRecognized);
  373. READ_HIDDEN_CONFIG (MinimumSendWindowLimit);
  374. //
  375. // Print out some config info, to make sure it is read right.
  376. //
  377. IF_NBFDBG (NBF_DEBUG_REGISTRY) {
  378. NbfPrint2("Links: init %d, max %d\n",
  379. ConfigurationInfo->InitLinks,
  380. ConfigurationInfo->MaxLinks);
  381. NbfPrint3("Timeouts (NBF ticks): T1 %d, T2 %d, Ti %d\n",
  382. ConfigurationInfo->DefaultT1Timeout / SHORT_TIMER_DELTA,
  383. ConfigurationInfo->DefaultT2Timeout / SHORT_TIMER_DELTA,
  384. ConfigurationInfo->DefaultTiTimeout / LONG_TIMER_DELTA);
  385. NbfPrint2("Pools: send %d, receive %d\n",
  386. ConfigurationInfo->SendPacketPoolSize,
  387. ConfigurationInfo->ReceivePacketPoolSize);
  388. NbfPrint1("Max mem %d\n",
  389. ConfigurationInfo->MaxMemoryUsage);
  390. NbfPrint2("NQRetries %d, NQTimeout %d\n",
  391. ConfigurationInfo->NameQueryRetries,
  392. ConfigurationInfo->NameQueryTimeout / SHORT_TIMER_DELTA);
  393. }
  394. //
  395. // Save the "hidden" parameters, these may not exist in
  396. // the registry.
  397. //
  398. // NOTE: These macros expect "ConfigurationInfo" and
  399. // "ParametersHandle" to exist when they are expanded.
  400. //
  401. //
  402. // 5/22/92 - don't write the parameters that are set
  403. // based on Size, since otherwise these will overwrite
  404. // those values since hidden parameters are set up
  405. // after the Size-based configuration is done.
  406. //
  407. WRITE_HIDDEN_CONFIG (MaxRequests);
  408. WRITE_HIDDEN_CONFIG (MaxLinks);
  409. WRITE_HIDDEN_CONFIG (MaxConnections);
  410. WRITE_HIDDEN_CONFIG (MaxAddressFiles);
  411. WRITE_HIDDEN_CONFIG (MaxAddresses);
  412. WRITE_HIDDEN_CONFIG (MinimumT1Timeout);
  413. WRITE_HIDDEN_CONFIG (DefaultT1Timeout);
  414. WRITE_HIDDEN_CONFIG (DefaultT2Timeout);
  415. WRITE_HIDDEN_CONFIG (DefaultTiTimeout);
  416. WRITE_HIDDEN_CONFIG (LlcRetries);
  417. WRITE_HIDDEN_CONFIG (LlcMaxWindowSize);
  418. WRITE_HIDDEN_CONFIG (MaximumIncomingFrames);
  419. WRITE_HIDDEN_CONFIG (NameQueryRetries);
  420. WRITE_HIDDEN_CONFIG (NameQueryTimeout);
  421. WRITE_HIDDEN_CONFIG (AddNameQueryRetries);
  422. WRITE_HIDDEN_CONFIG (AddNameQueryTimeout);
  423. WRITE_HIDDEN_CONFIG (GeneralRetries);
  424. WRITE_HIDDEN_CONFIG (GeneralTimeout);
  425. WRITE_HIDDEN_CONFIG (WanNameQueryRetries);
  426. WRITE_HIDDEN_CONFIG (UseDixOverEthernet);
  427. WRITE_HIDDEN_CONFIG (QueryWithoutSourceRouting);
  428. WRITE_HIDDEN_CONFIG (AllRoutesNameRecognized);
  429. // ZwFlushKey (ParametersHandle);
  430. ExFreePool (RegistryPathBuffer);
  431. NbfCloseParametersKey (ParametersHandle);
  432. ZwClose (NbfConfigHandle);
  433. return STATUS_SUCCESS;
  434. } /* NbfConfigureTransport */
  435. VOID
  436. NbfFreeConfigurationInfo (
  437. IN PCONFIG_DATA ConfigurationInfo
  438. )
  439. /*++
  440. Routine Description:
  441. This routine is called by NBF to get free any storage that was allocated
  442. by NbfConfigureTransport in producing the specified CONFIG_DATA structure.
  443. Arguments:
  444. ConfigurationInfo - A pointer to the configuration information structure.
  445. Return Value:
  446. None.
  447. --*/
  448. {
  449. UINT i;
  450. for (i=0; i<ConfigurationInfo->NumAdapters; i++) {
  451. RemoveAdapter (ConfigurationInfo, i);
  452. RemoveDevice (ConfigurationInfo, i);
  453. }
  454. ExFreePool (ConfigurationInfo);
  455. } /* NbfFreeConfigurationInfo */
  456. NTSTATUS
  457. NbfOpenParametersKey(
  458. IN HANDLE NbfConfigHandle,
  459. OUT PHANDLE ParametersHandle
  460. )
  461. /*++
  462. Routine Description:
  463. This routine is called by NBF to open the NBF "Parameters" key.
  464. Arguments:
  465. ParametersHandle - Returns the handle used to read parameters.
  466. Return Value:
  467. The status of the request.
  468. --*/
  469. {
  470. NTSTATUS Status;
  471. HANDLE ParamHandle;
  472. PWSTR ParametersString = L"Parameters";
  473. UNICODE_STRING ParametersKeyName;
  474. OBJECT_ATTRIBUTES TmpObjectAttributes;
  475. //
  476. // Open the NBF parameters key.
  477. //
  478. RtlInitUnicodeString (&ParametersKeyName, ParametersString);
  479. InitializeObjectAttributes(
  480. &TmpObjectAttributes,
  481. &ParametersKeyName, // name
  482. OBJ_CASE_INSENSITIVE, // attributes
  483. NbfConfigHandle, // root
  484. NULL // security descriptor
  485. );
  486. Status = ZwOpenKey(
  487. &ParamHandle,
  488. KEY_READ,
  489. &TmpObjectAttributes);
  490. if (!NT_SUCCESS(Status)) {
  491. NbfPrint1("Could not open parameters key: %lx\n", Status);
  492. return Status;
  493. }
  494. IF_NBFDBG (NBF_DEBUG_REGISTRY) {
  495. NbfPrint1("Opened parameters key: %lx\n", ParamHandle);
  496. }
  497. *ParametersHandle = ParamHandle;
  498. //
  499. // All keys successfully opened or created.
  500. //
  501. return STATUS_SUCCESS;
  502. } /* NbfOpenParametersKey */
  503. VOID
  504. NbfCloseParametersKey(
  505. IN HANDLE ParametersHandle
  506. )
  507. /*++
  508. Routine Description:
  509. This routine is called by NBF to close the "Parameters" key.
  510. It closes the handles passed in and does any other work needed.
  511. Arguments:
  512. ParametersHandle - The handle used to read other parameters.
  513. Return Value:
  514. None.
  515. --*/
  516. {
  517. ZwClose (ParametersHandle);
  518. } /* NbfCloseParametersKey */
  519. NTSTATUS
  520. NbfCountEntries(
  521. IN PWSTR ValueName,
  522. IN ULONG ValueType,
  523. IN PVOID ValueData,
  524. IN ULONG ValueLength,
  525. IN PVOID Context,
  526. IN PVOID EntryContext
  527. )
  528. /*++
  529. Routine Description:
  530. This routine is a callback routine for RtlQueryRegistryValues
  531. It is called with the "Bind" and "Export" multi-strings.
  532. It counts the number of name entries required in the
  533. CONFIGURATION_DATA structure and then allocates it.
  534. Arguments:
  535. ValueName - The name of the value ("Bind" or "Export" -- ignored).
  536. ValueType - The type of the value (REG_MULTI_SZ -- ignored).
  537. ValueData - The null-terminated data for the value.
  538. ValueLength - The length of ValueData (ignored).
  539. Context - A pointer to a pointer to the ConfigurationInfo structure.
  540. When the "Export" callback is made this is filled in
  541. with the allocate structure.
  542. EntryContext - A pointer to a counter holding the total number
  543. of name entries required.
  544. Return Value:
  545. STATUS_SUCCESS
  546. --*/
  547. {
  548. ULONG StringCount;
  549. PWCHAR ValuePointer = (PWCHAR)ValueData;
  550. PCONFIG_DATA * ConfigurationInfo = (PCONFIG_DATA *)Context;
  551. PULONG TotalCount = ((PULONG)EntryContext);
  552. ULONG OldTotalCount = *TotalCount;
  553. #if DBG
  554. ASSERT (ValueType == REG_MULTI_SZ);
  555. #else
  556. UNREFERENCED_PARAMETER(ValueType);
  557. #endif
  558. //
  559. // Count the number of strings in the multi-string; first
  560. // check that it is NULL-terminated to make the rest
  561. // easier.
  562. //
  563. if ((ValueLength < 2) ||
  564. (ValuePointer[(ValueLength/2)-1] != (WCHAR)'\0')) {
  565. return STATUS_INVALID_PARAMETER;
  566. }
  567. StringCount = 0;
  568. while (*ValuePointer != (WCHAR)'\0') {
  569. while (*ValuePointer != (WCHAR)'\0') {
  570. ++ValuePointer;
  571. }
  572. ++StringCount;
  573. ++ValuePointer;
  574. if ((ULONG)((PUCHAR)ValuePointer - (PUCHAR)ValueData) >= ValueLength) {
  575. break;
  576. }
  577. }
  578. (*TotalCount) += StringCount;
  579. if (*ValueName == (WCHAR)'E') {
  580. //
  581. // This is "Export", allocate the config data structure.
  582. //
  583. *ConfigurationInfo = ExAllocatePoolWithTag(
  584. NonPagedPool,
  585. sizeof (CONFIG_DATA) +
  586. ((*TotalCount-1) * sizeof(NDIS_STRING)),
  587. NBF_MEM_TAG_CONFIG_DATA);
  588. if (*ConfigurationInfo == NULL) {
  589. return STATUS_INSUFFICIENT_RESOURCES;
  590. }
  591. RtlZeroMemory(
  592. *ConfigurationInfo,
  593. sizeof(CONFIG_DATA) + ((*TotalCount-1) * sizeof(NDIS_STRING)));
  594. (*ConfigurationInfo)->DevicesOffset = OldTotalCount;
  595. }
  596. return STATUS_SUCCESS;
  597. } /* NbfCountEntries */
  598. NTSTATUS
  599. NbfAddBind(
  600. IN PWSTR ValueName,
  601. IN ULONG ValueType,
  602. IN PVOID ValueData,
  603. IN ULONG ValueLength,
  604. IN PVOID Context,
  605. IN PVOID EntryContext
  606. )
  607. /*++
  608. Routine Description:
  609. This routine is a callback routine for RtlQueryRegistryValues
  610. It is called for each piece of the "Bind" multi-string and
  611. saves the information in a ConfigurationInfo structure.
  612. Arguments:
  613. ValueName - The name of the value ("Bind" -- ignored).
  614. ValueType - The type of the value (REG_SZ -- ignored).
  615. ValueData - The null-terminated data for the value.
  616. ValueLength - The length of ValueData (ignored).
  617. Context - A pointer to the ConfigurationInfo structure.
  618. EntryContext - A pointer to a count of binds that is incremented.
  619. Return Value:
  620. STATUS_SUCCESS
  621. --*/
  622. {
  623. PCONFIG_DATA ConfigurationInfo = *(PCONFIG_DATA *)Context;
  624. PULONG CurBindNum = ((PULONG)EntryContext);
  625. UNREFERENCED_PARAMETER(ValueName);
  626. UNREFERENCED_PARAMETER(ValueType);
  627. UNREFERENCED_PARAMETER(ValueLength);
  628. InsertAdapter(
  629. ConfigurationInfo,
  630. *CurBindNum,
  631. (PWSTR)(ValueData));
  632. ++(*CurBindNum);
  633. return STATUS_SUCCESS;
  634. } /* NbfAddBind */
  635. NTSTATUS
  636. NbfAddExport(
  637. IN PWSTR ValueName,
  638. IN ULONG ValueType,
  639. IN PVOID ValueData,
  640. IN ULONG ValueLength,
  641. IN PVOID Context,
  642. IN PVOID EntryContext
  643. )
  644. /*++
  645. Routine Description:
  646. This routine is a callback routine for RtlQueryRegistryValues
  647. It is called for each piece of the "Export" multi-string and
  648. saves the information in a ConfigurationInfo structure.
  649. Arguments:
  650. ValueName - The name of the value ("Export" -- ignored).
  651. ValueType - The type of the value (REG_SZ -- ignored).
  652. ValueData - The null-terminated data for the value.
  653. ValueLength - The length of ValueData (ignored).
  654. Context - A pointer to the ConfigurationInfo structure.
  655. EntryContext - A pointer to a count of exports that is incremented.
  656. Return Value:
  657. STATUS_SUCCESS
  658. --*/
  659. {
  660. PCONFIG_DATA ConfigurationInfo = *(PCONFIG_DATA *)Context;
  661. PULONG CurExportNum = ((PULONG)EntryContext);
  662. UNREFERENCED_PARAMETER(ValueName);
  663. UNREFERENCED_PARAMETER(ValueType);
  664. UNREFERENCED_PARAMETER(ValueLength);
  665. InsertDevice(
  666. ConfigurationInfo,
  667. *CurExportNum,
  668. (PWSTR)(ValueData));
  669. ++(*CurExportNum);
  670. return STATUS_SUCCESS;
  671. } /* NbfAddExport */
  672. VOID
  673. NbfReadLinkageInformation(
  674. IN PWSTR RegistryPathBuffer,
  675. IN PCONFIG_DATA * ConfigurationInfo
  676. )
  677. /*++
  678. Routine Description:
  679. This routine is called by NBF to read its linkage information
  680. from the registry. If there is none present, then ConfigData
  681. is filled with a list of all the adapters that are known
  682. to NBF.
  683. Arguments:
  684. RegistryPathBuffer - The null-terminated root of the NBF registry tree.
  685. ConfigurationInfo - Returns NBF's current configuration.
  686. Return Value:
  687. None.
  688. --*/
  689. {
  690. UINT ConfigBindings;
  691. UINT NameCount = 0;
  692. NTSTATUS Status;
  693. RTL_QUERY_REGISTRY_TABLE QueryTable[6];
  694. PWSTR Subkey = L"Linkage";
  695. PWSTR Bind = L"Bind";
  696. PWSTR Export = L"Export";
  697. ULONG BindCount, ExportCount;
  698. UINT i;
  699. //
  700. // Set up QueryTable to do the following:
  701. //
  702. //
  703. // 1) Switch to the Linkage key below NBF
  704. //
  705. QueryTable[0].QueryRoutine = NULL;
  706. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  707. QueryTable[0].Name = Subkey;
  708. //
  709. // 2) Call NbfCountEntries for the "Bind" multi-string
  710. //
  711. QueryTable[1].QueryRoutine = NbfCountEntries;
  712. QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  713. QueryTable[1].Name = Bind;
  714. QueryTable[1].EntryContext = (PVOID)&NameCount;
  715. QueryTable[1].DefaultType = REG_NONE;
  716. //
  717. // 3) Call NbfCountEntries for the "Export" multi-string
  718. //
  719. QueryTable[2].QueryRoutine = NbfCountEntries;
  720. QueryTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  721. QueryTable[2].Name = Export;
  722. QueryTable[2].EntryContext = (PVOID)&NameCount;
  723. QueryTable[2].DefaultType = REG_NONE;
  724. //
  725. // 4) Call NbfAddBind for each string in "Bind"
  726. //
  727. QueryTable[3].QueryRoutine = NbfAddBind;
  728. QueryTable[3].Flags = 0;
  729. QueryTable[3].Name = Bind;
  730. QueryTable[3].EntryContext = (PVOID)&BindCount;
  731. QueryTable[3].DefaultType = REG_NONE;
  732. //
  733. // 5) Call NbfAddExport for each string in "Export"
  734. //
  735. QueryTable[4].QueryRoutine = NbfAddExport;
  736. QueryTable[4].Flags = 0;
  737. QueryTable[4].Name = Export;
  738. QueryTable[4].EntryContext = (PVOID)&ExportCount;
  739. QueryTable[4].DefaultType = REG_NONE;
  740. //
  741. // 6) Stop
  742. //
  743. QueryTable[5].QueryRoutine = NULL;
  744. QueryTable[5].Flags = 0;
  745. QueryTable[5].Name = NULL;
  746. BindCount = 0;
  747. ExportCount = 0;
  748. Status = RtlQueryRegistryValues(
  749. RTL_REGISTRY_ABSOLUTE,
  750. RegistryPathBuffer,
  751. QueryTable,
  752. (PVOID)ConfigurationInfo,
  753. NULL);
  754. if (Status != STATUS_SUCCESS) {
  755. return;
  756. }
  757. //
  758. // Make sure that BindCount and ExportCount match, if not
  759. // remove the extras.
  760. //
  761. if (BindCount < ExportCount) {
  762. for (i=BindCount; i<ExportCount; i++) {
  763. RemoveDevice (*ConfigurationInfo, i);
  764. }
  765. ConfigBindings = BindCount;
  766. } else if (ExportCount < BindCount) {
  767. for (i=ExportCount; i<BindCount; i++) {
  768. RemoveAdapter (*ConfigurationInfo, i);
  769. }
  770. ConfigBindings = ExportCount;
  771. } else {
  772. ConfigBindings = BindCount; // which is equal to ExportCount
  773. }
  774. (*ConfigurationInfo)->NumAdapters = ConfigBindings;
  775. } /* NbfReadLinkageInformation */
  776. ULONG
  777. NbfReadSingleParameter(
  778. IN HANDLE ParametersHandle,
  779. IN PWCHAR ValueName,
  780. IN ULONG DefaultValue
  781. )
  782. /*++
  783. Routine Description:
  784. This routine is called by NBF to read a single parameter
  785. from the registry. If the parameter is found it is stored
  786. in Data.
  787. Arguments:
  788. ParametersHandle - A pointer to the open registry.
  789. ValueName - The name of the value to search for.
  790. DefaultValue - The default value.
  791. Return Value:
  792. The value to use; will be the default if the value is not
  793. found or is not in the correct range.
  794. --*/
  795. {
  796. ULONG InformationBuffer[32]; // declare ULONG to get it aligned
  797. PKEY_VALUE_FULL_INFORMATION Information =
  798. (PKEY_VALUE_FULL_INFORMATION)InformationBuffer;
  799. UNICODE_STRING ValueKeyName;
  800. ULONG InformationLength;
  801. ULONG ReturnValue;
  802. NTSTATUS Status;
  803. RtlInitUnicodeString (&ValueKeyName, ValueName);
  804. Status = ZwQueryValueKey(
  805. ParametersHandle,
  806. &ValueKeyName,
  807. KeyValueFullInformation,
  808. (PVOID)Information,
  809. sizeof (InformationBuffer),
  810. &InformationLength);
  811. if ((Status == STATUS_SUCCESS) &&
  812. (Information->DataLength == sizeof(ULONG))) {
  813. RtlCopyMemory(
  814. (PVOID)&ReturnValue,
  815. ((PUCHAR)Information) + Information->DataOffset,
  816. sizeof(ULONG));
  817. if ((LONG)ReturnValue < 0) {
  818. ReturnValue = DefaultValue;
  819. }
  820. } else {
  821. ReturnValue = DefaultValue;
  822. }
  823. return ReturnValue;
  824. } /* NbfReadSingleParameter */
  825. VOID
  826. NbfWriteSingleParameter(
  827. IN HANDLE ParametersHandle,
  828. IN PWCHAR ValueName,
  829. IN ULONG ValueData
  830. )
  831. /*++
  832. Routine Description:
  833. This routine is called by NBF to write a single parameter
  834. from the registry.
  835. Arguments:
  836. ParametersHandle - A pointer to the open registry.
  837. ValueName - The name of the value to store.
  838. ValueData - The data to store at the value.
  839. Return Value:
  840. None.
  841. --*/
  842. {
  843. UNICODE_STRING ValueKeyName;
  844. NTSTATUS Status;
  845. ULONG TmpValueData = ValueData;
  846. RtlInitUnicodeString (&ValueKeyName, ValueName);
  847. Status = ZwSetValueKey(
  848. ParametersHandle,
  849. &ValueKeyName,
  850. 0,
  851. REG_DWORD,
  852. (PVOID)&TmpValueData,
  853. sizeof(ULONG));
  854. if (!NT_SUCCESS(Status)) {
  855. NbfPrint1("NBF: Could not write dword key: %lx\n", Status);
  856. }
  857. } /* NbfWriteSingleParameter */
  858. NTSTATUS
  859. NbfGetExportNameFromRegistry(
  860. IN PUNICODE_STRING RegistryPath,
  861. IN PUNICODE_STRING BindName,
  862. OUT PUNICODE_STRING ExportName
  863. )
  864. {
  865. NTSTATUS OpenStatus;
  866. HANDLE ParametersHandle;
  867. HANDLE NbfConfigHandle;
  868. NTSTATUS Status;
  869. PWSTR RegistryPathBuffer;
  870. OBJECT_ATTRIBUTES TmpObjectAttributes;
  871. RTL_QUERY_REGISTRY_TABLE QueryTable[3];
  872. PWSTR Subkey = L"Linkage";
  873. PWSTR Bind = L"Bind";
  874. PWSTR Export = L"Export";
  875. LONG BindNumber;
  876. //
  877. // Open the registry.
  878. //
  879. InitializeObjectAttributes(
  880. &TmpObjectAttributes,
  881. RegistryPath, // name
  882. OBJ_CASE_INSENSITIVE, // attributes
  883. NULL, // root
  884. NULL // security descriptor
  885. );
  886. OpenStatus = ZwOpenKey(
  887. &NbfConfigHandle,
  888. KEY_WRITE,
  889. &TmpObjectAttributes
  890. );
  891. if (!NT_SUCCESS(OpenStatus)) {
  892. NbfPrint1("NBF: Could not open NBF key: %lx\n", OpenStatus);
  893. return OpenStatus;
  894. }
  895. Status = NbfOpenParametersKey (NbfConfigHandle, &ParametersHandle);
  896. if (Status != STATUS_SUCCESS) {
  897. ZwClose (NbfConfigHandle);
  898. return Status;
  899. }
  900. //
  901. // NbfReadLinkageInformation expects a null-terminated path,
  902. // so we have to create one from the UNICODE_STRING.
  903. //
  904. RegistryPathBuffer = (PWSTR)ExAllocatePoolWithTag(
  905. NonPagedPool,
  906. RegistryPath->Length + sizeof(WCHAR),
  907. NBF_MEM_TAG_REGISTRY_PATH);
  908. if (RegistryPathBuffer == NULL) {
  909. NbfCloseParametersKey (ParametersHandle);
  910. ZwClose (NbfConfigHandle);
  911. return STATUS_INSUFFICIENT_RESOURCES;
  912. }
  913. RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
  914. *(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
  915. //
  916. // We have a new device whose binding was absent
  917. // at boot - get export name given the bind name
  918. //
  919. // First we need to get index of the bind name
  920. // Set up QueryTable to do the following:
  921. //
  922. // 1) Switch to the Linkage key below NBF
  923. //
  924. QueryTable[0].QueryRoutine = NULL;
  925. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  926. QueryTable[0].Name = Subkey;
  927. //
  928. // 2) Call NbfMatchBindName for each string in "Bind"
  929. //
  930. QueryTable[1].QueryRoutine = NbfMatchBindName;
  931. QueryTable[1].Flags = 0;
  932. QueryTable[1].Name = Bind;
  933. QueryTable[1].EntryContext = (PVOID)&BindNumber;
  934. QueryTable[1].DefaultType = REG_NONE;
  935. //
  936. // 3) Stop
  937. //
  938. QueryTable[2].QueryRoutine = NULL;
  939. QueryTable[2].Flags = 0;
  940. QueryTable[2].Name = NULL;
  941. BindNumber = -1;
  942. Status = RtlQueryRegistryValues(
  943. RTL_REGISTRY_ABSOLUTE,
  944. RegistryPathBuffer,
  945. QueryTable,
  946. (PVOID)BindName,
  947. NULL);
  948. IF_NBFDBG (NBF_DEBUG_PNP) {
  949. NbfPrint2 ("Status from NbfMatchBindName's = %08x, Bind Number = %d\n",
  950. Status, BindNumber);
  951. }
  952. if (Status != STATUS_NO_MORE_MATCHES)
  953. {
  954. #if DBG
  955. DbgBreakPoint();
  956. #endif
  957. if (Status == STATUS_SUCCESS) {
  958. // We did not find the device 'bind name'
  959. Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  960. IF_NBFDBG (NBF_DEBUG_PNP) {
  961. NbfPrint1 ("NBF - cannot find dynamic binding %S\n", BindName->Buffer);
  962. }
  963. }
  964. goto Done;
  965. }
  966. ASSERT(BindNumber >= 0);
  967. // First we need to get export name given index
  968. // Set up QueryTable to do the following:
  969. //
  970. // 1) Switch to the Linkage key below NBF
  971. //
  972. QueryTable[0].QueryRoutine = NULL;
  973. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  974. QueryTable[0].Name = Subkey;
  975. //
  976. // 2) Call NbfAddExport for each string in "Export"
  977. //
  978. QueryTable[1].QueryRoutine = NbfExportAtIndex;
  979. QueryTable[1].Flags = 0;
  980. QueryTable[1].Name = Export;
  981. QueryTable[1].EntryContext = (PVOID)&BindNumber;
  982. QueryTable[1].DefaultType = REG_NONE;
  983. //
  984. // 3) Stop
  985. //
  986. QueryTable[2].QueryRoutine = NULL;
  987. QueryTable[2].Flags = 0;
  988. QueryTable[2].Name = NULL;
  989. RtlInitUnicodeString(ExportName, NULL);
  990. Status = RtlQueryRegistryValues(
  991. RTL_REGISTRY_ABSOLUTE,
  992. RegistryPathBuffer,
  993. QueryTable,
  994. (PVOID)ExportName,
  995. NULL);
  996. IF_NBFDBG (NBF_DEBUG_PNP) {
  997. NbfPrint2("Status from NbfExportAtIndex's = %08x, ExportLength = %d\n",
  998. Status,
  999. ExportName->Length);
  1000. if (ExportName->Length > 0)
  1001. {
  1002. NbfPrint1("ExportName = %S\n", ExportName->Buffer);
  1003. }
  1004. }
  1005. if (ExportName->Length != 0) {
  1006. ASSERT(Status == STATUS_NO_MORE_MATCHES);
  1007. Status = STATUS_SUCCESS;
  1008. }
  1009. else {
  1010. // We found the bind, but no corr export
  1011. Status = NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER;
  1012. }
  1013. Done:
  1014. ExFreePool (RegistryPathBuffer);
  1015. NbfCloseParametersKey (ParametersHandle);
  1016. ZwClose (NbfConfigHandle);
  1017. return Status;
  1018. }
  1019. NTSTATUS
  1020. NbfMatchBindName(
  1021. IN PWSTR ValueName,
  1022. IN ULONG ValueType,
  1023. IN PVOID ValueData,
  1024. IN ULONG ValueLength,
  1025. IN PVOID Context,
  1026. IN PVOID EntryContext
  1027. )
  1028. /*++
  1029. Routine Description:
  1030. This routine is a callback routine for RtlQueryRegistryValues
  1031. It is called for each piece of the "Bind" multi-string and
  1032. tries to match a given bind name with each of these pieces.
  1033. Arguments:
  1034. ValueName - The name of the value ("Bind" -- ignored).
  1035. ValueType - The type of the value (REG_SZ -- ignored).
  1036. ValueData - The null-terminated data for the value.
  1037. ValueLength - The length of ValueData (ignored).
  1038. Context - Bind name that we are trying to match.
  1039. EntryContext - A pointer where index of the match is stored.
  1040. Return Value:
  1041. STATUS_SUCCESS
  1042. --*/
  1043. {
  1044. PUNICODE_STRING BindName = (PUNICODE_STRING) Context;
  1045. PLONG CurBindNum = (PLONG) EntryContext;
  1046. UNICODE_STRING ValueString;
  1047. UNREFERENCED_PARAMETER(ValueName);
  1048. UNREFERENCED_PARAMETER(ValueType);
  1049. UNREFERENCED_PARAMETER(ValueLength);
  1050. RtlInitUnicodeString(&ValueString, ValueData);
  1051. // We are yet to find a match
  1052. (*CurBindNum)++ ;
  1053. if (NdisEqualString(BindName, &ValueString, TRUE)) {
  1054. return STATUS_NO_MORE_MATCHES;
  1055. }
  1056. return STATUS_SUCCESS;
  1057. } /* NbfMatchBindName */
  1058. NTSTATUS
  1059. NbfExportAtIndex(
  1060. IN PWSTR ValueName,
  1061. IN ULONG ValueType,
  1062. IN PVOID ValueData,
  1063. IN ULONG ValueLength,
  1064. IN PVOID Context,
  1065. IN PVOID EntryContext
  1066. )
  1067. {
  1068. PUNICODE_STRING ExportName = (PUNICODE_STRING) Context;
  1069. PLONG CurBindNum = (PLONG) EntryContext;
  1070. PWSTR ValueWideChars;
  1071. UINT ValueWideLength;
  1072. UNICODE_STRING ValueString;
  1073. UNREFERENCED_PARAMETER(ValueName);
  1074. UNREFERENCED_PARAMETER(ValueType);
  1075. ASSERT(*CurBindNum >= 0);
  1076. if (*CurBindNum == 0)
  1077. {
  1078. ValueWideLength = NbfWstrLength(ValueData) + sizeof(WCHAR);
  1079. ValueWideChars = (PWSTR) ExAllocatePoolWithTag(NonPagedPool,
  1080. ValueWideLength,
  1081. NBF_MEM_TAG_DEVICE_EXPORT);
  1082. if (ValueWideChars == NULL)
  1083. {
  1084. return STATUS_INSUFFICIENT_RESOURCES;
  1085. }
  1086. RtlCopyMemory (ValueWideChars, ValueData, ValueWideLength);
  1087. RtlInitUnicodeString (ExportName, ValueWideChars);
  1088. return STATUS_NO_MORE_MATCHES;
  1089. }
  1090. (*CurBindNum)-- ;
  1091. return STATUS_SUCCESS;
  1092. } /* NbfExportAtIndex */