/*++ Copyright (c) 1991 Microsoft Corporation Module Name: sh_api.c Abstract: This module implements the Stream Head Driver functions that map between NT IRPs and STREAMS APIs. Author: Eric Chin (ericc) July 1, 1991 Revision History: --*/ #include "shead.h" #include "sh_inc.h" NTSTATUS SHDispIoctl( IN PIRP irp, IN PIO_STACK_LOCATION irpsp ) /*++ Routine Description: This routine unwraps the IRP sent via a STREAMS ioctl(2) api, probes the arguments, and calls the appropriate do_*() function. Arguments: irp - pointer to I/O request packet irpsp - pointer to current stack location in IRP Return Value: NTSTATUS - Status of request --*/ { int icode; char *inbuf; NTSTATUS status; int MyErrno, retval; ASSERT((irpsp->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED); ASSERT(irpsp->Parameters.DeviceIoControl.IoControlCode == IOCTL_STREAMS_IOCTL); IF_STRMDBG(CALL) { STRMTRACE(("SHEAD: SHDispIoctl(irp = %lx), fileobj = %lx\n", irp, irpsp->FileObject)); } if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(int)) { IF_STRMDBG(TERSE) { STRMTRACE(("SHEAD: SHDispIoctl() insufficient inbuflen = %lx\n", irpsp->Parameters.DeviceIoControl.InputBufferLength)); } shortreply(irp, STATUS_INVALID_PARAMETER, 0); return(STATUS_INVALID_PARAMETER); } /* * the first int in the input buffer is the ioctl(2) command code, * followed by command-specific parameters. */ icode = * (int *) irp->AssociatedIrp.SystemBuffer; inbuf = (char *) irp->AssociatedIrp.SystemBuffer + sizeof(int); switch (icode) { case I_STR: return(SHDispIStr(irp)); break; case I_FDINSERT: return(SHDispFdInsert(irp, irpsp)); break; case I_PUSH: status = do_push( irp, inbuf, irpsp->Parameters.DeviceIoControl.InputBufferLength - sizeof(int), &retval, &MyErrno); break; case I_LINK: status = do_link( irp, inbuf, irpsp->Parameters.DeviceIoControl.InputBufferLength - sizeof(int), &retval, &MyErrno); break; case I_DEBUG: status = do_sdebug( irp, irpsp->FileObject, inbuf, irpsp->Parameters.DeviceIoControl.InputBufferLength - sizeof(int), &retval, &MyErrno); break; case I_UNLINK: status = do_unlink( irp, inbuf, irpsp->Parameters.DeviceIoControl.InputBufferLength - sizeof(int), &retval, &MyErrno); break; default: retval = -1; MyErrno = EINVAL; status = STATUS_SUCCESS; break; } switch (status) { case STATUS_PENDING: break; default: if (NT_SUCCESS(status)) { SHpGenReply(irp, retval, MyErrno); } else { shortreply(irp, status, 0); } break; } IF_STRMDBG(CALL) { STRMTRACE(("SHEAD: SHDispIoctl(irp = %lx) status = %lx\n", irp, status)); } return(status); } // SHDispIoctl NTSTATUS SHDispPoll( IN PIRP irp, IN PIO_STACK_LOCATION irpsp ) /*++ Routine Description: This routine unwraps the IRP sent via a STREAMS poll(2) api, probes the arguments, and then calls do_poll(). Arguments: irp - pointer to I/O request packet irpsp - pointer to current stack location in IRP Return Value: NTSTATUS - Status of request --*/ { NTSTATUS status; int MyErrno, retval; ASSERT((irpsp->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED); ASSERT(irpsp->Parameters.DeviceIoControl.IoControlCode == IOCTL_STREAMS_POLL); IF_STRMDBG(CALL) { STRMTRACE(("SHEAD: SHDispPoll(), SysBuf = %lx, UserBuf = %lx\n", irp->AssociatedIrp.SystemBuffer, irp->UserBuffer)); } status = do_poll( irp, irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.DeviceIoControl.InputBufferLength, &retval, &MyErrno); switch (status) { case STATUS_PENDING: break; default: if (NT_SUCCESS(status)) { SHpGenReply(irp, retval, MyErrno); } else { shortreply(irp, status, 0); } break; } IF_STRMDBG(CALL) { STRMTRACE(("SHEAD: SHDispPoll(irp = %lx) status = %lx\n", irp, status)); } return(status); } // SHDispPoll