/*++
*******************************************************************************
* Copyright (c) 1990-97 Digi International Inc., All Rights Reserved				*
* 																										*
* This software contains proprietary and confidential information of Digi		*
* International Inc.  By accepting transfer of this copy, Recipient agrees		*
* to retain this software in confidence, to prevent disclosure to others,		*
* and to make no use of this software other than that for which it was			*
* delivered.  This is an unpublished copyrighted work of Digi International	*
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly	*
* prohibited.																						*
* 																										*
* Restricted Rights Legend																		*
*																										*
* Use, duplication, or disclosure by the Government is subject to					*
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in			*
* Technical Data and Computer Software clause at DFARS 252.227-7031 or			*
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -				*
* Restricted Rights at 48 CFR 52.227-19, as applicable.								*
*																										*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343				*
*																										*
*******************************************************************************

Module Name:

   DsVerify.c

Abstract:

   This file contains a set of library routines which can be used to test and 
   validate a DStreams Provider driver implementation of the DStreams API.  The
	routines are intented to be portable between usermode and kernel, so that
	simple user/kernel wrappers may be written which control the execution of the 
	tests but don't repeat all of the actual test code.

	This first implementation only includes a usermode test.  Although some Kernelmode 
	support routines are done (#ifdef'd out), the full implementation is left as an 
	exercise for the reader.   :-)

Author:

   Michael Zarns

--*/
//#define DIGI_KERNEL
#ifdef DIGI_KERNEL
#include <ntddk.h>
#define BOOL BOOLEAN
#else
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#endif

#include "DsIoctl.h"


///////////////////////////////////////////////////////////////////////////////
//
// Globals 
//

#ifndef _NTDDK_
// Debug print buffer.  No multithreaded issues as all tests are run in sequence
// not simultaneously.
char DbgBuf[2048];
#endif

typedef BOOL ( * PVERIFY_ROUTINE )( HANDLE hDevice );



///////////////////////////////////////////////////////////////////////////////
//
//  Constants and Defines
//

// Define HOUSTON to build for a dense adapter.  Otherwise it builds for
// Syncport/DFPrime.  Syncport uses SLO0 loopback device, houston uses IWANLOOP.
#define HOUSTON

#ifdef HOUSTON
#define DS_LOOP_DEVICE		"IWANLOOP"
#define DS_UPPER_DEVICE		"IL3"
#define DS_LOWER_DEVICE		"LAPD"
#else
#define DS_LOOP_DEVICE		"SLO0"
#define DS_UPPER_DEVICE		"X250"
#define DS_LOWER_DEVICE		"LAPB"
#endif

#define DS_DEFAULT_SIZE  256

// An IO_REQUEST object is used for every PutMsg request
typedef struct DSV_REQUEST
{
	PUCHAR pControl;
	PUCHAR pData;
	union
	{
	  DS_OPEN   Open;
	  DS_CLOSE  Close;
	  DS_PUTMSG PutMsg;
	  DS_GETMSG GetMsg;
	  DS_IOCTL  Ioctl;
	  DS_LINK   Link;
	  DS_PUSH   Push;
	};

#ifdef _NTDDK_
	KEVENT Event;
	IO_STATUS_BLOCK IoStatus;
#else
	OVERLAPPED Ol;
	DWORD dwBytes;
#endif

} DSV_REQUEST, *PDSV_REQUEST;



///////////////////////////////////////////////////////////////////////////////
//
// Debug Output Support
//							  

#if DBG // Checked build

#ifdef _NTDDK_	// kernelmode build
#define DebugBreak()				DebugBreakPoint()
#define DebugPrint(stuff)		DbgPrint stuff
#else // usermode	build
#define DebugPrint(stuff)		printf stuff
#endif // _NTDDK_

#undef ASSERT
#define ASSERT( statement )																\
{																									\
	if ( !(statement) )																		\
	{																								\
		DebugPrint( ( "ASSERT FAILED: " #statement "\n\tfile %s, line %d\n",	\
		            __FILE__, __LINE__ ) );												\
		DebugBreak();																			\
	}																								\
}

#else // Free build

#define DebugPrint(foo)
#define DebugBreak()				;
#define ASSERT( statement )	;

#endif // DBG



///////////////////////////////////////////////////////////////////////////////
//
// Kernel/User Wrapper Routines.  
// 
// Use these routines which hide system calls to keep code in this library 
// portable across kernel and user modes.
// 
//

#if 0
#ifdef _NTDDK_ // Kernelmode


_inline VOID 
InitRequest( PREQUEST pRequest )
{
	KeInitializeEvent( &pRequest->Event, NotificationEvent, FALSE );
	RtlZeroMemory( &pRequest->IoStatus, sizeof( IO_STATUS_BLOCK ) );
}

_inline VOID 
ResetRequest( PREQUEST pRequest )
{
	KeClearEvent( &pRequest->Event );
	RtlZeroMemory( &pRequest->IoStatus, sizeof( IO_STATUS_BLOCK ) );
}

#define ReleaseRequest( s )	;

#else // usermode

_inline VOID 
InitRequest( PREQUEST pRequest )
{
	dsvZeroMemory( &pRequest->Ol, sizeof( OVERLAPPED ) );
	pRequest->Ol.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	pRequest->dwBytes = 0;
}

_inline VOID 
ResetRequest( PREQUEST pRequest )
{
	HANDLE hEvent = pRequest->Ol.hEvent;
	dsvZeroMemory( &pRequest->Ol, sizeof( OVERLAPPED ) );
	pRequest->Ol.hEvent = hEvent;
	ResetEvent( pRequest->Ol.hEvent );
	pRequest->dwBytes = 0;
}

_inline VOID
ReleaseRequest( PREQUEST pRequest )
{
	CloseHandle( pRequest->Ol.hEvent );
}

#endif // _NTDDK_
#endif

//
// I/O Request routines
//

#ifdef _NTDDK_	// Kernel mode
#define dsvZeroMemory	RtlZeroMemory

