282 lines
5.8 KiB
C++
282 lines
5.8 KiB
C++
/*++
|
||
|
||
Copyright (c) 1998-2000 Microsoft Corporation. All rights reserved.
|
||
|
||
Module Name:
|
||
|
||
shmisc.cpp
|
||
|
||
Abstract:
|
||
|
||
This module contains miscellaneous functions for the kernel streaming
|
||
filter shell.
|
||
|
||
Author:
|
||
|
||
Dale Sather (DaleSat) 31-Jul-1998
|
||
|
||
--*/
|
||
|
||
#include "private.h"
|
||
#include "ksshellp.h"
|
||
#include <kcom.h>
|
||
|
||
#pragma code_seg("PAGE")
|
||
|
||
|
||
void
|
||
KsWorkSinkItemWorker(
|
||
IN PVOID Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine calls a worker function on a work sink interface.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
|
||
{
|
||
_DbgPrintF(DEBUGLVL_BLAB,("KsWorkSinkItemWorker"));
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT(Context);
|
||
|
||
PIKSWORKSINK(Context)->Work();
|
||
}
|
||
|
||
|
||
void
|
||
KspShellStandardConnect(
|
||
IN PIKSSHELLTRANSPORT NewTransport OPTIONAL,
|
||
OUT PIKSSHELLTRANSPORT *OldTransport OPTIONAL,
|
||
IN KSPIN_DATAFLOW DataFlow,
|
||
IN PIKSSHELLTRANSPORT ThisTransport,
|
||
IN PIKSSHELLTRANSPORT* SourceTransport,
|
||
IN PIKSSHELLTRANSPORT* SinkTransport
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine establishes a transport connection.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
|
||
{
|
||
_DbgPrintF(DEBUGLVL_BLAB,("KspShellStandardConnect"));
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT(ThisTransport);
|
||
ASSERT(SourceTransport);
|
||
ASSERT(SinkTransport);
|
||
|
||
//
|
||
// Make sure this object sticks around until we are done.
|
||
//
|
||
ThisTransport->AddRef();
|
||
|
||
PIKSSHELLTRANSPORT* transport =
|
||
(DataFlow & KSPIN_DATAFLOW_IN) ?
|
||
SourceTransport :
|
||
SinkTransport;
|
||
|
||
//
|
||
// Release the current source/sink.
|
||
//
|
||
if (*transport) {
|
||
//
|
||
// First disconnect the old back link. If we are connecting a back
|
||
// link for a new connection, we need to do this too. If we are
|
||
// clearing a back link (disconnecting), this request came from the
|
||
// component we're connected to, so we don't bounce back again.
|
||
//
|
||
switch (DataFlow) {
|
||
case KSPIN_DATAFLOW_IN:
|
||
(*transport)->Connect(NULL,NULL,KSPSHELL_BACKCONNECT_OUT);
|
||
break;
|
||
|
||
case KSPIN_DATAFLOW_OUT:
|
||
(*transport)->Connect(NULL,NULL,KSPSHELL_BACKCONNECT_IN);
|
||
break;
|
||
|
||
case KSPSHELL_BACKCONNECT_IN:
|
||
if (NewTransport) {
|
||
(*transport)->Connect(NULL,NULL,KSPSHELL_BACKCONNECT_OUT);
|
||
}
|
||
break;
|
||
|
||
case KSPSHELL_BACKCONNECT_OUT:
|
||
if (NewTransport) {
|
||
(*transport)->Connect(NULL,NULL,KSPSHELL_BACKCONNECT_IN);
|
||
}
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Now release the old neighbor or hand it off to the caller.
|
||
//
|
||
if (OldTransport) {
|
||
*OldTransport = *transport;
|
||
} else {
|
||
(*transport)->Release();
|
||
}
|
||
} else if (OldTransport) {
|
||
*OldTransport = NULL;
|
||
}
|
||
|
||
//
|
||
// Copy the new source/sink.
|
||
//
|
||
*transport = NewTransport;
|
||
|
||
if (NewTransport) {
|
||
//
|
||
// Add a reference if necessary.
|
||
//
|
||
NewTransport->AddRef();
|
||
|
||
//
|
||
// Do the back connect if necessary.
|
||
//
|
||
switch (DataFlow) {
|
||
case KSPIN_DATAFLOW_IN:
|
||
NewTransport->Connect(ThisTransport,NULL,KSPSHELL_BACKCONNECT_OUT);
|
||
break;
|
||
|
||
case KSPIN_DATAFLOW_OUT:
|
||
NewTransport->Connect(ThisTransport,NULL,KSPSHELL_BACKCONNECT_IN);
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now this object may die if it has no references.
|
||
//
|
||
ThisTransport->Release();
|
||
}
|
||
|
||
#pragma code_seg()
|
||
|
||
|
||
NTSTATUS
|
||
KspShellTransferKsIrp(
|
||
IN PIKSSHELLTRANSPORT NewTransport,
|
||
IN PIRP Irp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine transfers a streaming IRP using the kernel streaming shell
|
||
transport.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
|
||
{
|
||
_DbgPrintF(DEBUGLVL_BLAB,("KspShellTransferKsIrp"));
|
||
|
||
ASSERT(NewTransport);
|
||
ASSERT(Irp);
|
||
|
||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||
while (NewTransport) {
|
||
PIKSSHELLTRANSPORT nextTransport;
|
||
status = NewTransport->TransferKsIrp(Irp,&nextTransport);
|
||
|
||
ASSERT(NT_SUCCESS(status) || ! nextTransport);
|
||
|
||
NewTransport = nextTransport;
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
#pragma code_seg("PAGE")
|
||
|
||
#if DBG
|
||
|
||
void
|
||
DbgPrintCircuit(
|
||
IN PIKSSHELLTRANSPORT Transport
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine spews a transport circuit.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
|
||
{
|
||
_DbgPrintF(DEBUGLVL_BLAB,("DbgPrintCircuit"));
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT(Transport);
|
||
|
||
#define MAX_NAME_SIZE 64
|
||
|
||
PIKSSHELLTRANSPORT transport = Transport;
|
||
while (transport) {
|
||
CHAR name[MAX_NAME_SIZE + 1];
|
||
PIKSSHELLTRANSPORT next;
|
||
PIKSSHELLTRANSPORT prev;
|
||
|
||
transport->DbgRollCall(MAX_NAME_SIZE,name,&next,&prev);
|
||
DbgPrint(" %s",name);
|
||
|
||
if (prev) {
|
||
PIKSSHELLTRANSPORT next2;
|
||
PIKSSHELLTRANSPORT prev2;
|
||
prev->DbgRollCall(MAX_NAME_SIZE,name,&next2,&prev2);
|
||
if (next2 != transport) {
|
||
DbgPrint(" SOURCE'S(0x%08x) SINK(0x%08x) != THIS(%08x)",prev,next2,transport);
|
||
}
|
||
} else {
|
||
DbgPrint(" NO SOURCE");
|
||
}
|
||
|
||
if (next) {
|
||
PIKSSHELLTRANSPORT next2;
|
||
PIKSSHELLTRANSPORT prev2;
|
||
next->DbgRollCall(MAX_NAME_SIZE,name,&next2,&prev2);
|
||
if (prev2 != transport) {
|
||
DbgPrint(" SINK'S(0x%08x) SOURCE(0x%08x) != THIS(%08x)",next,prev2,transport);
|
||
}
|
||
} else {
|
||
DbgPrint(" NO SINK");
|
||
}
|
||
|
||
DbgPrint("\n");
|
||
|
||
transport = next;
|
||
if (transport == Transport) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#endif
|