/*static char *SCCSID = "@(#)lockeas.c	6.3 92/02/19";*/
#define BSWAP0 BSWAP0

#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>

#include <fsd.h>
#include <fsh.h>
#include "const.h"
#include "chain.h"
#include "misc.h"
#include "buf.h"
#include "dir.h"
#include "volume.h"
#include "frame.h"
#include "storage.h"
#include "fnode.h"
#include "tables.h"
#include "lw.h"
#include "fsdata.h"
#include "pbmacros.h"
#include "ea.h"
#include "heap.h"
#include "pr_misc.h"
#include "pr_ea.h"
#include "pr_debug.h"
#include "pr_heap.h"


#define VM_LOCK_HAND_SIZE 12

/*
 *	HISTORY
 *	    19-Sep-89 by JR (John Rogers, JohnRo@Microsoft)
 *		- Avoid warnings from Microsoft C 5.2 (on slash-slash comments).
 */

USHORT far
LockEAs (peaop, flag, plhFEA, plhGEA, ppFEA, ppGEA, fVMLock, pfrm)
PEAOP peaop;
USHORT flag;
LHANDLE far * plhFEA;		/* ptr to lock handle */
LHANDLE far * plhGEA;		/* ptr to lock handle */
PFEALIST far *ppFEA;
PGEALIST far *ppGEA;
BOOL fVMLock;
PFRAME	      pfrm;
{
	PGEALIST pGEAList;
	PFEALIST pFEAList;
	USHORT us;
	USHORT usOp;
	USHORT usDump;

 if (fVMLock) {

	*plhGEA = *plhFEA = NULL;

	/*
	 * Probe the eaop struct, fsh_probebuf will catch it if the pointer
	 * is null so no need to check manually
	 */
	MAYBLOCK (us = FSH_PROBEBUF (PB_OPREAD, (PBYTE) peaop, sizeof (EAOP)))
	if (us != NO_ERROR) {
		return (us);
	}

	/*
	 * buffer is okay, save the pointers to avoid further probes
	 * on eaop.
	 */
	pFEAList = peaop->fpFEAList;
	pGEAList = peaop->fpGEAList;

	/* probe fea segment */
	if (flag & LEAS_SET) {
	    usOp = PB_OPREAD;
	} else {
	    usOp = PB_OPWRITE;
	}

	/*
	 * Get the selector, then probe.  Check the lock handle after
	 * we probe since we need to have fsh_probebuf cause a gpfault if
	 * the pointer is bad (rather than return gracefully with an error
	 * code
	 */

	if( (*plhFEA = GHS(VM_LOCK_HAND_SIZE,pfrm)) == NULL )
	    return ERROR_NOT_ENOUGH_MEMORY;

	/* note!  Must probe for read for at least the cbList field */
	MAYBLOCK (us = FSH_PROBEBUF (usOp,
				     (PBYTE) pFEAList,
				     sizeof (pFEAList->cbList)))
	if( us != NO_ERROR ) {
	    goto ErrorFreeLH;
	}

	MAYBLOCK ( us = VMLock( 0L,
			   (PBYTE)pFEAList,
			   pFEAList->cbList,
			   (PVOID)-1L,
			   *plhFEA,
			   &usDump ) )

	if (us != NO_ERROR) {
	    goto ErrorFreeLH;
	}

	if( usOp == PB_OPWRITE ) {
	    /*
	     * If they give us a huge FEA buffer to GetEAs into,
	     * just treat it as 64K
	     */
	    if( pFEAList->cbList > (ULONG)CB_MAX_EALIST ) {
		pFEAList->cbList = (ULONG)CB_MAX_EALIST;
	    }
	}

	MAYBLOCK (us = FSH_PROBEBUF (usOp,
				     (PBYTE) pFEAList,
				     (USHORT) pFEAList->cbList))

	if (us != NO_ERROR) {
		goto ErrorUnlockFEA;
	}

#ifdef DEBUG
	/*dprintf ("LockEAs: locked FEA, *plhFEA=%lx\n", *plhFEA);*/
#endif

	if (flag & LEAS_LOCKGEAS) {

		if( (*plhGEA = GHS(VM_LOCK_HAND_SIZE,pfrm)) == NULL ) {
		    us = ERROR_NOT_ENOUGH_MEMORY;
		    goto ErrorUnlockFEA;
		}

		/* probe fea segment */
		MAYBLOCK (us = FSH_PROBEBUF (PB_OPREAD,
					     (PBYTE) pGEAList,
					     sizeof (pGEAList->cbList)))

		if (us != NO_ERROR) {
			goto ErrorUnlockFEA;
		}

		/* lock the segment, probe, then check the lock handle */
		MAYBLOCK ( us = VMLock( 0L,
				   (PBYTE)pGEAList,
				   pGEAList->cbList,
				   (PVOID)-1L,
				   *plhGEA,
				   &usDump) )

		if (us != NO_ERROR) {
		    goto ErrorUnlockFEA;
		}


		/*
		 * Make sure user didn't give us a big buffer
		 */
		if( pGEAList->cbList > (ULONG)CB_MAX_EALIST ) {
		    us = ERROR_INVALID_PARAMETER;
		    goto ErrorUnlockBoth;
		}

		MAYBLOCK (
			us = FSH_PROBEBUF (PB_OPREAD,
					   (PBYTE) pGEAList,
					   (USHORT)pGEAList->cbList)
		)

		if (us != NO_ERROR) {
			goto ErrorUnlockBoth;
		}
#ifdef DEBUG
		/*dprintf ("LockEAs: locked GEA, *plhGEA=%lx\n", *plhGEA);*/
#endif
	}

	/* return the pointers to the caller and then return no error */
	*ppFEA = pFEAList;
	*ppGEA = pGEAList;

 }  else {
	/*
	 * buffer is okay, save the pointers to avoid further probes
	 * on eaop.
	 */
	*ppFEA = peaop->fpFEAList;
	*ppGEA = peaop->fpGEAList;
 }
	return (NO_ERROR);

ErrorUnlockBoth:
	if( *plhGEA != NULL )
	    MAYBLOCK ( VMUnlock (*plhGEA))

ErrorUnlockFEA:
	if( *plhFEA != NULL )
	    MAYBLOCK (VMUnlock (*plhFEA))

ErrorFreeLH:
	if( *plhGEA != NULL )
	    RetHeap(*plhGEA );

	if( *plhFEA != NULL )
	    RetHeap(*plhFEA );

	return (us);
}