BOOL
SyncIoRequest( HANDLE hDevice, 
               ULONG Ioctl, 
               PVOID pInData, 
               ULONG InDataLength, 
               PVOID pOutData, 
               ULONG OutDataLength,
               PKEVENT pEvent,
               PIO_STATUS_BLOCK pIoStatus )
{
	BOOL bSuccess;
	PIRP pIrp;
	NTSTATUS Status;

	pIrp = IoBuildDeviceIoControlRequest( Ioctl, hDevice, 
	                                      pInData, InDataLength,
	                                      pOutData, OutDataLength,
	                                      FALSE, pEvent, pIoStatus );
	if ( !pIrp )
		return( FALSE );

	Status = IoCallDriver( hDevice, pIrp );
	if ( Status == STATUS_PENDING )
		Status = KeWaitForSingleObject( pEvent, Executive, KernelMode, FALSE, NULL );

	if ( NT_SUCCESS(Status) )
		return( TRUE );
	else
		return( FALSE );
}


BOOL
AsyncIoRequest( HANDLE hDevice, 
                LONG Ioctl, 
                PVOID pInData, 
                ULONG InDataLength, 
                PVOID pOutData, 
                ULONG OutDataLength,
                PKEVENT pEvent,
                PIO_STATUS_BLOCK pIoStatus )
{
	BOOL bSuccess;
	PIRP pIrp;
	NTSTATUS Status;

	pIrp = IoBuildDeviceIoControlRequest( Ioctl, hDevice, 
	                                      pInData, InDataLength,
	                                      pOutData, OutDataLength,
	                                      FALSE, pEvent, pIoStatus );
	if ( !pIrp )
		return( FALSE );

	Status = IoCallDriver( hDevice, pIrp );

	if ( NT_SUCCESS(Status) )
		return( TRUE );
	else
		return( FALSE );
}

#else	// UserMode

#define dsvZeroMemory	ZeroMemory

BOOL 
dsvSyncIoRequest( IN HANDLE hDevice, 
                  IN LONG   Ioctl, 
                  IN PVOID  pInData, 
                  IN ULONG  InDataLength, 
                  IN PVOID  pOutData, 
                  IN ULONG  OutDataLength,
                  OUT PDWORD pError )
{
	BOOL bSuccess;
	DWORD dwBytes;
	OVERLAPPED Ol;

	dsvZeroMemory( &Ol, sizeof( Ol ) );
	Ol.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	dwBytes = 0;

	bSuccess = DeviceIoControl( hDevice, Ioctl, 
	                            pInData, InDataLength,
	                            pOutData, OutDataLength,
	                            &dwBytes, &Ol );
	if ( !bSuccess  && GetLastError() == ERROR_IO_PENDING )
		bSuccess = GetOverlappedResult( hDevice, &Ol, &dwBytes, TRUE );

	CloseHandle( Ol.hEvent );

	*pError = bSuccess ? 0 : GetLastError();
	return( bSuccess );
}


BOOL 
dsvAsyncIoRequest( HANDLE hDevice, 
                   LONG   Ioctl, 
                   PVOID  pInData, 
                   ULONG  InDataLength, 
                   PVOID  pOutData, 
                   ULONG  OutDataLength,
                   PDWORD pdwBytes,
                   LPOVERLAPPED pOl )
{
	BOOL bSuccess;

	bSuccess = DeviceIoControl( hDevice, Ioctl, 
	                            pInData, InDataLength,
	                            pOutData, OutDataLength,
	                            pdwBytes, pOl );

#if DBG
	if ( !bSuccess && GetLastError() != ERROR_IO_PENDING )
		DebugPrint( (  "AsyncIoRequest failed, GetLastError = 0x%08x\n", GetLastError() ) );
#endif

	return( bSuccess );
}

#endif




///////////////////////////////////////////////////////////////////////////////
//
// Helper Routines.  
//
// These routines hide the gory details of commonly performed actions, such as 
// sending an Open request.
//
// All helper, or internal, routines begin with the "dsv" prefix.
// 

_inline VOID dsvCopyString( PCHAR pDest, PCHAR pSrc, ULONG MaxLen )
{
	ULONG i;	
	for ( i = 0; i < MaxLen; i++ )
	{
		if ( !pSrc[i] )
			break;
		pDest[i] = pSrc[i];
	}
}


BOOL
dsvOpen(
	IN HANDLE hDevice,
	IN PCHAR pDeviceName,
	OUT PHANDLE phStream )
/*++

Description:

	This routine performs a synchronous open request to the named device.

Parameters:

	hDevice
		Device handle on which to send this request.

	pDeviceName
		Null-terminated string containing the devicename to open, i.e. "X250".

	phStream
		Address to which the stream handle will be written on successful completion
		of the open request..

Return Value:

	TRUE if successful, otherwise FALSE.

--*/
{
	DS_OPEN Open;
	BOOL bSuccess;
	DWORD Error;

	dsvZeroMemory( &Open, sizeof( Open ) );
	dsvCopyString( (PVOID)&Open.DeviceName, pDeviceName, DS_DEVICENAME_SIZE );

	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             &Open, sizeof( Open ),
	                             &Error );
	*phStream = Open.hStream;
	return( bSuccess && !Open.ErrorCode );
}


BOOL
dsvClose(
	IN HANDLE hDevice,
	IN HANDLE hStream )
/*++

Description:

	Performs a synchronous close request on the stream.

Parameters:

	hDevice
		Device handle on which to send this request.

	hStream
		Handle of stream to close.

Return Value:

	TRUE if successful, otherwise FALSE.

--*/
{
	DS_CLOSE Close;
	BOOL bSuccess;
	DWORD Error;
	dsvZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStream;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ),
	                             &Close, sizeof( Close ),
	                             &Error );
	return( bSuccess );
}


BOOL
dsvLink(
	IN HANDLE hDevice,
	IN HANDLE hStreamUpper,
	IN HANDLE hStreamLower )
/*++

Description:

	Performs a synchronous close request on the stream.

Parameters:

	hDevice
		Device handle on which to send this request.

	hStreamUpper
		Handle of upper stream for link.

	hStreamLower
		Handle of upper stream for link.

Return Value:

	TRUE if successful, otherwise FALSE.

--*/
{
	DS_LINK Link;
	BOOL bSuccess;
	DWORD Error;
	dsvZeroMemory( &Link, sizeof( Link ) );
	Link.hStreamUpper = hStreamUpper;
	Link.hStreamLower = hStreamLower;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ),
	                             &Error );
	if ( !bSuccess || Error || Link.MuxId == -1 || Link.ErrorCode )
		return( FALSE );
	return( TRUE );
}


_inline VOID
dsvInitOpen( PDS_OPEN pOpen )
{
	dsvZeroMemory( pOpen, sizeof( DS_OPEN ) );
	dsvCopyString( pOpen->DeviceName, DS_LOOP_DEVICE, DS_DEVICENAME_SIZE );
}


