/*static char *SCCSID = "@(#)vlptuser.c 6.10 92/03/20";*/
#pragma linesize(132)
#pragma pagesize(60)
#pragma title("VLPTUSER.C")
/****************************************************************************/
/*                                                                          */
/*                       IBM/Microsoft Confidential                         */
/*                                                                          */
/*                 Copyright (c) IBM Corporation  1987, 1990                */
/*                 Copyright (c) Microsoft Corp.  1987, 1990                */
/*                           All Rights Reserved                            */
/*                                                                          */
/****************************************************************************/
/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  VLPTUSER.C                                            */
/*                                                                            */
/*   DESCRIPTIVE NAME:  Process VDM events that the VLPT has registered for   */
/*                      notification of when they occur                       */
/*                                                                            */
/*   FUNCTION: These routines process specific VDM events and return to       */
/*             the caller.                                                    */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: Spooler is running                                      */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*             VLPTCreate     -  VDM creation event handler                   */
/*             VLPTTerminate  -  VDM termination event handler                */
/*             VLPTPDBChange  -  VDM PDB change event handler                 */
/*             VLPTPDBDestroy -  VDM PDB destruction event handler            */
/*             VDHPrintClose  -  VKBD Ctrl-Alt-PrtSc handler                  */
/*             VLPTSetSpoolClose - PRINT_TIMEOUT DOS Setting change handler   */
/*             VLPTEventContext - Int 17h Print timeout handler               */
/*             VLPTDOSLink    -  VDD API interface for DOS/DPMI applications  */ /*107402*/
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*             VDHAllocHook      - Allocate hook handle for VDHArmReturnHook  */
/*             VDHCloseVDD       - Close IDC with VDD                         */
/*             VDHInstallIntHook - Hook an interrupt                          */
/*             VDHInstallIOHook  - Hook the I/O port trap handler             */
/*             VDHRemoveIOHook   - Remove the hook for I/O port trap handler  */
/*             VDHCreateSem      - Create an event semaphore                  */
/*             VDHDestroySem     - Destroy an event semaphore                 */
/*             VDHOpenVDD        - Open IDC with VDD                          */
/*             VDHPostEventSem   - Post an event semaphore                    */
/*             VDHQuerySem       - Query state of event semaphore             */
/*             VDHQueryHookData  - Query Context Hook Data                    */
/*             VDHQueryProperty  - Query a DOS property                       */
/*             VDHRequestVDD     - Query a DOS property                       */
/*             VDHResetEventSem  - Reset an event semaphore                   */
/*                                                                            */
/*   HISTORY:                                                                 */
/*                                                                            */
/* 107402  12/16/94  Change Team  Added VDD API interface for DOS/DPMI apps.  */
/* 112961  02/20/94  Change Team  Request exclusive access to lpt port.       */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#include <mvdm.h>                       /* VDH services, etc.        */
#include "vlptp.h"                      /* VLPT data defines         */
#include "vlptdata.h"                   /* VLPT external data        */

#pragma BEGIN_SWAP_DATA
extern  SZ      szProplpt1timeout;
extern  SZ      szProplptseparate;
#pragma END_SWAP_DATA

