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.

1549 lines
49 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 | OBJ_KERNEL_HANDLE,
  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 = NULL;
  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. PCM_PARTIAL_RESOURCE_LIST pResourceList;
  358. UINT j;
  359. ULONG ValueData;
  360. #define PQueryTable ConfigHandle->KeyQueryTable
  361. //
  362. // There are some built-in parameters which can always be
  363. // read, even if not present in the registry. This is the
  364. // number of them.
  365. //
  366. #define BUILT_IN_COUNT 3
  367. static NDIS_STRING BuiltInStrings[BUILT_IN_COUNT] =
  368. {
  369. NDIS_STRING_CONST ("Environment"),
  370. NDIS_STRING_CONST ("ProcessorType"),
  371. NDIS_STRING_CONST ("NdisVersion")
  372. };
  373. static NDIS_STRING MiniportNameStr = NDIS_STRING_CONST ("MiniportName");
  374. #define STANDARD_RESOURCE_COUNT 9
  375. //
  376. // The names of the standard resource types.
  377. //
  378. static NDIS_STRING StandardResourceStrings[STANDARD_RESOURCE_COUNT] =
  379. {
  380. NDIS_STRING_CONST ("IoBaseAddress"),
  381. NDIS_STRING_CONST ("InterruptNumber"),
  382. NDIS_STRING_CONST ("MemoryMappedBaseAddress"),
  383. NDIS_STRING_CONST ("DmaChannel"),
  384. //
  385. // a few drivers use non-standard keywords, so take care of them for now
  386. //
  387. NDIS_STRING_CONST ("IoAddress"),
  388. NDIS_STRING_CONST ("Interrupt"),
  389. NDIS_STRING_CONST ("IOBase"),
  390. NDIS_STRING_CONST ("Irq"),
  391. NDIS_STRING_CONST ("RamAddress")
  392. };
  393. UCHAR StandardResourceTypes[STANDARD_RESOURCE_COUNT]=
  394. {
  395. CmResourceTypePort,
  396. CmResourceTypeInterrupt,
  397. CmResourceTypeMemory,
  398. CmResourceTypeDma,
  399. CmResourceTypePort,
  400. CmResourceTypeInterrupt,
  401. CmResourceTypePort,
  402. CmResourceTypeInterrupt,
  403. CmResourceTypeMemory
  404. };
  405. static NDIS_CONFIGURATION_PARAMETER BuiltInParameters[BUILT_IN_COUNT] =
  406. { { NdisParameterInteger, NdisEnvironmentWindowsNt },
  407. { NdisParameterInteger,
  408. #if defined(_M_IX86)
  409. NdisProcessorX86
  410. #elif defined(_M_MRX000)
  411. NdisProcessorMips
  412. #elif defined(_ALPHA_)
  413. NdisProcessorAlpha
  414. #else
  415. NdisProcessorPpc
  416. #endif
  417. },
  418. { NdisParameterInteger, ((NDIS_MAJOR_VERSION << 16) | NDIS_MINOR_VERSION)}
  419. };
  420. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  421. ("==>NdisReadConfiguration\n"));
  422. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  423. (" Keyword: "));
  424. DBGPRINT_UNICODE(DBG_COMP_REG, DBG_LEVEL_INFO,
  425. Keyword);
  426. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  427. ("\n"));
  428. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  429. do
  430. {
  431. KeywordBuffer = Keyword->Buffer;
  432. //
  433. // assume failure
  434. //
  435. RegistryStatus = STATUS_UNSUCCESSFUL;
  436. //
  437. // First check if this is one of the built-in parameters.
  438. //
  439. for (i = 0; i < BUILT_IN_COUNT; i++)
  440. {
  441. if (RtlEqualUnicodeString(Keyword, &BuiltInStrings[i], TRUE))
  442. {
  443. RegistryStatus = STATUS_SUCCESS;
  444. *ParameterValue = &BuiltInParameters[i];
  445. break;
  446. }
  447. }
  448. if (NT_SUCCESS(RegistryStatus))
  449. break;
  450. if ((Miniport = (PNDIS_MINIPORT_BLOCK)PQueryTable[3].QueryRoutine) != NULL)
  451. {
  452. //
  453. // check to see if driver is asking for miniport name
  454. //
  455. if (RtlEqualUnicodeString(Keyword, &MiniportNameStr, TRUE))
  456. {
  457. RegistryStatus = ndisSaveParameters(MiniportNameStr.Buffer,
  458. REG_SZ,
  459. (PVOID)Miniport->MiniportName.Buffer,
  460. Miniport->MiniportName.Length,
  461. (PVOID)ConfigHandle,
  462. (PVOID)ParameterValue);
  463. break;
  464. }
  465. //
  466. // check to see if this is a resource keyword
  467. //
  468. for (i = 0; i < STANDARD_RESOURCE_COUNT; i++)
  469. {
  470. if (RtlEqualUnicodeString(Keyword, &StandardResourceStrings[i], TRUE))
  471. break;
  472. }
  473. if (i < STANDARD_RESOURCE_COUNT)
  474. {
  475. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_2,
  476. ("NdisReadConfiguration: Miniport %p should use NdisMQueryAdapterResources to get the standard resources.\n", Miniport));
  477. do
  478. {
  479. if (Miniport->AllocatedResources == NULL)
  480. break;
  481. pResourceList = &(Miniport->AllocatedResources->List[0].PartialResourceList);
  482. //
  483. // walk through resource list and find the first one that matches
  484. //
  485. for (j = 0; j < pResourceList->Count; j++)
  486. {
  487. if (pResourceList->PartialDescriptors[j].Type == StandardResourceTypes[i])
  488. {
  489. //
  490. // could have used pResourceList->PartialDescriptors[j].Generic.Start.LowPart for all
  491. // cases, but in the future, memory value can be 64 bit
  492. //
  493. switch (StandardResourceTypes[i])
  494. {
  495. case CmResourceTypePort:
  496. ValueData = pResourceList->PartialDescriptors[j].u.Port.Start.LowPart;
  497. break;
  498. case CmResourceTypeInterrupt:
  499. ValueData = pResourceList->PartialDescriptors[j].u.Interrupt.Level;
  500. break;
  501. case CmResourceTypeMemory:
  502. ValueData = pResourceList->PartialDescriptors[j].u.Memory.Start.LowPart;
  503. break;
  504. case CmResourceTypeDma:
  505. ValueData = pResourceList->PartialDescriptors[j].u.Dma.Channel;
  506. break;
  507. default:
  508. ASSERT(FALSE);
  509. }
  510. //
  511. // call SaveParameter ourselves
  512. //
  513. RegistryStatus = ndisSaveParameters(StandardResourceStrings[i].Buffer,
  514. REG_DWORD,
  515. (PVOID)&ValueData,
  516. sizeof(ULONG),
  517. (PVOID)ConfigHandle,
  518. (PVOID)ParameterValue);
  519. break;
  520. }
  521. }
  522. if (j >= pResourceList->Count)
  523. {
  524. RegistryStatus = STATUS_UNSUCCESSFUL;
  525. }
  526. } while (FALSE);
  527. //
  528. // if keyword was a standard resource keyword, we should break here
  529. // no matter what the outcome of finding the resource in resource list
  530. //
  531. break;
  532. } // end of if it was a resource keyword
  533. } // end of if NdisReadConfiguration called for a miniport
  534. //
  535. // the keyword was not a standard resource or built-in keyword
  536. // get back to our regular programming...
  537. //
  538. //
  539. // Allocate room for a null-terminated version of the keyword
  540. //
  541. KeywordBuffer = (PWSTR)ALLOC_FROM_POOL(Keyword->Length + sizeof(WCHAR), NDIS_TAG_DEFAULT);
  542. if (KeywordBuffer == NULL)
  543. {
  544. RegistryStatus = STATUS_UNSUCCESSFUL;;
  545. break;
  546. }
  547. CopyMemory(KeywordBuffer, Keyword->Buffer, Keyword->Length);
  548. *(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) = (WCHAR)L'\0';
  549. PQueryTable[1].Name = KeywordBuffer;
  550. PQueryTable[1].EntryContext = ParameterValue;
  551. if (Miniport != NULL)
  552. {
  553. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  554. //
  555. // set the subkey
  556. //
  557. PQueryTable[0].Name = PQueryTable[3].Name;
  558. #if NDIS_TEST_REG_FAILURE
  559. RegistryStatus = STATUS_UNSUCCESSFUL;
  560. #else
  561. RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  562. PLUGPLAY_REGKEY_DRIVER,
  563. GENERIC_READ | MAXIMUM_ALLOWED,
  564. &Handle);
  565. #endif
  566. if(NT_SUCCESS(RegistryStatus))
  567. {
  568. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  569. Handle,
  570. PQueryTable,
  571. ConfigHandle, // context
  572. NULL);
  573. }
  574. }
  575. else
  576. {
  577. //
  578. // protocols
  579. //
  580. RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
  581. PQueryTable[3].Name,
  582. PQueryTable,
  583. ConfigHandle, // context
  584. NULL);
  585. }
  586. if (NT_SUCCESS(RegistryStatus))
  587. {
  588. //
  589. // if a value is stored in registry as string but the driver is trying
  590. // to read it as Integer or HexInteger, do the conversion here
  591. //
  592. if ((*ParameterValue)->ParameterType == NdisParameterString)
  593. {
  594. if (ParameterType == NdisParameterInteger)
  595. {
  596. RtlUnicodeStringToInteger(&(*ParameterValue)->ParameterData.StringData,
  597. 10, (PULONG)(&(*ParameterValue)->ParameterData.IntegerData));
  598. (*ParameterValue)->ParameterType = NdisParameterInteger;
  599. }
  600. else if (ParameterType == NdisParameterHexInteger)
  601. {
  602. RtlUnicodeStringToInteger(&(*ParameterValue)->ParameterData.StringData,
  603. 16, (PULONG)(&(*ParameterValue)->ParameterData.IntegerData));
  604. (*ParameterValue)->ParameterType = NdisParameterHexInteger;
  605. }
  606. }
  607. }
  608. } while (FALSE);
  609. if (KeywordBuffer && (KeywordBuffer != Keyword->Buffer))
  610. {
  611. FREE_POOL(KeywordBuffer); // no longer needed
  612. }
  613. if (!NT_SUCCESS(RegistryStatus))
  614. {
  615. *Status = NDIS_STATUS_FAILURE;
  616. }
  617. else
  618. {
  619. *Status = NDIS_STATUS_SUCCESS;
  620. }
  621. if (Handle)
  622. ZwClose(Handle);
  623. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  624. ("<==NdisReadConfiguration\n"));
  625. #undef PQueryTable
  626. }
  627. VOID
  628. NdisWriteConfiguration(
  629. OUT PNDIS_STATUS Status,
  630. IN NDIS_HANDLE ConfigurationHandle,
  631. IN PNDIS_STRING Keyword,
  632. PNDIS_CONFIGURATION_PARAMETER ParameterValue
  633. )
  634. /*++
  635. Routine Description:
  636. This routine is used to write a parameter to the configuration database.
  637. Arguments:
  638. Status - Returns the status of the request.
  639. ConfigurationHandle - Handle passed to the driver
  640. Keyword - The keyword to set.
  641. ParameterValue - Specifies the new value for this keyword.
  642. Return Value:
  643. None.
  644. --*/
  645. {
  646. PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
  647. NTSTATUS RegistryStatus;
  648. PNDIS_MINIPORT_BLOCK Miniport;
  649. PWSTR KeywordBuffer;
  650. BOOLEAN FreeKwBuf = FALSE;
  651. PVOID ValueData = NULL;
  652. ULONG ValueLength = 0;
  653. ULONG ValueType = REG_DWORD;
  654. PDEVICE_OBJECT PhysicalDeviceObject;
  655. HANDLE Handle, RootHandle;
  656. OBJECT_ATTRIBUTES ObjAttr;
  657. UNICODE_STRING RelativePath;
  658. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  659. ("==>NdisWriteConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  660. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  661. *Status = NDIS_STATUS_SUCCESS;
  662. KeywordBuffer = Keyword->Buffer;
  663. do
  664. {
  665. //
  666. // Get the value data.
  667. //
  668. switch (ParameterValue->ParameterType)
  669. {
  670. case NdisParameterHexInteger:
  671. case NdisParameterInteger:
  672. ValueData = &ParameterValue->ParameterData.IntegerData;
  673. ValueLength = sizeof(ParameterValue->ParameterData.IntegerData);
  674. ValueType = REG_DWORD;
  675. break;
  676. case NdisParameterString:
  677. ValueData = ParameterValue->ParameterData.StringData.Buffer;
  678. ValueLength = ParameterValue->ParameterData.StringData.Length;
  679. ValueType = REG_SZ;
  680. break;
  681. case NdisParameterMultiString:
  682. ValueData = ParameterValue->ParameterData.StringData.Buffer;
  683. ValueLength = ParameterValue->ParameterData.StringData.Length;
  684. ValueType = REG_MULTI_SZ;
  685. break;
  686. case NdisParameterBinary:
  687. ValueData = ParameterValue->ParameterData.BinaryData.Buffer;
  688. ValueLength = ParameterValue->ParameterData.BinaryData.Length;
  689. ValueType = REG_BINARY;
  690. break;
  691. default:
  692. *Status = NDIS_STATUS_NOT_SUPPORTED;
  693. break;
  694. }
  695. if (*Status != NDIS_STATUS_SUCCESS)
  696. break;
  697. if (Keyword->MaximumLength <= (Keyword->Length + sizeof(WCHAR)))
  698. {
  699. KeywordBuffer = (PWSTR)ALLOC_FROM_POOL(Keyword->Length + sizeof(WCHAR), NDIS_TAG_DEFAULT);
  700. if (KeywordBuffer == NULL)
  701. {
  702. *Status = NDIS_STATUS_RESOURCES;
  703. break;
  704. }
  705. CopyMemory(KeywordBuffer, Keyword->Buffer, Keyword->Length);
  706. FreeKwBuf = TRUE;
  707. }
  708. *(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) = (WCHAR)L'\0';
  709. if ((Miniport = (PNDIS_MINIPORT_BLOCK)NdisConfigHandle->KeyQueryTable[3].QueryRoutine) != NULL)
  710. {
  711. //
  712. // Adapters
  713. //
  714. PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
  715. #if NDIS_TEST_REG_FAILURE
  716. RegistryStatus = STATUS_UNSUCCESSFUL;
  717. RootHandle = NULL;
  718. #else
  719. RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  720. PLUGPLAY_REGKEY_DRIVER,
  721. GENERIC_WRITE | MAXIMUM_ALLOWED,
  722. &RootHandle);
  723. #endif
  724. if (!NT_SUCCESS(RegistryStatus))
  725. {
  726. *Status = NDIS_STATUS_FAILURE;
  727. break;
  728. }
  729. RtlInitUnicodeString(&RelativePath, NdisConfigHandle->KeyQueryTable[3].Name);
  730. InitializeObjectAttributes(&ObjAttr,
  731. &RelativePath,
  732. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  733. RootHandle,
  734. NULL);
  735. RegistryStatus = ZwOpenKey(&Handle,
  736. GENERIC_READ | MAXIMUM_ALLOWED,
  737. &ObjAttr);
  738. if (NT_SUCCESS(RegistryStatus))
  739. {
  740. RegistryStatus = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE,
  741. Handle,
  742. KeywordBuffer,
  743. ValueType,
  744. ValueData,
  745. ValueLength);
  746. ZwClose (Handle);
  747. }
  748. ZwClose (RootHandle);
  749. }
  750. else
  751. {
  752. //
  753. // protocols
  754. //
  755. RegistryStatus = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
  756. NdisConfigHandle->KeyQueryTable[3].Name,
  757. KeywordBuffer,
  758. ValueType,
  759. ValueData,
  760. ValueLength);
  761. }
  762. if (!NT_SUCCESS(RegistryStatus))
  763. {
  764. *Status = NDIS_STATUS_FAILURE;
  765. }
  766. } while (FALSE);
  767. if (FreeKwBuf)
  768. {
  769. FREE_POOL(KeywordBuffer); // no longer needed
  770. }
  771. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  772. ("<==NdisWriteConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  773. }
  774. VOID
  775. NdisCloseConfiguration(
  776. IN NDIS_HANDLE ConfigurationHandle
  777. )
  778. /*++
  779. Routine Description:
  780. This routine is used to close a configuration database opened by
  781. NdisOpenConfiguration.
  782. Arguments:
  783. ConfigurationHandle - Handle returned by NdisOpenConfiguration.
  784. Return Value:
  785. None.
  786. --*/
  787. {
  788. //
  789. // Obtain the actual configuration handle structure
  790. //
  791. PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
  792. PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode;
  793. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  794. ("==>NdisCloseConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  795. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  796. //
  797. // deallocate the parameter nodes
  798. //
  799. ParameterNode = NdisConfigHandle->ParameterList;
  800. while (ParameterNode != NULL)
  801. {
  802. NdisConfigHandle->ParameterList = ParameterNode->Next;
  803. FREE_POOL(ParameterNode);
  804. ParameterNode = NdisConfigHandle->ParameterList;
  805. }
  806. FREE_POOL(ConfigurationHandle);
  807. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  808. ("<==NdisCloseConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
  809. }
  810. VOID
  811. NdisReadNetworkAddress(
  812. OUT PNDIS_STATUS Status,
  813. OUT PVOID * NetworkAddress,
  814. OUT PUINT NetworkAddressLength,
  815. IN NDIS_HANDLE ConfigurationHandle
  816. )
  817. /*++
  818. Routine Description:
  819. This routine is used to read the "NetworkAddress" parameter
  820. from the configuration database. It reads the value as a
  821. string separated by hyphens, then converts it to a binary
  822. array and stores the result.
  823. Arguments:
  824. Status - Returns the status of the request.
  825. NetworkAddress - Returns a pointer to the address.
  826. NetworkAddressLength - Returns the length of the address.
  827. ConfigurationHandle - Handle returned by NdisOpenConfiguration. Points
  828. to the parameter subkey.
  829. Return Value:
  830. None.
  831. --*/
  832. {
  833. NDIS_STRING NetAddrStr = NDIS_STRING_CONST("NetworkAddress");
  834. PNDIS_CONFIGURATION_PARAMETER ParameterValue;
  835. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  836. UCHAR ConvertArray[3];
  837. PWSTR CurrentReadLoc;
  838. PWSTR AddressEnd;
  839. PUCHAR CurrentWriteLoc;
  840. UINT TotalBytesRead;
  841. ULONG TempUlong;
  842. ULONG AddressLength;
  843. PNDIS_MINIPORT_BLOCK Miniport;
  844. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  845. ("==>NdisReadNetworkAddress: ConfigurationHandle %p\n", ConfigurationHandle));
  846. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  847. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle)->KeyQueryTable[3].QueryRoutine;
  848. ASSERT(Miniport != NULL);
  849. ASSERT(Miniport->Signature == (PVOID)MINIPORT_DEVICE_MAGIC_VALUE);
  850. if (Miniport->Signature == (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
  851. {
  852. Miniport->MacOptions |= NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE;
  853. Miniport->InfoFlags |= NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE;
  854. }
  855. do
  856. {
  857. //
  858. // First read the "NetworkAddress" from the registry
  859. //
  860. NdisReadConfiguration(Status, &ParameterValue, ConfigurationHandle, &NetAddrStr, NdisParameterString);
  861. if ((*Status != NDIS_STATUS_SUCCESS) ||
  862. (ParameterValue->ParameterType != NdisParameterString))
  863. {
  864. *Status = NDIS_STATUS_FAILURE;
  865. break;
  866. }
  867. //
  868. // If there is not an address specified then exit now.
  869. //
  870. if (0 == ParameterValue->ParameterData.StringData.Length)
  871. {
  872. *Status = NDIS_STATUS_FAILURE;
  873. break;
  874. }
  875. //
  876. // Now convert the address to binary (we do this
  877. // in-place, since this allows us to use the memory
  878. // already allocated which is automatically freed
  879. // by NdisCloseConfiguration).
  880. //
  881. ConvertArray[2] = '\0';
  882. CurrentReadLoc = (PWSTR)ParameterValue->ParameterData.StringData.Buffer;
  883. CurrentWriteLoc = (PUCHAR)CurrentReadLoc;
  884. TotalBytesRead = ParameterValue->ParameterData.StringData.Length;
  885. AddressEnd = CurrentReadLoc + (TotalBytesRead / sizeof(WCHAR));
  886. AddressLength = 0;
  887. //1 is address string a multiple of 2 and if not, what are the implications?
  888. while ((CurrentReadLoc+2) <= AddressEnd)
  889. {
  890. //
  891. // Copy the current two-character value into ConvertArray
  892. //
  893. ConvertArray[0] = (UCHAR)(*(CurrentReadLoc++));
  894. ConvertArray[1] = (UCHAR)(*(CurrentReadLoc++));
  895. //
  896. // Convert it to a Ulong and update
  897. //
  898. NtStatus = RtlCharToInteger((PCSZ)ConvertArray, 16, &TempUlong);
  899. if (!NT_SUCCESS(NtStatus))
  900. {
  901. *Status = NDIS_STATUS_FAILURE;
  902. break;
  903. }
  904. *(CurrentWriteLoc++) = (UCHAR)TempUlong;
  905. ++AddressLength;
  906. //
  907. // If the next character is a hyphen, skip it.
  908. //
  909. if (CurrentReadLoc < AddressEnd)
  910. {
  911. if (*CurrentReadLoc == (WCHAR)L'-')
  912. {
  913. ++CurrentReadLoc;
  914. }
  915. }
  916. }
  917. if (!NT_SUCCESS(NtStatus))
  918. break;
  919. *Status = NDIS_STATUS_SUCCESS;
  920. *NetworkAddress = ParameterValue->ParameterData.StringData.Buffer;
  921. *NetworkAddressLength = AddressLength;
  922. if (AddressLength == 0)
  923. {
  924. *Status = NDIS_STATUS_FAILURE;
  925. }
  926. } while (FALSE);
  927. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  928. ("<==NdisReadNetworkAddress: ConfigurationHandle %p\n", ConfigurationHandle));
  929. }
  930. VOID
  931. NdisConvertStringToAtmAddress(
  932. OUT PNDIS_STATUS Status,
  933. IN PNDIS_STRING String,
  934. OUT PATM_ADDRESS AtmAddress
  935. )
  936. /*++
  937. Routine Description:
  938. Arguments:
  939. Status - Returns the status of the request.
  940. String - String representation of the atm address.
  941. * Format defined in Section 5.4,
  942. * "Example Master File Format" in ATM95-1532R4 ATM Name System:
  943. *
  944. * AESA format: a string of hexadecimal digits, with '.' characters for punctuation, e.g.
  945. *
  946. * 39.246f.00.0e7c9c.0312.0001.0001.000012345678.00
  947. *
  948. * E164 format: A '+' character followed by a string of
  949. * decimal digits, with '.' chars for punctuation, e.g.:
  950. *
  951. * +358.400.1234567
  952. AtmAddress - The converted Atm address is returned here.
  953. Return Value:
  954. None.
  955. --*/
  956. {
  957. USHORT i, j, NumDigits;
  958. PWSTR p, q;
  959. UNICODE_STRING Us;
  960. ANSI_STRING As;
  961. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  962. ("==>NdisConvertStringToAtmAddress\n"));
  963. //
  964. // Start off by stripping the punctuation characters from the string. We do this in place.
  965. //
  966. for (i = NumDigits = 0, j = String->Length/sizeof(WCHAR), p = q = String->Buffer;
  967. (i < j) && (*p != 0);
  968. i++, p++)
  969. {
  970. if ((*p == ATM_ADDR_BLANK_CHAR) ||
  971. (*p == ATM_ADDR_PUNCTUATION_CHAR))
  972. {
  973. continue;
  974. }
  975. *q++ = *p;
  976. NumDigits ++;
  977. }
  978. //
  979. // Look at the first character to determine if the address is E.164 or NSAP.
  980. // If the address isn't long enough, we assume that it is native E.164.
  981. //
  982. p = String->Buffer;
  983. if ((*p == ATM_ADDR_E164_START_CHAR) || (NumDigits <= 15))
  984. {
  985. if (*p == ATM_ADDR_E164_START_CHAR)
  986. {
  987. p ++;
  988. NumDigits --;
  989. }
  990. if ((NumDigits == 0) || (NumDigits > ATM_ADDRESS_LENGTH))
  991. {
  992. *Status = NDIS_STATUS_INVALID_LENGTH;
  993. return;
  994. }
  995. AtmAddress->AddressType = ATM_E164;
  996. AtmAddress->NumberOfDigits = NumDigits;
  997. }
  998. else
  999. {
  1000. if (NumDigits != 2*ATM_ADDRESS_LENGTH)
  1001. {
  1002. *Status = NDIS_STATUS_INVALID_LENGTH;
  1003. return;
  1004. }
  1005. AtmAddress->AddressType = ATM_NSAP;
  1006. AtmAddress->NumberOfDigits = NumDigits/sizeof(WCHAR);
  1007. }
  1008. //
  1009. // Convert the address to Ansi now
  1010. //
  1011. Us.Buffer = p;
  1012. Us.Length = Us.MaximumLength = NumDigits*sizeof(WCHAR);
  1013. As.Buffer = ALLOC_FROM_POOL(NumDigits + 1, NDIS_TAG_CO);
  1014. As.Length = 0;
  1015. As.MaximumLength = NumDigits + 1;
  1016. if (As.Buffer == NULL)
  1017. {
  1018. *Status = NDIS_STATUS_RESOURCES;
  1019. return;
  1020. }
  1021. *Status = NdisUnicodeStringToAnsiString(&As, &Us);
  1022. if (!NT_SUCCESS(*Status))
  1023. {
  1024. FREE_POOL(As.Buffer);
  1025. *Status = NDIS_STATUS_FAILURE;
  1026. return;
  1027. }
  1028. //
  1029. // Now get the bytes into the destination ATM Address structure.
  1030. //
  1031. if (AtmAddress->AddressType == ATM_E164)
  1032. {
  1033. //
  1034. // We just need to copy in the digits in ANSI form.
  1035. //
  1036. NdisMoveMemory(AtmAddress->Address, As.Buffer, NumDigits);
  1037. }
  1038. else
  1039. {
  1040. //
  1041. // This is in NSAP form. We need to pack the hex digits.
  1042. //
  1043. UCHAR xxString[3];
  1044. ULONG val;
  1045. xxString[2] = 0;
  1046. for (i = 0; i < ATM_ADDRESS_LENGTH; i++)
  1047. {
  1048. xxString[0] = As.Buffer[i*2];
  1049. xxString[1] = As.Buffer[i*2+1];
  1050. *Status = CHAR_TO_INT((PCSZ)xxString, 16, &val);
  1051. if (!NT_SUCCESS(*Status))
  1052. {
  1053. FREE_POOL(As.Buffer);
  1054. *Status = NDIS_STATUS_FAILURE;
  1055. return;
  1056. }
  1057. AtmAddress->Address[i] = (UCHAR)val;
  1058. }
  1059. }
  1060. FREE_POOL(As.Buffer);
  1061. DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
  1062. ("<==NdisConvertStringToAtmAddress\n"));
  1063. *Status = NDIS_STATUS_SUCCESS;
  1064. }
  1065. NTSTATUS
  1066. ndisSaveParameters(
  1067. IN PWSTR ValueName,
  1068. IN ULONG ValueType,
  1069. IN PVOID ValueData,
  1070. IN ULONG ValueLength,
  1071. IN PVOID Context,
  1072. IN PVOID EntryContext
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. This routine is a callback routine for RtlQueryRegistryValues
  1077. It is called with the value for a specified parameter. It allocates
  1078. memory to hold the data and copies it over.
  1079. Arguments:
  1080. ValueName - The name of the value (ignored).
  1081. ValueType - The type of the value.
  1082. ValueData - The null-terminated data for the value.
  1083. ValueLength - The length of ValueData.
  1084. Context - Points to the head of the parameter chain.
  1085. EntryContext - A pointer to
  1086. Return Value:
  1087. STATUS_SUCCESS
  1088. --*/
  1089. {
  1090. NDIS_STATUS Status;
  1091. //
  1092. // Obtain the actual configuration handle structure
  1093. //
  1094. PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)Context;
  1095. //
  1096. // Where the user wants a pointer returned to the data.
  1097. //
  1098. PNDIS_CONFIGURATION_PARAMETER *ParameterValue = (PNDIS_CONFIGURATION_PARAMETER *)EntryContext;
  1099. //
  1100. // Use this to link parameters allocated to this open
  1101. //
  1102. PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode;
  1103. //
  1104. // Size of memory to allocate for parameter node
  1105. //
  1106. UINT Size;
  1107. UNREFERENCED_PARAMETER(ValueName);
  1108. //
  1109. // Allocate our parameter node
  1110. //
  1111. Size = sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE);
  1112. if ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ) || (ValueType == REG_BINARY))
  1113. {
  1114. Size += ValueLength;
  1115. }
  1116. ParameterNode = ALLOC_FROM_POOL(Size, NDIS_TAG_PARAMETER_NODE);
  1117. Status = (ParameterNode != NULL) ? NDIS_STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
  1118. if (Status != NDIS_STATUS_SUCCESS)
  1119. {
  1120. return (NTSTATUS)Status;
  1121. }
  1122. *ParameterValue = &ParameterNode->Parameter;
  1123. //
  1124. // Map registry datatypes to ndis data types
  1125. //
  1126. if (ValueType == REG_DWORD)
  1127. {
  1128. //
  1129. // The registry says that the data is in a dword boundary.
  1130. //
  1131. (*ParameterValue)->ParameterType = NdisParameterInteger;
  1132. (*ParameterValue)->ParameterData.IntegerData = *((PULONG) ValueData);
  1133. }
  1134. else if ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ))
  1135. {
  1136. (*ParameterValue)->ParameterType =
  1137. (ValueType == REG_SZ) ? NdisParameterString : NdisParameterMultiString;
  1138. (*ParameterValue)->ParameterData.StringData.Buffer = (PWSTR)((PUCHAR)ParameterNode + sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE));
  1139. CopyMemory((*ParameterValue)->ParameterData.StringData.Buffer,
  1140. ValueData,
  1141. ValueLength);
  1142. (*ParameterValue)->ParameterData.StringData.Length = (USHORT)ValueLength;
  1143. (*ParameterValue)->ParameterData.StringData.MaximumLength = (USHORT)ValueLength;
  1144. //
  1145. // Special fix; if a string ends in a NULL and that is included
  1146. // in the length, remove it.
  1147. //
  1148. if (ValueType == REG_SZ)
  1149. {
  1150. if ((((PUCHAR)ValueData)[ValueLength-1] == 0) &&
  1151. (((PUCHAR)ValueData)[ValueLength-2] == 0))
  1152. {
  1153. (*ParameterValue)->ParameterData.StringData.Length -= 2;
  1154. }
  1155. }
  1156. }
  1157. else if (ValueType == REG_BINARY)
  1158. {
  1159. (*ParameterValue)->ParameterType = NdisParameterBinary;
  1160. (*ParameterValue)->ParameterData.BinaryData.Buffer = ValueData;
  1161. (*ParameterValue)->ParameterData.BinaryData.Length = (USHORT)ValueLength;
  1162. (*ParameterValue)->ParameterData.BinaryData.Buffer = (PWSTR)((PUCHAR)ParameterNode + sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE));
  1163. CopyMemory((*ParameterValue)->ParameterData.BinaryData.Buffer,
  1164. ValueData,
  1165. ValueLength);
  1166. }
  1167. else
  1168. {
  1169. FREE_POOL(ParameterNode);
  1170. return STATUS_OBJECT_NAME_NOT_FOUND;
  1171. }
  1172. //
  1173. // Queue this parameter node
  1174. //
  1175. ParameterNode->Next = NdisConfigHandle->ParameterList;
  1176. NdisConfigHandle->ParameterList = ParameterNode;
  1177. return STATUS_SUCCESS;
  1178. }
  1179. NTSTATUS
  1180. ndisReadParameter(
  1181. IN PWSTR ValueName,
  1182. IN ULONG ValueType,
  1183. IN PVOID ValueData,
  1184. IN ULONG ValueLength,
  1185. IN PVOID Context,
  1186. IN PVOID EntryContext
  1187. )
  1188. /*++
  1189. Routine Description:
  1190. This routine is a callback routine for RtlQueryRegistryValues
  1191. It is called with the values for the "Bind" and "Export" multi-strings
  1192. for a given driver. It allocates memory to hold the data and copies
  1193. it over.
  1194. Arguments:
  1195. ValueName - The name of the value ("Bind" or "Export" -- ignored).
  1196. ValueType - The type of the value (REG_MULTI_SZ -- ignored).
  1197. ValueData - The null-terminated data for the value.
  1198. ValueLength - The length of ValueData.
  1199. Context - Unused.
  1200. EntryContext - A pointer to the pointer that holds the copied data.
  1201. Return Value:
  1202. STATUS_SUCCESS
  1203. --*/
  1204. {
  1205. //1 everwhere this function is called, check for the type and if applicable the range
  1206. //1 make sure anybody using this API, frees the allocated memory,
  1207. PUCHAR * Data = ((PUCHAR *)EntryContext);
  1208. UNREFERENCED_PARAMETER(ValueName);
  1209. //
  1210. // Allocate one DWORD more and zero is out
  1211. //
  1212. *Data = ALLOC_FROM_POOL(ValueLength + sizeof(ULONG), NDIS_TAG_REG_READ_DATA_BUFFER);
  1213. if (*Data == NULL)
  1214. {
  1215. return STATUS_INSUFFICIENT_RESOURCES;
  1216. }
  1217. ZeroMemory(*Data, ValueLength + sizeof(ULONG));
  1218. CopyMemory(*Data, ValueData, ValueLength);
  1219. if (Context)
  1220. {
  1221. *((PULONG)Context) = ValueType;
  1222. }
  1223. return STATUS_SUCCESS;
  1224. }