Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1555 lines
47 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. NDIS wrapper functions initializing drivers.
  7. Author:
  8. Adam Barr (adamba) 11-Jul-1990
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. 26-Feb-1991 JohnsonA Added Debugging Code
  13. 10-Jul-1991 JohnsonA Implement revised Ndis Specs
  14. 01-Jun-1995 JameelH Re-organized
  15. --*/
  16. #include <precomp.h>
  17. #include <atm.h>
  18. #pragma hdrstop
  19. #include <stdarg.h>
  20. //
  21. // Define the module number for debug code.
  22. //
  23. #define MODULE_NUMBER MODULE_INIT
  24. //
  25. // Configuration Requests
  26. //
  27. VOID
  28. NdisOpenConfiguration(
  29. OUT PNDIS_STATUS Status,
  30. OUT PNDIS_HANDLE ConfigurationHandle,
  31. IN NDIS_HANDLE WrapperConfigurationContext
  32. )
  33. /*++
  34. Routine Description:
  35. This routine is used to open the parameter subkey of the
  36. adapter registry tree.
  37. Arguments:
  38. Status - Returns the status of the request.
  39. ConfigurationHandle - Returns a handle which is used in calls to
  40. NdisReadConfiguration and NdisCloseConfiguration.
  41. WrapperConfigurationContext - a handle pointing to an RTL_QUERY_REGISTRY_TABLE
  42. that is set up for this driver's parameters.
  43. Return Value:
  44. None.
  45. --*/
  46. {
  47. //
  48. // Handle to be returned
  49. //
  50. PNDIS_CONFIGURATION_HANDLE HandleToReturn;
  51. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  52. ("==>NdisOpenConfiguration: WrapperConfigurationContext %p\n", WrapperConfigurationContext));
  53. //
  54. // Allocate the configuration handle
  55. //
  56. HandleToReturn = ALLOC_FROM_POOL(sizeof(NDIS_CONFIGURATION_HANDLE), NDIS_TAG_CONFIG_HANLDE);
  57. *Status = (HandleToReturn != NULL) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES;
  58. if (*Status == NDIS_STATUS_SUCCESS)
  59. {
  60. HandleToReturn->KeyQueryTable = ((PNDIS_WRAPPER_CONFIGURATION_HANDLE)WrapperConfigurationContext)->ParametersQueryTable;
  61. HandleToReturn->ParameterList = NULL;
  62. *ConfigurationHandle = (NDIS_HANDLE)HandleToReturn;
  63. }
  64. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  65. ("<==NdisOpenConfiguration: WrapperConfigurationContext %p\n", WrapperConfigurationContext));
  66. }
  67. VOID
  68. NdisOpenConfigurationKeyByName(
  69. OUT PNDIS_STATUS Status,
  70. IN NDIS_HANDLE ConfigurationHandle,
  71. IN PNDIS_STRING KeyName,
  72. OUT PNDIS_HANDLE KeyHandle
  73. )
  74. /*++
  75. Routine Description:
  76. This routine is used to open a subkey relative to the configuration handle.
  77. Arguments:
  78. Status - Returns the status of the request.
  79. ConfigurationHandle - Handle to an already open section of the registry
  80. KeyName - Name of the subkey to open
  81. KeyHandle - Placeholder for the handle to the sub-key.
  82. Return Value:
  83. None.
  84. --*/
  85. {
  86. //
  87. // Handle to be returned
  88. //
  89. PNDIS_CONFIGURATION_HANDLE SKHandle, ConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
  90. PNDIS_WRAPPER_CONFIGURATION_HANDLE WConfigHandle;
  91. UNICODE_STRING Parent, Child, Sep;
  92. #define PQueryTable WConfigHandle->ParametersQueryTable
  93. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  94. ("==>NdisOpenConfigurationKeyByName: ConfigurationHandle\n", ConfigurationHandle));
  95. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  96. do
  97. {
  98. if (*ConfigHandle->KeyQueryTable[3].Name)
  99. {
  100. RtlInitUnicodeString(&Parent, ConfigHandle->KeyQueryTable[3].Name);
  101. RtlInitUnicodeString(&Sep, L"\\");
  102. Child.MaximumLength = KeyName->Length + Parent.Length + Sep.Length + sizeof(WCHAR);
  103. }
  104. else
  105. {
  106. Child.MaximumLength = KeyName->Length + sizeof(WCHAR);
  107. }
  108. Child.Length = 0;
  109. //
  110. // Allocate the configuration handle
  111. //
  112. SKHandle = ALLOC_FROM_POOL(sizeof(NDIS_CONFIGURATION_HANDLE) +
  113. sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE) +
  114. Child.MaximumLength,
  115. NDIS_TAG_CONFIG_HANLDE);
  116. *Status = (SKHandle != NULL) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES;
  117. if (*Status != NDIS_STATUS_SUCCESS)
  118. {
  119. *KeyHandle = (NDIS_HANDLE)NULL;
  120. break;
  121. }
  122. WConfigHandle = (PNDIS_WRAPPER_CONFIGURATION_HANDLE)((PUCHAR)SKHandle + sizeof(NDIS_CONFIGURATION_HANDLE));
  123. Child.Buffer = (PWSTR)((PUCHAR)WConfigHandle + sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE));
  124. //
  125. // if there is no parent path, avoid starting the child path with "\\"
  126. //
  127. if (*ConfigHandle->KeyQueryTable[3].Name)
  128. {
  129. RtlCopyUnicodeString(&Child, &Parent);
  130. RtlAppendUnicodeStringToString(&Child, &Sep);
  131. }
  132. RtlAppendUnicodeStringToString(&Child, KeyName);
  133. SKHandle->KeyQueryTable = WConfigHandle->ParametersQueryTable;
  134. PQueryTable[0].QueryRoutine = NULL;
  135. PQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  136. PQueryTable[0].Name = L"";
  137. //
  138. // 1.
  139. // Call ndisSaveParameter for a parameter, which will allocate storage for it.
  140. //
  141. PQueryTable[1].QueryRoutine = ndisSaveParameters;
  142. PQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  143. PQueryTable[1].DefaultType = REG_NONE;
  144. //
  145. // PQueryTable[0].Name and PQueryTable[0].EntryContext
  146. // are filled in inside ReadConfiguration, in preparation
  147. // for the callback.
  148. //
  149. // PQueryTable[0].Name = KeywordBuffer;
  150. // PQueryTable[0].EntryContext = ParameterValue;
  151. //
  152. // 2.
  153. // Stop
  154. //
  155. PQueryTable[2].QueryRoutine = NULL;
  156. PQueryTable[2].Flags = 0;
  157. PQueryTable[2].Name = NULL;
  158. //
  159. // NOTE: Some fields in ParametersQueryTable[3] are used to store information for later retrieval.
  160. //
  161. PQueryTable[3].QueryRoutine = ConfigHandle->KeyQueryTable[3].QueryRoutine;
  162. PQueryTable[3].Name = Child.Buffer;
  163. PQueryTable[3].EntryContext = NULL;
  164. PQueryTable[3].DefaultData = NULL;
  165. SKHandle->ParameterList = NULL;
  166. *KeyHandle = (NDIS_HANDLE)SKHandle;
  167. } while (FALSE);
  168. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  169. ("<==NdisOpenConfigurationKeyByName: ConfigurationHandle\n", ConfigurationHandle));
  170. #undef PQueryTable
  171. }
  172. VOID
  173. NdisOpenConfigurationKeyByIndex(
  174. OUT PNDIS_STATUS Status,
  175. IN NDIS_HANDLE ConfigurationHandle,
  176. IN ULONG Index,
  177. OUT PNDIS_STRING KeyName,
  178. OUT PNDIS_HANDLE KeyHandle
  179. )
  180. /*++
  181. Routine Description:
  182. This routine is used to open a subkey relative to the configuration handle.
  183. Arguments:
  184. Status - Returns the status of the request.
  185. ConfigurationHandle - Handle to an already open section of the registry
  186. Index - Index of the sub-key to open
  187. KeyName - Placeholder for the name of subkey being opened
  188. KeyHandle - Placeholder for the handle to the sub-key.
  189. Return Value:
  190. None.
  191. --*/
  192. {
  193. PNDIS_CONFIGURATION_HANDLE ConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
  194. HANDLE Handle = NULL, RootHandle = NULL;
  195. OBJECT_ATTRIBUTES ObjAttr;
  196. UNICODE_STRING KeyPath = {0}, Services = {0}, AbsolutePath={0};
  197. PKEY_BASIC_INFORMATION InfoBuf = NULL;
  198. ULONG Len;
  199. PDEVICE_OBJECT PhysicalDeviceObject;
  200. PNDIS_MINIPORT_BLOCK Miniport;
  201. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  202. ("==>NdisOpenConfigurationKeyByIndex: ConfigurationHandle\n", ConfigurationHandle));
  203. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  204. *KeyHandle = NULL;
  205. do
  206. {
  207. if (ConfigHandle->KeyQueryTable[3].Name != NULL)
  208. {
  209. RtlInitUnicodeString(&KeyPath, ConfigHandle->KeyQueryTable[3].Name);
  210. }
  211. if ((Miniport = (PNDIS_MINIPORT_BLOCK)ConfigHandle->KeyQueryTable[3].QueryRoutine) == NULL)
  212. {
  213. //
  214. // protocols
  215. //
  216. //
  217. // Open the current key and lookup the Nth subkey. But first conver the service relative
  218. // path to absolute since this is what ZwOpenKey expects.
  219. //
  220. RtlInitUnicodeString(&Services, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
  221. }
  222. else
  223. {
  224. //
  225. // Adapters
  226. //
  227. // for adapters, first we have to open the key for PDO
  228. //
  229. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  230. #if NDIS_TEST_REG_FAILURE
  231. *Status = STATUS_UNSUCCESSFUL;
  232. #else
  233. *Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  234. PLUGPLAY_REGKEY_DRIVER,
  235. GENERIC_READ | MAXIMUM_ALLOWED,
  236. &RootHandle);
  237. #endif
  238. if (!NT_SUCCESS(*Status))
  239. {
  240. break;
  241. }
  242. }
  243. if (KeyPath.Length || Services.Length)
  244. {
  245. AbsolutePath.MaximumLength = KeyPath.Length + Services.Length + sizeof(WCHAR);
  246. AbsolutePath.Buffer = (PWSTR)ALLOC_FROM_POOL(AbsolutePath.MaximumLength, NDIS_TAG_DEFAULT);
  247. if (AbsolutePath.Buffer == NULL)
  248. {
  249. *Status = NDIS_STATUS_RESOURCES;
  250. break;
  251. }
  252. NdisMoveMemory(AbsolutePath.Buffer, Services.Buffer, Services.Length);
  253. AbsolutePath.Length = Services.Length;
  254. RtlAppendUnicodeStringToString(&AbsolutePath, &KeyPath);
  255. }
  256. InitializeObjectAttributes(&ObjAttr,
  257. &AbsolutePath,
  258. OBJ_CASE_INSENSITIVE,
  259. RootHandle,
  260. NULL);
  261. *Status = ZwOpenKey(&Handle,
  262. GENERIC_READ | MAXIMUM_ALLOWED,
  263. &ObjAttr);
  264. if (!NT_SUCCESS(*Status))
  265. {
  266. Handle = NULL;
  267. break;
  268. }
  269. //
  270. // Allocate memory for the call to ZwEnumerateKey
  271. //
  272. Len = sizeof(KEY_BASIC_INFORMATION) + 256;
  273. InfoBuf = (PKEY_BASIC_INFORMATION)ALLOC_FROM_POOL(Len, NDIS_TAG_DEFAULT);
  274. if (InfoBuf == NULL)
  275. {
  276. *Status = NDIS_STATUS_RESOURCES;
  277. break;
  278. }
  279. //
  280. // Get the Index(th) key, if it exists
  281. //
  282. *Status = ZwEnumerateKey(Handle,
  283. Index,
  284. KeyValueBasicInformation,
  285. InfoBuf,
  286. Len,
  287. &Len);
  288. if (NT_SUCCESS(*Status))
  289. {
  290. //
  291. // This worked. Now simply pick up the name and do a NdisOpenConfigurationKeyByName on it.
  292. //
  293. KeyPath.Length = KeyPath.MaximumLength = (USHORT)InfoBuf->NameLength;
  294. KeyPath.Buffer = InfoBuf->Name;
  295. NdisOpenConfigurationKeyByName(Status,
  296. ConfigurationHandle,
  297. &KeyPath,
  298. KeyHandle);
  299. if (*Status == NDIS_STATUS_SUCCESS)
  300. {
  301. PNDIS_CONFIGURATION_HANDLE NewHandle = *(PNDIS_CONFIGURATION_HANDLE *)KeyHandle;
  302. //
  303. // The path in the new handle has the name of the key. Extract it and return to caller
  304. //
  305. RtlInitUnicodeString(KeyName, NewHandle->KeyQueryTable[3].Name);
  306. KeyName->Buffer = (PWSTR)((PUCHAR)KeyName->Buffer + KeyName->Length - KeyPath.Length);
  307. KeyName->Length = KeyPath.Length;
  308. KeyName->MaximumLength = KeyPath.MaximumLength;
  309. }
  310. }
  311. } while (FALSE);
  312. if (AbsolutePath.Buffer != NULL)
  313. {
  314. FREE_POOL(AbsolutePath.Buffer);
  315. }
  316. if (InfoBuf != NULL)
  317. {
  318. FREE_POOL(InfoBuf);
  319. }
  320. if (RootHandle)
  321. ZwClose (RootHandle);
  322. if (Handle)
  323. ZwClose (Handle);
  324. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  325. ("<==NdisOpenConfigurationKeyByIndex: ConfigurationHandle\n", ConfigurationHandle));
  326. }
  327. VOID
  328. NdisReadConfiguration(
  329. OUT PNDIS_STATUS Status,
  330. OUT PNDIS_CONFIGURATION_PARAMETER * ParameterValue,
  331. IN NDIS_HANDLE ConfigurationHandle,
  332. IN PNDIS_STRING Keyword,
  333. IN NDIS_PARAMETER_TYPE ParameterType
  334. )
  335. /*++
  336. Routine Description:
  337. This routine is used to read the parameter for a configuration
  338. keyword from the configuration database.
  339. Arguments:
  340. Status - Returns the status of the request.
  341. ParameterValue - Returns the value for this keyword.
  342. ConfigurationHandle - Handle returned by NdisOpenConfiguration. Points
  343. to the parameter subkey.
  344. Keyword - The keyword to search for.
  345. ParameterType - Ignored on NT, specifies the type of the value.
  346. Return Value:
  347. None.
  348. --*/
  349. {
  350. NTSTATUS RegistryStatus;
  351. PWSTR KeywordBuffer;
  352. UINT i;
  353. PNDIS_CONFIGURATION_HANDLE ConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
  354. PDEVICE_OBJECT PhysicalDeviceObject;
  355. HANDLE Handle = NULL;
  356. PNDIS_MINIPORT_BLOCK Miniport = NULL;
  357. PDEVICE_OBJECT DeviceObject;
  358. PCM_PARTIAL_RESOURCE_LIST pResourceList;
  359. UINT j;
  360. ULONG ValueData;
  361. #define PQueryTable ConfigHandle->KeyQueryTable
  362. //
  363. // There are some built-in parameters which can always be
  364. // read, even if not present in the registry. This is the
  365. // number of them.
  366. //
  367. #define BUILT_IN_COUNT 3
  368. static NDIS_STRING BuiltInStrings[BUILT_IN_COUNT] =
  369. {
  370. NDIS_STRING_CONST ("Environment"),
  371. NDIS_STRING_CONST ("ProcessorType"),
  372. NDIS_STRING_CONST ("NdisVersion")
  373. };
  374. static NDIS_STRING MiniportNameStr = NDIS_STRING_CONST ("MiniportName");
  375. #define STANDARD_RESOURCE_COUNT 9
  376. //
  377. // The names of the standard resource types.
  378. //
  379. static NDIS_STRING StandardResourceStrings[STANDARD_RESOURCE_COUNT] =
  380. {
  381. NDIS_STRING_CONST ("IoBaseAddress"),
  382. NDIS_STRING_CONST ("InterruptNumber"),
  383. NDIS_STRING_CONST ("MemoryMappedBaseAddress"),
  384. NDIS_STRING_CONST ("DmaChannel"),
  385. //
  386. // a few drivers use non-standard keywords, so take care of them for now
  387. //
  388. NDIS_STRING_CONST ("IoAddress"),
  389. NDIS_STRING_CONST ("Interrupt"),
  390. NDIS_STRING_CONST ("IOBase"),
  391. NDIS_STRING_CONST ("Irq"),
  392. NDIS_STRING_CONST ("RamAddress")
  393. };
  394. UCHAR StandardResourceTypes[STANDARD_RESOURCE_COUNT]=
  395. {
  396. CmResourceTypePort,
  397. CmResourceTypeInterrupt,
  398. CmResourceTypeMemory,
  399. CmResourceTypeDma,
  400. CmResourceTypePort,
  401. CmResourceTypeInterrupt,
  402. CmResourceTypePort,
  403. CmResourceTypeInterrupt,
  404. CmResourceTypeMemory
  405. };
  406. static NDIS_CONFIGURATION_PARAMETER BuiltInParameters[BUILT_IN_COUNT] =
  407. { { NdisParameterInteger, NdisEnvironmentWindowsNt },
  408. { NdisParameterInteger,
  409. #if defined(_M_IX86)
  410. NdisProcessorX86
  411. #elif defined(_M_MRX000)
  412. NdisProcessorMips
  413. #elif defined(_ALPHA_)
  414. NdisProcessorAlpha
  415. #else
  416. NdisProcessorPpc
  417. #endif
  418. },
  419. { NdisParameterInteger, ((NDIS_MAJOR_VERSION << 16) | NDIS_MINOR_VERSION)}
  420. };
  421. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  422. ("==>NdisReadConfiguration\n"));
  423. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  424. (" Keyword: "));
  425. DBGPRINT_UNICODE(DBG_COMP_REG, DBG_LEVEL_INFO,
  426. Keyword);
  427. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  428. ("\n"));
  429. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  430. do
  431. {
  432. KeywordBuffer = Keyword->Buffer;
  433. //
  434. // assume failure
  435. //
  436. RegistryStatus = STATUS_UNSUCCESSFUL;
  437. //
  438. // First check if this is one of the built-in parameters.
  439. //
  440. for (i = 0; i < BUILT_IN_COUNT; i++)
  441. {
  442. if (RtlEqualUnicodeString(Keyword, &BuiltInStrings[i], TRUE))
  443. {
  444. RegistryStatus = STATUS_SUCCESS;
  445. *ParameterValue = &BuiltInParameters[i];
  446. break;
  447. }
  448. }
  449. if (NT_SUCCESS(RegistryStatus))
  450. break;
  451. if ((Miniport = (PNDIS_MINIPORT_BLOCK)PQueryTable[3].QueryRoutine) != NULL)
  452. {
  453. //
  454. // check to see if driver is asking for miniport name
  455. //
  456. if (RtlEqualUnicodeString(Keyword, &MiniportNameStr, TRUE))
  457. {
  458. RegistryStatus = ndisSaveParameters(MiniportNameStr.Buffer,
  459. REG_SZ,
  460. (PVOID)Miniport->MiniportName.Buffer,
  461. Miniport->MiniportName.Length,
  462. (PVOID)ConfigHandle,
  463. (PVOID)ParameterValue);
  464. break;
  465. }
  466. //
  467. // check to see if this is a resource keyword
  468. //
  469. for (i = 0; i < STANDARD_RESOURCE_COUNT; i++)
  470. {
  471. if (RtlEqualUnicodeString(Keyword, &StandardResourceStrings[i], TRUE))
  472. break;
  473. }
  474. if (i < STANDARD_RESOURCE_COUNT)
  475. {
  476. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_2,
  477. ("NdisReadConfiguration: Miniport %p should use NdisMQueryAdapterResources to get the standard resources.\n", Miniport));
  478. do
  479. {
  480. if (Miniport->AllocatedResources == NULL)
  481. break;
  482. pResourceList = &(Miniport->AllocatedResources->List[0].PartialResourceList);
  483. //
  484. // walk through resource list and find the first one that matches
  485. //
  486. for (j = 0; j < pResourceList->Count; j++)
  487. {
  488. if (pResourceList->PartialDescriptors[j].Type == StandardResourceTypes[i])
  489. {
  490. //
  491. // could have used pResourceList->PartialDescriptors[j].Generic.Start.LowPart for all
  492. // cases, but in the future, memory value can be 64 bit
  493. //
  494. switch (StandardResourceTypes[i])
  495. {
  496. case CmResourceTypePort:
  497. ValueData = pResourceList->PartialDescriptors[j].u.Port.Start.LowPart;
  498. break;
  499. case CmResourceTypeInterrupt:
  500. ValueData = pResourceList->PartialDescriptors[j].u.Interrupt.Level;
  501. break;
  502. case CmResourceTypeMemory:
  503. ValueData = pResourceList->PartialDescriptors[j].u.Memory.Start.LowPart;
  504. break;
  505. case CmResourceTypeDma:
  506. ValueData = pResourceList->PartialDescriptors[j].u.Dma.Channel;
  507. break;
  508. default:
  509. ASSERT(FALSE);
  510. }
  511. //
  512. // call SaveParameter ourselves
  513. //
  514. RegistryStatus = ndisSaveParameters(StandardResourceStrings[i].Buffer,
  515. REG_DWORD,
  516. (PVOID)&ValueData,
  517. sizeof(ULONG),
  518. (PVOID)ConfigHandle,
  519. (PVOID)ParameterValue);
  520. break;
  521. }
  522. }
  523. if (j >= pResourceList->Count)
  524. {
  525. RegistryStatus = STATUS_UNSUCCESSFUL;
  526. }
  527. } while (FALSE);
  528. //
  529. // if keyword was a standard resource keyword, we should break here
  530. // no matter what the outcome of finding the resource in resource list
  531. //
  532. break;
  533. } // end of if it was a resource keyword
  534. } // end of if NdisReadConfiguration called for a miniport
  535. //
  536. // the keyword was not a standard resource or built-in keyword
  537. // get back to our regular programming...
  538. //
  539. //
  540. // Allocate room for a null-terminated version of the keyword
  541. //
  542. if (Keyword->MaximumLength < (Keyword->Length + sizeof(WCHAR)))
  543. {
  544. KeywordBuffer = (PWSTR)ALLOC_FROM_POOL(Keyword->Length + sizeof(WCHAR), NDIS_TAG_DEFAULT);
  545. if (KeywordBuffer == NULL)
  546. {
  547. RegistryStatus = STATUS_UNSUCCESSFUL;;
  548. break;
  549. }
  550. CopyMemory(KeywordBuffer, Keyword->Buffer, Keyword->Length);
  551. }
  552. if (*(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) != (WCHAR)L'\0')
  553. {
  554. *(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) = (WCHAR)L'\0';
  555. }
  556. PQueryTable[1].Name = KeywordBuffer;
  557. PQueryTable[1].EntryContext = ParameterValue;
  558. if (Miniport != NULL)
  559. {
  560. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  561. //
  562. // set the subkey
  563. //
  564. PQueryTable[0].Name = PQueryTable[3].Name;
  565. #if NDIS_TEST_REG_FAILURE
  566. RegistryStatus = STATUS_UNSUCCESSFUL;
  567. #else
  568. RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  569. PLUGPLAY_REGKEY_DRIVER,
  570. GENERIC_READ | MAXIMUM_ALLOWED,
  571. &Handle);
  572. #endif
  573. if(NT_SUCCESS(RegistryStatus))
  574. {
  575. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  576. Handle,
  577. PQueryTable,
  578. ConfigHandle, // context
  579. NULL);
  580. }
  581. }
  582. else
  583. {
  584. //
  585. // protocols
  586. //
  587. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
  588. PQueryTable[3].Name,
  589. PQueryTable,
  590. ConfigHandle, // context
  591. NULL);
  592. }
  593. if (NT_SUCCESS(RegistryStatus))
  594. {
  595. //
  596. // if a value is stored in registry as string but the driver is trying
  597. // to read it as Integer or HexInteger, do the conversion here
  598. //
  599. if ((*ParameterValue)->ParameterType == NdisParameterString)
  600. {
  601. if (ParameterType == NdisParameterInteger)
  602. {
  603. RtlUnicodeStringToInteger(&(*ParameterValue)->ParameterData.StringData,
  604. 10, (PULONG)(&(*ParameterValue)->ParameterData.IntegerData));
  605. (*ParameterValue)->ParameterType = NdisParameterInteger;
  606. }
  607. else if (ParameterType == NdisParameterHexInteger)
  608. {
  609. RtlUnicodeStringToInteger(&(*ParameterValue)->ParameterData.StringData,
  610. 16, (PULONG)(&(*ParameterValue)->ParameterData.IntegerData));
  611. (*ParameterValue)->ParameterType = NdisParameterHexInteger;
  612. }
  613. }
  614. }
  615. } while (FALSE);
  616. if (KeywordBuffer != Keyword->Buffer)
  617. {
  618. FREE_POOL(KeywordBuffer); // no longer needed
  619. }
  620. if (!NT_SUCCESS(RegistryStatus))
  621. {
  622. *Status = NDIS_STATUS_FAILURE;
  623. }
  624. else
  625. {
  626. *Status = NDIS_STATUS_SUCCESS;
  627. }
  628. if (Handle)
  629. ZwClose(Handle);
  630. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  631. ("<==NdisReadConfiguration\n"));
  632. #undef PQueryTable
  633. }
  634. VOID
  635. NdisWriteConfiguration(
  636. OUT PNDIS_STATUS Status,
  637. IN NDIS_HANDLE ConfigurationHandle,
  638. IN PNDIS_STRING Keyword,
  639. PNDIS_CONFIGURATION_PARAMETER ParameterValue
  640. )
  641. /*++
  642. Routine Description:
  643. This routine is used to write a parameter to the configuration database.
  644. Arguments:
  645. Status - Returns the status of the request.
  646. ConfigurationHandle - Handle passed to the driver
  647. Keyword - The keyword to set.
  648. ParameterValue - Specifies the new value for this keyword.
  649. Return Value:
  650. None.
  651. --*/
  652. {
  653. PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
  654. NTSTATUS RegistryStatus;
  655. PNDIS_MINIPORT_BLOCK Miniport;
  656. PWSTR KeywordBuffer;
  657. BOOLEAN FreeKwBuf = FALSE;
  658. PVOID ValueData;
  659. ULONG ValueLength;
  660. ULONG ValueType;
  661. PDEVICE_OBJECT PhysicalDeviceObject;
  662. HANDLE Handle, RootHandle;
  663. OBJECT_ATTRIBUTES ObjAttr;
  664. UNICODE_STRING RelativePath;
  665. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  666. ("==>NdisWriteConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  667. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  668. *Status = NDIS_STATUS_SUCCESS;
  669. KeywordBuffer = Keyword->Buffer;
  670. do
  671. {
  672. //
  673. // Get the value data.
  674. //
  675. switch (ParameterValue->ParameterType)
  676. {
  677. case NdisParameterHexInteger:
  678. case NdisParameterInteger:
  679. ValueData = &ParameterValue->ParameterData.IntegerData;
  680. ValueLength = sizeof(ParameterValue->ParameterData.IntegerData);
  681. ValueType = REG_DWORD;
  682. break;
  683. case NdisParameterString:
  684. ValueData = ParameterValue->ParameterData.StringData.Buffer;
  685. ValueLength = ParameterValue->ParameterData.StringData.Length;
  686. ValueType = REG_SZ;
  687. break;
  688. case NdisParameterMultiString:
  689. ValueData = ParameterValue->ParameterData.StringData.Buffer;
  690. ValueLength = ParameterValue->ParameterData.StringData.Length;
  691. ValueType = REG_MULTI_SZ;
  692. break;
  693. case NdisParameterBinary:
  694. ValueData = ParameterValue->ParameterData.BinaryData.Buffer;
  695. ValueLength = ParameterValue->ParameterData.BinaryData.Length;
  696. ValueType = REG_BINARY;
  697. break;
  698. default:
  699. *Status = NDIS_STATUS_NOT_SUPPORTED;
  700. break;
  701. }
  702. if (*Status != NDIS_STATUS_SUCCESS)
  703. break;
  704. if (Keyword->MaximumLength <= (Keyword->Length + sizeof(WCHAR)))
  705. {
  706. KeywordBuffer = (PWSTR)ALLOC_FROM_POOL(Keyword->Length + sizeof(WCHAR), NDIS_TAG_DEFAULT);
  707. if (KeywordBuffer == NULL)
  708. {
  709. *Status = NDIS_STATUS_RESOURCES;
  710. break;
  711. }
  712. CopyMemory(KeywordBuffer, Keyword->Buffer, Keyword->Length);
  713. FreeKwBuf = TRUE;
  714. }
  715. if (*(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) != (WCHAR)L'\0')
  716. {
  717. *(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) = (WCHAR)L'\0';
  718. }
  719. if ((Miniport = (PNDIS_MINIPORT_BLOCK)NdisConfigHandle->KeyQueryTable[3].QueryRoutine) != NULL)
  720. {
  721. //
  722. // Adapters
  723. //
  724. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  725. #if NDIS_TEST_REG_FAILURE
  726. RegistryStatus = STATUS_UNSUCCESSFUL;
  727. RootHandle = NULL;
  728. #else
  729. RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  730. PLUGPLAY_REGKEY_DRIVER,
  731. GENERIC_WRITE | MAXIMUM_ALLOWED,
  732. &RootHandle);
  733. #endif
  734. if (!NT_SUCCESS(RegistryStatus))
  735. {
  736. *Status = NDIS_STATUS_FAILURE;
  737. break;
  738. }
  739. RtlInitUnicodeString(&RelativePath, NdisConfigHandle->KeyQueryTable[3].Name);
  740. InitializeObjectAttributes(&ObjAttr,
  741. &RelativePath,
  742. OBJ_CASE_INSENSITIVE,
  743. RootHandle,
  744. NULL);
  745. RegistryStatus = ZwOpenKey(&Handle,
  746. GENERIC_READ | MAXIMUM_ALLOWED,
  747. &ObjAttr);
  748. if (NT_SUCCESS(RegistryStatus))
  749. {
  750. RegistryStatus = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE,
  751. Handle,
  752. KeywordBuffer,
  753. ValueType,
  754. ValueData,
  755. ValueLength);
  756. ZwClose (Handle);
  757. }
  758. ZwClose (RootHandle);
  759. }
  760. else
  761. {
  762. //
  763. // protocols
  764. //
  765. RegistryStatus = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
  766. NdisConfigHandle->KeyQueryTable[3].Name,
  767. KeywordBuffer,
  768. ValueType,
  769. ValueData,
  770. ValueLength);
  771. }
  772. if (!NT_SUCCESS(RegistryStatus))
  773. {
  774. *Status = NDIS_STATUS_FAILURE;
  775. }
  776. } while (FALSE);
  777. if (FreeKwBuf)
  778. {
  779. FREE_POOL(KeywordBuffer); // no longer needed
  780. }
  781. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  782. ("<==NdisWriteConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  783. }
  784. VOID
  785. NdisCloseConfiguration(
  786. IN NDIS_HANDLE ConfigurationHandle
  787. )
  788. /*++
  789. Routine Description:
  790. This routine is used to close a configuration database opened by
  791. NdisOpenConfiguration.
  792. Arguments:
  793. ConfigurationHandle - Handle returned by NdisOpenConfiguration.
  794. Return Value:
  795. None.
  796. --*/
  797. {
  798. //
  799. // Obtain the actual configuration handle structure
  800. //
  801. PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
  802. PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode;
  803. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  804. ("==>NdisCloseConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  805. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  806. //
  807. // deallocate the parameter nodes
  808. //
  809. ParameterNode = NdisConfigHandle->ParameterList;
  810. while (ParameterNode != NULL)
  811. {
  812. NdisConfigHandle->ParameterList = ParameterNode->Next;
  813. FREE_POOL(ParameterNode);
  814. ParameterNode = NdisConfigHandle->ParameterList;
  815. }
  816. FREE_POOL(ConfigurationHandle);
  817. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  818. ("<==NdisCloseConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  819. }
  820. VOID
  821. NdisReadNetworkAddress(
  822. OUT PNDIS_STATUS Status,
  823. OUT PVOID * NetworkAddress,
  824. OUT PUINT NetworkAddressLength,
  825. IN NDIS_HANDLE ConfigurationHandle
  826. )
  827. /*++
  828. Routine Description:
  829. This routine is used to read the "NetworkAddress" parameter
  830. from the configuration database. It reads the value as a
  831. string separated by hyphens, then converts it to a binary
  832. array and stores the result.
  833. Arguments:
  834. Status - Returns the status of the request.
  835. NetworkAddress - Returns a pointer to the address.
  836. NetworkAddressLength - Returns the length of the address.
  837. ConfigurationHandle - Handle returned by NdisOpenConfiguration. Points
  838. to the parameter subkey.
  839. Return Value:
  840. None.
  841. --*/
  842. {
  843. NDIS_STRING NetAddrStr = NDIS_STRING_CONST("NetworkAddress");
  844. PNDIS_CONFIGURATION_PARAMETER ParameterValue;
  845. NTSTATUS NtStatus;
  846. UCHAR ConvertArray[3];
  847. PWSTR CurrentReadLoc;
  848. PWSTR AddressEnd;
  849. PUCHAR CurrentWriteLoc;
  850. UINT TotalBytesRead;
  851. ULONG TempUlong;
  852. ULONG AddressLength;
  853. PNDIS_MINIPORT_BLOCK Miniport;
  854. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  855. ("==>NdisReadNetworkAddress: ConfigurationHandle %p\n", ConfigurationHandle));
  856. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  857. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle)->KeyQueryTable[3].QueryRoutine;
  858. ASSERT(Miniport != NULL);
  859. ASSERT(Miniport->Signature == (PVOID)MINIPORT_DEVICE_MAGIC_VALUE);
  860. if (Miniport->Signature == (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
  861. {
  862. Miniport->MacOptions |= NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE;
  863. Miniport->InfoFlags |= NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE;
  864. }
  865. do
  866. {
  867. //
  868. // First read the "NetworkAddress" from the registry
  869. //
  870. NdisReadConfiguration(Status, &ParameterValue, ConfigurationHandle, &NetAddrStr, NdisParameterString);
  871. if ((*Status != NDIS_STATUS_SUCCESS) ||
  872. (ParameterValue->ParameterType != NdisParameterString))
  873. {
  874. *Status = NDIS_STATUS_FAILURE;
  875. break;
  876. }
  877. //
  878. // If there is not an address specified then exit now.
  879. //
  880. if (0 == ParameterValue->ParameterData.StringData.Length)
  881. {
  882. *Status = NDIS_STATUS_FAILURE;
  883. break;
  884. }
  885. //
  886. // Now convert the address to binary (we do this
  887. // in-place, since this allows us to use the memory
  888. // already allocated which is automatically freed
  889. // by NdisCloseConfiguration).
  890. //
  891. ConvertArray[2] = '\0';
  892. CurrentReadLoc = (PWSTR)ParameterValue->ParameterData.StringData.Buffer;
  893. CurrentWriteLoc = (PUCHAR)CurrentReadLoc;
  894. TotalBytesRead = ParameterValue->ParameterData.StringData.Length;
  895. AddressEnd = CurrentReadLoc + (TotalBytesRead / sizeof(WCHAR));
  896. AddressLength = 0;
  897. while ((CurrentReadLoc+2) <= AddressEnd)
  898. {
  899. //
  900. // Copy the current two-character value into ConvertArray
  901. //
  902. ConvertArray[0] = (UCHAR)(*(CurrentReadLoc++));
  903. ConvertArray[1] = (UCHAR)(*(CurrentReadLoc++));
  904. //
  905. // Convert it to a Ulong and update
  906. //
  907. NtStatus = RtlCharToInteger(ConvertArray, 16, &TempUlong);
  908. if (!NT_SUCCESS(NtStatus))
  909. {
  910. *Status = NDIS_STATUS_FAILURE;
  911. break;
  912. }
  913. *(CurrentWriteLoc++) = (UCHAR)TempUlong;
  914. ++AddressLength;
  915. //
  916. // If the next character is a hyphen, skip it.
  917. //
  918. if (CurrentReadLoc < AddressEnd)
  919. {
  920. if (*CurrentReadLoc == (WCHAR)L'-')
  921. {
  922. ++CurrentReadLoc;
  923. }
  924. }
  925. }
  926. if (NtStatus != NDIS_STATUS_SUCCESS)
  927. break;
  928. *Status = NDIS_STATUS_SUCCESS;
  929. *NetworkAddress = ParameterValue->ParameterData.StringData.Buffer;
  930. *NetworkAddressLength = AddressLength;
  931. if (AddressLength == 0)
  932. {
  933. *Status = NDIS_STATUS_FAILURE;
  934. }
  935. } while (FALSE);
  936. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  937. ("<==NdisReadNetworkAddress: ConfigurationHandle %p\n", ConfigurationHandle));
  938. }
  939. VOID
  940. NdisConvertStringToAtmAddress(
  941. OUT PNDIS_STATUS Status,
  942. IN PNDIS_STRING String,
  943. OUT PATM_ADDRESS AtmAddress
  944. )
  945. /*++
  946. Routine Description:
  947. Arguments:
  948. Status - Returns the status of the request.
  949. String - String representation of the atm address.
  950. * Format defined in Section 5.4,
  951. * "Example Master File Format" in ATM95-1532R4 ATM Name System:
  952. *
  953. * AESA format: a string of hexadecimal digits, with '.' characters for punctuation, e.g.
  954. *
  955. * 39.246f.00.0e7c9c.0312.0001.0001.000012345678.00
  956. *
  957. * E164 format: A '+' character followed by a string of
  958. * decimal digits, with '.' chars for punctuation, e.g.:
  959. *
  960. * +358.400.1234567
  961. AtmAddress - The converted Atm address is returned here.
  962. Return Value:
  963. None.
  964. --*/
  965. {
  966. USHORT i, j, NumDigits;
  967. PWSTR p, q;
  968. UNICODE_STRING Us;
  969. ANSI_STRING As;
  970. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  971. ("==>NdisConvertStringToAtmAddress\n"));
  972. //
  973. // Start off by stripping the punctuation characters from the string. We do this in place.
  974. //
  975. for (i = NumDigits = 0, j = String->Length/sizeof(WCHAR), p = q = String->Buffer;
  976. (i < j) && (*p != 0);
  977. i++, p++)
  978. {
  979. if ((*p == ATM_ADDR_BLANK_CHAR) ||
  980. (*p == ATM_ADDR_PUNCTUATION_CHAR))
  981. {
  982. continue;
  983. }
  984. *q++ = *p;
  985. NumDigits ++;
  986. }
  987. //
  988. // Look at the first character to determine if the address is E.164 or NSAP.
  989. // If the address isn't long enough, we assume that it is native E.164.
  990. //
  991. p = String->Buffer;
  992. if ((*p == ATM_ADDR_E164_START_CHAR) || (NumDigits <= 15))
  993. {
  994. if (*p == ATM_ADDR_E164_START_CHAR)
  995. {
  996. p ++;
  997. NumDigits --;
  998. }
  999. if ((NumDigits == 0) || (NumDigits > ATM_ADDRESS_LENGTH))
  1000. {
  1001. *Status = NDIS_STATUS_INVALID_LENGTH;
  1002. return;
  1003. }
  1004. AtmAddress->AddressType = ATM_E164;
  1005. AtmAddress->NumberOfDigits = NumDigits;
  1006. }
  1007. else
  1008. {
  1009. if (NumDigits != 2*ATM_ADDRESS_LENGTH)
  1010. {
  1011. *Status = NDIS_STATUS_INVALID_LENGTH;
  1012. return;
  1013. }
  1014. AtmAddress->AddressType = ATM_NSAP;
  1015. AtmAddress->NumberOfDigits = NumDigits/sizeof(WCHAR);
  1016. }
  1017. //
  1018. // Convert the address to Ansi now
  1019. //
  1020. Us.Buffer = p;
  1021. Us.Length = Us.MaximumLength = NumDigits*sizeof(WCHAR);
  1022. As.Buffer = ALLOC_FROM_POOL(NumDigits + 1, NDIS_TAG_CO);
  1023. As.Length = 0;
  1024. As.MaximumLength = NumDigits + 1;
  1025. if (As.Buffer == NULL)
  1026. {
  1027. *Status = NDIS_STATUS_RESOURCES;
  1028. return;
  1029. }
  1030. *Status = NdisUnicodeStringToAnsiString(&As, &Us);
  1031. if (!NT_SUCCESS(*Status))
  1032. {
  1033. FREE_POOL(As.Buffer);
  1034. *Status = NDIS_STATUS_FAILURE;
  1035. return;
  1036. }
  1037. //
  1038. // Now get the bytes into the destination ATM Address structure.
  1039. //
  1040. if (AtmAddress->AddressType == ATM_E164)
  1041. {
  1042. //
  1043. // We just need to copy in the digits in ANSI form.
  1044. //
  1045. NdisMoveMemory(AtmAddress->Address, As.Buffer, NumDigits);
  1046. }
  1047. else
  1048. {
  1049. //
  1050. // This is in NSAP form. We need to pack the hex digits.
  1051. //
  1052. UCHAR xxString[3];
  1053. ULONG val;
  1054. xxString[2] = 0;
  1055. for (i = 0; i < ATM_ADDRESS_LENGTH; i++)
  1056. {
  1057. xxString[0] = As.Buffer[i*2];
  1058. xxString[1] = As.Buffer[i*2+1];
  1059. *Status = CHAR_TO_INT(xxString, 16, &val);
  1060. if (!NT_SUCCESS(*Status))
  1061. {
  1062. FREE_POOL(As.Buffer);
  1063. *Status = NDIS_STATUS_FAILURE;
  1064. return;
  1065. }
  1066. AtmAddress->Address[i] = (UCHAR)val;
  1067. }
  1068. }
  1069. FREE_POOL(As.Buffer);
  1070. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  1071. ("<==NdisConvertStringToAtmAddress\n"));
  1072. *Status = NDIS_STATUS_SUCCESS;
  1073. }
  1074. NTSTATUS
  1075. ndisSaveParameters(
  1076. IN PWSTR ValueName,
  1077. IN ULONG ValueType,
  1078. IN PVOID ValueData,
  1079. IN ULONG ValueLength,
  1080. IN PVOID Context,
  1081. IN PVOID EntryContext
  1082. )
  1083. /*++
  1084. Routine Description:
  1085. This routine is a callback routine for RtlQueryRegistryValues
  1086. It is called with the value for a specified parameter. It allocates
  1087. memory to hold the data and copies it over.
  1088. Arguments:
  1089. ValueName - The name of the value (ignored).
  1090. ValueType - The type of the value.
  1091. ValueData - The null-terminated data for the value.
  1092. ValueLength - The length of ValueData.
  1093. Context - Points to the head of the parameter chain.
  1094. EntryContext - A pointer to
  1095. Return Value:
  1096. STATUS_SUCCESS
  1097. --*/
  1098. {
  1099. NDIS_STATUS Status;
  1100. //
  1101. // Obtain the actual configuration handle structure
  1102. //
  1103. PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)Context;
  1104. //
  1105. // Where the user wants a pointer returned to the data.
  1106. //
  1107. PNDIS_CONFIGURATION_PARAMETER *ParameterValue = (PNDIS_CONFIGURATION_PARAMETER *)EntryContext;
  1108. //
  1109. // Use this to link parameters allocated to this open
  1110. //
  1111. PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode;
  1112. //
  1113. // Size of memory to allocate for parameter node
  1114. //
  1115. UINT Size;
  1116. //
  1117. // Allocate our parameter node
  1118. //
  1119. Size = sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE);
  1120. if ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ) || (ValueType == REG_BINARY))
  1121. {
  1122. Size += ValueLength;
  1123. }
  1124. ParameterNode = ALLOC_FROM_POOL(Size, NDIS_TAG_PARAMETER_NODE);
  1125. Status = (ParameterNode != NULL) ? NDIS_STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
  1126. if (Status != NDIS_STATUS_SUCCESS)
  1127. {
  1128. return (NTSTATUS)Status;
  1129. }
  1130. *ParameterValue = &ParameterNode->Parameter;
  1131. //
  1132. // Map registry datatypes to ndis data types
  1133. //
  1134. if (ValueType == REG_DWORD)
  1135. {
  1136. //
  1137. // The registry says that the data is in a dword boundary.
  1138. //
  1139. (*ParameterValue)->ParameterType = NdisParameterInteger;
  1140. (*ParameterValue)->ParameterData.IntegerData = *((PULONG) ValueData);
  1141. }
  1142. else if ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ))
  1143. {
  1144. (*ParameterValue)->ParameterType =
  1145. (ValueType == REG_SZ) ? NdisParameterString : NdisParameterMultiString;
  1146. (*ParameterValue)->ParameterData.StringData.Buffer = (PWSTR)((PUCHAR)ParameterNode + sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE));
  1147. CopyMemory((*ParameterValue)->ParameterData.StringData.Buffer,
  1148. ValueData,
  1149. ValueLength);
  1150. (*ParameterValue)->ParameterData.StringData.Length = (USHORT)ValueLength;
  1151. (*ParameterValue)->ParameterData.StringData.MaximumLength = (USHORT)ValueLength;
  1152. //
  1153. // Special fix; if a string ends in a NULL and that is included
  1154. // in the length, remove it.
  1155. //
  1156. if (ValueType == REG_SZ)
  1157. {
  1158. if ((((PUCHAR)ValueData)[ValueLength-1] == 0) &&
  1159. (((PUCHAR)ValueData)[ValueLength-2] == 0))
  1160. {
  1161. (*ParameterValue)->ParameterData.StringData.Length -= 2;
  1162. }
  1163. }
  1164. }
  1165. else if (ValueType == REG_BINARY)
  1166. {
  1167. (*ParameterValue)->ParameterType = NdisParameterBinary;
  1168. (*ParameterValue)->ParameterData.BinaryData.Buffer = ValueData;
  1169. (*ParameterValue)->ParameterData.BinaryData.Length = (USHORT)ValueLength;
  1170. (*ParameterValue)->ParameterData.BinaryData.Buffer = (PWSTR)((PUCHAR)ParameterNode + sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE));
  1171. CopyMemory((*ParameterValue)->ParameterData.BinaryData.Buffer,
  1172. ValueData,
  1173. ValueLength);
  1174. }
  1175. else
  1176. {
  1177. FREE_POOL(ParameterNode);
  1178. return STATUS_OBJECT_NAME_NOT_FOUND;
  1179. }
  1180. //
  1181. // Queue this parameter node
  1182. //
  1183. ParameterNode->Next = NdisConfigHandle->ParameterList;
  1184. NdisConfigHandle->ParameterList = ParameterNode;
  1185. return STATUS_SUCCESS;
  1186. }
  1187. NTSTATUS
  1188. ndisReadParameter(
  1189. IN PWSTR ValueName,
  1190. IN ULONG ValueType,
  1191. IN PVOID ValueData,
  1192. IN ULONG ValueLength,
  1193. IN PVOID Context,
  1194. IN PVOID EntryContext
  1195. )
  1196. /*++
  1197. Routine Description:
  1198. This routine is a callback routine for RtlQueryRegistryValues
  1199. It is called with the values for the "Bind" and "Export" multi-strings
  1200. for a given driver. It allocates memory to hold the data and copies
  1201. it over.
  1202. Arguments:
  1203. ValueName - The name of the value ("Bind" or "Export" -- ignored).
  1204. ValueType - The type of the value (REG_MULTI_SZ -- ignored).
  1205. ValueData - The null-terminated data for the value.
  1206. ValueLength - The length of ValueData.
  1207. Context - Unused.
  1208. EntryContext - A pointer to the pointer that holds the copied data.
  1209. Return Value:
  1210. STATUS_SUCCESS
  1211. --*/
  1212. {
  1213. PUCHAR * Data = ((PUCHAR *)EntryContext);
  1214. UNREFERENCED_PARAMETER(ValueName);
  1215. //
  1216. // Allocate one DWORD more and zero is out
  1217. //
  1218. *Data = ALLOC_FROM_POOL(ValueLength + sizeof(ULONG), NDIS_TAG_REG_READ_DATA_BUFFER);
  1219. if (*Data == NULL)
  1220. {
  1221. return STATUS_INSUFFICIENT_RESOURCES;
  1222. }
  1223. ZeroMemory(*Data, ValueLength + sizeof(ULONG));
  1224. CopyMemory(*Data, ValueData, ValueLength);
  1225. if (Context)
  1226. {
  1227. *((PULONG)Context) = ValueType;
  1228. }
  1229. return STATUS_SUCCESS;
  1230. }