home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- *
- * SOURCE FILE NAME = pdrapi.c
- *
- * DESCRIPTIVE NAME = parallel port driver exported SplPd APIs
- *
- * Copyright : COPYRIGHT IBM CORPORATION, 1994, 1995
- * LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
- * REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
- * RESTRICTED MATERIALS OF IBM
- * IBM CONFIDENTIAL
- *
- * VERSION = V2.2
- *
- * DATE
- *
- * DESCRIPTION
- *
- *
- * FUNCTIONS
- *
- * ENTRY POINTS:
- *
- * DEPENDENCIES:
- *
- * NOTES
- *
- *
- * STRUCTURES
- *
- * EXTERNAL REFERENCES
- *
- * EXTERNAL FUNCTIONS
- *
- * CHANGE ACTIVITY =
- * DATE FLAG APAR CHANGE DESCRIPTION
- * -------- ---------- ----- --------------------------------------
- * mm/dd/yy @Vr.mpppxx xxxxx xxxxxxx
- ****************************************************************************/
-
- #include "pdrconst.h"
- #include "pdrtypes.h"
- #include "pdrproto.h"
-
- #define BIDI_TEST_RESP 0x9000
-
- /*
- ** SPLPD functions that can be called by ANY process, not just the spooler
- */
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdEnumPort
- *
- * DESCRIPTION = Return ports supported by this port driver
- * Currently this will return those ports this port
- * driver supports by default.
- * The print object only calls this if the port
- * driver does not export the extended attribute
- * "DEFAULT_PORT"
- *
- * INPUT = hab - anchor block handle
- * pBuf - buffer to get enumerated PORTNAMES structures
- * cbBuf - size(in bytes) of pBuf passed in
- *
- * OUTPUT = *pulReturned - number of PORTNAMES structures stored in pBuf
- * *pulTotal - total ports supported by this port driver
- * *pcbRequired - size(in bytes) of buffer needed to store
- * all enumerated PORTNAMES entries.
- * pBuf - gets an array(number elements is *pulReturned) of
- * PORTNAMES structures.
- * Each psz in PORTNAMES structure points to a string
- * copied into the end of pBuf.
- *
- * typedef struct _PORTNAMES {
- * PSZ pszPortName; // Name of port, example: PAR1284
- * PSZ pszPortDesc; // Port description
- * } PORTNAMES;
- *
- * RETURN-NORMAL = 0 - if all portnames and descriptions fit in pBuf
- *
- * RETURN-ERROR = ERROR_INSUFFICIENT_BUFFER - if no PORTNAMES structs
- * could fit in buffer. Caller
- * uses *pcbRequired to allocate
- * a buffer big enough to store all
- * port names.
- * ERROR_MORE_DATA - if some, but not all, PORTNAMES structs
- * could fit in buffer. Caller
- * uses *pcbRequired to allocate
- * a buffer big enough to store all
- * port names.
- *
- ****************************************************************************/
-
- APIRET APIENTRY SplPdEnumPort ( HAB hab,
- PVOID pBuf,
- ULONG cbBuf,
- PULONG pulReturned,
- PULONG pulTotal,
- PULONG pcbRequired )
-
- {
- /*
- ** ensure pointers not null
- */
- if (!pulReturned ||
- !pulTotal ||
- !pcbRequired)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
- /*
- ** if buffer length is supplied then there should be pBuf
- */
- if (!pBuf && cbBuf)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
- /*
- ** check if cbBuf is 0 - then return number of ports in pulTotal
- ** and number of bytes required in pcbRequired
- */
- if (cbBuf == 0L)
- {
- *pulReturned = 0;
- *pcbRequired = CalcBufLength ( hab );
- *pulTotal = 3 ; /* Currently support PAR1284 */
- /*
- ** NOTE: early version of the print object checked for
- ** ERROR_MORE_DATA instead of ERROR_INSUFFICIENT_BUFFER
- ** For this reason we return ERROR_MORE_DATA here.
- */
- return(ERROR_MORE_DATA);
- }
-
- /*
- ** check number of ports info we can fit in supplied buffer
- */
- *pulTotal = 3 ; /* Currently support PAR1284 */
- *pcbRequired = CalcBufLength ( hab );
- *pulReturned = NumPortsCanFit ( hab, cbBuf);
-
- /*
- ** return error if we can not fit one port.
- */
- if (!(*pulReturned))
- {
- return(ERROR_INSUFFICIENT_BUFFER);
- }
-
- /*
- ** copy all the ports which we can store in the pBuf
- */
- CopyNPorts (hab, (PCH)pBuf, *pulReturned);
-
- /*
- ** copy all the ports which we can store in the pBuf
- */
- if (*pulReturned < *pulTotal)
- {
- return(ERROR_MORE_DATA);
- }
-
- return(NO_ERROR);
- }
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdInstallPort
- *
- * DESCRIPTION = Install a new port for this port driver.
- *
- * The print object calls this when user selects to install
- * a new printer port. The portname given might be the
- * name from the "DEFAULT_PORT" extended attribute of
- * the port driver file, in which case this port driver
- * can generate a new port name to install.
- * If this port driver cannot find any printer it
- * can communicate with, it should return
- * ERROR_PRINT_CANCELLED to make sure the print object
- * does not put up "Port Installed" message.
- *
- * The print object will not call SplPdSetPort after
- * this. Each port driver has the option to
- * bring up their SplPdSetPort dialog during processing
- * of this call to allow users to select the printer
- * they wish to connect with(and possibly change the
- * name of the print port they are installing).
- *
- * INPUT = hab - Anchor block handle
- * pszPortName - name of port to be installed
- *
- * OUTPUT =
- *
- * RETURN-NORMAL = 0
- *
- * RETURN-ERROR = ERROR_INVALID_PARAMETER - if bad port name given
- * ERROR_PRINT_CANCELLED - port not installed
- *
- ****************************************************************************/
-
- APIRET APIENTRY SplPdInstallPort ( HAB hab,
- PSZ pszPortName )
- {
- CHAR chBuf[CCHMAXPATH];
- CHAR chPortDesc[STR_LEN_PORTDESC];
- PPORTDLGSTRUCT pPortDlgStruct;
- ULONG rc;
- BOOL fSuccess;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
- /*
- ** Check if port name string is NULL. This is an error.
- */
- if (!pszPortName)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
- /*
- ** Make Application name string "PM_Port Name"
- */
- strcpy (chBuf, APPNAME_LEAD_STR);
- strcat (chBuf, pszPortName);
-
- /*
- ** Check for this being our default Port Name to install
- ** If so(pszPortName == "LPT") then generate a unique
- ** port name so that we can install multiple IR printers.
- */
- if (!strcmp(pszPortName, DEF_PORTNAME))
- {
- /*
- ** Use chBuf to store the new portname to install
- ** Must first increment past "PM_" in chBuf
- */
- pszPortName = chBuf + 3;
- GenerateUniquePortName( pszPortName );
- }
-
- /*
- ** Check if we have description for port
- */
- if (!GetPortDescription (hab, pszPortName, chPortDesc))
- {
- /*
- ** Port description not found, use port name
- */
- strcpy( chPortDesc, pszPortName );
- }
-
- /*
- ** Write data for this port in ini file with new format.
- */
- PrfWriteProfileString (HINI_SYSTEMPROFILE,
- chBuf,
- KEY_DESCRIPTION,
- chPortDesc);
-
- PrfWriteProfileString (HINI_SYSTEMPROFILE,
- chBuf,
- KEY_TIMEOUT_QUERY,
- DEF_TIMEOUT_QUERY);
-
- PrfWriteProfileString (HINI_SYSTEMPROFILE,
- chBuf,
- KEY_TIMEOUT_JOB,
- DEF_TIMEOUT_JOB);
-
- PrfWriteProfileString (HINI_SYSTEMPROFILE,
- chBuf,
- KEY_PORTDRIVER,
- DEF_PORTDRIVER);
-
- /*
- ** Write data for this port in ini file with old format.
- ** This call will add pszPortName as a selectable port
- ** from the print object "Output Port" settings page.
- */
- fSuccess = PrfWriteProfileString (HINI_SYSTEMPROFILE,
- APPNAME_PM_SPOOLER_PORT,
- pszPortName,
- DEF_OLD_INITIALIZATION);
- if (!fSuccess)
- {
- /*
- ** Unable to add the new port
- */
- DBPRINTF ((logbuf, "SplPdInstallPort Unable to add PM_SPOOLER_PORT(%s)", pszPortName));
- return( ERROR_INVALID_PARAMETER );
- }
- /*
- ** rewrite portdriver connection - fix for old spooler
- */
- PrfWriteProfileString (HINI_SYSTEMPROFILE,
- chBuf,
- KEY_PORTDRIVER,
- DEF_PORTDRIVER);
-
- /*
- ** Now that the port has been added we can
- ** display the settings dialog to let the user
- ** select the settings for this printer port.
- **
- ** First allocate a port driver dialog structure
- */
- pPortDlgStruct = NULL;
- rc = DosAllocMem((PVOID)&pPortDlgStruct,
- sizeof(PORTDLGSTRUCT),
- PAG_READ | PAG_WRITE | PAG_COMMIT);
- if (rc)
- {
- DBPRINTF ((logbuf, "SplPdInstallPort DosAllocMem failed rc=%d",rc));
- return(rc);
- }
- /*
- ** Give user dialog to connect to a new printer
- */
- memset (pPortDlgStruct, 0, sizeof (PORTDLGSTRUCT));
- pPortDlgStruct->signature = PDLG_SIGNATURE;
- pPortDlgStruct->hAB = hab ;
- pPortDlgStruct->hModule = hPdrMod ;
- pPortDlgStruct->pszPortName = pszPortName ;
-
- /*
- ** Load the dialog for user to change.
- */
- OpenPar1284PortDlg (hab, pPortDlgStruct);
-
- DosFreeMem( pPortDlgStruct );
- DBPRINTF ((logbuf, "SplPdInstallPort Successful(%s)", pszPortName));
-
- return(NO_ERROR);
- }
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdGetPortIcon
- *
- * DESCRIPTION = Return Resource ID of icon representing this port.
- * Note: only one icon will represent all ports supported
- * by a port driver.
- *
- * INPUT = hab - Anchor block handle
- * idIcon - gets Resource ID of icon bit map
- *
- * OUTPUT =
- *
- * RETURN-NORMAL = TRUE
- *
- * RETURN-ERROR = FALSE - if unable to return icon Resource ID
- *
- ****************************************************************************/
-
- BOOL APIENTRY SplPdGetPortIcon ( HAB hab,
- PULONG idIcon )
- {
- /*
- ** Check for our global port icon ID(is always set)
- */
- if (idIcon)
- {
- *idIcon = PAR1284_ICON;
- }
- return(TRUE);
- }
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdQueryPort
- *
- * DESCRIPTION = Returns textual data that describes the port configuration.
- *
- * INPUT = hab - Anchor block handle
- * pszPortName - name of port to get configuration for
- * pBufIn - pointer to buffer of returned data structures
- * cbBuf - Size of pBufIn in bytes
- * cItems - Count of number of strings of descriptions
- * returned
- *
- * OUTPUT =
- *
- * RETURN-NORMAL = 0
- *
- * RETURN-ERROR = ERROR_INSUFFICIENT_BUFFER - if buffer is too small
- * ERROR_INVALID_PARAMETER - if bad port name given
- *
- ****************************************************************************/
-
- APIRET APIENTRY SplPdQueryPort ( HAB hab,
- PSZ pszPortName,
- PVOID pBufIn,
- ULONG cbBuf,
- PULONG cItems )
- {
- CHAR chString[STR_LEN_DESC];
- USHORT usNumLines;
- USHORT usLineID;
- USHORT usStrLength;
- PCH pBuf = (PCH)pBufIn;
-
- /*
- ** check pointer to all the return variables is not null
- */
- if (!cItems)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
- /*
- ** if pBuf or cbBuf is NULL - it is an error.
- */
- if (!pBuf || !cbBuf)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
- chString[0] = '\0' ;
-
- /*
- ** get number of lines.
- */
- WinLoadString(hab, hPdrMod, (USHORT)ID_NUMBER_OF_DESC_LINES, STR_LEN_DESC,
- chString);
- usNumLines = (USHORT)atoi (chString);
- usLineID = ID_FIRST_DESC_LINES;
- for (*cItems = 0; *cItems < usNumLines; *cItems++)
- {
- WinLoadString(hab, hPdrMod, usLineID, STR_LEN_DESC, chString);
- if (cbBuf >= (usStrLength = (USHORT)(strlen (chString) + 1)))
- {
- strcpy (pBuf, chString);
- pBuf += usStrLength;
- cbBuf -= usStrLength;
- }
- else
- {
- return(ERROR_INSUFFICIENT_BUFFER);
- }
- }
- return(NO_ERROR);
-
- }
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdRemovePort
- *
- * DESCRIPTION = Tells port driver the name of a port that needs to be removed.
- * Port driver should remove its data from the INI file.
- *
- * INPUT = hab - Anchor block handle
- * pszPortName - name of port to be removed
- *
- * OUTPUT =
- *
- * RETURN-NORMAL = 0
- *
- * RETURN-ERROR = ERROR_INVALID_PARAMETER - if bad port name given
- *
- ****************************************************************************/
-
- APIRET APIENTRY SplPdRemovePort ( HAB hab,
- PSZ pszPortName )
- {
- CHAR chBuf[STR_LEN_PORTNAME];
- CHAR chPortDriver[STR_LEN_PORTNAME];
- BOOL fSuccess;
- #ifdef DEBUG_ALERT
- CHAR logbuf[260];
- #endif
-
- /*
- ** Check if port name string is NULL. This is an error.
- */
- if (!pszPortName)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
- /*
- * Remove port from port list
- * Must free all threads waiting for this port @BUGBUG
- */
- EnterPdrSem();
- RemovePortInst ( pszPortName );
- LeavePdrSem();
-
- /*
- ** Make Application name string.
- */
- strcpy (chBuf, APPNAME_LEAD_STR);
- strcat (chBuf, pszPortName);
-
- /*
- ** Check if this port is PAR1284 port.
- */
- if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
- KEY_PORTDRIVER, NULL, chPortDriver,
- STR_LEN_PORTNAME)))
- {
- DBPRINTF ((logbuf, "SplPdRemovePort failed - no portdriver in INI(%s)", pszPortName));
- return(ERROR_INVALID_PARAMETER);
- }
-
- if (strcmp (chPortDriver, DEF_PORTDRIVER))
- {
- DBPRINTF ((logbuf, "SplPdRemovePort failed - wrong portdriver in INI(%s)", pszPortName));
- return(ERROR_INVALID_PARAMETER);
- }
-
- /*
- ** We found port to be removed.
- ** Remove INI entries for "PM_portname"
- */
- PrfWriteProfileString (HINI_SYSTEMPROFILE, chBuf, NULL, NULL);
-
- /*
- ** remove this port from selectable ports in the print object
- */
- fSuccess = PrfWriteProfileString (HINI_SYSTEMPROFILE,
- APPNAME_PM_SPOOLER_PORT,
- pszPortName,
- NULL);
- DBPRINTF ((logbuf, "SplPdRemovePort removing %s from INI fSuccess=%d", pszPortName, fSuccess));
-
- return(NO_ERROR);
-
- }
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdSetPort
- *
- * DESCRIPTION = Display a dialog to allow the user to browse and modify
- * port configurations.
- *
- * INPUT = hab - Anchor block handle
- * pszPortName - name of port to configure
- * flModified - Flag to indicate that the configuration
- * has been modified.(TRUE if modified).
- *
- * OUTPUT =
- *
- * RETURN-NORMAL = 0
- *
- * RETURN-ERROR = ERROR_INVALID_PARAMETER - if bad port name given
- *
- ****************************************************************************/
-
- APIRET APIENTRY SplPdSetPort ( HAB hab,
- PSZ pszPortName,
- PULONG flModified )
- {
- ULONG rc;
- PPORTDLGSTRUCT pPortDlgStruct;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
- /*
- ** Check if port name string is NULL. This is an error.
- */
- if (!pszPortName || !flModified)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
-
- /*
- ** First allocate a port driver dialog structure
- */
- pPortDlgStruct = NULL;
- rc = DosAllocMem((PVOID)&pPortDlgStruct,
- sizeof(PORTDLGSTRUCT),
- PAG_READ | PAG_WRITE | PAG_COMMIT);
- if (rc)
- {
- DBPRINTF ((logbuf, "SplPdSetPort DosAllocMem failed rc=%d",rc));
- return(rc);
- }
- /*
- ** Give user dialog to connect to a new printer
- */
- memset (pPortDlgStruct, 0, sizeof (PORTDLGSTRUCT));
- pPortDlgStruct->signature = PDLG_SIGNATURE;
- pPortDlgStruct->hAB = hab ;
- pPortDlgStruct->hModule = hPdrMod ;
- pPortDlgStruct->pszPortName = pszPortName ;
-
- /*
- ** Load the dialog for user to change.
- */
- *flModified = OpenPar1284PortDlg (hab, pPortDlgStruct);
-
- DosFreeMem( pPortDlgStruct );
- DBPRINTF ((logbuf, "SplPdSetPort flModified=%d(%s)", *flModified, pszPortName));
-
- return(NO_ERROR);
- }
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdRemoteSetPort
- *
- * DESCRIPTION = Display a dialog to allow the user to browse and modify
- * port configurations.
- *
- * INPUT = hab - Anchor block handle
- * pszComputerName - Name of print server being configured.
- * pszPortName - name of port to configure
- * flModified - Flag to indicate that the configuration
- * has been modified.(TRUE if modified).
- *
- * OUTPUT =
- *
- * RETURN-NORMAL = 0
- *
- * RETURN-ERROR = ERROR_INVALID_PARAMETER - if bad port name given
- *
- ****************************************************************************/
-
- #ifdef BIDI
-
- APIRET APIENTRY SplPdRemoteSetPort ( HAB hab,
- PSZ pszComputerName,
- PSZ pszPortName,
- PULONG flModified )
- {
-
- ULONG rc;
- PPORTDLGSTRUCT pPortDlgStruct;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
- /*
- ** Check if port name string is NULL. This is an error.
- */
- if (!pszComputerName || !pszPortName || !flModified)
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
-
- /*
- ** First allocate a port driver dialog structure
- */
- pPortDlgStruct = NULL;
- rc = DosAllocMem((PVOID)&pPortDlgStruct,
- sizeof(PORTDLGSTRUCT),
- PAG_READ | PAG_WRITE | PAG_COMMIT);
- if (rc)
- {
- DBPRINTF ((logbuf, "SplPdRemoteSetPort DosAllocMem failed rc=%d",rc));
- return(rc);
- }
- /*
- ** Give user dialog to connect to a new printer
- */
- memset (pPortDlgStruct, 0, sizeof (PORTDLGSTRUCT));
- pPortDlgStruct->signature = PDLG_SIGNATURE;
- pPortDlgStruct->hAB = hab ;
- pPortDlgStruct->hModule = hPdrMod ;
- pPortDlgStruct->pszPortName = pszPortName ;
- pPortDlgStruct->pszComputerName = pszComputerName ;
-
- /*
- ** Load the dialog for user to change.
- */
- *flModified = OpenPar1284PortDlg (hab, pPortDlgStruct);
-
- DosFreeMem( pPortDlgStruct );
- DBPRINTF ((logbuf, "SplPdRemoteSetPort flModified=%d(%s on %s)", *flModified, pszPortName, pszComputerName));
-
- return(NO_ERROR);
-
- }
- #endif // ifdef BIDI
-
-
-
- /*
- ** SPLPD functions that can only be called by the spooler process
- */
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdOpen - EXTERNAL API
- *
- * DESCRIPTION = Open a print port for output.
- *
- *
- *
- * INPUT = pszPortName - name of port to open
- * phDevice - gets port driver handle
- * pDeviceFlags - gets device type being opened
- *
- * HANDTYPE_FILE 0x0000
- * HANDTYPE_DEVICE 0x0001
- * HANDTYPE_PIPE 0x0002
- * HANDTYPE_LPTDEVICE 0x0004
- * HANDTYPE_COMDEVICE 0x0008
- * HANDTYPE_PROTECTED 0x4000
- * HANDTYPE_NETWORK 0x8000
- *
- * pPrtOpenStruct - spooler parameter structure for PrtOpen
- *
- * OUTPUT = 0 - successful.
- * This device cannot be opened again until SplPdClose()
- * is called.
- *
- * *phDevice = port driver handle to be used with
- * SplPdWrite/SplPdAbortDoc/SplPdClose...
- * *pDeviceFlags = device handle flags
- *
- * Other - error code, port not opened.
- *
- ****************************************************************************/
-
- ULONG APIENTRY SplPdOpen( PSZ pszPortName,
- PHFILE phFile,
- PULONG pDeviceFlags,
- PVOID pPrtOpenStruct)
- {
- ULONG rc;
- ULONG cb;
- PPORTINST pPortInst;
- PPDOPENINST pPdOpenInstance;
- PRTSTARTJOB PrtStartJob;
- PPRTOPENSTRUCT0 pPrtOpenStruct0;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
-
- /*
- * Check for valid pointers
- */
- if (!phFile || !pDeviceFlags )
- {
- return(ERROR_INVALID_PARAMETER);
- }
-
- *phFile = NULLHANDLE;
- pPdOpenInstance = NULL;
- pPortInst = NULL;
- rc = 0;
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDOPEN))
- {
- sprintf( logbuf,
- "SplPdOpen on %s\r\n",
- pszPortName);
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- cb = sizeof(PDOPENINST) + strlen(pszPortName) + 1 ;
- EnterPdrSem();
- /*
- ** Add port to list.
- ** If added previously, get pointer to structure.
- ** If not yet opened, open the port
- */
- pPortInst = AddPortInst ( pszPortName );
-
- /*
- ** Set TimeLastCmd so that we don't close this
- ** port from our ControlThread
- */
- if (pPortInst) {
- pPortInst->ulTimeLastCmd = time();
- }
-
- if (pPortInst && !(pPortInst->flStatus & PF_PORT_OPEN))
- {
- rc = PdOpen(pPortInst);
- }
- if (!rc)
- {
- pPdOpenInstance = (PPDOPENINST) AllocPdrMem( cb );
- }
-
- LeavePdrSem();
- if (!rc && !pPdOpenInstance)
- {
- rc = ERROR_NOT_ENOUGH_MEMORY;
- }
-
- if (!rc)
- {
- /*
- ** init instance struct
- */
- memset( pPdOpenInstance, 0, sizeof(PDOPENINST) );
- pPdOpenInstance->signature = PD_SIGNATURE ;
- pPdOpenInstance->cb = cb ;
- pPdOpenInstance->pNext = NULL;
- pPdOpenInstance->pPortInst = pPortInst;
- pPdOpenInstance->pszPortName = (PSZ)(pPdOpenInstance+1);
- strcpy( pPdOpenInstance->pszPortName, pszPortName);
- /*
- * Add this pdopen instance to this driver's list
- */
- EnterPdrSem();
- rc = AddPdOpenInst( pPdOpenInstance );
- LeavePdrSem();
- if (!rc)
- {
- *phFile = (HFILE)( pPdOpenInstance );
- *pDeviceFlags = HANDTYPE_DEVICE;
- }
- }
-
- if (!rc)
- {
- /*
- ** Send start job command
- */
- #ifdef BIDI
- pPrtOpenStruct0 = (PPRTOPENSTRUCT0)pPrtOpenStruct;
- if (pPrtOpenStruct0) {
- PrtStartJob.ulSpoolerJobID = pPrtOpenStruct0->ulSpoolerJobID ;
- PrtStartJob.ulInterpreterID = pPrtOpenStruct0->ulLogicalUnit ;
- PrtStartJob.ulStartPage = pPrtOpenStruct0->ulStartPage ;
- PrtStartJob.ulEndPage = pPrtOpenStruct0->ulEndPage ;
- } else {
- PrtStartJob.ulSpoolerJobID = (ULONG)-1;
- PrtStartJob.ulInterpreterID = (ULONG)-1;
- PrtStartJob.ulStartPage = 0;
- PrtStartJob.ulEndPage = 0;
- }
-
- rc = MyPrtSet ( NULL, pszPortName, TYPE_LONG_WAIT, BIDI_STARTJOB,
- &PrtStartJob, sizeof(PrtStartJob));
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDOPEN))
- {
- sprintf( logbuf,
- "SplPdOpen PrtSet(BIDI_STARTJOB) rc=%d\r\n",
- rc);
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
- if ( (rc == ERROR_NOT_SUPPORTED) || (rc == ERROR_TIMEOUT) )
- {
- /*
- * You will receive ERROR_NOT_SUPPORTED from BIDI_STARTJOB
- * if there is no protocol converter.
- * You also could receive ERROR_TIMEOUT if the converter
- * is not working properly.
- */
- rc = 0;
- }
- #endif
- /*
- ** Set JOB_PRINTING flag AFTER sending STARTJOB to allow sending
- ** the BIDI_STARTJOB sequence, and avoid sending query data
- ** while sending a job.
- */
- if (!rc) {
- EnterPdrSem();
- pPortInst->ulJobPrinting = PDR_PRINTING;
- LeavePdrSem();
- }
-
- } /* end if pPdOpenInstance created OK */
-
- if (rc) {
- /*
- ** Error occurred initializing the port
- */
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDOPEN))
- {
- sprintf( logbuf,
- "SplPdOpen failed, freeing pdOpenInst=%lX\r\n",
- (ULONG)pPdOpenInstance);
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
- EnterPdrSem();
- if (pPortInst && !(pPortInst->flStatus & PF_Q_PORT_CALLED))
- {
- /*
- ** We close connection at end of each job ONLY if
- ** bidi is not enabled(never received BIDI_Q_PORT)
- */
- PdClose( pPortInst );
- }
- if (pPdOpenInstance) {
- /*
- ** Free PdInstance if open fails
- */
- RemovePdOpenInst ( pPdOpenInstance );
- FreePdrMem( (PVOID)pPdOpenInstance , pPdOpenInstance->cb );
- }
- LeavePdrSem();
- *phFile = NULLHANDLE;
- }
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDOPEN))
- {
- sprintf( logbuf,
- "SplPdOpen on %s rc=%d hFile=%lX\r\n",
- pszPortName, rc, *phFile);
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- return(rc);
- }
-
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdWrite - EXTERNAL API
- *
- * DESCRIPTION = Write data to a printer port opened with SplPdOpen()
- *
- * INPUT = hDevice - handle from SplPdOpen
- * pchData - ptr to data buffer to write
- * cbData - length of data in bytes
- * pcbWritten - gets count of bytes actually written
- *
- * OUTPUT = 0 - successful.
- * *pcbWritten must be checked to ensure cbData bytes
- * have been written.
- * Possible to get 0 rc and 0 bytes written.
- *
- *
- * Other - error code, write failed
- * *pcbWritten contains number of bytes successfully
- * written.
- *
- * NOTES Not in port driver semaphore on entry/exit
- * Data may be buffered; PrtClose must send any buffered data.
- *
- ****************************************************************************/
-
- ULONG APIENTRY SplPdWrite( HFILE hFile,
- PVOID pchData,
- ULONG cbData,
- PULONG pcbWritten )
- {
- ULONG rc;
- PPORTINST pPortInst;
- PPDOPENINST pPdOpenInstance ;
- ULONG ulPortTimeout ; /* timeout for this port */
- ULONG cbWritten ; /* bytes written to port so far */
- ULONG ulTime ; /* time prior to issuing DosWrite call */
- BOOL fMustCheckDevID; /* TRUE = call GetDeviceID */
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
- #ifdef DEBUG_ALERT
- {
- if (flChangeDebugLog & FL_PDRDB_ENABLE_SPLPDWRITE)
- {
- sprintf( logbuf,
- "SplPdWrite hFile=%lX pBuf=%lX cb=%d\r\n",
- hFile, (ULONG)pchData, cbData );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- /*
- * Validate file handle
- */
- if (!(pPdOpenInstance = ValidatePdOpenInst((PPDOPENINST)hFile)) ) {
- return(ERROR_INVALID_HANDLE);
- }
-
- /*
- * Get port structure,
- */
- pPortInst = pPdOpenInstance->pPortInst;
-
- if (!(pPortInst) ) {
- return(ERROR_INVALID_HANDLE);
- }
-
- if ( (pPortInst->ulCurrentMode <= CURMODE_COMPATIBLE) &&
- !(pPortInst->flStatus & PF_BIDI_CHECKED) &&
- (pPortInst->ulModeSelected != PARMODE_DISABLE_BIDI) ) {
- /*
- ** If this write is successful
- ** then we should try to query the deviceID for the printer.
- ** This is done in case the printer was not powered on
- ** when we initially tried to get the device ID from it.
- ** The result(if a bidi printer was powered off but is
- ** on when the first job is sent) is that the first job
- ** is printed in unidirectional mode, an alert is sent
- ** (PRTALERT_TYPE_COMM_STATUS_CHANGED) which causes the
- ** spooler to re-init the printer after the current job
- ** completes. This will put the software into bidi mode.
- */
- fMustCheckDevID = TRUE;
- } else {
- fMustCheckDevID = FALSE;
- }
- /*
- * Save time prior to issuing DosWrite
- * If write fails before printer timeout expired
- * retry the request.
- * This allows us to set shorter timeout with the
- * device driver
- */
- ulTime = time() ;
- *pcbWritten = 0 ; /* init bytes written to zero */
- //
- // Get write mutex sem
- //
- rc = DosRequestMutexSem ( pPortInst->hPortSem, SEM_INDEFINITE_WAIT );
- while (pPortInst->fMoreCmds) {
- /*
- ** We were in the process of sending multiple
- ** queries to the printer.
- ** Hold off the print job until the query commands
- ** have been sent.
- */
- rc = DosReleaseMutexSem ( pPortInst->hPortSem );
- DosSleep(500);
- rc = DosRequestMutexSem ( pPortInst->hPortSem, SEM_INDEFINITE_WAIT );
- }
-
- rc = PdWrite(pPortInst, pchData, cbData, pcbWritten);
-
- if (rc || (*pcbWritten != cbData) ) {
- /*
- * Check time it took to issue write
- * If this is a known port
- * there is a timeout for the port
- * and the time it took to do the write was
- * less than (PortTimeout - 1)
- * then
- * Retry Request
- *
- * If the job was aborted, ulJobPrinting would be reset.
- */
- if ( (pPdOpenInstance->signature == PD_SIGNATURE) &&
- (ulPortTimeout = pPortInst->ulPrintTimeOut) &&
- ( (time() - ulTime) < (ulPortTimeout - 1) )) {
-
- /*
- * Keep track of total bytes written
- * Reset clock if DosWrite succeeded without writting all bytes
- * Retry request
- */
- cbWritten = *pcbWritten ;
- do
- {
- if ( (rc == 0) && (*pcbWritten) ) {
- /*
- * if DosWrite successful and bytes were written
- * reset timeout value
- */
- ulTime = time() ;
- }
-
- /*
- ** Some printers allow query commands to be sent
- ** while still sending the print job.
- ** Here we release the mutex Write semaphore to allow
- ** the protocol converter to issue a query to the
- ** printer.
- ** It is up to the protocol converter to ensure @BUGBUG
- ** the printer can accept the query command in
- ** the middle of a print job.
- */
- rc = DosReleaseMutexSem ( pPortInst->hPortSem );
- /* Sleep one second to avoid hard loop on DosWrite */
- DosSleep(1000) ;
- rc = DosRequestMutexSem ( pPortInst->hPortSem, SEM_INDEFINITE_WAIT );
-
- *pcbWritten = 0 ; /* reset bytes written */
-
- /*
- * Write buffer, taking into account bytes written so far
- */
- rc = PdWrite( pPortInst,
- (PVOID)((PBYTE)pchData + cbWritten),
- /* index past bytes written */
- cbData - cbWritten,/* only write remaining data */
- pcbWritten);
-
- cbWritten += *pcbWritten ;
-
- } while ( (cbWritten < cbData) &&
- (pPortInst->ulJobPrinting == PDR_PRINTING) &&
- ( (time() - ulTime) < (ulPortTimeout - 1) )) ;
-
- /* return actual bytes written */
- *pcbWritten = cbWritten ;
- }
-
- } /* end giving retry */
-
- //
- // Give up write sem
- //
- rc = DosReleaseMutexSem ( pPortInst->hPortSem );
-
- if (pPortInst->flJob & PRTSW_JOB_WRAPPER_REQUIRED) {
- /*
- ** This printer gets a bidi wrapper put around all data writes.
- ** Wakeup ParReadThread so we can get the acknowledgement @BUGBUG
- ** to the buffer we just sent, because some printers(NPAP)
- ** might reject data buffers when the printer is busy.
- ** The CNV waits for an ack that the printer accepted the
- ** data buffer before sending the next data buffer.
- **
- ** Later we should allow PROTCNV to tell us whether we should
- ** expect an Ack for data writes(dynamically set the state
- ** using PrtSet).
- */
- DosPostEventSem(pPortInst->hevReadThread);
- }
-
- #ifdef DEBUG_ALERT
- {
- if (flChangeDebugLog & FL_PDRDB_ENABLE_SPLPDWRITE)
- {
- sprintf( logbuf,
- "SplPdWrite rc=%d cbWritten=%d\r\n",
- rc, *pcbWritten );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
- /*
- ** If anything was written to the printer for the first time
- ** then try to get the printer's device ID.
- */
- if ( fMustCheckDevID && (*pcbWritten > 1) ) {
- RecheckDevID( pPortInst );
- }
-
- return(rc);
-
- }
-
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdAbortDoc - EXTERNAL API
- *
- * DESCRIPTION = Flush all current write requests for a h SplPdOpen()
- *
- * INPUT = hDevice - handle from SplPdOpen
- * pchData - ptr to data buffer to write
- * cbData - length of data in bytes
- * ulFlags - abort processing flags
- *
- * OUTPUT = 0 - successful.
- *
- * Other - error code, write failed
- * *pcbWritten contains number of bytes successfully
- * written.
- *
- * NOTES This currently does not buffer any write requests,
- * so there are no buffers to flush.
- *
- ****************************************************************************/
-
- ULONG APIENTRY SplPdAbortDoc( HFILE hFile,
- PVOID pchData,
- ULONG cbData,
- ULONG ulFlags )
- {
- ULONG rc;
- ULONG ulJobPrinting;
- ULONG cbWritten;
- PPORTINST pPortInst;
- PPDOPENINST pPdOpenInstance ;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDABORT))
- {
- sprintf( logbuf,
- "SplPdAbortDoc hFile=%lX pBuf=%lX cb=%d Flags=%lX\r\n",
- hFile, (ULONG)pchData, cbData, ulFlags );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- rc = 0 ;
- cbWritten = 0;
-
- /*
- * Validate file handle
- */
- if (!(pPdOpenInstance = ValidatePdOpenInst((PPDOPENINST)hFile)) ) {
- return(ERROR_INVALID_HANDLE);
- }
- /*
- * Get port structure
- */
- pPortInst = pPdOpenInstance->pPortInst;
-
- if (!(pPortInst) ) {
- return(ERROR_INVALID_HANDLE);
- }
-
- /*
- * Issue FLUSH IOCtl to clear any data in PAR1284 kernel device driver
- *
- * Note: It is possible that data other than for this job could
- * be flushed since the kernel device driver does not
- * keep track of job boundaries, therefore the flush IOCtl
- * is not sent!
- */
-
- /*
- * If any reset data, send it after flushing our buffers
- */
- if (cbData) {
- rc = PdWrite(pPortInst, pchData, cbData, &cbWritten);
- }
- /*
- * Reset flag indicating job aborted
- */
- EnterPdrSem();
- ulJobPrinting = pPortInst->ulJobPrinting;
- pPortInst->ulJobPrinting = PDR_ABORTED;
- LeavePdrSem();
- /*
- * Only release semaphore if needed
- */
- if (ulJobPrinting == PDR_PRINTING) {
- rc = DosReleaseMutexSem ( pPortInst->hPortSem );
- }
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDABORT))
- {
- sprintf( logbuf,
- "SplPdAbortDoc rc=%d cbWritten=%d\r\n",
- rc, cbWritten );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- return(rc);
- }
-
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdNewPage - EXTERNAL API
- *
- * DESCRIPTION = notify port driver that another print page is being sent to
- * the printer
- *
- *
- * INPUT = hDevice - handle from SplPdOpen
- * ulPageNumber - page number to be sent next
- * Starts with page 1
- *
- * OUTPUT = 0 - successful.
- * Valid hDevice, spooler updated job with page number
- *
- * ERROR_INVALID_HANDLE - invalid hDevice given
- *
- * Other - failure from port driver.
- *
- ****************************************************************************/
-
- ULONG APIENTRY SplPdNewPage ( HFILE hFile, ULONG ulPageNumber )
- {
-
- /*
- * Validate file handle
- */
- if (!(ValidatePdOpenInst((PPDOPENINST)hFile)) ) {
- return(ERROR_INVALID_HANDLE);
- }
-
- /*
- * Spooler sets job "Sent to printer" pij->page number.
- * This port driver does not use pagessent value.
- */
-
- return 0;
- }
-
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdClose - EXTERNAL API
- *
- * DESCRIPTION = close a printer device opened with SplPdOpen
- *
- *
- *
- * INPUT = hDevice - handle from SplPdOpen
- *
- * OUTPUT = 0 - successful.
- * SplPdOpen handle freed; the port may be opened again
- * with SplPdOpen()
- *
- * Other - error code, close failed.
- * If not ERROR_INVALID_HANDLE then caller should
- * reissue SplPdClose().
- *
- * NOTES: If SplPdWrite data buffered, this outputs data before closing.
- * If error outputting data, issue SplMessageBox(and retry)
- *
- ****************************************************************************/
-
- ULONG APIENTRY SplPdClose( HFILE hFile )
- {
- ULONG rc;
- ULONG ulJobPrinting;
- PPDOPENINST pPdOpenInstance ;
- PPORTINST pPortInst;
- PRTJOB PrtJob;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDOPEN))
- {
- sprintf( logbuf,
- "SplPdClose hFile=%lX\r\n",
- hFile);
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- /*
- * Validate file handle
- */
- if (!(pPdOpenInstance = ValidatePdOpenInst((PPDOPENINST)hFile)) ) {
- return(ERROR_INVALID_HANDLE);
- }
-
- /*
- * Reset flag indicating no job printing
- */
- EnterPdrSem();
- pPortInst = pPdOpenInstance->pPortInst;
- if (!(pPortInst) || (pPortInst->signature != PT_SIGNATURE) ) {
- rc = ERROR_FILE_NOT_FOUND;
- pPortInst = NULL;
- } else {
- /*
- ** Clear JOB_PRINTING flag BEFORE sending ENDJOB to allow sending
- ** the BIDI_ENDJOB sequence.
- */
- ulJobPrinting = pPortInst->ulJobPrinting;
- pPortInst->ulTimeLastJob = time();
- pPortInst->ulJobPrinting = PDR_NOT_PRINTING;
- /*
- * Only release semaphore if needed
- */
- if (ulJobPrinting == PDR_PRINTING) {
- rc = DosReleaseMutexSem ( pPortInst->hPortSem );
- }
- }
-
- if (pPortInst && !(pPortInst->flStatus & PF_Q_PORT_CALLED))
- {
- /*
- ** We close connection at end of each job ONLY if
- ** bidi is not enabled(never received BIDI_Q_PORT)
- */
- PdClose( pPortInst );
- }
- /*
- * if DosClose fails @BUGBUG
- * for now return 0 and assume the port can be reopened
- */
- if (rc) {
- rc = 0;
- }
-
- /*
- * Send end job command
- */
- #ifdef BIDI
-
- if (pPortInst && (pPortInst->flStatus & PF_Q_PORT_CALLED)) {
- PrtJob.ulInterpreterID = (ULONG)-1;
- PrtJob.ulPrinterJobID = (ULONG)-1;
- LeavePdrSem();
- rc = MyPrtSet ( NULL, pPdOpenInstance->pszPortName, TYPE_LONG_WAIT, BIDI_ENDJOB,
- &PrtJob, sizeof(PRTJOB));
- EnterPdrSem();
- /*
- * Reset rc to 0 even if BIDI_ENDJOB doesn't work
- */
- rc = 0;
- }
- #endif
-
- RemovePdOpenInst ( pPdOpenInstance );
-
- FreePdrMem( (PVOID)pPdOpenInstance , pPdOpenInstance->cb );
- LeavePdrSem();
-
- DosPostEventSem( hevControl );
-
- return rc;
- }
-
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdQuery - EXTERNAL API
- *
- * DESCRIPTION = Query information about a print device
- *
- * INPUT = pszDeviceName - name of port printer is attached
- * ulFlags - query options
- * ulCommand - function code for query
- * pInData - command specific input data
- * cbInData - length in bytes of pInData
- * pOutData - returned query structure, format depends
- * on ulCommand
- * pcbOutData - Points to length of pOutData(in bytes)
- * On entry this is set to length of buffer
- * passed in.
- * On exit this is updated with the length
- * of available data, which may be more
- * than put into pOutData
- *
- * OUTPUT = 0 - successful.
- * *pcbOutData = length of data returned by query
- * pOutData = query structure
- * 234(ERROR_MORE_DATA) - partial query structure returned
- * *pcbOutData = length of buffer required to store
- * entire query structure
- * pOutData = partial query structure
- * 2123(NERR_BufTooSmall) - buffer too small to fit any data
- * *pcbOutData = length of buffer required to store
- * entire query structure
- * pOutData = not updated, since it is much too small
- * Other - error code, nothing updated
- *
- *
- *
- * NOTE Not in port driver semaphore on entry/exit
- *
- ****************************************************************************/
-
-
- ULONG APIENTRY SplPdQuery ( PSZ pszDeviceName,
- ULONG ulFlags,
- ULONG ulCommand,
- PVOID pInData,
- ULONG cbInData,
- PVOID pOutData,
- PULONG pcbOutData )
- {
- ULONG rc;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
- #ifdef DEBUG_ALERT
- {
- PULONG pul;
- pul = (PULONG)pInData;
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDQUERY))
- {
- sprintf( logbuf,
- "SplPdQuery on %s Flags=%lX Cmd=%lX cb=%d Data=%lX %lX\r\n",
- pszDeviceName, ulFlags, ulCommand, cbInData,
- (cbInData >= 4) ? pul[0]:0,
- (cbInData >= 8) ? pul[1]:0
- );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- rc = 0;
-
- #ifdef BIDI
- switch (ulCommand) {
- case BIDI_Q_PORT:
- /*
- * Add port to the list of supported ports and return
- * the status of the PAR1284 connected printer.
- */
- rc = HandleQPort( pszDeviceName,
- ulFlags,
- pOutData,
- pcbOutData );
- break;
-
- case BIDI_WAIT_ALERT:
- /*
- * Read alert, waiting if necessary ( Assume what is returned from
- * the PAR1284 kernel driver is complete )
- */
- rc = HandleWaitAlert( pszDeviceName,
- ulFlags,
- ulCommand,
- pInData,
- cbInData,
- pOutData,
- pcbOutData );
- break;
-
- case BIDI_Q_PORTDRV:
- /*
- * Check for valid data
- */
- if (!pOutData || !pcbOutData ) {
- return(ERROR_INVALID_PARAMETER);
- }
- /*
- * Send back PORTSETTINGS structure
- */
- rc = HandleQPortDRV ( pszDeviceName,
- pOutData,
- pcbOutData );
- break;
-
- case BIDI_READ_PASSTHRU:
- /*
- * An application wants to read passthru data from the printer and there
- * is no protocol converter used on this port(CNV would get called
- * with this command instead of the port driver).
- */
- rc = ReadPassthru ( pszDeviceName,
- ulFlags,
- ulCommand,
- pInData,
- cbInData,
- pOutData,
- pcbOutData );
- break;
-
-
- default:
- /*
- ** Let protocol converter handle all other queries.
- */
- rc = MySplProtSendCmd ( pszDeviceName,
- ulFlags,
- ulCommand,
- (PFN) SplPdSendCmd,
- (PFN) NULL,
- pInData,
- cbInData,
- pOutData,
- pcbOutData );
- }
- #else
- rc = ERROR_NOT_SUPPORTED;
- #endif // ifdef BIDI
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDQUERY))
- {
- sprintf( logbuf,
- "SplPdQuery on %s rc=%d\r\n",
- pszDeviceName,
- rc );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- return(rc);
- }
-
-
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdSet - EXTERNAL API
- *
- * DESCRIPTION = Set printer device information
- *
- * INPUT = pszDeviceName - name of port printer is attached
- * ulFlags - set options
- * ulCommand - function code for set command
- * pInData - command specific input data
- * cbInData - length in bytes of pInData
- *
- * OUTPUT = 0 - successful.
- * Other - error code
- *
- * NOTE Not in port driver semaphore on entry/exit
- *
- ****************************************************************************/
- ULONG APIENTRY SplPdSet ( PSZ pszDeviceName,
- ULONG ulFlags,
- ULONG ulCommand,
- PVOID pInData,
- ULONG cbInData )
- {
- ULONG rc = 0;
- PPORTINST pPortInst = NULL;
- PPRTSW pPrtSw;
- ULONG ulcbOutBuf;
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
- #ifdef DEBUG_ALERT
- {
- PULONG pul;
- pul = (PULONG)pInData;
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDSET))
- {
- sprintf( logbuf,
- "SplPdSet on %s Flags=%lX Cmd=%lX cb=%d Data=%lX %lX\r\n",
- pszDeviceName, ulFlags, ulCommand, cbInData,
- (cbInData >= 4) ? pul[0]:0,
- (cbInData >= 8) ? pul[1]:0
- );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- /*
- * Check for valid set command
- */
- if (ulCommand >= BIDI_READ_PASSTHRU) {
- return(ERROR_INVALID_FUNCTION);
- }
- rc = 0;
- pPortInst = NULL;
-
- switch (ulCommand) {
- case BIDI_INIT_PORTDRV:
- /*
- * Create thread to control all LPT ports.
- * Move DllInit mem init routine here @BUGBUG
- */
- CreateControlThread();
- break;
-
- #ifdef BIDI
-
- case BIDI_RESET:
- //
- // Reset printer - done by protocol converter
- //
- break;
- case BIDI_SHUTDOWN:
- /*
- ** Wake up control thread to begin termination
- */
- fShutdownInProgress = TRUE;
- DosPostEventSem(hevControl);
- /*
- ** This should wait until all threads are shutdown
- ** because the spooler process will terminate when
- ** this returns.
- ** If this does not return within 25 seconds, the spooler
- ** process will terminate anyway without letting us
- ** complete our shutdown.
- */
- break;
- case BIDI_INIT:
- //
- // Change printer from Uni to Bidirectional - currently not needed
- //
- break;
- case BIDI_TERM:
- //
- // Change printer from Bidirectional to Uni - currently not needed
- //
- break;
- case BIDI_RESPONSE_FMT:
- /*
- * Set format of printer-to-host response = currently not used
- */
- break;
- case BIDI_PACKET_SIZE:
- /*
- * Set printer-to-host max packet size = currently not used
- */
- break;
- case BIDI_SET_SW:
- /*
- * Gives software capabilities of attached bidi printer
- */
- if (!pInData || cbInData < sizeof(PRTSW)) {
- return(ERROR_INVALID_PARAMETER);
- }
- /*
- * Find port instance
- */
- EnterPdrSem();
- pPortInst = FindPortInst ( pszDeviceName );
- if (pPortInst) {
- /*
- * Set Port Driver variables
- */
- pPrtSw = (PPRTSW) pInData;
- pPortInst->flJob = pPrtSw->flJob;
- pPortInst->flDevice = pPrtSw->flDevice;
- } else {
- rc = ERROR_FILE_NOT_FOUND;
- }
- LeavePdrSem();
- break;
-
- case BIDI_SET_PORTDRV:
- /*
- * Save port settings
- */
- if (!pInData || cbInData < sizeof(PPORTSETTINGS)) {
- return(ERROR_INVALID_PARAMETER);
- }
- /*
- * Save PORTSETTINGS structure
- */
- rc = HandleSetPortDRV ( pszDeviceName,
- pInData,
- cbInData );
- break;
-
- case BIDI_NOTIFY_ENDJOBCONNECT:
- /*
- * Spooler no longer waiting for any job confirmations from port
- * This could be used to drop a job-based connection quicker
- * than the timeouts used in ControlThread.
- */
- break;
- case BIDI_NOTIFY_PORT_SELECTED:
- /*
- * Spooler tells port driver that this port is connected to a print queue
- * We could pay more attention to this output port than
- * one not connected to a print queue.
- */
- break;
- case BIDI_NOTIFY_PORT_RELEASED:
- /*
- * Spooler tells port driver this port is no longer connected
- * to a print queue. We could pay less attention to this
- * output port now that it is not connected to a queue.
- */
- break;
- case BIDI_ADD_VIRTUAL_PORT:
- /*
- * An application requested a virtual port to get information from
- * this port driver. This is useful if an App wants the
- * port driver to enumerate or find printers on the network wire.
- * The buffer passed in is port-driver specific.
- * The PAR1284 port driver does not support this.
- */
- rc = ERROR_NOT_SUPPORTED;
- break;
- case BIDI_DEL_VIRTUAL_PORT:
- /*
- * An application wants to delete a virtual port it has previously
- * created. This is done in response to SplDeletePort() for
- * a virtual port.
- * The PAR1284 port driver does not support virtual ports.
- */
- rc = ERROR_NOT_SUPPORTED;
- case BIDI_DEL_PORT:
- /*
- * A port belonging to this port driver was removed from the System INI.
- * It may have been this port driver that removed it( SplPdRemovePort ).
- * We can free our instance data for this port now.
- * Be certain that any reference to the PORTINST structures
- * allow for deleting a PORTINST.
- * Since we only support LPT1-3, we don't actually remove any
- * port from our instance list.
- */
- break;
-
-
- case BIDI_START_PASSTHRU:
- /*
- * An application wants a passthru session and there is no
- * protocol converter used on this port(CNV would get called
- * with this command instead of the port driver).
- */
- rc = StartPassthru( pszDeviceName,
- ulFlags,
- ulCommand,
- pInData,
- cbInData );
- break;
-
- case BIDI_SEND_PASSTHRU:
- /*
- * An application wants to send passthru data to the printer and there
- * is no protocol converter used on this port(CNV would get called
- * with this command instead of the port driver).
- */
- rc = SendPassthru( pszDeviceName,
- ulFlags,
- ulCommand,
- pInData,
- cbInData );
- break;
-
- case BIDI_END_PASSTHRU:
- /*
- * An application wants to end a passthru session with the printer and
- * there is no protocol converter used on this port(CNV would get
- * called with this command instead of the port driver).
- */
- rc = EndPassthru( pszDeviceName,
- ulFlags,
- ulCommand,
- pInData,
- cbInData );
- break;
-
-
- #endif // #ifdef BIDI
- default:
- #ifdef BIDI
- /*
- ** Let protocol converter handle any other set command
- */
- ulcbOutBuf = 0;
- rc = MySplProtSendCmd ( pszDeviceName,
- ulFlags,
- ulCommand,
- (PFN) SplPdSendCmd,
- (PFN) NULL,
- pInData,
- cbInData,
- NULL,
- &ulcbOutBuf );
- #else
- rc = ERROR_NOT_SUPPORTED;
- #endif // #ifdef BIDI
- }
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDSET))
- {
- sprintf( logbuf,
- "SplPdSet on %s rc=%d\r\n",
- pszDeviceName,
- rc );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- return(rc);
- }
-
-
-
- /****************************************************************************
- *
- * FUNCTION NAME = SplPdSendCmd - EXTERNAL API
- *
- * DESCRIPTION = Send protocol specific commands to the printer
- *
- *
- * INPUT = pszDeviceName - name of port printer is attached
- * ulFlags - query/set options
- * Only channel currently for the PAR1284 port is data
- * ulCommand - function code for query/set
- * pInData - command specific input data
- * cbInData - length in bytes of pInData
- *
- * OUTPUT = 0 - successful.
- * Other - error code, nothing updated
- *
- * NOTE Not in port driver semaphore on entry/exit
- * If cbInData is 0, just check ulCommand value
- *
- ****************************************************************************/
-
- #ifdef BIDI
-
- ULONG APIENTRY SplPdSendCmd( PSZ pszDeviceName,
- ULONG ulFlags,
- ULONG ulCommand,
- PVOID pInData,
- ULONG cbInData )
- {
- ULONG rc;
- PPORTINST pPortInst;
- PBYTE pBufToSend; /* -> buffer to give to PdWrite */
- ULONG cbWritten;
- ULONG cbWrite;
- ULONG ulPortTimeout ; /* timeout for this port */
- ULONG ulTime ; /* time prior to issuing DosWrite call */
- #ifdef DEBUG_ALERT
- char logbuf[260];
- #endif
-
-
-
- #ifdef DEBUG_ALERT
- {
- PULONG pul;
- pul = (PULONG)pInData;
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDSENDCMD))
- {
- sprintf( logbuf,
- "SplPdSendCmd on %s Flags=%lX Cmd=%lX cb=%d Data=%lX %lX\r\n",
- pszDeviceName, ulFlags, ulCommand, cbInData,
- (cbInData >= 4) ? pul[0]:0,
- (cbInData >= 8) ? pul[1]:0
- );
- LogCall( logbuf );
- /*
- * Dump out the Bidi commands we are going to send to
- * the printer when in debug mode
- */
- DumpHex( (PBYTE)pInData, cbInData );
- }
- }
- #endif /* DEBUG */
-
- rc = 0;
- /*
- * Get port instance
- */
- EnterPdrSem();
- pPortInst = AddPortInst ( pszDeviceName );
- if (!pPortInst) {
- rc = ERROR_FILE_NOT_FOUND;
- } else {
- /*
- * Here we could check for whether a job is printing or not @BUGBUG
- * For now, we allow commands to be sent to the printer
- * while sending a print job because some protocol converters
- * packetize job data writes.
- * For those protocol converters that do not allow sending commands
- * to the printer while in the middle of sending a print job, the
- * converter must ensure it does not try to send a command
- * use SplPdSendCmd().
- */
- //if (pPortInst->ulJobPrinting == PDR_PRINTING ) {
- // //
- // // Since there is only one channel to the printer
- // // we cannot send commands while in the middle of sending
- // // a print job
- // // We handle BIDI_STARTJOB and BIDI_ENDJOB by not setting
- // // the port status to PDR_PRINTING until AFTER STARTJOB
- // // and clearing it BEFORE ENDJOB.
- // //
- // if (!(ulFlags & FLG_SYNCH) || !(ulFlags & FLG_MUSTCOMPLETE)) {
- // rc = ERROR_INFO_NOT_AVAIL;
- // }
- //}
- }
- LeavePdrSem();
- if (rc) {
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDSENDCMD))
- {
- sprintf( logbuf,
- "SplPdSendCmd on %s rc=%d %lX\r\n",
- pszDeviceName, rc );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- return(rc);
- }
- rc = DosRequestMutexSem ( pPortInst->hPortSem, SEM_INDEFINITE_WAIT );
- /*
- * If we wanted to hold the caller until the current job data was @BUGBUG
- * sent to the printer, the following bit of code would do it:
- */
- // /*
- // * Loop until there is no job data being sent to the printer
- // * variable is reset.
- // */
- // while (pPortInst->ulJobPrinting == PDR_PRINTING) {
- // rc = DosReleaseMutexSem ( pPortInst->hPortSem );
- // DosSleep(500);
- // rc = DosRequestMutexSem ( pPortInst->hPortSem, SEM_INDEFINITE_WAIT );
- // }
- EnterPdrSem();
- /*
- ** Set TimeLastCmd so that we don't close this
- ** port from our ControlThread
- */
- pPortInst->ulTimeLastCmd = time();
-
- /*
- ** open PAR1284 device if not yet opened
- */
- if ( !rc && !(pPortInst->flStatus & PF_PORT_OPEN) ) {
- rc = PdOpen(pPortInst);
- }
-
- LeavePdrSem();
-
- if (rc) {
- DosReleaseMutexSem ( pPortInst->hPortSem );
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDSENDCMD))
- {
- sprintf( logbuf,
- "SplPdSendCmd on %s rc=%d %lX\r\n",
- pszDeviceName, rc );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- return(rc);
- }
-
- /*
- * Save time prior to issuing DosWrite
- * If write fails before printer timeout expired
- * retry the request.
- */
- cbWrite = 0;
- cbWritten = 0;
- ulTime = time() ;
- /*
- ** Some 32-bit linear addresses are not handled well by DosWrite
- ** (all pages have to be able to be locked by the filesystem).
- ** To ensure we do not get rc=5(ACCESS_DENIED) from DosWrite
- ** we copy the data out to a separately allocated buffer,
- ** and pass this buffer to DosWrite.
- ** We only do this for SplPdSendCmd() because our 32-bit print
- ** drivers(callers of SplPdWrite) already handle this.
- **/
- if ((cbInData <= DEFAULT_BUFSIZE) && pPortInst->pbWriteBuf) {
- memcpy( pPortInst->pbWriteBuf, pInData, cbInData );
- pBufToSend = pPortInst->pbWriteBuf;
- } else {
- pBufToSend = pInData;
- }
- rc = PdWrite( pPortInst, pBufToSend, cbInData, &cbWrite );
-
- if (rc || ( cbWrite != cbInData ) ) {
- /*
- * Check time it took to issue write
- * If this is a known port
- * there is a timeout for the port
- * and the time it took to do the DosWrite was
- * less than (PortTimeout - 1)
- * then
- * Retry Request
- */
- if ( (ulPortTimeout = pPortInst->ulPrintTimeOut) &&
- ( (time() - ulTime) < (ulPortTimeout - 1) )) {
-
- /*
- * Keep track of total bytes written
- * Reset clock if DosWrite succeeded without writting all bytes
- * Retry request
- */
- cbWritten = cbWrite ;
- do
- {
- if ( (rc == 0) && ( cbWrite ) ) {
- /*
- * if DosWrite successful and bytes were written
- * reset timeout value
- */
- ulTime = time() ;
- }
-
- /* Sleep one second to avoid hard loop on DosWrite */
- DosSleep(1000) ;
-
- cbWrite = 0 ; /* reset bytes written */
-
- /*
- * Write buffer, taking into account bytes written so far
- */
- rc = PdWrite( pPortInst,
- (PVOID)((PBYTE)pBufToSend + cbWritten),
- /* index past bytes written */
- cbInData - cbWritten,/* only write remaining data */
- &cbWrite );
-
- cbWritten += cbWrite ;
-
- } while ( (cbWritten < cbInData) &&
- ( (time() - ulTime) < (ulPortTimeout - 1) )) ;
- }
-
- } /* end giving retry */
-
- /*
- ** Set TimeLastCmd so that we don't close this
- ** port from our ControlThread until necessary.
- ** Wakeup control thread if it is waiting indefinitely.
- ** This is done to ensure we close the port
- ** when only query commands are sent to it.
- ** The control thread will just check this port,
- ** then reset its eventSem timeout to the next time
- ** it should check this port.
- ** This is done because we never know when the last
- ** query buffer for a port is coming.
- */
- pPortInst->ulTimeLastCmd = time();
- if (!fControlWakeupPending)
- {
- DosPostEventSem(hevControl);
- }
- DosReleaseMutexSem ( pPortInst->hPortSem );
- /*
- ** Wakeup ParReadThread so we can get the response
- ** to the command we just sent.
- */
- DosPostEventSem(pPortInst->hevReadThread);
-
- #ifdef DEBUG_ALERT
- {
- if (!(flChangeDebugLog & FL_PDRDB_DISABLE_SPLPDSENDCMD))
- {
- sprintf( logbuf,
- "SplPdSendCmd on %s rc=%d %lX\r\n",
- pszDeviceName, rc );
- LogCall( logbuf );
- }
- }
- #endif /* DEBUG */
-
- return(rc);
- }
-
-
- #endif // ifdef BIDI
-
-