home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ddkx86v5.zip
/
DDKX86
/
SRC
/
PARALLEL
/
PARALLEL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-14
|
68KB
|
2,216 lines
/*DDK*************************************************************************/
/* */
/* COPYRIGHT Copyright (C) 1995 IBM Corporation */
/* */
/* The following IBM OS/2 WARP source code is provided to you solely for */
/* the purpose of assisting you in your development of OS/2 WARP device */
/* drivers. You may use this code in accordance with the IBM License */
/* Agreement provided in the IBM Device Driver Source Kit for OS/2. This */
/* Copyright statement may not be removed. */
/* */
/*****************************************************************************/
/**************************************************************************
*
* SOURCE FILE NAME = PARALLEL.C
*
* DESCRIPTIVE NAME = Parallel port driver
*
*
* VERSION = V2.0
*
* DATE
*
* DESCRIPTION
*
*
* FUNCTIONS
*
* ENTRY POINTS:
*
* DEPENDENCIES:
*
* NOTES
*
*
* STRUCTURES
*
* EXTERNAL REFERENCES
*
* EXTERNAL FUNCTIONS
*
*/
#define LINT_ARGS /* argument checking enabled */
#define INCL_DOS
#define INCL_GPI
#undef INCL_GPI
#define INCL_DEV
#define INCL_DOSMEMMGR /* Include standard OS/2 support */
#define INCL_DOSMODULEMGR /* For DosLoadModule */
#define INCL_DOSPROCESS
#define INCL_GPILCIDS
#define INCL_WINCOMMON /* Include Window Management support */
#define INCL_WINDOWMGR
#define INCL_WINSWITCHLIST
#define INCL_WINPROGRAMLIST
#define INCL_WINMENUS
#define INCL_WINWINDOWMGR
#define INCL_WINMESSAGEMGR
#define INCL_WINDIALOGS
#define INCL_WINSTATICS
#define INCL_WINLISTBOXES
#define INCL_WINMENUS
#define INCL_WINSYS
#define INCL_WINFRAMEMGR
#define INCL_INCLWINACCELERATORS
#define INCL_WINPOINTERS
#define INCL_WINERRORS
#define INCL_WINSHELLDATA
#define INCL_WINTYPES
#define INCL_WINACCELERATORS
#define INCL_WINBUTTONS
#define INCL_WINENTRYFIELDS
#define INCL_WINRECTANGLES
#define INCL_WINTIMER
#define INCL_WINSCROLLBARS
#define INCL_WINHEAP
#define INCL_SHLERRORS
#define INCL_WININPUT
#define INCL_WINHELP
#define INCL_WINSTDSPIN
#define INCL_SPL
#define INCL_SPLP
#define INCL_SPLERRORS
#define INCL_SHLERRORS
#define INCL_DOSERRORS
#define INCL_WINHOOKS
int acrtused=1; /* Define variable to say this is a DLL */
#include <os2.h>
#include <stdlib.h>
#include <string.h>
#include "PARALLEL.h"
#include "port.h"
/*
** If port driver is not defined in INI file yet
** assume it exists in the boot drive's \OS2\DLL directory
*/
CHAR szDefaultPortDrvPath[] = "?:\\OS2\\DLL\\PARALLEL.PDR";
/*
** Below definition of PORTNAMES structure should be defined in
** common header file pmspl.h.
*/
typedef struct _PORTNAMES
{
PSZ pszPortName; /* -> name of port(ie "LPT1) */
PSZ pszPortDesc; /* -> description of port(ie "Parallel Port 1") */
} PORTNAMES, *PPORTNAMES;
/*
** We want to avoid automatically loading the help manager(HELPMGR.DLL),
** since this takes up lots of memory.
** Do this by only linking to the HELPMGR if user selects help item.
** We replace the WinxxxxHelpInstance calls with our local versions.
** These versions use DosLoadModule() and DosQueryProcAddr() to
** call the "real" help manager functions.
** The below function pointers, prototypes and variables are used
** to this end.
*/
BOOL APIENTRY CALLAssociateHelpInstance (HWND hwndHelpInstance, HWND hwndApp);
BOOL APIENTRY CALLDestroyHelpInstance(HWND hwndHelpInstance);
HWND APIENTRY CALLCreateHelpInstance(HAB hab,PHELPINIT phinitHMInitStructure);
HWND APIENTRY CALLQueryHelpInstance(HWND hwndApp);
BOOL (* APIENTRY pfnWinAssociateHelpInstance)(HWND, HWND);
BOOL (* APIENTRY pfnWinCreateHelpInstance)(HAB, PHELPINIT);
BOOL (* APIENTRY pfnWinDestroyHelpInstance)(HWND);
BOOL (* APIENTRY pfnWinQueryHelpInstance)(HWND);
VOID EXPENTRY InitializeHelp(VOID);
BOOL EXPENTRY SetHelpStubHook(VOID);
VOID EXPENTRY ReleaseHelpStubHook(VOID);
INT EXPENTRY HelpStubHook( HAB AppHAB, USHORT Context, USHORT IdTopic,
USHORT IdSubTopic, PRECTL RectLPtr );
/*
** Global handle for helpmgr module, so it is only loaded once
*/
HMODULE hvHelpmgrModule;
HWND hwndHelp ;
BOOL HelpStubHookIsSet; /* for help */
BOOL HelpAlreadyInitialized; /* for help */
/*
** HELPINIT -- help manager initialization structure
*/
static HELPINIT hmiHelpData = {
sizeof(HELPINIT),
0L,
(PSZ) NULL,
(PHELPTABLE) NULL,
(HMODULE) NULL,
(HMODULE) NULL,
(USHORT) NULL,
(USHORT) NULL,
(PSZ) NULL,
CMIC_HIDE_PANEL_ID,
(PSZ) PRT_HELPFILE_NAME
};
/*
** Local Functions
*/
ULONG CalcBufLength ( HAB hab, HMODULE hModule );
ULONG CalcStructLength ( HAB hab, HMODULE hModule, USHORT usID );
ULONG NumPortsCanFit ( HAB hab, HMODULE hModule, ULONG cbBuf );
VOID CopyNPorts ( HAB hab, HMODULE hModule, PCH pBuf, ULONG ulReturned ) ;
VOID CopyStruct ( HAB hab, HMODULE hModule, USHORT usID, PCH pBuf,
PULONG pulBeginStruct, PULONG pulBeginText );
BOOL GetPortDescription ( HAB hab, HMODULE hModule, PSZ pszPortName,
PSZ pszPortDesc );
ULONG OpenParallPortDlg ( HAB hab, HMODULE hModule, PSZ pszPortName,
PSZ pszAppName );
BOOL GetPortSettings( PPARALLDATA pParallData );
BOOL SavePortSettings(PPARALLDATA pParallData, HWND hDlg);
VOID RemoveLeadTrailBlanks ( PCH pTarget, PCH pSource );
USHORT DisplayError ( HWND hwndOwner, HMODULE hModule,
USHORT usStringID, USHORT usWinStyle );
VOID DE ( PCH str );
MRESULT EXPENTRY ParallDlg( HWND hDlg, USHORT msg, MPARAM mp1, MPARAM mp2 );
/****************************************************************************
*
* FUNCTION NAME = SplPdEnumPort
*
* DESCRIPTION = Return ports supported by this port driver
* Currently this will return those ports this port
* driver supports by default.
* Future enhancement might be to also return any
* ports that have been added that now use this
* port driver.
*
* 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: LPT1
* 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.
*
* NOTE: early versions of the print object expected ERROR_MORE_DATA
* to be returned, even when no PORTNAMES structures would fit.
* For this reason, we do not return ERROR_INSUFFICIENT_BUFFER
*
****************************************************************************/
APIRET APIENTRY SplPdEnumPort ( HAB hab,
PVOID pBuf,
ULONG cbBuf,
PULONG pulReturned,
PULONG pulTotal,
PULONG pcbRequired )
{
HMODULE hModule;
ULONG ulBootDrive;
ULONG rcLoadMod;
CHAR szPathName[260]; /* will contain full path to this port driver */
/*
** 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);
}
/*
** We need our module handle.
** Easiest way to do this is to find the path to our port driver
** from the system INI file.
** If not found in the INI file
** assume it is in the boot drive's \OS2\DLL directory
*/
/* change ? in szDefaultPortDrvPath to boot drive */
DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
sizeof (ULONG));
szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
PrfQueryProfileString (HINI_SYSTEMPROFILE,
"PM_PORT_DRIVER",
"PARALLEL",
szDefaultPortDrvPath,
szPathName,
256 );
/*
** get module handle for our dll
*/
rcLoadMod = DosLoadModule (NULL, 0, szPathName, &hModule);
/*
** 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, hModule);
*pulTotal = 3 ; /* Currently support LPT1 LPT2 and LPT3 */
if (!rcLoadMod)
DosFreeModule (hModule);
/*
** 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 LPT1 LPT2 and LPT3 */
*pcbRequired = CalcBufLength (hab, hModule);
*pulReturned = NumPortsCanFit (hab, hModule, cbBuf);
/*
** return error if we can not fit one port.
*/
if (!(*pulReturned))
{
if (!rcLoadMod)
DosFreeModule (hModule);
return(ERROR_INSUFFICIENT_BUFFER);
}
/*
** copy all the ports which we can store in the pBuf
*/
CopyNPorts (hab, hModule, (PCH)pBuf, *pulReturned);
/*
** Free the module - we do not need it any more.
*/
if (!rcLoadMod)
DosFreeModule (hModule);
/*
** copy all the ports which we can store in the pBuf
*/
if (*pulReturned < *pulTotal)
{
return(ERROR_MORE_DATA);
}
return(NO_ERROR);
}
/****************************************************************************
*
* FUNCTION NAME = SplPdInitPort
*
* DESCRIPTION = Initialize port on behalf of the spooler
*
* INPUT = hFile - File handle to port
* pszPortName - name of port to initialize
*
* OUTPUT = Sets Parallel port settings(port timeout)
*
* RETURN-NORMAL = 0
*
* RETURN-ERROR = ERROR_INVALID_PARAMETER - if port name given
*
****************************************************************************/
APIRET APIENTRY SplPdInitPort ( HFILE hFile,
PSZ pszPortName )
{
USHORT usParamPacket= 0;
USHORT usDataPacket = 0;
UCHAR bInfRetry;
CHAR chBuf[STR_LEN_PORTNAME];
CHAR chInitVal[STR_LEN_PORTNAME];
PCH pchPortDriver = chInitVal;
ULONG ulReturned1;
ULONG ulReturned2;
/*
** Check if port name string is NULL. This is an error.
*/
if (!pszPortName)
{
return(ERROR_INVALID_PARAMETER);
}
/*
** Make Application name string( "PM_PortName" )
*/
strcpy (chBuf, APPNAME_LEAD_STR);
strcat (chBuf, pszPortName);
/*
** Check if this port is parallel port.
*/
if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
KEY_PORTDRIVER, NULL, pchPortDriver,
STR_LEN_PORTNAME)))
{
return(ERROR_INVALID_PARAMETER);
}
if (strcmp (pchPortDriver, DEF_PORTDRIVER))
{
return(ERROR_INVALID_PARAMETER);
}
/*
** Check if this port is installed.
*/
if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
KEY_TIMEOUT, NULL, chInitVal,
STR_LEN_PORTNAME)))
{
return(ERROR_INVALID_PARAMETER);
}
/*
** Set printer timeout
*/
usDataPacket = (USHORT)atoi (chInitVal);
ulReturned2 = 2L ;
DosDevIOCtl(
hFile, /* Hfile passed into SplPdInit */
0x5, /* Category number */
0x4e, /* Function number */
NULL, /* pParams - not needed */
0, /* sizeof *pParms */
NULL, /* &size in/out */
(PVOID) &usDataPacket, /* points to LPT timeout value */
sizeof (USHORT), /* sizeof usDataPacket */
&ulReturned2); /* &size in/out */
/*
** Check for initialization settings for multiple hardware access
**
** If not there, or not equal to "1;"
** disallow multiple hardware access
** else(if equal to "1;")
** allow multiple hardware access to this LPT port
**
*/
if ( (PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
KEY_INITIALIZATION, NULL, chInitVal,
STR_LEN_PORTNAME))
&& ( chInitVal[0] == '1' ) )
{
/* Set to allow multiple hardware access by setting bit 0 on */
usDataPacket = 0x0001 ;
}
else
{
/* Set to not allow multiple hardware access by clearing bit 0 */
usDataPacket = 0x0000 ;
}
/*
** Set multiple hardware access
*/
/* Set return sizes so IOCTL will work */
ulReturned1 = 1L ;
ulReturned2 = 1L ;
DosDevIOCtl(
hFile, /* Hfile passed into SplPdInit */
0x5, /* Category number */
0x51, /* Function number */
(PVOID) &usParamPacket, /* -> command byte - must be 0 */
sizeof (BYTE),
&ulReturned1,
(PVOID) &usDataPacket, /* points to flag byte */
sizeof (BYTE),
&ulReturned2);
/*
** Set infinite retry to false.
*/
bInfRetry = (UCHAR)FALSE;
DosDevIOCtl(
hFile,
0x05,
0x44,
NULL,
0L,
NULL,
(PCH)&bInfRetry,
sizeof (USHORT),
&ulReturned2);
return(NO_ERROR);
}
/****************************************************************************
*
* FUNCTION NAME = SplPdInstallPort
*
* DESCRIPTION = Tells port driver the name of a port that needs to be
* installed.
* Port driver should write Initialization/Termination
* strings to the INI file.
* Typically SplPdSetPort will be called after this.
* This should allow any port to be added for this port driver.
* (ie: if it is not a port we returned in SplPdEnumPort,
* still allow the port to use this port driver).
*
* INPUT = hab - Anchor block handle
* pszPortName - name of port to be installed
*
* OUTPUT =
*
* RETURN-NORMAL = 0
*
* RETURN-ERROR = ERROR_INVALID_PARAMETER - if port name given
*
****************************************************************************/
APIRET APIENTRY SplPdInstallPort ( HAB hab,
PSZ pszPortName )
{
CHAR chBuf[STR_LEN_PORTNAME];
CHAR chPortDesc[STR_LEN_PORTDESC];
HMODULE hModule;
ULONG ulBootDrive;
CHAR szPathName[260]; /* will contain full path to this port driver */
/*
** Check if port name string is NULL. This is an error.
*/
if (!pszPortName)
{
return(ERROR_INVALID_PARAMETER);
}
/*
** We need our module handle.
** Easiest way to do this is to find the path to our port driver
** from the system INI file.
** If not found in the INI file
** assume it is in the boot drive's \OS2\DLL directory
*/
/* change ? in szDefaultPortDrvPath to boot drive */
DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
sizeof (ULONG));
szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
PrfQueryProfileString (HINI_SYSTEMPROFILE,
"PM_PORT_DRIVER",
"PARALLEL",
szDefaultPortDrvPath,
szPathName,
256 );
hModule = 0L ; /* Init module handle to null */
/*
** get module handle for our dll
*/
DosLoadModule (NULL, 0, szPathName, &hModule);
/*
** Check if we have description for port
*/
if (!GetPortDescription (hab, hModule, pszPortName, chPortDesc))
{
/*
** Port description not found, use port name
*/
strcpy( chPortDesc, pszPortName );
}
/*
** Free the module
*/
DosFreeModule (hModule);
/*
** Make Application name string.
*/
strcpy (chBuf, APPNAME_LEAD_STR);
strcat (chBuf, pszPortName);
/*
** Write data for this port in ini file with new format.
*/
PrfWriteProfileString (HINI_SYSTEMPROFILE,
chBuf,
KEY_DESCRIPTION,
chPortDesc);
PrfWriteProfileString (HINI_SYSTEMPROFILE,
chBuf,
KEY_INITIALIZATION,
DEF_INITIALIZATION);
PrfWriteProfileString (HINI_SYSTEMPROFILE,
chBuf,
KEY_TERMINATION,
DEF_TERMINATION);
PrfWriteProfileString (HINI_SYSTEMPROFILE,
chBuf,
KEY_TIMEOUT,
DEF_TIMEOUT);
PrfWriteProfileString (HINI_SYSTEMPROFILE,
chBuf,
KEY_PORTDRIVER,
DEF_PORTDRIVER);
/*
** Write data for this port in ini file with old format.
*/
PrfWriteProfileString (HINI_SYSTEMPROFILE,
APPNAME_PM_SPOOLER_PORT,
pszPortName,
DEF_OLD_INITIALIZATION);
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 = PARALLEL_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 port name given
*
****************************************************************************/
APIRET APIENTRY SplPdQueryPort ( HAB hab,
PSZ pszPortName,
PVOID pBufIn,
ULONG cbBuf,
PULONG cItems )
{
HMODULE hModule;
CHAR chString[STR_LEN_DESC];
USHORT usNumLines;
USHORT usLineID;
USHORT usStrLength;
ULONG ulBootDrive;
PCH pBuf = (PCH)pBufIn;
CHAR szPathName[260]; /* will contain full path to this port driver */
/*
** 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);
}
/*
** We need our module handle.
** Easiest way to do this is to find the path to our port driver
** from the system INI file.
** If not found in the INI file
** assume it is in the boot drive's \OS2\DLL directory
*/
/* change ? in szDefaultPortDrvPath to boot drive */
DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
sizeof (ULONG));
szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
PrfQueryProfileString (HINI_SYSTEMPROFILE,
"PM_PORT_DRIVER",
"PARALLEL",
szDefaultPortDrvPath,
szPathName,
256 );
hModule = 0L ; /* Init module handle to null */
/*
** get module handle for our dll
*/
DosLoadModule (NULL, 0, szPathName, &hModule);
chString[0] = '\0' ;
/*
** get number of lines.
*/
WinLoadString(hab, hModule, (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, hModule, usLineID, STR_LEN_DESC, chString);
if (cbBuf >= (usStrLength = (USHORT)(strlen (chString) + 1)))
{
strcpy (pBuf, chString);
pBuf += usStrLength;
cbBuf -= usStrLength;
}
else
{
DosFreeModule (hModule);
return(ERROR_INSUFFICIENT_BUFFER);
}
}
DosFreeModule (hModule);
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 port name given
*
****************************************************************************/
APIRET APIENTRY SplPdSetPort ( HAB hab,
PSZ pszPortName,
PULONG flModified )
{
CHAR chBuf[STR_LEN_PORTNAME];
CHAR chPortDriver[STR_LEN_PORTNAME];
HMODULE hModule;
ULONG ulBootDrive;
CHAR szPathName[260]; /* will contain full path to this port driver */
/*
** Check if port name string is NULL. This is an error.
*/
if (!pszPortName || !flModified)
{
return(ERROR_INVALID_PARAMETER);
}
/*
** Make Application name string( "PM_PortName" ).
*/
strcpy (chBuf, APPNAME_LEAD_STR);
strcat (chBuf, pszPortName);
/*
** Check if this port is parallel port.
*/
if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
KEY_PORTDRIVER, NULL, chPortDriver,
STR_LEN_PORTNAME)))
{
return(ERROR_INVALID_PARAMETER);
}
if (strcmp (chPortDriver, DEF_PORTDRIVER))
{
return(ERROR_INVALID_PARAMETER);
}
/*
** We need our module handle.
** Easiest way to do this is to find the path to our port driver
** from the system INI file.
** If not found in the INI file
** assume it is in the boot drive's \OS2\DLL directory
*/
/* change ? in szDefaultPortDrvPath to boot drive */
DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
sizeof (ULONG));
szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
PrfQueryProfileString (HINI_SYSTEMPROFILE,
"PM_PORT_DRIVER",
"PARALLEL",
szDefaultPortDrvPath,
szPathName,
256 );
hModule = 0L ; /* Init module handle to null */
/*
** get module handle for our dll
*/
DosLoadModule (NULL, 0, szPathName, &hModule);
/*
** Load the dialog for user to change.
*/
*flModified = OpenParallPortDlg (hab, hModule, pszPortName, chBuf);
/*
** free the module
*/
DosFreeModule (hModule);
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 port name given
*
****************************************************************************/
APIRET APIENTRY SplPdRemovePort ( HAB hab,
PSZ pszPortName )
{
CHAR chBuf[STR_LEN_PORTNAME];
CHAR chPortDriver[STR_LEN_PORTNAME];
/*
** Check if port name string is NULL. This is an error.
*/
if (!pszPortName)
{
return(ERROR_INVALID_PARAMETER);
}
/*
** Make Application name string.
*/
strcpy (chBuf, APPNAME_LEAD_STR);
strcat (chBuf, pszPortName);
/*
** Check if this port is parallel port.
*/
if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
KEY_PORTDRIVER, NULL, chPortDriver,
STR_LEN_PORTNAME)))
{
return(ERROR_INVALID_PARAMETER);
}
if (strcmp (chPortDriver, DEF_PORTDRIVER))
{
return(ERROR_INVALID_PARAMETER);
}
/*
** We found port to be removed.
** Remove it from new format "PM_portname"
*/
PrfWriteProfileString (HINI_SYSTEMPROFILE, chBuf, NULL, NULL);
/*
** remove this port from old format.
*/
PrfWriteProfileString (HINI_SYSTEMPROFILE,
APPNAME_PM_SPOOLER_PORT,
pszPortName,
NULL);
return(NO_ERROR);
}
/****************************************************************************
*
* FUNCTION NAME = SplPdTermPort
*
* DESCRIPTION = Terminate port on behalf of the spooler
*
* INPUT = hFile - File handle to port
* pszPortName - name of port whose job is completing
*
* OUTPUT = Sets Parallel port settings(port timeout)
*
* RETURN-NORMAL = 0
*
* RETURN-ERROR = ERROR_INVALID_PARAMETER - if port name given
*
****************************************************************************/
SPLERR EXPENTRY SplPdTermPort ( HFILE hFile,
PSZ pszPortName )
{
CHAR chBuf[STR_LEN_PORTNAME];
PCH chPortDriver[STR_LEN_PORTNAME];
/*
** We do not have to take any action. Return NO_ERROR
*/
return(NO_ERROR);
#ifdef TERM_ACTION_NEEDED
/*
** Check if port name string is NULL. This is an error.
*/
if (!pszPortName)
{
return(ERROR_INVALID_PARAMETER);
}
/*
** Make Application name string.
*/
strcpy (chBuf, APPNAME_LEAD_STR);
strcat (chBuf, pszPortName);
/*
** Check if this port is parallel port.
*/
if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
KEY_PORTDRIVER, NULL, chPortDriver, 64)))
{
return(ERROR_INVALID_PARAMETER);
}
if (strcmp ((PSZ)chPortDriver, DEF_PORTDRIVER))
{
return(ERROR_INVALID_PARAMETER);
}
/*
** We do not have to take any action - return NO_ERROR
*/
return(NO_ERROR);
#endif
}
/****************************************************************************
*
* FUNCTION NAME = CalcBufLength
*
* DESCRIPTION = Determine how big buffer is needed to store all PORTNAMES
* structures
*
* INPUT = hab - anchor block handle
* hModule - this port driver's module handle
*
* OUTPUT = length of buffer necessary to store all default port names
* supported by this port driver.
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
ULONG CalcBufLength ( HAB hab,
HMODULE hModule )
{
ULONG cbRequired;
USHORT usID;
cbRequired = 0;
/*
** calculate length required to fit all the port info.
*/
for (usID = PORT_ID_FIRST; usID <= PORT_ID_LAST; usID += 2)
{
cbRequired += CalcStructLength (hab, hModule, usID);
}
return(cbRequired);
}
/****************************************************************************
*
* FUNCTION NAME = CalcStructLength
*
* DESCRIPTION = Determine size of buffer needed to store PORTNAMES structure
* for given string ID.
*
* INPUT = hab - anchor block handle
* hModule - this port driver's module handle
* usID - string ID for port name
*
* OUTPUT = length of buffer necessary to store this port name
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
ULONG CalcStructLength ( HAB hab,
HMODULE hModule,
USHORT usID )
{
ULONG cbRequired;
CHAR chString[STR_LEN_PORTDESC];
cbRequired = 0;
WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, chString);
cbRequired += strlen (chString) + 1;
WinLoadString(hab, hModule, (USHORT)(usID + 1), STR_LEN_PORTDESC, chString);
cbRequired += strlen (chString) + 1;
cbRequired += sizeof (PORTNAMES);
return(cbRequired);
}
/****************************************************************************
*
* FUNCTION NAME = NumPortsCanFit
*
* DESCRIPTION = Determine how many ports can fit in buffer
*
* INPUT = hab - anchor block handle
* hModule - this port driver's module handle
* cbBuf - size in bytes of buffer to hold PORTNAMES
*
* OUTPUT = count of PORTNAMES structures that can fit in buffer
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
ULONG NumPortsCanFit ( HAB hab,
HMODULE hModule,
ULONG cbBuf )
{
ULONG cbRequired;
USHORT usID;
ULONG ulNumPort;
cbRequired = 0;
ulNumPort = 0;
/*
** calculate how many ports we can fit in buf.
*/
for (usID = PORT_ID_FIRST; usID <= PORT_ID_LAST; usID += 2)
{
cbRequired += CalcStructLength (hab, hModule, usID);
if (cbRequired > cbBuf)
{
return(ulNumPort);
}
ulNumPort++;
}
return(ulNumPort);
}
/****************************************************************************
*
* FUNCTION NAME = CopyNPorts
*
* DESCRIPTION = Copy given number of ports into buffer
*
* INPUT = hab - anchor block handle
* hModule - this port driver's module handle
* pBuf - buffer to get PORTNAMES structures
* ulReturned - number of ports to return
*
* OUTPUT = pBuf is updated
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
VOID CopyNPorts ( HAB hab,
HMODULE hModule,
PCH pBuf,
ULONG ulReturned )
{
USHORT usID;
ULONG ulBeginText;
ULONG ulBeginStruct;
ulBeginText = ulReturned * sizeof (PORTNAMES);
ulBeginStruct = 0;
for (usID = PORT_ID_FIRST;
usID <= PORT_ID_LAST && ulReturned;
usID += 2, --ulReturned)
{
CopyStruct (hab, hModule, usID, pBuf, &ulBeginStruct, &ulBeginText);
}
}
/****************************************************************************
*
* FUNCTION NAME = CopyStruct
*
* DESCRIPTION = Copy single PORTNAMES structure to buffer
*
* INPUT = hab - anchor block handle
* hModule - this port driver's module handle
* usID - string ID for port to return
* pBuf - buffer to get PORTNAMES structures
* pulBeginStruct - offset from begin of pBuf to store next
* PORTNAMES
* pulBeginText - offset from pBuf to store next string
*
* OUTPUT = pBuf is updated
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
VOID CopyStruct ( HAB hab,
HMODULE hModule,
USHORT usID,
PCH pBuf,
PULONG pulBeginStruct,
PULONG pulBeginText )
{
PPORTNAMES pPortNames;
pPortNames = (PPORTNAMES)(pBuf + *pulBeginStruct);
*pulBeginStruct += sizeof (PORTNAMES);
/*
** copy port name in the structure
*/
pPortNames->pszPortName = pBuf + *pulBeginText;
WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, pPortNames->pszPortName);
*pulBeginText += strlen (pPortNames->pszPortName) + 1;
/*
** copy port description to the structure
*/
pPortNames->pszPortDesc = pBuf + *pulBeginText;
WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, pPortNames->pszPortDesc);
*pulBeginText += strlen (pPortNames->pszPortDesc) + 1;
}
/****************************************************************************
*
* FUNCTION NAME = GetPortDescription
*
* DESCRIPTION = Get port description from our string resources.
*
* INPUT = hab - anchor block handle
* hModule - this port driver's module handle
* pszPortName - name of port to get description for
* pszPortDesc - gets port description
*
* OUTPUT = TRUE - if portname description is found
* FALSE - if not
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
BOOL GetPortDescription ( HAB hab,
HMODULE hModule,
PSZ pszPortName,
PSZ pszPortDesc )
{
USHORT usID;
CHAR chBuf[STR_LEN_PORTDESC];
for (usID = PORT_ID_FIRST; usID <= PORT_ID_LAST; usID += 2)
{
WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, chBuf);
if (!strcmp (pszPortName, chBuf))
{
strcpy (pszPortDesc, chBuf);
return(TRUE);
}
}
return(FALSE);
}
/****************************************************************************
*
* FUNCTION NAME = OpenParallPortDlg
*
* DESCRIPTION = Display port settings dialog
*
* INPUT = hab - anchor block handle
* hModule - this port driver's module handle
* pszPortName - name of port to get description for
* pszAppName - INI Appname for port( "PM_Portname").
*
* OUTPUT = TRUE - if port settings changed
* FALSE - if port settings not changed
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
ULONG OpenParallPortDlg ( HAB hab,
HMODULE hModule,
PSZ pszPortName,
PSZ pszAppName )
{
PARALLDATA ParallData;
memset (&ParallData, 0, sizeof (PARALLDATA));
ParallData.hAB = hab;
ParallData.hModule = hModule;
ParallData.pszPortName = pszPortName;
ParallData.pszAppName = pszAppName;
WinDlgBox (HWND_DESKTOP,
HWND_DESKTOP,
(PFNWP)ParallDlg,
(HMODULE)hModule,
IDD_PORTPARALLEL,
&ParallData);
return ParallData.lfModified;
}
/****************************************************************************
*
* FUNCTION NAME = ParallDlg
*
* DESCRIPTION = Port settings dialog procedure
*
* INPUT = hDlg: HWND
* msg: message
* mp1: message parameter
* mp2: " "
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
MRESULT EXPENTRY ParallDlg( HWND hDlg,
USHORT msg,
MPARAM mp1,
MPARAM mp2 )
{
PPARALLDATA pParallData;
/*
**ULONG ulTimeOut;
**HWND hwndMenu;
**HWND hwndHelpInstance;
*/
switch (msg) {
case WM_INITDLG:
pParallData = (PPARALLDATA)mp2;
WinSetWindowULong (hDlg, QWL_USER, (ULONG)pParallData);
WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
SPBM_SETLIMITS,
MPFROMP(TIMEOUT_UPPER_LIMIT),
MPFROMP(TIMEOUT_LOWER_LIMIT));
{
CHAR szDesc[ STR_LEN_PORTDESC];
CHAR szTitle[ STR_LEN_TITLE + 1];
if (PrfQueryProfileString (HINI_SYSTEMPROFILE,
pParallData->pszAppName,
KEY_DESCRIPTION,
NULL,
(PSZ)szDesc,
STR_LEN_PORTDESC))
{
WinSetWindowText (WinWindowFromID (hDlg,
(USHORT)IDC_PPA_DESC),
szDesc);
/*
** full description port name
*/
WinQueryWindowText (hDlg, STR_LEN_TITLE, szTitle);
strcat (szTitle, szDesc);
WinSetWindowText (hDlg, szTitle);
}
}
GetPortSettings (pParallData);
WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
SPBM_SETCURRENTVALUE,
MPFROMSHORT(pParallData->usOrgTimeOut),
MPFROMSHORT(NULL));
/*
** added setting - new checkbox for share access
*/
WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
BM_SETCHECK,
MPFROMSHORT(pParallData->fOrgShareAccess),
MPFROMSHORT(NULL));
/*
** create help hook for helps
*/
SetHelpStubHook();
break;
case WM_COMMAND:
pParallData = (PPARALLDATA)WinQueryWindowULong (hDlg, QWL_USER);
switch (SHORT1FROMMP(mp1)) {
case IDC_OK:
/*
** Call function to save any changed port settings
*/
if (SavePortSettings(pParallData, hDlg))
{
WinDismissDlg(hDlg, 0);
}
break;
case IDC_RESET:
WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
SPBM_SETCURRENTVALUE,
MPFROMSHORT(pParallData->usOrgTimeOut),
MPFROMSHORT(NULL));
/*
** added setting new checkbox for share access
*/
WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
BM_SETCHECK,
MPFROMSHORT(pParallData->fOrgShareAccess),
MPFROMSHORT(NULL));
break;
case IDC_DEFAULT:
WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
SPBM_SETCURRENTVALUE,
MPFROMSHORT(DEF_TIMEOUT_VALUE),
MPFROMSHORT(NULL));
/*
** added setting new checkbox for share access
*/
WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
BM_SETCHECK,
MPFROMSHORT(FALSE),
MPFROMSHORT(NULL));
break;
case IDC_CANCEL:
WinDismissDlg(hDlg, MBID_CANCEL);
break;
default:
return(WinDefDlgProc(hDlg, msg, mp1, mp2) );
break;
}
break;
case WM_HELP:
InitializeHelp();
if (hwndHelp)
{
WinSendMsg (hwndHelp, HM_DISPLAY_HELP,
(MPARAM)IDH_DLG_EXTENDED, NULL);
return (MRESULT)TRUE;
}
break;
case WM_DESTROY:
/*
** if we have a help instance destroy it.
*/
if (HelpAlreadyInitialized)
{
CALLDestroyHelpInstance(hwndHelp);
hwndHelp = (HWND) NULL;
HelpAlreadyInitialized = FALSE;
HelpStubHookIsSet=FALSE;
}
ReleaseHelpStubHook();
break;
default:
return(WinDefDlgProc(hDlg, msg, mp1, mp2) );
break;
}
return FALSE;
}
/****************************************************************************
*
* FUNCTION NAME = GetPortSettings
*
* DESCRIPTION = Get port Initialization settings from INI file
*
* INPUT = pParallData -> structure containing port name.
* On return this will have port timeout
* and share access flag.
*
* OUTPUT = TRUE - if INI information found for port
* FALSE - if INI info not found
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
BOOL GetPortSettings( PPARALLDATA pParallData )
{
CHAR szBuf[20];
PSZ p;
/*
** Get port timeout value ( "PM_LPT1" "TIMEOUT" "timeout;" )
*/
if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE,
pParallData->pszAppName,
KEY_TIMEOUT,
NULL,
(PSZ)szBuf,
20)))
{
return FALSE;
}
RemoveLeadTrailBlanks ((PSZ)szBuf, (PSZ)szBuf);
if (p = strchr(szBuf, ';'))
{
*p = '\0';
}
if (*szBuf)
{
pParallData->usOrgTimeOut = (USHORT)atoi (szBuf);
}
else
{
pParallData->usOrgTimeOut = DEF_TIMEOUT_VALUE;
}
pParallData->usSaveTimeOut = pParallData->usOrgTimeOut;
/*
** Get port's share access flag (part of initialization string)
*/
if ( (PrfQueryProfileString (HINI_SYSTEMPROFILE, pParallData->pszAppName,
KEY_INITIALIZATION, NULL,
(PSZ)szBuf,
20))
&& (szBuf[0] == '1') )
{
pParallData->fOrgShareAccess = TRUE ;
pParallData->fShareAccess = TRUE ;
}
else
{
pParallData->fOrgShareAccess = FALSE;
pParallData->fShareAccess = FALSE;
}
return(TRUE);
}
/****************************************************************************
*
* FUNCTION NAME = SavePortSettings
*
* DESCRIPTION = save any changed values for this LPT port in INI file
*
* INPUT = pParallalData -> this port's information
* hDlg - handle of dialog window
*
* OUTPUT = TRUE - successful
* FALSE - PrfWrite failed
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
BOOL SavePortSettings( PPARALLDATA pParallData,
HWND hDlg )
{
CHAR szBuf[20];
PSZ pszInitialization ;
ULONG ulTimeOut;
HFILE hFile ;
ULONG ActionTaken ;
USHORT usParamPacket= 0;
USHORT usDataPacket = 0;
ULONG ulReturned1;
ULONG ulReturned2;
/*
** Get current status of share access checkbox
*/
pParallData->fShareAccess =
SHORT1FROMMP( WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
BM_QUERYCHECK,
MPFROMSHORT(NULL),
MPFROMSHORT(NULL)) );
if (pParallData->fShareAccess != pParallData->fOrgShareAccess)
{
if (pParallData->fShareAccess)
pszInitialization = "1;" ;
else
pszInitialization = "0;" ;
pParallData->lfModified = TRUE;
/*
** If user selects to change parallel port access mode,
** we must issue IOCtl to PRINT02.SYS to set the
** share mode now. (Open port direct, NONSPOOLED!).
** It could be possible the user will use programs
** that do not print, but still require the parallel
** port's hardware registers
*/
if ( DosOpen(pParallData->pszPortName, /* port "LPT1" */
&hFile,
&ActionTaken,
0L, /* filesize */
0L, /* attribute */
FILE_OPEN|FILE_CREATE, /* open flags */
OPEN_FLAGS_NONSPOOLED | /* open mode */
OPEN_FLAGS_FAIL_ON_ERROR |
OPEN_ACCESS_WRITEONLY |
OPEN_SHARE_DENYNONE,
NULL ) == 0) /* No EAs */
{
/*
** flag byte: bit 0 off -> don't allow more than one process
** to access parallel port at one time
** on -> allow multiple processes to access
** parallel port simultaneously
*/
usDataPacket = (USHORT)pParallData->fShareAccess ;
ulReturned1 = 1 ; /* length of in/output parameters */
ulReturned2 = 1 ;
DosDevIOCtl(
hFile, /* port file handle */
0x5, /* Category number */
0x51, /* Function - set share access */
(PVOID) &usParamPacket, /* Not needed for IOCTL */
sizeof (BYTE),
&ulReturned1,
(PVOID) &usDataPacket, /* 1 = allow multiple access */
sizeof (BYTE),
&ulReturned2);
DosClose(hFile) ;
}
/*
** Write initialization string to ini file
*/
if (!PrfWriteProfileString (HINI_SYSTEMPROFILE,
pParallData->pszAppName,
KEY_INITIALIZATION,
pszInitialization))
{
DE ("Error in writing to system ini file");
return FALSE;
}
}
WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT, SPBM_QUERYVALUE,
(MPARAM)&ulTimeOut, (MPARAM)NULL);
if (pParallData->usSaveTimeOut != (USHORT)ulTimeOut)
{
pParallData->usSaveTimeOut = (USHORT)ulTimeOut;
pParallData->lfModified = TRUE;
_itoa (pParallData->usSaveTimeOut, szBuf, 10);
strcat (szBuf, ";");
/*
** Write data for this port in ini file with new format.
*/
if (!PrfWriteProfileString (HINI_SYSTEMPROFILE,
pParallData->pszAppName,
KEY_TIMEOUT,
szBuf))
{
DE ("Error in writing to system init file");
return FALSE;
}
}
return TRUE;
}
/****************************************************************************
*
* FUNCTION NAME = RemoveLeadTrailBlanks
*
* DESCRIPTION = Remove all the leading blanks and all the trailing blanks
* from the source string. The target string contains no lead
* or trail blanks. Source string is not altered.
*
* INPUT = pTarget - Target string.
* pSource - Source string.
*
* OUTPUT = Void function.
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
* Note : Function accepts the same pointer for both source and target.
* This means that same buffer can be used as input and output.
*
****************************************************************************/
VOID RemoveLeadTrailBlanks ( PCH pTarget,
PCH pSource )
{
for (; *pSource == ' ' || *pSource == '\t' || *pSource == '\n'; pSource++);
if (!(*pSource))
{
*pTarget = '\0';
return;
}
for (; *pSource; *pTarget++ = *pSource++);
for (pTarget--; *pTarget == ' ' || *pTarget == '\t' || *pTarget == '\n';
pTarget--);
*++pTarget = '\0';
}
/****************************************************************************
*
* FUNCTION NAME = DisplayError
*
* DESCRIPTION = Display error having string from the resource file.
*
* INPUT = hwndOwner - Owner of message box.
* if NULL, default is last active window.
* usStringID - ID of string in resource file.
* usWinStyle - Window style of message box.
* if NULL, default is MB_OK.
*
* OUTPUT = User-response value returned by WimMessageBox API.
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
USHORT DisplayError ( HWND hwndOwner,
HMODULE hModule,
USHORT usStringID,
USHORT usWinStyle )
{
CHAR pszTitle[256]; /* Message-box window title */
CHAR pszText[256]; /* Message-box window message */
USHORT usResponse;
HAB hAB;
ULONG ulLen = 255L;
hAB = WinQueryAnchorBlock (HWND_DESKTOP);
WinLoadString (hAB, hModule, PORT_ERR_TITLE, 255, (PSZ)pszTitle);
WinLoadString (hAB, hModule, usStringID, 255, (PSZ)pszText);
if (!hwndOwner)
{
hwndOwner = WinQueryActiveWindow (HWND_DESKTOP);
}
if (!usWinStyle)
{
usWinStyle = MB_OK;
}
usResponse = WinMessageBox (HWND_DESKTOP, hwndOwner, pszText, pszTitle, 1,
(ULONG)usWinStyle);
return (usResponse);
}
/****************************************************************************
*
* FUNCTION NAME = DE
*
* DESCRIPTION = Display Error message
*
* INPUT = str - error message string to display
*
* OUTPUT = None
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
VOID DE ( PCH str )
{
WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
(PCH)str,
(PCH)"Error",
1,
MB_OKCANCEL | MB_APPLMODAL |
MB_MOVEABLE | MB_ICONASTERISK);
}
/*
** Following routines replace Win help manager function calls.
** This is done to avoid automatically loading the help manager
** when the port driver is used.
** DosLoadModule is used to get the help manager function addresses
** and WinHook mechanism is used to get notified of F1 key.
**
** All CallxxHelpxx call equivalent WinxxHelpxx
*/
/****************************************************************************
*
* FUNCTION NAME = CALLAssociateHelpInstance
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
BOOL APIENTRY CALLAssociateHelpInstance ( HWND hwndHelpInstance,
HWND hwndApp )
{
ULONG rc = 0;
HMODULE hModule;
if (!hvHelpmgrModule)
{
/*
** If there is an error display it and return.
** This call should only be made if CreateHelpInstance was called.
**
** This uses an error message from print object and should
** be replaced with custom message.
*/
DosQueryModuleHandle ("WPPRINT", &hModule);
#define STR_BASE 7000
#define STR_DLL_LOAD_ERROR (STR_BASE + 36)
DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
}
else
{
/*
** Check to see if we have the pointer from a previous call
*/
if (!pfnWinAssociateHelpInstance)
{
/*
** Get pointer to the location of the function we want.
*/
rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
(PSZ)"WIN32ASSOCIATEHELPINSTANCE",
(PFN *)&pfnWinAssociateHelpInstance);
}
/*
** If no error continue.
*/
if (!rc )
{
rc = (*pfnWinAssociateHelpInstance)(hwndHelpInstance, hwndApp);
/*
** Function returns a bool
*/
if (rc == TRUE)
return(TRUE);
}
}
return(FALSE);
}
/****************************************************************************
*
* FUNCTION NAME = CALLCreateHelpInstance
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
HWND APIENTRY CALLCreateHelpInstance ( HAB hab,
PHELPINIT phinitHMInitStructure )
{
ULONG rc = 0;
HWND hwnd = (HWND)NULLHANDLE;
HMODULE hModule;
/*
** Check to see if we already have the handle
*/
if (!hvHelpmgrModule)
rc = DosLoadModule((PSZ)NULL, 0,
(PSZ)"HELPMGR", (PHMODULE)&hvHelpmgrModule);
if (rc)
{
/*
** If there is an error display it and return.
*/
DosQueryModuleHandle ("WPPRINT", &hModule);
DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
}
else
{
if (!pfnWinCreateHelpInstance)
/*
** Next get pointer to the location of the function we want.
*/
rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
(PSZ)"WIN32CREATEHELPINSTANCE",
(PFN *)&pfnWinCreateHelpInstance);
/*
** If no error continue.
*/
if (!rc )
hwnd = (*pfnWinCreateHelpInstance)(hab, phinitHMInitStructure );
}
return(hwnd);
}
/****************************************************************************
*
* FUNCTION NAME = CALLDestroyHelpInstance
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
BOOL APIENTRY CALLDestroyHelpInstance ( HWND hwndHelpInstance )
{
ULONG rc = 0;
HMODULE hModule;
if (!hvHelpmgrModule)
{
/*
** If there is an error display it and return.
*/
DosQueryModuleHandle ("WPPRINT", &hModule);
DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
}
else
{
if (!pfnWinDestroyHelpInstance)
/*
** Next get pointer to the location of the function we want.
*/
rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
(PSZ)"WIN32DESTROYHELPINSTANCE",
(PFN *)&pfnWinDestroyHelpInstance);
/*
** If no error continue.
*/
if (!rc )
{
rc = (*pfnWinDestroyHelpInstance)(hwndHelpInstance);
/*
** Function returns a bool
*/
if (rc == TRUE)
{
/* DosFreeModule(hvHelpmgrModule); */
return(TRUE);
}
}
}
return(FALSE);
}
/****************************************************************************
*
* FUNCTION NAME = CALLQueryHelpInstance
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
HWND APIENTRY CALLQueryHelpInstance ( HWND hwndApp )
{
ULONG rc = 0;
HWND hwnd = (HWND)NULLHANDLE;
HMODULE hModule;
if (!hvHelpmgrModule)
{
/*
** If there is an error display it and return.
*/
DosQueryModuleHandle ("WPPRINT", &hModule);
DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
MB_OK | MB_APPLMODAL | MB_MOVEABLE);
}
else
{
if (!pfnWinQueryHelpInstance)
/*
** Get pointer to the location of the function we want.
*/
rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
(PSZ)"WIN32QUERYHELPINSTANCE",
(PFN *)&pfnWinQueryHelpInstance);
/*
** If no error continue.
*/
if (!rc )
{
/*
** Make sure that the handle is associated with this instance
**
** Make call
*/
hwnd = (*pfnWinQueryHelpInstance)( hwndApp);
}
}
return(hwnd);
}
/****************************************************************************
*
* FUNCTION NAME = SetHelpStubHook
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
BOOL EXPENTRY SetHelpStubHook()
{
if(!HelpStubHookIsSet)
{
if(WinSetHook(0L, HMQ_CURRENT, HK_HELP, (PFN)HelpStubHook, 0L))
{
HelpStubHookIsSet = TRUE;
return TRUE;
}
}
return FALSE;
}
/****************************************************************************
*
* FUNCTION NAME = ReleaseHelpStubHook
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
VOID EXPENTRY ReleaseHelpStubHook()
{
if(HelpStubHookIsSet)
{
WinReleaseHook(0L, HMQ_CURRENT, HK_HELP, (PFN)HelpStubHook, 0L);
HelpStubHookIsSet = FALSE;
}
}
/****************************************************************************
*
* FUNCTION NAME = HelpStubHook
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
INT EXPENTRY HelpStubHook( HAB AppHAB,
USHORT Context,
USHORT IdTopic,
USHORT IdSubTopic,
PRECTL RectLPtr )
{
InitializeHelp();
return FALSE;
}
/****************************************************************************
*
* FUNCTION NAME = InitializeHelp
*
* DESCRIPTION =
*
* INPUT =
*
* OUTPUT =
*
* RETURN-NORMAL =
* RETURN-ERROR =
*
****************************************************************************/
VOID EXPENTRY InitializeHelp()
{
HAB hAB;
HWND hWnd;
HWND hWndActive;
ULONG ulBootDrive;
HMODULE hModule;
CHAR szBuf[256];
CHAR szPathName[260]; /* will contain full path to this port driver */
if(HelpAlreadyInitialized) return;
/*
** Initialize Help
** ---------------
**
** Create an instance of the Help Manager, and associate it
** with the Frame. If the Association fails, we handle it
** the same way as if the creation fails, ie hwndHelp
** (the Help Manager Object Window handle) is set to NULL.
** If we can't load the Module containing the Help Panel
** definitions, we forget Help altogether.
*/
hWndActive = WinQueryActiveWindow(HWND_DESKTOP);
hWnd = WinQueryWindow(hWndActive,QW_OWNER);
/*
** if unable to get active window's owner
** use active window
*/
if (hWnd == (HWND)NULL)
hWnd = hWndActive ;
/*
** We need our module handle.
** Easiest way to do this is to find the path to our port driver
** from the system INI file.
** If not found in the INI file
** assume it is in the boot drive's \OS2\DLL directory
*/
/* change ? in szDefaultPortDrvPath to boot drive */
DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
sizeof (ULONG));
szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
PrfQueryProfileString (HINI_SYSTEMPROFILE,
"PM_PORT_DRIVER",
"PARALLEL",
szDefaultPortDrvPath,
szPathName,
256 );
/*
** get module handle for our dll
*/
DosQueryModuleHandle ( szPathName, &hModule);
/*
** Initialize a couple of the helpmgr structure elements
** First, get the title
**
** Now load the title
*/
WinLoadString (hAB, hModule,
(USHORT)(PORT_HELP_TITLE), (SHORT)(256), szBuf);
hmiHelpData.pszHelpWindowTitle = (PSZ)szBuf;
hmiHelpData.pszHelpLibraryName = "WPHELP.HLP";
hAB = WinQueryAnchorBlock(hWnd);
/*
** Only create a handle if we don't have one.
*/
if (hwndHelp == 0L)
hwndHelp = CALLCreateHelpInstance(hAB, &hmiHelpData);
/*
** Always associate the helpmgr handle with the active window
*/
if (hwndHelp != 0L)
{
if(!CALLAssociateHelpInstance(hwndHelp, hWnd) )
{
CALLDestroyHelpInstance(hwndHelp);
hwndHelp = (HWND)NULL;
}
}
/*
** If help was initialized, get rid of our hook. Otherwise, we have
** to ensure that our stub hook is the FIRST hook in the HK_HELP
** hook chain.
*/
if(hwndHelp != 0L)
{
HelpAlreadyInitialized = TRUE;
ReleaseHelpStubHook();
}
else
{
ReleaseHelpStubHook();
SetHelpStubHook();
}
}