Annotation of ntddk/src/comm/parallel/initunlo.c, revision 1.1.1.1

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:             &paramTable[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:                             &paramTable[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:         &parametersPath,
                   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:         &parametersPath,
                   1803:         RegistryPath
                   1804:         );
                   1805:     RtlAppendUnicodeToString(
                   1806:         &parametersPath,
                   1807:         L"\\"
                   1808:         );
                   1809:     RtlAppendUnicodeToString(
                   1810:         &parametersPath,
                   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:              &parametersPath)
                   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:         &parametersAttributes,
                   1856:         &parametersPath,
                   1857:         OBJ_CASE_INSENSITIVE,
                   1858:         NULL,
                   1859:         NULL
                   1860:         );
                   1861: 
                   1862:     if (!NT_SUCCESS(ZwOpenKey(
                   1863:                        &parametersKey,
                   1864:                        MAXIMUM_ALLOWED,
                   1865:                        &parametersAttributes
                   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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.