|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: initunlo.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains the code that is very specific to initialization ! 12: and unloading of the parallel driver. ! 13: ! 14: Author: ! 15: ! 16: Anthony V. Ercolano 1-Aug-1992 ! 17: ! 18: Environment: ! 19: ! 20: Kernel mode ! 21: ! 22: Revision History : ! 23: ! 24: --*/ ! 25: ! 26: #include <stddef.h> ! 27: #include "ntddk.h" ! 28: #include "par.h" ! 29: #include "parlog.h" ! 30: ! 31: ! 32: // ! 33: // This is the actual definition of ParDebugLevel. ! 34: // Note that it is only defined if this is a "debug" ! 35: // build. ! 36: // ! 37: #if DBG ! 38: extern ULONG ParDebugLevel = 0; ! 39: #endif ! 40: ! 41: // ! 42: // Give a timeout of 300 seconds. Some postscript printers will ! 43: // buffer up a lot of commands then proceed to render what they ! 44: // have. The printer will then refuse to accept any characters ! 45: // until it's done with the rendering. This render process can ! 46: // take a while. We'll give it 300 seconds. ! 47: // ! 48: // Note that an application can change this value. ! 49: // ! 50: #define PAR_WRITE_TIMEOUT_VALUE 300 ! 51: ! 52: static const PHYSICAL_ADDRESS ParPhysicalZero = {0}; ! 53: ! 54: NTSTATUS ! 55: DriverEntry( ! 56: IN PDRIVER_OBJECT DriverObject, ! 57: IN PUNICODE_STRING RegistryPath ! 58: ); ! 59: ! 60: NTSTATUS ! 61: ParInitializeController( ! 62: IN PDRIVER_OBJECT DriverObject, ! 63: IN PCONFIG_DATA ConfigData ! 64: ); ! 65: ! 66: NTSTATUS ! 67: ParItemCallBack( ! 68: IN PVOID Context, ! 69: IN PUNICODE_STRING PathName, ! 70: IN INTERFACE_TYPE BusType, ! 71: IN ULONG BusNumber, ! 72: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 73: IN CONFIGURATION_TYPE ControllerType, ! 74: IN ULONG ControllerNumber, ! 75: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 76: IN CONFIGURATION_TYPE PeripheralType, ! 77: IN ULONG PeripheralNumber, ! 78: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 79: ); ! 80: ! 81: NTSTATUS ! 82: ParConfigCallBack( ! 83: IN PVOID Context, ! 84: IN PUNICODE_STRING PathName, ! 85: IN INTERFACE_TYPE BusType, ! 86: IN ULONG BusNumber, ! 87: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 88: IN CONFIGURATION_TYPE ControllerType, ! 89: IN ULONG ControllerNumber, ! 90: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 91: IN CONFIGURATION_TYPE PeripheralType, ! 92: IN ULONG PeripheralNumber, ! 93: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 94: ); ! 95: ! 96: VOID ! 97: ParGetConfigInfo( ! 98: IN PDRIVER_OBJECT DriverObject, ! 99: IN PUNICODE_STRING RegistryPath, ! 100: OUT PLIST_ENTRY ConfigList ! 101: ); ! 102: ! 103: BOOLEAN ! 104: ParPutInConfigList( ! 105: IN PDRIVER_OBJECT DriverObject, ! 106: IN OUT PLIST_ENTRY ConfigList, ! 107: IN PCONFIG_DATA New ! 108: ); ! 109: ! 110: PVOID ! 111: ParGetMappedAddress( ! 112: IN INTERFACE_TYPE BusType, ! 113: IN ULONG BusNumber, ! 114: PHYSICAL_ADDRESS IoAddress, ! 115: ULONG NumberOfBytes, ! 116: ULONG AddressSpace, ! 117: PBOOLEAN MappedAddress ! 118: ); ! 119: ! 120: VOID ! 121: ParSetupExternalNaming( ! 122: IN PPAR_DEVICE_EXTENSION Extension ! 123: ); ! 124: ! 125: VOID ! 126: ParCleanupDevice( ! 127: IN PPAR_DEVICE_EXTENSION Extension ! 128: ); ! 129: ! 130: VOID ! 131: ParCleanupExternalNaming( ! 132: IN PPAR_DEVICE_EXTENSION Extension ! 133: ); ! 134: ! 135: typedef enum _PAR_MEM_COMPARES { ! 136: AddressesAreEqual, ! 137: AddressesOverlap, ! 138: AddressesAreDisjoint ! 139: } PAR_MEM_COMPARES,*PPAR_MEM_COMPARES; ! 140: ! 141: PAR_MEM_COMPARES ! 142: ParMemCompare( ! 143: IN PHYSICAL_ADDRESS A, ! 144: IN ULONG SpanOfA, ! 145: IN PHYSICAL_ADDRESS B, ! 146: IN ULONG SpanOfB ! 147: ); ! 148: ! 149: ! 150: VOID ! 151: ParUnReportResourcesDevice( ! 152: IN PPAR_DEVICE_EXTENSION Extension ! 153: ); ! 154: ! 155: VOID ! 156: ParReportResourcesDevice( ! 157: IN PPAR_DEVICE_EXTENSION Extension, ! 158: IN BOOLEAN ClaimInterrupt, ! 159: OUT BOOLEAN *ConflictDetected ! 160: ); ! 161: ! 162: #ifdef ALLOC_PRAGMA ! 163: #pragma alloc_text(init,DriverEntry) ! 164: #pragma alloc_text(init,ParInitializeController) ! 165: #pragma alloc_text(init,ParItemCallBack) ! 166: #pragma alloc_text(init,ParConfigCallBack) ! 167: #pragma alloc_text(init,ParGetConfigInfo) ! 168: #pragma alloc_text(init,ParPutInConfigList) ! 169: #pragma alloc_text(init,ParGetMappedAddress) ! 170: #pragma alloc_text(init,ParSetupExternalNaming) ! 171: #pragma alloc_text(init,ParReportResourcesDevice) ! 172: #endif ! 173: ! 174: NTSTATUS ! 175: DriverEntry( ! 176: IN PDRIVER_OBJECT DriverObject, ! 177: IN PUNICODE_STRING RegistryPath ! 178: ) ! 179: ! 180: /*++ ! 181: ! 182: Routine Description: ! 183: ! 184: The entry point that the system point calls to initialize ! 185: any driver. ! 186: ! 187: This path will gather the configuration information, ! 188: attempt to initialize all driver data structures, ! 189: connect to interrupts for ports. If the above ! 190: goes reasonably well it will fill in the dispatch points, ! 191: reset the parallel devices and then return to the system. ! 192: ! 193: Arguments: ! 194: ! 195: DriverObject - Just what it says, really of little use ! 196: to the driver itself, it is something that the IO system ! 197: cares more about. ! 198: ! 199: PathToRegistry - points to the entry for this driver ! 200: in the current control set of the registry. ! 201: ! 202: Return Value: ! 203: ! 204: STATUS_SUCCESS if we could initialize a single device, ! 205: otherwise STATUS_NO_SUCH_DEVICE. ! 206: ! 207: --*/ ! 208: ! 209: { ! 210: ! 211: // ! 212: // Holds status information return by various OS and driver ! 213: // initialization routines. ! 214: // ! 215: NTSTATUS status; ! 216: ! 217: // ! 218: // List head for configuration records. ! 219: // ! 220: LIST_ENTRY configList; ! 221: ! 222: // ! 223: // We use this to query into the registry as to whether we ! 224: // should break at driver entry. ! 225: // ! 226: RTL_QUERY_REGISTRY_TABLE paramTable[3]; ! 227: ULONG zero = 0; ! 228: ULONG debugLevel = 0; ! 229: ULONG shouldBreak = 0; ! 230: PWCHAR path; ! 231: ! 232: // ! 233: // Since the registry path parameter is a "counted" UNICODE string, it ! 234: // might not be zero terminated. For a very short time allocate memory ! 235: // to hold the registry path zero terminated so that we can use it to ! 236: // delve into the registry. ! 237: // ! 238: // NOTE NOTE!!!! This is not an architected way of breaking into ! 239: // a driver. It happens to work for this driver because the author ! 240: // likes to do things this way. ! 241: // ! 242: ! 243: if (path = ExAllocatePool( ! 244: PagedPool, ! 245: RegistryPath->Length+sizeof(WCHAR) ! 246: )) { ! 247: ! 248: RtlZeroMemory( ! 249: ¶mTable[0], ! 250: sizeof(paramTable) ! 251: ); ! 252: RtlZeroMemory( ! 253: path, ! 254: RegistryPath->Length+sizeof(WCHAR) ! 255: ); ! 256: RtlMoveMemory( ! 257: path, ! 258: RegistryPath->Buffer, ! 259: RegistryPath->Length ! 260: ); ! 261: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 262: paramTable[0].Name = L"BreakOnEntry"; ! 263: paramTable[0].EntryContext = &shouldBreak; ! 264: paramTable[0].DefaultType = REG_DWORD; ! 265: paramTable[0].DefaultData = &zero; ! 266: paramTable[0].DefaultLength = sizeof(ULONG); ! 267: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 268: paramTable[1].Name = L"DebugLevel"; ! 269: paramTable[1].EntryContext = &debugLevel; ! 270: paramTable[1].DefaultType = REG_DWORD; ! 271: paramTable[1].DefaultData = &zero; ! 272: paramTable[1].DefaultLength = sizeof(ULONG); ! 273: ! 274: if (!NT_SUCCESS(RtlQueryRegistryValues( ! 275: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, ! 276: path, ! 277: ¶mTable[0], ! 278: NULL, ! 279: NULL ! 280: ))) { ! 281: ! 282: shouldBreak = 0; ! 283: debugLevel = 0; ! 284: ! 285: } ! 286: ! 287: } ! 288: ! 289: // ! 290: // We don't need that path anymore. ! 291: // ! 292: ! 293: if (path) { ! 294: ! 295: ExFreePool(path); ! 296: ! 297: } ! 298: ! 299: #if DBG ! 300: ParDebugLevel = debugLevel; ! 301: #endif ! 302: ! 303: if (shouldBreak) { ! 304: ! 305: DbgBreakPoint(); ! 306: ! 307: } ! 308: ! 309: ParGetConfigInfo( ! 310: DriverObject, ! 311: RegistryPath, ! 312: &configList ! 313: ); ! 314: ! 315: // ! 316: // Initialize each item in the list of configuration records. ! 317: // ! 318: ! 319: while (!IsListEmpty(&configList)) { ! 320: ! 321: PCONFIG_DATA currentConfig; ! 322: PLIST_ENTRY head; ! 323: ! 324: head = RemoveHeadList(&configList); ! 325: ! 326: currentConfig = CONTAINING_RECORD( ! 327: head, ! 328: CONFIG_DATA, ! 329: ConfigList ! 330: ); ! 331: ! 332: ParInitializeController( ! 333: DriverObject, ! 334: currentConfig ! 335: ); ! 336: ! 337: } ! 338: ! 339: if (DriverObject->DeviceObject) { ! 340: ! 341: status = STATUS_SUCCESS; ! 342: ! 343: // ! 344: // Initialize the Driver Object with driver's entry points ! 345: // ! 346: ! 347: DriverObject->MajorFunction[IRP_MJ_WRITE] = ParDispatch; ! 348: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ParDispatch; ! 349: DriverObject->MajorFunction[IRP_MJ_CREATE] = ParCreateOpen; ! 350: DriverObject->MajorFunction[IRP_MJ_CLOSE] = ParClose; ! 351: DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ParCleanup; ! 352: DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = ! 353: ParQueryInformationFile; ! 354: DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = ! 355: ParSetInformationFile; ! 356: DriverObject->DriverUnload = ParUnload; ! 357: ! 358: } else { ! 359: ! 360: status = STATUS_NO_SUCH_DEVICE; ! 361: ! 362: } ! 363: ! 364: return status; ! 365: } ! 366: ! 367: NTSTATUS ! 368: ParInitializeController( ! 369: IN PDRIVER_OBJECT DriverObject, ! 370: IN PCONFIG_DATA ConfigData ! 371: ) ! 372: ! 373: /*++ ! 374: ! 375: Routine Description: ! 376: ! 377: Really too many things to mention here. In general, it forms ! 378: and sets up names, creates the device, translates bus relative ! 379: items... ! 380: ! 381: ! 382: Arguments: ! 383: ! 384: DriverObject - Just used to create the device object. ! 385: ! 386: ConfigData - Pointer to a record for a single port. ! 387: ! 388: NOTE: This routine will deallocate the config data. ! 389: ! 390: Return Value: ! 391: ! 392: STATUS_SUCCCESS if everything went ok. A !NT_SUCCESS status ! 393: otherwise. ! 394: ! 395: --*/ ! 396: ! 397: { ! 398: ! 399: // ! 400: // This will hold the string that we need to use to describe ! 401: // the name of the device to the IO system. ! 402: // ! 403: UNICODE_STRING uniNameString; ! 404: ! 405: // ! 406: // Holds the NT Status that is returned from each call to the ! 407: // kernel and executive. ! 408: // ! 409: NTSTATUS status = STATUS_SUCCESS; ! 410: ! 411: // ! 412: // Points to the device object (not the extension) created ! 413: // for this device. ! 414: // ! 415: PDEVICE_OBJECT deviceObject; ! 416: ! 417: // ! 418: // Points to the device extension for the device object ! 419: // (see above) created for the device we are initializing. ! 420: // ! 421: PPAR_DEVICE_EXTENSION extension = NULL; ! 422: ! 423: // ! 424: // Passed back from the resource reporting code to indicate ! 425: // whether the requested resources are already being used by ! 426: // another device. ! 427: // ! 428: BOOLEAN conflict; ! 429: ! 430: ! 431: ParDump( ! 432: PARCONFIG, ! 433: ("PARALLEL: Initializing for configuration record of %wZ\n", ! 434: &ConfigData->NtNameForPort) ! 435: ); ! 436: ! 437: // ! 438: // Form a name like \Device\Parallel0. ! 439: // ! 440: // First we allocate space for the name. ! 441: // ! 442: ! 443: RtlInitUnicodeString( ! 444: &uniNameString, ! 445: NULL ! 446: ); ! 447: ! 448: uniNameString.MaximumLength = sizeof(L"\\Device\\") + ! 449: ConfigData->NtNameForPort.Length+sizeof(WCHAR); ! 450: uniNameString.Buffer = ExAllocatePool( ! 451: PagedPool, ! 452: uniNameString.MaximumLength ! 453: ); ! 454: ! 455: // ! 456: // The only reason the above could have failed is if ! 457: // there wasn't enough system memory to form the UNICODE ! 458: // string. ! 459: // ! 460: ! 461: if (!uniNameString.Buffer) { ! 462: ! 463: ParLogError( ! 464: DriverObject, ! 465: NULL, ! 466: ConfigData->Controller, ! 467: ParPhysicalZero, ! 468: 0, ! 469: 0, ! 470: 0, ! 471: 2, ! 472: STATUS_SUCCESS, ! 473: PAR_INSUFFICIENT_RESOURCES ! 474: ); ! 475: ParDump( ! 476: PARERRORS, ! 477: ("PARALLEL: Could not form Unicode name string for %wZ\n", ! 478: &ConfigData->NtNameForPort) ! 479: ); ! 480: ExFreePool(ConfigData->ObjectDirectory.Buffer); ! 481: ExFreePool(ConfigData->NtNameForPort.Buffer); ! 482: ExFreePool(ConfigData->SymbolicLinkName.Buffer); ! 483: ExFreePool(ConfigData); ! 484: return STATUS_INSUFFICIENT_RESOURCES; ! 485: ! 486: } ! 487: ! 488: // ! 489: // Actually form the Name. ! 490: // ! 491: ! 492: RtlZeroMemory( ! 493: uniNameString.Buffer, ! 494: uniNameString.MaximumLength ! 495: ); ! 496: ! 497: RtlAppendUnicodeToString( ! 498: &uniNameString, ! 499: L"\\Device\\" ! 500: ); ! 501: ! 502: RtlAppendUnicodeStringToString( ! 503: &uniNameString, ! 504: &ConfigData->NtNameForPort ! 505: ); ! 506: ! 507: // ! 508: // Create the device object for this device. ! 509: // ! 510: ! 511: status = IoCreateDevice( ! 512: DriverObject, ! 513: sizeof(PAR_DEVICE_EXTENSION), ! 514: &uniNameString, ! 515: FILE_DEVICE_PARALLEL_PORT, ! 516: 0, ! 517: TRUE, ! 518: &deviceObject ! 519: ); ! 520: ! 521: // ! 522: // If we couldn't create the device object, then there ! 523: // is no point in going on. ! 524: // ! 525: ! 526: if (!NT_SUCCESS(status)) { ! 527: ! 528: ParLogError( ! 529: DriverObject, ! 530: NULL, ! 531: ConfigData->Controller, ! 532: ParPhysicalZero, ! 533: 0, ! 534: 0, ! 535: 0, ! 536: 3, ! 537: STATUS_SUCCESS, ! 538: PAR_INSUFFICIENT_RESOURCES ! 539: ); ! 540: ParDump( ! 541: PARERRORS, ! 542: ("PARALLEL: Could not create a device for %wZ\n", ! 543: &ConfigData->NtNameForPort) ! 544: ); ! 545: ExFreePool(ConfigData->ObjectDirectory.Buffer); ! 546: ExFreePool(ConfigData->NtNameForPort.Buffer); ! 547: ExFreePool(ConfigData->SymbolicLinkName.Buffer); ! 548: ExFreePool(ConfigData); ! 549: ExFreePool(uniNameString.Buffer); ! 550: return STATUS_INSUFFICIENT_RESOURCES; ! 551: ! 552: } ! 553: ! 554: // ! 555: // We have created the device, increment the counter in the ! 556: // IO system that keep track. Anyplace that we do an IoDeleteDevice ! 557: // we need to decrement. ! 558: // ! 559: ! 560: IoGetConfigurationInformation()->ParallelCount++; ! 561: ! 562: // ! 563: // The device object has a pointer to an area of non-paged ! 564: // pool allocated for this device. This will be the device ! 565: // extension. ! 566: // ! 567: ! 568: extension = deviceObject->DeviceExtension; ! 569: ! 570: // ! 571: // Zero all of the memory associated with the device ! 572: // extension. ! 573: // ! 574: ! 575: RtlZeroMemory( ! 576: extension, ! 577: sizeof(PAR_DEVICE_EXTENSION) ! 578: ); ! 579: ! 580: // ! 581: // Save off our name. ! 582: // ! 583: ! 584: RtlInitUnicodeString( ! 585: &extension->DeviceName, ! 586: NULL ! 587: ); ! 588: ! 589: extension->DeviceName.Length = uniNameString.Length; ! 590: extension->DeviceName.MaximumLength = uniNameString.MaximumLength; ! 591: extension->DeviceName.Buffer = uniNameString.Buffer; ! 592: ! 593: // ! 594: // Just initialize the names so that we don't try ! 595: // to "clean" them up if we cant intialize the ! 596: // controller all the way. ! 597: // ! 598: ! 599: RtlInitUnicodeString( ! 600: &extension->ObjectDirectory, ! 601: NULL ! 602: ); ! 603: RtlInitUnicodeString( ! 604: &extension->NtNameForPort, ! 605: NULL ! 606: ); ! 607: RtlInitUnicodeString( ! 608: &extension->SymbolicLinkName, ! 609: NULL ! 610: ); ! 611: ! 612: // ! 613: // Get a "back pointer" to the device object and specify ! 614: // that this driver only supports buffered IO. This basically ! 615: // means that the IO system copies the users data to and from ! 616: // system supplied buffers. ! 617: // ! 618: ! 619: extension->DeviceObject = deviceObject; ! 620: deviceObject->Flags |= DO_BUFFERED_IO; ! 621: ! 622: // ! 623: // Map the memory for the control registers for the parallel device ! 624: // into virtual memory. ! 625: // ! 626: ! 627: extension->Controller = ParGetMappedAddress( ! 628: ConfigData->InterfaceType, ! 629: ConfigData->BusNumber, ! 630: ConfigData->Controller, ! 631: ConfigData->SpanOfController, ! 632: (BOOLEAN)ConfigData->AddressSpace, ! 633: &extension->UnMapRegisters ! 634: ); ! 635: ! 636: if (!extension->Controller) { ! 637: ! 638: ParLogError( ! 639: deviceObject->DriverObject, ! 640: deviceObject, ! 641: ConfigData->Controller, ! 642: ParPhysicalZero, ! 643: 0, ! 644: 0, ! 645: 0, ! 646: 4, ! 647: STATUS_SUCCESS, ! 648: PAR_REGISTERS_NOT_MAPPED ! 649: ); ! 650: ParDump( ! 651: PARERRORS, ! 652: ("PARALLEL: Could not map memory for device registers for %wZ\n", ! 653: &ConfigData->NtNameForPort) ! 654: ); ! 655: extension->UnMapRegisters = FALSE; ! 656: status = STATUS_NONE_MAPPED; ! 657: goto ExtensionCleanup; ! 658: ! 659: } ! 660: ! 661: extension->AddressSpace = ConfigData->AddressSpace; ! 662: extension->OriginalController = ConfigData->Controller; ! 663: extension->SpanOfController = ConfigData->SpanOfController; ! 664: ! 665: // ! 666: // Save off the interface type and the bus number. ! 667: // ! 668: ! 669: extension->InterfaceType = ConfigData->InterfaceType; ! 670: extension->BusNumber = ConfigData->BusNumber; ! 671: ! 672: // ! 673: // We now try to claim the ports used by this device. ! 674: // ! 675: ! 676: ParReportResourcesDevice( ! 677: extension, ! 678: FALSE, ! 679: &conflict ! 680: ); ! 681: ! 682: if (conflict) { ! 683: ! 684: status = STATUS_NO_SUCH_DEVICE; ! 685: ParLogError( ! 686: deviceObject->DriverObject, ! 687: deviceObject, ! 688: ConfigData->Controller, ! 689: ParPhysicalZero, ! 690: 0, ! 691: 0, ! 692: 0, ! 693: 5, ! 694: STATUS_SUCCESS, ! 695: PAR_ADDRESS_CONFLICT ! 696: ); ! 697: ParDump( ! 698: PARERRORS, ! 699: ("PARALLEL: Could not claim the device registers for %wZ\n", ! 700: &ConfigData->NtNameForPort) ! 701: ); ! 702: goto ExtensionCleanup; ! 703: ! 704: } ! 705: ! 706: // ! 707: // Disable the device from interrupting. ! 708: // ! 709: ! 710: StoreControl( ! 711: extension->Controller, ! 712: (UCHAR)PAR_CONTROL_WR_CONTROL ! 713: ); ! 714: KeStallExecutionProcessor(60); ! 715: ! 716: // ! 717: // If it was requested that the port be disabled, now is the ! 718: // time to do it. ! 719: // ! 720: ! 721: if (ConfigData->DisablePort) { ! 722: ! 723: ! 724: status = STATUS_NO_SUCH_DEVICE; ! 725: ParLogError( ! 726: deviceObject->DriverObject, ! 727: deviceObject, ! 728: ConfigData->Controller, ! 729: ParPhysicalZero, ! 730: 0, ! 731: 0, ! 732: 0, ! 733: 40, ! 734: STATUS_SUCCESS, ! 735: PAR_DISABLED_PORT ! 736: ); ! 737: ParDump( ! 738: PARERRORS, ! 739: ("PARALLEL: Port %wZ disabled as requested\n", ! 740: &ConfigData->NtNameForPort) ! 741: ); ! 742: goto ExtensionCleanup; ! 743: } ! 744: ! 745: // ! 746: // The call will set up the naming necessary for ! 747: // external applications to get to the driver. It ! 748: // will also set up the device map. ! 749: // ! 750: ! 751: extension->ObjectDirectory = ConfigData->ObjectDirectory; ! 752: extension->NtNameForPort = ConfigData->NtNameForPort; ! 753: extension->SymbolicLinkName = ConfigData->SymbolicLinkName; ! 754: ParSetupExternalNaming(extension); ! 755: ! 756: extension->Initialized = FALSE; ! 757: extension->AutoFeed = FALSE; ! 758: extension->TimerStart = PAR_WRITE_TIMEOUT_VALUE; ! 759: InitializeListHead(&extension->WorkQueue); ! 760: ! 761: extension->AbsoluteOneSecond = RtlConvertUlongToLargeInteger(10*1000*1000); ! 762: extension->OneSecond = RtlLargeIntegerNegate( ! 763: RtlConvertUlongToLargeInteger(10*1000*1000) ! 764: ); ! 765: ! 766: KeInitializeSemaphore( ! 767: &extension->RequestSemaphore, ! 768: 0L, ! 769: MAXLONG ! 770: ); ! 771: ! 772: // ! 773: // Common error path cleanup. If the status is ! 774: // bad, get rid of the device extension, device object ! 775: // and any memory associated with it. ! 776: // ! 777: ! 778: ExtensionCleanup: ; ! 779: ! 780: ExFreePool(ConfigData); ! 781: ! 782: if (NT_ERROR(status)) { ! 783: ! 784: if (extension) { ! 785: ! 786: ParCleanupDevice(extension); ! 787: IoDeleteDevice(deviceObject); ! 788: IoGetConfigurationInformation()->ParallelCount--; ! 789: ! 790: ! 791: } ! 792: ! 793: } ! 794: ! 795: return status; ! 796: ! 797: } ! 798: ! 799: NTSTATUS ! 800: ParItemCallBack( ! 801: IN PVOID Context, ! 802: IN PUNICODE_STRING PathName, ! 803: IN INTERFACE_TYPE BusType, ! 804: IN ULONG BusNumber, ! 805: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 806: IN CONFIGURATION_TYPE ControllerType, ! 807: IN ULONG ControllerNumber, ! 808: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 809: IN CONFIGURATION_TYPE PeripheralType, ! 810: IN ULONG PeripheralNumber, ! 811: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 812: ) ! 813: ! 814: /*++ ! 815: ! 816: Routine Description: ! 817: ! 818: This routine is called to check if a particular item ! 819: is present in the registry. ! 820: ! 821: Arguments: ! 822: ! 823: Context - Pointer to a boolean. ! 824: ! 825: PathName - unicode registry path. Not Used. ! 826: ! 827: BusType - Internal, Isa, ... ! 828: ! 829: BusNumber - Which bus if we are on a multibus system. ! 830: ! 831: BusInformation - Configuration information about the bus. Not Used. ! 832: ! 833: ControllerType - Controller type. ! 834: ! 835: ControllerNumber - Which controller if there is more than one ! 836: controller in the system. ! 837: ! 838: ControllerInformation - Array of pointers to the three pieces of ! 839: registry information. ! 840: ! 841: PeripheralType - Should be a peripheral. ! 842: ! 843: PeripheralNumber - Which peripheral - not used.. ! 844: ! 845: PeripheralInformation - Configuration information. Not Used. ! 846: ! 847: Return Value: ! 848: ! 849: STATUS_SUCCESS ! 850: ! 851: --*/ ! 852: ! 853: { ! 854: ! 855: *((BOOLEAN *)Context) = TRUE; ! 856: return STATUS_SUCCESS; ! 857: } ! 858: ! 859: // ! 860: // This structure is only used to communicate between the ! 861: // code that queries what the firmware found and the code ! 862: // that is calling the quering of the firmware data. ! 863: // ! 864: typedef struct PARALLEL_FIRMWARE_DATA { ! 865: PDRIVER_OBJECT DriverObject; ! 866: ULONG ControllersFound; ! 867: UNICODE_STRING Directory; ! 868: UNICODE_STRING NtNameSuffix; ! 869: UNICODE_STRING DirectorySymbolicName; ! 870: LIST_ENTRY ConfigList; ! 871: } PARALLEL_FIRMWARE_DATA,*PPARALLEL_FIRMWARE_DATA; ! 872: ! 873: ! 874: NTSTATUS ! 875: ParConfigCallBack( ! 876: IN PVOID Context, ! 877: IN PUNICODE_STRING PathName, ! 878: IN INTERFACE_TYPE BusType, ! 879: IN ULONG BusNumber, ! 880: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 881: IN CONFIGURATION_TYPE ControllerType, ! 882: IN ULONG ControllerNumber, ! 883: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 884: IN CONFIGURATION_TYPE PeripheralType, ! 885: IN ULONG PeripheralNumber, ! 886: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 887: ) ! 888: ! 889: /*++ ! 890: ! 891: Routine Description: ! 892: ! 893: This routine is used to acquire all of the configuration ! 894: information for each parallel controller found by the firmware ! 895: ! 896: Arguments: ! 897: ! 898: Context - Pointer to the list head of the list of configuration ! 899: records that we are building up. ! 900: ! 901: PathName - unicode registry path. Not Used. ! 902: ! 903: BusType - Internal, Isa, ... ! 904: ! 905: BusNumber - Which bus if we are on a multibus system. ! 906: ! 907: BusInformation - Configuration information about the bus. Not Used. ! 908: ! 909: ControllerType - Should always be ParallelController. ! 910: ! 911: ControllerNumber - Which controller if there is more than one ! 912: controller in the system. ! 913: ! 914: ControllerInformation - Array of pointers to the three pieces of ! 915: registry information. ! 916: ! 917: PeripheralType - Undefined for this call. ! 918: ! 919: PeripheralNumber - Undefined for this call. ! 920: ! 921: PeripheralInformation - Undefined for this call. ! 922: ! 923: Return Value: ! 924: ! 925: STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES ! 926: if all of the resource information couldn't be acquired. ! 927: ! 928: --*/ ! 929: ! 930: { ! 931: ! 932: // ! 933: // So we don't have to typecast the context. ! 934: // ! 935: PPARALLEL_FIRMWARE_DATA config = Context; ! 936: ! 937: // ! 938: // Pointer to the configuration stuff for this controller. ! 939: // ! 940: PCONFIG_DATA controller; ! 941: ! 942: // ! 943: // Two booleans to help us determine that we got enough configuration ! 944: // data. ! 945: // ! 946: BOOLEAN foundPort = FALSE; ! 947: BOOLEAN foundInterrupt = FALSE; ! 948: ! 949: // ! 950: // Simple iteration variable. ! 951: // ! 952: ULONG i; ! 953: ! 954: // ! 955: // Pointer to the configuration "data" portion of the configuration ! 956: // structures in the registry for this device. ! 957: // ! 958: PCM_FULL_RESOURCE_DESCRIPTOR controllerData; ! 959: ! 960: ASSERT(ControllerType == ParallelController); ! 961: ! 962: config->ControllersFound++; ! 963: ! 964: // ! 965: // Bail if some fool wrote a loader. ! 966: // ! 967: ! 968: if (!ControllerInformation[IoQueryDeviceConfigurationData]->DataLength) { ! 969: ! 970: return STATUS_SUCCESS; ! 971: ! 972: } ! 973: ! 974: controllerData = ! 975: (PCM_FULL_RESOURCE_DESCRIPTOR) ! 976: (((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData]) + ! 977: ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset); ! 978: // ! 979: // Allocate the memory for the controller config data out of paged pool ! 980: // since we will only be accessing it at initialization time. ! 981: // ! 982: ! 983: controller = ExAllocatePool( ! 984: PagedPool, ! 985: sizeof(CONFIG_DATA) ! 986: ); ! 987: ! 988: if (!controller) { ! 989: ! 990: ParLogError( ! 991: config->DriverObject, ! 992: NULL, ! 993: ParPhysicalZero, ! 994: ParPhysicalZero, ! 995: 0, ! 996: 0, ! 997: 0, ! 998: 7, ! 999: STATUS_SUCCESS, ! 1000: PAR_INSUFFICIENT_RESOURCES ! 1001: ); ! 1002: ParDump( ! 1003: PARERRORS, ! 1004: ("PARALLEL: Couldn't allocate memory for the configuration data\n" ! 1005: "-------- for firmware data\n") ! 1006: ); ! 1007: return STATUS_INSUFFICIENT_RESOURCES; ! 1008: ! 1009: } ! 1010: ! 1011: RtlZeroMemory( ! 1012: controller, ! 1013: sizeof(CONFIG_DATA) ! 1014: ); ! 1015: InitializeListHead(&controller->ConfigList); ! 1016: ! 1017: controller->InterfaceType = BusType; ! 1018: controller->BusNumber = BusNumber; ! 1019: ! 1020: // ! 1021: // We need to get the following information out of the partial ! 1022: // resource descriptors. ! 1023: // ! 1024: // The irql and vector. ! 1025: // ! 1026: // The base address and span covered by the parallel controllers ! 1027: // registers. ! 1028: // ! 1029: // It is not defined how these appear in the partial resource ! 1030: // lists, so we will just loop over all of them. If we find ! 1031: // something we don't recognize, we drop that information on ! 1032: // the floor. When we have finished going through all the ! 1033: // partial information, we validate that we got the above ! 1034: // two. ! 1035: // ! 1036: ! 1037: for ( ! 1038: i = 0; ! 1039: i < controllerData->PartialResourceList.Count; ! 1040: i++ ! 1041: ) { ! 1042: ! 1043: PCM_PARTIAL_RESOURCE_DESCRIPTOR partial = ! 1044: &controllerData->PartialResourceList.PartialDescriptors[i]; ! 1045: ! 1046: switch (partial->Type) { ! 1047: ! 1048: case CmResourceTypePort: { ! 1049: ! 1050: foundPort = TRUE; ! 1051: ! 1052: // ! 1053: // No matter what the registry says, we ! 1054: // know how long the register set is. ! 1055: // ! 1056: ! 1057: controller->SpanOfController = PARALLEL_REGISTER_SPAN; ! 1058: controller->Controller = partial->u.Port.Start; ! 1059: controller->AddressSpace = partial->Flags; ! 1060: ! 1061: break; ! 1062: } ! 1063: case CmResourceTypeInterrupt: { ! 1064: ! 1065: foundInterrupt = TRUE; ! 1066: if (partial->Flags & CM_RESOURCE_INTERRUPT_LATCHED) { ! 1067: ! 1068: controller->InterruptMode = Latched; ! 1069: ! 1070: } else { ! 1071: ! 1072: controller->InterruptMode = LevelSensitive; ! 1073: ! 1074: } ! 1075: ! 1076: controller->OriginalIrql = partial->u.Interrupt.Level; ! 1077: controller->OriginalVector = partial->u.Interrupt.Vector; ! 1078: ! 1079: break; ! 1080: ! 1081: } ! 1082: default: { ! 1083: ! 1084: break; ! 1085: ! 1086: } ! 1087: ! 1088: } ! 1089: ! 1090: } ! 1091: ! 1092: if (foundPort && foundInterrupt) { ! 1093: ! 1094: // ! 1095: // The following are so the we can form the ! 1096: // name following the \Device ! 1097: // and the default name that will be symbolic ! 1098: // linked to the device and the object directory ! 1099: // that link will go in. ! 1100: // ! 1101: ! 1102: WCHAR ntNumberBuffer[100]; ! 1103: WCHAR symbolicNumberBuffer[100]; ! 1104: UNICODE_STRING ntNumberString; ! 1105: UNICODE_STRING symbolicNumberString; ! 1106: ! 1107: ntNumberString.Length = 0; ! 1108: ntNumberString.MaximumLength = 100; ! 1109: ntNumberString.Buffer = &ntNumberBuffer[0]; ! 1110: ! 1111: symbolicNumberString.Length = 0; ! 1112: symbolicNumberString.MaximumLength = 100; ! 1113: symbolicNumberString.Buffer = &symbolicNumberBuffer[0]; ! 1114: ! 1115: // ! 1116: // Everthing is great so far. We now need to form the ! 1117: // Nt Names and symbolic link names. ! 1118: // ! 1119: ! 1120: if (!NT_SUCCESS(RtlIntegerToUnicodeString( ! 1121: config->ControllersFound - 1, ! 1122: 10, ! 1123: &ntNumberString ! 1124: ))) { ! 1125: ! 1126: ParLogError( ! 1127: config->DriverObject, ! 1128: NULL, ! 1129: ParPhysicalZero, ! 1130: ParPhysicalZero, ! 1131: 0, ! 1132: 0, ! 1133: 0, ! 1134: 8, ! 1135: STATUS_SUCCESS, ! 1136: PAR_INSUFFICIENT_RESOURCES ! 1137: ); ! 1138: ParDump( ! 1139: PARERRORS, ! 1140: ("PARALLEL: Couldn't convert NT controller number to\n" ! 1141: "-------- to unicode for firmware data: %d\n", ! 1142: config->ControllersFound - 1) ! 1143: ); ! 1144: // ! 1145: // Oh well, ignore this controller. ! 1146: // ! 1147: ExFreePool(controller); ! 1148: ! 1149: } else { ! 1150: ! 1151: if (!NT_SUCCESS(RtlIntegerToUnicodeString( ! 1152: config->ControllersFound, ! 1153: 10, ! 1154: &symbolicNumberString ! 1155: ))) { ! 1156: ! 1157: ParLogError( ! 1158: config->DriverObject, ! 1159: NULL, ! 1160: ParPhysicalZero, ! 1161: ParPhysicalZero, ! 1162: 0, ! 1163: 0, ! 1164: 0, ! 1165: 9, ! 1166: STATUS_SUCCESS, ! 1167: PAR_INSUFFICIENT_RESOURCES ! 1168: ); ! 1169: ParDump( ! 1170: PARERRORS, ! 1171: ("PARALLEL: Couldn't convert symbolic controller number to\n" ! 1172: "-------- to unicode for firmware data: %d\n", ! 1173: config->ControllersFound) ! 1174: ); ! 1175: ExFreePool(controller); ! 1176: ! 1177: } else { ! 1178: ! 1179: UNICODE_STRING Temp; ! 1180: ! 1181: // ! 1182: // Ok, we have the non-constant portions of the ! 1183: // names all figured out. Now allocate memory ! 1184: // for what will be used later. ! 1185: // ! 1186: ! 1187: // ! 1188: // Save off a copy of the object directory name. ! 1189: // ! 1190: ! 1191: // ! 1192: // Init the destination. ! 1193: // ! 1194: RtlInitUnicodeString( ! 1195: &controller->ObjectDirectory, ! 1196: NULL ! 1197: ); ! 1198: ! 1199: // ! 1200: // This will get its length. ! 1201: // ! 1202: RtlInitUnicodeString( ! 1203: &Temp, ! 1204: DEFAULT_DIRECTORY ! 1205: ); ! 1206: ! 1207: ! 1208: // ! 1209: // Now allocate that much. ! 1210: // ! 1211: ! 1212: controller->ObjectDirectory.Buffer = ! 1213: ExAllocatePool( ! 1214: PagedPool, ! 1215: Temp.Length+sizeof(WCHAR) ! 1216: ); ! 1217: ! 1218: if (!controller->ObjectDirectory.Buffer) { ! 1219: ! 1220: ParLogError( ! 1221: config->DriverObject, ! 1222: NULL, ! 1223: ParPhysicalZero, ! 1224: ParPhysicalZero, ! 1225: 0, ! 1226: 0, ! 1227: 0, ! 1228: 10, ! 1229: STATUS_SUCCESS, ! 1230: PAR_INSUFFICIENT_RESOURCES ! 1231: ); ! 1232: ParDump( ! 1233: PARERRORS, ! 1234: ("PARALLEL: Couldn't allocate memory for object\n" ! 1235: "-------- directory for NT firmware data: %d\n", ! 1236: config->ControllersFound - 1) ! 1237: ); ! 1238: ExFreePool(controller); ! 1239: return STATUS_SUCCESS; ! 1240: ! 1241: } else { ! 1242: ! 1243: controller->ObjectDirectory.MaximumLength = ! 1244: Temp.Length+sizeof(WCHAR); ! 1245: ! 1246: // ! 1247: // Zero fill it. ! 1248: // ! 1249: ! 1250: RtlZeroMemory( ! 1251: controller->ObjectDirectory.Buffer, ! 1252: controller->ObjectDirectory.MaximumLength ! 1253: ); ! 1254: ! 1255: RtlAppendUnicodeStringToString( ! 1256: &controller->ObjectDirectory, ! 1257: &Temp ! 1258: ); ! 1259: ! 1260: } ! 1261: ! 1262: // ! 1263: // Init the destination. ! 1264: // ! 1265: RtlInitUnicodeString( ! 1266: &controller->NtNameForPort, ! 1267: NULL ! 1268: ); ! 1269: ! 1270: // ! 1271: // This will get its length. ! 1272: // ! 1273: RtlInitUnicodeString( ! 1274: &Temp, ! 1275: DEFAULT_NT_SUFFIX ! 1276: ); ! 1277: ! 1278: // ! 1279: // Allocate enough for the suffix and the number. ! 1280: // ! 1281: ! 1282: controller->NtNameForPort.Buffer = ! 1283: ExAllocatePool( ! 1284: PagedPool, ! 1285: Temp.Length + ! 1286: ntNumberString.Length + sizeof(WCHAR) ! 1287: ); ! 1288: ! 1289: if (!controller->NtNameForPort.Buffer) { ! 1290: ! 1291: ParLogError( ! 1292: config->DriverObject, ! 1293: NULL, ! 1294: ParPhysicalZero, ! 1295: ParPhysicalZero, ! 1296: 0, ! 1297: 0, ! 1298: 0, ! 1299: 11, ! 1300: STATUS_SUCCESS, ! 1301: PAR_INSUFFICIENT_RESOURCES ! 1302: ); ! 1303: ParDump( ! 1304: PARERRORS, ! 1305: ("PARALLEL: Couldn't allocate memory for NT\n" ! 1306: "-------- name for NT firmware data: %d\n", ! 1307: config->ControllersFound - 1) ! 1308: ); ! 1309: ExFreePool(controller->ObjectDirectory.Buffer); ! 1310: ExFreePool(controller); ! 1311: return STATUS_SUCCESS; ! 1312: ! 1313: } else { ! 1314: ! 1315: controller->NtNameForPort.MaximumLength = ! 1316: Temp.Length+ntNumberString.Length+sizeof(WCHAR); ! 1317: ! 1318: RtlZeroMemory( ! 1319: controller->NtNameForPort.Buffer, ! 1320: controller->NtNameForPort.MaximumLength ! 1321: ); ! 1322: ! 1323: RtlAppendUnicodeStringToString( ! 1324: &controller->NtNameForPort, ! 1325: &Temp ! 1326: ); ! 1327: ! 1328: RtlAppendUnicodeStringToString( ! 1329: &controller->NtNameForPort, ! 1330: &ntNumberString ! 1331: ); ! 1332: ! 1333: } ! 1334: ! 1335: // ! 1336: // Now form that name that will be used as a ! 1337: // symbolic link to the actual device name ! 1338: // we just formed. ! 1339: // ! 1340: ! 1341: RtlInitUnicodeString( ! 1342: &controller->SymbolicLinkName, ! 1343: NULL ! 1344: ); ! 1345: ! 1346: // ! 1347: // This will get its length. ! 1348: // ! 1349: RtlInitUnicodeString( ! 1350: &Temp, ! 1351: DEFAULT_PARALLEL_NAME ! 1352: ); ! 1353: ! 1354: // ! 1355: // Allocate enough for the suffix and the number. ! 1356: // ! 1357: ! 1358: controller->SymbolicLinkName.Buffer = ! 1359: ExAllocatePool( ! 1360: PagedPool, ! 1361: Temp.Length + ! 1362: symbolicNumberString.Length+sizeof(WCHAR) ! 1363: ); ! 1364: ! 1365: if (!controller->SymbolicLinkName.Buffer) { ! 1366: ! 1367: ParLogError( ! 1368: config->DriverObject, ! 1369: NULL, ! 1370: ParPhysicalZero, ! 1371: ParPhysicalZero, ! 1372: 0, ! 1373: 0, ! 1374: 0, ! 1375: 12, ! 1376: STATUS_SUCCESS, ! 1377: PAR_INSUFFICIENT_RESOURCES ! 1378: ); ! 1379: ParDump( ! 1380: PARERRORS, ! 1381: ("PARALLEL: Couldn't allocate memory for symbolic\n" ! 1382: "-------- name for NT firmware data: %d\n", ! 1383: config->ControllersFound - 1) ! 1384: ); ! 1385: ExFreePool(controller->ObjectDirectory.Buffer); ! 1386: ExFreePool(controller->NtNameForPort.Buffer); ! 1387: ExFreePool(controller); ! 1388: return STATUS_SUCCESS; ! 1389: ! 1390: } else { ! 1391: ! 1392: controller->SymbolicLinkName.MaximumLength = ! 1393: Temp.Length+symbolicNumberString.Length+sizeof(WCHAR); ! 1394: ! 1395: RtlZeroMemory( ! 1396: controller->SymbolicLinkName.Buffer, ! 1397: controller->SymbolicLinkName.MaximumLength ! 1398: ); ! 1399: ! 1400: RtlAppendUnicodeStringToString( ! 1401: &controller->SymbolicLinkName, ! 1402: &Temp ! 1403: ); ! 1404: ! 1405: RtlAppendUnicodeStringToString( ! 1406: &controller->SymbolicLinkName, ! 1407: &symbolicNumberString ! 1408: ); ! 1409: ! 1410: } ! 1411: ! 1412: InsertTailList( ! 1413: &config->ConfigList, ! 1414: &controller->ConfigList ! 1415: ); ! 1416: ! 1417: } ! 1418: ! 1419: } ! 1420: ! 1421: } else { ! 1422: ! 1423: ParLogError( ! 1424: config->DriverObject, ! 1425: NULL, ! 1426: ParPhysicalZero, ! 1427: ParPhysicalZero, ! 1428: 0, ! 1429: 0, ! 1430: 0, ! 1431: 13, ! 1432: STATUS_SUCCESS, ! 1433: PAR_NOT_ENOUGH_CONFIG_INFO ! 1434: ); ! 1435: ExFreePool(controller); ! 1436: ! 1437: } ! 1438: ! 1439: return STATUS_SUCCESS; ! 1440: } ! 1441: ! 1442: VOID ! 1443: ParGetConfigInfo( ! 1444: IN PDRIVER_OBJECT DriverObject, ! 1445: IN PUNICODE_STRING RegistryPath, ! 1446: OUT PLIST_ENTRY ConfigList ! 1447: ) ! 1448: ! 1449: /*++ ! 1450: ! 1451: Routine Description: ! 1452: ! 1453: This routine will "return" a list of configuration ! 1454: records for the parallel ports to initialize. ! 1455: ! 1456: It will first query the firmware data. It will then ! 1457: look for "user" specified parallel ports in the registry. ! 1458: It will place the user specified parallel ports in the ! 1459: the passed in list. ! 1460: ! 1461: After it finds all of the user specified ports, it will ! 1462: attempt to add the firmware parallel ports into the passed ! 1463: in lists. The insert in the list code detects conflicts ! 1464: and rejects a new port. In this way we can prevent ! 1465: firmware found ports from overiding information ! 1466: specified by the "user". Note, this means if the user ! 1467: specified data is incorrect in its use of the interrupt ! 1468: (which should *always* be correct from the firmware) ! 1469: that port likely will not work. But, then, we "trust" ! 1470: the user. ! 1471: ! 1472: ! 1473: Arguments: ! 1474: ! 1475: DriverObject - Not used. ! 1476: ! 1477: RegistryPath - Path to this drivers service node in ! 1478: the current control set. ! 1479: ! 1480: ConfigList - Listhead (which will be intialized) for a list ! 1481: of configuration records for ports to control. ! 1482: ! 1483: Return Value: ! 1484: ! 1485: None. ! 1486: ! 1487: --*/ ! 1488: ! 1489: { ! 1490: ! 1491: // ! 1492: // A structure that we pass to the firmware query routine ! 1493: // as "context". This context will contain the number of ! 1494: // ports already found as well as default names and the ! 1495: // listhead of the configuration list. ! 1496: // ! 1497: PARALLEL_FIRMWARE_DATA firmware; ! 1498: ! 1499: // ! 1500: // This will point to the structure that is used by RtlQueryRegistryValues ! 1501: // to "direct" its search and retrieval of values. ! 1502: // ! 1503: PRTL_QUERY_REGISTRY_TABLE parameters = NULL; ! 1504: ! 1505: // ! 1506: // We'll have to query the registry to determine what kind of ! 1507: // bus the system is using. Then when the user specifies the ! 1508: // address of a port, the user doesn't have to tell us the ! 1509: // the bus type (unless they really want to). When we determine ! 1510: // the default bus on the system, we'll know whether the interrupt ! 1511: // is latched or level sensitive. ! 1512: // ! 1513: INTERFACE_TYPE interfaceType; ! 1514: ULONG defaultInterfaceType; ! 1515: ! 1516: // ! 1517: // Default values for user data. ! 1518: // ! 1519: ULONG maxUlong = MAXULONG; ! 1520: ULONG zero = 0; ! 1521: ULONG defaultInterruptMode; ! 1522: ULONG defaultAddressSpace = CM_RESOURCE_PORT_IO; ! 1523: ! 1524: // ! 1525: // Where user data from the registry will be placed. ! 1526: // ! 1527: PHYSICAL_ADDRESS userPort; ! 1528: ULONG userVector; ! 1529: ULONG userLevel; ! 1530: ULONG userBusNumber; ! 1531: ULONG userInterfaceType; ! 1532: ULONG userAddressSpace; ! 1533: ULONG userInterruptMode; ! 1534: ULONG disablePort; ! 1535: UNICODE_STRING userSymbolicLink; ! 1536: ! 1537: UNICODE_STRING parametersPath; ! 1538: OBJECT_ATTRIBUTES parametersAttributes; ! 1539: HANDLE parametersKey; ! 1540: PKEY_BASIC_INFORMATION userSubKey = NULL; ! 1541: ULONG i; ! 1542: ! 1543: InitializeListHead(ConfigList); ! 1544: ! 1545: RtlZeroMemory( ! 1546: &firmware, ! 1547: sizeof(PARALLEL_FIRMWARE_DATA) ! 1548: ); ! 1549: ! 1550: firmware.DriverObject = DriverObject; ! 1551: ! 1552: // ! 1553: // Initialize the controllers found so far with the ! 1554: // values in configuration database that the io system ! 1555: // maintains ! 1556: // ! 1557: ! 1558: firmware.ControllersFound = IoGetConfigurationInformation()->ParallelCount; ! 1559: InitializeListHead(&firmware.ConfigList); ! 1560: RtlInitUnicodeString( ! 1561: &firmware.Directory, ! 1562: DEFAULT_DIRECTORY ! 1563: ); ! 1564: RtlInitUnicodeString( ! 1565: &firmware.NtNameSuffix, ! 1566: DEFAULT_NT_SUFFIX ! 1567: ); ! 1568: RtlInitUnicodeString( ! 1569: &firmware.DirectorySymbolicName, ! 1570: DEFAULT_PARALLEL_NAME ! 1571: ); ! 1572: ! 1573: // ! 1574: // First we query the hardware registry for all of ! 1575: // the firmware defined ports. We loop over all of ! 1576: // the busses. ! 1577: // ! 1578: ! 1579: for ( ! 1580: interfaceType = 0; ! 1581: interfaceType < MaximumInterfaceType; ! 1582: interfaceType++ ! 1583: ) { ! 1584: ! 1585: CONFIGURATION_TYPE sc = ParallelController; ! 1586: ! 1587: IoQueryDeviceDescription( ! 1588: &interfaceType, ! 1589: NULL, ! 1590: &sc, ! 1591: NULL, ! 1592: NULL, ! 1593: NULL, ! 1594: ParConfigCallBack, ! 1595: &firmware ! 1596: ); ! 1597: ! 1598: } ! 1599: ! 1600: // ! 1601: // Query the registry one more time. This time we ! 1602: // look for the first bus on the system (that isn't ! 1603: // the internal bus - we assume that the firmware ! 1604: // code knows about those ports). We will use that ! 1605: // as the default bus if no bustype or bus number ! 1606: // is specified in the "user" configuration records. ! 1607: // ! 1608: ! 1609: defaultInterfaceType = (ULONG)Isa; ! 1610: defaultInterruptMode = CM_RESOURCE_INTERRUPT_LATCHED; ! 1611: ! 1612: for ( ! 1613: interfaceType = 0; ! 1614: interfaceType < MaximumInterfaceType; ! 1615: interfaceType++ ! 1616: ) { ! 1617: ! 1618: ULONG busZero = 0; ! 1619: BOOLEAN foundOne = FALSE; ! 1620: ! 1621: if (interfaceType != Internal) { ! 1622: ! 1623: IoQueryDeviceDescription( ! 1624: &interfaceType, ! 1625: &busZero, ! 1626: NULL, ! 1627: NULL, ! 1628: NULL, ! 1629: NULL, ! 1630: ParItemCallBack, ! 1631: &foundOne ! 1632: ); ! 1633: ! 1634: if (foundOne) { ! 1635: ! 1636: defaultInterfaceType = (ULONG)interfaceType; ! 1637: if (defaultInterfaceType == MicroChannel) { ! 1638: ! 1639: defaultInterruptMode = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 1640: ! 1641: } ! 1642: ! 1643: break; ! 1644: ! 1645: } ! 1646: ! 1647: } ! 1648: ! 1649: } ! 1650: ! 1651: // ! 1652: // Gonna get the user data now. Allocate the ! 1653: // structures that we will be using throughout ! 1654: // the search for user data. We will deallocate ! 1655: // them before we leave this routine. ! 1656: // ! 1657: ! 1658: userSymbolicLink.Buffer = NULL; ! 1659: parametersPath.Buffer = NULL; ! 1660: ! 1661: // ! 1662: // Allocate the rtl query table. ! 1663: // ! 1664: ! 1665: parameters = ExAllocatePool( ! 1666: PagedPool, ! 1667: sizeof(RTL_QUERY_REGISTRY_TABLE)*15 ! 1668: ); ! 1669: ! 1670: if (!parameters) { ! 1671: ! 1672: ParLogError( ! 1673: DriverObject, ! 1674: NULL, ! 1675: ParPhysicalZero, ! 1676: ParPhysicalZero, ! 1677: 0, ! 1678: 0, ! 1679: 0, ! 1680: 14, ! 1681: STATUS_SUCCESS, ! 1682: PAR_INSUFFICIENT_RESOURCES ! 1683: ); ! 1684: ParDump( ! 1685: PARERRORS, ! 1686: ("PARALLEL: Couldn't allocate table for rtl query\n" ! 1687: "-------- to parameters for %wZ", ! 1688: RegistryPath) ! 1689: ); ! 1690: ! 1691: goto DoFirmwareAdd; ! 1692: ! 1693: } ! 1694: ! 1695: RtlZeroMemory( ! 1696: parameters, ! 1697: sizeof(RTL_QUERY_REGISTRY_TABLE)*15 ! 1698: ); ! 1699: ! 1700: // ! 1701: // Allocate the place where the users symbolic link name ! 1702: // for the port will go. ! 1703: // ! 1704: ! 1705: // ! 1706: // We will initially allocate space for 257 wchars. ! 1707: // we will then set the maximum size to 256 ! 1708: // This way the rtl routine could return a 256 ! 1709: // WCHAR wide string with no null terminator. ! 1710: // We'll remember that the buffer is one WCHAR ! 1711: // longer then it says it is so that we can always ! 1712: // have a NULL terminator at the end. ! 1713: // ! 1714: ! 1715: RtlInitUnicodeString( ! 1716: &userSymbolicLink, ! 1717: NULL ! 1718: ); ! 1719: userSymbolicLink.MaximumLength = sizeof(WCHAR)*256; ! 1720: userSymbolicLink.Buffer = ExAllocatePool( ! 1721: PagedPool, ! 1722: sizeof(WCHAR)*257 ! 1723: ); ! 1724: ! 1725: if (!userSymbolicLink.Buffer) { ! 1726: ! 1727: ParLogError( ! 1728: DriverObject, ! 1729: NULL, ! 1730: ParPhysicalZero, ! 1731: ParPhysicalZero, ! 1732: 0, ! 1733: 0, ! 1734: 0, ! 1735: 15, ! 1736: STATUS_SUCCESS, ! 1737: PAR_INSUFFICIENT_RESOURCES ! 1738: ); ! 1739: ParDump( ! 1740: PARERRORS, ! 1741: ("PARALLEL: Couldn't allocate buffer for the symbolic link\n" ! 1742: "-------- for parameters items in %wZ", ! 1743: RegistryPath) ! 1744: ); ! 1745: ! 1746: goto DoFirmwareAdd; ! 1747: ! 1748: } ! 1749: ! 1750: // ! 1751: // Form a path to our drivers Parameters subkey. ! 1752: // ! 1753: ! 1754: RtlInitUnicodeString( ! 1755: ¶metersPath, ! 1756: NULL ! 1757: ); ! 1758: ! 1759: parametersPath.MaximumLength = RegistryPath->Length + ! 1760: sizeof(L"\\") + ! 1761: sizeof(L"Parameters"); ! 1762: ! 1763: parametersPath.Buffer = ExAllocatePool( ! 1764: PagedPool, ! 1765: parametersPath.MaximumLength ! 1766: ); ! 1767: ! 1768: if (!parametersPath.Buffer) { ! 1769: ! 1770: ParLogError( ! 1771: DriverObject, ! 1772: NULL, ! 1773: ParPhysicalZero, ! 1774: ParPhysicalZero, ! 1775: 0, ! 1776: 0, ! 1777: 0, ! 1778: 16, ! 1779: STATUS_SUCCESS, ! 1780: PAR_INSUFFICIENT_RESOURCES ! 1781: ); ! 1782: ParDump( ! 1783: PARERRORS, ! 1784: ("PARALLEL: Couldn't allocate string for path\n" ! 1785: "-------- to parameters for %wZ", ! 1786: RegistryPath) ! 1787: ); ! 1788: ! 1789: goto DoFirmwareAdd; ! 1790: ! 1791: } ! 1792: ! 1793: // ! 1794: // Form the parameters path. ! 1795: // ! 1796: ! 1797: RtlZeroMemory( ! 1798: parametersPath.Buffer, ! 1799: parametersPath.MaximumLength ! 1800: ); ! 1801: RtlAppendUnicodeStringToString( ! 1802: ¶metersPath, ! 1803: RegistryPath ! 1804: ); ! 1805: RtlAppendUnicodeToString( ! 1806: ¶metersPath, ! 1807: L"\\" ! 1808: ); ! 1809: RtlAppendUnicodeToString( ! 1810: ¶metersPath, ! 1811: L"Parameters" ! 1812: ); ! 1813: ! 1814: userSubKey = ExAllocatePool( ! 1815: PagedPool, ! 1816: sizeof(KEY_BASIC_INFORMATION)+(sizeof(WCHAR)*256) ! 1817: ); ! 1818: ! 1819: if (!userSubKey) { ! 1820: ! 1821: ParLogError( ! 1822: DriverObject, ! 1823: NULL, ! 1824: ParPhysicalZero, ! 1825: ParPhysicalZero, ! 1826: 0, ! 1827: 0, ! 1828: 0, ! 1829: 17, ! 1830: STATUS_SUCCESS, ! 1831: PAR_INSUFFICIENT_RESOURCES ! 1832: ); ! 1833: ParDump( ! 1834: PARERRORS, ! 1835: ("PARALLEL: Couldn't allocate memory basic information\n" ! 1836: "-------- structure to enumerate subkeys for %wZ", ! 1837: ¶metersPath) ! 1838: ); ! 1839: ! 1840: goto DoFirmwareAdd; ! 1841: ! 1842: } ! 1843: ! 1844: // ! 1845: // Open the key given by our registry path & Parameters. ! 1846: // ! 1847: // Note: The reason we are opening up the key by hand, and ! 1848: // then enumerating all of the subkeys is so we don't have ! 1849: // to architect what the names of the devices have to be and ! 1850: // how many of them there could be. We just try to get ! 1851: // as many as there are. ! 1852: // ! 1853: ! 1854: InitializeObjectAttributes( ! 1855: ¶metersAttributes, ! 1856: ¶metersPath, ! 1857: OBJ_CASE_INSENSITIVE, ! 1858: NULL, ! 1859: NULL ! 1860: ); ! 1861: ! 1862: if (!NT_SUCCESS(ZwOpenKey( ! 1863: ¶metersKey, ! 1864: MAXIMUM_ALLOWED, ! 1865: ¶metersAttributes ! 1866: ))) { ! 1867: ! 1868: ParLogError( ! 1869: DriverObject, ! 1870: NULL, ! 1871: ParPhysicalZero, ! 1872: ParPhysicalZero, ! 1873: 0, ! 1874: 0, ! 1875: 0, ! 1876: 18, ! 1877: STATUS_SUCCESS, ! 1878: PAR_NO_PARAMETERS_INFO ! 1879: ); ! 1880: ParDump( ! 1881: PARERRORS, ! 1882: ("PARALLEL: Couldn't open the drivers Parameters key %wZ\n", ! 1883: RegistryPath) ! 1884: ); ! 1885: goto DoFirmwareAdd; ! 1886: ! 1887: } ! 1888: ! 1889: // ! 1890: // Gather all of the "user specified" information from ! 1891: // the registry. ! 1892: // ! 1893: ! 1894: parameters[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; ! 1895: ! 1896: parameters[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | ! 1897: RTL_QUERY_REGISTRY_DIRECT; ! 1898: parameters[1].Name = L"PortAddress"; ! 1899: parameters[1].EntryContext = &userPort.LowPart; ! 1900: ! 1901: parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1902: parameters[2].Name = L"Interrupt"; ! 1903: parameters[2].EntryContext = &userVector; ! 1904: parameters[2].DefaultType = REG_DWORD; ! 1905: parameters[2].DefaultData = &maxUlong; ! 1906: parameters[2].DefaultLength = sizeof(ULONG); ! 1907: ! 1908: parameters[3].Flags = RTL_QUERY_REGISTRY_REQUIRED | ! 1909: RTL_QUERY_REGISTRY_DIRECT; ! 1910: parameters[3].Name = firmware.Directory.Buffer; ! 1911: parameters[3].EntryContext = &userSymbolicLink; ! 1912: ! 1913: parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1914: parameters[4].Name = L"BusNumber"; ! 1915: parameters[4].EntryContext = &userBusNumber; ! 1916: parameters[4].DefaultType = REG_DWORD; ! 1917: parameters[4].DefaultData = &zero; ! 1918: parameters[4].DefaultLength = sizeof(ULONG); ! 1919: ! 1920: parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1921: parameters[5].Name = L"BusType"; ! 1922: parameters[5].EntryContext = &userInterfaceType; ! 1923: parameters[5].DefaultType = REG_DWORD; ! 1924: parameters[5].DefaultData = &defaultInterfaceType; ! 1925: parameters[5].DefaultLength = sizeof(ULONG); ! 1926: ! 1927: parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1928: parameters[6].Name = L"InterruptMode"; ! 1929: parameters[6].EntryContext = &userInterruptMode; ! 1930: parameters[6].DefaultType = REG_DWORD; ! 1931: parameters[6].DefaultData = &defaultInterruptMode; ! 1932: parameters[6].DefaultLength = sizeof(ULONG); ! 1933: ! 1934: parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1935: parameters[7].Name = L"AddressSpace"; ! 1936: parameters[7].EntryContext = &userAddressSpace; ! 1937: parameters[7].DefaultType = REG_DWORD; ! 1938: parameters[7].DefaultData = &defaultAddressSpace; ! 1939: parameters[7].DefaultLength = sizeof(ULONG); ! 1940: ! 1941: parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1942: parameters[8].Name = L"InterruptLevel"; ! 1943: parameters[8].EntryContext = &userLevel; ! 1944: parameters[8].DefaultType = REG_DWORD; ! 1945: parameters[8].DefaultData = &zero; ! 1946: parameters[8].DefaultLength = sizeof(ULONG); ! 1947: ! 1948: parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 1949: parameters[9].Name = L"DisablePort"; ! 1950: parameters[9].EntryContext = &disablePort; ! 1951: parameters[9].DefaultType = REG_DWORD; ! 1952: parameters[9].DefaultData = &zero; ! 1953: parameters[9].DefaultLength = sizeof(ULONG); ! 1954: ! 1955: i = 0; ! 1956: while (TRUE) { ! 1957: ! 1958: NTSTATUS status; ! 1959: ULONG actuallyReturned; ! 1960: ! 1961: // ! 1962: // We lie about the length of the buffer, so that we can ! 1963: // MAKE SURE that the name it returns can be padded with ! 1964: // a NULL. ! 1965: // ! 1966: ! 1967: status = ZwEnumerateKey( ! 1968: parametersKey, ! 1969: i, ! 1970: KeyBasicInformation, ! 1971: userSubKey, ! 1972: sizeof(KEY_BASIC_INFORMATION)+(sizeof(WCHAR)*255), ! 1973: &actuallyReturned ! 1974: ); ! 1975: ! 1976: if (status == STATUS_NO_MORE_ENTRIES) { ! 1977: ! 1978: break; ! 1979: } ! 1980: ! 1981: if (status == STATUS_BUFFER_OVERFLOW) { ! 1982: ! 1983: ParLogError( ! 1984: DriverObject, ! 1985: NULL, ! 1986: ParPhysicalZero, ! 1987: ParPhysicalZero, ! 1988: 0, ! 1989: 0, ! 1990: 0, ! 1991: 19, ! 1992: STATUS_SUCCESS, ! 1993: PAR_UNABLE_TO_ACCESS_CONFIG ! 1994: ); ! 1995: ParDump( ! 1996: PARERRORS, ! 1997: ("PARALLEL: Overflowed the enumerate buffer\n" ! 1998: "-------- for subkey #%d of %wZ\n", ! 1999: i,parametersPath) ! 2000: ); ! 2001: i++; ! 2002: continue; ! 2003: ! 2004: } ! 2005: ! 2006: if (!NT_SUCCESS(status)) { ! 2007: ! 2008: ParLogError( ! 2009: DriverObject, ! 2010: NULL, ! 2011: ParPhysicalZero, ! 2012: ParPhysicalZero, ! 2013: 0, ! 2014: 0, ! 2015: 0, ! 2016: 20, ! 2017: status, ! 2018: PAR_UNABLE_TO_ACCESS_CONFIG ! 2019: ); ! 2020: ParDump( ! 2021: PARERRORS, ! 2022: ("PARALLEL: Bad status returned: %x \n" ! 2023: "-------- on enumeration for subkey # %d of %wZ\n", ! 2024: status,i,parametersPath) ! 2025: ); ! 2026: i++; ! 2027: continue; ! 2028: ! 2029: } ! 2030: ! 2031: // ! 2032: // Pad the name returned with a null. ! 2033: // ! 2034: ! 2035: RtlZeroMemory( ! 2036: ((PUCHAR)(&userSubKey->Name[0]))+userSubKey->NameLength, ! 2037: sizeof(WCHAR) ! 2038: ); ! 2039: ! 2040: parameters[0].Name = &userSubKey->Name[0]; ! 2041: ! 2042: // ! 2043: // Make sure that the physical addresses start ! 2044: // out clean. ! 2045: // ! 2046: RtlZeroMemory( ! 2047: &userPort, ! 2048: sizeof(userPort) ! 2049: ); ! 2050: ! 2051: status = RtlQueryRegistryValues( ! 2052: RTL_REGISTRY_ABSOLUTE, ! 2053: parametersPath.Buffer, ! 2054: parameters, ! 2055: NULL, ! 2056: NULL ! 2057: ); ! 2058: ! 2059: if (NT_SUCCESS(status)) { ! 2060: ! 2061: PCONFIG_DATA newConfig; ! 2062: ! 2063: // ! 2064: // Well! Some supposedly valid information was found! ! 2065: // ! 2066: // We'll see about that. ! 2067: // ! 2068: // We don't want to cause the hal to have a bad day, ! 2069: // so let's check the interface type and bus number. ! 2070: // ! 2071: // We only need to check the registry if they aren't ! 2072: // equal to the defaults. ! 2073: // ! 2074: ! 2075: if ((userBusNumber != 0) || ! 2076: (userInterfaceType != defaultInterfaceType)) { ! 2077: ! 2078: BOOLEAN foundIt = FALSE; ! 2079: if (userInterfaceType >= MaximumInterfaceType) { ! 2080: ! 2081: // ! 2082: // Ehhhh! Lose Game. ! 2083: // ! 2084: ! 2085: ParLogError( ! 2086: DriverObject, ! 2087: NULL, ! 2088: userPort, ! 2089: ParPhysicalZero, ! 2090: 0, ! 2091: 0, ! 2092: 0, ! 2093: 21, ! 2094: STATUS_SUCCESS, ! 2095: PAR_UNKNOWN_BUS ! 2096: ); ! 2097: ParDump( ! 2098: PARERRORS, ! 2099: ("PARALLEL: Invalid Bus type %ws\n", ! 2100: parameters[0].Name) ! 2101: ); ! 2102: i++; ! 2103: continue; ! 2104: ! 2105: } ! 2106: ! 2107: IoQueryDeviceDescription( ! 2108: (INTERFACE_TYPE *)&userInterfaceType, ! 2109: &userBusNumber, ! 2110: NULL, ! 2111: NULL, ! 2112: NULL, ! 2113: NULL, ! 2114: ParItemCallBack, ! 2115: &foundIt ! 2116: ); ! 2117: ! 2118: if (!foundIt) { ! 2119: ! 2120: ParLogError( ! 2121: DriverObject, ! 2122: NULL, ! 2123: userPort, ! 2124: ParPhysicalZero, ! 2125: 0, ! 2126: 0, ! 2127: 0, ! 2128: 22, ! 2129: STATUS_SUCCESS, ! 2130: PAR_BUS_NOT_PRESENT ! 2131: ); ! 2132: ParDump( ! 2133: PARERRORS, ! 2134: ("PARALLEL: There aren't that many of those\n" ! 2135: "-------- busses on this system,%ws\n", ! 2136: parameters[0].Name) ! 2137: ); ! 2138: i++; ! 2139: continue; ! 2140: ! 2141: } ! 2142: ! 2143: } ! 2144: ! 2145: if ((userInterfaceType == MicroChannel) && ! 2146: (userInterruptMode == CM_RESOURCE_INTERRUPT_LATCHED)) { ! 2147: ! 2148: ParLogError( ! 2149: DriverObject, ! 2150: NULL, ! 2151: userPort, ! 2152: ParPhysicalZero, ! 2153: 0, ! 2154: 0, ! 2155: 0, ! 2156: 23, ! 2157: STATUS_SUCCESS, ! 2158: PAR_BUS_INTERRUPT_CONFLICT ! 2159: ); ! 2160: ParDump( ! 2161: PARERRORS, ! 2162: ("PARALLEL: Latched interrupts and MicroChannel\n" ! 2163: "-------- busses don't mix,%ws\n", ! 2164: parameters[0].Name) ! 2165: ); ! 2166: i++; ! 2167: continue; ! 2168: ! 2169: } ! 2170: ! 2171: // ! 2172: // Well ok, I guess we can take the data. ! 2173: // There be other tests later on to make ! 2174: // sure it doesn't have any other kinds ! 2175: // of conflicts. ! 2176: // ! 2177: ! 2178: // ! 2179: // Allocate the config record. ! 2180: // ! 2181: ! 2182: newConfig = ExAllocatePool( ! 2183: PagedPool, ! 2184: sizeof(CONFIG_DATA) ! 2185: ); ! 2186: ! 2187: if (!newConfig) { ! 2188: ! 2189: ParLogError( ! 2190: DriverObject, ! 2191: NULL, ! 2192: userPort, ! 2193: ParPhysicalZero, ! 2194: 0, ! 2195: 0, ! 2196: 0, ! 2197: 24, ! 2198: STATUS_SUCCESS, ! 2199: PAR_INSUFFICIENT_RESOURCES ! 2200: ); ! 2201: ParDump( ! 2202: PARERRORS, ! 2203: ("PARALLEL: Couldn't allocate memory for the\n" ! 2204: "-------- user configuration record\n" ! 2205: "-------- for %ws\n", ! 2206: parameters[0].Name) ! 2207: ); ! 2208: ! 2209: i++; ! 2210: continue; ! 2211: ! 2212: } ! 2213: ! 2214: RtlZeroMemory( ! 2215: newConfig, ! 2216: sizeof(CONFIG_DATA) ! 2217: ); ! 2218: ! 2219: // ! 2220: // Save off a copy of the object directory name. ! 2221: // ! 2222: ! 2223: // ! 2224: // Init the destination. ! 2225: // ! 2226: RtlInitUnicodeString( ! 2227: &newConfig->ObjectDirectory, ! 2228: DEFAULT_DIRECTORY ! 2229: ); ! 2230: newConfig->ObjectDirectory.MaximumLength += sizeof(WCHAR); ! 2231: ! 2232: // ! 2233: // Now allocate that much. ! 2234: // ! 2235: ! 2236: newConfig->ObjectDirectory.Buffer = ! 2237: ExAllocatePool( ! 2238: PagedPool, ! 2239: newConfig->ObjectDirectory.MaximumLength ! 2240: ); ! 2241: ! 2242: if (!newConfig->ObjectDirectory.Buffer) { ! 2243: ! 2244: ParLogError( ! 2245: DriverObject, ! 2246: NULL, ! 2247: userPort, ! 2248: ParPhysicalZero, ! 2249: 0, ! 2250: 0, ! 2251: 0, ! 2252: 25, ! 2253: STATUS_SUCCESS, ! 2254: PAR_INSUFFICIENT_RESOURCES ! 2255: ); ! 2256: ParDump( ! 2257: PARERRORS, ! 2258: ("PARALLEL: Couldn't allocate memory for object\n" ! 2259: "-------- directory for NT user data for: %ws\n", ! 2260: parameters[0].Name) ! 2261: ); ! 2262: ExFreePool(newConfig); ! 2263: i++; ! 2264: continue; ! 2265: ! 2266: } else { ! 2267: ! 2268: // ! 2269: // Zero fill it. ! 2270: // ! 2271: ! 2272: RtlZeroMemory( ! 2273: newConfig->ObjectDirectory.Buffer, ! 2274: newConfig->ObjectDirectory.MaximumLength ! 2275: ); ! 2276: ! 2277: newConfig->ObjectDirectory.Length = 0; ! 2278: RtlAppendUnicodeToString( ! 2279: &newConfig->ObjectDirectory, ! 2280: DEFAULT_DIRECTORY ! 2281: ); ! 2282: ! 2283: } ! 2284: ! 2285: // ! 2286: // Init the destination. ! 2287: // ! 2288: ! 2289: RtlInitUnicodeString( ! 2290: &newConfig->NtNameForPort, ! 2291: &userSubKey->Name[0] ! 2292: ); ! 2293: ! 2294: // ! 2295: // Allocate the space for the name. ! 2296: // ! 2297: ! 2298: newConfig->NtNameForPort.Length = 0; ! 2299: newConfig->NtNameForPort.MaximumLength += sizeof(WCHAR); ! 2300: newConfig->NtNameForPort.Buffer = ! 2301: ExAllocatePool( ! 2302: PagedPool, ! 2303: newConfig->NtNameForPort.MaximumLength ! 2304: ); ! 2305: ! 2306: if (!newConfig->NtNameForPort.Buffer) { ! 2307: ! 2308: ParLogError( ! 2309: DriverObject, ! 2310: NULL, ! 2311: userPort, ! 2312: ParPhysicalZero, ! 2313: 0, ! 2314: 0, ! 2315: 0, ! 2316: 26, ! 2317: STATUS_SUCCESS, ! 2318: PAR_INSUFFICIENT_RESOURCES ! 2319: ); ! 2320: ParDump( ! 2321: PARERRORS, ! 2322: ("PARALLEL: Couldn't allocate memory for NT\n" ! 2323: "-------- name for NT user data name: %ws\n", ! 2324: parameters[0].Name) ! 2325: ); ! 2326: ExFreePool(newConfig->ObjectDirectory.Buffer); ! 2327: ExFreePool(newConfig); ! 2328: i++; ! 2329: continue; ! 2330: ! 2331: } else { ! 2332: ! 2333: RtlZeroMemory( ! 2334: newConfig->NtNameForPort.Buffer, ! 2335: newConfig->NtNameForPort.MaximumLength ! 2336: ); ! 2337: ! 2338: RtlAppendUnicodeToString( ! 2339: &newConfig->NtNameForPort, ! 2340: &userSubKey->Name[0] ! 2341: ); ! 2342: ! 2343: } ! 2344: ! 2345: newConfig->SymbolicLinkName = userSymbolicLink; ! 2346: newConfig->SymbolicLinkName.MaximumLength += sizeof(WCHAR); ! 2347: ! 2348: newConfig->SymbolicLinkName.Buffer = ! 2349: ExAllocatePool( ! 2350: PagedPool, ! 2351: newConfig->SymbolicLinkName.MaximumLength ! 2352: ); ! 2353: ! 2354: if (!newConfig->SymbolicLinkName.Buffer) { ! 2355: ! 2356: ParLogError( ! 2357: DriverObject, ! 2358: NULL, ! 2359: userPort, ! 2360: ParPhysicalZero, ! 2361: 0, ! 2362: 0, ! 2363: 0, ! 2364: 27, ! 2365: STATUS_SUCCESS, ! 2366: PAR_INSUFFICIENT_RESOURCES ! 2367: ); ! 2368: ParDump( ! 2369: PARERRORS, ! 2370: ("PARALLEL: Couldn't allocate memory for symbolic\n" ! 2371: "-------- name from user data\n" ! 2372: "-------- %ws\n", ! 2373: parameters[0].Name) ! 2374: ); ! 2375: ExFreePool(newConfig->ObjectDirectory.Buffer); ! 2376: ExFreePool(newConfig->NtNameForPort.Buffer); ! 2377: ExFreePool(newConfig); ! 2378: i++; ! 2379: continue; ! 2380: ! 2381: } else { ! 2382: ! 2383: RtlZeroMemory( ! 2384: newConfig->SymbolicLinkName.Buffer, ! 2385: newConfig->SymbolicLinkName.MaximumLength ! 2386: ); ! 2387: ! 2388: newConfig->SymbolicLinkName.Length = 0; ! 2389: RtlAppendUnicodeStringToString( ! 2390: &newConfig->SymbolicLinkName, ! 2391: &userSymbolicLink ! 2392: ); ! 2393: ! 2394: } ! 2395: ! 2396: InitializeListHead(&newConfig->ConfigList); ! 2397: newConfig->Controller = userPort; ! 2398: newConfig->SpanOfController = PARALLEL_REGISTER_SPAN; ! 2399: newConfig->BusNumber = userBusNumber; ! 2400: newConfig->AddressSpace = userAddressSpace; ! 2401: newConfig->InterruptMode = userInterruptMode; ! 2402: newConfig->InterfaceType = userInterfaceType; ! 2403: newConfig->OriginalVector = userVector; ! 2404: newConfig->DisablePort = disablePort; ! 2405: if (!userLevel) { ! 2406: newConfig->OriginalIrql = userVector; ! 2407: } else { ! 2408: newConfig->OriginalIrql = userLevel; ! 2409: } ! 2410: ParDump( ! 2411: PARCONFIG, ! 2412: ("PARALLEL: 'user registry info - userPort: %x\n", ! 2413: userPort.LowPart) ! 2414: ); ! 2415: ParDump( ! 2416: PARCONFIG, ! 2417: ("PARALLEL: 'user registry info - userBusNumber: %d\n", ! 2418: userBusNumber) ! 2419: ); ! 2420: ParDump( ! 2421: PARCONFIG, ! 2422: ("PARALLEL: 'user registry info - userAddressSpace: %d\n", ! 2423: userAddressSpace) ! 2424: ); ! 2425: ParDump( ! 2426: PARCONFIG, ! 2427: ("PARALLEL: 'user registry info - userInterruptMode: %d\n", ! 2428: userInterruptMode) ! 2429: ); ! 2430: ParDump( ! 2431: PARCONFIG, ! 2432: ("PARALLEL: 'user registry info - userInterfaceType: %d\n", ! 2433: userInterfaceType) ! 2434: ); ! 2435: ParDump( ! 2436: PARCONFIG, ! 2437: ("PARALLEL: 'user registry info - userVector: %d\n", ! 2438: userVector) ! 2439: ); ! 2440: ParDump( ! 2441: PARCONFIG, ! 2442: ("PARALLEL: 'user registry info - userLevel: %d\n", ! 2443: userLevel) ! 2444: ); ! 2445: ! 2446: if (!ParPutInConfigList( ! 2447: DriverObject, ! 2448: ConfigList, ! 2449: newConfig ! 2450: )) { ! 2451: ! 2452: // ! 2453: // Dispose of this configuration record. ! 2454: // ! 2455: ! 2456: ParDump( ! 2457: PARERRORS, ! 2458: ("PARALLEL: Conflict detected amoungst user data %ws\n", ! 2459: parameters[0].Name) ! 2460: ); ! 2461: ! 2462: ExFreePool(newConfig->ObjectDirectory.Buffer); ! 2463: ExFreePool(newConfig->NtNameForPort.Buffer); ! 2464: ExFreePool(newConfig->SymbolicLinkName.Buffer); ! 2465: ExFreePool(newConfig); ! 2466: ! 2467: } ! 2468: ! 2469: i++; ! 2470: ! 2471: } else { ! 2472: ! 2473: ParLogError( ! 2474: DriverObject, ! 2475: NULL, ! 2476: ParPhysicalZero, ! 2477: ParPhysicalZero, ! 2478: 0, ! 2479: 0, ! 2480: 0, ! 2481: 28, ! 2482: STATUS_SUCCESS, ! 2483: PAR_INVALID_USER_CONFIG ! 2484: ); ! 2485: ParDump( ! 2486: PARERRORS, ! 2487: ("PARALLEL: Bad status returned: %x \n" ! 2488: "-------- for the value entries of\n" ! 2489: "-------- %ws\n", ! 2490: status,parameters[0].Name) ! 2491: ); ! 2492: ! 2493: i++; ! 2494: ! 2495: } ! 2496: ! 2497: } ! 2498: ! 2499: ZwClose(parametersKey); ! 2500: ! 2501: DoFirmwareAdd:; ! 2502: ! 2503: // ! 2504: // All done with the user specified information. Now try ! 2505: // to add the firmware specified data to the configuration. ! 2506: // If a conflict is detected then we simply dispose of that ! 2507: // firmware collected data. ! 2508: // ! 2509: ! 2510: while (!IsListEmpty(&firmware.ConfigList)) { ! 2511: ! 2512: PLIST_ENTRY head; ! 2513: PCONFIG_DATA firmwareData; ! 2514: ! 2515: head = RemoveHeadList(&firmware.ConfigList); ! 2516: ! 2517: firmwareData = CONTAINING_RECORD( ! 2518: head, ! 2519: CONFIG_DATA, ! 2520: ConfigList ! 2521: ); ! 2522: ! 2523: if (!ParPutInConfigList( ! 2524: DriverObject, ! 2525: ConfigList, ! 2526: firmwareData ! 2527: )) { ! 2528: ! 2529: // ! 2530: // Dispose of this configuration record. ! 2531: // ! 2532: ! 2533: ParLogError( ! 2534: DriverObject, ! 2535: NULL, ! 2536: firmwareData->Controller, ! 2537: ParPhysicalZero, ! 2538: 0, ! 2539: 0, ! 2540: 0, ! 2541: 29, ! 2542: STATUS_SUCCESS, ! 2543: PAR_USER_OVERRIDE ! 2544: ); ! 2545: ParDump( ! 2546: PARERRORS, ! 2547: ("PARALLEL: Conflict detected with user data for firmware port %wZ\n" ! 2548: "-------- User data will overides firmware data\n", ! 2549: &firmwareData->NtNameForPort) ! 2550: ); ! 2551: ExFreePool(firmwareData->ObjectDirectory.Buffer); ! 2552: ExFreePool(firmwareData->NtNameForPort.Buffer); ! 2553: ExFreePool(firmwareData->SymbolicLinkName.Buffer); ! 2554: ExFreePool(firmwareData); ! 2555: ! 2556: } ! 2557: ! 2558: } ! 2559: ! 2560: if (userSubKey) { ! 2561: ! 2562: ExFreePool(userSubKey); ! 2563: ! 2564: } ! 2565: ! 2566: if (userSymbolicLink.Buffer) { ! 2567: ! 2568: ExFreePool(userSymbolicLink.Buffer); ! 2569: ! 2570: } ! 2571: ! 2572: if (parametersPath.Buffer) { ! 2573: ! 2574: ExFreePool(parametersPath.Buffer); ! 2575: ! 2576: } ! 2577: ! 2578: if (parameters) { ! 2579: ! 2580: ExFreePool(parameters); ! 2581: ! 2582: } ! 2583: } ! 2584: ! 2585: BOOLEAN ! 2586: ParPutInConfigList( ! 2587: IN PDRIVER_OBJECT DriverObject, ! 2588: IN OUT PLIST_ENTRY ConfigList, ! 2589: IN PCONFIG_DATA New ! 2590: ) ! 2591: ! 2592: /*++ ! 2593: ! 2594: Routine Description: ! 2595: ! 2596: Given a new config record and a config list, this routine ! 2597: will perform a check to make sure that the new record doesn't ! 2598: conflict with old records. ! 2599: ! 2600: If everything checks out it will insert the new config record ! 2601: into the config list. ! 2602: ! 2603: Arguments: ! 2604: ! 2605: DriverObject - The driver we are attempting to get configuration ! 2606: information for. ! 2607: ! 2608: ConfigList - Listhead for a list of configuration records for ! 2609: ports to control. ! 2610: ! 2611: New = Pointer to new configuration record to add. ! 2612: ! 2613: Return Value: ! 2614: ! 2615: True if the record was added to the config list, false otherwise. ! 2616: ! 2617: --*/ ! 2618: ! 2619: { ! 2620: ! 2621: PHYSICAL_ADDRESS parPhysicalMax; ! 2622: ! 2623: parPhysicalMax.LowPart = (ULONG)~0; ! 2624: parPhysicalMax.HighPart = ~0; ! 2625: ! 2626: ParDump( ! 2627: PARCONFIG, ! 2628: ("PARALLEL: Attempting to add %wZ\n" ! 2629: "-------- to the config list\n" ! 2630: "-------- PortAddress is %x\n" ! 2631: "-------- BusNumber is %d\n" ! 2632: "-------- BusType is %d\n" ! 2633: "-------- AddressSpace is %d\n", ! 2634: &New->NtNameForPort, ! 2635: New->Controller.LowPart, ! 2636: New->BusNumber, ! 2637: New->InterfaceType, ! 2638: New->AddressSpace ! 2639: ) ! 2640: ); ! 2641: ! 2642: // ! 2643: // We don't support any boards whose memory wraps around ! 2644: // the physical address space. ! 2645: // ! 2646: ! 2647: if (ParMemCompare( ! 2648: New->Controller, ! 2649: New->SpanOfController, ! 2650: parPhysicalMax, ! 2651: (ULONG)0 ! 2652: ) != AddressesAreDisjoint) { ! 2653: ! 2654: ParLogError( ! 2655: DriverObject, ! 2656: NULL, ! 2657: New->Controller, ! 2658: ParPhysicalZero, ! 2659: 0, ! 2660: 0, ! 2661: 0, ! 2662: 30, ! 2663: STATUS_SUCCESS, ! 2664: PAR_DEVICE_TOO_HIGH ! 2665: ); ! 2666: ParDump( ! 2667: PARERRORS, ! 2668: ("PARALLEL: Error in config record for %wZ\n" ! 2669: "-------- registers rap around physical memory\n", ! 2670: &New->NtNameForPort) ! 2671: ); ! 2672: return FALSE; ! 2673: ! 2674: } ! 2675: ! 2676: // ! 2677: // Go through the list looking for previous devices ! 2678: // with the same address. ! 2679: // ! 2680: ! 2681: if (!IsListEmpty(ConfigList)) { ! 2682: ! 2683: PLIST_ENTRY CurrentConfigListEntry = ConfigList->Flink; ! 2684: ! 2685: do { ! 2686: ! 2687: PCONFIG_DATA OldConfig = CONTAINING_RECORD( ! 2688: CurrentConfigListEntry, ! 2689: CONFIG_DATA, ! 2690: ConfigList ! 2691: ); ! 2692: ! 2693: // ! 2694: // We only care about ports that are on the same bus. ! 2695: // ! 2696: ! 2697: if ((OldConfig->InterfaceType == New->InterfaceType) && ! 2698: (OldConfig->BusNumber == New->BusNumber)) { ! 2699: ! 2700: ParDump( ! 2701: PARCONFIG, ! 2702: ("PARALLEL: Comparing it to %wZ\n" ! 2703: "-------- already in the config list\n" ! 2704: "-------- PortAddress is %x\n" ! 2705: "-------- BusNumber is %d\n" ! 2706: "-------- BusType is %d\n" ! 2707: "-------- AddressSpace is %d\n", ! 2708: &OldConfig->NtNameForPort, ! 2709: OldConfig->Controller.LowPart, ! 2710: OldConfig->BusNumber, ! 2711: OldConfig->InterfaceType, ! 2712: OldConfig->AddressSpace ! 2713: ) ! 2714: ); ! 2715: ! 2716: if (ParMemCompare( ! 2717: New->Controller, ! 2718: New->SpanOfController, ! 2719: OldConfig->Controller, ! 2720: OldConfig->SpanOfController ! 2721: ) != AddressesAreDisjoint) { ! 2722: ! 2723: ParLogError( ! 2724: DriverObject, ! 2725: NULL, ! 2726: New->Controller, ! 2727: OldConfig->Controller, ! 2728: 0, ! 2729: 0, ! 2730: 0, ! 2731: 31, ! 2732: STATUS_SUCCESS, ! 2733: PAR_CONTROL_OVERLAP ! 2734: ); ! 2735: return FALSE; ! 2736: ! 2737: } ! 2738: ! 2739: } ! 2740: ! 2741: CurrentConfigListEntry = CurrentConfigListEntry->Flink; ! 2742: ! 2743: } while (CurrentConfigListEntry != ConfigList); ! 2744: ! 2745: } ! 2746: ! 2747: InsertTailList( ! 2748: ConfigList, ! 2749: &New->ConfigList ! 2750: ); ! 2751: ! 2752: return TRUE; ! 2753: ! 2754: } ! 2755: ! 2756: PVOID ! 2757: ParGetMappedAddress( ! 2758: IN INTERFACE_TYPE BusType, ! 2759: IN ULONG BusNumber, ! 2760: PHYSICAL_ADDRESS IoAddress, ! 2761: ULONG NumberOfBytes, ! 2762: ULONG AddressSpace, ! 2763: PBOOLEAN MappedAddress ! 2764: ) ! 2765: ! 2766: /*++ ! 2767: ! 2768: Routine Description: ! 2769: ! 2770: This routine maps an IO address to system address space. ! 2771: ! 2772: Arguments: ! 2773: ! 2774: BusType - what type of bus - eisa, mca, isa ! 2775: IoBusNumber - which IO bus (for machines with multiple buses). ! 2776: IoAddress - base device address to be mapped. ! 2777: NumberOfBytes - number of bytes for which address is valid. ! 2778: AddressSpace - Denotes whether the address is in io space or memory. ! 2779: MappedAddress - indicates whether the address was mapped. ! 2780: This only has meaning if the address returned ! 2781: is non-null. ! 2782: ! 2783: Return Value: ! 2784: ! 2785: Mapped address ! 2786: ! 2787: --*/ ! 2788: ! 2789: { ! 2790: PHYSICAL_ADDRESS cardAddress; ! 2791: PVOID address; ! 2792: ! 2793: HalTranslateBusAddress( ! 2794: BusType, ! 2795: BusNumber, ! 2796: IoAddress, ! 2797: &AddressSpace, ! 2798: &cardAddress ! 2799: ); ! 2800: ! 2801: // ! 2802: // Map the device base address into the virtual address space ! 2803: // if the address is in memory space. ! 2804: // ! 2805: ! 2806: if (!AddressSpace) { ! 2807: ! 2808: address = MmMapIoSpace( ! 2809: cardAddress, ! 2810: NumberOfBytes, ! 2811: FALSE ! 2812: ); ! 2813: ! 2814: *MappedAddress = (BOOLEAN)((address)?(TRUE):(FALSE)); ! 2815: ! 2816: } else { ! 2817: ! 2818: address = (PVOID)cardAddress.LowPart; ! 2819: *MappedAddress = FALSE; ! 2820: ! 2821: } ! 2822: ! 2823: return address; ! 2824: ! 2825: } ! 2826: ! 2827: VOID ! 2828: ParSetupExternalNaming( ! 2829: IN PPAR_DEVICE_EXTENSION Extension ! 2830: ) ! 2831: ! 2832: /*++ ! 2833: ! 2834: Routine Description: ! 2835: ! 2836: This routine will be used to create a symbolic link ! 2837: to the driver name in the given object directory. ! 2838: ! 2839: It will also create an entry in the device map for ! 2840: this device if the symbolic link was created. ! 2841: ! 2842: Arguments: ! 2843: ! 2844: Extension - Pointer to the device extension. ! 2845: ! 2846: Return Value: ! 2847: ! 2848: None. ! 2849: ! 2850: --*/ ! 2851: ! 2852: { ! 2853: ! 2854: UNICODE_STRING fullLinkName; ! 2855: ! 2856: // ! 2857: // Form the full symbolic link name we wish to create. ! 2858: // ! 2859: ! 2860: RtlInitUnicodeString( ! 2861: &fullLinkName, ! 2862: NULL ! 2863: ); ! 2864: ! 2865: // ! 2866: // Allocate some pool for the name. ! 2867: // ! 2868: ! 2869: fullLinkName.MaximumLength = (sizeof(L"\\")*2) + ! 2870: Extension->ObjectDirectory.Length+ ! 2871: Extension->SymbolicLinkName.Length+ ! 2872: sizeof(WCHAR); ! 2873: ! 2874: ! 2875: ! 2876: fullLinkName.Buffer = ExAllocatePool( ! 2877: PagedPool, ! 2878: fullLinkName.MaximumLength ! 2879: ); ! 2880: ! 2881: if (!fullLinkName.Buffer) { ! 2882: ! 2883: // ! 2884: // Couldn't allocate space for the name. Just go on ! 2885: // to the device map stuff. ! 2886: // ! 2887: ! 2888: ParLogError( ! 2889: Extension->DeviceObject->DriverObject, ! 2890: Extension->DeviceObject, ! 2891: Extension->OriginalController, ! 2892: ParPhysicalZero, ! 2893: 0, ! 2894: 0, ! 2895: 0, ! 2896: 32, ! 2897: STATUS_SUCCESS, ! 2898: PAR_INSUFFICIENT_RESOURCES ! 2899: ); ! 2900: ParDump( ! 2901: PARERRORS, ! 2902: ("PARALLEL: Couldn't allocate space for the symbolic \n" ! 2903: "-------- name for creating the link\n" ! 2904: "-------- for port %wZ\n", ! 2905: &Extension->DeviceName) ! 2906: ); ! 2907: ! 2908: } else { ! 2909: ! 2910: NTSTATUS status; ! 2911: RtlZeroMemory( ! 2912: fullLinkName.Buffer, ! 2913: fullLinkName.MaximumLength ! 2914: ); ! 2915: ! 2916: RtlAppendUnicodeToString( ! 2917: &fullLinkName, ! 2918: L"\\" ! 2919: ); ! 2920: ! 2921: RtlAppendUnicodeStringToString( ! 2922: &fullLinkName, ! 2923: &Extension->ObjectDirectory ! 2924: ); ! 2925: ! 2926: RtlAppendUnicodeToString( ! 2927: &fullLinkName, ! 2928: L"\\" ! 2929: ); ! 2930: ! 2931: RtlAppendUnicodeStringToString( ! 2932: &fullLinkName, ! 2933: &Extension->SymbolicLinkName ! 2934: ); ! 2935: ! 2936: status = IoCreateUnprotectedSymbolicLink( ! 2937: &fullLinkName, ! 2938: &Extension->DeviceName ! 2939: ); ! 2940: ! 2941: if (!NT_SUCCESS(status)) { ! 2942: ! 2943: // ! 2944: // Oh well, couldn't create the symbolic link. ! 2945: // ! 2946: ! 2947: ParDump( ! 2948: PARERRORS, ! 2949: ("PARALLEL: Couldn't create the symbolic link\n" ! 2950: "-------- for port %wZ\n", ! 2951: &Extension->DeviceName) ! 2952: ); ! 2953: ParLogError( ! 2954: Extension->DeviceObject->DriverObject, ! 2955: Extension->DeviceObject, ! 2956: Extension->OriginalController, ! 2957: ParPhysicalZero, ! 2958: 0, ! 2959: 0, ! 2960: 0, ! 2961: 33, ! 2962: status, ! 2963: PAR_NO_SYMLINK_CREATED ! 2964: ); ! 2965: ! 2966: } else { ! 2967: ! 2968: Extension->CreatedSymbolicLink = TRUE; ! 2969: ! 2970: status = RtlWriteRegistryValue( ! 2971: RTL_REGISTRY_DEVICEMAP, ! 2972: L"PARALLEL PORTS", ! 2973: Extension->NtNameForPort.Buffer, ! 2974: REG_SZ, ! 2975: Extension->SymbolicLinkName.Buffer, ! 2976: Extension->SymbolicLinkName.Length+sizeof(WCHAR) ! 2977: ); ! 2978: ! 2979: if (!NT_SUCCESS(status)) { ! 2980: ! 2981: // ! 2982: // Oh well, it didn't work. Just go to cleanup. ! 2983: // ! 2984: ! 2985: ParDump( ! 2986: PARERRORS, ! 2987: ("PARALLEL: Couldn't create the device map entry\n" ! 2988: "-------- for port %wZ\n", ! 2989: &Extension->DeviceName) ! 2990: ); ! 2991: ParLogError( ! 2992: Extension->DeviceObject->DriverObject, ! 2993: Extension->DeviceObject, ! 2994: Extension->OriginalController, ! 2995: ParPhysicalZero, ! 2996: 0, ! 2997: 0, ! 2998: 0, ! 2999: 34, ! 3000: status, ! 3001: PAR_NO_DEVICE_MAP_CREATED ! 3002: ); ! 3003: ! 3004: } ! 3005: ! 3006: } ! 3007: ! 3008: ExFreePool(fullLinkName.Buffer); ! 3009: ! 3010: } ! 3011: ! 3012: } ! 3013: ! 3014: PAR_MEM_COMPARES ! 3015: ParMemCompare( ! 3016: IN PHYSICAL_ADDRESS A, ! 3017: IN ULONG SpanOfA, ! 3018: IN PHYSICAL_ADDRESS B, ! 3019: IN ULONG SpanOfB ! 3020: ) ! 3021: ! 3022: /*++ ! 3023: ! 3024: Routine Description: ! 3025: ! 3026: Compare two phsical address. ! 3027: ! 3028: Arguments: ! 3029: ! 3030: A - One half of the comparison. ! 3031: ! 3032: SpanOfA - In units of bytes, the span of A. ! 3033: ! 3034: B - One half of the comparison. ! 3035: ! 3036: SpanOfB - In units of bytes, the span of B. ! 3037: ! 3038: ! 3039: Return Value: ! 3040: ! 3041: The result of the comparison. ! 3042: ! 3043: --*/ ! 3044: ! 3045: { ! 3046: ! 3047: LARGE_INTEGER a; ! 3048: LARGE_INTEGER b; ! 3049: ! 3050: LARGE_INTEGER lower; ! 3051: ULONG lowerSpan; ! 3052: LARGE_INTEGER higher; ! 3053: ! 3054: a.LowPart = A.LowPart; ! 3055: a.HighPart = A.HighPart; ! 3056: b.LowPart = B.LowPart; ! 3057: b.HighPart = B.HighPart; ! 3058: ! 3059: if (RtlLargeIntegerEqualTo( ! 3060: a, ! 3061: b ! 3062: )) { ! 3063: ! 3064: return AddressesAreEqual; ! 3065: ! 3066: } ! 3067: ! 3068: if (RtlLargeIntegerGreaterThan( ! 3069: a, ! 3070: b ! 3071: )) { ! 3072: ! 3073: higher = a; ! 3074: lower = b; ! 3075: lowerSpan = SpanOfB; ! 3076: ! 3077: } else { ! 3078: ! 3079: higher = b; ! 3080: lower = a; ! 3081: lowerSpan = SpanOfA; ! 3082: ! 3083: } ! 3084: ! 3085: if (RtlLargeIntegerGreaterThanOrEqualTo( ! 3086: RtlLargeIntegerSubtract( ! 3087: higher, ! 3088: lower ! 3089: ), ! 3090: RtlConvertUlongToLargeInteger(lowerSpan) ! 3091: )) { ! 3092: ! 3093: return AddressesAreDisjoint; ! 3094: ! 3095: } ! 3096: ! 3097: return AddressesOverlap; ! 3098: ! 3099: } ! 3100: ! 3101: VOID ! 3102: ParLogError( ! 3103: IN PDRIVER_OBJECT DriverObject, ! 3104: IN PDEVICE_OBJECT DeviceObject OPTIONAL, ! 3105: IN PHYSICAL_ADDRESS P1, ! 3106: IN PHYSICAL_ADDRESS P2, ! 3107: IN ULONG SequenceNumber, ! 3108: IN UCHAR MajorFunctionCode, ! 3109: IN UCHAR RetryCount, ! 3110: IN ULONG UniqueErrorValue, ! 3111: IN NTSTATUS FinalStatus, ! 3112: IN NTSTATUS SpecificIOStatus ! 3113: ) ! 3114: ! 3115: /*++ ! 3116: ! 3117: Routine Description: ! 3118: ! 3119: This routine allocates an error log entry, copies the supplied data ! 3120: to it, and requests that it be written to the error log file. ! 3121: ! 3122: Arguments: ! 3123: ! 3124: DriverObject - A pointer to the driver object for the device. ! 3125: ! 3126: DeviceObject - A pointer to the device object associated with the ! 3127: device that had the error, early in initialization, one may not ! 3128: yet exist. ! 3129: ! 3130: P1,P2 - If phyical addresses for the controller ports involved ! 3131: with the error are available, put them through as dump data. ! 3132: ! 3133: SequenceNumber - A ulong value that is unique to an IRP over the ! 3134: life of the irp in this driver - 0 generally means an error not ! 3135: associated with an irp. ! 3136: ! 3137: MajorFunctionCode - If there is an error associated with the irp, ! 3138: this is the major function code of that irp. ! 3139: ! 3140: RetryCount - The number of times a particular operation has been ! 3141: retried. ! 3142: ! 3143: UniqueErrorValue - A unique long word that identifies the particular ! 3144: call to this function. ! 3145: ! 3146: FinalStatus - The final status given to the irp that was associated ! 3147: with this error. If this log entry is being made during one of ! 3148: the retries this value will be STATUS_SUCCESS. ! 3149: ! 3150: SpecificIOStatus - The IO status for a particular error. ! 3151: ! 3152: Return Value: ! 3153: ! 3154: None. ! 3155: ! 3156: --*/ ! 3157: ! 3158: { ! 3159: PIO_ERROR_LOG_PACKET errorLogEntry; ! 3160: ! 3161: PVOID objectToUse; ! 3162: SHORT dumpToAllocate = 0; ! 3163: ! 3164: if (ARGUMENT_PRESENT(DeviceObject)) { ! 3165: ! 3166: objectToUse = DeviceObject; ! 3167: ! 3168: } else { ! 3169: ! 3170: objectToUse = DriverObject; ! 3171: ! 3172: } ! 3173: ! 3174: if (ParMemCompare( ! 3175: P1, ! 3176: (ULONG)1, ! 3177: ParPhysicalZero, ! 3178: (ULONG)1 ! 3179: ) != AddressesAreEqual) { ! 3180: ! 3181: dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS); ! 3182: ! 3183: } ! 3184: ! 3185: if (ParMemCompare( ! 3186: P2, ! 3187: (ULONG)1, ! 3188: ParPhysicalZero, ! 3189: (ULONG)1 ! 3190: ) != AddressesAreEqual) { ! 3191: ! 3192: dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS); ! 3193: ! 3194: } ! 3195: ! 3196: errorLogEntry = IoAllocateErrorLogEntry( ! 3197: objectToUse, ! 3198: (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + dumpToAllocate) ! 3199: ); ! 3200: ! 3201: if ( errorLogEntry != NULL ) { ! 3202: ! 3203: errorLogEntry->ErrorCode = SpecificIOStatus; ! 3204: errorLogEntry->SequenceNumber = SequenceNumber; ! 3205: errorLogEntry->MajorFunctionCode = MajorFunctionCode; ! 3206: errorLogEntry->RetryCount = RetryCount; ! 3207: errorLogEntry->UniqueErrorValue = UniqueErrorValue; ! 3208: errorLogEntry->FinalStatus = FinalStatus; ! 3209: errorLogEntry->DumpDataSize = dumpToAllocate; ! 3210: ! 3211: if (dumpToAllocate) { ! 3212: ! 3213: RtlCopyMemory( ! 3214: &errorLogEntry->DumpData[0], ! 3215: &P1, ! 3216: sizeof(PHYSICAL_ADDRESS) ! 3217: ); ! 3218: ! 3219: if (dumpToAllocate > sizeof(PHYSICAL_ADDRESS)) { ! 3220: ! 3221: RtlCopyMemory( ! 3222: ((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS), ! 3223: &P2, ! 3224: sizeof(PHYSICAL_ADDRESS) ! 3225: ); ! 3226: ! 3227: } ! 3228: ! 3229: } ! 3230: ! 3231: ! 3232: ! 3233: IoWriteErrorLogEntry(errorLogEntry); ! 3234: ! 3235: } ! 3236: ! 3237: } ! 3238: ! 3239: VOID ! 3240: ParReportResourcesDevice( ! 3241: IN PPAR_DEVICE_EXTENSION Extension, ! 3242: IN BOOLEAN ClaimInterrupt, ! 3243: OUT BOOLEAN *ConflictDetected ! 3244: ) ! 3245: ! 3246: /*++ ! 3247: ! 3248: Routine Description: ! 3249: ! 3250: This routine reports the resources used for a device that ! 3251: is "ready" to run. If some conflict was detected, it doesn't ! 3252: matter, the reources are reported. ! 3253: ! 3254: Arguments: ! 3255: ! 3256: Extension - The device extension of the device we are reporting ! 3257: resources for. ! 3258: ! 3259: ClaimInterrupts - If this was true then we should try to ! 3260: claim the interrupt that goes with this ! 3261: device ! 3262: ! 3263: ConflictDetected - Pointer to a boolean that we will pass ! 3264: to the resource reporting code. ! 3265: ! 3266: Return Value: ! 3267: ! 3268: None. ! 3269: ! 3270: --*/ ! 3271: ! 3272: { ! 3273: ! 3274: PCM_RESOURCE_LIST resourceList; ! 3275: ULONG countOfPartials = 1; ! 3276: ULONG sizeOfResourceList; ! 3277: PCM_PARTIAL_RESOURCE_DESCRIPTOR partial; ! 3278: UNICODE_STRING className; ! 3279: ! 3280: ParDump( ! 3281: PARCONFIG, ! 3282: ("PARALLEL: In ParReportResourcesDevice\n" ! 3283: "-------- for extension %x of port %wZ\n", ! 3284: Extension,&Extension->DeviceName) ! 3285: ); ! 3286: ! 3287: // ! 3288: // The resource list for a device will consist of ! 3289: // ! 3290: // The resource list record itself with a count ! 3291: // of one for the single "built in" full resource ! 3292: // descriptor. ! 3293: // ! 3294: // The built-in full resource descriptor will contain ! 3295: // the bus type and busnumber and the built in partial ! 3296: // resource list. ! 3297: // ! 3298: // The built in partial resource list will have a count of 1 or 2: ! 3299: // ! 3300: // 1) The base register physical address and it's span. ! 3301: // ! 3302: // 2) If the device is using an interrupt then it will ! 3303: // report that resource. ! 3304: // ! 3305: // ! 3306: ! 3307: if (ClaimInterrupt) { ! 3308: ! 3309: countOfPartials = 2; ! 3310: ! 3311: } ! 3312: ! 3313: sizeOfResourceList = sizeof(CM_RESOURCE_LIST) + ! 3314: (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)* ! 3315: (countOfPartials-1)); ! 3316: ! 3317: resourceList = ExAllocatePool( ! 3318: PagedPool, ! 3319: sizeOfResourceList ! 3320: ); ! 3321: ! 3322: if (!resourceList) { ! 3323: ! 3324: // ! 3325: // Oh well, can't allocate the memory. Act as though ! 3326: // we succeeded. ! 3327: // ! 3328: ! 3329: ParLogError( ! 3330: Extension->DeviceObject->DriverObject, ! 3331: Extension->DeviceObject, ! 3332: Extension->OriginalController, ! 3333: ParPhysicalZero, ! 3334: 0, ! 3335: 0, ! 3336: 0, ! 3337: 35, ! 3338: STATUS_SUCCESS, ! 3339: PAR_INSUFFICIENT_RESOURCES ! 3340: ); ! 3341: return; ! 3342: ! 3343: } ! 3344: ! 3345: RtlZeroMemory( ! 3346: resourceList, ! 3347: sizeOfResourceList ! 3348: ); ! 3349: ! 3350: resourceList->Count = 1; ! 3351: ! 3352: resourceList->List[0].InterfaceType = Extension->InterfaceType; ! 3353: resourceList->List[0].BusNumber = Extension->BusNumber; ! 3354: resourceList->List[0].PartialResourceList.Count = countOfPartials; ! 3355: partial = &resourceList->List[0].PartialResourceList.PartialDescriptors[0]; ! 3356: ! 3357: // ! 3358: // Account for the space used by the controller. ! 3359: // ! 3360: ! 3361: partial->Type = CmResourceTypePort; ! 3362: partial->ShareDisposition = CmResourceShareDeviceExclusive; ! 3363: partial->Flags = (USHORT)Extension->AddressSpace; ! 3364: partial->u.Port.Start = Extension->OriginalController; ! 3365: partial->u.Port.Length = Extension->SpanOfController; ! 3366: ! 3367: partial++; ! 3368: ! 3369: if (ClaimInterrupt) { ! 3370: ! 3371: // ! 3372: // Report the interrupt information. ! 3373: // ! 3374: ! 3375: partial->Type = CmResourceTypeInterrupt; ! 3376: ! 3377: if (Extension->InterruptShareable) { ! 3378: ! 3379: partial->ShareDisposition = CmResourceShareShared; ! 3380: ! 3381: } else { ! 3382: ! 3383: partial->ShareDisposition = CmResourceShareDeviceExclusive; ! 3384: ! 3385: } ! 3386: ! 3387: if (Extension->InterruptMode == Latched) { ! 3388: ! 3389: partial->Flags = CM_RESOURCE_INTERRUPT_LATCHED; ! 3390: ! 3391: } else { ! 3392: ! 3393: partial->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 3394: ! 3395: } ! 3396: ! 3397: partial->u.Interrupt.Vector = Extension->OriginalVector; ! 3398: partial->u.Interrupt.Level = Extension->OriginalIrql; ! 3399: ! 3400: } ! 3401: ! 3402: RtlInitUnicodeString( ! 3403: &className, ! 3404: L"LOADED PARALLEL DRIVER RESOURCES" ! 3405: ); ! 3406: ! 3407: IoReportResourceUsage( ! 3408: &className, ! 3409: Extension->DeviceObject->DriverObject, ! 3410: NULL, ! 3411: 0, ! 3412: Extension->DeviceObject, ! 3413: resourceList, ! 3414: sizeOfResourceList, ! 3415: FALSE, ! 3416: ConflictDetected ! 3417: ); ! 3418: ! 3419: ExFreePool(resourceList); ! 3420: ! 3421: } ! 3422: ! 3423: VOID ! 3424: ParUnload( ! 3425: IN PDRIVER_OBJECT DriverObject ! 3426: ) ! 3427: ! 3428: /*++ ! 3429: ! 3430: Routine Description: ! 3431: ! 3432: This routine cleans up all of the memory associated with ! 3433: any of the devices belonging to the driver. It will ! 3434: loop through the device list. ! 3435: ! 3436: Arguments: ! 3437: ! 3438: DriverObject - Pointer to the driver object controling all of the ! 3439: devices. ! 3440: ! 3441: Return Value: ! 3442: ! 3443: None. ! 3444: ! 3445: --*/ ! 3446: ! 3447: { ! 3448: ! 3449: PDEVICE_OBJECT currentDevice = DriverObject->DeviceObject; ! 3450: ! 3451: ParDump( ! 3452: PARUNLOAD, ! 3453: ("PARALLEL: In ParUnload\n") ! 3454: ); ! 3455: ! 3456: while (currentDevice) { ! 3457: ! 3458: // ! 3459: // Disable the device from interrupting. ! 3460: // ! 3461: ! 3462: StoreControl( ! 3463: ((PPAR_DEVICE_EXTENSION)currentDevice->DeviceExtension)->Controller, ! 3464: PAR_CONTROL_WR_CONTROL ! 3465: ); ! 3466: ParUnReportResourcesDevice(currentDevice->DeviceExtension); ! 3467: ParCleanupDevice(currentDevice->DeviceExtension); ! 3468: IoDeleteDevice(currentDevice); ! 3469: IoGetConfigurationInformation()->ParallelCount--; ! 3470: ! 3471: currentDevice = DriverObject->DeviceObject; ! 3472: ! 3473: } ! 3474: ! 3475: } ! 3476: ! 3477: VOID ! 3478: ParCleanupDevice( ! 3479: IN PPAR_DEVICE_EXTENSION Extension ! 3480: ) ! 3481: ! 3482: /*++ ! 3483: ! 3484: Routine Description: ! 3485: ! 3486: This routine will deallocate all of the memory used for ! 3487: a particular device. It will also disconnect any resources ! 3488: if need be. ! 3489: ! 3490: Arguments: ! 3491: ! 3492: Extension - Pointer to the device extension which is getting ! 3493: rid of all it's resources. ! 3494: ! 3495: Return Value: ! 3496: ! 3497: None. ! 3498: ! 3499: --*/ ! 3500: ! 3501: { ! 3502: ! 3503: ParDump( ! 3504: PARUNLOAD, ! 3505: ("PARALLEL: in ParCleanupDevice for extension: %x\n",Extension) ! 3506: ); ! 3507: ! 3508: if (Extension) { ! 3509: ! 3510: // ! 3511: // Get rid of all external naming as well as removing ! 3512: // the device map entry. ! 3513: // ! 3514: ! 3515: ParCleanupExternalNaming(Extension); ! 3516: ! 3517: // ! 3518: // Delallocate the memory for the various names. ! 3519: // NOTE: If we have an extension - Then we must ! 3520: // have a device name stored away. Which is *not* ! 3521: // true for the other names. ! 3522: // ! 3523: ! 3524: ExFreePool(Extension->DeviceName.Buffer); ! 3525: ! 3526: if (Extension->ObjectDirectory.Buffer) { ! 3527: ! 3528: ExFreePool(Extension->ObjectDirectory.Buffer); ! 3529: ! 3530: } ! 3531: ! 3532: if (Extension->NtNameForPort.Buffer) { ! 3533: ! 3534: ExFreePool(Extension->NtNameForPort.Buffer); ! 3535: ! 3536: } ! 3537: ! 3538: if (Extension->SymbolicLinkName.Buffer) { ! 3539: ! 3540: ExFreePool(Extension->SymbolicLinkName.Buffer); ! 3541: ! 3542: } ! 3543: ! 3544: // ! 3545: // If necessary, unmap the device registers. ! 3546: // ! 3547: ! 3548: if (Extension->UnMapRegisters) { ! 3549: ! 3550: MmUnmapIoSpace( ! 3551: Extension->Controller, ! 3552: Extension->SpanOfController ! 3553: ); ! 3554: ! 3555: } ! 3556: ! 3557: } ! 3558: ! 3559: } ! 3560: ! 3561: VOID ! 3562: ParCleanupExternalNaming( ! 3563: IN PPAR_DEVICE_EXTENSION Extension ! 3564: ) ! 3565: ! 3566: /*++ ! 3567: ! 3568: Routine Description: ! 3569: ! 3570: This routine will be used to delete a symbolic link ! 3571: to the driver name in the given object directory. ! 3572: ! 3573: It will also delete an entry in the device map for ! 3574: this device. ! 3575: ! 3576: Arguments: ! 3577: ! 3578: Extension - Pointer to the device extension. ! 3579: ! 3580: Return Value: ! 3581: ! 3582: None. ! 3583: ! 3584: --*/ ! 3585: ! 3586: { ! 3587: ! 3588: UNICODE_STRING fullLinkName; ! 3589: ! 3590: ParDump( ! 3591: PARUNLOAD, ! 3592: ("PARALLEL: In ParCleanupExternalNaming for\n" ! 3593: "-------- extension: %x of port %wZ\n", ! 3594: Extension,&Extension->DeviceName) ! 3595: ); ! 3596: ! 3597: // ! 3598: // We're cleaning up here. One reason we're cleaning up ! 3599: // is that we couldn't allocate space for the directory ! 3600: // name or the symbolic link. ! 3601: // ! 3602: ! 3603: if (Extension->ObjectDirectory.Buffer && ! 3604: Extension->SymbolicLinkName.Buffer && ! 3605: Extension->CreatedSymbolicLink) { ! 3606: ! 3607: // ! 3608: // Form the full symbolic link name we wish to create. ! 3609: // ! 3610: ! 3611: RtlInitUnicodeString( ! 3612: &fullLinkName, ! 3613: NULL ! 3614: ); ! 3615: ! 3616: // ! 3617: // Allocate some pool for the name. ! 3618: // ! 3619: ! 3620: fullLinkName.MaximumLength = (sizeof(L"\\")*2) + ! 3621: Extension->ObjectDirectory.Length+ ! 3622: Extension->SymbolicLinkName.Length+ ! 3623: sizeof(WCHAR); ! 3624: ! 3625: fullLinkName.Buffer = ExAllocatePool( ! 3626: PagedPool, ! 3627: fullLinkName.MaximumLength ! 3628: ); ! 3629: ! 3630: if (!fullLinkName.Buffer) { ! 3631: ! 3632: // ! 3633: // Couldn't allocate space for the name. Just go on ! 3634: // to the device map stuff. ! 3635: // ! 3636: ! 3637: ParLogError( ! 3638: Extension->DeviceObject->DriverObject, ! 3639: Extension->DeviceObject, ! 3640: Extension->OriginalController, ! 3641: ParPhysicalZero, ! 3642: 0, ! 3643: 0, ! 3644: 0, ! 3645: 36, ! 3646: STATUS_SUCCESS, ! 3647: PAR_INSUFFICIENT_RESOURCES ! 3648: ); ! 3649: ParDump( ! 3650: PARERRORS, ! 3651: ("PARALLEL: Couldn't allocate space for the symbolic \n" ! 3652: "-------- name for creating the link\n" ! 3653: "-------- for port %wZ on cleanup\n", ! 3654: &Extension->DeviceName) ! 3655: ); ! 3656: ! 3657: } else { ! 3658: ! 3659: RtlZeroMemory( ! 3660: fullLinkName.Buffer, ! 3661: fullLinkName.MaximumLength ! 3662: ); ! 3663: ! 3664: RtlAppendUnicodeToString( ! 3665: &fullLinkName, ! 3666: L"\\" ! 3667: ); ! 3668: ! 3669: RtlAppendUnicodeStringToString( ! 3670: &fullLinkName, ! 3671: &Extension->ObjectDirectory ! 3672: ); ! 3673: ! 3674: RtlAppendUnicodeToString( ! 3675: &fullLinkName, ! 3676: L"\\" ! 3677: ); ! 3678: ! 3679: RtlAppendUnicodeStringToString( ! 3680: &fullLinkName, ! 3681: &Extension->SymbolicLinkName ! 3682: ); ! 3683: ! 3684: IoDeleteSymbolicLink(&fullLinkName); ! 3685: ! 3686: ExFreePool(fullLinkName.Buffer); ! 3687: ! 3688: } ! 3689: ! 3690: // ! 3691: // We're cleaning up here. One reason we're cleaning up ! 3692: // is that we couldn't allocate space for the NtNameOfPort. ! 3693: // ! 3694: ! 3695: if (Extension->NtNameForPort.Buffer) { ! 3696: ! 3697: NTSTATUS status; ! 3698: ! 3699: status = RtlDeleteRegistryValue( ! 3700: RTL_REGISTRY_DEVICEMAP, ! 3701: L"PARALLEL PORTS", ! 3702: Extension->NtNameForPort.Buffer ! 3703: ); ! 3704: ! 3705: if (!NT_SUCCESS(status)) { ! 3706: ! 3707: ParLogError( ! 3708: Extension->DeviceObject->DriverObject, ! 3709: Extension->DeviceObject, ! 3710: Extension->OriginalController, ! 3711: ParPhysicalZero, ! 3712: 0, ! 3713: 0, ! 3714: 0, ! 3715: 37, ! 3716: status, ! 3717: PAR_NO_DEVICE_MAP_DELETED ! 3718: ); ! 3719: ParDump( ! 3720: PARERRORS, ! 3721: ("PARALLEL: Couldn't delete value entry %wZ\n", ! 3722: &Extension->DeviceName) ! 3723: ); ! 3724: ! 3725: } ! 3726: ! 3727: } ! 3728: ! 3729: } ! 3730: ! 3731: } ! 3732: ! 3733: VOID ! 3734: ParUnReportResourcesDevice( ! 3735: IN PPAR_DEVICE_EXTENSION Extension ! 3736: ) ! 3737: ! 3738: /*++ ! 3739: ! 3740: Routine Description: ! 3741: ! 3742: Purge the resources for this particular device. ! 3743: ! 3744: Arguments: ! 3745: ! 3746: Extension - The device extension of the device we are *un*reporting ! 3747: resources for. ! 3748: ! 3749: Return Value: ! 3750: ! 3751: None. ! 3752: ! 3753: --*/ ! 3754: ! 3755: { ! 3756: ! 3757: CM_RESOURCE_LIST resourceList; ! 3758: ULONG sizeOfResourceList = 0; ! 3759: UNICODE_STRING className; ! 3760: BOOLEAN junkBoolean; ! 3761: ! 3762: ParDump( ! 3763: PARUNLOAD, ! 3764: ("PARALLEL: In ParUnreportResourcesDevice\n" ! 3765: "-------- for extension %x of port %wZ\n", ! 3766: Extension,&Extension->DeviceName) ! 3767: ); ! 3768: RtlZeroMemory( ! 3769: &resourceList, ! 3770: sizeof(CM_RESOURCE_LIST) ! 3771: ); ! 3772: ! 3773: resourceList.Count = 0; ! 3774: ! 3775: RtlInitUnicodeString( ! 3776: &className, ! 3777: L"LOADED PARALLEL DRIVER RESOURCES" ! 3778: ); ! 3779: ! 3780: IoReportResourceUsage( ! 3781: &className, ! 3782: Extension->DeviceObject->DriverObject, ! 3783: NULL, ! 3784: 0, ! 3785: Extension->DeviceObject, ! 3786: &resourceList, ! 3787: sizeof(CM_RESOURCE_LIST), ! 3788: FALSE, ! 3789: &junkBoolean ! 3790: ); ! 3791: ! 3792: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.