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.

1711 lines
46 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. config.c
  5. Abstract:
  6. This contains all routines necessary for the support of the dynamic
  7. configuration of the ISN IPX module.
  8. Revision History:
  9. Sanjay Anand (SanjayAn) 19-Sept-1995
  10. Changes to support Plug and Play
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // Local functions used to access the registry.
  16. //
  17. NTSTATUS
  18. IpxGetConfigValue(
  19. IN PWSTR ValueName,
  20. IN ULONG ValueType,
  21. IN PVOID ValueData,
  22. IN ULONG ValueLength,
  23. IN PVOID Context,
  24. IN PVOID EntryContext
  25. );
  26. NTSTATUS
  27. IpxGetBindingValue(
  28. IN PWSTR ValueName,
  29. IN ULONG ValueType,
  30. IN PVOID ValueData,
  31. IN ULONG ValueLength,
  32. IN PVOID Context,
  33. IN PVOID EntryContext
  34. );
  35. NTSTATUS
  36. IpxGetFrameType(
  37. IN PWSTR ValueName,
  38. IN ULONG ValueType,
  39. IN PVOID ValueData,
  40. IN ULONG ValueLength,
  41. IN PVOID Context,
  42. IN PVOID EntryContext
  43. );
  44. NTSTATUS
  45. IpxAddBind(
  46. IN PWSTR ValueName,
  47. IN ULONG ValueType,
  48. IN PVOID ValueData,
  49. IN ULONG ValueLength,
  50. IN PVOID Context,
  51. IN PVOID EntryContext
  52. );
  53. NTSTATUS
  54. IpxAddExport(
  55. IN PWSTR ValueName,
  56. IN ULONG ValueType,
  57. IN PVOID ValueData,
  58. IN ULONG ValueLength,
  59. IN PVOID Context,
  60. IN PVOID EntryContext
  61. );
  62. NTSTATUS
  63. IpxReadLinkageInformation(
  64. IN PCONFIG Config
  65. );
  66. #ifdef ALLOC_PRAGMA
  67. #pragma alloc_text(INIT,IpxGetConfiguration)
  68. #pragma alloc_text(INIT,IpxFreeConfiguration)
  69. #pragma alloc_text(INIT,IpxAddBind)
  70. #pragma alloc_text(INIT,IpxAddExport)
  71. #pragma alloc_text(INIT,IpxReadLinkageInformation)
  72. #endif
  73. #define MAX_PATH 260
  74. NTSTATUS
  75. IpxGetConfiguration (
  76. IN PDRIVER_OBJECT DriverObject,
  77. IN PUNICODE_STRING RegistryPath,
  78. OUT PCONFIG * ConfigPtr
  79. )
  80. /*++
  81. Routine Description:
  82. This routine is called by IPX to get information from the configuration
  83. management routines. We read the registry, starting at RegistryPath,
  84. to get the parameters. If they don't exist, we use the defaults
  85. set in ipxcnfg.h file. A list of adapters to bind to is chained
  86. on to the config information.
  87. Arguments:
  88. DriverObject - Used for logging errors.
  89. RegistryPath - The name of IPX's node in the registry.
  90. ConfigPtr - Returns the configuration information.
  91. Return Value:
  92. Status - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES
  93. otherwise.
  94. --*/
  95. {
  96. PWSTR RegistryPathBuffer;
  97. PCONFIG Config;
  98. RTL_QUERY_REGISTRY_TABLE QueryTable[CONFIG_PARAMETERS+2];
  99. NTSTATUS Status;
  100. ULONG Zero = 0;
  101. ULONG One = 1;
  102. ULONG Five = 5;
  103. ULONG Eight = 8;
  104. ULONG Ten = 10;
  105. ULONG Fifteen = 15;
  106. ULONG Fifty = 50;
  107. ULONG DefaultSocketStart = 0x4000;
  108. ULONG DefaultSocketEnd = 0x8000;
  109. ULONG RipSegments = RIP_SEGMENTS;
  110. PWSTR Parameters = L"Parameters";
  111. struct {
  112. PWSTR KeyName;
  113. PULONG DefaultValue;
  114. } ParameterValues[CONFIG_PARAMETERS] = {
  115. { L"DedicatedRouter", &Zero } ,
  116. { L"InitDatagrams", &Ten } ,
  117. { L"MaxDatagrams", &Fifty } ,
  118. { L"RipAgeTime", &Five } , // minutes
  119. { L"RipCount", &Five } ,
  120. { L"RipTimeout", &One } , // half-second
  121. { L"RipUsageTime", &Fifteen } , // minutes
  122. { L"SourceRouteUsageTime", &Ten } , // minutes
  123. { L"SocketUniqueness", &Eight } ,
  124. { L"SocketStart", &DefaultSocketStart } ,
  125. { L"SocketEnd", &DefaultSocketEnd } ,
  126. { L"VirtualNetworkNumber", &Zero } ,
  127. { L"MaxMemoryUsage", &Zero } ,
  128. { L"RipTableSize", &RipSegments } ,
  129. { L"VirtualNetworkOptional", &One } ,
  130. { L"EthernetPadToEven", &One } ,
  131. { L"EthernetExtraPadding", &Zero } ,
  132. { L"SingleNetworkActive", &Zero } ,
  133. { L"DisableDialoutSap", &Zero } ,
  134. { L"DisableDialinNetbios", &One } ,
  135. { L"VerifySourceAddress", &One } };
  136. UINT i;
  137. //
  138. // Allocate memory for the main config structure.
  139. //
  140. Config = IpxAllocateMemory (sizeof(CONFIG), MEMORY_CONFIG, "Config");
  141. if (Config == NULL) {
  142. IpxWriteResourceErrorLog(
  143. (PVOID)DriverObject,
  144. EVENT_TRANSPORT_RESOURCE_POOL,
  145. sizeof(CONFIG),
  146. MEMORY_CONFIG);
  147. return STATUS_INSUFFICIENT_RESOURCES;
  148. }
  149. Config->DeviceName.Buffer = NULL;
  150. InitializeListHead (&Config->BindingList);
  151. Config->DriverObject = DriverObject;
  152. //
  153. // Read in the NDIS binding information.
  154. //
  155. // IpxReadLinkageInformation expects a null-terminated path,
  156. // so we have to create one from the UNICODE_STRING.
  157. //
  158. RegistryPathBuffer = (PWSTR)IpxAllocateMemory(RegistryPath->Length + sizeof(WCHAR),
  159. MEMORY_CONFIG, "RegistryPathBuffer");
  160. if (RegistryPathBuffer == NULL) {
  161. IpxFreeConfiguration(Config);
  162. IpxWriteResourceErrorLog(
  163. (PVOID)DriverObject,
  164. EVENT_TRANSPORT_RESOURCE_POOL,
  165. RegistryPath->Length + sizeof(WCHAR),
  166. MEMORY_CONFIG);
  167. return STATUS_INSUFFICIENT_RESOURCES;
  168. }
  169. RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
  170. *(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
  171. Config->RegistryPathBuffer = RegistryPathBuffer;
  172. //
  173. // Determine what name to export and who to bind to.
  174. //
  175. Status = IpxReadLinkageInformation (Config);
  176. if (Status != STATUS_SUCCESS) {
  177. //
  178. // It logged an error if it failed.
  179. //
  180. IpxFreeMemory (Config->RegistryPathBuffer,
  181. RegistryPath->Length + sizeof(WCHAR),
  182. MEMORY_CONFIG,
  183. "RegistryPathBuffer");
  184. IpxFreeConfiguration(Config);
  185. return Status;
  186. }
  187. //
  188. // Read the per-transport (as opposed to per-binding)
  189. // parameters.
  190. //
  191. //
  192. // Set up QueryTable to do the following:
  193. //
  194. //
  195. // 1) Switch to the Parameters key below IPX
  196. //
  197. QueryTable[0].QueryRoutine = NULL;
  198. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  199. QueryTable[0].Name = Parameters;
  200. //
  201. // 2-14) Call IpxGetConfigValue for each of the keys we
  202. // care about.
  203. //
  204. for (i = 0; i < CONFIG_PARAMETERS; i++) {
  205. QueryTable[i+1].QueryRoutine = IpxGetConfigValue;
  206. QueryTable[i+1].Flags = 0;
  207. QueryTable[i+1].Name = ParameterValues[i].KeyName;
  208. QueryTable[i+1].EntryContext = UlongToPtr(i);
  209. QueryTable[i+1].DefaultType = REG_DWORD;
  210. QueryTable[i+1].DefaultData = (PVOID)(ParameterValues[i].DefaultValue);
  211. QueryTable[i+1].DefaultLength = sizeof(ULONG);
  212. }
  213. //
  214. // 15) Stop
  215. //
  216. QueryTable[CONFIG_PARAMETERS+1].QueryRoutine = NULL;
  217. QueryTable[CONFIG_PARAMETERS+1].Flags = 0;
  218. QueryTable[CONFIG_PARAMETERS+1].Name = NULL;
  219. Status = RtlQueryRegistryValues(
  220. RTL_REGISTRY_ABSOLUTE,
  221. Config->RegistryPathBuffer,
  222. QueryTable,
  223. (PVOID)Config,
  224. NULL);
  225. if (Status != STATUS_SUCCESS) {
  226. IpxFreeMemory (Config->RegistryPathBuffer,
  227. RegistryPath->Length + sizeof(WCHAR),
  228. MEMORY_CONFIG,
  229. "RegistryPathBuffer");
  230. IpxFreeConfiguration(Config);
  231. IpxWriteGeneralErrorLog(
  232. (PVOID)DriverObject,
  233. EVENT_IPX_ILLEGAL_CONFIG,
  234. 905,
  235. Status,
  236. Parameters,
  237. 0,
  238. NULL);
  239. return STATUS_DEVICE_CONFIGURATION_ERROR;
  240. }
  241. //
  242. // For PnP, we need to keep this path around
  243. //
  244. *ConfigPtr = Config;
  245. return STATUS_SUCCESS;
  246. } /* IpxGetConfiguration */
  247. VOID
  248. IpxFreeConfiguration (
  249. IN PCONFIG Config
  250. )
  251. /*++
  252. Routine Description:
  253. This routine is called by IPX to get free any storage that was allocated
  254. by IpxGetConfiguration in producing the specified CONFIG structure.
  255. Arguments:
  256. Config - A pointer to the configuration information structure.
  257. Return Value:
  258. None.
  259. --*/
  260. {
  261. PLIST_ENTRY p;
  262. PBINDING_CONFIG Binding;
  263. while (!IsListEmpty (&Config->BindingList)) {
  264. p = RemoveHeadList (&Config->BindingList);
  265. Binding = CONTAINING_RECORD (p, BINDING_CONFIG, Linkage);
  266. IpxFreeMemory (Binding->AdapterName.Buffer, Binding->AdapterName.MaximumLength, MEMORY_CONFIG, "NameBuffer");
  267. IpxFreeMemory (Binding, sizeof(BINDING_CONFIG), MEMORY_CONFIG, "Binding");
  268. }
  269. if (Config->DeviceName.Buffer) {
  270. IpxFreeMemory (Config->DeviceName.Buffer, Config->DeviceName.MaximumLength, MEMORY_CONFIG, "DeviceName");
  271. }
  272. IpxFreeMemory (Config, sizeof(CONFIG), MEMORY_CONFIG, "Config");
  273. } /* IpxFreeConfiguration */
  274. NTSTATUS
  275. IpxGetConfigValue(
  276. IN PWSTR ValueName,
  277. IN ULONG ValueType,
  278. IN PVOID ValueData,
  279. IN ULONG ValueLength,
  280. IN PVOID Context,
  281. IN PVOID EntryContext
  282. )
  283. /*++
  284. Routine Description:
  285. This routine is a callback routine for RtlQueryRegistryValues
  286. It is called for each entry in the Parameters
  287. node to set the config values. The table is set up
  288. so that this function will be called with correct default
  289. values for keys that are not present.
  290. Arguments:
  291. ValueName - The name of the value (ignored).
  292. ValueType - The type of the value (REG_DWORD -- ignored).
  293. ValueData - The data for the value.
  294. ValueLength - The length of ValueData (ignored).
  295. Context - A pointer to the CONFIG structure.
  296. EntryContext - The index in Config->Parameters to save the value.
  297. Return Value:
  298. STATUS_SUCCESS
  299. --*/
  300. {
  301. PCONFIG Config = (PCONFIG)Context;
  302. UNREFERENCED_PARAMETER(ValueName);
  303. UNREFERENCED_PARAMETER(ValueType);
  304. UNREFERENCED_PARAMETER(ValueLength);
  305. if ((ValueType != REG_DWORD) || (ValueLength != sizeof(ULONG))) {
  306. IpxWriteGeneralErrorLog(
  307. (PVOID)Config->DriverObject,
  308. EVENT_IPX_ILLEGAL_CONFIG,
  309. 904,
  310. STATUS_INVALID_PARAMETER,
  311. ValueName,
  312. 0,
  313. NULL);
  314. return STATUS_INVALID_PARAMETER;
  315. }
  316. #ifdef SUNDOWN
  317. IPX_DEBUG (CONFIG, ("Config parameter %d, value %lx\n",
  318. (ULONG_PTR)EntryContext, *(UNALIGNED ULONG *)ValueData));
  319. Config->Parameters[(ULONG_PTR)EntryContext] = *(UNALIGNED ULONG *)ValueData;
  320. #else
  321. IPX_DEBUG (CONFIG, ("Config parameter %d, value %lx\n",
  322. (ULONG)EntryContext, *(UNALIGNED ULONG *)ValueData));
  323. Config->Parameters[(ULONG)EntryContext] = *(UNALIGNED ULONG *)ValueData;
  324. #endif
  325. return STATUS_SUCCESS;
  326. } /* IpxGetConfigValue */
  327. NTSTATUS
  328. IpxGetBindingValue(
  329. IN PWSTR ValueName,
  330. IN ULONG ValueType,
  331. IN PVOID ValueData,
  332. IN ULONG ValueLength,
  333. IN PVOID Context,
  334. IN PVOID EntryContext
  335. )
  336. /*++
  337. Routine Description:
  338. This routine is a callback routine for RtlQueryRegistryValues
  339. It is called for each entry in the NetConfig\DriverNN
  340. node to set the per-binding values. The table is set up
  341. so that this function will be called with correct default
  342. values for keys that are not present.
  343. Arguments:
  344. ValueName - The name of the value (ignored).
  345. ValueType - The type of the value (REG_DWORD -- ignored).
  346. ValueData - The data for the value.
  347. ValueLength - The length of ValueData (ignored).
  348. Context - A pointer to the BINDING_CONFIG structure.
  349. EntryContext - The index in Binding->Parameters to save the value.
  350. Return Value:
  351. STATUS_SUCCESS
  352. --*/
  353. {
  354. PBINDING_CONFIG Binding = (PBINDING_CONFIG)Context;
  355. UNREFERENCED_PARAMETER(ValueName);
  356. UNREFERENCED_PARAMETER(ValueType);
  357. UNREFERENCED_PARAMETER(ValueLength);
  358. if ((ValueType != REG_DWORD) || (ValueLength != sizeof(ULONG))) {
  359. IpxWriteGeneralErrorLog(
  360. (PVOID)Binding->DriverObject,
  361. EVENT_IPX_ILLEGAL_CONFIG,
  362. 903,
  363. STATUS_INVALID_PARAMETER,
  364. ValueName,
  365. 0,
  366. NULL);
  367. return STATUS_INVALID_PARAMETER;
  368. }
  369. #ifdef SUNDOWN
  370. IPX_DEBUG (CONFIG, ("Binding parameter %d, value %lx\n",
  371. (ULONG_PTR)EntryContext, *(UNALIGNED ULONG *)ValueData));
  372. Binding->Parameters[(ULONG_PTR)EntryContext] = *(UNALIGNED ULONG *)ValueData;
  373. #else
  374. IPX_DEBUG (CONFIG, ("Binding parameter %d, value %lx\n",
  375. (ULONG)EntryContext, *(UNALIGNED ULONG *)ValueData));
  376. Binding->Parameters[(ULONG)EntryContext] = *(UNALIGNED ULONG *)ValueData;
  377. #endif
  378. return STATUS_SUCCESS;
  379. } /* IpxGetBindingValue */
  380. NTSTATUS
  381. IpxGetFrameType(
  382. IN PWSTR ValueName,
  383. IN ULONG ValueType,
  384. IN PVOID ValueData,
  385. IN ULONG ValueLength,
  386. IN PVOID Context,
  387. IN PVOID EntryContext
  388. )
  389. /*++
  390. Routine Description:
  391. This routine is a callback routine for RtlQueryRegistryValues.
  392. It is called for each of the entry in the "PktType" and
  393. "NetworkNumber" multi-strings for a given binding.
  394. Arguments:
  395. ValueName - The name of the value ("PktType" or "NetworkNumber" -- ignored).
  396. ValueType - The type of the value (REG_MULTI_SZ -- ignored).
  397. ValueData - The null-terminated data for the value.
  398. ValueLength - The length of ValueData.
  399. Context - A pointer to the BINDING_CONFIG structure.
  400. EntryContext - A pointer to a count of multi-string entries.
  401. Return Value:
  402. STATUS_SUCCESS
  403. --*/
  404. {
  405. PBINDING_CONFIG Binding = (PBINDING_CONFIG)Context;
  406. ULONG IntegerValue;
  407. PWCHAR Cur;
  408. PULONG Count = (PULONG)EntryContext;
  409. ASSERT(Binding->DriverObject != NULL);
  410. if ((ValueType != REG_SZ) ||
  411. (*Count >= 4)) {
  412. IpxWriteGeneralErrorLog(
  413. (PVOID)Binding->DriverObject,
  414. EVENT_IPX_ILLEGAL_CONFIG,
  415. 903,
  416. STATUS_INVALID_PARAMETER,
  417. ValueName,
  418. 0,
  419. NULL);
  420. return STATUS_INVALID_PARAMETER;
  421. }
  422. IntegerValue = 0;
  423. for (Cur = (PWCHAR)(ValueData); ; Cur++) {
  424. if (*Cur >= L'0' && *Cur <= L'9') {
  425. IntegerValue = (IntegerValue * 16) + (*Cur - L'0');
  426. } else if (*Cur >= L'A' && *Cur <= L'F') {
  427. IntegerValue = (IntegerValue * 16) + (*Cur - L'A' + 10);
  428. } else if (*Cur >= L'a' && *Cur <= L'f') {
  429. IntegerValue = (IntegerValue * 16) + (*Cur - L'a' + 10);
  430. } else {
  431. break;
  432. }
  433. }
  434. if (((PWCHAR)ValueName)[0] == L'P') {
  435. //
  436. // PktType. We map arcnet to 802_3 so the code around
  437. // here can assume there are only four packets type --
  438. // the frame type is ignored later for arcnet.
  439. //
  440. if ((IntegerValue > ISN_FRAME_TYPE_ARCNET) &&
  441. (IntegerValue != ISN_FRAME_TYPE_AUTO)) {
  442. IpxWriteGeneralErrorLog(
  443. (PVOID)Binding->DriverObject,
  444. EVENT_IPX_ILLEGAL_CONFIG,
  445. 903,
  446. STATUS_INVALID_PARAMETER,
  447. ValueName,
  448. 0,
  449. NULL);
  450. return STATUS_INVALID_PARAMETER;
  451. }
  452. IPX_DEBUG (CONFIG, ("PktType(%d) is %lx\n", *Count, IntegerValue));
  453. if (IntegerValue == ISN_FRAME_TYPE_ARCNET) {
  454. Binding->FrameType[*Count] = ISN_FRAME_TYPE_802_3;
  455. } else {
  456. Binding->FrameType[*Count] = IntegerValue;
  457. }
  458. } else {
  459. //
  460. // NetworkNumber
  461. //
  462. IPX_DEBUG (CONFIG, ("NetworkNumber(%d) is %d\n", *Count, IntegerValue));
  463. Binding->NetworkNumber[*Count] = IntegerValue;
  464. }
  465. ++(*Count);
  466. return STATUS_SUCCESS;
  467. } /* IpxGetFrameType */
  468. NTSTATUS
  469. IpxAddBind(
  470. IN PWSTR ValueName,
  471. IN ULONG ValueType,
  472. IN PVOID ValueData,
  473. IN ULONG ValueLength,
  474. IN PVOID Context,
  475. IN PVOID EntryContext
  476. )
  477. /*++
  478. Routine Description:
  479. This routine is a callback routine for RtlQueryRegistryValues
  480. It is called for each piece of the "Bind" multi-string and
  481. saves the information in a Config structure. It
  482. also queries the per-binding information and stores it.
  483. Arguments:
  484. ValueName - The name of the value ("Bind" -- ignored).
  485. ValueType - The type of the value (REG_SZ -- ignored).
  486. ValueData - The null-terminated data for the value.
  487. ValueLength - The length of ValueData.
  488. Context - A pointer to the Config structure.
  489. EntryContext - A pointer to a count of binds that is incremented.
  490. Return Value:
  491. STATUS_SUCCESS
  492. --*/
  493. {
  494. PCONFIG Config = (PCONFIG)Context;
  495. PBINDING_CONFIG Binding;
  496. PULONG CurBindNum = ((PULONG)EntryContext);
  497. RTL_QUERY_REGISTRY_TABLE QueryTable[BINDING_PARAMETERS+4];
  498. ULONG FrameTypeCount, NetworkNumberCount;
  499. ULONG StringLoc;
  500. BOOLEAN AutoDetect;
  501. ULONG AutoDetectLoc;
  502. ULONG SlideCount;
  503. PWCHAR NameBuffer;
  504. NTSTATUS Status;
  505. BOOLEAN FrameTypeUsed[ISN_FRAME_TYPE_MAX];
  506. ULONG Zero = 0;
  507. ULONG One = 1;
  508. ULONG DefaultBindSap = 0x8137;
  509. ULONG DefaultAutoDetectType = ISN_FRAME_TYPE_802_2;
  510. WCHAR Subkey[MAX_PATH];// = L"Parameters\\Adapters\\12345678901234567890";
  511. PWSTR ValueDataWstr = (PWSTR)ValueData;
  512. struct {
  513. PWSTR KeyName;
  514. PULONG DefaultValue;
  515. } ParameterValues[BINDING_PARAMETERS] = {
  516. { L"MaxPktSize", &Zero } ,
  517. { L"BindSap", &DefaultBindSap } ,
  518. { L"DefaultAutoDetectType", &DefaultAutoDetectType } ,
  519. { L"SourceRouting", &One } ,
  520. { L"SourceRouteDef", &Zero } ,
  521. { L"SourceRouteBcast", &Zero } ,
  522. { L"SourceRouteMcast", &Zero } ,
  523. { L"EnableFuncaddr", &One } ,
  524. { L"EnableWanRouter", &One } };
  525. ULONG BindingPreference[ISN_FRAME_TYPE_MAX] = {
  526. ISN_FRAME_TYPE_802_2,
  527. ISN_FRAME_TYPE_802_3,
  528. ISN_FRAME_TYPE_ETHERNET_II,
  529. ISN_FRAME_TYPE_SNAP };
  530. UINT i, j, k;
  531. UNREFERENCED_PARAMETER(ValueName);
  532. UNREFERENCED_PARAMETER(ValueType);
  533. Binding = (PBINDING_CONFIG)IpxAllocateMemory (sizeof(BINDING_CONFIG), MEMORY_CONFIG, "Binding");
  534. if (Binding == NULL) {
  535. IpxWriteResourceErrorLog(
  536. (PVOID)Config->DriverObject,
  537. EVENT_TRANSPORT_RESOURCE_POOL,
  538. sizeof(BINDING_CONFIG),
  539. MEMORY_CONFIG);
  540. return STATUS_INSUFFICIENT_RESOURCES;
  541. }
  542. NameBuffer = (PWCHAR)IpxAllocateMemory (ValueLength, MEMORY_CONFIG, "NameBuffer");
  543. if (NameBuffer == NULL) {
  544. IpxFreeMemory (Binding, sizeof(BINDING_CONFIG), MEMORY_CONFIG, "Binding");
  545. IpxWriteResourceErrorLog(
  546. (PVOID)Config->DriverObject,
  547. EVENT_TRANSPORT_RESOURCE_POOL,
  548. ValueLength,
  549. MEMORY_CONFIG);
  550. return STATUS_INSUFFICIENT_RESOURCES;
  551. }
  552. RtlCopyMemory (NameBuffer, ValueData, ValueLength);
  553. Binding->AdapterName.Buffer = NameBuffer;
  554. Binding->AdapterName.Length = (USHORT)(ValueLength - sizeof(WCHAR));
  555. Binding->AdapterName.MaximumLength = (USHORT)ValueLength;
  556. Binding->DriverObject = Config->DriverObject;
  557. FrameTypeCount = 0;
  558. NetworkNumberCount = 0;
  559. //
  560. // The structure is allocated OK, insert it into the list.
  561. //
  562. InsertTailList (&Config->BindingList, &Binding->Linkage);
  563. ++(*CurBindNum);
  564. //
  565. // Set up QueryTable to do the following:
  566. //
  567. //
  568. // 1) Switch to the NetConfig\XXXX key below IPX
  569. // (we construct the right name in Subkey,
  570. // first scan back to find the \, then copy
  571. // the rest over, including the final '\0').
  572. //
  573. StringLoc = (ValueLength / sizeof(WCHAR)) - 2;
  574. while (ValueDataWstr[StringLoc] != L'\\') {
  575. --StringLoc;
  576. }
  577. RtlCopyMemory(&Subkey, L"Parameters\\Adapters\\12345678901234567890", 40);
  578. RtlCopyMemory(&Subkey[20], &ValueDataWstr[StringLoc+1], ValueLength - ((StringLoc+1) * sizeof(WCHAR)));
  579. KdPrint(("Subkey:%ws\n", Subkey));
  580. QueryTable[0].QueryRoutine = NULL;
  581. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  582. QueryTable[0].Name = Subkey;
  583. //
  584. // 2) Call IpxGetFrameType for each part of the
  585. // "PktType" multi-string.
  586. //
  587. QueryTable[1].QueryRoutine = IpxGetFrameType;
  588. QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  589. QueryTable[1].Name = L"PktType";
  590. QueryTable[1].EntryContext = &FrameTypeCount;
  591. QueryTable[1].DefaultType = REG_NONE;
  592. //
  593. // 3) Call IpxGetFrameType for each part of the
  594. // "NetworkNumber" multi-string.
  595. //
  596. QueryTable[2].QueryRoutine = IpxGetFrameType;
  597. QueryTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  598. QueryTable[2].Name = L"NetworkNumber";
  599. QueryTable[2].EntryContext = &NetworkNumberCount;
  600. QueryTable[2].DefaultType = REG_NONE;
  601. //
  602. // 4-11) Call IpxGetBindingValue for each of the keys we
  603. // care about.
  604. //
  605. for (i = 0; i < BINDING_PARAMETERS; i++) {
  606. QueryTable[i+3].QueryRoutine = IpxGetBindingValue;
  607. QueryTable[i+3].Flags = 0;
  608. QueryTable[i+3].Name = ParameterValues[i].KeyName;
  609. QueryTable[i+3].EntryContext = UlongToPtr(i);
  610. QueryTable[i+3].DefaultType = REG_DWORD;
  611. QueryTable[i+3].DefaultData = (PVOID)(ParameterValues[i].DefaultValue);
  612. QueryTable[i+3].DefaultLength = sizeof(ULONG);
  613. }
  614. //
  615. // 12) Stop
  616. //
  617. QueryTable[BINDING_PARAMETERS+3].QueryRoutine = NULL;
  618. QueryTable[BINDING_PARAMETERS+3].Flags = 0;
  619. QueryTable[BINDING_PARAMETERS+3].Name = NULL;
  620. IPX_DEBUG (CONFIG, ("Read bind key for %ws (%ws)\n", ValueData, Subkey));
  621. Status = RtlQueryRegistryValues(
  622. RTL_REGISTRY_ABSOLUTE,
  623. Config->RegistryPathBuffer,
  624. QueryTable,
  625. (PVOID)Binding,
  626. NULL);
  627. if (Status != STATUS_SUCCESS) {
  628. //
  629. // The binding will get freed during cleanup.
  630. //
  631. IpxWriteGeneralErrorLog(
  632. (PVOID)Config->DriverObject,
  633. EVENT_IPX_ILLEGAL_CONFIG,
  634. 906,
  635. Status,
  636. Subkey,
  637. 0,
  638. NULL);
  639. return STATUS_DEVICE_CONFIGURATION_ERROR;
  640. }
  641. if (FrameTypeCount == 0) {
  642. IpxWriteGeneralErrorLog(
  643. (PVOID)Config->DriverObject,
  644. EVENT_IPX_NO_FRAME_TYPES,
  645. 907,
  646. Status,
  647. Subkey + 10,
  648. 0,
  649. NULL);
  650. }
  651. if (FrameTypeCount > NetworkNumberCount) {
  652. for (i = NetworkNumberCount; i <FrameTypeCount; i++) {
  653. Binding->NetworkNumber[i] = 0;
  654. }
  655. }
  656. Binding->FrameTypeCount = FrameTypeCount;
  657. //
  658. // Go through and eliminate duplicates from the frame
  659. // type array.
  660. //
  661. for (i = 0; i < Binding->FrameTypeCount; i++) {
  662. for (j = i+1; j < Binding->FrameTypeCount; j++) {
  663. if (Binding->FrameType[j] == Binding->FrameType[i]) {
  664. IPX_DEBUG (CONFIG, ("Frame types %d and %d identical\n", i, j));
  665. //
  666. // A duplicate, slide everything else down.
  667. //
  668. for (k = j+1; k < Binding->FrameTypeCount; k++) {
  669. Binding->FrameType[k-1] = Binding->FrameType[k];
  670. Binding->NetworkNumber[k-1] = Binding->NetworkNumber[k];
  671. }
  672. --Binding->FrameTypeCount;
  673. --j; // so we check whoever just moved into this spot.
  674. }
  675. }
  676. }
  677. //
  678. // Mark all the explicitly configured frame types, and
  679. // see if we have to auto-detect.
  680. //
  681. for (i = 0; i < 4; i++) {
  682. FrameTypeUsed[i] = FALSE;
  683. }
  684. AutoDetect = FALSE;
  685. for (i = 0; i < Binding->FrameTypeCount; i++) {
  686. if (Binding->FrameType[i] == ISN_FRAME_TYPE_AUTO) {
  687. AutoDetectLoc = i;
  688. AutoDetect = TRUE;
  689. } else {
  690. Binding->AutoDetect[i] = FALSE;
  691. Binding->DefaultAutoDetect[i] = FALSE;
  692. FrameTypeUsed[Binding->FrameType[i]] = TRUE;
  693. }
  694. }
  695. if (!AutoDetect) {
  696. IPX_DEBUG (AUTO_DETECT, ("No bindings auto-detected\n"));
  697. return STATUS_SUCCESS;
  698. }
  699. //
  700. // Slide everything that is past the auto-detect point up
  701. // to the end.
  702. //
  703. SlideCount = Binding->FrameTypeCount - AutoDetectLoc - 1;
  704. for (j = 3; j > 3 - SlideCount; j--) {
  705. Binding->FrameType[j] = Binding->FrameType[j-(3-Binding->FrameTypeCount)];
  706. Binding->NetworkNumber[j] = Binding->NetworkNumber[j-(3-Binding->FrameTypeCount)];
  707. Binding->AutoDetect[j] = Binding->AutoDetect[j-(3-Binding->FrameTypeCount)];
  708. Binding->DefaultAutoDetect[j] = Binding->DefaultAutoDetect[j-(3-Binding->FrameTypeCount)];
  709. }
  710. //
  711. // Now fill in any frame types that are not hard-coded,
  712. // this will start at AutoDetectLoc and exactly fill up
  713. // the gap created when we slid things up above. We
  714. // first put the default auto-detect at the first spot.
  715. //
  716. if (!FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]]) {
  717. Binding->FrameType[AutoDetectLoc] = Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT];
  718. Binding->NetworkNumber[AutoDetectLoc] = 0;
  719. Binding->AutoDetect[AutoDetectLoc] = TRUE;
  720. Binding->DefaultAutoDetect[AutoDetectLoc] = TRUE;
  721. ++AutoDetectLoc;
  722. FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]] = TRUE;
  723. }
  724. //
  725. // Now fill in the array, using the preference order in
  726. // the BindingPreference array (this comes into effect
  727. // because the first frame type in our list that we
  728. // find is used).
  729. //
  730. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  731. if (!FrameTypeUsed[BindingPreference[i]]) {
  732. Binding->FrameType[AutoDetectLoc] = BindingPreference[i];
  733. Binding->NetworkNumber[AutoDetectLoc] = 0;
  734. Binding->AutoDetect[AutoDetectLoc] = TRUE;
  735. Binding->DefaultAutoDetect[AutoDetectLoc] = FALSE;
  736. ++AutoDetectLoc;
  737. }
  738. }
  739. Binding->FrameTypeCount = ISN_FRAME_TYPE_MAX;
  740. #if DBG
  741. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  742. IPX_DEBUG (AUTO_DETECT, ("%d: type %d, net %d, auto %d, defaultautodetect %d\n",
  743. i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[i], Binding->DefaultAutoDetect[i]));
  744. }
  745. #endif
  746. return STATUS_SUCCESS;
  747. } /* IpxAddBind */
  748. NTSTATUS
  749. IpxAddExport(
  750. IN PWSTR ValueName,
  751. IN ULONG ValueType,
  752. IN PVOID ValueData,
  753. IN ULONG ValueLength,
  754. IN PVOID Context,
  755. IN PVOID EntryContext
  756. )
  757. /*++
  758. Routine Description:
  759. This routine is a callback routine for RtlQueryRegistryValues
  760. It is called for each piece of the "Export" multi-string. It
  761. saves the first callback string in the Config structure.
  762. Arguments:
  763. ValueName - The name of the value ("Export" -- ignored).
  764. ValueType - The type of the value (REG_SZ -- ignored).
  765. ValueData - The null-terminated data for the value.
  766. ValueLength - The length of ValueData.
  767. Context - A pointer to the Config structure.
  768. EntryContext - A pointer to a ULONG that goes to 1 after the
  769. first call to this routine (so we know to ignore other ones).
  770. Return Value:
  771. STATUS_SUCCESS
  772. --*/
  773. {
  774. PCONFIG Config = (PCONFIG)Context;
  775. PULONG ValueReadOk = ((PULONG)EntryContext);
  776. PWCHAR NameBuffer;
  777. UNREFERENCED_PARAMETER(ValueName);
  778. UNREFERENCED_PARAMETER(ValueType);
  779. if (*ValueReadOk == 0) {
  780. IPX_DEBUG (CONFIG, ("Read export value %ws\n", ValueData));
  781. NameBuffer = (PWCHAR)IpxAllocateMemory (ValueLength, MEMORY_CONFIG, "DeviceName");
  782. if (NameBuffer == NULL) {
  783. IpxWriteResourceErrorLog(
  784. (PVOID)Config->DriverObject,
  785. EVENT_TRANSPORT_RESOURCE_POOL,
  786. ValueLength,
  787. MEMORY_CONFIG);
  788. return STATUS_INSUFFICIENT_RESOURCES;
  789. }
  790. RtlCopyMemory (NameBuffer, ValueData, ValueLength);
  791. Config->DeviceName.Buffer = NameBuffer;
  792. Config->DeviceName.Length = (USHORT)(ValueLength - sizeof(WCHAR));
  793. Config->DeviceName.MaximumLength = (USHORT)ValueLength;
  794. //
  795. // Set this to ignore any other callbacks and let the
  796. // caller know we read something.
  797. //
  798. *ValueReadOk = 1;
  799. }
  800. return STATUS_SUCCESS;
  801. } /* IpxAddExport */
  802. NTSTATUS
  803. IpxReadLinkageInformation(
  804. IN PCONFIG Config
  805. )
  806. /*++
  807. Routine Description:
  808. This routine is called by IPX to read its linkage information
  809. from the registry.
  810. Arguments:
  811. Config - The config structure which will have per-binding information
  812. linked on to it.
  813. Return Value:
  814. The status of the operation.
  815. --*/
  816. {
  817. NTSTATUS Status;
  818. RTL_QUERY_REGISTRY_TABLE QueryTable[3];
  819. PWSTR Subkey = L"Linkage";
  820. PWSTR Bind = L"Bind";
  821. PWSTR Export = L"Export";
  822. ULONG ValueReadOk;
  823. //
  824. // Set up QueryTable to do the following:
  825. //
  826. //
  827. // 1) Switch to the Linkage key below IPX
  828. //
  829. QueryTable[0].QueryRoutine = NULL;
  830. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  831. QueryTable[0].Name = Subkey;
  832. //
  833. // 1) Call IpxAddExport for each string in "Export"
  834. //
  835. QueryTable[1].QueryRoutine = IpxAddExport;
  836. QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  837. QueryTable[1].Name = Export;
  838. QueryTable[1].EntryContext = (PVOID)&ValueReadOk;
  839. QueryTable[1].DefaultType = REG_NONE;
  840. //
  841. // 2) Stop
  842. //
  843. QueryTable[2].QueryRoutine = NULL;
  844. QueryTable[2].Flags = 0;
  845. QueryTable[2].Name = NULL;
  846. ValueReadOk = 0;
  847. Status = RtlQueryRegistryValues(
  848. RTL_REGISTRY_ABSOLUTE,
  849. Config->RegistryPathBuffer,
  850. QueryTable,
  851. (PVOID)Config,
  852. NULL);
  853. if ((Status != STATUS_SUCCESS) || (ValueReadOk == 0)) {
  854. IpxWriteGeneralErrorLog(
  855. (PVOID)Config->DriverObject,
  856. EVENT_IPX_ILLEGAL_CONFIG,
  857. 901,
  858. Status,
  859. Export,
  860. 0,
  861. NULL);
  862. return STATUS_DEVICE_CONFIGURATION_ERROR;
  863. }
  864. return STATUS_SUCCESS;
  865. } /* IpxReadLinkageInformation */
  866. VOID
  867. IpxWriteDefaultAutoDetectType(
  868. IN PUNICODE_STRING RegistryPath,
  869. IN struct _ADAPTER * Adapter,
  870. IN ULONG FrameType
  871. )
  872. /*++
  873. Routine Description:
  874. This routine is called when we were unable to detect the default
  875. auto-detect type and instead found a different one. We update
  876. the "DefaultAutoDetectType" in the registry.
  877. Arguments:
  878. RegistryPath - The name of IPX's node in the registry.
  879. Adapter - The adapter which we auto-detected on.
  880. FrameType - The new auto-detected value.
  881. Return Value:
  882. None.
  883. --*/
  884. {
  885. PWSTR FullRegistryPath;
  886. PUCHAR CurRegistryPath;
  887. ULONG FullRegistryPathLength;
  888. ULONG AdapterNameLength;
  889. WCHAR Adapters[] = L"\\Parameter\\Adapters\\";
  890. static PWCHAR FrameTypeNames[4] = { L"Ethernet II", L"802.3", L"802.2", L"SNAP" };
  891. PWCHAR CurAdapterName;
  892. NTSTATUS Status;
  893. //
  894. // We need to allocate a buffer which contains the registry path,
  895. // followed by "\Parameters\Adapters\", followed by the adapter name, and
  896. // then NULL-terminated.
  897. //
  898. CurAdapterName = &Adapter->AdapterName[(Adapter->AdapterNameLength/sizeof(WCHAR))-2];
  899. while (*CurAdapterName != L'\\') {
  900. --CurAdapterName;
  901. }
  902. // AdapterNameLength is unlikely to exceed 32-bit, RtlCopyMemory takes 32-bit only, so we cast it to ULONG
  903. AdapterNameLength = (ULONG) (Adapter->AdapterNameLength - ((CurAdapterName - Adapter->AdapterName) * sizeof(WCHAR)) - sizeof(WCHAR));
  904. FullRegistryPathLength = RegistryPath->Length + sizeof(Adapters) + AdapterNameLength;
  905. FullRegistryPath = (PWSTR)IpxAllocateMemory (FullRegistryPathLength, MEMORY_CONFIG, "FullRegistryPath");
  906. if (FullRegistryPath == NULL) {
  907. IpxWriteResourceErrorLog(
  908. IpxDevice->DeviceObject,
  909. EVENT_TRANSPORT_RESOURCE_POOL,
  910. FullRegistryPathLength,
  911. MEMORY_CONFIG);
  912. return;
  913. }
  914. CurRegistryPath = (PUCHAR)FullRegistryPath;
  915. RtlCopyMemory (CurRegistryPath, RegistryPath->Buffer, RegistryPath->Length);
  916. CurRegistryPath += RegistryPath->Length;
  917. RtlCopyMemory (CurRegistryPath, Adapters, sizeof(Adapters) - sizeof(WCHAR));
  918. CurRegistryPath += (sizeof(Adapters) - sizeof(WCHAR));
  919. RtlCopyMemory (CurRegistryPath, CurAdapterName, AdapterNameLength);
  920. CurRegistryPath += AdapterNameLength;
  921. *(PWCHAR)CurRegistryPath = L'\0';
  922. Status = RtlWriteRegistryValue(
  923. RTL_REGISTRY_ABSOLUTE,
  924. FullRegistryPath,
  925. L"DefaultAutoDetectType",
  926. REG_DWORD,
  927. &FrameType,
  928. sizeof(ULONG));
  929. IpxFreeMemory (FullRegistryPath, FullRegistryPathLength, MEMORY_CONFIG, "FullRegistryPath");
  930. IpxWriteGeneralErrorLog(
  931. IpxDevice->DeviceObject,
  932. EVENT_IPX_NEW_DEFAULT_TYPE,
  933. 888,
  934. STATUS_SUCCESS,
  935. FrameTypeNames[FrameType],
  936. 0,
  937. NULL);
  938. } /* IpxWriteDefaultAutoDetectType */
  939. //
  940. // Vnet# and VnetOptional
  941. //
  942. #define VIRTUAL_NETWORK_PARAMETERS 2
  943. NTSTATUS
  944. IpxPnPGetVirtualNetworkNumber (
  945. IN PCONFIG Config
  946. )
  947. /*++
  948. Routine Description:
  949. This routine is called by IPX to read the virtual network number
  950. from the registry. This is called on appearance/disappearance of an
  951. adapter from the system. We read the registry, starting at RegistryPath,
  952. to get the value of the VirtualNetworkNumber parameter. If it doesn't
  953. exist, we use the default set in ipxcnfg.h file.
  954. Adapted from IpxGetConfiguration().
  955. Arguments:
  956. Config - Contians the configuration information.
  957. Return Value:
  958. Status - STATUS_SUCCESS if everything OK, STATUS_DEVICE_CONFIGURATION_ERROR
  959. otherwise.
  960. --*/
  961. {
  962. RTL_QUERY_REGISTRY_TABLE QueryTable[VIRTUAL_NETWORK_PARAMETERS+2];
  963. NTSTATUS Status;
  964. ULONG Zero = 0;
  965. ULONG One = 1;
  966. PWSTR Parameters = L"Parameters";
  967. struct {
  968. PWSTR KeyName;
  969. PULONG DefaultValue;
  970. } ParameterValues[VIRTUAL_NETWORK_PARAMETERS] = {
  971. { L"VirtualNetworkNumber", &Zero } ,
  972. { L"VirtualNetworkOptional", &One } };
  973. UINT i;
  974. //
  975. // Read the virtual net number from the parameters.
  976. //
  977. //
  978. // Set up QueryTable to do the following:
  979. //
  980. //
  981. // 1) Switch to the Parameters key below IPX
  982. //
  983. QueryTable[0].QueryRoutine = NULL;
  984. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  985. QueryTable[0].Name = Parameters;
  986. //
  987. // 2) Call IpxGetConfigValue for the virtual net number key
  988. //
  989. QueryTable[1].QueryRoutine = IpxGetConfigValue;
  990. QueryTable[1].Flags = 0;
  991. QueryTable[1].Name = ParameterValues[0].KeyName;
  992. QueryTable[1].EntryContext = (PVOID)CONFIG_VIRTUAL_NETWORK;
  993. QueryTable[1].DefaultType = REG_DWORD;
  994. QueryTable[1].DefaultData = (PVOID)(ParameterValues[0].DefaultValue);
  995. QueryTable[1].DefaultLength = sizeof(ULONG);
  996. //
  997. // 2) Call IpxGetConfigValue for the virtual net optional key
  998. //
  999. QueryTable[2].QueryRoutine = IpxGetConfigValue;
  1000. QueryTable[2].Flags = 0;
  1001. QueryTable[2].Name = ParameterValues[1].KeyName;
  1002. QueryTable[2].EntryContext = (PVOID)CONFIG_VIRTUAL_OPTIONAL;
  1003. QueryTable[2].DefaultType = REG_DWORD;
  1004. QueryTable[2].DefaultData = (PVOID)(ParameterValues[1].DefaultValue);
  1005. QueryTable[2].DefaultLength = sizeof(ULONG);
  1006. //
  1007. // 15) Stop
  1008. //
  1009. QueryTable[3].QueryRoutine = NULL;
  1010. QueryTable[3].Flags = 0;
  1011. QueryTable[3].Name = NULL;
  1012. Status = RtlQueryRegistryValues(
  1013. RTL_REGISTRY_ABSOLUTE,
  1014. Config->RegistryPathBuffer,
  1015. QueryTable,
  1016. (PVOID)Config,
  1017. NULL);
  1018. if (Status != STATUS_SUCCESS) {
  1019. IpxWriteGeneralErrorLog(
  1020. (PVOID)Config->DriverObject,
  1021. EVENT_IPX_ILLEGAL_CONFIG,
  1022. 905,
  1023. Status,
  1024. Parameters,
  1025. 0,
  1026. NULL);
  1027. return STATUS_DEVICE_CONFIGURATION_ERROR;
  1028. }
  1029. return STATUS_SUCCESS;
  1030. } /* IpxPnPGetNetworkNumber */
  1031. #define IPX_REG_KEY_CONFIG_NAME L"Parameters\\Adapters\\12345678901234567890"
  1032. #define IPX_REG_KEY_CONFIG_DUMMY_LENGTH 40
  1033. #define IPX_REG_KEY_CONFIG_LENGTH 20
  1034. NTSTATUS
  1035. IpxPnPGetAdapterParameters(
  1036. IN PCONFIG Config,
  1037. IN PNDIS_STRING DeviceName,
  1038. IN OUT PBINDING_CONFIG Binding
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This routine is called by IPX to read the adapter-specific parameters
  1043. from the registry on PnP appearance of an adapter in the system.
  1044. We read the registry, starting at RegistryPath\NetConfig\DeviceName.
  1045. Adapted from IpxAddBind().
  1046. Arguments:
  1047. Config - Config structure - supplies the DeviceObject and RegistryPathBuffer.
  1048. DeviceName - name of the adapter that was added.
  1049. Binding - Returns the configuration information per adapter.
  1050. Return Value:
  1051. Status - STATUS_SUCCESS if everything OK, STATUS_DEVICE_CONFIGURATION_ERROR
  1052. otherwise.
  1053. --*/
  1054. {
  1055. RTL_QUERY_REGISTRY_TABLE QueryTable[BINDING_PARAMETERS+4];
  1056. ULONG FrameTypeCount, NetworkNumberCount;
  1057. ULONG StringLoc;
  1058. BOOLEAN AutoDetect;
  1059. ULONG AutoDetectLoc;
  1060. ULONG SlideCount;
  1061. PWCHAR NameBuffer;
  1062. NTSTATUS Status;
  1063. BOOLEAN FrameTypeUsed[ISN_FRAME_TYPE_MAX];
  1064. ULONG Zero = 0;
  1065. ULONG One = 1;
  1066. ULONG DefaultBindSap = 0x8137;
  1067. ULONG DefaultAutoDetectType = ISN_FRAME_TYPE_802_2;
  1068. WCHAR Subkey[MAX_PATH];// = L"NetConfig\\12345678901234567890";
  1069. struct {
  1070. PWSTR KeyName;
  1071. PULONG DefaultValue;
  1072. } ParameterValues[BINDING_PARAMETERS] = {
  1073. { L"MaxPktSize", &Zero } ,
  1074. { L"BindSap", &DefaultBindSap } ,
  1075. { L"DefaultAutoDetectType", &DefaultAutoDetectType } ,
  1076. { L"SourceRouting", &One } ,
  1077. { L"SourceRouteDef", &Zero } ,
  1078. { L"SourceRouteBcast", &Zero } ,
  1079. { L"SourceRouteMcast", &Zero } ,
  1080. { L"EnableFuncaddr", &One } ,
  1081. { L"EnableWanRouter", &One } };
  1082. ULONG BindingPreference[ISN_FRAME_TYPE_MAX] = {
  1083. ISN_FRAME_TYPE_802_2,
  1084. ISN_FRAME_TYPE_802_3,
  1085. ISN_FRAME_TYPE_ETHERNET_II,
  1086. ISN_FRAME_TYPE_SNAP };
  1087. UINT i, j, k;
  1088. ASSERT(Binding->DriverObject != NULL);
  1089. FrameTypeCount = 0;
  1090. NetworkNumberCount = 0;
  1091. //
  1092. // The structure is allocated OK, insert it into the list.
  1093. //
  1094. // InsertTailList (&Config->BindingList, &Binding->Linkage);
  1095. // ++(*CurBindNum);
  1096. //
  1097. // Set up QueryTable to do the following:
  1098. //
  1099. //
  1100. // 1) Switch to the NetConfig\XXXX key below IPX
  1101. // (we construct the right name in Subkey,
  1102. // first scan back to find the \, then copy
  1103. // the rest over, including the final '\0').
  1104. //
  1105. StringLoc = (DeviceName->Length / sizeof(WCHAR)) - 2;
  1106. while (DeviceName->Buffer[StringLoc] != L'\\') {
  1107. --StringLoc;
  1108. }
  1109. RtlCopyMemory(&Subkey, IPX_REG_KEY_CONFIG_NAME, IPX_REG_KEY_CONFIG_DUMMY_LENGTH);
  1110. RtlCopyMemory(&Subkey[IPX_REG_KEY_CONFIG_LENGTH], &DeviceName->Buffer[StringLoc+1], DeviceName->Length - ((StringLoc+1) * sizeof(WCHAR)));
  1111. Subkey[IPX_REG_KEY_CONFIG_LENGTH + (DeviceName->Length / sizeof (WCHAR)) - (StringLoc+1) ] = L'\0';
  1112. IPX_DEBUG(CONFIG, ("Subkey:%ws\n", Subkey));
  1113. //RtlCopyMemory(&Subkey[10], &DeviceName->Buffer[StringLoc+1], DeviceName->MaximumLength - ((StringLoc+1) * sizeof(WCHAR)));
  1114. QueryTable[0].QueryRoutine = NULL;
  1115. QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  1116. QueryTable[0].Name = Subkey;
  1117. //
  1118. // 2) Call IpxGetFrameType for each part of the
  1119. // "PktType" multi-string.
  1120. //
  1121. QueryTable[1].QueryRoutine = IpxGetFrameType;
  1122. QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  1123. QueryTable[1].Name = L"PktType";
  1124. QueryTable[1].EntryContext = &FrameTypeCount;
  1125. QueryTable[1].DefaultType = REG_NONE;
  1126. //
  1127. // 3) Call IpxGetFrameType for each part of the
  1128. // "NetworkNumber" multi-string.
  1129. //
  1130. QueryTable[2].QueryRoutine = IpxGetFrameType;
  1131. QueryTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED;
  1132. QueryTable[2].Name = L"NetworkNumber";
  1133. QueryTable[2].EntryContext = &NetworkNumberCount;
  1134. QueryTable[2].DefaultType = REG_NONE;
  1135. //
  1136. // 4-11) Call IpxGetBindingValue for each of the keys we
  1137. // care about.
  1138. //
  1139. for (i = 0; i < BINDING_PARAMETERS; i++) {
  1140. QueryTable[i+3].QueryRoutine = IpxGetBindingValue;
  1141. QueryTable[i+3].Flags = 0;
  1142. QueryTable[i+3].Name = ParameterValues[i].KeyName;
  1143. QueryTable[i+3].EntryContext = UlongToPtr(i);
  1144. QueryTable[i+3].DefaultType = REG_DWORD;
  1145. QueryTable[i+3].DefaultData = (PVOID)(ParameterValues[i].DefaultValue);
  1146. QueryTable[i+3].DefaultLength = sizeof(ULONG);
  1147. }
  1148. //
  1149. // 12) Stop
  1150. //
  1151. QueryTable[BINDING_PARAMETERS+3].QueryRoutine = NULL;
  1152. QueryTable[BINDING_PARAMETERS+3].Flags = 0;
  1153. QueryTable[BINDING_PARAMETERS+3].Name = NULL;
  1154. IPX_DEBUG (CONFIG, ("Read bind key for %ws (%ws)\n", DeviceName->Buffer, Subkey));
  1155. Status = RtlQueryRegistryValues(
  1156. RTL_REGISTRY_ABSOLUTE,
  1157. Config->RegistryPathBuffer,
  1158. QueryTable,
  1159. (PVOID)Binding,
  1160. NULL);
  1161. if (Status != STATUS_SUCCESS) {
  1162. //
  1163. // The binding will get freed during cleanup.
  1164. //
  1165. IpxWriteGeneralErrorLog(
  1166. (PVOID)Config->DriverObject,
  1167. EVENT_IPX_ILLEGAL_CONFIG,
  1168. 906,
  1169. Status,
  1170. Subkey,
  1171. 0,
  1172. NULL);
  1173. return STATUS_DEVICE_CONFIGURATION_ERROR;
  1174. }
  1175. if (FrameTypeCount == 0) {
  1176. IpxWriteGeneralErrorLog(
  1177. (PVOID)Config->DriverObject,
  1178. EVENT_IPX_NO_FRAME_TYPES,
  1179. 907,
  1180. Status,
  1181. Subkey + 10,
  1182. 0,
  1183. NULL);
  1184. }
  1185. if (FrameTypeCount > NetworkNumberCount) {
  1186. for (i = NetworkNumberCount; i <FrameTypeCount; i++) {
  1187. Binding->NetworkNumber[i] = 0;
  1188. }
  1189. }
  1190. Binding->FrameTypeCount = FrameTypeCount;
  1191. //
  1192. // Go through and eliminate duplicates from the frame
  1193. // type array.
  1194. //
  1195. for (i = 0; i < Binding->FrameTypeCount; i++) {
  1196. for (j = i+1; j < Binding->FrameTypeCount; j++) {
  1197. if (Binding->FrameType[j] == Binding->FrameType[i]) {
  1198. IPX_DEBUG (CONFIG, ("Frame types %d and %d identical\n", i, j));
  1199. //
  1200. // A duplicate, slide everything else down.
  1201. //
  1202. for (k = j+1; k < Binding->FrameTypeCount; k++) {
  1203. Binding->FrameType[k-1] = Binding->FrameType[k];
  1204. Binding->NetworkNumber[k-1] = Binding->NetworkNumber[k];
  1205. }
  1206. --Binding->FrameTypeCount;
  1207. --j; // so we check whoever just moved into this spot.
  1208. }
  1209. }
  1210. }
  1211. //
  1212. // Mark all the explicitly configured frame types, and
  1213. // see if we have to auto-detect.
  1214. //
  1215. for (i = 0; i < 4; i++) {
  1216. FrameTypeUsed[i] = FALSE;
  1217. }
  1218. AutoDetect = FALSE;
  1219. for (i = 0; i < Binding->FrameTypeCount; i++) {
  1220. if ((Binding->FrameType[i] == ISN_FRAME_TYPE_AUTO)) {
  1221. AutoDetectLoc = i;
  1222. AutoDetect = TRUE;
  1223. } else {
  1224. Binding->AutoDetect[i] = FALSE;
  1225. Binding->DefaultAutoDetect[i] = FALSE;
  1226. FrameTypeUsed[Binding->FrameType[i]] = TRUE;
  1227. }
  1228. }
  1229. if (!AutoDetect) {
  1230. IPX_DEBUG (AUTO_DETECT, ("No bindings auto-detected\n"));
  1231. #if DBG
  1232. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  1233. IPX_DEBUG (AUTO_DETECT, ("%d: type %d, net %d, auto %d, default auto detect %d\n",
  1234. i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[i], Binding->DefaultAutoDetect[i]));
  1235. }
  1236. #endif
  1237. return STATUS_SUCCESS;
  1238. }
  1239. //
  1240. // Slide everything that is past the auto-detect point up
  1241. // to the end.
  1242. //
  1243. //
  1244. // Fixed this loop which can spill over if the FrameTypeCount is 4 and the SlideCount > 0.
  1245. // Here, the FrameTypeCount is 1-based, whereas the indices are 0-based, we need to make
  1246. // the index 1-based for this to work. So, instead of (3-Binding->FrameTypeCount), we use
  1247. // (4-Binding->FrameTypeCount). This loop copies all the non-auto-detect frametypes down to
  1248. // the bottom of the array to make space after the last auto-detect frame-type for filling
  1249. // in the frametypes in the preference order.
  1250. //
  1251. #if 0
  1252. SlideCount = Binding->FrameTypeCount - AutoDetectLoc - 1;
  1253. for (j = 3; j > 3 - SlideCount; j--) {
  1254. Binding->FrameType[j] = Binding->FrameType[j-(3-Binding->FrameTypeCount)];
  1255. Binding->NetworkNumber[j] = Binding->NetworkNumber[j-(3-Binding->FrameTypeCount)];
  1256. Binding->AutoDetect[j] = Binding->AutoDetect[j-(3-Binding->FrameTypeCount)];
  1257. Binding->DefaultAutoDetect[j] = Binding->DefaultAutoDetect[j-(3-Binding->FrameTypeCount)];
  1258. }
  1259. #else
  1260. SlideCount = Binding->FrameTypeCount - AutoDetectLoc - 1;
  1261. for (j = 3; j > 3 - SlideCount; j--) {
  1262. Binding->FrameType[j] = Binding->FrameType[j-(4-Binding->FrameTypeCount)];
  1263. Binding->NetworkNumber[j] = Binding->NetworkNumber[j-(4-Binding->FrameTypeCount)];
  1264. Binding->AutoDetect[j] = Binding->AutoDetect[j-(4-Binding->FrameTypeCount)];
  1265. Binding->DefaultAutoDetect[j] = Binding->DefaultAutoDetect[j-(4-Binding->FrameTypeCount)];
  1266. }
  1267. #endif
  1268. //
  1269. // Now fill in any frame types that are not hard-coded,
  1270. // this will start at AutoDetectLoc and exactly fill up
  1271. // the gap created when we slid things up above. We
  1272. // first put the default auto-detect at the first spot.
  1273. //
  1274. if (!FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]]) {
  1275. Binding->FrameType[AutoDetectLoc] = Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT];
  1276. Binding->NetworkNumber[AutoDetectLoc] = 0;
  1277. Binding->AutoDetect[AutoDetectLoc] = TRUE;
  1278. Binding->DefaultAutoDetect[AutoDetectLoc] = TRUE;
  1279. ++AutoDetectLoc;
  1280. FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]] = TRUE;
  1281. }
  1282. //
  1283. // Now fill in the array, using the preference order in
  1284. // the BindingPreference array (this comes into effect
  1285. // because the first frame type in our list that we
  1286. // find is used).
  1287. //
  1288. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  1289. if (!FrameTypeUsed[BindingPreference[i]]) {
  1290. Binding->FrameType[AutoDetectLoc] = BindingPreference[i];
  1291. Binding->NetworkNumber[AutoDetectLoc] = 0;
  1292. Binding->AutoDetect[AutoDetectLoc] = TRUE;
  1293. Binding->DefaultAutoDetect[AutoDetectLoc] = FALSE;
  1294. ++AutoDetectLoc;
  1295. }
  1296. }
  1297. Binding->FrameTypeCount = ISN_FRAME_TYPE_MAX;
  1298. #if DBG
  1299. for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
  1300. IPX_DEBUG (AUTO_DETECT, ("%d: type %d, net %d, auto %d, default auto detect %d\n",
  1301. i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[i], Binding->DefaultAutoDetect[i]));
  1302. }
  1303. #endif
  1304. return STATUS_SUCCESS;
  1305. } /* IpxPnPGetAdapterParameters */