/*static char *SCCSID = "@(#)fs_ioctl.c	6.2 91/01/14";*/
#define SCCSID "@(#)fs_ioctl.c	6.2 91/01/14"
/*
 *	IBM/Microsoft Confidential
 *
 *	Copyright (c) IBM Corporation 1987, 1989
 *	Copyright (c) Microsoft Corporation 1987, 1989
 *
 *	All Rights Reserved
 *
 */

/***    FS_IOCTL - I/O Control for Devices
 *
 *  DESCRIPTION
 *
 *      The FSD passes all device operations directly on to the device
 *      driver.
 *
 *
 *  ENTRY
 *      psffsi  = Pointer to filesystem independent portion of
 *                  open file instance.  This has the handle to the
 *                  VPB that we need to get the handle to the driver.
 *      psffsd  = Pointer to filesystem-dependent portion of
 *                  open file instance.  Not used here.
 *      cat     = IOCtl category to be passed to driver
 *      func    = IOCtl function to be passed to driver
 *      pParm   = Address of application input parameter area.
 *                  Not validated by kernel.
 *                  A NULL value indicates the parameter is not
 *                  specified for this function.
 *      LenParm = Byte length of pParm.  If this is 0 and pParm
 *                  is not NULL, it means that the length of pParm
 *                  is not known due to the reqeust being submitted
 *                  via an old IOCTL or DosDevIOCtl interface.
 *      pParmLenInOut = On input, this is the length of parameter data
 *                      in the buffer.  On output, this is the length of
 *                      data returned in the buffer.
 *      pData   = Address of application output data area.
 *                  Not validated by kernel.
 *                  A NULL value indicates the parameter is not
 *                  specified for this function.
 *      LenData = Byte length of pData.  If this is 0 and pData
 *                  is not NULL, it means that the length of pData
 *                  is not known due to the reqeust being submitted
 *                  via an old IOCTL or DosDevIOCtl interface.
 *      pDataLenInOut = On input, this is the length of the data
 *                      in the buffer.  On output, this is the length of
 *                      data returned in the buffer.
 *
 *
 *  EXIT
 *      NO_ERROR if requested function was performed.
 *
 *      Whatever error/success code is returned by FSH_GETVOLPARM,
 *      FSH_DEVIOCTL, FSH_DOVOLIO2, or the driver.
 *
 *
 *  REVISION HISTORY (in reverse chronological order)
 *  --------------------------------------------------------------------------
 *  8/23/89     Paul Bingman    First working version
 *  8/4/89      Brian Andrew    Initial Blank Template
 *
 *
 * TO DO
 * --------------------------------------------------------------------------
 * Add code to check for initialization.
 *
 * What is PUBLIC_BUILD_FUTURE (a Pinball-ism)?
 *
 */


#define INCL_DOSERRORS
#define INCL_NOPMAPI
#include <os2.h>
#include <fsd.h>
#include <fsh.h>

#include "cdfs.h"
#include "sem.h"
#include "path.h"
#include "vol.h"
#include "buffer.h"
#include "mem.h"
#include "heap.h"
#include "message.h"

#ifdef STATS_H
#include "stats.h"
#endif

#include "fsdata.h"
#include "pr_memin.h"
#include "file.h"


#ifdef DEBUG
#include "pr_DEBUG.h"
#endif


int far pascal
FS_IOCTL (  PSFFSI      psffsi,
			PSFFSD      psffsd,
			USHORT      cat,
			USHORT      func,
			PCHAR       pParm,
			USHORT      lenParm,
			PUSHORT     pParmLenInOut,
			PCHAR       pData,
			USHORT      lenData,
			PUSHORT     pDataLenInOut)
{
	PVPFSI      pVPBfsi;        /* to get handle to driver  */
	PVPFSD      pVPBfsd;        /* not used; needed for FSH_GETVOLPARM */
	USHORT      usRet;          /* return code holder */

#ifdef DEBUG
	dprintf ("FS_IOCTL(cat=%x, func=%x)\n",
				cat, func);
#endif

#ifdef STATS_H
	CurSt.st_ioctl++;
#endif

	/* Check for initialization */
	if (usRet = CHECK_INIT)
		return usRet;

	/*
	 * get volume parameters
	 */

	usRet = FSH_GETVOLPARM (psffsi->sfi_hVPB, &pVPBfsi, &pVPBfsd);

	/*
	 * Pass the IOCTL on to the driver.
	 *
	 * Here is where you would want to add a filter
	 * for IOCTL calls you wanted to trap or handle yourself
	 * or modify in some way.
	 */

	if (!usRet)
	{
#ifdef PUBLIC_BUILD_FUTURE
		usRet = FSH_DEVIOCTL (FALSE,
							  pVPBfsi->vpi_hDEV,
							  psffsi->sfi_selfsfn,
							  cat,
							  func,
							  pParm,
							  lenParm,
							  pData,
							  lenData);
#else
		usRet = FSH_DOVOLIO2 (pVPBfsi->vpi_hDEV,
							  psffsi->sfi_selfsfn,
							  cat,
							  func,
							  pParm,
							  lenParm,
							  pData,
							  lenData);
#endif
	}

	/* Set output lengths as best we can. */
	if (pDataLenInOut != NULL) {
	   *pDataLenInOut = lenData;
    }

	if (pParmLenInOut != NULL) {
	   *pParmLenInOut = lenParm;
    }
	return (usRet);

	/* no warnings */
	psffsd;pParmLenInOut;pDataLenInOut;
}

/* end FS_IOCTL */
