Annotation of ntddk/src/mmedia/soundlib/soundlib.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1992  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     soundlib.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains common code for Sound Kernel mode device
        !            12:     drivers.
        !            13: 
        !            14: Author:
        !            15: 
        !            16:     Robin Speed (robinsp) 16-October-1992
        !            17: 
        !            18: Environment:
        !            19: 
        !            20:     Kernel mode
        !            21: 
        !            22: Revision History:
        !            23: 
        !            24: 
        !            25: --*/
        !            26: 
        !            27: #include <string.h>
        !            28: #include <stdlib.h>
        !            29: #include <stdio.h>             // For vsprintf
        !            30: #include <stdarg.h>            // For va_list
        !            31: #include <soundlib.h>          // Definition of what's in here
        !            32: 
        !            33: //
        !            34: // Internal routine definintions
        !            35: //
        !            36: 
        !            37: NTSTATUS SoundConfigurationCallout(
        !            38:     IN PVOID Context,
        !            39:     IN PUNICODE_STRING PathName,
        !            40:     IN INTERFACE_TYPE BusType,
        !            41:     IN ULONG BusNumber,
        !            42:     IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
        !            43:     IN CONFIGURATION_TYPE ControllerType,
        !            44:     IN ULONG ControllerNumber,
        !            45:     IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
        !            46:     IN CONFIGURATION_TYPE PeripheralType,
        !            47:     IN ULONG PeripheralNumber,
        !            48:     IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
        !            49: );
        !            50: 
        !            51: //
        !            52: // Remove initialization stuff from resident memory
        !            53: //
        !            54: 
        !            55: #ifdef ALLOC_PRAGMA
        !            56: #pragma alloc_text(init,SoundGetBusNumber)
        !            57: #pragma alloc_text(init,SoundConfigurationCallout)
        !            58: #pragma alloc_text(init,SoundReportResourceUsage)
        !            59: #pragma alloc_text(init,SoundCreateDevice)
        !            60: #pragma alloc_text(init,SoundMapPortAddress)
        !            61: #pragma alloc_text(init,SoundConnectInterrupt)
        !            62: #pragma alloc_text(init,SoundSetErrorCode)
        !            63: #pragma alloc_text(init,SoundSaveRegistryPath)
        !            64: #endif
        !            65: 
        !            66: 
        !            67: NTSTATUS
        !            68: SoundGetBusNumber(
        !            69:     IN OUT  INTERFACE_TYPE InterfaceType,
        !            70:     OUT PULONG BusNumber
        !            71: )
        !            72: /*++
        !            73: 
        !            74: Routine Description :
        !            75: 
        !            76:     Find the bus of the type we are looking for - and hope this is
        !            77:     the one with our card on!  Actually if bus is not
        !            78:     bus number 0 we fail.
        !            79: 
        !            80: Arguments :
        !            81: 
        !            82:     BusNumber - Where to put the answer
        !            83: 
        !            84: Return Value :
        !            85: 
        !            86:     NT status code - STATUS_SUCCESS if no problems
        !            87: 
        !            88: --*/
        !            89: {
        !            90:     ULONG TestBusNumber = 0;
        !            91:     NTSTATUS Status;
        !            92:     BOOLEAN Ok = FALSE;   // Must match type passed by reference to
        !            93:                           // SoundConfigurationCallout by
        !            94:                           // IoQueryDeviceDescription.
        !            95: 
        !            96:     //
        !            97:     // See if our bus type exists by calling IoQueryDeviceDescription
        !            98:     //
        !            99: 
        !           100: 
        !           101:     Status = IoQueryDeviceDescription(
        !           102:                  &InterfaceType,
        !           103:                  &TestBusNumber,
        !           104:                  NULL,
        !           105:                  NULL,
        !           106:                  NULL,
        !           107:                  NULL,
        !           108:                  SoundConfigurationCallout,
        !           109:                  (PVOID)&Ok);
        !           110: 
        !           111: 
        !           112:     if (Ok) {
        !           113:         *BusNumber = TestBusNumber;
        !           114:     }
        !           115: 
        !           116:     return Ok ? STATUS_SUCCESS : STATUS_DEVICE_DOES_NOT_EXIST;
        !           117: }
        !           118: 
        !           119: 
        !           120: 
        !           121: 
        !           122: NTSTATUS
        !           123: SoundConfigurationCallout(
        !           124:     IN PVOID Context,
        !           125:     IN PUNICODE_STRING PathName,
        !           126:     IN INTERFACE_TYPE BusType,
        !           127:     IN ULONG BusNumber,
        !           128:     IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
        !           129:     IN CONFIGURATION_TYPE ControllerType,
        !           130:     IN ULONG ControllerNumber,
        !           131:     IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
        !           132:     IN CONFIGURATION_TYPE PeripheralType,
        !           133:     IN ULONG PeripheralNumber,
        !           134:     IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
        !           135: )
        !           136: /*++
        !           137: 
        !           138: Routine Description :
        !           139: 
        !           140:     Set the return to OK to indicate we've found the bus type
        !           141:     we were looking for.  Merely being called is confirmation
        !           142:     that our bus is there.
        !           143: 
        !           144: Arguments :
        !           145: 
        !           146:     See the arguments defined by PIO_QUERY_DEVICE_ROUTINE
        !           147: 
        !           148: Return Value :
        !           149: 
        !           150:     STATUS_SUCCESS if no problems
        !           151: 
        !           152: --*/
        !           153: {
        !           154:     *(PBOOLEAN)Context = (BOOLEAN)TRUE;
        !           155:     return STATUS_SUCCESS;
        !           156: }
        !           157: 
        !           158: 
        !           159: 
        !           160: 
        !           161: NTSTATUS SoundReportResourceUsage(
        !           162:     IN PDEVICE_OBJECT DeviceObject,
        !           163:     IN INTERFACE_TYPE BusType,
        !           164:     IN ULONG BusNumber,
        !           165:     IN PULONG InterruptNumber OPTIONAL,
        !           166:     IN KINTERRUPT_MODE InterruptMode,
        !           167:     IN BOOLEAN InterruptShareDisposition,
        !           168:     IN PULONG DmaChannel OPTIONAL,
        !           169:     IN PULONG FirstIoPort OPTIONAL,
        !           170:     IN ULONG IoPortLength
        !           171: )
        !           172: /*++
        !           173: 
        !           174: Routine Description :
        !           175: 
        !           176:     Calls IoReportResourceUsage for the device and resources
        !           177:     passed in.  NOTE that this supercedes previous resources
        !           178:     declared for this device.
        !           179: 
        !           180:     It is assumed that all resources owned by the device cannot
        !           181:     be shared, except for level-sensitive interrupts which can be
        !           182:     shared.
        !           183: 
        !           184: Arguments :
        !           185: 
        !           186:     DeviceObject - The device which 'owns' the resources
        !           187:                    This can also be a pointer to a driver object
        !           188:     BusType      - The type of bus on which the device lives
        !           189:     BusNumber    - The bus number (of type BusType) where the device is
        !           190:     InterruptNumber - The interrupt the devices uses (if any)
        !           191:     DmaChannel   - The DMA channel the device uses
        !           192:     FirstIoPort  - The start Io port for the device
        !           193:     IoPortLength - The number of bytes of IO space the device uses
        !           194:                    (starting at FirstIoPort)
        !           195: 
        !           196: Return Value :
        !           197: 
        !           198:     STATUS_SUCCESS if no problems
        !           199:     The return from IoReportResourceUsage if this fails
        !           200:     STATUS_DEVICE_CONFIGURATION_ERROR is IoReportResourceUsage reports
        !           201:         a conflict
        !           202: 
        !           203: --*/
        !           204: 
        !           205: {
        !           206:     NTSTATUS Status;
        !           207: 
        !           208:     //
        !           209:     // Our resource list to report back to the system
        !           210:     //
        !           211: 
        !           212:     /*
        !           213: 
        !           214:      Compiler rejects this
        !           215: 
        !           216:     UCHAR ResBuffer[FIELD_OFFSET(
        !           217:                        CM_RESOURCE_LIST,
        !           218:                        List[0].PartialResourceList.PartialDescriptors[3].Type)];
        !           219: 
        !           220:      */
        !           221: 
        !           222:     UCHAR ResBuffer[3 * sizeof(CM_RESOURCE_LIST)];
        !           223: 
        !           224:     BOOLEAN ResourceConflict;
        !           225: 
        !           226:     PCM_RESOURCE_LIST ResourceList;
        !           227:     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
        !           228: 
        !           229:     ResourceList = (PCM_RESOURCE_LIST)ResBuffer;
        !           230:     Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
        !           231:     ResourceConflict = FALSE;
        !           232: 
        !           233:     //
        !           234:     // Zero out any unused data
        !           235:     //
        !           236: 
        !           237:     RtlZeroMemory(ResBuffer, sizeof(ResBuffer));
        !           238: 
        !           239:     //
        !           240:     // We assume there's only 1 bus so we only need one list.
        !           241:     // Fill in the bus description
        !           242:     //
        !           243: 
        !           244:     ResourceList->Count = 1;
        !           245:     ResourceList->List[0].InterfaceType = BusType;
        !           246:     ResourceList->List[0].BusNumber = BusNumber;
        !           247: 
        !           248:     //
        !           249:     // If the device is using IO Ports add this to the list
        !           250:     //
        !           251: 
        !           252:     if (ARGUMENT_PRESENT(FirstIoPort)) {
        !           253:         PHYSICAL_ADDRESS PortAddress;
        !           254:         ULONG MemType;
        !           255:         PHYSICAL_ADDRESS MappedAddress;
        !           256: 
        !           257:         PortAddress.LowPart = *FirstIoPort;
        !           258:         PortAddress.HighPart = 0;
        !           259:         MemType = 1;
        !           260: 
        !           261:         HalTranslateBusAddress(
        !           262:                     BusType,
        !           263:                     BusNumber,
        !           264:                     PortAddress,
        !           265:                     &MemType,
        !           266:                     &MappedAddress);
        !           267: 
        !           268: 
        !           269:         ResourceList->List[0].PartialResourceList.Count++;
        !           270: 
        !           271:         Descriptor->Type = CmResourceTypePort;
        !           272: 
        !           273:         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
        !           274: 
        !           275:         Descriptor->u.Port.Start.LowPart = *FirstIoPort;
        !           276: 
        !           277:         Descriptor->u.Port.Length = IoPortLength;
        !           278: 
        !           279:         Descriptor->Flags = MemType == 0 ? CM_RESOURCE_PORT_MEMORY :
        !           280:                                            CM_RESOURCE_PORT_IO;
        !           281: 
        !           282:         //
        !           283:         // Move on to next resource descriptor entry
        !           284:         //
        !           285: 
        !           286:         Descriptor++;
        !           287:     }
        !           288: 
        !           289:     //
        !           290:     // Add interrupt information (if any) to the list
        !           291:     //
        !           292: 
        !           293:     if (ARGUMENT_PRESENT(InterruptNumber)) {
        !           294:         ResourceList->List[0].PartialResourceList.Count++;
        !           295: 
        !           296:         Descriptor->Type = CmResourceTypeInterrupt;
        !           297: 
        !           298:         Descriptor->ShareDisposition = InterruptShareDisposition ?
        !           299:                                        CmResourceShareShared :
        !           300:                                        CmResourceShareDeviceExclusive;
        !           301: 
        !           302:         Descriptor->Flags =
        !           303:            InterruptMode == Latched ? CM_RESOURCE_INTERRUPT_LATCHED :
        !           304:                                       CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
        !           305: 
        !           306:         Descriptor->u.Interrupt.Level = *InterruptNumber;
        !           307: 
        !           308:         Descriptor->u.Interrupt.Vector = *InterruptNumber;
        !           309: 
        !           310:         //
        !           311:         // Move on to next resource descriptor entry
        !           312:         //
        !           313: 
        !           314:         Descriptor++;
        !           315:     }
        !           316: 
        !           317:     //
        !           318:     // Add DMA description if any
        !           319:     //
        !           320: 
        !           321:     if (ARGUMENT_PRESENT(DmaChannel)) {
        !           322:         ResourceList->List[0].PartialResourceList.Count++;
        !           323: 
        !           324:         Descriptor->Type = CmResourceTypeDma;
        !           325: 
        !           326:         Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
        !           327: 
        !           328:         Descriptor->u.Dma.Channel = *DmaChannel;
        !           329: 
        !           330:         Descriptor->u.Dma.Port = 0;  // ???
        !           331: 
        !           332:         //
        !           333:         // Move on to next resource descriptor entry
        !           334:         //
        !           335: 
        !           336:         Descriptor++;
        !           337:     }
        !           338: 
        !           339:     //
        !           340:     // Report our resource usage and detect conflicts
        !           341:     //
        !           342: 
        !           343:     switch (DeviceObject->Type) {
        !           344:     case IO_TYPE_DEVICE:
        !           345:         Status = IoReportResourceUsage(NULL,
        !           346:                                        DeviceObject->DriverObject,
        !           347:                                        NULL,
        !           348:                                        0,
        !           349:                                        DeviceObject,
        !           350:                                        ResourceList,
        !           351:                                        (PUCHAR)Descriptor - (PUCHAR)ResourceList,
        !           352:                                        FALSE,
        !           353:                                        &ResourceConflict);
        !           354:         break;
        !           355:     case IO_TYPE_DRIVER:
        !           356:         Status = IoReportResourceUsage(NULL,
        !           357:                                        (PDRIVER_OBJECT)DeviceObject,
        !           358:                                        ResourceList,
        !           359:                                        (PUCHAR)Descriptor - (PUCHAR)ResourceList,
        !           360:                                        NULL,
        !           361:                                        NULL,
        !           362:                                        0,
        !           363:                                        FALSE,
        !           364:                                        &ResourceConflict);
        !           365:         break;
        !           366: 
        !           367:     default:
        !           368:         ASSERTMSG("SoundReportResourceUsage - invalid object", FALSE);
        !           369:     }
        !           370: 
        !           371:     if (ResourceConflict) {
        !           372:         dprintf1(("Resource conflict reported"));
        !           373:         Status = STATUS_DEVICE_CONFIGURATION_ERROR;
        !           374:     }
        !           375: 
        !           376:     return Status;
        !           377: }
        !           378: 
        !           379: 
        !           380: 
        !           381: 
        !           382: VOID
        !           383: SoundFreeDevice(
        !           384:     IN  PDEVICE_OBJECT DeviceObject
        !           385: )
        !           386: /*++
        !           387: 
        !           388: Routine Description :
        !           389: 
        !           390:     Free the all resources related to this device :
        !           391: 
        !           392:         The device object itself
        !           393: 
        !           394:         Any declared hardware resources (via IoReportResourceUsage)
        !           395: 
        !           396:         Any symbolic link related to this device
        !           397: 
        !           398: Arguments :
        !           399: 
        !           400:     DeviceObject - the device to free
        !           401: 
        !           402: Return Value :
        !           403: 
        !           404:     None
        !           405: 
        !           406: --*/
        !           407: {
        !           408:     CM_RESOURCE_LIST NullResourceList;
        !           409:     BOOLEAN ResourceConflict;
        !           410: 
        !           411: 
        !           412:     //
        !           413:     // Free the device if any
        !           414:     //
        !           415: 
        !           416:     if (DeviceObject != NULL) {
        !           417: 
        !           418: 
        !           419:         //
        !           420:         // Undeclare any resources used by the device
        !           421:         // (delete anything the driver has at the same time!)
        !           422:         //
        !           423: 
        !           424:         NullResourceList.Count = 0;
        !           425: 
        !           426:         IoReportResourceUsage(NULL,
        !           427:                               DeviceObject->DriverObject,
        !           428:                               &NullResourceList,
        !           429:                               sizeof(ULONG),
        !           430:                               DeviceObject,
        !           431:                               &NullResourceList,
        !           432:                               sizeof(ULONG),
        !           433:                               FALSE,
        !           434:                               &ResourceConflict);
        !           435: 
        !           436:         //
        !           437:         // Remove the device's symbolic link
        !           438:         //
        !           439: 
        !           440:         {
        !           441:             PLOCAL_DEVICE_INFO pLDI;
        !           442:             UNICODE_STRING DeviceName;
        !           443:             WCHAR Number[8];
        !           444:             WCHAR TestName[SOUND_MAX_DEVICE_NAME];
        !           445: 
        !           446:             pLDI = DeviceObject->DeviceExtension;
        !           447: 
        !           448:             DeviceName.Buffer = TestName;
        !           449:             DeviceName.MaximumLength = sizeof(TestName);
        !           450:             DeviceName.Length = 0;
        !           451: 
        !           452:             RtlAppendUnicodeToString(&DeviceName, L"\\DosDevices");
        !           453: 
        !           454:             RtlAppendUnicodeToString(
        !           455:                 &DeviceName,
        !           456:                 pLDI->DeviceInit->PrototypeName +
        !           457:                     (sizeof(L"\\Device") - sizeof(UNICODE_NULL)) /
        !           458:                          sizeof(UNICODE_NULL));
        !           459: 
        !           460:             if (!(pLDI->CreationFlags & SOUND_CREATION_NO_NAME_RANGE)) {
        !           461:                 UNICODE_STRING UnicodeNum;
        !           462:                 WCHAR Number[8];
        !           463:                 UnicodeNum.MaximumLength = sizeof(Number);
        !           464:                 UnicodeNum.Buffer = Number;
        !           465: 
        !           466:                 RtlIntegerToUnicodeString(pLDI->DeviceNumber, 10, &UnicodeNum);
        !           467:                 RtlAppendUnicodeStringToString(&DeviceName, &UnicodeNum);
        !           468:             }
        !           469: 
        !           470:             IoDeleteSymbolicLink(&DeviceName);
        !           471:         }
        !           472: 
        !           473:         //
        !           474:         // Delete the device object
        !           475:         //
        !           476: 
        !           477:         IoDeleteDevice(DeviceObject);
        !           478:     }
        !           479: }
        !           480: 
        !           481: 
        !           482: NTSTATUS
        !           483: SoundCreateDevice(
        !           484:     IN   PSOUND_DEVICE_INIT DeviceInit,
        !           485:     IN   UCHAR CreationFlags,
        !           486:     IN   PDRIVER_OBJECT pDriverObject,
        !           487:     IN   PVOID pGDI,
        !           488:     IN   PVOID DeviceSpecificData,
        !           489:     IN   PVOID pHw,
        !           490:     IN   int i,
        !           491:     OUT  PDEVICE_OBJECT *ppDevObj
        !           492: )
        !           493: 
        !           494: /*++
        !           495: 
        !           496: Routine Description:
        !           497: 
        !           498:     Create a new device using a name derived from szPrototypeName
        !           499:     by adding a number on to the end such that the no device with the
        !           500:     qualified name exists.
        !           501: 
        !           502:     A symbolic link in \DosDevices is also created
        !           503: 
        !           504: Arguments:
        !           505: 
        !           506:     DeviceInit - device initialization data
        !           507: 
        !           508:     NoRange - if this is set then no number is concatenated, the
        !           509:           explicit name is used.
        !           510: 
        !           511:     pDriverObject - our driver
        !           512: 
        !           513:     pGDI - global context
        !           514: 
        !           515:     pHw - hardware context
        !           516: 
        !           517:     i - device number for back reference
        !           518: 
        !           519:     ppDevObj - where to write back the device object pointer
        !           520: 
        !           521: Return Value:
        !           522: 
        !           523:     An NTSTATUS code.
        !           524: 
        !           525: --*/
        !           526: 
        !           527: {
        !           528: 
        !           529:     int DeviceNumber;
        !           530:     NTSTATUS Status;
        !           531:     UNICODE_STRING DeviceName;
        !           532:     UNICODE_STRING UnicodeNum;
        !           533:     WCHAR TestName[SOUND_MAX_DEVICE_NAME];
        !           534:     WCHAR Number[8];
        !           535:     OBJECT_ATTRIBUTES ObjectAttributes;
        !           536:     PLOCAL_DEVICE_INFO pLDI;
        !           537: 
        !           538: #ifdef SOUND_DIRECTORIES
        !           539:     HANDLE DirectoryHandle = NULL;
        !           540: 
        !           541:     //
        !           542:     // Create the directory for this device type.
        !           543:     //
        !           544: 
        !           545:     RtlInitUnicodeString(&DeviceName, DeviceInit->PrototypeName);
        !           546:     InitializeObjectAttributes(&ObjectAttributes,
        !           547:                                &DeviceName,
        !           548:                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
        !           549:                                NULL,
        !           550:                                (PSECURITY_DESCRIPTOR)NULL);
        !           551: 
        !           552:     //
        !           553:     // We create the directory if it doesn't exist.
        !           554:     // We must keep this handle open until we create something as
        !           555:     // we're not making it permanent.  This means that if we unload
        !           556:     // the system may be able to get rid of the directory
        !           557:     //
        !           558: 
        !           559:     Status = ZwCreateDirectoryObject(&DirectoryHandle,
        !           560:                                      GENERIC_READ,
        !           561:                                      &ObjectAttributes);
        !           562: 
        !           563:     if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION) {
        !           564:         dprintf1(("Return code from NtCreateDirectoryObject = %x", Status));
        !           565:         return Status;
        !           566:     } else {
        !           567:         //
        !           568:         // Directory is permanent so it won't go away.
        !           569:         //
        !           570:         ZwClose(DirectoryHandle);
        !           571:     }
        !           572: #endif // SOUND_DIRECTORIES
        !           573: 
        !           574:     for (DeviceNumber = 0; DeviceNumber < SOUND_MAX_DEVICES; DeviceNumber ++) {
        !           575: 
        !           576:         //
        !           577:         // Create our test name
        !           578:         //
        !           579: 
        !           580:         DeviceName.Length = 0;
        !           581:         DeviceName.Buffer = TestName;
        !           582:         DeviceName.MaximumLength = sizeof(TestName);
        !           583: 
        !           584:         Status = RtlAppendUnicodeToString(&DeviceName, DeviceInit->PrototypeName);
        !           585: 
        !           586:         if (!NT_SUCCESS(Status)) {
        !           587:             return Status;
        !           588:         }
        !           589: 
        !           590: #ifdef SOUND_DIRECTORIES
        !           591:         RtlAppendUnicodeToString(&DeviceName, "\\");
        !           592: #else
        !           593: #endif // SOUND_DIRECTORIES
        !           594: 
        !           595:         //
        !           596:         // Append the device number if required
        !           597:         //
        !           598: 
        !           599:         if (!(CreationFlags & SOUND_CREATION_NO_NAME_RANGE)) {
        !           600:             UnicodeNum.MaximumLength = sizeof(Number);
        !           601:             UnicodeNum.Buffer = Number;
        !           602:             RtlIntegerToUnicodeString(DeviceNumber, 10, &UnicodeNum);
        !           603: 
        !           604:             RtlAppendUnicodeStringToString(&DeviceName, &UnicodeNum);
        !           605:         } else {
        !           606:             DeviceNumber = 255;
        !           607:         }
        !           608: 
        !           609:         Status = IoCreateDevice(
        !           610:                      pDriverObject,
        !           611:                      sizeof(LOCAL_DEVICE_INFO),
        !           612:                      &DeviceName,
        !           613:                      DeviceInit->Type,
        !           614:                      0,
        !           615:                      FALSE,                      // Non-Exclusive
        !           616:                      ppDevObj
        !           617:                      );
        !           618: 
        !           619:         if (NT_SUCCESS(Status)) {
        !           620:             dprintf2(("Created device %d", DeviceNumber));
        !           621: 
        !           622:             //
        !           623:             // Set up the rest of the device stuff
        !           624:             //
        !           625: 
        !           626:             (*ppDevObj)->Flags |= DeviceInit->IoMethod;
        !           627:             (*ppDevObj)->AlignmentRequirement = FILE_BYTE_ALIGNMENT;
        !           628: 
        !           629:             if (DeviceInit->DeferredRoutine) {
        !           630:                 IoInitializeDpcRequest((*ppDevObj), DeviceInit->DeferredRoutine);
        !           631:             }
        !           632: 
        !           633:             pLDI = (*ppDevObj)->DeviceExtension;
        !           634:             RtlZeroMemory(pLDI, sizeof(*pLDI));
        !           635: 
        !           636:             //
        !           637:             // Try to create a symbolic link object for this device
        !           638:             //
        !           639:             // No security
        !           640:             //
        !           641:             // We make (eg)
        !           642:             //    \DosDevices\WaveOut0
        !           643:             // Point to
        !           644:             //    \Device\WaveOut0
        !           645:             //
        !           646: 
        !           647:             {
        !           648:                 UNICODE_STRING LinkObject;
        !           649:                 WCHAR LinkName[80];
        !           650:                 ULONG DeviceSize;
        !           651: 
        !           652:                 LinkName[0] = UNICODE_NULL;
        !           653: 
        !           654:                 RtlInitUnicodeString(&LinkObject, LinkName);
        !           655: 
        !           656:                 LinkObject.MaximumLength = sizeof(LinkName);
        !           657: 
        !           658:                 RtlAppendUnicodeToString(&LinkObject, L"\\DosDevices");
        !           659: 
        !           660:                 DeviceSize = sizeof(L"\\Device") - sizeof(UNICODE_NULL);
        !           661:                 DeviceName.Buffer += DeviceSize / sizeof(WCHAR);
        !           662:                 DeviceName.Length -= DeviceSize;
        !           663: 
        !           664:                 RtlAppendUnicodeStringToString(&LinkObject, &DeviceName);
        !           665: 
        !           666:                 DeviceName.Buffer -= DeviceSize / sizeof(WCHAR);
        !           667:                 DeviceName.Length += DeviceSize;
        !           668: 
        !           669:                 Status = IoCreateSymbolicLink(&LinkObject, &DeviceName);
        !           670: 
        !           671:                 if (!NT_SUCCESS(Status)) {
        !           672:                     dprintf1(("Failed to create symbolic link object"));
        !           673:                     IoDeleteDevice(*ppDevObj);
        !           674:                     *ppDevObj = NULL;
        !           675:                     return Status;
        !           676:                 }
        !           677:             }
        !           678: 
        !           679:             //
        !           680:             // Fill in the rest of the device information
        !           681:             //
        !           682: 
        !           683: #ifdef VOLUME_NOTIFY
        !           684:             InitializeListHead(&pLDI->VolumeQueue);
        !           685: #endif // VOLUME_NOTIFY
        !           686: 
        !           687:             pLDI->DeviceNumber = DeviceNumber;
        !           688:             pLDI->DeviceInit = DeviceInit;
        !           689:             pLDI->CreationFlags = CreationFlags;
        !           690: 
        !           691:             pLDI->Key = *(PULONG)DeviceInit->Key;
        !           692:             pLDI->DeviceType = DeviceInit->DeviceType;
        !           693:             pLDI->DeviceIndex = (UCHAR)i;
        !           694:             pLDI->pGlobalInfo = pGDI;
        !           695:             pLDI->DeviceSpecificData = DeviceSpecificData;
        !           696:             pLDI->HwContext = pHw;
        !           697: 
        !           698:             return STATUS_SUCCESS;
        !           699:         }
        !           700:     }
        !           701:     //
        !           702:     // Failed !
        !           703:     //
        !           704: 
        !           705:     return STATUS_INSUFFICIENT_RESOURCES;
        !           706: }
        !           707: 
        !           708: 
        !           709: 
        !           710: 
        !           711: PUCHAR
        !           712: SoundMapPortAddress(
        !           713:     INTERFACE_TYPE BusType,
        !           714:     ULONG BusNumber,
        !           715:     ULONG PortBase,
        !           716:     ULONG Length,
        !           717:     PULONG MemType
        !           718: )
        !           719: /*++
        !           720: 
        !           721: Routine Description :
        !           722: 
        !           723:     Map a physical device port address to an address we can pass
        !           724:     to READ/WRITE_PORT_UCHAR/USHORT etc
        !           725: 
        !           726: Arguments :
        !           727:     BusType - type of bus
        !           728:     BusNumber - bus number
        !           729:     PortBase - The port start address
        !           730:     Length - how many bytes of port space to map (needed by MmMapIoSpace)
        !           731: 
        !           732: Return Value :
        !           733: 
        !           734:     The virtual port address
        !           735: 
        !           736: --*/
        !           737: {
        !           738:     PHYSICAL_ADDRESS PortAddress;
        !           739:     PHYSICAL_ADDRESS MappedAddress;
        !           740: 
        !           741:     *MemType = 1;                 // IO space
        !           742:     PortAddress.LowPart = PortBase;
        !           743:     PortAddress.HighPart = 0;
        !           744:     HalTranslateBusAddress(
        !           745:                 BusType,
        !           746:                 BusNumber,
        !           747:                 PortAddress,
        !           748:                 MemType,
        !           749:                 &MappedAddress);
        !           750: 
        !           751:     if (*MemType == 0) {
        !           752:         //
        !           753:         // Map memory type IO space into our address space
        !           754:         //
        !           755:         return (PUCHAR)MmMapIoSpace(MappedAddress, Length, FALSE);
        !           756:     } else {
        !           757:         return (PUCHAR)MappedAddress.LowPart;
        !           758:     }
        !           759: }
        !           760: 
        !           761: 
        !           762: 
        !           763: NTSTATUS
        !           764: SoundConnectInterrupt(
        !           765:     IN ULONG InterruptNumber,
        !           766:     IN INTERFACE_TYPE BusType,
        !           767:     IN ULONG BusNumber,
        !           768:     IN PKSERVICE_ROUTINE Isr,
        !           769:     IN PVOID ServiceContext,
        !           770:     IN KINTERRUPT_MODE InterruptMode,
        !           771:     IN BOOLEAN ShareVector,
        !           772:     OUT PKINTERRUPT *Interrupt
        !           773: )
        !           774: /*++
        !           775: 
        !           776: Routine Description :
        !           777: 
        !           778:     Connect to an interrupt.  From this point on our interrupt service
        !           779:     routine can receive interrupts
        !           780: 
        !           781:     We assume that floating point arithmetic will not be used in the
        !           782:     service routine.
        !           783: 
        !           784: Arguments :
        !           785: 
        !           786:     InterruptNumber - the interrupt number we're using
        !           787:     BusType - Our bus type
        !           788:     BusNumber - the number of our buse (of type BusType)
        !           789:     Isr - the interrupt service routine
        !           790:     ServiceContext - a value passed to the interrupt service routine
        !           791:     InterruptMode - whether it's latched or level sensitive
        !           792:     ShareVector - whether the interrupt can be shared
        !           793:     Interrupt - Returns the pointer to the interrupt object
        !           794: 
        !           795: Return Value :
        !           796: 
        !           797:     An NTSTATUS return value - STATUS_SUCCESS if OK.
        !           798: 
        !           799: --*/
        !           800: {
        !           801:     KAFFINITY Affinity;
        !           802:     KIRQL InterruptRequestLevel;
        !           803:     ULONG InterruptVector;
        !           804:     NTSTATUS Status;
        !           805: 
        !           806:     //
        !           807:     // Call HalGetInterruptVector to get the interrupt vector,
        !           808:     // processor affinity and  request level to pass to IoConnectInterrupt
        !           809:     //
        !           810: 
        !           811:     InterruptVector = HalGetInterruptVector(Isa,
        !           812:                                             BusNumber,
        !           813:                                             InterruptNumber,
        !           814:                                             InterruptNumber,
        !           815:                                             &InterruptRequestLevel,
        !           816:                                             &Affinity);
        !           817: 
        !           818: 
        !           819:     Status = IoConnectInterrupt(
        !           820:                    Interrupt,
        !           821:                    Isr,
        !           822:                    ServiceContext,
        !           823:                    (PKSPIN_LOCK)NULL,
        !           824:                    InterruptVector,
        !           825:                    InterruptRequestLevel,
        !           826:                    InterruptRequestLevel,
        !           827:                    InterruptMode,
        !           828:                    ShareVector,
        !           829:                    Affinity,
        !           830:                    FALSE                      // No floating point save
        !           831:                    );
        !           832: 
        !           833:     return Status == STATUS_INVALID_PARAMETER ?
        !           834:                        STATUS_DEVICE_CONFIGURATION_ERROR : Status;
        !           835: }
        !           836: 
        !           837: 
        !           838: 
        !           839: NTSTATUS
        !           840: SoundSetErrorCode(
        !           841:     IN   PWSTR RegistryPath,
        !           842:     IN   ULONG Value
        !           843: )
        !           844: /*++
        !           845: 
        !           846: Routine Description :
        !           847: 
        !           848:     Write the given DWORD into the registry using the path
        !           849:     with a value name of SOUND_REG_CONFIGERROR
        !           850: 
        !           851: Arguments :
        !           852: 
        !           853:     RegistryPath- path to registry key
        !           854: 
        !           855:     Value - value to store
        !           856: 
        !           857: Return Value :
        !           858: 
        !           859:     NTSTATUS code
        !           860: 
        !           861: --*/
        !           862: {
        !           863:     return SoundWriteRegistryDWORD(RegistryPath, SOUND_REG_CONFIGERROR, Value);
        !           864: }
        !           865: 
        !           866: 
        !           867: NTSTATUS
        !           868: SoundWriteRegistryDWORD(
        !           869:     IN   PWSTR RegistryPath,
        !           870:     IN   PWSTR ValueName,
        !           871:     IN   ULONG Value
        !           872: )
        !           873: /*++
        !           874: 
        !           875: Routine Description :
        !           876: 
        !           877:     Write the given DWORD into the registry using the path and
        !           878:     value name supplied by calling RtlWriteRegistryValue
        !           879: 
        !           880: Arguments :
        !           881: 
        !           882:     RegistryPath- path to registry key
        !           883: 
        !           884:     ValueName - name of value to write
        !           885: 
        !           886:     Value - value to store
        !           887: 
        !           888: Return Value :
        !           889: 
        !           890:     NTSTATUS code
        !           891: 
        !           892: --*/
        !           893: {
        !           894:     NTSTATUS Status;
        !           895: 
        !           896:     Status = RtlWriteRegistryValue(
        !           897:                  RTL_REGISTRY_ABSOLUTE,
        !           898:                  RegistryPath,
        !           899:                  ValueName,
        !           900:                  REG_DWORD,
        !           901:                  &Value,
        !           902:                  sizeof(Value));
        !           903: 
        !           904:     if (!NT_SUCCESS(Status)) {
        !           905:         dprintf1(("Writing parameter %ls to registry failed status %8X",
        !           906:                   ValueName, Status));
        !           907:     }
        !           908: 
        !           909:     return Status;
        !           910: }
        !           911: 
        !           912: 
        !           913: VOID
        !           914: SoundDelay(
        !           915:     IN ULONG Milliseconds
        !           916: )
        !           917: /*++
        !           918: 
        !           919: Routine Description :
        !           920: 
        !           921:     Stall the current thread for the given number of milliseconds AT LEAST
        !           922: 
        !           923: Arguments :
        !           924: 
        !           925:     Milliseconds - number of milliseconds to delay
        !           926: 
        !           927: Return Value :
        !           928: 
        !           929:     None
        !           930: 
        !           931: --*/
        !           932: {
        !           933:     LARGE_INTEGER Delay;
        !           934: 
        !           935:     //
        !           936:     // Can't call SoundDelay() from high irql
        !           937:     //
        !           938: 
        !           939:     if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
        !           940:         return;
        !           941:     }
        !           942: 
        !           943:     //
        !           944:     // First a tiny delay to synch us up with the timer otherwise we
        !           945:     // may wait up to 15ms less time than we expected!
        !           946:     //
        !           947: 
        !           948:     Delay = RtlConvertLongToLargeInteger(-1);
        !           949: 
        !           950:     KeDelayExecutionThread(KernelMode,
        !           951:                            FALSE,         // Not alertable
        !           952:                            &Delay);
        !           953: 
        !           954:     Delay = RtlConvertLongToLargeInteger((-(LONG)Milliseconds) * 10000);
        !           955: 
        !           956:     KeDelayExecutionThread(KernelMode,
        !           957:                            FALSE,         // Not alertable
        !           958:                            &Delay);
        !           959: }
        !           960: 
        !           961: 
        !           962: LARGE_INTEGER
        !           963: SoundGetTime(
        !           964:     VOID
        !           965: )
        !           966: /*++
        !           967: 
        !           968: Routine Description:
        !           969: 
        !           970:     Get an accurate estimate of the current time by calling
        !           971:     KeQueryPerformanceCounter and converting the result to 100ns units
        !           972: 
        !           973: Arguments:
        !           974: 
        !           975:     ErrorText - text of message
        !           976: 
        !           977: Return Value:
        !           978: 
        !           979: --*/
        !           980: {
        !           981:     static LARGE_INTEGER StartTime100ns, StartTimeTicks, TicksPerSecond;
        !           982:     static BOOLEAN Initialized;
        !           983:     static ULONG Multiplier;
        !           984:     ULONG Remainder;
        !           985: 
        !           986:     if (!Initialized) {
        !           987: 
        !           988:         Initialized = TRUE;
        !           989: 
        !           990:         KeQuerySystemTime(&StartTime100ns);
        !           991:         StartTimeTicks = KeQueryPerformanceCounter(&TicksPerSecond);
        !           992: 
        !           993:         Multiplier = 10000000;
        !           994: 
        !           995:         while (TicksPerSecond.HighPart != 0) {
        !           996:             Multiplier = Multiplier / 10;
        !           997:             TicksPerSecond =
        !           998:                 RtlExtendedLargeIntegerDivide(TicksPerSecond, 10, &Remainder);
        !           999:         }
        !          1000:     }
        !          1001: 
        !          1002:     //
        !          1003:     // Convert ticks to 100ns units (and hope we don't overflow!)
        !          1004:     //
        !          1005: 
        !          1006:     return RtlLargeIntegerAdd(
        !          1007:               RtlExtendedLargeIntegerDivide(
        !          1008:                   RtlExtendedIntegerMultiply(
        !          1009:                       RtlLargeIntegerSubtract(
        !          1010:                           KeQueryPerformanceCounter(NULL),
        !          1011:                           StartTimeTicks
        !          1012:                       ),
        !          1013:                       Multiplier
        !          1014:                   ),
        !          1015:                   TicksPerSecond.LowPart,
        !          1016:                   &Remainder
        !          1017:               ),
        !          1018:               StartTime100ns
        !          1019:            );
        !          1020: }
        !          1021: 
        !          1022: 
        !          1023: 
        !          1024: VOID
        !          1025: SoundFreeQ(
        !          1026:     PLIST_ENTRY ListHead,
        !          1027:     NTSTATUS IoStatus
        !          1028: )
        !          1029: /*++
        !          1030: 
        !          1031: Routine Description:
        !          1032: 
        !          1033:     Free a list of Irps - setting the specified status and completing
        !          1034:     them.  The list will be empty on exit.
        !          1035: 
        !          1036: Arguments:
        !          1037: 
        !          1038:     pListNode - the list to free
        !          1039:     IoStatus  - the status to set in each Irp.
        !          1040: 
        !          1041: Return Value:
        !          1042: 
        !          1043:     None.
        !          1044: 
        !          1045: --*/
        !          1046: {
        !          1047:     //
        !          1048:     // Remove all the queue entries, completing all
        !          1049:     // the Irps represented by the entries
        !          1050:     //
        !          1051: 
        !          1052:     for (;;) {
        !          1053:         PIRP pIrp;
        !          1054: 
        !          1055:         //
        !          1056:         // The queue may be cancellable so use our routine to get the Irp
        !          1057:         //
        !          1058: 
        !          1059:         pIrp = SoundRemoveFromCancellableQ(ListHead);
        !          1060: 
        !          1061:         if (pIrp == NULL) {
        !          1062:             break;
        !          1063:         }
        !          1064: 
        !          1065:         pIrp->IoStatus.Status = IoStatus;
        !          1066: 
        !          1067:         //
        !          1068:         // Bump priority here because the application may still be trying
        !          1069:         // to be real-time
        !          1070:         //
        !          1071:         IoCompleteRequest(pIrp, IO_SOUND_INCREMENT);
        !          1072:     }
        !          1073: }
        !          1074: 
        !          1075: 
        !          1076: VOID
        !          1077: SoundRemoveAndComplete(
        !          1078:     PDEVICE_OBJECT pDO,
        !          1079:     PIRP Irp
        !          1080: )
        !          1081: /*++
        !          1082: 
        !          1083: Routine Description:
        !          1084: 
        !          1085:     Removes the Irp from any queue it's on
        !          1086:     Completes it as cancelled.
        !          1087: 
        !          1088: Arguments:
        !          1089: 
        !          1090:     Irp - the Irp
        !          1091:     Cancellable - If it is to be made cancellable
        !          1092: 
        !          1093: Return Value:
        !          1094: 
        !          1095:     None.
        !          1096: 
        !          1097: Notes:
        !          1098: 
        !          1099:     This routine is called with the cancel spin lock held
        !          1100: 
        !          1101: --*/
        !          1102: {
        !          1103:     dprintf2(("Cancelling Irp from cancel routine"));
        !          1104: 
        !          1105:     //
        !          1106:     // Remove the Irp from the queue
        !          1107:     //
        !          1108: 
        !          1109:     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
        !          1110: 
        !          1111:     //
        !          1112:     // Release the cancel spin lock
        !          1113:     //
        !          1114: 
        !          1115:     IoReleaseCancelSpinLock(Irp->CancelIrql);
        !          1116: 
        !          1117:     //
        !          1118:     // Set status and complete
        !          1119:     //
        !          1120: 
        !          1121:     Irp->IoStatus.Status = STATUS_CANCELLED;
        !          1122: 
        !          1123:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          1124: }
        !          1125: 
        !          1126: 
        !          1127: 
        !          1128: VOID
        !          1129: SoundAddIrpToCancellableQ(
        !          1130:     PLIST_ENTRY QueueHead,
        !          1131:     PIRP Irp,
        !          1132:     BOOLEAN Head
        !          1133: )
        !          1134: /*++
        !          1135: 
        !          1136: Routine Description:
        !          1137: 
        !          1138: 
        !          1139:     Add the Irp to the queue and set the cancel routine under the
        !          1140:     protection of the cancel spin lock.
        !          1141: 
        !          1142: Arguments:
        !          1143: 
        !          1144:     QueueHead - the queue to add it to
        !          1145:     Irp - the Irp
        !          1146:     Head - if TRUE insert at the head of the queue
        !          1147: 
        !          1148: Return Value:
        !          1149: 
        !          1150:     None.
        !          1151: 
        !          1152: --*/
        !          1153: {
        !          1154:     KIRQL OldIrql;
        !          1155: 
        !          1156:     //
        !          1157:     // Get the cancel spin lock so we can mess with the cancel stuff
        !          1158:     //
        !          1159: 
        !          1160:     IoAcquireCancelSpinLock(&OldIrql);
        !          1161: 
        !          1162:     //
        !          1163:     // Well, it may ALREADY be cancelled!
        !          1164:     //
        !          1165: 
        !          1166:     if (Irp->Cancel) {
        !          1167: 
        !          1168:         dprintf2(("Irp already cancelled"));
        !          1169: 
        !          1170:         //
        !          1171:         // Release the cancel spin lock
        !          1172:         //
        !          1173: 
        !          1174:         IoReleaseCancelSpinLock(OldIrql);
        !          1175: 
        !          1176:         //
        !          1177:         // Set status and complete
        !          1178:         //
        !          1179: 
        !          1180:         Irp->IoStatus.Status = STATUS_CANCELLED;
        !          1181: 
        !          1182:         IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !          1183:         return;
        !          1184:     }
        !          1185: 
        !          1186:     //
        !          1187:     // Set the cancel routine
        !          1188:     //
        !          1189: 
        !          1190:     IoSetCancelRoutine(Irp, SoundRemoveAndComplete);
        !          1191: 
        !          1192:     //
        !          1193:     // Insert it in the queue
        !          1194:     //
        !          1195: 
        !          1196:     if (Head) {
        !          1197:         InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry);
        !          1198:     } else {
        !          1199:         InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry);
        !          1200:     }
        !          1201: 
        !          1202:     //
        !          1203:     // Free the spin lock
        !          1204:     //
        !          1205: 
        !          1206:     IoReleaseCancelSpinLock(OldIrql);
        !          1207: }
        !          1208: 
        !          1209: 
        !          1210: PIRP
        !          1211: SoundRemoveFromCancellableQ(
        !          1212:     PLIST_ENTRY QueueHead
        !          1213: )
        !          1214: /*++
        !          1215: 
        !          1216: Routine Description:
        !          1217: 
        !          1218: 
        !          1219:     Remove the Irp to the queue and remove the cancel routine under the
        !          1220:     protection of the cancel spin lock.
        !          1221: 
        !          1222: Arguments:
        !          1223: 
        !          1224:     QueueHead - the queue to remove it from
        !          1225: 
        !          1226: Return Value:
        !          1227: 
        !          1228:     The Irp at the head of the queue or NULL if the queue is empty.
        !          1229: 
        !          1230: --*/
        !          1231: {
        !          1232:     KIRQL OldIrql;
        !          1233:     PIRP Irp;
        !          1234:     LIST_ENTRY ListNode;
        !          1235: 
        !          1236:     //
        !          1237:     // Get the cancel spin lock so we can mess with the cancel stuff
        !          1238:     //
        !          1239: 
        !          1240:     IoAcquireCancelSpinLock(&OldIrql);
        !          1241: 
        !          1242: 
        !          1243:     if (IsListEmpty(QueueHead)) {
        !          1244:         Irp = NULL;
        !          1245:     } else {
        !          1246: 
        !          1247:         PLIST_ENTRY ListNode;
        !          1248:         ListNode = RemoveHeadList(QueueHead);
        !          1249:         Irp = CONTAINING_RECORD(ListNode, IRP, Tail.Overlay.ListEntry);
        !          1250: 
        !          1251:         //
        !          1252:         // Remove the cancel routine
        !          1253:         //
        !          1254: 
        !          1255:         IoSetCancelRoutine(Irp, NULL);
        !          1256:     }
        !          1257: 
        !          1258:     //
        !          1259:     // Free the spin lock
        !          1260:     //
        !          1261: 
        !          1262:     IoReleaseCancelSpinLock(OldIrql);
        !          1263: 
        !          1264:     //
        !          1265:     // Return IRP (if any)
        !          1266:     //
        !          1267: 
        !          1268:     return Irp;
        !          1269: }
        !          1270: 
        !          1271: 
        !          1272: 
        !          1273: NTSTATUS
        !          1274: SoundSaveRegistryPath(
        !          1275:     IN    PUNICODE_STRING RegistryPathName,
        !          1276:     OUT   PWSTR *SavedString
        !          1277: )
        !          1278: /*++
        !          1279: 
        !          1280: Routine Description:
        !          1281: 
        !          1282:     Save the driver's registry path, appending the 'Parameters' key.
        !          1283: 
        !          1284:     NOTE this registry path must only be accessed BELOW dispatch level
        !          1285:     as the save area is allocated from paged pool.
        !          1286: 
        !          1287:     The caller must free the unicode string buffer if the driver unloads.
        !          1288: 
        !          1289: Arguments:
        !          1290: 
        !          1291:     RegistryPathName - Our driver's registry entry
        !          1292:     SavedString - Saved version of RegistryPathName with the 'Parameters'
        !          1293:          subkey string appended
        !          1294: 
        !          1295: Return Value:
        !          1296: 
        !          1297:     NTSTATUS code
        !          1298: 
        !          1299: --*/
        !          1300: {
        !          1301:     int Length;
        !          1302: 
        !          1303:     ASSERT(*SavedString == NULL);
        !          1304: 
        !          1305:     Length =
        !          1306:         RegistryPathName->Length + sizeof(PARMS_SUBKEY) +
        !          1307:               sizeof(UNICODE_NULL);                // Include backslash
        !          1308: 
        !          1309: 
        !          1310:     *SavedString =
        !          1311:         ExAllocatePool(PagedPool, Length); // Only access on caller thread
        !          1312: 
        !          1313:     if (*SavedString == NULL) {
        !          1314:         return STATUS_INSUFFICIENT_RESOURCES;
        !          1315:     }
        !          1316: 
        !          1317:     //
        !          1318:     // Copy the character data
        !          1319:     //
        !          1320: 
        !          1321:     RtlCopyMemory(*SavedString, RegistryPathName->Buffer,
        !          1322:                   RegistryPathName->Length);
        !          1323: 
        !          1324:     (*SavedString)[RegistryPathName->Length / sizeof(WCHAR)] = L'\\';
        !          1325:     (*SavedString)[RegistryPathName->Length / sizeof(WCHAR) + 1] = UNICODE_NULL;
        !          1326: 
        !          1327:     //
        !          1328:     // Append the parameters suffix prepended by a backslash
        !          1329:     //
        !          1330: 
        !          1331:     wcscat(*SavedString, PARMS_SUBKEY);
        !          1332: 
        !          1333:     return STATUS_SUCCESS;
        !          1334: }
        !          1335: 
        !          1336: 
        !          1337: VOID
        !          1338: SoundFlushRegistryKey(
        !          1339:     IN    PWSTR RegistryPathName
        !          1340: )
        !          1341: /*++
        !          1342: 
        !          1343: Routine Description:
        !          1344: 
        !          1345:     Flush a key - usually the driver's parameters key -
        !          1346:     used mainly to save volume settings.
        !          1347: 
        !          1348: Arguments:
        !          1349: 
        !          1350:     RegistryPathName - Our driver's parameters registry entry
        !          1351: 
        !          1352: Return Value:
        !          1353: 
        !          1354:     None
        !          1355: 
        !          1356: --*/
        !          1357: {
        !          1358: 
        !          1359:     HANDLE KeyHandle;
        !          1360:     OBJECT_ATTRIBUTES ObjectAttributes;
        !          1361:     UNICODE_STRING RegistryPathString;
        !          1362: 
        !          1363:     RtlInitUnicodeString(&RegistryPathString, RegistryPathName);
        !          1364: 
        !          1365:     InitializeObjectAttributes(&ObjectAttributes,
        !          1366:                                &RegistryPathString,
        !          1367:                                OBJ_CASE_INSENSITIVE,
        !          1368:                                NULL,
        !          1369:                                (PSECURITY_DESCRIPTOR)NULL);
        !          1370: 
        !          1371:     //
        !          1372:     // Just open the key and flush it.  Not much we can do if this
        !          1373:     // fails.
        !          1374:     //
        !          1375: 
        !          1376:     if (NT_SUCCESS(ZwOpenKey(&KeyHandle,
        !          1377:                              KEY_WRITE,
        !          1378:                              &ObjectAttributes))) {
        !          1379:        ZwFlushKey(KeyHandle);
        !          1380:        ZwClose(KeyHandle);
        !          1381:     } else {
        !          1382:         dprintf1(("Could not open device's key for flushing"));
        !          1383:     }
        !          1384: }
        !          1385: 
        !          1386: #if 0
        !          1387: 
        !          1388: VOID
        !          1389: SoundRaiseHardError(
        !          1390:     PWSTR ErrorText
        !          1391: )
        !          1392: /*++
        !          1393: 
        !          1394: Routine Description:
        !          1395: 
        !          1396:     Cause a pop-up - note this doesn't seem to work!
        !          1397: 
        !          1398: Arguments:
        !          1399: 
        !          1400:     ErrorText - text of message
        !          1401: 
        !          1402: Return Value:
        !          1403: 
        !          1404:     None
        !          1405: 
        !          1406: --*/
        !          1407: {
        !          1408:     UNICODE_STRING String;
        !          1409:     RtlInitUnicodeString(&String, ErrorText);
        !          1410:     IoRaiseInformationalHardError(STATUS_SUCCESS,
        !          1411:                                   &String,
        !          1412:                                   NULL);
        !          1413: }
        !          1414: #endif
        !          1415: 
        !          1416: 
        !          1417: #if DBG
        !          1418: 
        !          1419: char *DriverName = "Unknown Sound Driver";
        !          1420: ULONG SoundDebugLevel = 1;
        !          1421: 
        !          1422: void dDbgOut(char * szFormat, ...)
        !          1423: {
        !          1424:     char buf[256];
        !          1425:     va_list va;
        !          1426: 
        !          1427:     va_start(va, szFormat);
        !          1428:     vsprintf(buf, szFormat, va);
        !          1429:     va_end(va);
        !          1430:     DbgPrint("SOUND: %s\n", buf);
        !          1431: }
        !          1432: 
        !          1433: #endif // DBG
        !          1434: 
        !          1435: 
        !          1436: 

unix.superglobalmegacorp.com

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