_inline VOID
dsvInitPutMsg( PDS_PUTMSG pPutMsg, 
					HANDLE     hStream,
               PVOID      pCtrl, 
               ULONG      CtrlLen, 
               PVOID      pData, 
               ULONG      DataLen )
{
	dsvZeroMemory( pPutMsg, sizeof( DS_PUTMSG ) );
	pPutMsg->hStream   = hStream;
	pPutMsg->pControl  = pCtrl;
	pPutMsg->cbControl = CtrlLen;
	pPutMsg->pData     = pData;
	pPutMsg->cbData    = DataLen;
}


_inline VOID
dsvInitGetMsg( PDS_GETMSG pGetMsg, 
					HANDLE     hStream,
               PVOID      pCtrl, 
               ULONG      CtrlLen, 
               PVOID      pData, 
               ULONG      DataLen )
{
	dsvZeroMemory( pGetMsg, sizeof( DS_GETMSG ) );
	pGetMsg->hStream      = hStream;
	pGetMsg->pControl     = pCtrl;
	pGetMsg->cbMaxControl = CtrlLen;
	pGetMsg->pData        = pData;
	pGetMsg->cbMaxData    = DataLen;
}


_inline VOID
dsvInitIoctl( PDS_IOCTL pIoctl, 
				  HANDLE    hStream,
              ULONG     Command, 
              PVOID     pData, 
              ULONG     DataLen )
{
	dsvZeroMemory( pIoctl, sizeof( DS_IOCTL ) );
	pIoctl->hStream = hStream;
	pIoctl->Command = Command;
	pIoctl->pDataIn = pIoctl->pDataOut = pData;
	pIoctl->cbDataIn = pIoctl->cbMaxDataOut = DataLen;
}


_inline VOID
dsvInitLink( PDS_LINK pLink, 
				 HANDLE   hStreamUpper,
				 HANDLE   hStreamLower )
{
	dsvZeroMemory( pLink, sizeof( DS_LINK ) );
	pLink->hStreamUpper = hStreamUpper;
	pLink->hStreamLower = hStreamLower;
}


_inline VOID
dsvInitPurge( PDS_PURGE pPurge, 
				  HANDLE hStream,
				  ULONG  Flags )
{
	dsvZeroMemory( pPurge, sizeof( DS_PURGE ) );
	pPurge->hStream = hStream;
	pPurge->Flags = Flags;
}


_inline BOOL 
dsvVerify( 
	BOOL Result, 
	BOOL ExpectedResult, 
	DWORD Error,
	PCHAR Routine )
/*++

Description:

	This routine prints verifies return values.  Prints debug messages and returns 
	FALSE when return doesn't match expected.

Parameters:

	Result
		Result of IoRequest.

	ExpectedResult
		The result needed to pass the test.

	Error
		Error returned from IoRequest.

	ExpectedError
		The error needed to pass the test.

Return Value:

	TRUE if Result and Error match the expected values,
	otherwise FALSE 

--*/
{
	// Check whether the IoRequest pass/fail was correct
	if ( Result != ExpectedResult )
	{
		if ( Result )
			DebugPrint( (  "%s test failed, request succeeded\n", Routine ) );
		else
			DebugPrint( (  "%s test failed, request failed\n", Routine ) );

		return( FALSE );
	}
	
	// If the IoRequest failed, verify that the correct error code was returned.
	if ( !Result )
		ASSERT( Error );

	return( TRUE );
}



///////////////////////////////////////////////////////////////////////////////
//
// Test Routines
//
// These routines perform the actual DStreams API tests.
// 

BOOL
DsvOpenCloseTypical(
	HANDLE hDevice )