USHORT far
LockFindEAs (peaop, cbList, plhList, plhGEA, pfrm)
PEAOP		peaop;		  /* beginning of list (eaop) */
USHORT		cbList;		  /* size of list which contains eaop */
LHANDLE far *	plhList;	  /* ptr to lock handle */
LHANDLE far *	plhGEA;		  /* ptr to lock handle */
PFRAME		pfrm;
{
	PGEALIST pGEAList;
	USHORT us;
	USHORT usDump;

	*plhList = *plhGEA = NULL;

	/*
	 * Get the selector, then probe.  Check the lock handle after
	 * we probe since we need to have fsh_probebuf cause a gpfault if
	 * the pointer is bad (rather than return gracefully with an error
	 * code
	 */
	if( (*plhList = GHS(VM_LOCK_HAND_SIZE,pfrm)) == NULL )
	    return ERROR_NOT_ENOUGH_MEMORY;

	MAYBLOCK ( us = VMLock( 0L,
			   (PBYTE)peaop,
			   (ULONG)cbList,
			   (PVOID)-1L,
			   *plhList,
			   &usDump ) )


	if( us != NO_ERROR )
	    goto ErrorLockFind;

	/* The eaop is followed by a list
	 * so we probe the eaop and list together.
	 */
	MAYBLOCK (us = FSH_PROBEBUF (PB_OPWRITE,
				     (PBYTE) peaop,
				     cbList))
	if (us != NO_ERROR) {
	    goto ErrorUnlockList;
	}
	/*
	 * Get the gea list pointer now that the eaop is locked and valid
	 */

	pGEAList = peaop->fpGEAList;
	if( (*plhGEA = GHS(VM_LOCK_HAND_SIZE,pfrm)) == NULL ) {
	    us = ERROR_NOT_ENOUGH_MEMORY;
	    goto ErrorUnlockList;
	}

	/* probe fea segment */
	MAYBLOCK (us = FSH_PROBEBUF (PB_OPREAD,
				     (PBYTE) pGEAList,
				     sizeof (pGEAList->cbList)))

	if (us != NO_ERROR) {
	    goto ErrorUnlockList;
	}

	/* lock the segment, probe, then check the lock handle */
	MAYBLOCK ( us = VMLock( 0L,
			   (PBYTE)pGEAList,
			   pGEAList->cbList,
			   (PVOID)-1L,
			   *plhGEA,
			   &usDump ) )

	if (us != NO_ERROR) {
	    goto ErrorUnlockList;
	}

	/*
	 * Make sure user didn't give us a big buffer
	 */
	if( pGEAList->cbList > (ULONG)CB_MAX_EALIST ) {
	    us = ERROR_INVALID_PARAMETER;
	    goto ErrorUnlockBoth;
	}

	/* probe entire gea list */
	MAYBLOCK (us = FSH_PROBEBUF( PB_OPREAD,
				     (PBYTE) pGEAList,
				     (USHORT)pGEAList->cbList ))
	if (us == NO_ERROR) {
		return (NO_ERROR);
	}


ErrorUnlockBoth:
	if( *plhGEA != NULL )
	    MAYBLOCK (VMUnlock (*plhGEA))

ErrorUnlockList:
	if( *plhList != NULL )
	    MAYBLOCK (VMUnlock (*plhList))

ErrorLockFind:
	if( *plhGEA != NULL )
	    RetHeap( *plhGEA );

	if( *plhList != NULL )
	    RetHeap( *plhList );

	return (us);
}

void far
UnlockEAs (lhFEA, lhGEA, pfrm)
LHANDLE lhFEA;
LHANDLE lhGEA;
PFRAME	pfrm;
{
#ifdef DEBUG
	USHORT us;

	/* dprintf ("UnlockEAs: lhFEA=%lx lhGEA=%lx\n", lhFEA, lhGEA); */

	MAYBLOCK (us = VMUnlock (lhFEA))

	if (us)
		dprintf ("UnlockEAs: bad unlock, lhFEA=%lx\n", lhFEA);

	if (lhGEA != 0) {
		MAYBLOCK (us = VMUnlock (lhGEA))
		if (us) {
			dprintf ("UnlockEAs:bad unlock, lhGEA=%lx\n", lhGEA);
		}
		RetHeap( lhGEA );
	}
	RetHeap( lhFEA );
#else
	MAYBLOCK (VMUnlock (lhFEA))
	RetHeap( lhFEA );

	if( lhGEA != NULL ) {
	    MAYBLOCK (VMUnlock (lhGEA))
	    RetHeap( lhGEA );
	}
#endif
}