#pragma BEGIN_SWAP_CODE

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTCREATE                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  VLPT VDM Creation Event Handler                 */
/*                                                                    */
/* FUNCTION:  This routine is called from the VDM Manager when a VDM  */
/*            is created. Instance data is initialized. Interrupt 17h */
/*            hook routine is registered. IN and OUT parallel port    */
/*            hook routines are registered. Interrupt 05h hook        */
/*            routine is registered. Interrupt 05h return hook is     */
/*            allocated.                                              */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VLPTCreate                                           */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  VDM Handle                                                 */
/*                                                                    */
/* EXIT-NORMAL:  returns !0                                           */
/*                                                                    */
/* EXIT-ERROR:   returns 0                                            */
/*                                                                    */
/* EFFECTS:  Per VDM data area is initialized.                        */
/*           VDM bios data area is created.                           */
/*                                                                    */
/* INTERNAL REFERENCES:  VLPTTerminate                                */
/*                                                                    */
/* EXTERNAL REFERENCES:  VDHAllocHook                                 */
/*                       VDHCloseVDD                                  */
/*                       VDHInstallIntHook                            */
/*                       VDHInstallIOHook                             */
/*                       VDHCreateSem                                 */
/*                       VDHOpenVDD                                   */
/*                       VDHQuerySem                                  */
/*                       VDHQueryHookData                             */
/*                       VDHQueryProperty                             */
/*                       VDHRequestVDD                                */
/*                       VDHResetEventSem                             */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BOOL HOOKENTRY VLPTCreate(hvdm)
HVDM hvdm;
{
    INT i, j, k;                       /* counters                   */
    VDHSEMSTATE SemStateStruc;         /* set up semaphore state     */
                                       /*    structure               */
    PVOID posinbuffer;                 /* POS input buffer           */
    k = 0;                             /* initialize counter         */

#ifdef DEBUG
   vdhInt3();
#endif

    /*---------------------------------------------------------------*/
    /* If running on a PS2 then get the handle to VBIOS for making   */
    /* a request to get the address of the POS register data         */
    /* structure. After getting the VBIOS handle request the address */
    /* of the POS register data structure. Do this only once.        */
    /* All VDMs created after the first will not do this because     */
    /* the address is good for all VDMs.                             */
    /*---------------------------------------------------------------*/
    if (MachineType == MACHINE_TYPE_PS2)
    {
      if (pvddvbiospos==NULL)
      {
        if ((hvddvbios=VDHOpenVDD(VBIOS_NAME))==FALSE)
        {
          return FALSE;
        } else
        {
          if(VDHRequestVDD(hvddvbios,
                        hvdm,
                        0,
                        SSToDS(&posinbuffer),
                        &pvddvbiospos)==FALSE)
                        {
                          VDHCloseVDD(hvddvbios);
                          return FALSE;
                        }
        }
      }
    }

    /*---------------------------------------------------------------*/
    /*- Initialize non per port instance data                       -*/
    /*---------------------------------------------------------------*/
    this_VDM = hvdm;
    resp_val = 0;
    vlpt_sem_handle = (DWORD)0;
    pdbCurrent = INVALID_PDB;

    /*---------------------------------------------------------------*/
    /*- This loop initializes the per VDM bios data area parallel   -*/
    /*- port addresses and the per VDM data area.                   -*/
    /*---------------------------------------------------------------*/
    for(i=0; i<MAXPRTS; i++) {

    /*---------------------------------------------------------------*/
    /*- Copy the VLPT port address table base printer port address  -*/
    /*- into the current base printer port address location in the  -*/
    /*- current VDMs bios data area.                                -*/
    /*---------------------------------------------------------------*/
        VDMBase.rb_awLPT[i] = vpa_table[i].data;
        pvd_area[i].flags = FLAG_NOT_SET;
        pvd_area[i].data = FLAG_NOT_SET;
        pvd_area[i].status = (BYTE)POWER_ON_STATUS;
        pvd_area[i].lptportid = (UCHAR)i;
        pvd_area[i].fshandle = INVALID_HANDLE;
        pvd_area[i].bufcount = 0;
        pvd_area[i].reserve_word = 0;
        pvd_area[i].stream = NULL;
        pvd_area[i].pdb_spool = INVALID_PDB;
        pvd_area[i].pdb_direct = INVALID_PDB;

    /*---------------------------------------------------------------*/
    /*-  Allocate timer Hook for LPT spool Timeout                  -*/
    /*---------------------------------------------------------------*/

        if (!(pvd_area[i].hhookLptEventContext = VDHAllocHook(VDH_TIMER_HOOK,
                                                     (PFNARM)VLPTEventContext,
                                                     sizeof(PVLPTINST))))
            return FALSE;

    /*---------------------------------------------------------------*/
    /*- Initialize Timer Hook Data, see VLPTEventContext()          -*/
    /*---------------------------------------------------------------*/

        *(PULONG)VDHQueryHookData(pvd_area[i].hhookLptEventContext) =
                                  (ULONG)&pvd_area[i];

    } /* endfor */

    /*---------------------------------------------------------------*/
    /*- Set number of printers installed to 3 in VDM bios data area.-*/
    /*- DosDevConfig uses this area to find out how many physical   -*/
    /*- parallel ports are in the system. Therefore VLPT cannot     -*/
    /*- set it to match how many ports it is virtualizing.          -*/
    /*---------------------------------------------------------------*/
    //  VDMBase.rb_fsEquip |= BIOSEQUIP_PRINTERMASK;

    /*---------------------------------------------------------------*/
    /*- Register a semaphore for retry processing. If the call      -*/
    /*- fails return with failure.                                  -*/
    /*---------------------------------------------------------------*/
    if ((VDHCreateSem(&vlpt_sem_handle,VDH_EVENTSEM)) == 0) {

        return FALSE;                 /* return FALSE if call failed */

    } else {

    /*---------------------------------------------------------------*/
    /*- Call VDHQuerySem and check the state of the semaphore. If   -*/
    /*- it is posted/not owned then call VDHResetEventSem to own it.-*/
    /*---------------------------------------------------------------*/
        VDHQuerySem(vlpt_sem_handle,(PVDHSEMSTATE)SSToDS(&SemStateStruc));

        if (!(SemStateStruc.vss_fOwned)) {
            VDHResetEventSem(vlpt_sem_handle);
        } /* endif */

    } /* endif */

    /*---------------------------------------------------------------*/
    /*- Allocate hook handle for VDHArmReturnHook                   -*/
    /*---------------------------------------------------------------*/
    if((hhookVLPTIRet5 = VDHAllocHook(VDH_RETURN_HOOK, (PFNARM)VLPTIRet5,
      sizeof(UINT))) == NULL) {
        return FALSE;
    }

    /*---------------------------------------------------------------*/
    /*- Register a VDM interrupt hook handler for Int 17H.          -*/
    /*---------------------------------------------------------------*/
    VDHInstallIntHook(hvdm,
                      (ULONG)INT_17,
                      VLPTInt17,
                      !VDH_ASM_HOOK);


    /*---------------------------------------------------------------*/
    /*- Register a VDM interrupt hook handler for Int 05H.          -*/
    /*---------------------------------------------------------------*/
    VDHInstallIntHook(hvdm,
                      (ULONG)INT_05,
                      VLPTInt05,
                      !VDH_ASM_HOOK);

    /*---------------------------------------------------------------*/ /*107402*/
    /*- Register a VDD API that can be used by DOS/DPMI applications */ /*107402*/
    /*---------------------------------------------------------------*/ /*107402*/
    VDHRegisterAPI("VLPT", (PFNHOOK)VLPTDOSLink, (PFNHOOK)VLPTDOSLink); /*107402*/

    /*---------------------------------------------------------------*/
    /*- This loop installs IO hooks for the data, status, control,  -*/
    /*- and reserve ports for each parallel printer port.           -*/
    /*---------------------------------------------------------------*/
    for(j=0; j<MAXPRTS; j++) {

    /*---------------------------------------------------------------*/
    /*- Only hook physical ports.                                   -*/
    /*---------------------------------------------------------------*/
       if (vpa_table[j].flags == PHYSICAL_PORT)
       {
    /*---------------------------------------------------------------*/
    /*- Register a VDM IO hook handler for parallel printer ports.  -*/
    /*- If the call ever fails then before returning VLPTTerminate  -*/
    /*- will be called to clean up IO and INT17 hooks.              -*/
    /*---------------------------------------------------------------*/
        if ((VDHInstallIOHook(hvdm,
                              vpa_table[j].data,
                              1,
                              &v_ioh[k].iohtable,
                              !VDH_ASM_HOOK)) == 0) {
            return FALSE;             /* return FALSE                */
        } /* endif */

        k++;                       /* increment IO handler table ptr */

        if ((VDHInstallIOHook(hvdm,
                              vpa_table[j].status,
                              1,
                              &v_ioh[k].iohtable,
                              !VDH_ASM_HOOK)) == 0) {
            return FALSE;             /* return FALSE                */
        } /* endif */

        k++;                       /* increment IO handler table ptr */

        if ((VDHInstallIOHook(hvdm,
                              vpa_table[j].control,
                              1,
                              &v_ioh[k].iohtable,
                              !VDH_ASM_HOOK)) == 0) {
            return FALSE;             /* return FALSE                */
        } /* endif */

        k++;                       /* increment IO handler table ptr */

    /*---------------------------------------------------------------*/
    /*- The 3BFh port is documented as a reserved parallel port in  -*/
    /*- the IBM Hardware Interface Technical Reference. The Hercules-*/
    /*- video adapter manufacturers broke compatibility by using    -*/
    /*- the reserved LPT1 port.  Now, other Super VGA adapter       -*/
    /*- manufacturers have also started using this port.  In the    -*/
    /*- interest of supporting SVGA, VLPT is discontinuing to hook  -*/
    /*- this IO port (VDHInstallIOHook) so that the video software  -*/
    /*- can use it.                                                 -*/
    /*---------------------------------------------------------------*/
        if (vpa_table[j].reserve != 0x03BF)
        {
          if ((VDHInstallIOHook(hvdm,
                                vpa_table[j].reserve,
                                1,
                                &v_ioh[k].iohtable,
                                !VDH_ASM_HOOK)) == 0) {
              return FALSE;             /* return FALSE                */
          } /* endif */

        }
        k++;                 /* increment IO handler table ptr */

       } else {
        k+=4;         /* if not physical increment for ports skipped */
       }

    } /* endfor */

    // Get the Current DOS Properties Setting

    nmsLptTimeout = VDHQueryProperty(szProplpt1timeout)*1000;
    if (VDHQueryProperty(szProplptseparate))
      VLPTFlags |= (FLAGS)LPTINT17SEP;
    else
      VLPTFlags &= ~(FLAGS)LPTINT17SEP;

    return TRUE;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTTERMINATE                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  VLPT VDM Termination Event Handler              */
/*                                                                    */
/* FUNCTION:  This routine is called from the VDM Manager when a VDM  */
/*            is terminating. All printers are closed for the current */
/*            VDM handle using doClose. All IO hooks are removed.     */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VLPTTerminate                                        */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  VDM Handle                                                 */
/*                                                                    */
/* EXIT-NORMAL:  !0                                                   */
/*                                                                    */
/* EXIT-ERROR:   0                                                    */
/*                                                                    */
/* EFFECTS:   Init-time flag in per VDM data area.                    */
/*                                                                    */
/* INTERNAL REFERENCES:  doCloseSpool                                 */
/*                       doCloseDirect                                */
/*                                                                    */
/* EXTERNAL REFERENCES:  VDHRemoveIOHook                              */
/*                       VDHDestroySem                                */
/*                       VDHPostEventSem                              */
/*                       VDHQuerySem                                  */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BOOL HOOKENTRY VLPTTerminate(hvdm)
HVDM hvdm;
{
    INT i;                             /* counters                   */
    VDHSEMSTATE SemStateStruc;         /* set up semaphore state     */
                                       /*    structure               */

#ifdef DEBUG
   vdhInt3();
#endif

    /*---------------------------------------------------------------*/
    /*- This loop calls doCloseSpool and doCloseDirect to close all -*/
    /*- printers. It also clears the INIT flag in the per VDM data  -*/
    /*- area flags for each printer. It also removes all IO hooks   -*/
    /*- for the parallel printer ports.                             -*/
    /*---------------------------------------------------------------*/
    for(i=0; i<MAXPRTS; i++) {
        pvd_area[i].flags &= (~INIT_FLAG);
        doCloseSpool(&pvd_area[i]);
        doCloseDirect(&pvd_area[i]);

    /*---------------------------------------------------------------*/
    /*- If a Print-Screen is in progress the hold area of the per   -*/
    /*- VDM data area contains an open device and a data stream     -*/
    /*- that need to be cleaned up.                                 -*/
    /*---------------------------------------------------------------*/
        if (pvd_area[i].flags & PRT_SC_IN_PROG) {
            pvd_area[PORT_HOLD].flags &= (~INIT_FLAG);
            doCloseSpool(&pvd_area[PORT_HOLD]);
        } /* endif */

    } /* endfor */

    /*---------------------------------------------------------------*/
    /*- If the VDHCreateSem has returned a valid semaphore then     -*/
    /*- call VDHQuerySem and check the state of the semaphore to    -*/
    /*- make sure the semaphore is posted/not owned before          -*/
    /*- destroying it. If the semaphore is not posted/not owned     -*/
    /*- then call VDHPostEventSem to set it as posted/not owned.    -*/
    /*---------------------------------------------------------------*/
    if (vlpt_sem_handle) {

        VDHQuerySem(vlpt_sem_handle,(PVDHSEMSTATE)SSToDS(&SemStateStruc));

        if (SemStateStruc.vss_fOwned) {

            VDHPostEventSem(vlpt_sem_handle);

        } /* endif */

        VDHDestroySem(vlpt_sem_handle);

    } /* endif */

    return TRUE;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTPDBCHANGE                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  VLPT VDM PDB Change Event Handler               */
/*                                                                    */
/* FUNCTION:  This routine is called from the VDM Manager when a VDM  */
/*            PDB change occurs.                                      */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VLPTPDBChange                                        */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  hvdm   - VDM handle                                        */
/*         vPDB   - v86 segment of PDB                                */
/*                                                                    */
/* EXIT-NORMAL:  !0                                                   */
/*                                                                    */
/* EXIT-ERROR:   0                                                    */
/*                                                                    */
/* EFFECTS:                                                           */
/*                                                                    */
/* INTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BOOL HOOKENTRY VLPTPDBChange(hvdm,vPDB)
HVDM hvdm;
VLPTPDB vPDB;
{

#ifdef DEBUG
   vdhInt3();
#endif

    /*---------------------------------------------------------------*/
    /*- Save current PDB                                            -*/
    /*---------------------------------------------------------------*/
    pdbCurrent = vPDB;

    return TRUE;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTPDBDESTROY                                   */
/*                                                                    */
/* DESCRIPTIVE NAME:  VLPT VDM PDB Destruction Event Handler          */
/*                                                                    */
/* FUNCTION:  This routine is called from the VDM Manager when a VDM  */
/*            PDB is destroyed. Upon entry this routine will look     */
/*            for data streams that have a PDB that matches the one   */
/*            that was destroyed. Each data stream that has a PDB     */
/*            that matches will be closed.                            */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VLPTPDBDestroy                                       */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  hvdm   - VDM handle                                        */
/*         vPDB   - v86 segment of PDB                                */
/*                                                                    */
/* EXIT-NORMAL:  !0                                                   */
/*                                                                    */
/* EXIT-ERROR:   0                                                    */
/*                                                                    */
/* EFFECTS:                                                           */
/*                                                                    */
/* INTERNAL REFERENCES:  doCloseSpool                                 */
/*                       doCloseDirect                                */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
BOOL HOOKENTRY VLPTPDBDestroy(hvdm,vPDB)
HVDM hvdm;
VLPTPDB vPDB;
{
    INT i;                             /* counter                    */

#ifdef DEBUG
   vdhInt3();
#endif
    /*---------------------------------------------------------------*/
    /*- If separate print setting is ON then split on PDB destroy   -*/
    /*---------------------------------------------------------------*/
    if (VLPTFlags & LPTINT17SEP)
      {

      /*---------------------------------------------------------------*/
      /*- Make sure passed in PDB is valid                            -*/
      /*---------------------------------------------------------------*/
      if (vPDB != INVALID_PDB) {

      /*---------------------------------------------------------------*/
      /*- Look at each PDB in the per VDM data for ones that match    -*/
      /*- the PDB being destroyed. Call doClose for each device that  -*/
      /*- has a PDB match. If a Print-Screen is in progress for the   -*/
      /*- device in question then the device in the per VDM data area -*/
      /*- hold area should be closed if it's PDB is the same as the   -*/
      /*- current one. This will allow the Print-Screen to complete   -*/
      /*- normally.                                                   -*/
      /*---------------------------------------------------------------*/
          for(i=0; i<MAXPRTS; i++) {

              if (pvd_area[i].flags & PRT_SC_IN_PROG) {

                  if (vPDB == pvd_area[PORT_HOLD].pdb_spool) {
                      pvd_area[PORT_HOLD].flags &= (~INIT_FLAG);
                      doCloseSpool(&pvd_area[PORT_HOLD]);
                  } /* endif */

              } else {

                  if (vPDB == pvd_area[i].pdb_spool) {
                      pvd_area[i].flags &= (~INIT_FLAG);
                      doCloseSpool(&pvd_area[i]);
                  } /* endif */

              } /* endif */

              if (vPDB == pvd_area[i].pdb_direct) {
                  doCloseDirect(&pvd_area[i]);
              } /* endif */

          } /* endfor */

      } /* endif */
    } /* endif */
    return TRUE;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VDHPRINTCLOSE                                    */
/*                                                                    */
/* DESCRIPTIVE NAME:  Flush and close all open printers for a VDM     */
/*                                                                    */
/* FUNCTION:  This VDH service is called by other VDDs who wish to    */
/*            flush and close a VDM's open printers for any reason.   */
/*            A VDM may have more than one printer open. This service */
/*            will flush and close all of them.                       */
/*                                                                    */
/* NOTES:  This is an exported service.                               */
/*                                                                    */
/* CONTEXT: VDM task time                                             */
/*                                                                    */
/* ENTRY POINT:  VDHPrintClose                                        */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  hvdm   VDM handle                                          */
/*                                                                    */
/* EXIT-NORMAL: NONE                                                  */
/*                                                                    */
/* EXIT-ERROR: NONE                                                   */
/*                                                                    */
/* EFFECTS:  Init flag in per VDM data area.                          */
/*                                                                    */
/* INTERNAL REFERENCES:  doCloseSpool                                 */
/*                       doCloseDirect                                */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID VDHENTRY VDHPrintClose(hvdm)
HVDM hvdm;
{
    INT i;                             /* counter                    */

#ifdef DEBUG
   vdhInt3();
#endif
    /*---------------------------------------------------------------*/
    /*- This loop calls doClose to close all printers. It also      -*/
    /*- clears the INIT flag in the per VDM data area flags for each-*/
    /*- printer.                                                    -*/
    /*---------------------------------------------------------------*/
    for(i=0; i<MAXPRTS; i++) {

    /*---------------------------------------------------------------*/
    /*- If a Print-Screen is in progress for the device in question -*/
    /*- then the device in the per VDM data area hold area should be-*/
    /*- closed. This will allow the Print-Screen to complete        -*/
    /*- normally.                                                   -*/
    /*---------------------------------------------------------------*/
        if (pvd_area[i].flags & PRT_SC_IN_PROG) {

            pvd_area[PORT_HOLD].flags &= (~INIT_FLAG);
            doCloseSpool(&pvd_area[PORT_HOLD]);

        } else {

            pvd_area[i].flags &= (~INIT_FLAG);
            doCloseSpool(&pvd_area[i]);

        } /* endif */

        doCloseDirect(&pvd_area[i]);

    } /* endfor */
    return;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTSetSpoolClose                                */
/*                                                                    */
/* DESCRIPTIVE NAME:  Set/validate the DOS Setting PRINT_TIMEOUT.     */
/*                                                                    */
/* FUNCTION:  This routine is called when the state of                */
/*            PRINT_TIMEOUT DOS Setting changes.                      */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task context                                          */
/*                                                                    */
/* ENTRY POINT:  VLPTSetSpoolClose                                    */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  op     operation to perform                                */
/*         hvdm   VDM handle                                          */
/*         cb     length of value                                     */
/*         psz    ptr to value                                        */
/*                                                                    */
/* EXIT-NORMAL: Returns zero, no error                                */
/*                                                                    */
/* EXIT-ERROR: NONE                                                   */
/*                                                                    */
/* EFFECTS:  nmsLptTimeout                                            */
/*                                                                    */
/* INTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
ULONG EXPENTRY VLPTSetSpoolClose(ULONG op, HVDM hvdm, ULONG cb, PSZ psz)
{
    REFHVDM(hvdm, ULONG, nmsLptTimeout ) = (ULONG)psz*1000;
    return 0;
}

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTEventContext                                 */
/*                                                                    */
/* DESCRIPTIVE NAME:  Close any int 17h generated spool files.        */
/*                                                                    */
/* FUNCTION:  This routine is called at task time when the            */
/*            VLPTEventTimer() has expired.  The event timer expires  */
/*            when an application stops issuing int 17h requests.     */
/*            This routine flushes any remaining characters that VLPT */
/*            has buffered to the spooler.                            */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: VDM task context                                          */
/*                                                                    */
/* ENTRY POINT:  VLPTEventContext                                     */
/*    LINKAGE:  CALL NEAR 32                                          */
/*                                                                    */
/* INPUT:  p      reference data (not used)                           */
/*         pcrf   pointer to client register frame (not used)         */
/*                                                                    */
/* EXIT-NORMAL: NONE                                                  */
/*                                                                    */
/* EXIT-ERROR: NONE                                                   */
/*                                                                    */
/* EFFECTS:  VLPTFlags                                                */
/*                                                                    */
/* INTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID HOOKENTRY VLPTEventContext(PVOID p, PCRF pcrf)
{
    VLPTFlags |= (FLAGS)TIMEOUT_IN_PROG;
    doCloseSpool(*(PPVLPTINST)p);
    VLPTFlags &= ~(FLAGS)TIMEOUT_IN_PROG;

}

/* Defect 107402 starts here */
/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  VLPTDOSLink                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Provide an interface for DOS/DPMI applications  */
/*                                                                    */
/* FUNCTION:  Service clients AH operation                            */
/*            AH=00, Release exclusive access to lpt port             */
/*                   DX = LPT port address                            */
/*                   RETURNS AH=0 FOR NORMAL SUCCESS                  */
/*                   RETURNS AH=-1 FOR ERROR                          */
/*            AH=01, Request exclusive access to lpt port             */
/*                   DX = LPT port address                            */
/*                   RETURNS AH=0 FOR NORMAL SUCCESS                  */
/*                   RETURNS AH=!0 FOR ERROR                          */
/*                                                                    */
/* NOTES:  This is a private VDD entry point.                         */
/*                                                                    */
/* CONTEXT: DOS session task time                                     */
/*                                                                    */
/* ENTRY POINT:  VLPTDOSLink                                          */
/*    LINKAGE:  CALL FAR 32                                           */
/*                                                                    */
/* INPUT:                                                             */
/*          p     - reserved                                          */
/*          pcrf  - client's register frame.                          */
/*                  Registers contain input parameters                */
/*                  for services.                                     */
/*                                                                    */
/* EXIT-NORMAL: Always succeeds;                                      */
/*              client's registers contain information, depending     */
/*                      on which service was called.                  */
/*                                                                    */
/* EXIT-ERROR: Always succeeds                                        */
/*              client's registers contain information, depending     */
/*                      on which service was called.                  */
/*                                                                    */
/* EFFECTS:  NONE                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:  DoCloseDirect                                */
/*                                                                    */
/* EXTERNAL REFERENCES:  NONE                                         */
/*                                                                    */
/* NOTES: Assumes service will always be called with a far 16 bit call*/
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/
VOID HOOKENTRY VLPTDOSLink(PVOID pRefData, PCRF pcrf)
{
   UINT uFunction;
   UINT uDefLPT;
   VPVOID vpretaddr;

   if (VDHPopStack(4, SSToDS(&vpretaddr)))
   {
      IP(pcrf) = OFFSETOF16(vpretaddr);
      CS(pcrf) = SEGMENTOF16(vpretaddr);

      uFunction = AH(pcrf);
      switch(uFunction)
      {
         case 0:          /* Release exclusive access to LPT port */
            uDefLPT = DX(pcrf);
            if( uDefLPT == vpa_table[pvd_area[LPTONE].lptportid].data )
            {
               doCloseDirect(&pvd_area[LPTONE]);
               AH(pcrf) = 0;  /* return success */
            }
            else if( uDefLPT == vpa_table[pvd_area[LPTTWO].lptportid].data )
            {
               doCloseDirect(&pvd_area[LPTTWO]);
               AH(pcrf) = 0;  /* return success */
            }
            else if( uDefLPT == vpa_table[pvd_area[LPTTHREE].lptportid].data )
            {
               doCloseDirect(&pvd_area[LPTTHREE]);
               AH(pcrf) = 0;  /* return success */
            }
            else
            {
               AH(pcrf) = -1;  /* return error */
            }
            break;

         case 1:          /* Request exclusive access to LPT port */ /* 112961 */
            uDefLPT = DX(pcrf);                                      /* 112961 */
            if( uDefLPT == vpa_table[pvd_area[LPTONE].lptportid].data ) /* 112961 */
            {                                                        /* 112961 */
               AH(pcrf) = get_direct_access(&pvd_area[LPTONE]);      /* 112961 */
            }                                                        /* 112961 */
            else if( uDefLPT == vpa_table[pvd_area[LPTTWO].lptportid].data ) /* 112961 */
            {                                                        /* 112961 */
               AH(pcrf) = get_direct_access(&pvd_area[LPTTWO]);      /* 112961 */
            }                                                        /* 112961 */
            else if( uDefLPT == vpa_table[pvd_area[LPTTHREE].lptportid].data ) /* 112961 */
            {                                                        /* 112961 */
               AH(pcrf) = get_direct_access(&pvd_area[LPTTHREE]);    /* 112961 */
            }                                                        /* 112961 */
            else                                                     /* 112961 */
            {                                                        /* 112961 */
               AH(pcrf) = -1;  /* return error */                    /* 112961 */
            }                                                        /* 112961 */
            break;                                                   /* 112961 */

         default:           /* operation not supported */
            AH(pcrf) = -1;  /* return error */
            break;

      } /* end switch */
   } /* end if */

   return;
}  /* end VLPTDOSLink */
/* Defect 107402 ends here */

#pragma END_SWAP_CODE