/*++

Description:

	This routine performs typical open and close requests.  The expected response is a 
	successful open and successful close.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenCloseTypical";
	BOOL bSuccess;
	HANDLE hStream;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed\n", Routine ) );
		return( FALSE );
	}

	bSuccess = dsvClose( hDevice, hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed\n", Routine ) );
		return( FALSE );
	}

	return( TRUE );
}



BOOL
DsvOpenInBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenInBufferNull";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             NULL, sizeof( Open ),
	                             &Open, sizeof( Open ),
	                             &Error );

	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenInBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length input buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenInBufferZero";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, 0,
	                             &Open, sizeof( Open ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenInBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length input buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;
	const PCHAR Routine = "DsvOpenInBufferNone";

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             NULL, 0,
	                             &Open, sizeof( Open ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenInBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;
	const PCHAR Routine = "DsvOpenInBufferShort";

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ) / 2,
	                             &Open, sizeof( Open ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenInBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;
	const PCHAR Routine = "DsvOpenInBufferLong";

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ) * 2,
	                             &Open, sizeof( Open ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenOutBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenOutBufferNull";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             NULL, sizeof( Open ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenOutBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length output buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenOutBufferZero";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             &Open, 0,
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenOutBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length output buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenOutBufferNone";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             NULL, 0,
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenOutBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short output buffer test from the Basic Irp Handling tests

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenOutBufferShort";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             &Open, sizeof( Open ) / 2,
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenOutBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenOutBufferLong";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	dsvInitOpen( &Open );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             &Open, sizeof( Open ) * 2,
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenDeviceNameNull(
	HANDLE hDevice )
/*++

Description:

	This routine sends an Open request with no devicename.  The request is expected 
	to fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenDeviceNameNull";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;

	ZeroMemory( &Open, sizeof( Open ) );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             &Open, sizeof( Open ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenDeviceNameLong(
	HANDLE hDevice )
/*++

Description:

	This routine sends an Open request with a too-long devicename.  The request is 
	expected to fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenDeviceNameLong";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;
	ULONG i;

	ZeroMemory( &Open, sizeof( Open ) );
	for ( i = 0; i < DS_DEVICENAME_SIZE; i++ )
		Open.DeviceName[i] = 'A';

	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             &Open, sizeof( Open ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) ); 
}



BOOL
DsvOpenDeviceNameLongEx(
	HANDLE hDevice )
/*++

Description:

	This routine sends an Open request with a too-long devicename, plus the entire open
	structure is nonzero, which would cause strlen to access violate if the driver isn't
	careful.  The request is expected to fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvOpenDeviceNameLongEx";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	DS_OPEN Open;
	DWORD Error;
	ULONG i;

	ZeroMemory( &Open, sizeof( Open ) );
	for ( i = 0; i < sizeof( DS_OPEN ); i++ )
		Open.DeviceName[i] = 'A';

	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_OPEN,
	                             &Open, sizeof( Open ),
	                             &Open, sizeof( Open ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	if ( bSuccess )
	{
		bSuccess = dsvClose( hDevice, Open.hStream );
		ASSERT( bSuccess );
	}
	return( bPassed );
}



BOOL
DsvCloseInBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null input buffer test for Close.  Expected result is 
	fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseInBufferNull";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStream;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             NULL, sizeof( Close ),
	                             &Close, sizeof( Close ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bPassed );
}



BOOL
DsvCloseInBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length input buffer test for Close.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseInBufferZero";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStream;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, 0,
	                             &Close, sizeof( Close ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bPassed );
}



BOOL
DsvCloseInBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length input buffer test for Close.  
	Expected result is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseInBufferNone";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStream;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             NULL, 0,
	                             &Close, sizeof( Close ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bPassed );
}



BOOL
DsvCloseInBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short input buffer test for Close.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseInBufferShort";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStream;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ) / 2,
	                             &Close, sizeof( Close ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bPassed );
}



BOOL
DsvCloseInBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long input buffer test for Close.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseInBufferLong";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStream;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ) * 2,
	                             &Close, sizeof( Close ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	if ( !bSuccess )
	{
		bSuccess = dsvClose( hDevice, hStream );
		ASSERT( bSuccess );
	}
	return( bPassed );
}



BOOL
DsvCloseStreamNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null hStream test for Close.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseStreamNull";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = NULL;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ),
	                             &Close, sizeof( Close ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bPassed );
}



BOOL
DsvCloseStreamInvalid(
	HANDLE hDevice )
/*++

Description:

	This routine performs the invalid stream test for Close.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseStreamInvalid";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = (PVOID)0x87654320;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ),
	                             &Close, sizeof( Close ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine ); 
	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bPassed );
}



BOOL
DsvCloseAfterClose(
	HANDLE hDevice )
/*++

Description:

	This routine performs the request after close test for Close.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseAfterClose";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_CLOSE Close;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	bSuccess = dsvClose( hDevice, hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}

	// Test case: close again after a successful close
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStream;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ),
	                             &Close, sizeof( Close ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) );
}



BOOL
DsvCloseLowerLinkFirst(
	HANDLE hDevice )
/*++

Description:

	This routine performs the "close lower after link" test for Close.  Expected result 
	is pass.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvCloseLowerLinkFirst";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStreamLower;
	HANDLE hStreamUpper;
	DWORD Error;
	DS_CLOSE Close;

#ifdef HOUSTON
		DebugPrint( (  "skipped, Houston linking broken - " ) );
		return FALSE;
#else
	// Open upper stream
	bSuccess = dsvOpen( hDevice, DS_UPPER_DEVICE, &hStreamUpper );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	// Open lower stream
	bSuccess = dsvOpen( hDevice, DS_LOWER_DEVICE, &hStreamLower );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		// Cleanup
		bSuccess = dsvClose( hDevice, hStreamUpper );
		ASSERT( bSuccess );
		return( FALSE );
	}

	// Link the two streams
	bSuccess = dsvLink( hDevice, hStreamUpper, hStreamLower );

	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, link failed\n", Routine ) );
		// Cleanup
		bSuccess = dsvClose( hDevice, hStreamUpper );
		ASSERT( bSuccess );
		bSuccess = dsvClose( hDevice, hStreamLower );
		ASSERT( bSuccess );
		return( FALSE );
	}

	// Close lower stream first
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStreamLower;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ),
	                             &Close, sizeof( Close ),
	                             &Error );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, close lower failed\n", Routine ) );
		bSuccess = dsvClose( hDevice, hStreamUpper );
		ASSERT( bSuccess );
		return( FALSE );
	}

	// Then close upper stream
	ZeroMemory( &Close, sizeof( Close ) );
	Close.hStream = hStreamUpper;
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_CLOSE,
	                             &Close, sizeof( Close ),
	                             &Close, sizeof( Close ),
	                             &Error );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, close upper failed\n", Routine ) );
		return( FALSE );
	}
	return( TRUE );
#endif
}



BOOL
DsvPutMsgGetMsgTypical(
	HANDLE hDevice )
/*++

Description:

	This routine performs typical putmsg and getmsg requests.  The expected response 
	is success.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgGetMsgTypical";
	BOOL bSuccess;
	BOOL bTestPassed;
	DWORD Error;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, NULL, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, PutMsg request failed\n", Routine ) );
		bTestPassed = FALSE;
		goto Cleanup;
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, GetMsg request failed\n", Routine ) );
		bTestPassed = FALSE;
	}
	else
		bTestPassed = TRUE;

Cleanup:;

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgInBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPutMsgInBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             NULL, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgInBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length input buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPutMsgInBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, 0,
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgInBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length input buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPutMsgInBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             NULL, 0,
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgInBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPutMsgInBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ) / 2,
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgInBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPutMsgInBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ) * 2,
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgStreamNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null stream test.  The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgStreamNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, NULL, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgStreamInvalid(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null invalid stream test.  The expected result is 
	failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgStreamInvalid";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, (PVOID)0x87654320, 
	               Control, DS_DEFAULT_SIZE, 
	               Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgControlNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null control buffer, non-zero control length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgControlNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, NULL, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgControlZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null control buffer, zero control length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgControlZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgControlNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the Data only (no control portion) test.  
	The expected result is success.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgControlNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, NULL, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, TRUE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgDataNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null data buffer, non-zero data length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgDataNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, NULL, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgDataZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null data buffer, zero data length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgDataZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, Data, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgDataNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the Control only (no data portion) test.  
	The expected result is success.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgDataNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, NULL, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, TRUE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgNone(
	HANDLE hDevice )
/*++

Description:

	This routine sends a putmsg with null data buffer, zero length data, null control 
	buffer and zero control length test.  The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PUTMSG PutMsg;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPutMsg( &PutMsg, hStream, NULL, 0, NULL, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPutMsgAfterClose(
	HANDLE hDevice )
/*++

Description:

	This routine performs the request after close test.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPutMsgAfterClose";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	HANDLE hStream;
	DWORD Error;
	DS_PUTMSG PutMsg;;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	bSuccess = dsvClose( hDevice, hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}

	// Test case: after a successful close
	dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG,
	                             &PutMsg, sizeof( PutMsg ),
	                             &PutMsg, sizeof( PutMsg ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) );
}



BOOL
DsvGetMsgInBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvGetMsgInBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             NULL, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgInBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length input buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvGetMsgInBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, 0,
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgInBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length input buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvGetMsgInBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             NULL, 0,
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgInBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvGetMsgInBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ) / 2,
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgInBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvGetMsgInBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ) * 2,
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgOutBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgOutBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             NULL, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgOutBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length output buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgOutBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, 0, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgOutBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length output buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgOutBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             NULL, 0,
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgOutBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short output buffer test from the Basic Irp Handling tests

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgOutBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ) / 2, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgOutBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgOutBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ) * 2, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgStreamNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null stream test.  The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgStreamNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, NULL, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgStreamInvalid(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null invalid stream test.  The expected result is 
	failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgStreamInvalid";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, (PVOID)0x87654320, 
	               Control, DS_DEFAULT_SIZE, 
	               Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgControlNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null control buffer, non-zero control length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgControlNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, NULL, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgControlZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null control buffer, zero control length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgControlZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgControlNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the data only (no control portion) test.  
	The expected result is success.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgControlNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	{
		DS_PUTMSG PutMsg;
		dsvInitPutMsg( &PutMsg, hStream, NULL, 0, Data, DS_DEFAULT_SIZE );
		bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG, &PutMsg, sizeof( PutMsg ), &PutMsg, sizeof( PutMsg ), &Error );
		if ( !bSuccess )
		{
			DebugPrint( (  "%s failed, PutMsg failed\n", Routine ) );
			return( FALSE );
		}
	}

	dsvInitGetMsg( &GetMsg, hStream, NULL, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, TRUE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgDataNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null data buffer, non-zero data length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgDataNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, NULL, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgDataZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null data buffer, zero data length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgDataZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgDataNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the Control Only (no data portion) test.  
	The expected result is success.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgDataNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return FALSE;
	}

	{
		DS_PUTMSG PutMsg;
		dsvInitPutMsg( &PutMsg, hStream, Control, DS_DEFAULT_SIZE, NULL, 0 );
		bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PUTMSG, &PutMsg, sizeof( PutMsg ), &PutMsg, sizeof( PutMsg ), &Error );
		if ( !bSuccess )
		{
			DebugPrint( (  "%s failed, PutMsg failed\n", Routine ) );
			return( FALSE );
		}
	}

#ifdef HOUSTON
	DebugPrint( (  "skipped, Houston iwanloop doesn't like this! - " ) );
	return FALSE;
#else
	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, NULL, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, TRUE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
#endif
}



BOOL
DsvGetMsgNone(
	HANDLE hDevice )
/*++

Description:

	This routine sends a GetMsg with null, zero-length control and data buffers.
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, NULL, 0, NULL, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvGetMsgAfterClose(
	HANDLE hDevice )
/*++

Description:

	This routine performs the request after the stream is already closed test.  The 
	expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvGetMsgAfterClose";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_GETMSG GetMsg;
	CHAR Control[DS_DEFAULT_SIZE];
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	bSuccess = dsvClose( hDevice, hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, close failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitGetMsg( &GetMsg, hStream, Control, DS_DEFAULT_SIZE, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_GETMSG,
	                             &GetMsg, sizeof( GetMsg ),
	                             &GetMsg, sizeof( GetMsg ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );
	return( bTestPassed );
}



BOOL
DsvIoctlInBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvIoctlInBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             NULL, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlInBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length input buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvIoctlInBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, 0,
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlInBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length input buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvIoctlInBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             NULL, 0,
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlInBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvIoctlInBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ) / 2,
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlInBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvIoctlInBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ) * 2,
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlOutBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlOutBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             NULL, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlOutBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length output buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlOutBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, 0, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlOutBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length output buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlOutBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             NULL, 0,
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlOutBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short output buffer test from the Basic Irp Handling tests

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlOutBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ) / 2, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlOutBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlOutBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ) * 2, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlStreamNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null stream test.  The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlStreamNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, NULL, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlStreamInvalid(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null invalid stream test.  The expected result is 
	failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlStreamInvalid";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, (PVOID)0x87654320, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlDataNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null data buffer, non-zero data length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlDataNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, NULL, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlDataZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero data length test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlDataZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlDataNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null data buffer, zero data length test.  
	The expected result is success.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlDataNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, NULL, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, TRUE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlCommandInvalid(
	HANDLE hDevice )
/*++

Description:

	This routine performs the invalid command test.  
	The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlCommandInvalid";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_IOCTL Ioctl;
	CHAR Data[DS_DEFAULT_SIZE];
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, TRUE, Error, Routine );
	if( bTestPassed )
	{
		if ( !Ioctl.ErrorCode && !Ioctl.ReturnValue )
		{
			DebugPrint( (  "%s failed, ioctl returned success\n", Routine ) );
			bTestPassed = FALSE;
		}
	}

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvIoctlAfterClose(
	HANDLE hDevice )
/*++

Description:

	This routine performs the request after close test.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvIoctlAfterClose";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	CHAR Data[DS_DEFAULT_SIZE];
	HANDLE hStream;
	DWORD Error;
	DS_IOCTL Ioctl;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	bSuccess = dsvClose( hDevice, hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}

	// Test case: ioctl after a successful close
	dsvInitIoctl( &Ioctl, hStream, 0, Data, DS_DEFAULT_SIZE );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_IOCTL,
	                             &Ioctl, sizeof( Ioctl ),
	                             &Ioctl, sizeof( Ioctl ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) );
}



BOOL
DsvLinkInBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvLinkInBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             NULL, sizeof( Link ),
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkInBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length input buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvLinkInBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, 0,
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkInBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length input buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvLinkInBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             NULL, 0,
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkInBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvLinkInBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ) / 2,
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkInBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvLinkInBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ) * 2,
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkOutBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkOutBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             NULL, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkOutBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length output buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkOutBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, 0, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkOutBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length output buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkOutBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             NULL, 0,
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkOutBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short output buffer test from the Basic Irp Handling tests

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkOutBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ) / 2, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkOutBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long output buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkOutBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ) * 2, 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkStreamUpperNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null stream test.  The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkStreamUpperNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStreamUpper;
	HANDLE hStreamLower;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_UPPER_DEVICE, &hStreamUpper );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open %s failed\n", Routine, DS_UPPER_DEVICE ) );
		return( FALSE );
	}

	bSuccess = dsvOpen( hDevice, DS_LOWER_DEVICE, &hStreamLower );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open %s failed\n", Routine, DS_LOWER_DEVICE ) );
		bSuccess = dsvClose( hDevice, hStreamUpper );
		ASSERT( bSuccess );
		return( FALSE );
	}

	dsvInitLink( &Link, NULL, hStreamLower );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStreamLower );
	ASSERT( bSuccess );
	bSuccess = dsvClose( hDevice, hStreamUpper );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkStreamLowerNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null stream test.  The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkStreamLowerNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStreamUpper;
	HANDLE hStreamLower;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_UPPER_DEVICE, &hStreamUpper );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	bSuccess = dsvOpen( hDevice, DS_LOWER_DEVICE, &hStreamLower );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		bSuccess = dsvClose( hDevice, hStreamUpper );
		ASSERT( bSuccess );
		return( FALSE );
	}

	dsvInitLink( &Link, hStreamUpper, NULL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStreamLower );
	ASSERT( bSuccess );
	bSuccess = dsvClose( hDevice, hStreamUpper );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkStreamInvalid(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null invalid stream test.  The expected result is 
	failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkStreamInvalid";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_LINK Link;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitLink( &Link, hStream, (PVOID)0x87654320 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvLinkAfterCloseLower(
	HANDLE hDevice )
/*++

Description:

	This routine performs the request after close test.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkAfterCloseLower";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStreamUpper;
	HANDLE hStreamLower;
	DWORD Error;
	DS_LINK Link;

	bSuccess = dsvOpen( hDevice, DS_UPPER_DEVICE, &hStreamUpper );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	bSuccess = dsvOpen( hDevice, DS_LOWER_DEVICE, &hStreamLower );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	bSuccess = dsvClose( hDevice, hStreamLower );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, close failed\n", Routine ) );
		bSuccess = dsvClose( hDevice, hStreamUpper );
		ASSERT( bSuccess );
		return( FALSE );
	}

	// Test case: Link after a successful close
	dsvInitLink( &Link, hStreamUpper, hStreamLower );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ),
	                             &Error );

	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine );
	bSuccess = dsvClose( hDevice, hStreamUpper );
	return( bPassed );
}



BOOL
DsvLinkAfterCloseUpper(
	HANDLE hDevice )
/*++

Description:

	This routine performs the request after close test.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLinkAfterCloseUpper";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStreamUpper;
	HANDLE hStreamLower;
	DWORD Error;
	DS_LINK Link;

	bSuccess = dsvOpen( hDevice, DS_UPPER_DEVICE, &hStreamUpper );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	bSuccess = dsvOpen( hDevice, DS_LOWER_DEVICE, &hStreamLower );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	
	bSuccess = dsvClose( hDevice, hStreamUpper );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, close failed\n", Routine ) );
		bSuccess = dsvClose( hDevice, hStreamLower );
		ASSERT( bSuccess );
		return( FALSE );
	}

	// Test case: Link after a successful close
	dsvInitLink( &Link, hStreamUpper, hStreamLower );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_LINK,
	                             &Link, sizeof( Link ),
	                             &Link, sizeof( Link ),
	                             &Error );
	bPassed = dsvVerify( bSuccess, FALSE, Error, Routine );
	bSuccess = dsvClose( hDevice, hStreamUpper );
	return( bPassed );
}



BOOL
DsvPurgeInBufferNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPurgeInBufferNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, hStream, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             NULL, sizeof( Purge ),
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPurgeInBufferZero(
	HANDLE hDevice )
/*++

Description:

	This routine performs the zero length input buffer test from the Basic Irp 
	Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPurgeInBufferZero";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, hStream, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             &Purge, 0,
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPurgeInBufferNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null buffer, zero length input buffer test from the 
	Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPurgeInBufferNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, hStream, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             NULL, 0,
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPurgeInBufferShort(
	HANDLE hDevice )
/*++

Description:

	This routine performs the short input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPurgeInBufferShort";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, hStream, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             &Purge, sizeof( Purge ) / 2,
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPurgeInBufferLong(
	HANDLE hDevice )
/*++

Description:

	This routine performs the long input buffer test from the Basic Irp Handling tests.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "dsvPurgeInBufferLong";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, hStream, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             &Purge, sizeof( Purge ) * 2,
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPurgeStreamNull(
	HANDLE hDevice )
/*++

Description:

	This routine performs the null stream test.  The expected result is failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPurgeStreamNull";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, NULL, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             &Purge, sizeof( Purge ),
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPurgeStreamInvalid(
	HANDLE hDevice )
/*++

Description:

	This routine performs the non-null invalid stream test.  The expected result is 
	failure.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPurgeStreamInvalid";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, (PVOID)0x87654320, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             &Purge, sizeof( Purge ),
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, FALSE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}



BOOL
DsvPurgeAfterClose(
	HANDLE hDevice )
/*++

Description:

	This routine performs the request after close test.  Expected result 
	is fail.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPurgeAfterClose";
	BOOL bSuccess;
	BOOL bPassed = TRUE;
	HANDLE hStream;
	DWORD Error;
	DS_PURGE Purge;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}

	bSuccess = dsvClose( hDevice, hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, close failed\n", Routine ) );
		return( FALSE );
	}

	// Test case: Purge after a successful close
	dsvInitPurge( &Purge, hStream, DS_PURGE_ALL );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             &Purge, sizeof( Purge ),
	                             &Purge, sizeof( Purge ),
	                             &Error );
	return( dsvVerify( bSuccess, FALSE, Error, Routine ) );
}



BOOL
DsvPurgeFlagsNone(
	HANDLE hDevice )
/*++

Description:

	This routine performs purge with flags set to none test.  The expected result is 
	success.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvPurgeFlagsNone";
	BOOL bSuccess;
	BOOL bTestPassed;
	HANDLE hStream;
	DS_PURGE Purge;
	DWORD Error;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s failed, open failed\n", Routine ) );
		return( FALSE );
	}

	dsvInitPurge( &Purge, hStream, 0 );
	bSuccess = dsvSyncIoRequest( hDevice, IOCTL_DS_PURGE,
	                             &Purge, sizeof( Purge ),
	                             &Purge, sizeof( Purge ), 
	                             &Error );
	bTestPassed = dsvVerify( bSuccess, TRUE, Error, Routine );

	bSuccess = dsvClose( hDevice, hStream );
	ASSERT( bSuccess );
	return( bTestPassed );
}


BOOL
DsvLeaveStreamOpen(
	HANDLE hDevice )
/*++

Description:

	This routine performs opens a stream, leaving it open s.t. IRP_MJ_DISPATCH routine
	must close it.

Parameters:

	hDevice
		Handle returned from CreateFile.  The request is sent to this device.

Return Value:

	TRUE if successful,
	otherwise FALSE 

--*/
{
	const PCHAR Routine = "DsvLeaveStreamOpen";
	BOOL bSuccess;
	HANDLE hStream;

	bSuccess = dsvOpen( hDevice, DS_LOOP_DEVICE, &hStream );
	if ( !bSuccess )
	{
		DebugPrint( (  "%s test failed, open failed\n", Routine ) );
		return( FALSE );
	}
	return( TRUE );
}



