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.

1096 lines
27 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. dlcreg.c
  5. Abstract:
  6. This module accesses the registry for DLC.SYS
  7. Contents:
  8. DlcRegistryInitialization
  9. LoadDlcConfiguration
  10. LoadAdapterConfiguration
  11. GetAdapterParameters
  12. OpenDlcRegistryHandle
  13. OpenDlcAdapterRegistryHandle
  14. GetRegistryParameter
  15. SetRegistryParameter
  16. DlcpGetParameter
  17. DlcRegistryTermination
  18. Author:
  19. Richard L Firth (rfirth) 31-Mar-1993
  20. Environment:
  21. kernel mode only
  22. Revision History:
  23. 30-Mar-1993 rfirth
  24. created
  25. 04-May-1994 rfirth
  26. Exposed GetAdapterParameters
  27. --*/
  28. #include <ntddk.h>
  29. #include <windef.h>
  30. #include <dlcapi.h>
  31. #include <dlcio.h>
  32. #include <ndis.h>
  33. #include "llcapi.h"
  34. #include "dlcdef.h"
  35. #include "dlcreg.h"
  36. #include "dlctyp.h"
  37. #include "llcdef.h"
  38. #include "llcmem.h"
  39. #include "llctyp.h"
  40. #include "llcext.h"
  41. //
  42. // manifests
  43. //
  44. #define MAX_ADAPTER_NAME_LENGTH 32 // ?
  45. #define MAX_INFORMATION_BUFFER_LENGTH 256 // ?
  46. #define PARAMETERS_STRING L"Parameters"
  47. //
  48. // indicies of parameters within parameter table
  49. //
  50. #define SWAP_INDEX 0
  51. #define USEDIX_INDEX 1
  52. #define T1_TICK_ONE_INDEX 2
  53. #define T2_TICK_ONE_INDEX 3
  54. #define Ti_TICK_ONE_INDEX 4
  55. #define T1_TICK_TWO_INDEX 5
  56. #define T2_TICK_TWO_INDEX 6
  57. #define Ti_TICK_TWO_INDEX 7
  58. #define FRAME_SIZE_INDEX 8
  59. //
  60. // typedefs
  61. //
  62. //
  63. // macros
  64. //
  65. #define CloseDlcRegistryHandle(handle) ZwClose(handle)
  66. #define CloseAdapterRegistryHandle(handle) ZwClose(handle)
  67. //
  68. // Global data
  69. //
  70. //
  71. // private data
  72. //
  73. UNICODE_STRING DlcRegistryPath;
  74. UNICODE_STRING ParametersPath;
  75. //
  76. // AdapterParameterTable - used for loading DLC parameters from registry in
  77. // data-driven manner. Each adapter that DLC talks to can have a set of all
  78. // or part of the following variables
  79. //
  80. DLC_REGISTRY_PARAMETER AdapterParameterTable[] = {
  81. L"Swap",
  82. (PVOID)DEFAULT_SWAP_ADDRESS_BITS,
  83. {
  84. REG_DWORD,
  85. PARAMETER_IS_BOOLEAN,
  86. NULL,
  87. sizeof(ULONG),
  88. NULL,
  89. 0,
  90. 0
  91. },
  92. L"UseDixOverEthernet",
  93. (PVOID)DEFAULT_DIX_FORMAT,
  94. {
  95. REG_DWORD,
  96. PARAMETER_IS_BOOLEAN,
  97. NULL,
  98. sizeof(ULONG),
  99. NULL,
  100. 0,
  101. 0
  102. },
  103. L"T1TickOne",
  104. (PVOID)DEFAULT_T1_TICK_ONE,
  105. {
  106. REG_DWORD,
  107. PARAMETER_IS_UCHAR,
  108. NULL,
  109. sizeof(ULONG),
  110. NULL,
  111. MIN_TIMER_TICK_VALUE,
  112. MAX_TIMER_TICK_VALUE
  113. },
  114. L"T2TickOne",
  115. (PVOID)DEFAULT_T2_TICK_ONE,
  116. {
  117. REG_DWORD,
  118. PARAMETER_IS_UCHAR,
  119. NULL,
  120. sizeof(ULONG),
  121. NULL,
  122. MIN_TIMER_TICK_VALUE,
  123. MAX_TIMER_TICK_VALUE
  124. },
  125. L"TiTickOne",
  126. (PVOID)DEFAULT_Ti_TICK_ONE,
  127. {
  128. REG_DWORD,
  129. PARAMETER_IS_UCHAR,
  130. NULL,
  131. sizeof(ULONG),
  132. NULL,
  133. MIN_TIMER_TICK_VALUE,
  134. MAX_TIMER_TICK_VALUE
  135. },
  136. L"T1TickTwo",
  137. (PVOID)DEFAULT_T1_TICK_TWO,
  138. {
  139. REG_DWORD,
  140. PARAMETER_IS_UCHAR,
  141. NULL,
  142. sizeof(ULONG),
  143. NULL,
  144. MIN_TIMER_TICK_VALUE,
  145. MAX_TIMER_TICK_VALUE
  146. },
  147. L"T2TickTwo",
  148. (PVOID)DEFAULT_T2_TICK_TWO,
  149. {
  150. REG_DWORD,
  151. PARAMETER_IS_UCHAR,
  152. NULL,
  153. sizeof(ULONG),
  154. NULL,
  155. MIN_TIMER_TICK_VALUE,
  156. MAX_TIMER_TICK_VALUE
  157. },
  158. L"TiTickTwo",
  159. (PVOID)DEFAULT_Ti_TICK_TWO,
  160. {
  161. REG_DWORD,
  162. PARAMETER_IS_UCHAR,
  163. NULL,
  164. sizeof(ULONG),
  165. NULL,
  166. MIN_TIMER_TICK_VALUE,
  167. MAX_TIMER_TICK_VALUE
  168. },
  169. L"UseEthernetFrameSize",
  170. (PVOID)DEFAULT_USE_ETHERNET_FRAME_SIZE,
  171. {
  172. REG_DWORD,
  173. PARAMETER_IS_BOOLEAN,
  174. NULL,
  175. sizeof(ULONG),
  176. NULL,
  177. 0,
  178. 0
  179. }
  180. };
  181. #ifdef NDIS40
  182. DLC_REGISTRY_PARAMETER AdapterInitTimeout =
  183. {
  184. L"WaitForAdapter",
  185. (PVOID) 15, // Default is 15 seconds.
  186. {
  187. REG_DWORD,
  188. PARAMETER_AS_SPECIFIED,
  189. NULL,
  190. sizeof(ULONG),
  191. NULL,
  192. 0, // Min acceptable value
  193. (ULONG) -1 // Allow to set anything.
  194. }
  195. };
  196. #endif // NDIS40
  197. #define NUMBER_OF_DLC_PARAMETERS (sizeof(AdapterParameterTable)/sizeof(AdapterParameterTable[0]))
  198. //
  199. // private function prototypes
  200. //
  201. NTSTATUS
  202. OpenDlcRegistryHandle(
  203. IN PUNICODE_STRING RegistryPath,
  204. OUT PHANDLE DlcRegistryHandle
  205. );
  206. NTSTATUS
  207. OpenDlcAdapterRegistryHandle(
  208. IN HANDLE DlcRegistryHandle,
  209. IN PUNICODE_STRING AdapterName,
  210. OUT PHANDLE DlcAdapterRegistryHandle,
  211. OUT PBOOLEAN Created
  212. );
  213. NTSTATUS
  214. GetRegistryParameter(
  215. IN HANDLE KeyHandle,
  216. IN PDLC_REGISTRY_PARAMETER Parameter,
  217. IN BOOLEAN SetOnFail
  218. );
  219. NTSTATUS
  220. SetRegistryParameter(
  221. IN HANDLE KeyHandle,
  222. IN PDLC_REGISTRY_PARAMETER Parameter
  223. );
  224. NTSTATUS
  225. DlcpGetParameter(
  226. IN PWSTR ValueName,
  227. IN ULONG ValueType,
  228. IN PVOID ValueData,
  229. IN ULONG ValueLength,
  230. IN PVOID Context,
  231. IN PVOID EntryContext
  232. );
  233. //
  234. // debug display options
  235. //
  236. #if DBG
  237. BOOLEAN DebugConfig = TRUE;
  238. #endif
  239. //
  240. // functions
  241. //
  242. VOID
  243. DlcRegistryInitialization(
  244. IN PUNICODE_STRING RegistryPath
  245. )
  246. /*++
  247. Routine Description:
  248. Initializes memory structures for functions in this module
  249. Arguments:
  250. RegistryPath - pointer to UNICODE_STRING giving base of DLC section in
  251. registry
  252. Return Value:
  253. None.
  254. --*/
  255. {
  256. ASSUME_IRQL(PASSIVE_LEVEL);
  257. LlcInitUnicodeString(&DlcRegistryPath, RegistryPath);
  258. RtlInitUnicodeString(&ParametersPath, PARAMETERS_STRING);
  259. }
  260. VOID
  261. DlcRegistryTermination(
  262. VOID
  263. )
  264. /*++
  265. Routine Description:
  266. Undoes anything done in DlcRegistryInitialization
  267. Arguments:
  268. None.
  269. Return Value:
  270. None.
  271. --*/
  272. {
  273. ASSUME_IRQL(PASSIVE_LEVEL);
  274. LlcFreeUnicodeString(&DlcRegistryPath);
  275. }
  276. VOID
  277. LoadDlcConfiguration(
  278. VOID
  279. )
  280. /*++
  281. Routine Description:
  282. Initializes the data structures used to access the registry and loads any
  283. configuration parameters for the driver
  284. Arguments:
  285. None.
  286. Return Value:
  287. None.
  288. --*/
  289. {
  290. //
  291. // nothing else to do at present since we made all currently known
  292. // configuration parameters per-adapter
  293. //
  294. }
  295. VOID
  296. LoadAdapterConfiguration(
  297. IN PUNICODE_STRING AdapterName,
  298. OUT PADAPTER_CONFIGURATION_INFO ConfigInfo
  299. )
  300. /*++
  301. Routine Description:
  302. Loads all of DLC initialization parameters for an adapter from registry:
  303. Swap 0 or 1, default 1
  304. UseDixOverEthernet 0 or 1, default 0
  305. T1TickOne 1 - 255, default 5
  306. T1TickTwo 1 - 255, default 25
  307. T2TickOne 1 - 255, default 1
  308. T2TickTwo 1 - 255, default 10
  309. TiTickOne 1 - 255, default 25
  310. TiTickTwo 1 - 255, default 125
  311. UseEthernetFrameSize 0 or 1, default 1
  312. If any of the parameters do not exist in the DLC\Parameters\<AdapterName>
  313. section, then they are created
  314. Arguments:
  315. AdapterName - pointer to UNICODE_STRING structure giving the name of the
  316. adapter we are opening. This is the value of a key in the
  317. DLC\Parameters section.
  318. The string is EXPECTED to be of the form \Device\<adapter>
  319. ConfigInfo - pointer to the structure that receives the values on output
  320. Return Value:
  321. None.
  322. --*/
  323. {
  324. UINT i;
  325. PDLC_REGISTRY_PARAMETER parameterTable;
  326. ASSUME_IRQL(PASSIVE_LEVEL);
  327. //
  328. // fill in the adapter configuration structure with default values. These
  329. // will be used to update the registry if the value entry doesn't currently
  330. // exist
  331. //
  332. ConfigInfo->SwapAddressBits = (BOOLEAN)DEFAULT_SWAP_ADDRESS_BITS;
  333. ConfigInfo->UseDix = (BOOLEAN)DEFAULT_DIX_FORMAT;
  334. ConfigInfo->TimerTicks.T1TickOne = (UCHAR)DEFAULT_T1_TICK_ONE;
  335. ConfigInfo->TimerTicks.T2TickOne = (UCHAR)DEFAULT_T2_TICK_ONE;
  336. ConfigInfo->TimerTicks.TiTickOne = (UCHAR)DEFAULT_Ti_TICK_ONE;
  337. ConfigInfo->TimerTicks.T1TickTwo = (UCHAR)DEFAULT_T1_TICK_TWO;
  338. ConfigInfo->TimerTicks.T2TickTwo = (UCHAR)DEFAULT_T2_TICK_TWO;
  339. ConfigInfo->TimerTicks.TiTickTwo = (UCHAR)DEFAULT_Ti_TICK_TWO;
  340. ConfigInfo->UseEthernetFrameSize = (BOOLEAN)DEFAULT_USE_ETHERNET_FRAME_SIZE;
  341. //
  342. // create and initialize a copy of the DLC adapter parameters template
  343. //
  344. parameterTable = (PDLC_REGISTRY_PARAMETER)ALLOCATE_MEMORY_DRIVER(
  345. sizeof(*parameterTable) * NUMBER_OF_DLC_PARAMETERS);
  346. if (parameterTable) {
  347. RtlCopyMemory(parameterTable, AdapterParameterTable, sizeof(AdapterParameterTable));
  348. for (i = 0; i < NUMBER_OF_DLC_PARAMETERS; ++i) {
  349. parameterTable[i].Descriptor.Value = (PVOID)&parameterTable[i].DefaultValue;
  350. switch (i) {
  351. case SWAP_INDEX:
  352. parameterTable[i].Descriptor.Variable = &ConfigInfo->SwapAddressBits;
  353. break;
  354. case USEDIX_INDEX:
  355. parameterTable[i].Descriptor.Variable = &ConfigInfo->UseDix;
  356. break;
  357. case T1_TICK_ONE_INDEX:
  358. parameterTable[i].Descriptor.Variable = &ConfigInfo->TimerTicks.T1TickOne;
  359. break;
  360. case T2_TICK_ONE_INDEX:
  361. parameterTable[i].Descriptor.Variable = &ConfigInfo->TimerTicks.T2TickOne;
  362. break;
  363. case Ti_TICK_ONE_INDEX:
  364. parameterTable[i].Descriptor.Variable = &ConfigInfo->TimerTicks.TiTickOne;
  365. break;
  366. case T1_TICK_TWO_INDEX:
  367. parameterTable[i].Descriptor.Variable = &ConfigInfo->TimerTicks.T1TickTwo;
  368. break;
  369. case T2_TICK_TWO_INDEX:
  370. parameterTable[i].Descriptor.Variable = &ConfigInfo->TimerTicks.T2TickTwo;
  371. break;
  372. case Ti_TICK_TWO_INDEX:
  373. parameterTable[i].Descriptor.Variable = &ConfigInfo->TimerTicks.TiTickTwo;
  374. break;
  375. case FRAME_SIZE_INDEX:
  376. parameterTable[i].Descriptor.Variable = &ConfigInfo->UseEthernetFrameSize;
  377. break;
  378. }
  379. }
  380. GetAdapterParameters(AdapterName, parameterTable, NUMBER_OF_DLC_PARAMETERS, FALSE);
  381. FREE_MEMORY_DRIVER(parameterTable);
  382. }
  383. #if DBG
  384. if (DebugConfig) {
  385. DbgPrint("DLC.LoadAdapterConfigurationFromRegistry for adapter %ws:\n"
  386. "\tSwap . . . . . . . . . : %d\n"
  387. "\tUseDixOverEthernet . . : %d\n"
  388. "\tT1TickOne. . . . . . . : %d\n"
  389. "\tT2TickOne. . . . . . . : %d\n"
  390. "\tTiTickOne. . . . . . . : %d\n"
  391. "\tT1TickTwo. . . . . . . : %d\n"
  392. "\tT2TickTwo. . . . . . . : %d\n"
  393. "\tTiTickTwo. . . . . . . : %d\n"
  394. "\tUseEthernetFrameSize . : %d\n",
  395. AdapterName->Buffer,
  396. ConfigInfo->SwapAddressBits,
  397. ConfigInfo->UseDix,
  398. ConfigInfo->TimerTicks.T1TickOne,
  399. ConfigInfo->TimerTicks.T2TickOne,
  400. ConfigInfo->TimerTicks.TiTickOne,
  401. ConfigInfo->TimerTicks.T1TickTwo,
  402. ConfigInfo->TimerTicks.T2TickTwo,
  403. ConfigInfo->TimerTicks.TiTickTwo,
  404. ConfigInfo->UseEthernetFrameSize
  405. );
  406. }
  407. #endif
  408. }
  409. #ifdef NDIS40
  410. NTSTATUS
  411. GetAdapterWaitTimeout(
  412. PULONG pulWait)
  413. /*++
  414. Routine Description:
  415. Some adapters are delayed during initialization and are not completed
  416. even after the PnPBindsComplete event (such as ATM LANE adapter).
  417. This timeout value 'WaitForAdapter' indicates how many seconds to wait for
  418. an adapter if is not already present/bound in LlcOpenAdapter
  419. Arguments:
  420. pulWait -- Pointer to variable to store the wait timeout.
  421. Return Value:
  422. STATUS_SUCCESS
  423. STATUS_INSUFFICIENT_RESOURCES
  424. --*/
  425. {
  426. NTSTATUS NtStatus;
  427. HANDLE hDlc;
  428. HANDLE hDlcParms;
  429. OBJECT_ATTRIBUTES ObjAttribs;
  430. ULONG ulDisp;
  431. NtStatus = OpenDlcRegistryHandle(&DlcRegistryPath, &hDlc);
  432. if (NT_SUCCESS(NtStatus))
  433. {
  434. InitializeObjectAttributes(
  435. &ObjAttribs,
  436. &ParametersPath,
  437. OBJ_CASE_INSENSITIVE,
  438. hDlc,
  439. NULL);
  440. NtStatus = ZwCreateKey(
  441. &hDlcParms,
  442. KEY_READ,
  443. &ObjAttribs,
  444. 0,
  445. NULL,
  446. 0,
  447. &ulDisp);
  448. if (NT_SUCCESS(NtStatus))
  449. {
  450. PDLC_REGISTRY_PARAMETER pWaitTimeout;
  451. pWaitTimeout = (PDLC_REGISTRY_PARAMETER) ALLOCATE_MEMORY_DRIVER(
  452. sizeof(DLC_REGISTRY_PARAMETER));
  453. if (pWaitTimeout)
  454. {
  455. RtlCopyMemory(
  456. pWaitTimeout,
  457. &AdapterInitTimeout,
  458. sizeof(AdapterInitTimeout));
  459. pWaitTimeout->Descriptor.Variable = pulWait;
  460. pWaitTimeout->Descriptor.Value = (PVOID)&pWaitTimeout->DefaultValue;
  461. NtStatus = GetRegistryParameter(
  462. hDlcParms,
  463. pWaitTimeout,
  464. FALSE); // Don't set on fail.
  465. FREE_MEMORY_DRIVER(pWaitTimeout);
  466. }
  467. else
  468. {
  469. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  470. }
  471. ZwClose(hDlcParms);
  472. }
  473. CloseDlcRegistryHandle(hDlc);
  474. }
  475. return (NtStatus);
  476. }
  477. #endif // NDIS40
  478. NTSTATUS
  479. GetAdapterParameters(
  480. IN PUNICODE_STRING AdapterName,
  481. IN PDLC_REGISTRY_PARAMETER Parameters,
  482. IN ULONG NumberOfParameters,
  483. IN BOOLEAN SetOnFail
  484. )
  485. /*++
  486. Routine Description:
  487. Retrieves a list of parameters from the DLC\Parameters\<AdapterName> section
  488. in the registry
  489. Arguments:
  490. AdapterName - pointer to UNICODE_STRING identifying adapter section
  491. in DLC section of registry to open
  492. Parameters - pointer to array of DLC_REGISTRY_PARAMETER structures
  493. describing variables and default values to retrieve
  494. NumberOfParameters - number of structures in Parameters array
  495. SetOnFail - TRUE if we should set the registry parameter if we
  496. fail to get it
  497. Return Value:
  498. NTSTATUS
  499. Success - STATUS_SUCCESS
  500. Failure -
  501. --*/
  502. {
  503. NTSTATUS status;
  504. HANDLE dlcHandle;
  505. ASSUME_IRQL(PASSIVE_LEVEL);
  506. status = OpenDlcRegistryHandle(&DlcRegistryPath, &dlcHandle);
  507. if (NT_SUCCESS(status)) {
  508. HANDLE adapterHandle;
  509. BOOLEAN created;
  510. status = OpenDlcAdapterRegistryHandle(dlcHandle,
  511. AdapterName,
  512. &adapterHandle,
  513. &created
  514. );
  515. if (NT_SUCCESS(status)) {
  516. while (NumberOfParameters--) {
  517. //
  518. // if this adapter section was created then create the parameter
  519. // value entries and set them to the defaults, else retrieve the
  520. // current registry values
  521. //
  522. if (created) {
  523. SetRegistryParameter(adapterHandle, Parameters);
  524. } else {
  525. GetRegistryParameter(adapterHandle, Parameters, SetOnFail);
  526. }
  527. ++Parameters;
  528. }
  529. CloseAdapterRegistryHandle(adapterHandle);
  530. }
  531. CloseDlcRegistryHandle(dlcHandle);
  532. }
  533. return status;
  534. }
  535. NTSTATUS
  536. OpenDlcRegistryHandle(
  537. IN PUNICODE_STRING RegistryPath,
  538. OUT PHANDLE DlcRegistryHandle
  539. )
  540. /*++
  541. Routine Description:
  542. Opens a handle to the DLC section in the registry
  543. Arguments:
  544. RegistryPath - pointer to UNICODE_STRING giving full registry path to
  545. DLC section
  546. DlcRegistryHandle - returned handle
  547. Return Value:
  548. NTSTATUS
  549. Success - STATUS_SUCCESS
  550. Failure -
  551. --*/
  552. {
  553. OBJECT_ATTRIBUTES objectAttributes;
  554. NTSTATUS status;
  555. ULONG disposition;
  556. ASSUME_IRQL(PASSIVE_LEVEL);
  557. InitializeObjectAttributes(&objectAttributes,
  558. RegistryPath,
  559. OBJ_CASE_INSENSITIVE,
  560. NULL,
  561. NULL
  562. );
  563. status = ZwCreateKey(DlcRegistryHandle,
  564. KEY_WRITE, // might want to update something in registry
  565. &objectAttributes,
  566. 0, // title index
  567. NULL, // class
  568. 0, // create options
  569. &disposition
  570. );
  571. #if DBG
  572. if (DebugConfig) {
  573. if (!NT_SUCCESS(status)) {
  574. DbgPrint("DLC.OpenDlcRegistryHandle: Error: %08x\n", status);
  575. }
  576. }
  577. #endif
  578. return status;
  579. }
  580. NTSTATUS
  581. OpenDlcAdapterRegistryHandle(
  582. IN HANDLE DlcRegistryHandle,
  583. IN PUNICODE_STRING AdapterName,
  584. OUT PHANDLE DlcAdapterRegistryHandle,
  585. OUT PBOOLEAN Created
  586. )
  587. /*++
  588. Routine Description:
  589. Opens a handle to the DLC\Parameters\<AdapterName> section in the registry.
  590. If this node does not exist, it is created
  591. Arguments:
  592. DlcRegistryHandle - open handle to DLC section in registry
  593. AdapterName - name of adapter in Parameters section. This
  594. MUST be of the form \Device\<adapter_name>
  595. DlcAdapterRegistryHandle - returned open handle
  596. Created - returned TRUE if the handle was created
  597. Return Value:
  598. NTSTATUS
  599. Success - STATUS_SUCCESS
  600. Failure -
  601. --*/
  602. {
  603. UNICODE_STRING keyName;
  604. UNICODE_STRING adapterName;
  605. WCHAR keyBuffer[sizeof(PARAMETERS_STRING) + MAX_ADAPTER_NAME_LENGTH];
  606. OBJECT_ATTRIBUTES objectAttributes;
  607. NTSTATUS status;
  608. ULONG disposition;
  609. ASSUME_IRQL(PASSIVE_LEVEL);
  610. keyName.Buffer = keyBuffer;
  611. keyName.Length = 0;
  612. keyName.MaximumLength = sizeof(keyBuffer);
  613. RtlCopyUnicodeString(&keyName, &ParametersPath);
  614. RtlInitUnicodeString(&adapterName, AdapterName->Buffer);
  615. adapterName.Buffer += sizeof(L"\\Device") / sizeof(L"") - 1;
  616. adapterName.Length -= sizeof(L"\\Device") - sizeof(L"");
  617. adapterName.MaximumLength -= sizeof(L"\\Device") - sizeof(L"");
  618. RtlAppendUnicodeStringToString(&keyName, &adapterName);
  619. InitializeObjectAttributes(&objectAttributes,
  620. &keyName,
  621. OBJ_CASE_INSENSITIVE,
  622. DlcRegistryHandle,
  623. NULL
  624. );
  625. //
  626. // if the DLC\Parameters\<adapter_name> key does not exist, then we will
  627. // create it
  628. //
  629. status = ZwCreateKey(DlcAdapterRegistryHandle,
  630. KEY_WRITE,
  631. &objectAttributes,
  632. 0,
  633. NULL,
  634. 0,
  635. &disposition
  636. );
  637. *Created = (disposition == REG_CREATED_NEW_KEY);
  638. #if DBG
  639. if (DebugConfig) {
  640. if (!NT_SUCCESS(status)) {
  641. DbgPrint("DLC.OpenDlcAdapterRegistryHandle: Error: %08x\n", status);
  642. }
  643. }
  644. #endif
  645. return status;
  646. }
  647. NTSTATUS
  648. GetRegistryParameter(
  649. IN HANDLE KeyHandle,
  650. IN PDLC_REGISTRY_PARAMETER Parameter,
  651. IN BOOLEAN SetOnFail
  652. )
  653. /*++
  654. Routine Description:
  655. Retrieves a parameter from a section of the registry. If the section cannot
  656. be accessed or returns invalid data, then we get the default value from the
  657. Parameter structure
  658. Arguments:
  659. KeyHandle - open handle to the required section in the registry
  660. Parameter - pointer to DLC_REGISTRY_PARAMETER structure giving address and
  661. type of the parameter to be retrieved, etc.
  662. SetOnFail - if we fail to get the value from the registry, we try to set
  663. the default value in the registry
  664. Return Value:
  665. NTSTATUS
  666. Success - STATUS_SUCCESS
  667. Failure -
  668. --*/
  669. {
  670. NTSTATUS status;
  671. UNICODE_STRING parameterName;
  672. UCHAR informationBuffer[MAX_INFORMATION_BUFFER_LENGTH];
  673. PKEY_VALUE_FULL_INFORMATION valueInformation = (PKEY_VALUE_FULL_INFORMATION)informationBuffer;
  674. ULONG informationLength;
  675. ASSUME_IRQL(PASSIVE_LEVEL);
  676. RtlInitUnicodeString(&parameterName, Parameter->ParameterName);
  677. status = ZwQueryValueKey(KeyHandle,
  678. &parameterName,
  679. KeyValueFullInformation,
  680. (PVOID)valueInformation,
  681. sizeof(informationBuffer),
  682. &informationLength
  683. );
  684. if (NT_SUCCESS(status) && valueInformation->DataLength) {
  685. //
  686. // use the value retrieved from the registry
  687. //
  688. status = DlcpGetParameter(Parameter->ParameterName,
  689. valueInformation->Type,
  690. (PVOID)&informationBuffer[valueInformation->DataOffset],
  691. valueInformation->DataLength,
  692. NULL,
  693. (PVOID)&Parameter->Descriptor
  694. );
  695. } else {
  696. #if DBG
  697. if (DebugConfig) {
  698. if (!NT_SUCCESS(status)) {
  699. DbgPrint("DLC.GetRegistryParameter: Error: %08x\n", status);
  700. } else {
  701. DbgPrint("DLC.GetRegistryParameter: Error: valueInformation->DataLength is 0\n");
  702. }
  703. }
  704. #endif
  705. if (!NT_SUCCESS(status) && SetOnFail) {
  706. SetRegistryParameter(KeyHandle, Parameter);
  707. }
  708. //
  709. // set the default value
  710. //
  711. status = DlcpGetParameter(Parameter->ParameterName,
  712. Parameter->Descriptor.Type,
  713. Parameter->Descriptor.Value,
  714. Parameter->Descriptor.Length,
  715. NULL,
  716. (PVOID)&Parameter->Descriptor
  717. );
  718. }
  719. return status;
  720. }
  721. NTSTATUS
  722. SetRegistryParameter(
  723. IN HANDLE KeyHandle,
  724. IN PDLC_REGISTRY_PARAMETER Parameter
  725. )
  726. /*++
  727. Routine Description:
  728. Sets a parameter in the DLC\Parameters\<AdapterName> section
  729. Arguments:
  730. KeyHandle - open handle to required section in registry
  731. Parameter - pointer to DLC_REGISTRY_PARAMETER containing all required
  732. parameter information
  733. Return Value:
  734. NTSTATUS
  735. Success - STATUS_SUCCESS
  736. Failure -
  737. --*/
  738. {
  739. NTSTATUS status;
  740. UNICODE_STRING name;
  741. ASSUME_IRQL(PASSIVE_LEVEL);
  742. RtlInitUnicodeString(&name, Parameter->ParameterName);
  743. status = ZwSetValueKey(KeyHandle,
  744. &name,
  745. 0, // TitleIndex
  746. Parameter->Descriptor.Type,
  747. Parameter->Descriptor.Value,
  748. Parameter->Descriptor.Length
  749. );
  750. #if DBG
  751. if (DebugConfig) {
  752. if (!NT_SUCCESS(status)) {
  753. DbgPrint("DLC.SetRegistryParameter: Error: %08x\n", status);
  754. }
  755. }
  756. #endif
  757. return status;
  758. }
  759. NTSTATUS
  760. DlcpGetParameter(
  761. IN PWSTR ValueName,
  762. IN ULONG ValueType,
  763. IN PVOID ValueData,
  764. IN ULONG ValueLength,
  765. IN PVOID Context,
  766. IN PVOID EntryContext
  767. )
  768. /*++
  769. Routine Description:
  770. Call-back function which copies the data retrieved from the registry to
  771. a variable
  772. Arguments:
  773. ValueName - pointer to name of parameter being set (ignored)
  774. ValueType - type of parameter being set
  775. ValueData - pointer to data retrieved from registry
  776. ValueLength - length of data retrieved
  777. Context - ignored
  778. EntryContext - pointer to REGISTRY_PARAMETER_DESCRIPTOR structure
  779. Return Value:
  780. NTSTATUS
  781. Success - STATUS_SUCCESS
  782. Failure -
  783. --*/
  784. {
  785. #define Descriptor ((PREGISTRY_PARAMETER_DESCRIPTOR)EntryContext)
  786. //
  787. // if we have a registry entry for the parameter, but it is a different
  788. // type from that expected (say REG_SZ instead of REG_DWORD) then we use
  789. // the default type, length and value
  790. //
  791. if (ValueType != Descriptor->Type) {
  792. #if DBG
  793. DbgPrint("DLC.DlcpGetParameter: Error: type for %ws is %d, expected %d, using default\n",
  794. ValueName,
  795. ValueType,
  796. Descriptor->Type
  797. );
  798. #endif
  799. ValueType = Descriptor->Type;
  800. ValueData = Descriptor->Value;
  801. ValueLength = Descriptor->Length;
  802. }
  803. switch (ValueType) {
  804. case REG_DWORD: {
  805. ULONG value;
  806. if (Descriptor->RealType == PARAMETER_IS_BOOLEAN) {
  807. value = (*(PULONG)ValueData != 0);
  808. *(PBOOLEAN)(Descriptor->Variable) = (BOOLEAN)value;
  809. //
  810. // no limit check for BOOLEAN type
  811. //
  812. break;
  813. } else {
  814. value = *(PULONG)ValueData;
  815. }
  816. //
  817. // check range. If outside range, use default. Comparison is ULONG
  818. //
  819. if (value < Descriptor->LowerLimit || value > Descriptor->UpperLimit) {
  820. #if DBG
  821. DbgPrint("DLC.DlcpGetParameter: Error: Parameter %ws = %d: Out of range (%d..%d). Using default = %d\n",
  822. ValueName,
  823. value,
  824. Descriptor->LowerLimit,
  825. Descriptor->UpperLimit,
  826. *(PULONG)(Descriptor->Value)
  827. );
  828. #endif
  829. value = *(PULONG)(Descriptor->Value);
  830. }
  831. if (Descriptor->RealType == PARAMETER_IS_UCHAR) {
  832. *(PUCHAR)(Descriptor->Variable) = (UCHAR)value;
  833. } else {
  834. *(PULONG)(Descriptor->Variable) = value;
  835. }
  836. break;
  837. }
  838. #if DBG
  839. default:
  840. DbgPrint("DLC.DlcpGetParameter: Error: didn't expect ValueType %d\n", ValueType);
  841. #endif
  842. }
  843. return STATUS_SUCCESS;
  844. #undef pDescriptor
  845. }