ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

irpstream.cpp
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel Streaming
00004  * FILE:            drivers/wdm/audio/backpln/portcls/irpstream.cpp
00005  * PURPOSE:         IRP Stream handling
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 #include "private.hpp"
00010 
00011 
00012 class CIrpQueue : public IIrpQueue
00013 {
00014 public:
00015     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
00016 
00017     STDMETHODIMP_(ULONG) AddRef()
00018     {
00019         InterlockedIncrement(&m_Ref);
00020         return m_Ref;
00021     }
00022     STDMETHODIMP_(ULONG) Release()
00023     {
00024         InterlockedDecrement(&m_Ref);
00025 
00026         if (!m_Ref)
00027         {
00028             delete this;
00029             return 0;
00030         }
00031         return m_Ref;
00032     }
00033     IMP_IIrpQueue;
00034     CIrpQueue(IUnknown *OuterUnknown){}
00035     virtual ~CIrpQueue(){}
00036 
00037 protected:
00038 
00039     PKSPIN_CONNECT m_ConnectDetails;
00040     PKSPIN_DESCRIPTOR m_Descriptor;
00041 
00042     KSPIN_LOCK m_IrpListLock;
00043     LIST_ENTRY m_IrpList;
00044     LIST_ENTRY m_FreeIrpList;
00045 
00046     BOOLEAN m_OutOfMapping;
00047     ULONG m_MaxFrameSize;
00048     ULONG m_Alignment;
00049     ULONG m_TagSupportEnabled;
00050     ULONG m_NumDataAvailable;
00051     volatile ULONG m_CurrentOffset;
00052 
00053     PIRP m_Irp;
00054 
00055 
00056     LONG m_Ref;
00057 
00058 };
00059 
00060 typedef struct
00061 {
00062     ULONG StreamHeaderCount;
00063     ULONG StreamHeaderIndex;
00064     ULONG TotalStreamData;
00065 
00066     PKSSTREAM_HEADER CurStreamHeader;
00067     PVOID * Data;
00068     PVOID * Tags;
00069 }KSSTREAM_DATA, *PKSSTREAM_DATA;
00070 
00071 #define STREAM_DATA_OFFSET   (0)
00072 
00073 
00074 NTSTATUS
00075 NTAPI
00076 CIrpQueue::QueryInterface(
00077     IN  REFIID refiid,
00078     OUT PVOID* Output)
00079 {
00080     if (IsEqualGUIDAligned(refiid, IID_IUnknown))
00081     {
00082         *Output = PVOID(PUNKNOWN(this));
00083         PUNKNOWN(*Output)->AddRef();
00084         return STATUS_SUCCESS;
00085     }
00086 
00087     return STATUS_UNSUCCESSFUL;
00088 }
00089 
00090 NTSTATUS
00091 NTAPI
00092 CIrpQueue::Init(
00093     IN PKSPIN_CONNECT ConnectDetails,
00094     IN PKSPIN_DESCRIPTOR Descriptor,
00095     IN ULONG FrameSize,
00096     IN ULONG Alignment,
00097     IN ULONG TagSupportEnabled)
00098 {
00099     m_ConnectDetails = ConnectDetails;
00100     m_Descriptor = Descriptor;
00101     m_MaxFrameSize = FrameSize;
00102     m_Alignment = Alignment;
00103     m_TagSupportEnabled = TagSupportEnabled;
00104 
00105     InitializeListHead(&m_IrpList);
00106     InitializeListHead(&m_FreeIrpList);
00107     KeInitializeSpinLock(&m_IrpListLock);
00108 
00109     return STATUS_SUCCESS;
00110 }
00111 
00112 NTSTATUS
00113 NTAPI
00114 CIrpQueue::AddMapping(
00115     IN PIRP Irp,
00116     OUT PULONG Data)
00117 {
00118     PKSSTREAM_HEADER Header;
00119     NTSTATUS Status = STATUS_UNSUCCESSFUL;
00120     PIO_STACK_LOCATION IoStack;
00121     ULONG Index, Length;
00122     PMDL Mdl;
00123     PKSSTREAM_DATA StreamData;
00124 
00125     PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
00126 
00127     // allocate stream data
00128     StreamData = (PKSSTREAM_DATA)AllocateItem(NonPagedPool, sizeof(KSSTREAM_DATA), TAG_PORTCLASS);
00129     if (!StreamData)
00130     {
00131         // not enough memory
00132         return STATUS_INSUFFICIENT_RESOURCES;
00133     }
00134 
00135     // get current irp stack location
00136     IoStack = IoGetCurrentIrpStackLocation(Irp);
00137 
00138     // lets probe the irp
00139     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
00140     {
00141         // probe IOCTL_KS_WRITE_STREAM
00142         Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
00143     }
00144     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
00145     {
00146         // probe IOCTL_KS_READ_STREAM
00147         Status = KsProbeStreamIrp(Irp, KSSTREAM_READ  | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
00148     }
00149 
00150     // check for success
00151     if (!NT_SUCCESS(Status))
00152     {
00153         // irp probing failed
00154         FreeItem(StreamData, TAG_PORTCLASS);
00155         return Status;
00156     }
00157 
00158     // get first stream header
00159     Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
00160 
00161     // store header
00162     StreamData->CurStreamHeader = Header;
00163 
00164     // sanity check
00165     PC_ASSERT(Header);
00166 
00167     // first calculate the numbers of stream headers
00168     Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
00169 
00170     do
00171     {
00172         /* subtract size */
00173         Length -= Header->Size;
00174 
00175         /* increment header count */
00176         StreamData->StreamHeaderCount++;
00177 
00178         if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
00179         {
00180             // irp sink
00181             StreamData->TotalStreamData += Header->DataUsed;
00182         }
00183         else
00184         {
00185             // irp source
00186             StreamData->TotalStreamData += Header->FrameExtent;
00187         }
00188 
00189         /* move to next header */
00190         Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size);
00191 
00192     }while(Length);
00193 
00194     // sanity check
00195     ASSERT(StreamData->StreamHeaderCount);
00196 
00197     // allocate array for storing the pointers of the data */
00198     StreamData->Data = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) * StreamData->StreamHeaderCount, TAG_PORTCLASS);
00199     if (!StreamData->Data)
00200     {
00201         // out of memory
00202         FreeItem(StreamData, TAG_PORTCLASS);
00203 
00204         // done
00205         return STATUS_INSUFFICIENT_RESOURCES;
00206     }
00207 
00208     if (m_TagSupportEnabled)
00209     {
00210         // allocate array for storing the pointers of the data */
00211         StreamData->Tags = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) * StreamData->StreamHeaderCount, TAG_PORTCLASS);
00212         if (!StreamData->Data)
00213         {
00214             // out of memory
00215             FreeItem(StreamData->Data, TAG_PORTCLASS);
00216             FreeItem(StreamData, TAG_PORTCLASS);
00217 
00218             // done
00219             return STATUS_INSUFFICIENT_RESOURCES;
00220         }
00221     }
00222 
00223 
00224     // now get a system address for the user buffers
00225     Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
00226     Mdl = Irp->MdlAddress;
00227 
00228     for(Index = 0; Index < StreamData->StreamHeaderCount; Index++)
00229     {
00230         /* get system address */
00231         StreamData->Data[Index] = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
00232 
00233         /* check for success */
00234         if (!StreamData->Data[Index])
00235         {
00236             // out of resources
00237             FreeItem(StreamData->Data, TAG_PORTCLASS);
00238 
00239             if (m_TagSupportEnabled)
00240             {
00241                 // free tag array
00242                 FreeItem(StreamData->Tags, TAG_PORTCLASS);
00243             }
00244 
00245             FreeItem(StreamData, TAG_PORTCLASS);
00246             // done
00247             return STATUS_INSUFFICIENT_RESOURCES;
00248         }
00249 
00250         if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
00251         {
00252             // increment available data
00253             InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, Header->DataUsed);
00254         }
00255         else if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT)
00256         {
00257             // increment available data
00258             InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, Header->FrameExtent);
00259         }
00260 
00261         // move to next header / mdl
00262         Mdl = Mdl->Next;
00263         Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size);
00264 
00265     }
00266 
00267     // store stream data
00268     Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET] = (PVOID)StreamData;
00269 
00270     *Data = StreamData->TotalStreamData;
00271 
00272     // mark irp as pending
00273     IoMarkIrpPending(Irp);
00274 
00275     // add irp to cancelable queue
00276     KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, Irp, KsListEntryTail, NULL);
00277 
00278     // disable mapping failed status
00279     m_OutOfMapping = FALSE;
00280 
00281     // done
00282     return STATUS_SUCCESS;
00283 }
00284 
00285 NTSTATUS
00286 NTAPI
00287 CIrpQueue::GetMapping(
00288     OUT PUCHAR * Buffer,
00289     OUT PULONG BufferSize)
00290 {
00291     PIRP Irp;
00292     ULONG Offset;
00293     PKSSTREAM_DATA StreamData;
00294 
00295     // check if there is an irp in the partially processed
00296     if (m_Irp)
00297     {
00298         // use last irp
00299         if (m_Irp->Cancel == FALSE)
00300         {
00301             Irp = m_Irp;
00302             Offset = m_CurrentOffset;
00303         }
00304         else
00305         {
00306             // irp has been cancelled
00307             m_Irp->IoStatus.Status = STATUS_CANCELLED;
00308             IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
00309             m_Irp = Irp = NULL;
00310             m_CurrentOffset = 0;
00311         }
00312     }
00313     else
00314     {
00315         // get a fresh new irp from the queue
00316         m_Irp = Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
00317         m_CurrentOffset = Offset = 0;
00318     }
00319 
00320     if (!Irp)
00321     {
00322         // no irp buffer available
00323         return STATUS_UNSUCCESSFUL;
00324     }
00325 
00326     // get stream data
00327     StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
00328 
00329     // sanity check
00330     PC_ASSERT(StreamData);
00331 
00332     // get buffer size
00333     if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
00334     {
00335         // sink pin
00336         *BufferSize = StreamData->CurStreamHeader->DataUsed - Offset;
00337     }
00338     else
00339     {
00340         // source pin
00341         *BufferSize = StreamData->CurStreamHeader->FrameExtent - Offset;
00342     }
00343 
00344     // sanity check
00345     PC_ASSERT(*BufferSize);
00346 
00347     // store buffer
00348     *Buffer = &((PUCHAR)StreamData->Data[StreamData->StreamHeaderIndex])[Offset];
00349 
00350     // unset flag that no irps are available
00351     m_OutOfMapping = FALSE;
00352 
00353     return STATUS_SUCCESS;
00354 }
00355 
00356 VOID
00357 NTAPI
00358 CIrpQueue::UpdateMapping(
00359     IN ULONG BytesWritten)
00360 {
00361     PKSSTREAM_DATA StreamData;
00362     ULONG Size;
00363     PIO_STACK_LOCATION IoStack;
00364 
00365     // sanity check
00366     ASSERT(m_Irp);
00367 
00368     // get stream data
00369     StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
00370 
00371     // sanity check
00372     ASSERT(StreamData);
00373 
00374     // add to current offset
00375     InterlockedExchangeAdd((PLONG)&m_CurrentOffset, (LONG)BytesWritten);
00376 
00377     if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT)
00378     {
00379         // store written bytes (source pin)
00380         StreamData->CurStreamHeader->DataUsed += BytesWritten;
00381     }
00382 
00383     // decrement available data counter
00384     m_NumDataAvailable -= BytesWritten;
00385 
00386     // get audio buffer size
00387     if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT)
00388         Size = StreamData->CurStreamHeader->FrameExtent;
00389     else
00390         Size = StreamData->CurStreamHeader->DataUsed;
00391 
00392     // sanity check
00393     PC_ASSERT(Size);
00394 
00395     if (m_CurrentOffset >= Size)
00396     {
00397         // sanity check
00398         PC_ASSERT(Size == m_CurrentOffset);
00399 
00400         if (StreamData->StreamHeaderIndex + 1 < StreamData->StreamHeaderCount)
00401         {
00402             // move to next stream header
00403             StreamData->CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader + StreamData->CurStreamHeader->Size);
00404 
00405             // increment stream header index
00406             StreamData->StreamHeaderIndex++;
00407 
00408             // reset offset
00409             m_CurrentOffset = 0;
00410 
00411             // done
00412             return;
00413         }
00414 
00415         //
00416         // all stream buffers have been played
00417         // check if this is a looped buffer
00418         //
00419         if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
00420         {
00421             // looped streaming repeat the buffers untill
00422             // the caller decides to stop the streams
00423 
00424             // reset stream header index
00425             StreamData->StreamHeaderIndex = 0;
00426 
00427             // reset stream header
00428             StreamData->CurStreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
00429 
00430             // increment available data
00431             InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, StreamData->TotalStreamData);
00432 
00433             // re-insert irp
00434             KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL);
00435 
00436             // clear current irp
00437             m_Irp = NULL;
00438 
00439             // reset offset
00440             m_CurrentOffset = 0;
00441 
00442             // done
00443             return;
00444         }
00445 
00446         // free stream data array
00447         FreeItem(StreamData->Data, TAG_PORTCLASS);
00448 
00449         if (m_TagSupportEnabled)
00450         {
00451             // free tag array
00452             FreeItem(StreamData->Tags, TAG_PORTCLASS);
00453         }
00454 
00455         // free stream data
00456         FreeItem(StreamData, TAG_PORTCLASS);
00457 
00458         // get io stack
00459         IoStack = IoGetCurrentIrpStackLocation(m_Irp);
00460 
00461         // store operation status
00462         m_Irp->IoStatus.Status = STATUS_SUCCESS;
00463 
00464         // store operation length
00465         m_Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
00466 
00467         // complete the request
00468         IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
00469 
00470         // remove irp as it is complete
00471         m_Irp = NULL;
00472 
00473         // reset offset
00474         m_CurrentOffset = 0;
00475     }
00476 }
00477 
00478 ULONG
00479 NTAPI
00480 CIrpQueue::NumData()
00481 {
00482     // returns the amount of audio stream data available
00483     return m_NumDataAvailable;
00484 }
00485 
00486 BOOL
00487 NTAPI
00488 CIrpQueue::CancelBuffers()
00489 {
00490     //TODO: own cancel routine
00491 
00492     // is there an active irp
00493     if (m_Irp)
00494     {
00495         // re-insert it to cancelable queue
00496         KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL);
00497         //set it to zero
00498         m_Irp = NULL;
00499     }
00500 
00501     // cancel all irps
00502     KsCancelIo(&m_IrpList, &m_IrpListLock);
00503 
00504     // reset number of data available
00505     m_NumDataAvailable = 0;
00506 
00507     // done
00508     return TRUE;
00509 }
00510 
00511 NTSTATUS
00512 NTAPI
00513 CIrpQueue::GetMappingWithTag(
00514     IN PVOID Tag,
00515     OUT PPHYSICAL_ADDRESS  PhysicalAddress,
00516     OUT PVOID  *VirtualAddress,
00517     OUT PULONG  ByteCount,
00518     OUT PULONG  Flags)
00519 {
00520     PKSSTREAM_DATA StreamData;
00521 
00522     /* sanity checks */
00523     PC_ASSERT(Tag != NULL);
00524     PC_ASSERT(PhysicalAddress);
00525     PC_ASSERT(VirtualAddress);
00526     PC_ASSERT(ByteCount);
00527     PC_ASSERT(Flags);
00528 
00529     if (!m_Irp)
00530     {
00531         // get an irp from the queue
00532         m_Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
00533     }
00534 
00535     // check if there is an irp
00536     if (!m_Irp)
00537     {
00538         // no irp available
00539         m_OutOfMapping = TRUE;
00540         return STATUS_NOT_FOUND;
00541     }
00542 
00543     // get stream data
00544     StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
00545 
00546     // sanity check
00547     PC_ASSERT(StreamData->StreamHeaderIndex < StreamData->StreamHeaderCount);
00548 
00549     // setup mapping
00550     *PhysicalAddress = MmGetPhysicalAddress(StreamData->Data[StreamData->StreamHeaderIndex]);
00551     *VirtualAddress = StreamData->Data[StreamData->StreamHeaderIndex];
00552 
00553     // store tag in irp
00554     StreamData->Tags[StreamData->StreamHeaderIndex] = Tag;
00555 
00556     // mapping size
00557     if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
00558     {
00559         // sink pin
00560         *ByteCount = StreamData->CurStreamHeader->DataUsed;
00561 
00562         // decrement num data available
00563         m_NumDataAvailable -= StreamData->CurStreamHeader->DataUsed;
00564     }
00565     else
00566     {
00567         // source pin
00568         *ByteCount = StreamData->CurStreamHeader->FrameExtent;
00569 
00570         // decrement num data available
00571         m_NumDataAvailable -= StreamData->CurStreamHeader->FrameExtent;
00572     }
00573 
00574     if (StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount)
00575     {
00576         // last mapping
00577         *Flags = 1;
00578 
00579         // insert mapping into free list
00580         ExInterlockedInsertTailList(&m_FreeIrpList, &m_Irp->Tail.Overlay.ListEntry, &m_IrpListLock);
00581 
00582         // clear irp
00583         m_Irp = NULL;
00584 
00585     }
00586     else
00587     {
00588         // one more mapping in the irp
00589         *Flags = 0;
00590 
00591         // increment header index
00592         StreamData->StreamHeaderIndex++;
00593 
00594         // move to next header
00595         StreamData->CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader + StreamData->CurStreamHeader->Size);
00596     }
00597 
00598     // done
00599     return STATUS_SUCCESS;
00600 }
00601 
00602 NTSTATUS
00603 NTAPI
00604 CIrpQueue::ReleaseMappingWithTag(
00605     IN PVOID Tag)
00606 {
00607     PIRP Irp;
00608     PLIST_ENTRY CurEntry;
00609     PKSSTREAM_DATA StreamData;
00610     PIO_STACK_LOCATION IoStack;
00611     ULONG Index;
00612 
00613     // first check if there is an active irp
00614     if (m_Irp)
00615     {
00616         // now check if there are already used mappings
00617         StreamData = (PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
00618 
00619         if (StreamData->StreamHeaderIndex)
00620         {
00621             // check if the released mapping is one current processed irps
00622             for(Index = 0; Index < StreamData->StreamHeaderIndex; Index++)
00623             {
00624                 // check if it is the same tag
00625                 if (StreamData->Tags[Index] == Tag)
00626                 {
00627                     // mark mapping as released
00628                     StreamData->Tags[Index] = NULL;
00629 
00630                     // done
00631                     return STATUS_SUCCESS;
00632                 }
00633 
00634             }
00635         }
00636     }
00637 
00638     // remove irp from used list
00639     CurEntry = ExInterlockedRemoveHeadList(&m_FreeIrpList, &m_IrpListLock);
00640 
00641     // sanity check
00642     PC_ASSERT(CurEntry);
00643 
00644     // get irp from list entry
00645     Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
00646 
00647     // get stream data
00648     StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
00649 
00650     // sanity check
00651     PC_ASSERT(StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount);
00652 
00653     // check if the released mapping is one of these
00654     for(Index = 0; Index < StreamData->StreamHeaderCount; Index++)
00655     {
00656         if (StreamData->Tags[Index] == Tag)
00657         {
00658             // mark mapping as released
00659             StreamData->Tags[Index] = NULL;
00660 
00661             // done
00662             break;
00663         }
00664         else
00665         {
00666             //
00667             // we assume that mappings are released in the same order as they have been acquired
00668             // therefore if the current mapping is not the searched one, it must have been already
00669             // released
00670             //
00671             PC_ASSERT(StreamData->Tags[Index] == NULL);
00672         }
00673     }
00674 
00675     // check if this is the last one released mapping
00676     if (Index + 1 == StreamData->StreamHeaderCount)
00677     {
00678         // last mapping released
00679         // now check if this is a looped buffer
00680         if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
00681         {
00682             // looped buffers are not completed when they have been played
00683             // they are completed when the stream is set to stop
00684 
00685             // reset stream header index
00686             StreamData->StreamHeaderIndex = 0;
00687 
00688             // reset stream header
00689             StreamData->CurStreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
00690 
00691             // increment available data
00692             InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, StreamData->TotalStreamData);
00693 
00694             // re-insert irp
00695             KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, Irp, KsListEntryTail, NULL);
00696 
00697             // done
00698             return STATUS_SUCCESS;
00699         }
00700 
00701         //
00702         // time to complete non looped buffer
00703         //
00704 
00705         // free stream data array
00706         FreeItem(StreamData->Data, TAG_PORTCLASS);
00707 
00708         // free stream tags array
00709         FreeItem(StreamData->Tags, TAG_PORTCLASS);
00710 
00711         // free stream data
00712         FreeItem(StreamData, TAG_PORTCLASS);
00713 
00714         // get io stack
00715         IoStack = IoGetCurrentIrpStackLocation(Irp);
00716 
00717         // store operation status
00718         Irp->IoStatus.Status = STATUS_SUCCESS;
00719 
00720         // store operation length
00721         Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
00722 
00723         // complete the request
00724         IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
00725     }
00726 
00727     return STATUS_SUCCESS;
00728 }
00729 
00730 BOOLEAN
00731 NTAPI
00732 CIrpQueue::HasLastMappingFailed()
00733 {
00734     return m_OutOfMapping;
00735 }
00736 
00737 ULONG
00738 NTAPI
00739 CIrpQueue::GetCurrentIrpOffset()
00740 {
00741 
00742     return m_CurrentOffset;
00743 }
00744 
00745 BOOLEAN
00746 NTAPI
00747 CIrpQueue::GetAcquiredTagRange(
00748     IN PVOID * FirstTag,
00749     IN PVOID * LastTag)
00750 {
00751     KIRQL OldLevel;
00752     BOOLEAN Ret = FALSE;
00753     //PIRP Irp;
00754     //PLIST_ENTRY CurEntry;
00755     //PKSSTREAM_DATA StreamData;
00756 
00757     // lock list
00758     KeAcquireSpinLock(&m_IrpListLock, &OldLevel);
00759 
00760     // initialize to zero
00761     *FirstTag = NULL;
00762     *LastTag = NULL;
00763 
00764     UNIMPLEMENTED;
00765 
00766     // release lock
00767     KeReleaseSpinLock(&m_IrpListLock, OldLevel);
00768     // done
00769     return Ret;
00770 }
00771 
00772 NTSTATUS
00773 NTAPI
00774 NewIrpQueue(
00775     IN IIrpQueue **Queue)
00776 {
00777     CIrpQueue *This = new(NonPagedPool, TAG_PORTCLASS)CIrpQueue(NULL);
00778     if (!This)
00779         return STATUS_INSUFFICIENT_RESOURCES;
00780 
00781     This->AddRef();
00782 
00783     *Queue = (IIrpQueue*)This;
00784     return STATUS_SUCCESS;
00785 }
00786 

Generated on Fri May 25 2012 04:26:50 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.