///////////////////////////////////////////////////////////////////////////////
//
// Main
//
// Run all the tests
// 

typedef struct VERIFY_ENTRY
{
	PVERIFY_ROUTINE Test;
	PUCHAR Name;
} VERIFY_ENTRY, *PVERIFY_ENTRY;

VERIFY_ENTRY Routines[] =
{	
	{ DsvOpenCloseTypical,		"DsvOpenCloseTypical" },
	{ DsvOpenInBufferNull,		"DsvOpenInBufferNull" },
	{ DsvOpenInBufferZero,		"DsvOpenInBufferZero" },
	{ DsvOpenInBufferNone,		"DsvOpenInBufferNone" },
	{ DsvOpenInBufferShort,		"DsvOpenInBufferShort" },
	{ DsvOpenInBufferLong,		"DsvOpenInBufferLong" },
	{ DsvOpenOutBufferNull,		"DsvOpenOutBufferNull" },
	{ DsvOpenOutBufferZero,		"DsvOpenOutBufferZero" },
	{ DsvOpenOutBufferNone,		"DsvOpenOutBufferNone" },
	{ DsvOpenOutBufferShort,	"DsvOpenOutBufferShort" },
	{ DsvOpenOutBufferLong,		"DsvOpenOutBufferLong" },
	{ DsvOpenDeviceNameNull,	"DsvOpenDeviceNameNull" },
	{ DsvOpenDeviceNameLong,	"DsvOpenDeviceNameLong" },
	{ DsvOpenDeviceNameLongEx,	"DsvOpenDeviceNameLongEx" },
	{ DsvCloseInBufferNull,		"DsvCloseInBufferNull" },
	{ DsvCloseInBufferZero,		"DsvCloseInBufferZero" },
	{ DsvCloseInBufferNone,		"DsvCloseInBufferNone" },
	{ DsvCloseInBufferShort,	"DsvCloseInBufferShort" },
	{ DsvCloseInBufferLong,		"DsvCloseInBufferLong" },
	{ DsvCloseStreamNull,		"DsvCloseStreamNull" },
	{ DsvCloseStreamInvalid,	"DsvCloseStreamInvalid" },
	{ DsvCloseAfterClose,		"DsvCloseAfterClose" },
	{ DsvCloseLowerLinkFirst,	"DsvCloseLowerLinkFirst" },
	{ DsvPutMsgGetMsgTypical,	"DsvPutMsgGetMsgTypical" },
	{ DsvPutMsgInBufferNull,	"DsvPutMsgInBufferNull" },
	{ DsvPutMsgInBufferZero,	"DsvPutMsgInBufferZero" },
	{ DsvPutMsgInBufferNone,	"DsvPutMsgInBufferNone" },
	{ DsvPutMsgInBufferShort,	"DsvPutMsgInBufferShort" },
	{ DsvPutMsgInBufferLong,	"DsvPutMsgInBufferLong" },
	{ DsvPutMsgStreamNull,		"DsvPutMsgStreamNull" },
	{ DsvPutMsgStreamInvalid,	"DsvPutMsgStreamInvalid" },
	{ DsvPutMsgControlNull,		"DsvPutMsgControlNull" },
	{ DsvPutMsgControlZero,		"DsvPutMsgControlZero" },
	{ DsvPutMsgControlNone,		"DsvPutMsgControlNone" },
	{ DsvPutMsgDataNull,			"DsvPutMsgDataNull" },
	{ DsvPutMsgDataZero,			"DsvPutMsgDataZero" },
	{ DsvPutMsgDataNone,			"DsvPutMsgDataNone" },
	{ DsvPutMsgNone,				"DsvPutMsgNone" },
	{ DsvPutMsgAfterClose,		"DsvPutMsgAfterClose" },
	{ DsvGetMsgInBufferNull,	"DsvGetMsgInBufferNull" },
	{ DsvGetMsgInBufferZero,	"DsvGetMsgInBufferZero" },
	{ DsvGetMsgInBufferNone,	"DsvGetMsgInBufferNone" },
	{ DsvGetMsgInBufferShort,	"DsvGetMsgInBufferShort" },
	{ DsvGetMsgInBufferLong,	"DsvGetMsgInBufferLong" },
	{ DsvGetMsgOutBufferNull,	"DsvGetMsgOutBufferNull" },
	{ DsvGetMsgOutBufferZero,	"DsvGetMsgOutBufferZero" },
	{ DsvGetMsgOutBufferNone,	"DsvGetMsgOutBufferNone" },
	{ DsvGetMsgOutBufferShort,	"DsvGetMsgOutBufferShort" },
	{ DsvGetMsgOutBufferLong,	"DsvGetMsgOutBufferLong" },
	{ DsvGetMsgStreamNull,		"DsvGetMsgStreamNull" },
	{ DsvGetMsgStreamInvalid,	"DsvGetMsgStreamInvalid" },
	{ DsvGetMsgControlNull,		"DsvGetMsgControlNull" },
	{ DsvGetMsgControlZero,		"DsvGetMsgControlZero" },
	{ DsvGetMsgControlNone,		"DsvGetMsgControlNone" },
	{ DsvGetMsgDataNull,			"DsvGetMsgDataNull" },
	{ DsvGetMsgDataZero,			"DsvGetMsgDataZero" },
	{ DsvGetMsgDataNone,			"DsvGetMsgDataNone" },
	{ DsvGetMsgNone,				"DsvGetMsgNone" },
	{ DsvGetMsgAfterClose,		"DsvGetMsgAfterClose" },
	{ DsvIoctlInBufferNull,		"DsvIoctlInBufferNull" },
	{ DsvIoctlInBufferZero,		"DsvIoctlInBufferZero" },
	{ DsvIoctlInBufferNone,		"DsvIoctlInBufferNone" },
	{ DsvIoctlInBufferShort,	"DsvIoctlInBufferShort" },
	{ DsvIoctlInBufferLong,		"DsvIoctlInBufferLong" },
	{ DsvIoctlOutBufferNull,	"DsvIoctlOutBufferNull" },
	{ DsvIoctlOutBufferZero,	"DsvIoctlOutBufferZero" },
	{ DsvIoctlOutBufferNone,	"DsvIoctlOutBufferNone" },
	{ DsvIoctlOutBufferShort,	"DsvIoctlOutBufferShort" },
	{ DsvIoctlOutBufferLong,	"DsvIoctlOutBufferLong" },
	{ DsvIoctlStreamNull,		"DsvIoctlStreamNull" },
	{ DsvIoctlStreamInvalid,	"DsvIoctlStreamInvalid" },
	{ DsvIoctlDataNull,			"DsvIoctlDataNull" },
	{ DsvIoctlDataZero,			"DsvIoctlDataZero" },
	{ DsvIoctlDataNone,			"DsvIoctlDataNone" },
	{ DsvIoctlCommandInvalid,	"DsvIoctlCommandInvalid" },
	{ DsvIoctlAfterClose,		"DsvIoctlAfterClose" },
	{ DsvLinkInBufferNull,		"DsvLinkInBufferNull" },
	{ DsvLinkInBufferZero,		"DsvLinkInBufferZero" },
	{ DsvLinkInBufferNone,		"DsvLinkInBufferNone" },
	{ DsvLinkInBufferShort,		"DsvLinkInBufferShort" },
	{ DsvLinkInBufferLong,		"DsvLinkInBufferLong" },
	{ DsvLinkOutBufferNull,		"DsvLinkOutBufferNull" },
	{ DsvLinkOutBufferZero,		"DsvLinkOutBufferZero" },
	{ DsvLinkOutBufferNone,		"DsvLinkOutBufferNone" },
	{ DsvLinkOutBufferShort,	"DsvLinkOutBufferShort" },
	{ DsvLinkOutBufferLong,		"DsvLinkOutBufferLong" },
	{ DsvLinkStreamUpperNull,	"DsvLinkStreamUpperNull" },
	{ DsvLinkStreamLowerNull,	"DsvLinkStreamLowerNull" },
	{ DsvLinkStreamInvalid,		"DsvLinkStreamInvalid" },
	{ DsvLinkAfterCloseLower,	"DsvLinkAfterCloseLower" },
	{ DsvLinkAfterCloseUpper,	"DsvLinkAfterCloseUpper" },
	{ DsvPurgeInBufferNull,		"DsvPurgeInBufferNull" },
	{ DsvPurgeInBufferZero,		"DsvPurgeInBufferZero" },
	{ DsvPurgeInBufferNone,		"DsvPurgeInBufferNone" },
	{ DsvPurgeInBufferShort,	"DsvPurgeInBufferShort" },
	{ DsvPurgeInBufferLong,		"DsvPurgeInBufferLong" },
	{ DsvPurgeStreamNull,		"DsvPurgeStreamNull" },
	{ DsvPurgeStreamInvalid,	"DsvPurgeStreamInvalid" },
	{ DsvPurgeAfterClose,		"DsvPurgeAfterClose" },
	{ DsvPurgeFlagsNone,			"DsvPurgeFlagsNone" },
	{ DsvLeaveStreamOpen,		"DsvLeaveStreamOpen" }
};


