|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1989-1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: stcnfg.c ! 8: ! 9: Abstract: ! 10: ! 11: This contains all routines necessary for the support of the dynamic ! 12: configuration of ST. ! 13: ! 14: Revision History: ! 15: ! 16: --*/ ! 17: ! 18: #include "st.h" ! 19: ! 20: ! 21: // ! 22: // Local functions used to access the registry. ! 23: // ! 24: ! 25: NTSTATUS ! 26: StConfigureTransport ( ! 27: IN PUNICODE_STRING RegistryPath, ! 28: IN PCONFIG_DATA * ConfigurationInfoPtr ! 29: ); ! 30: ! 31: VOID ! 32: StFreeConfigurationInfo ( ! 33: IN PCONFIG_DATA ConfigurationInfo ! 34: ); ! 35: ! 36: NTSTATUS ! 37: StOpenParametersKey( ! 38: IN HANDLE StConfigHandle, ! 39: OUT PHANDLE ParametersHandle ! 40: ); ! 41: ! 42: VOID ! 43: StCloseParametersKey( ! 44: IN HANDLE ParametersHandle ! 45: ); ! 46: ! 47: NTSTATUS ! 48: StCountEntries( ! 49: IN PWSTR ValueName, ! 50: IN ULONG ValueType, ! 51: IN PVOID ValueData, ! 52: IN ULONG ValueLength, ! 53: IN PVOID Context, ! 54: IN PVOID EntryContext ! 55: ); ! 56: ! 57: NTSTATUS ! 58: StAddBind( ! 59: IN PWSTR ValueName, ! 60: IN ULONG ValueType, ! 61: IN PVOID ValueData, ! 62: IN ULONG ValueLength, ! 63: IN PVOID Context, ! 64: IN PVOID EntryContext ! 65: ); ! 66: ! 67: NTSTATUS ! 68: StAddExport( ! 69: IN PWSTR ValueName, ! 70: IN ULONG ValueType, ! 71: IN PVOID ValueData, ! 72: IN ULONG ValueLength, ! 73: IN PVOID Context, ! 74: IN PVOID EntryContext ! 75: ); ! 76: ! 77: VOID ! 78: StReadLinkageInformation( ! 79: IN PWSTR RegistryPathBuffer, ! 80: IN PCONFIG_DATA * ConfigurationInfo ! 81: ); ! 82: ! 83: UINT ! 84: StReadSizeInformation( ! 85: IN HANDLE ParametersHandle ! 86: ); ! 87: ! 88: ULONG ! 89: StReadSingleParameter( ! 90: IN HANDLE ParametersHandle, ! 91: IN PWCHAR ValueName, ! 92: IN ULONG DefaultValue ! 93: ); ! 94: ! 95: VOID ! 96: StWriteSingleParameter( ! 97: IN HANDLE ParametersHandle, ! 98: IN PWCHAR ValueName, ! 99: IN ULONG ValueData ! 100: ); ! 101: ! 102: VOID ! 103: StSaveConfigInRegistry( ! 104: IN HANDLE ParametersHandle, ! 105: IN PCONFIG_DATA ConfigurationInfo ! 106: ); ! 107: ! 108: UINT ! 109: StWstrLength( ! 110: IN PWSTR Wstr ! 111: ); ! 112: ! 113: #ifdef ALLOC_PRAGMA ! 114: #pragma alloc_text(init,StWstrLength) ! 115: #pragma alloc_text(init,StConfigureTransport) ! 116: #pragma alloc_text(init,StFreeConfigurationInfo) ! 117: #pragma alloc_text(init,StOpenParametersKey) ! 118: #pragma alloc_text(init,StCloseParametersKey) ! 119: #pragma alloc_text(init,StCountEntries) ! 120: #pragma alloc_text(init,StAddBind) ! 121: #pragma alloc_text(init,StAddExport) ! 122: #pragma alloc_text(init,StReadLinkageInformation) ! 123: #pragma alloc_text(init,StReadSingleParameter) ! 124: #pragma alloc_text(init,StWriteSingleParameter) ! 125: #pragma alloc_text(init,StSaveConfigInRegistry) ! 126: #endif ! 127: ! 128: ! 129: UINT ! 130: StWstrLength( ! 131: IN PWSTR Wstr ! 132: ) ! 133: { ! 134: UINT Length = 0; ! 135: while (*Wstr++) { ! 136: Length += sizeof(WCHAR); ! 137: } ! 138: return Length; ! 139: } ! 140: ! 141: #define InsertAdapter(ConfigurationInfo, Subscript, Name) \ ! 142: { \ ! 143: PWSTR _S; \ ! 144: PWSTR _N = (Name); \ ! 145: UINT _L = StWstrLength(_N)+sizeof(WCHAR); \ ! 146: _S = (PWSTR)ExAllocatePool(NonPagedPool, _L); \ ! 147: if (_S != NULL) { \ ! 148: RtlCopyMemory(_S, _N, _L); \ ! 149: RtlInitUnicodeString (&(ConfigurationInfo)->Names[Subscript], _S); \ ! 150: } \ ! 151: } ! 152: ! 153: #define InsertDevice(ConfigurationInfo, Subscript, Name) \ ! 154: { \ ! 155: PWSTR _S; \ ! 156: PWSTR _N = (Name); \ ! 157: UINT _L = StWstrLength(_N)+sizeof(WCHAR); \ ! 158: _S = (PWSTR)ExAllocatePool(NonPagedPool, _L); \ ! 159: if (_S != NULL) { \ ! 160: RtlCopyMemory(_S, _N, _L); \ ! 161: RtlInitUnicodeString (&(ConfigurationInfo)->Names[(ConfigurationInfo)->DevicesOffset+Subscript], _S); \ ! 162: } \ ! 163: } ! 164: ! 165: ! 166: #define RemoveAdapter(ConfigurationInfo, Subscript) \ ! 167: ExFreePool ((ConfigurationInfo)->Names[Subscript].Buffer) ! 168: ! 169: #define RemoveDevice(ConfigurationInfo, Subscript) \ ! 170: ExFreePool ((ConfigurationInfo)->Names[(ConfigurationInfo)->DevicesOffset+Subscript].Buffer) ! 171: ! 172: ! 173: ! 174: // ! 175: // These strings are used in various places by the registry. ! 176: // ! 177: ! 178: #define DECLARE_STRING(_str_) STATIC WCHAR Str ## _str_[] = L#_str_ ! 179: ! 180: DECLARE_STRING(Large); ! 181: DECLARE_STRING(Medium); ! 182: DECLARE_STRING(Small); ! 183: ! 184: DECLARE_STRING(InitRequests); ! 185: DECLARE_STRING(InitConnections); ! 186: DECLARE_STRING(InitAddressFiles); ! 187: DECLARE_STRING(InitAddresses); ! 188: ! 189: DECLARE_STRING(MaxRequests); ! 190: DECLARE_STRING(MaxConnections); ! 191: DECLARE_STRING(MaxAddressFiles); ! 192: DECLARE_STRING(MaxAddresses); ! 193: ! 194: DECLARE_STRING(InitPackets); ! 195: DECLARE_STRING(InitReceivePackets); ! 196: DECLARE_STRING(InitReceiveBuffers); ! 197: ! 198: DECLARE_STRING(SendPacketPoolSize); ! 199: DECLARE_STRING(ReceivePacketPoolSize); ! 200: DECLARE_STRING(MaxMemoryUsage); ! 201: ! 202: ! 203: #define READ_HIDDEN_CONFIG(_Field) \ ! 204: { \ ! 205: ConfigurationInfo->_Field = \ ! 206: StReadSingleParameter( \ ! 207: ParametersHandle, \ ! 208: Str ## _Field, \ ! 209: ConfigurationInfo->_Field); \ ! 210: } ! 211: ! 212: #define WRITE_HIDDEN_CONFIG(_Field) \ ! 213: { \ ! 214: StWriteSingleParameter( \ ! 215: ParametersHandle, \ ! 216: Str ## _Field, \ ! 217: ConfigurationInfo->_Field); \ ! 218: } ! 219: ! 220: ! 221: ! 222: NTSTATUS ! 223: StConfigureTransport ( ! 224: IN PUNICODE_STRING RegistryPath, ! 225: IN PCONFIG_DATA * ConfigurationInfoPtr ! 226: ) ! 227: /*++ ! 228: ! 229: Routine Description: ! 230: ! 231: This routine is called by ST to get information from the configuration ! 232: management routines. We read the registry, starting at RegistryPath, ! 233: to get the parameters. If they don't exist, we use the defaults ! 234: set in nbfcnfg.h file. ! 235: ! 236: Arguments: ! 237: ! 238: RegistryPath - The name of ST's node in the registry. ! 239: ! 240: ConfigurationInfoPtr - A pointer to the configuration information structure. ! 241: ! 242: Return Value: ! 243: ! 244: Status - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES ! 245: otherwise. ! 246: ! 247: --*/ ! 248: { ! 249: ! 250: NTSTATUS OpenStatus; ! 251: HANDLE ParametersHandle; ! 252: UINT StSize; ! 253: HANDLE StConfigHandle; ! 254: NTSTATUS Status; ! 255: ULONG Disposition; ! 256: PWSTR RegistryPathBuffer; ! 257: OBJECT_ATTRIBUTES TmpObjectAttributes; ! 258: PCONFIG_DATA ConfigurationInfo; ! 259: ! 260: ! 261: // ! 262: // Open the registry. ! 263: // ! 264: ! 265: InitializeObjectAttributes( ! 266: &TmpObjectAttributes, ! 267: RegistryPath, // name ! 268: OBJ_CASE_INSENSITIVE, // attributes ! 269: NULL, // root ! 270: NULL // security descriptor ! 271: ); ! 272: ! 273: Status = ZwCreateKey( ! 274: &StConfigHandle, ! 275: KEY_WRITE, ! 276: &TmpObjectAttributes, ! 277: 0, // title index ! 278: NULL, // class ! 279: 0, // create options ! 280: &Disposition); // disposition ! 281: ! 282: if (!NT_SUCCESS(Status)) { ! 283: StPrint1("ST: Could not open/create ST key: %lx\n", Status); ! 284: return Status; ! 285: } ! 286: ! 287: ! 288: OpenStatus = StOpenParametersKey (StConfigHandle, &ParametersHandle); ! 289: ! 290: if (OpenStatus != STATUS_SUCCESS) { ! 291: return OpenStatus; ! 292: } ! 293: ! 294: // ! 295: // Read in the NDIS binding information (if none is present ! 296: // the array will be filled with all known drivers). ! 297: // ! 298: // StReadLinkageInformation expects a null-terminated path, ! 299: // so we have to create one from the UNICODE_STRING. ! 300: // ! 301: ! 302: RegistryPathBuffer = (PWSTR)ExAllocatePool( ! 303: NonPagedPool, ! 304: RegistryPath->Length + sizeof(WCHAR)); ! 305: if (RegistryPathBuffer == NULL) { ! 306: StCloseParametersKey (ParametersHandle); ! 307: return STATUS_INSUFFICIENT_RESOURCES; ! 308: } ! 309: RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length); ! 310: *(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0'; ! 311: ! 312: StReadLinkageInformation (RegistryPathBuffer, ConfigurationInfoPtr); ! 313: ! 314: if (*ConfigurationInfoPtr == NULL) { ! 315: ExFreePool (RegistryPathBuffer); ! 316: StCloseParametersKey (ParametersHandle); ! 317: return STATUS_INSUFFICIENT_RESOURCES; ! 318: } ! 319: ConfigurationInfo = *ConfigurationInfoPtr; ! 320: ! 321: ! 322: // ! 323: // Read the size parameter; this returns 0 if none is ! 324: // present, or 1 (Small), 2 (Medium) and 3 (Large). ! 325: // ! 326: ! 327: StSize = StReadSizeInformation (ParametersHandle); ! 328: ! 329: switch (StSize) { ! 330: ! 331: case 0: ! 332: case 1: ! 333: ! 334: // ! 335: // Default is Small. ! 336: // ! 337: ! 338: // ! 339: // These are the initial value used; the comment after ! 340: // each one shows the expected maximum (if every resource ! 341: // is at the expected maximum, ST should be very close ! 342: // to being out of memory). ! 343: // ! 344: // For now the "Max" values default to 0 (no limit). ! 345: // ! 346: ! 347: ConfigurationInfo->InitRequests = 5; // 30 ! 348: ConfigurationInfo->InitConnections = 1; // 10 ! 349: ConfigurationInfo->InitAddressFiles = 0; // 10 ! 350: ConfigurationInfo->InitAddresses = 0; // 10 ! 351: ! 352: // ! 353: // These are the initial values; remember that the ! 354: // resources above also allocate some of these each ! 355: // time they are allocated (shown in the comment). ! 356: // ! 357: ! 358: ConfigurationInfo->InitPackets = 30; // + link + conn (40) ! 359: ConfigurationInfo->InitReceivePackets = 10; // + link + addr (30) ! 360: ConfigurationInfo->InitReceiveBuffers = 5; // + addr (15) ! 361: ! 362: // ! 363: // Set the size of the packet pools and the total ! 364: // allocateable by ST. ! 365: // ! 366: ! 367: ConfigurationInfo->SendPacketPoolSize = 100; ! 368: ConfigurationInfo->ReceivePacketPoolSize = 30; ! 369: ConfigurationInfo->MaxMemoryUsage = 100000; ! 370: ! 371: break; ! 372: ! 373: case 2: ! 374: ! 375: // ! 376: // Medium ST. ! 377: // ! 378: ! 379: // ! 380: // These are the initial value used; the comment after ! 381: // each one shows the expected maximum (if every resource ! 382: // is at the expected maximum, ST should be very close ! 383: // to being out of memory). ! 384: // ! 385: // For now the "Max" values default to 0 (no limit). ! 386: // ! 387: ! 388: ConfigurationInfo->InitRequests = 10; // 100 ! 389: ConfigurationInfo->InitConnections = 2; // 64 ! 390: ConfigurationInfo->InitAddressFiles = 1; // 20 ! 391: ConfigurationInfo->InitAddresses = 1; // 20 ! 392: ! 393: // ! 394: // These are the initial values; remember that the ! 395: // resources above also allocate some of these each ! 396: // time they are allocated (shown in the comment). ! 397: // ! 398: ! 399: ConfigurationInfo->InitPackets = 50; // + link + conn (150) ! 400: ConfigurationInfo->InitReceivePackets = 15; // + link + addr (100) ! 401: ConfigurationInfo->InitReceiveBuffers = 10; // + addr (30) ! 402: ! 403: // ! 404: // Set the size of the packet pools and the total ! 405: // allocateable by ST. ! 406: // ! 407: ! 408: ConfigurationInfo->SendPacketPoolSize = 250; ! 409: ConfigurationInfo->ReceivePacketPoolSize = 100; ! 410: ConfigurationInfo->MaxMemoryUsage = 250000; ! 411: ! 412: break; ! 413: ! 414: case 3: ! 415: ! 416: // ! 417: // Big ST. ! 418: // ! 419: ! 420: // ! 421: // These are the initial value used. ! 422: // ! 423: // For now the "Max" values default to 0 (no limit). ! 424: // ! 425: ! 426: ConfigurationInfo->InitRequests = 15; ! 427: ConfigurationInfo->InitConnections = 3; ! 428: ConfigurationInfo->InitAddressFiles = 2; ! 429: ConfigurationInfo->InitAddresses = 2; ! 430: ! 431: // ! 432: // These are the initial values; remember that the ! 433: // resources above also allocate some of these each ! 434: // time they are allocated (shown in the comment). ! 435: // ! 436: ! 437: ConfigurationInfo->InitPackets = 75; // + link + conn ! 438: ConfigurationInfo->InitReceivePackets = 25; // + link + addr ! 439: ConfigurationInfo->InitReceiveBuffers = 20; // + addr ! 440: ! 441: // ! 442: // Set the size of the packet pools and the total ! 443: // allocateable by ST. ! 444: // ! 445: ! 446: ConfigurationInfo->SendPacketPoolSize = 500; ! 447: ConfigurationInfo->ReceivePacketPoolSize = 200; ! 448: ConfigurationInfo->MaxMemoryUsage = 0; // no limit ! 449: ! 450: break; ! 451: ! 452: default: ! 453: ! 454: ASSERT(FALSE); ! 455: break; ! 456: ! 457: } ! 458: ! 459: ! 460: // ! 461: // Now read the optional "hidden" parameters; if these do ! 462: // not exist then the current values are used. Note that ! 463: // the current values will be 0 unless they have been ! 464: // explicitly initialized above. ! 465: // ! 466: // NOTE: These macros expect "ConfigurationInfo" and ! 467: // "ParametersHandle" to exist when they are expanded. ! 468: // ! 469: ! 470: READ_HIDDEN_CONFIG (InitRequests); ! 471: READ_HIDDEN_CONFIG (InitConnections); ! 472: READ_HIDDEN_CONFIG (InitAddressFiles); ! 473: READ_HIDDEN_CONFIG (InitAddresses); ! 474: ! 475: READ_HIDDEN_CONFIG (MaxRequests); ! 476: READ_HIDDEN_CONFIG (MaxConnections); ! 477: READ_HIDDEN_CONFIG (MaxAddressFiles); ! 478: READ_HIDDEN_CONFIG (MaxAddresses); ! 479: ! 480: READ_HIDDEN_CONFIG (InitPackets); ! 481: READ_HIDDEN_CONFIG (InitReceivePackets); ! 482: READ_HIDDEN_CONFIG (InitReceiveBuffers); ! 483: ! 484: READ_HIDDEN_CONFIG (SendPacketPoolSize); ! 485: READ_HIDDEN_CONFIG (ReceivePacketPoolSize); ! 486: READ_HIDDEN_CONFIG (MaxMemoryUsage); ! 487: ! 488: ! 489: // ! 490: // Now that we are completely configured, save the information ! 491: // in the registry. ! 492: // ! 493: ! 494: StSaveConfigInRegistry (ParametersHandle, ConfigurationInfo); ! 495: ! 496: ExFreePool (RegistryPathBuffer); ! 497: StCloseParametersKey (ParametersHandle); ! 498: ZwClose (StConfigHandle); ! 499: ! 500: return STATUS_SUCCESS; ! 501: ! 502: } /* StConfigureTransport */ ! 503: ! 504: ! 505: VOID ! 506: StFreeConfigurationInfo ( ! 507: IN PCONFIG_DATA ConfigurationInfo ! 508: ) ! 509: ! 510: /*++ ! 511: ! 512: Routine Description: ! 513: ! 514: This routine is called by ST to get free any storage that was allocated ! 515: by StConfigureTransport in producing the specified CONFIG_DATA structure. ! 516: ! 517: Arguments: ! 518: ! 519: ConfigurationInfo - A pointer to the configuration information structure. ! 520: ! 521: Return Value: ! 522: ! 523: None. ! 524: ! 525: --*/ ! 526: { ! 527: UINT i; ! 528: ! 529: for (i=0; i<ConfigurationInfo->NumAdapters; i++) { ! 530: RemoveAdapter (ConfigurationInfo, i); ! 531: RemoveDevice (ConfigurationInfo, i); ! 532: } ! 533: ExFreePool (ConfigurationInfo); ! 534: ! 535: } /* StFreeConfigurationInfo */ ! 536: ! 537: ! 538: NTSTATUS ! 539: StOpenParametersKey( ! 540: IN HANDLE StConfigHandle, ! 541: OUT PHANDLE ParametersHandle ! 542: ) ! 543: ! 544: /*++ ! 545: ! 546: Routine Description: ! 547: ! 548: This routine is called by ST to open the ST "Parameters" key. ! 549: ! 550: Arguments: ! 551: ! 552: ParametersHandle - Returns the handle used to read parameters. ! 553: ! 554: Return Value: ! 555: ! 556: The status of the request. ! 557: ! 558: --*/ ! 559: { ! 560: ! 561: NTSTATUS Status; ! 562: HANDLE ParamHandle; ! 563: PWSTR ParametersString = L"Parameters"; ! 564: UNICODE_STRING ParametersKeyName; ! 565: OBJECT_ATTRIBUTES TmpObjectAttributes; ! 566: ! 567: // ! 568: // Open the ST parameters key. ! 569: // ! 570: ! 571: RtlInitUnicodeString (&ParametersKeyName, ParametersString); ! 572: ! 573: InitializeObjectAttributes( ! 574: &TmpObjectAttributes, ! 575: &ParametersKeyName, // name ! 576: OBJ_CASE_INSENSITIVE, // attributes ! 577: StConfigHandle, // root ! 578: NULL // security descriptor ! 579: ); ! 580: ! 581: ! 582: Status = ZwOpenKey( ! 583: &ParamHandle, ! 584: KEY_READ, ! 585: &TmpObjectAttributes); ! 586: ! 587: if (!NT_SUCCESS(Status)) { ! 588: ! 589: StPrint1("Could not open parameters key: %lx\n", Status); ! 590: return Status; ! 591: ! 592: } ! 593: ! 594: *ParametersHandle = ParamHandle; ! 595: ! 596: ! 597: // ! 598: // All keys successfully opened or created. ! 599: // ! 600: ! 601: return STATUS_SUCCESS; ! 602: ! 603: } /* StOpenParametersKey */ ! 604: ! 605: VOID ! 606: StCloseParametersKey( ! 607: IN HANDLE ParametersHandle ! 608: ) ! 609: ! 610: /*++ ! 611: ! 612: Routine Description: ! 613: ! 614: This routine is called by ST to close the "Parameters" key. ! 615: It closes the handles passed in and does any other work needed. ! 616: ! 617: Arguments: ! 618: ! 619: ParametersHandle - The handle used to read other parameters. ! 620: ! 621: Return Value: ! 622: ! 623: None. ! 624: ! 625: --*/ ! 626: ! 627: { ! 628: ! 629: ZwClose (ParametersHandle); ! 630: ! 631: } /* StCloseParametersKey */ ! 632: ! 633: ! 634: NTSTATUS ! 635: StCountEntries( ! 636: IN PWSTR ValueName, ! 637: IN ULONG ValueType, ! 638: IN PVOID ValueData, ! 639: IN ULONG ValueLength, ! 640: IN PVOID Context, ! 641: IN PVOID EntryContext ! 642: ) ! 643: ! 644: /*++ ! 645: ! 646: Routine Description: ! 647: ! 648: This routine is a callback routine for RtlQueryRegistryValues ! 649: It is called with the "Bind" and "Export" multi-strings. ! 650: It counts the number of name entries required in the ! 651: CONFIGURATION_DATA structure and then allocates it. ! 652: ! 653: Arguments: ! 654: ! 655: ValueName - The name of the value ("Bind" or "Export" -- ignored). ! 656: ! 657: ValueType - The type of the value (REG_MULTI_SZ -- ignored). ! 658: ! 659: ValueData - The null-terminated data for the value. ! 660: ! 661: ValueLength - The length of ValueData (ignored). ! 662: ! 663: Context - A pointer to a pointer to the ConfigurationInfo structure. ! 664: When the "Export" callback is made this is filled in ! 665: with the allocate structure. ! 666: ! 667: EntryContext - A pointer to a counter holding the total number ! 668: of name entries required. ! 669: ! 670: Return Value: ! 671: ! 672: STATUS_SUCCESS ! 673: ! 674: --*/ ! 675: ! 676: { ! 677: ULONG StringCount; ! 678: PWCHAR ValuePointer = (PWCHAR)ValueData; ! 679: PCONFIG_DATA * ConfigurationInfo = (PCONFIG_DATA *)Context; ! 680: PULONG TotalCount = ((PULONG)EntryContext); ! 681: ULONG OldTotalCount = *TotalCount; ! 682: ! 683: ASSERT (ValueType == REG_MULTI_SZ); ! 684: ! 685: // ! 686: // Count the number of strings in the multi-string; first ! 687: // check that it is NULL-terminated to make the rest ! 688: // easier. ! 689: // ! 690: ! 691: if ((ValueLength < 2) || ! 692: (ValuePointer[(ValueLength/2)-1] != (WCHAR)'\0')) { ! 693: return STATUS_INVALID_PARAMETER; ! 694: } ! 695: ! 696: StringCount = 0; ! 697: while (*ValuePointer != (WCHAR)'\0') { ! 698: while (*ValuePointer != (WCHAR)'\0') { ! 699: ++ValuePointer; ! 700: } ! 701: ++StringCount; ! 702: ++ValuePointer; ! 703: if ((ULONG)((PUCHAR)ValuePointer - (PUCHAR)ValueData) >= ValueLength) { ! 704: break; ! 705: } ! 706: } ! 707: ! 708: (*TotalCount) += StringCount; ! 709: ! 710: if (*ValueName == (WCHAR)'E') { ! 711: ! 712: // ! 713: // This is "Export", allocate the config data structure. ! 714: // ! 715: ! 716: *ConfigurationInfo = ExAllocatePool( ! 717: NonPagedPool, ! 718: sizeof (CONFIG_DATA) + ! 719: ((*TotalCount-1) * sizeof(NDIS_STRING))); ! 720: ! 721: if (*ConfigurationInfo == NULL) { ! 722: return STATUS_INSUFFICIENT_RESOURCES; ! 723: } ! 724: ! 725: RtlZeroMemory( ! 726: *ConfigurationInfo, ! 727: sizeof(CONFIG_DATA) + ((*TotalCount-1) * sizeof(NDIS_STRING))); ! 728: ! 729: (*ConfigurationInfo)->DevicesOffset = OldTotalCount; ! 730: ! 731: } ! 732: ! 733: return STATUS_SUCCESS; ! 734: ! 735: } /* StCountEntries */ ! 736: ! 737: ! 738: NTSTATUS ! 739: StAddBind( ! 740: IN PWSTR ValueName, ! 741: IN ULONG ValueType, ! 742: IN PVOID ValueData, ! 743: IN ULONG ValueLength, ! 744: IN PVOID Context, ! 745: IN PVOID EntryContext ! 746: ) ! 747: ! 748: /*++ ! 749: ! 750: Routine Description: ! 751: ! 752: This routine is a callback routine for RtlQueryRegistryValues ! 753: It is called for each piece of the "Bind" multi-string and ! 754: saves the information in a ConfigurationInfo structure. ! 755: ! 756: Arguments: ! 757: ! 758: ValueName - The name of the value ("Bind" -- ignored). ! 759: ! 760: ValueType - The type of the value (REG_SZ -- ignored). ! 761: ! 762: ValueData - The null-terminated data for the value. ! 763: ! 764: ValueLength - The length of ValueData (ignored). ! 765: ! 766: Context - A pointer to the ConfigurationInfo structure. ! 767: ! 768: EntryContext - A pointer to a count of binds that is incremented. ! 769: ! 770: Return Value: ! 771: ! 772: STATUS_SUCCESS ! 773: ! 774: --*/ ! 775: ! 776: { ! 777: PCONFIG_DATA ConfigurationInfo = *(PCONFIG_DATA *)Context; ! 778: PULONG CurBindNum = ((PULONG)EntryContext); ! 779: ! 780: UNREFERENCED_PARAMETER(ValueName); ! 781: UNREFERENCED_PARAMETER(ValueType); ! 782: UNREFERENCED_PARAMETER(ValueLength); ! 783: ! 784: InsertAdapter( ! 785: ConfigurationInfo, ! 786: *CurBindNum, ! 787: (PWSTR)(ValueData)); ! 788: ! 789: ++(*CurBindNum); ! 790: ! 791: return STATUS_SUCCESS; ! 792: ! 793: } /* StAddBind */ ! 794: ! 795: ! 796: NTSTATUS ! 797: StAddExport( ! 798: IN PWSTR ValueName, ! 799: IN ULONG ValueType, ! 800: IN PVOID ValueData, ! 801: IN ULONG ValueLength, ! 802: IN PVOID Context, ! 803: IN PVOID EntryContext ! 804: ) ! 805: ! 806: /*++ ! 807: ! 808: Routine Description: ! 809: ! 810: This routine is a callback routine for RtlQueryRegistryValues ! 811: It is called for each piece of the "Export" multi-string and ! 812: saves the information in a ConfigurationInfo structure. ! 813: ! 814: Arguments: ! 815: ! 816: ValueName - The name of the value ("Export" -- ignored). ! 817: ! 818: ValueType - The type of the value (REG_SZ -- ignored). ! 819: ! 820: ValueData - The null-terminated data for the value. ! 821: ! 822: ValueLength - The length of ValueData (ignored). ! 823: ! 824: Context - A pointer to the ConfigurationInfo structure. ! 825: ! 826: EntryContext - A pointer to a count of exports that is incremented. ! 827: ! 828: Return Value: ! 829: ! 830: STATUS_SUCCESS ! 831: ! 832: --*/ ! 833: ! 834: { ! 835: PCONFIG_DATA ConfigurationInfo = *(PCONFIG_DATA *)Context; ! 836: PULONG CurExportNum = ((PULONG)EntryContext); ! 837: ! 838: UNREFERENCED_PARAMETER(ValueName); ! 839: UNREFERENCED_PARAMETER(ValueType); ! 840: UNREFERENCED_PARAMETER(ValueLength); ! 841: ! 842: InsertDevice( ! 843: ConfigurationInfo, ! 844: *CurExportNum, ! 845: (PWSTR)(ValueData)); ! 846: ! 847: ++(*CurExportNum); ! 848: ! 849: return STATUS_SUCCESS; ! 850: ! 851: } /* StAddExport */ ! 852: ! 853: ! 854: VOID ! 855: StReadLinkageInformation( ! 856: IN PWSTR RegistryPathBuffer, ! 857: IN PCONFIG_DATA * ConfigurationInfo ! 858: ) ! 859: ! 860: /*++ ! 861: ! 862: Routine Description: ! 863: ! 864: This routine is called by ST to read its linkage information ! 865: from the registry. If there is none present, then ConfigData ! 866: is filled with a list of all the adapters that are known ! 867: to ST. ! 868: ! 869: Arguments: ! 870: ! 871: RegistryPathBuffer - The null-terminated root of the ST registry tree. ! 872: ! 873: ConfigurationInfo - Returns ST's current configuration. ! 874: ! 875: Return Value: ! 876: ! 877: None. ! 878: ! 879: --*/ ! 880: ! 881: { ! 882: ! 883: UINT ConfigBindings; ! 884: UINT NameCount = 0; ! 885: NTSTATUS Status; ! 886: RTL_QUERY_REGISTRY_TABLE QueryTable[6]; ! 887: PWSTR Subkey = L"Linkage"; ! 888: PWSTR Bind = L"Bind"; ! 889: PWSTR Export = L"Export"; ! 890: ULONG BindCount, ExportCount; ! 891: UINT i; ! 892: ! 893: ! 894: // ! 895: // Set up QueryTable to do the following: ! 896: // ! 897: ! 898: // ! 899: // 1) Switch to the Linkage key below ST ! 900: // ! 901: ! 902: QueryTable[0].QueryRoutine = NULL; ! 903: QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; ! 904: QueryTable[0].Name = Subkey; ! 905: ! 906: // ! 907: // 2) Call StCountEntries for the "Bind" multi-string ! 908: // ! 909: ! 910: QueryTable[1].QueryRoutine = StCountEntries; ! 911: QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; ! 912: QueryTable[1].Name = Bind; ! 913: QueryTable[1].EntryContext = (PVOID)&NameCount; ! 914: QueryTable[1].DefaultType = REG_NONE; ! 915: ! 916: // ! 917: // 3) Call StCountEntries for the "Export" multi-string ! 918: // ! 919: ! 920: QueryTable[2].QueryRoutine = StCountEntries; ! 921: QueryTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; ! 922: QueryTable[2].Name = Export; ! 923: QueryTable[2].EntryContext = (PVOID)&NameCount; ! 924: QueryTable[2].DefaultType = REG_NONE; ! 925: ! 926: // ! 927: // 4) Call StAddBind for each string in "Bind" ! 928: // ! 929: ! 930: QueryTable[3].QueryRoutine = StAddBind; ! 931: QueryTable[3].Flags = 0; ! 932: QueryTable[3].Name = Bind; ! 933: QueryTable[3].EntryContext = (PVOID)&BindCount; ! 934: QueryTable[3].DefaultType = REG_NONE; ! 935: ! 936: // ! 937: // 5) Call StAddExport for each string in "Export" ! 938: // ! 939: ! 940: QueryTable[4].QueryRoutine = StAddExport; ! 941: QueryTable[4].Flags = 0; ! 942: QueryTable[4].Name = Export; ! 943: QueryTable[4].EntryContext = (PVOID)&ExportCount; ! 944: QueryTable[4].DefaultType = REG_NONE; ! 945: ! 946: // ! 947: // 6) Stop ! 948: // ! 949: ! 950: QueryTable[5].QueryRoutine = NULL; ! 951: QueryTable[5].Flags = 0; ! 952: QueryTable[5].Name = NULL; ! 953: ! 954: ! 955: BindCount = 0; ! 956: ExportCount = 0; ! 957: ! 958: Status = RtlQueryRegistryValues( ! 959: RTL_REGISTRY_ABSOLUTE, ! 960: RegistryPathBuffer, ! 961: QueryTable, ! 962: (PVOID)ConfigurationInfo, ! 963: NULL); ! 964: ! 965: if (Status != STATUS_SUCCESS) { ! 966: return; ! 967: } ! 968: ! 969: // ! 970: // Make sure that BindCount and ExportCount match, if not ! 971: // remove the extras. ! 972: // ! 973: ! 974: if (BindCount < ExportCount) { ! 975: ! 976: for (i=BindCount; i<ExportCount; i++) { ! 977: RemoveDevice (*ConfigurationInfo, i); ! 978: } ! 979: ConfigBindings = BindCount; ! 980: ! 981: } else if (ExportCount < BindCount) { ! 982: ! 983: for (i=ExportCount; i<BindCount; i++) { ! 984: RemoveAdapter (*ConfigurationInfo, i); ! 985: } ! 986: ConfigBindings = ExportCount; ! 987: ! 988: } else { ! 989: ! 990: ConfigBindings = BindCount; // which is equal to ExportCount ! 991: ! 992: } ! 993: ! 994: (*ConfigurationInfo)->NumAdapters = ConfigBindings; ! 995: ! 996: } /* StReadLinkageInformation */ ! 997: ! 998: ! 999: UINT ! 1000: StReadSizeInformation( ! 1001: IN HANDLE ParametersHandle ! 1002: ) ! 1003: ! 1004: /*++ ! 1005: ! 1006: Routine Description: ! 1007: ! 1008: This routine is called by ST to read the Size information ! 1009: from the registry. ! 1010: ! 1011: Arguments: ! 1012: ! 1013: RegistryHandle - A pointer to the open registry. ! 1014: ! 1015: Return Value: ! 1016: ! 1017: 0 - no Size specified ! 1018: 1 - Small ! 1019: 2 - Medium ! 1020: 3 - Big / Large ! 1021: ! 1022: --*/ ! 1023: ! 1024: { ! 1025: ! 1026: UINT SizeToReturn; ! 1027: // STRING KeywordName; ! 1028: // PCONFIG_KEYWORD Keyword; ! 1029: ! 1030: ULONG InformationBuffer[16]; // declare ULONG to get it aligned ! 1031: PKEY_VALUE_FULL_INFORMATION Information = ! 1032: (PKEY_VALUE_FULL_INFORMATION)InformationBuffer; ! 1033: ULONG InformationLength; ! 1034: WCHAR SizeString[] = L"Size"; ! 1035: UNICODE_STRING SizeValueName; ! 1036: NTSTATUS Status; ! 1037: PUCHAR InformationData; ! 1038: ULONG InformationLong; ! 1039: ! 1040: ! 1041: // ! 1042: // Read the size parameter out of the registry. ! 1043: // ! 1044: ! 1045: RtlInitUnicodeString (&SizeValueName, SizeString); ! 1046: ! 1047: Status = ZwQueryValueKey( ! 1048: ParametersHandle, ! 1049: &SizeValueName, ! 1050: KeyValueFullInformation, ! 1051: (PVOID)Information, ! 1052: sizeof (InformationBuffer), ! 1053: &InformationLength); ! 1054: ! 1055: // ! 1056: // Compare to the expected values. ! 1057: // ! 1058: ! 1059: if (Status == STATUS_SUCCESS) { ! 1060: ! 1061: InformationData = ((PUCHAR)Information) + Information->DataOffset; ! 1062: InformationLong = *((PULONG)InformationData); ! 1063: ! 1064: if ((Information->DataLength == sizeof(ULONG)) && ! 1065: (InformationLong >= 1 && InformationLong <= 3)) { ! 1066: ! 1067: SizeToReturn = InformationLong; ! 1068: ! 1069: } else { ! 1070: ! 1071: if ((Information->DataLength >= 10) && ! 1072: (RtlCompareMemory (StrLarge, InformationData, 10) == 10)) { ! 1073: ! 1074: SizeToReturn = 3; ! 1075: ! 1076: } else if ((Information->DataLength >= 12) && ! 1077: (RtlCompareMemory (StrMedium, InformationData, 12) == 12)) { ! 1078: ! 1079: SizeToReturn = 2; ! 1080: ! 1081: } else if ((Information->DataLength >= 10) && ! 1082: (RtlCompareMemory (StrSmall, InformationData, 10) == 10)) { ! 1083: ! 1084: SizeToReturn = 1; ! 1085: ! 1086: } else { ! 1087: ! 1088: SizeToReturn = 0; ! 1089: ! 1090: } ! 1091: ! 1092: } ! 1093: ! 1094: } else { ! 1095: ! 1096: SizeToReturn = 0; ! 1097: ! 1098: } ! 1099: ! 1100: return SizeToReturn; ! 1101: ! 1102: } /* StReadSizeInformation */ ! 1103: ! 1104: ! 1105: ULONG ! 1106: StReadSingleParameter( ! 1107: IN HANDLE ParametersHandle, ! 1108: IN PWCHAR ValueName, ! 1109: IN ULONG DefaultValue ! 1110: ) ! 1111: ! 1112: /*++ ! 1113: ! 1114: Routine Description: ! 1115: ! 1116: This routine is called by ST to read a single parameter ! 1117: from the registry. If the parameter is found it is stored ! 1118: in Data. ! 1119: ! 1120: Arguments: ! 1121: ! 1122: ParametersHandle - A pointer to the open registry. ! 1123: ! 1124: ValueName - The name of the value to search for. ! 1125: ! 1126: DefaultValue - The default value. ! 1127: ! 1128: Return Value: ! 1129: ! 1130: The value to use; will be the default if the value is not ! 1131: found or is not in the correct range. ! 1132: ! 1133: --*/ ! 1134: ! 1135: { ! 1136: ULONG InformationBuffer[16]; // declare ULONG to get it aligned ! 1137: PKEY_VALUE_FULL_INFORMATION Information = ! 1138: (PKEY_VALUE_FULL_INFORMATION)InformationBuffer; ! 1139: UNICODE_STRING ValueKeyName; ! 1140: ULONG InformationLength; ! 1141: ULONG ReturnValue; ! 1142: NTSTATUS Status; ! 1143: ! 1144: RtlInitUnicodeString (&ValueKeyName, ValueName); ! 1145: ! 1146: Status = ZwQueryValueKey( ! 1147: ParametersHandle, ! 1148: &ValueKeyName, ! 1149: KeyValueFullInformation, ! 1150: (PVOID)Information, ! 1151: sizeof (InformationBuffer), ! 1152: &InformationLength); ! 1153: ! 1154: if ((Status == STATUS_SUCCESS) && (Information->DataLength == sizeof(ULONG))) { ! 1155: ! 1156: RtlCopyMemory( ! 1157: (PVOID)&ReturnValue, ! 1158: ((PUCHAR)Information) + Information->DataOffset, ! 1159: sizeof(ULONG)); ! 1160: ! 1161: if (ReturnValue < 0) { ! 1162: ! 1163: ReturnValue = DefaultValue; ! 1164: ! 1165: } ! 1166: ! 1167: } else { ! 1168: ! 1169: ReturnValue = DefaultValue; ! 1170: ! 1171: } ! 1172: ! 1173: return ReturnValue; ! 1174: ! 1175: } /* StReadSingleParameter */ ! 1176: ! 1177: ! 1178: VOID ! 1179: StWriteSingleParameter( ! 1180: IN HANDLE ParametersHandle, ! 1181: IN PWCHAR ValueName, ! 1182: IN ULONG ValueData ! 1183: ) ! 1184: ! 1185: /*++ ! 1186: ! 1187: Routine Description: ! 1188: ! 1189: This routine is called by ST to write a single parameter ! 1190: from the registry. ! 1191: ! 1192: Arguments: ! 1193: ! 1194: ParametersHandle - A pointer to the open registry. ! 1195: ! 1196: ValueName - The name of the value to store. ! 1197: ! 1198: ValueData - The data to store at the value. ! 1199: ! 1200: Return Value: ! 1201: ! 1202: None. ! 1203: ! 1204: --*/ ! 1205: ! 1206: { ! 1207: UNICODE_STRING ValueKeyName; ! 1208: NTSTATUS Status; ! 1209: ULONG TmpValueData = ValueData; ! 1210: ! 1211: RtlInitUnicodeString (&ValueKeyName, ValueName); ! 1212: ! 1213: Status = ZwSetValueKey( ! 1214: ParametersHandle, ! 1215: &ValueKeyName, ! 1216: 0, ! 1217: REG_DWORD, ! 1218: (PVOID)&TmpValueData, ! 1219: sizeof(ULONG)); ! 1220: ! 1221: if (!NT_SUCCESS(Status)) { ! 1222: StPrint1("ST: Could not write dword key: %lx\n", Status); ! 1223: } ! 1224: ! 1225: } /* StWriteSingleParameter */ ! 1226: ! 1227: ! 1228: VOID ! 1229: StSaveConfigInRegistry( ! 1230: IN HANDLE ParametersHandle, ! 1231: IN PCONFIG_DATA ConfigurationInfo ! 1232: ) ! 1233: ! 1234: /*++ ! 1235: ! 1236: Routine Description: ! 1237: ! 1238: This routine is called by ST to save its configuraition ! 1239: information in the registry. It saves the information if ! 1240: the registry structure did not exist before this boot. ! 1241: ! 1242: Arguments: ! 1243: ! 1244: ParametersHandle - The handle used to read other parameters. ! 1245: ! 1246: ConfigurationInfo - Describes ST's current configuration. ! 1247: ! 1248: Return Value: ! 1249: ! 1250: None. ! 1251: ! 1252: --*/ ! 1253: ! 1254: { ! 1255: ! 1256: // ! 1257: // Save the "hidden" parameters, these may not exist in ! 1258: // the registry. ! 1259: // ! 1260: // NOTE: These macros expect "ConfigurationInfo" and ! 1261: // "ParametersHandle" to exist when they are expanded. ! 1262: // ! 1263: ! 1264: // ! 1265: // Don't write the parameters that are set ! 1266: // based on Size, since otherwise these will overwrite ! 1267: // those values since hidden parameters are set up ! 1268: // after the Size-based configuration is done. ! 1269: // ! 1270: ! 1271: WRITE_HIDDEN_CONFIG (MaxRequests); ! 1272: WRITE_HIDDEN_CONFIG (MaxConnections); ! 1273: WRITE_HIDDEN_CONFIG (MaxAddressFiles); ! 1274: WRITE_HIDDEN_CONFIG (MaxAddresses); ! 1275: ! 1276: } /* StSaveConfigInRegistry */ ! 1277:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.