/*static char *SCCSID = "@(#)vdmapi.c   6.2 91/02/08";*/

#define SCCSID "@(#)vdmapi.c    6.2 91/02/08"

/***    VDMAPI.C
 *
 *
 *      IBM/Microsoft Confidential
 *
 *      Copyright (c) IBM Corporation 1987, 1989
 *      Copyright (c) Microsoft Corporation 1987, 1989
 *
 *      All Rights Reserved
 *
 *      Title:
 *
 *      VDMAPI  Exported Procedures
 *
 *      Description:
 *
 *      Dos APIs provided by VDMM
 *
 *      Created: Sudeep Bharati      10/14/88
 *
 *
 *      Modification History:
 *
 *      09/19/94  bjn    Changed segment names for page tuning.
 *      98325 07/14/95 ChgTeam - Added check for NULL hksemHVDD to VR32CloseVDD
 *                               and VR32RequestVDD to avoid trap in
 *                               KSEMRequestMutex when PROTECTONLY=YES.
 *
 */

#define FNO_NUM  FNO_VDMAPI_C
#include <fnomvdm.h>

#define INCL_NONE
#define INCL_TYPES
#define INCL_MVDMTYPES
#define INCL_VDHALL
#define VDDSTRICT

#include <vdmvdh.h>
#include <kmode.h>

INT     PRIVENTRY vdmmOpenVDD(PSZ,PHVDD);
INT     PRIVENTRY vdmmCloseVDD(HVDD);
INT     PRIVENTRY vdmmRequestVDD(HVDD,ULONG,ULONG,ULONG,PVOID,ULONG,PVOID);

extern  PHDLVDD         PRIVENTRY OpenVDD(PSZ,ULONG);
extern  BOOL            PRIVENTRY CloseVDD(HVDD);

extern  PHDLVDD         phdlVddHead;
extern  HKSEM           hksemHVDD;

#pragma BEGIN_MVDM_SWAP_CODE

#pragma code_seg("SWAP32_23","CODE")
/***EP+ VR32OpenVDD - Open a VDD
 *
 *      Verification routine for DOS32OPENVDD
 *
 *      ENTRY
 *              pszName - name of the VDD
 *              phvdd - address where handle to vdd will be placed
 *
 *      EXIT
 *              SUCCESS
 *                      returns 0
 *              FAILURE
 *                      returns what ever vdmmOpenVDD returns
 *
 *      CONTEXT
 *              An OS/2 protected-mode process, such as the Shell
 *
 *      PCODE
 *              Verify the parameters
 *              call the worker vdmmOpenVDD
 *              return whatever worker returns
 */
INT CDECL VR32OpenVDD(sef,pszName,phvdd)
THUNKSEF sef;
PSZ     pszName;
PHVDD   phvdd;
/*end*/
{
HVDD    hvdd;
CHAR    buf[MAXLENXDD+1];
ULONG   rc,len;

    sef;                   // eliminate compiler warning
    if (hksemHVDD == (HKSEM) 0)
       return ERROR_INVALID_CALLER;                                   /*98325*/

    //Fetch the address of VDD name from user address space
    if(rc = TKFuBuffz(SSToDS(&len),SSToDS(buf),pszName,MAXLENXDD+1,TK_UM_FATAL))
        return(rc);

    //Call worker routine
    rc=vdmmOpenVDD(SSToDS(buf),SSToDS(&hvdd));

    //If worker retuens success copy the VDD handle to user space
    if(!rc)
        return(TKSuDWord(hvdd,phvdd));
}

#pragma code_seg("SWAP32_23","CODE")
/***LP+ vdmmOpenVDD - Worker routine for DOS32OPENVDD
 *
 *      Worker routine for DOS32OPENVDD
 *
 *      ENTRY
 *              pszName - name of the VDD
 *              phvdd - address where handle to vdd will be placed
 *
 *      EXIT
 *              SUCCESS
 *                      returns 0
 *              FAILURE
 *                      returns !0
 *                      ERROR_VDD_NOT_FOUND
 *                      ERROR_INVALID_CALLER
 *
 *      CONTEXT
 *              An OS/2 protected-mode process, such as the Shell
 *
 *      PCODE
 *              scan list of VDD entry points for *pszName
 *              if not found return FAILURE
 *              Allocate,fill and put a handle to VDD on handle list
 *              Copy handle in VDD handle list
 *              return SUCCESS
 */