#define DSV_LOGFILE  "DsVerify.log"
_inline VOID
dsvLog( HANDLE hFile, PCHAR pString )
{
	DWORD Bytes;
	printf( pString );
	WriteFile( hFile, pString, strlen( pString ), &Bytes, NULL );
}

CHAR LogBuffer[1024];



void __cdecl 
main( int argc, char *argv[] )
{
	ULONG i;
	HANDLE hLogFile, hDevice;
	BOOL bSuccess;
	CHAR FullDeviceName[64];

	if ( argc != 2 )
	{
		printf( "Usage:\n\n"
		        "  DsVerify <device>\n\n"
		        "where <device> is a DStreams devicename, i.e. digisxb2\n"
		        "Output is written to %s\n", DSV_LOGFILE );
		return;
	}

	hLogFile = CreateFile( DSV_LOGFILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
	                       CREATE_ALWAYS, 
	                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL );
	if ( hLogFile == INVALID_HANDLE_VALUE )
	{
		printf( "Couldn't open log file!\n" );
		return;
	}

	// Open the NT device
	strcpy( FullDeviceName, "\\\\.\\" );
	strcat( FullDeviceName, argv[1] );	// argv[0] is the exe, argv[1] is devicename

	sprintf( LogBuffer, "Opening device %s\n", FullDeviceName );
	dsvLog( hLogFile, LogBuffer );

	hDevice = CreateFile( FullDeviceName, GENERIC_READ | GENERIC_WRITE,  
	                      FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 
	                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );

	if ( hDevice == INVALID_HANDLE_VALUE )
	{
		sprintf( LogBuffer, "CreateFile failed!\n" );
		dsvLog( hLogFile, LogBuffer );
		CloseHandle( hLogFile );
		return;
	}

	sprintf( LogBuffer, "Beginning Tests:\n" );
	dsvLog( hLogFile, LogBuffer );

	for ( i = 0; i < sizeof( Routines ) / sizeof( VERIFY_ENTRY ); i++ )
	{
		sprintf( LogBuffer, "Test %d (%s)...", i, Routines[i].Name );
		dsvLog( hLogFile, LogBuffer );

		bSuccess = Routines[i].Test( hDevice );

		sprintf( LogBuffer, "%s\n", bSuccess ? "passed" : "failed" );
		dsvLog( hLogFile, LogBuffer );
	}
	sprintf( LogBuffer, "Done\n" );
	dsvLog( hLogFile, LogBuffer );
	CloseHandle( hLogFile );
	CloseHandle( hDevice );
	return;
}