INT PRIVENTRY vdmmOpenVDD(pszName,phvdd)
PSZ     pszName;
PHVDD   phvdd;
/*end*/
{
PHDLVDD   phdlvdd;

    if(pPTDACur->ptda_infoseg.LIS_ProcType == LIS_PT_REALMODE)
        return ERROR_INVALID_CALLER;
    // Call the generic routine to open the VDD for OS/2 process
    phdlvdd = OpenVDD(pszName,OS2VDD);
    if(phdlvdd == NULL)
        return(ERROR_VDD_NOT_FOUND);              /* No such registered VDD*/
    *phvdd=(HVDD)phdlvdd;
    return 0;
}

#pragma code_seg("SWAP32_17","CODE")
/***EP+ VR32RequestVDD - Send request to VDD
 *
 *      Verification routine for DOS32REQUESTVDD
 *
 *      ENTRY
 *              hvdd     - handle to VDD(s)
 *              SGid     - screen group id
 *                         0 - not for a specific screen group
 *                         !0 - for a specific screen group
 *              ulCmd    - Command (Depends on VDD)
 *              cbIn     - Size of input buffer
 *              pInbuf   - input buffer
 *              cbOut    - Size of output buffer
 *              pOutbuf  - output buffer
 *
 *      EXIT
 *              SUCCESS
 *                  returns 0
 *              FAILURE
 *                  returns whatever worker routine returns
 *
 *      CONTEXT
 *              An OS/2 protected-mode process, such as the Shell
 */

INT CDECL VR32RequestVDD(sef,hvdd,SGid,ulCmd,cbIn,pInbuf,cbOut,pOutbuf)
THUNKSEF sef;
HVDD   hvdd;
SGID   SGid;
ULONG  ulCmd;
ULONG  cbIn;
PVOID  pInbuf;
ULONG  cbOut;
PVOID  pOutbuf;
/*end*/
{

    sef;                   // eliminate compiler warning
    if (hksemHVDD == (HKSEM) 0)
       return ERROR_INVALID_CALLER;                                   /*98325*/

    //  As the input and output buffers can be large this API will
    //  not copy them instaed it will pass on to the VDD the pointers
    //  to these buffers and it is VDDs resposibility to lock them using
    //  VDHLockMem.

    return(vdmmRequestVDD(hvdd,SGid,ulCmd,cbIn,pInbuf,cbOut,pOutbuf));
}

#pragma code_seg("SWAP32_17","CODE")
/***EP+ vdmmRequestVDD - Worker routine for DOS32REQUESTVDD
 *
 *      Request VDD services.
 *      This function is used by the PM shell to:
 *
 *          1)  Get screen copies destined for the PM clipboard from a VDM
 *
 *      This service can also be used to allow an OS/2 application to
 *      debug a DOS application (a "Debug" VDD is required).
 *
 *      Every DosReq proc registered under the VDD name associated with
 *      the given handle is called until one returns a TRUE.  There
 *      is no guaranteed order to the calling sequence.
 *
 *      ENTRY
 *              hvdd     - handle to VDD(s)
 *              SGid     - screen group id
 *                         0 - not for a specific screen group
 *                         !0 - for a specific screen group
 *              ulCmd    - Command (Depends on VDD)
 *              cbIn     - Size of input buffer
 *              pInbuf   - input buffer
 *              cbOut    - Size of output buffer
 *              pOutbuf  - output buffer
 *
 *      EXIT
 *              SUCCESS
 *                  returns 0
 *              FAILURE
 *                  returns
 *                      ERROR_INVALID_HANDLE
 *                      ERROR_INVALID_CALLER
 *                      ERROR_NOT_READY
 *                      Onther VDD defined error values
 *
 *
 *      NOTE
 *              VDD handler routine will return TRUE as success
 *
 *      CONTEXT
 *              An OS/2 protected-mode process, such as the Shell
 */

INT PRIVENTRY vdmmRequestVDD(hvdd,SGid,ulCmd,cbIn,pInbuf,cbOut,pOutbuf)
HVDD   hvdd;
ULONG  SGid;
ULONG  ulCmd;
ULONG  cbIn;
PVOID  pInbuf;
ULONG  cbOut;
PVOID  pOutbuf;
/*end*/
{
PHDLVDD          phvddCur,phvdd;
PVDDPROC         pvddproc;
INT              rc;

    if(pPTDACur->ptda_infoseg.LIS_ProcType == LIS_PT_REALMODE)
        return ERROR_INVALID_CALLER;

    phvdd=(PHDLVDD)hvdd;

    // Grab the mutex semaphore
    if (KSEMRequestMutex (hksemHVDD, -1) != NO_ERROR)
        Panic (("vdmmRequestVDD: KSEMRequestMutex"));

    // Scan the list of VDD handler to get a match for hvdd
    phvddCur = phdlVddHead;
    while(phvddCur != NULL){
        if(phvdd == phvddCur){
            pvddproc = phvddCur->hdlvdd_pvddproc;
            KSEMReleaseMutex (hksemHVDD);
            while(pvddproc != NULL){
              if(*pvddproc->vddproc_pfnos2){
                rc=(INT)(*pvddproc->vddproc_pfnos2)((SGID)SGid,ulCmd,cbIn,
                                             pInbuf,cbOut,pOutbuf);
                if(rc != VDDREQ_PASS){
                    return rc;
                }
              }
              pvddproc = pvddproc->pvddproc;
            }
            return ERROR_NOT_READY;
        }
        else
            phvddCur = phvddCur->hdlvdd;
    }
    KSEMReleaseMutex (hksemHVDD);
    return(ERROR_INVALID_HANDLE);
}

#pragma code_seg("SWAP32_25","CODE")
/***EP+ VR32CloseVDD - Close a VDD
 *
 *      Verification routine for DOS32CLOSEVDD
 *
 *      ENTRY
 *              hvdd -  handle to vdd
 *
 *      EXIT
 *              SUCCESS
 *                      returns 0
 *              FAILURE
 *                      returns whatever worker routine returns
 *
 *      CONTEXT
 *              An OS/2 protected-mode process, such as the Shell
 *
 *      PCODE
 *              Verify parameters
 *              call worker routine vdmmCloseVDD
 *              return whatever worker returns
 */
INT CDECL VR32CloseVDD(sef,hvdd)
THUNKSEF sef;
HVDD    hvdd;
/*end*/
{
    sef;                      // eliminate compiler warning
    if (hksemHVDD == (HKSEM) 0)
       return ERROR_INVALID_CALLER;                                   /*98325*/
    return(vdmmCloseVDD(hvdd));
}

#pragma code_seg("SWAP32_25","CODE")
/***LP+ vdmmCloseVDD - Worker routine for DOS32CLOSEVDD
 *
 *      Worker routine for DOS32CLOSEVDD
 *
 *      ENTRY
 *              hvdd -  handle to vdd
 *
 *      EXIT
 *              SUCCESS
 *                      returns 0
 *              FAILURE
 *                      returns !0
 *                         ERROR_INVALID_HANDLE
 *                         ERROR_INVALID_CALLER
 *
 *      CONTEXT
 *              An OS/2 protected-mode process, such as the Shell
 *
 *      PCODE
 *              return FAILURE if hvdd is invalid
 *              release HVDD
 *              return SUCCESS
 */
INT PRIVENTRY vdmmCloseVDD(hvdd)
HVDD    hvdd;
/*end*/
{
// PHDLVDD phdlvdd,phdlvddCur,phdlvddPrev;

    if(pPTDACur->ptda_infoseg.LIS_ProcType == LIS_PT_REALMODE)
        return ERROR_INVALID_CALLER;

    if (CloseVDD (hvdd))
        return 0;
    else
        return(ERROR_INVALID_HANDLE);
}

#pragma END_MVDM_SWAP_CODE
