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 >
C/C++ Source or Header  |  1995-04-14  |  68KB  |  2,216 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12. /**************************************************************************
  13.  *
  14.  * SOURCE FILE NAME = PARALLEL.C
  15.  *
  16.  * DESCRIPTIVE NAME = Parallel port driver
  17.  *
  18.  *
  19.  * VERSION = V2.0
  20.  *
  21.  * DATE
  22.  *
  23.  * DESCRIPTION
  24.  *
  25.  *
  26.  * FUNCTIONS
  27.  *
  28.  * ENTRY POINTS:
  29.  *
  30.  * DEPENDENCIES:
  31.  *
  32.  * NOTES
  33.  *
  34.  *
  35.  * STRUCTURES
  36.  *
  37.  * EXTERNAL REFERENCES
  38.  *
  39.  * EXTERNAL FUNCTIONS
  40.  *
  41. */
  42.  
  43. #define LINT_ARGS                      /* argument checking enabled         */
  44.  
  45. #define  INCL_DOS
  46. #define  INCL_GPI
  47. #undef   INCL_GPI
  48. #define  INCL_DEV
  49. #define  INCL_DOSMEMMGR                /* Include standard OS/2 support     */
  50. #define  INCL_DOSMODULEMGR             /* For DosLoadModule                 */
  51. #define  INCL_DOSPROCESS
  52. #define  INCL_GPILCIDS
  53. #define  INCL_WINCOMMON                /* Include Window Management support */
  54. #define  INCL_WINDOWMGR
  55. #define  INCL_WINSWITCHLIST
  56. #define  INCL_WINPROGRAMLIST
  57. #define  INCL_WINMENUS
  58. #define  INCL_WINWINDOWMGR
  59. #define  INCL_WINMESSAGEMGR
  60. #define  INCL_WINDIALOGS
  61. #define  INCL_WINSTATICS
  62. #define  INCL_WINLISTBOXES
  63. #define  INCL_WINMENUS
  64. #define  INCL_WINSYS
  65. #define  INCL_WINFRAMEMGR
  66. #define  INCL_INCLWINACCELERATORS
  67. #define  INCL_WINPOINTERS
  68. #define  INCL_WINERRORS
  69. #define  INCL_WINSHELLDATA
  70.  
  71. #define  INCL_WINTYPES
  72. #define  INCL_WINACCELERATORS
  73. #define  INCL_WINBUTTONS
  74. #define  INCL_WINENTRYFIELDS
  75. #define  INCL_WINRECTANGLES
  76. #define  INCL_WINTIMER
  77. #define  INCL_WINSCROLLBARS
  78. #define  INCL_WINHEAP
  79. #define  INCL_SHLERRORS
  80. #define  INCL_WININPUT
  81. #define  INCL_WINHELP
  82. #define  INCL_WINSTDSPIN
  83.  
  84. #define  INCL_SPL
  85. #define  INCL_SPLP
  86. #define  INCL_SPLERRORS
  87. #define  INCL_SHLERRORS
  88. #define  INCL_DOSERRORS
  89. #define  INCL_WINHOOKS
  90.  
  91. int acrtused=1;                     /* Define variable to say this is a DLL */
  92.  
  93. #include    <os2.h>
  94.  
  95. #include    <stdlib.h>
  96. #include    <string.h>
  97.  
  98. #include    "PARALLEL.h"
  99. #include    "port.h"
  100.  
  101. /*
  102. ** If port driver is not defined in INI file yet
  103. **   assume it exists in the boot drive's \OS2\DLL directory
  104. */
  105. CHAR szDefaultPortDrvPath[] = "?:\\OS2\\DLL\\PARALLEL.PDR";
  106.  
  107.  
  108. /*
  109. ** Below definition of PORTNAMES structure should be defined in
  110. ** common header file pmspl.h.
  111. */
  112. typedef struct _PORTNAMES
  113. {
  114.    PSZ pszPortName;         /* -> name of port(ie "LPT1)                    */
  115.    PSZ pszPortDesc;         /* -> description of port(ie "Parallel Port 1") */
  116. } PORTNAMES, *PPORTNAMES;
  117.  
  118.  
  119. /*
  120. ** We want to avoid automatically loading the help manager(HELPMGR.DLL),
  121. **   since this takes up lots of memory.
  122. ** Do this by only linking to the HELPMGR if user selects help item.
  123. ** We replace the WinxxxxHelpInstance calls with our local versions.
  124. ** These versions use DosLoadModule() and DosQueryProcAddr() to
  125. **   call the "real" help manager functions.
  126. ** The below function pointers, prototypes and variables are used
  127. **   to this end.
  128. */
  129.  
  130. BOOL APIENTRY CALLAssociateHelpInstance (HWND hwndHelpInstance, HWND hwndApp);
  131. BOOL APIENTRY CALLDestroyHelpInstance(HWND hwndHelpInstance);
  132. HWND APIENTRY CALLCreateHelpInstance(HAB hab,PHELPINIT phinitHMInitStructure);
  133. HWND APIENTRY CALLQueryHelpInstance(HWND hwndApp);
  134.  
  135. BOOL (* APIENTRY pfnWinAssociateHelpInstance)(HWND, HWND);
  136. BOOL (* APIENTRY pfnWinCreateHelpInstance)(HAB, PHELPINIT);
  137. BOOL (* APIENTRY pfnWinDestroyHelpInstance)(HWND);
  138. BOOL (* APIENTRY pfnWinQueryHelpInstance)(HWND);
  139.  
  140. VOID EXPENTRY InitializeHelp(VOID);
  141. BOOL EXPENTRY SetHelpStubHook(VOID);
  142. VOID EXPENTRY ReleaseHelpStubHook(VOID);
  143. INT  EXPENTRY HelpStubHook( HAB AppHAB, USHORT Context, USHORT IdTopic,
  144.                             USHORT IdSubTopic, PRECTL RectLPtr );
  145.  
  146. /*
  147. ** Global handle for helpmgr module, so it is only loaded once
  148. */
  149. HMODULE  hvHelpmgrModule;
  150.  
  151. HWND hwndHelp ;
  152. BOOL HelpStubHookIsSet;                                         /* for help */
  153. BOOL HelpAlreadyInitialized;                                    /* for help */
  154.  
  155.  
  156. /*
  157. ** HELPINIT -- help manager initialization structure
  158. */
  159. static HELPINIT hmiHelpData = {
  160.     sizeof(HELPINIT),
  161.     0L,
  162.     (PSZ)     NULL,
  163.     (PHELPTABLE) NULL,
  164.     (HMODULE) NULL,
  165.     (HMODULE) NULL,
  166.     (USHORT)  NULL,
  167.     (USHORT)  NULL,
  168.     (PSZ)     NULL,
  169.     CMIC_HIDE_PANEL_ID,
  170.     (PSZ)     PRT_HELPFILE_NAME
  171. };
  172.  
  173. /*
  174. ** Local Functions
  175. */
  176. ULONG  CalcBufLength ( HAB hab, HMODULE hModule );
  177. ULONG  CalcStructLength ( HAB hab, HMODULE hModule, USHORT usID );
  178. ULONG  NumPortsCanFit ( HAB hab, HMODULE hModule, ULONG cbBuf );
  179. VOID   CopyNPorts ( HAB hab, HMODULE hModule, PCH pBuf, ULONG ulReturned ) ;
  180. VOID   CopyStruct ( HAB hab, HMODULE hModule, USHORT usID, PCH pBuf,
  181.                    PULONG pulBeginStruct, PULONG pulBeginText );
  182. BOOL   GetPortDescription ( HAB hab, HMODULE hModule, PSZ pszPortName,
  183.                             PSZ pszPortDesc );
  184. ULONG  OpenParallPortDlg ( HAB hab, HMODULE hModule, PSZ pszPortName,
  185.                            PSZ pszAppName );
  186. BOOL   GetPortSettings( PPARALLDATA pParallData );
  187. BOOL   SavePortSettings(PPARALLDATA pParallData, HWND hDlg);
  188. VOID   RemoveLeadTrailBlanks ( PCH pTarget, PCH pSource );
  189. USHORT DisplayError ( HWND hwndOwner, HMODULE hModule,
  190.                       USHORT usStringID, USHORT usWinStyle );
  191. VOID   DE ( PCH str );
  192. MRESULT EXPENTRY ParallDlg( HWND hDlg, USHORT msg, MPARAM mp1, MPARAM mp2 );
  193.  
  194.  
  195. /****************************************************************************
  196.  *
  197.  * FUNCTION NAME = SplPdEnumPort
  198.  *
  199.  * DESCRIPTION   = Return ports supported by this port driver
  200.  *                 Currently this will return those ports this port
  201.  *                  driver supports by default.
  202.  *                 Future enhancement might be to also return any
  203.  *                  ports that have been added that now use this
  204.  *                  port driver.
  205.  *
  206.  * INPUT         = hab - anchor block handle
  207.  *                 pBuf - buffer to get enumerated PORTNAMES structures
  208.  *                 cbBuf - size(in bytes) of pBuf passed in
  209.  *
  210.  * OUTPUT        = *pulReturned - number of PORTNAMES structures stored in pBuf
  211.  *                 *pulTotal    - total ports supported by this port driver
  212.  *                 *pcbRequired - size(in bytes) of buffer needed to store
  213.  *                                all enumerated PORTNAMES entries.
  214.  *                 pBuf - gets an array(number elements is *pulReturned) of
  215.  *                        PORTNAMES structures.
  216.  *                        Each psz in PORTNAMES structure points to a string
  217.  *                        copied into the end of pBuf.
  218.  *
  219.  *                 typedef struct _PORTNAMES {
  220.  *                         PSZ pszPortName;  // Name of port, example: LPT1
  221.  *                         PSZ pszPortDesc;  // Port description
  222.  *                 } PORTNAMES;
  223.  *
  224.  * RETURN-NORMAL = 0 - if all portnames and descriptions fit in pBuf
  225.  *
  226.  * RETURN-ERROR  = ERROR_INSUFFICIENT_BUFFER - if no PORTNAMES structs
  227.  *                                             could fit in buffer.  Caller
  228.  *                                             uses *pcbRequired to allocate
  229.  *                                             a buffer big enough to store all
  230.  *                                             port names.
  231.  *                 ERROR_MORE_DATA - if some, but not all, PORTNAMES structs
  232.  *                                   could fit in buffer.  Caller
  233.  *                                   uses *pcbRequired to allocate
  234.  *                                   a buffer big enough to store all
  235.  *                                   port names.
  236.  *
  237.  *      NOTE: early versions of the print object expected ERROR_MORE_DATA
  238.  *            to be returned, even when no PORTNAMES structures would fit.
  239.  *            For this reason, we do not return ERROR_INSUFFICIENT_BUFFER
  240.  *
  241.  ****************************************************************************/
  242.  
  243. APIRET APIENTRY SplPdEnumPort ( HAB hab,
  244.                                 PVOID pBuf,
  245.                                 ULONG cbBuf,
  246.                                 PULONG pulReturned,
  247.                                 PULONG pulTotal,
  248.                                 PULONG pcbRequired )
  249.  
  250. {
  251.    HMODULE hModule;
  252.    ULONG   ulBootDrive;
  253.    ULONG   rcLoadMod;
  254.    CHAR    szPathName[260]; /* will contain full path to this port driver */
  255.  
  256.       /*
  257.       ** ensure pointers not null
  258.       */
  259.    if (!pulReturned ||
  260.        !pulTotal ||
  261.        !pcbRequired)
  262.    {
  263.       return(ERROR_INVALID_PARAMETER);
  264.    }
  265.  
  266.       /*
  267.       ** if buffer length is supplied then there should be pBuf
  268.       */
  269.    if (!pBuf && cbBuf)
  270.    {
  271.       return(ERROR_INVALID_PARAMETER);
  272.    }
  273.  
  274.       /*
  275.       ** We need our module handle.
  276.       ** Easiest way to do this is to find the path to our port driver
  277.       **  from the system INI file.
  278.       ** If not found in the INI file
  279.       **  assume it is in the boot drive's \OS2\DLL directory
  280.       */
  281.  
  282.    /* change ? in szDefaultPortDrvPath to boot drive */
  283.    DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
  284.                     sizeof (ULONG));
  285.    szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
  286.  
  287.    PrfQueryProfileString (HINI_SYSTEMPROFILE,
  288.                           "PM_PORT_DRIVER",
  289.                           "PARALLEL",
  290.                           szDefaultPortDrvPath,
  291.                           szPathName,
  292.                           256 );
  293.  
  294.       /*
  295.       ** get module handle for our dll
  296.       */
  297.    rcLoadMod = DosLoadModule (NULL, 0, szPathName, &hModule);
  298.  
  299.       /*
  300.       ** check if cbBuf is 0 - then return number of ports in pulTotal
  301.       ** and number of bytes required in pcbRequired
  302.       */
  303.    if (cbBuf == 0L)
  304.    {
  305.       *pulReturned = 0;
  306.       *pcbRequired = CalcBufLength (hab, hModule);
  307.       *pulTotal    = 3 ;            /* Currently support LPT1 LPT2 and LPT3 */
  308.       if (!rcLoadMod)
  309.         DosFreeModule (hModule);
  310.  
  311.            /*
  312.            ** NOTE: early version of the print object checked for
  313.            **       ERROR_MORE_DATA instead of ERROR_INSUFFICIENT_BUFFER
  314.            **       For this reason we return ERROR_MORE_DATA here.
  315.            */
  316.         return(ERROR_MORE_DATA);
  317.    }
  318.  
  319.       /*
  320.       ** check number of ports info we can fit in supplied buffer
  321.       */
  322.    *pulTotal    = 3 ; /* Currently support LPT1 LPT2 and LPT3 */
  323.    *pcbRequired = CalcBufLength (hab, hModule);
  324.    *pulReturned = NumPortsCanFit (hab, hModule, cbBuf);
  325.  
  326.       /*
  327.       ** return error if we can not fit one port.
  328.       */
  329.    if (!(*pulReturned))
  330.    {
  331.       if (!rcLoadMod)
  332.         DosFreeModule (hModule);
  333.       return(ERROR_INSUFFICIENT_BUFFER);
  334.    }
  335.  
  336.       /*
  337.       ** copy all the ports which we can store in the pBuf
  338.       */
  339.    CopyNPorts (hab, hModule, (PCH)pBuf, *pulReturned);
  340.  
  341.       /*
  342.       ** Free the module - we do not need it any more.
  343.       */
  344.    if (!rcLoadMod)
  345.      DosFreeModule (hModule);
  346.  
  347.       /*
  348.       ** copy all the ports which we can store in the pBuf
  349.       */
  350.    if (*pulReturned < *pulTotal)
  351.    {
  352.       return(ERROR_MORE_DATA);
  353.    }
  354.  
  355.    return(NO_ERROR);
  356. }
  357.  
  358. /****************************************************************************
  359.  *
  360.  * FUNCTION NAME = SplPdInitPort
  361.  *
  362.  * DESCRIPTION   = Initialize port on behalf of the spooler
  363.  *
  364.  * INPUT         = hFile       - File handle to port
  365.  *                 pszPortName - name of port to initialize
  366.  *
  367.  * OUTPUT        = Sets Parallel port settings(port timeout)
  368.  *
  369.  * RETURN-NORMAL = 0
  370.  *
  371.  * RETURN-ERROR  = ERROR_INVALID_PARAMETER - if     port name given
  372.  *
  373.  ****************************************************************************/
  374.  
  375. APIRET APIENTRY SplPdInitPort ( HFILE hFile,
  376.                                 PSZ pszPortName )
  377. {
  378.     USHORT usParamPacket= 0;
  379.     USHORT usDataPacket = 0;
  380.     UCHAR  bInfRetry;
  381.     CHAR   chBuf[STR_LEN_PORTNAME];
  382.     CHAR   chInitVal[STR_LEN_PORTNAME];
  383.     PCH    pchPortDriver = chInitVal;
  384.     ULONG  ulReturned1;
  385.     ULONG  ulReturned2;
  386.  
  387.       /*
  388.       ** Check if port name string is NULL. This is an error.
  389.       */
  390.    if (!pszPortName)
  391.    {
  392.       return(ERROR_INVALID_PARAMETER);
  393.    }
  394.  
  395.       /*
  396.       ** Make Application name string( "PM_PortName" )
  397.       */
  398.    strcpy (chBuf, APPNAME_LEAD_STR);
  399.    strcat (chBuf, pszPortName);
  400.  
  401.       /*
  402.       ** Check if this port is parallel port.
  403.       */
  404.    if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
  405.                                 KEY_PORTDRIVER, NULL, pchPortDriver,
  406.                                 STR_LEN_PORTNAME)))
  407.    {
  408.       return(ERROR_INVALID_PARAMETER);
  409.    }
  410.  
  411.    if (strcmp (pchPortDriver, DEF_PORTDRIVER))
  412.    {
  413.       return(ERROR_INVALID_PARAMETER);
  414.    }
  415.  
  416.       /*
  417.       ** Check if this port is installed.
  418.       */
  419.    if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
  420.                                 KEY_TIMEOUT, NULL, chInitVal,
  421.                                 STR_LEN_PORTNAME)))
  422.    {
  423.       return(ERROR_INVALID_PARAMETER);
  424.    }
  425.       /*
  426.       ** Set printer timeout
  427.       */
  428.     usDataPacket = (USHORT)atoi (chInitVal);
  429.  
  430.     ulReturned2 = 2L ;
  431.  
  432.     DosDevIOCtl(
  433.                 hFile,                    /* Hfile passed into SplPdInit */
  434.                 0x5,                      /* Category number             */
  435.                 0x4e,                     /* Function number             */
  436.                 NULL,                     /* pParams - not needed        */
  437.                 0,                        /* sizeof *pParms              */
  438.                 NULL,                     /* &size in/out                */
  439.                 (PVOID) &usDataPacket,    /* points to LPT timeout value */
  440.                 sizeof (USHORT),          /* sizeof usDataPacket         */
  441.                 &ulReturned2);            /* &size in/out                */
  442.  
  443.  
  444.       /*
  445.       ** Check for initialization settings for multiple hardware access
  446.       **
  447.       ** If not there, or not equal to "1;"
  448.       **   disallow multiple hardware access
  449.       ** else(if equal to "1;")
  450.       **   allow multiple hardware access to this LPT port
  451.       **
  452.       */
  453.    if ( (PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
  454.                                 KEY_INITIALIZATION, NULL, chInitVal,
  455.                                 STR_LEN_PORTNAME))
  456.         && ( chInitVal[0] == '1' ) )
  457.    {
  458.       /* Set to allow multiple hardware access by setting bit 0 on   */
  459.       usDataPacket = 0x0001 ;
  460.    }
  461.    else
  462.    {
  463.       /* Set to not allow multiple hardware access by clearing bit 0 */
  464.       usDataPacket = 0x0000 ;
  465.    }
  466.       /*
  467.       ** Set multiple hardware access
  468.       */
  469.  
  470.     /* Set return sizes so IOCTL will work */
  471.     ulReturned1 = 1L ;
  472.     ulReturned2 = 1L ;
  473.  
  474.     DosDevIOCtl(
  475.                 hFile,                    /* Hfile passed into SplPdInit */
  476.                 0x5,                      /* Category number             */
  477.                 0x51,                     /* Function number             */
  478.                 (PVOID) &usParamPacket,   /* -> command byte - must be 0 */
  479.                 sizeof (BYTE),
  480.                 &ulReturned1,
  481.                 (PVOID) &usDataPacket,    /* points to flag byte         */
  482.                 sizeof (BYTE),
  483.                 &ulReturned2);
  484.  
  485.  
  486.       /*
  487.       ** Set infinite retry to false.
  488.       */
  489.     bInfRetry = (UCHAR)FALSE;
  490.     DosDevIOCtl(
  491.                  hFile,
  492.                  0x05,
  493.                  0x44,
  494.                  NULL,
  495.                  0L,
  496.                  NULL,
  497.                  (PCH)&bInfRetry,
  498.                  sizeof (USHORT),
  499.                  &ulReturned2);
  500.  
  501.    return(NO_ERROR);
  502. }
  503.  
  504. /****************************************************************************
  505.  *
  506.  * FUNCTION NAME = SplPdInstallPort
  507.  *
  508.  * DESCRIPTION   = Tells port driver the name of a port that needs to be
  509.  *                   installed.
  510.  *                 Port driver should write Initialization/Termination
  511.  *                   strings to the INI file.
  512.  *                 Typically SplPdSetPort will be called after this.
  513.  *                 This should allow any port to be added for this port driver.
  514.  *                   (ie: if it is not a port we returned in SplPdEnumPort,
  515.  *                          still allow the port to use this port driver).
  516.  *
  517.  * INPUT         = hab         - Anchor block handle
  518.  *                 pszPortName - name of port to be installed
  519.  *
  520.  * OUTPUT        =
  521.  *
  522.  * RETURN-NORMAL = 0
  523.  *
  524.  * RETURN-ERROR  = ERROR_INVALID_PARAMETER - if     port name given
  525.  *
  526.  ****************************************************************************/
  527.  
  528. APIRET APIENTRY SplPdInstallPort ( HAB hab,
  529.                                    PSZ pszPortName )
  530. {
  531.    CHAR    chBuf[STR_LEN_PORTNAME];
  532.    CHAR    chPortDesc[STR_LEN_PORTDESC];
  533.    HMODULE hModule;
  534.    ULONG   ulBootDrive;
  535.    CHAR    szPathName[260];   /* will contain full path to this port driver */
  536.  
  537.       /*
  538.       ** Check if port name string is NULL. This is an error.
  539.       */
  540.    if (!pszPortName)
  541.    {
  542.       return(ERROR_INVALID_PARAMETER);
  543.    }
  544.       /*
  545.       ** We need our module handle.
  546.       ** Easiest way to do this is to find the path to our port driver
  547.       **  from the system INI file.
  548.       ** If not found in the INI file
  549.       **  assume it is in the boot drive's \OS2\DLL directory
  550.       */
  551.  
  552.    /* change ? in szDefaultPortDrvPath to boot drive */
  553.    DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
  554.                     sizeof (ULONG));
  555.    szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
  556.  
  557.    PrfQueryProfileString (HINI_SYSTEMPROFILE,
  558.                           "PM_PORT_DRIVER",
  559.                           "PARALLEL",
  560.                           szDefaultPortDrvPath,
  561.                           szPathName,
  562.                           256 );
  563.  
  564.    hModule = 0L ;                             /* Init module handle to null */
  565.  
  566.       /*
  567.       ** get module handle for our dll
  568.       */
  569.    DosLoadModule (NULL, 0, szPathName, &hModule);
  570.  
  571.       /*
  572.       ** Check if we have description for port
  573.       */
  574.    if (!GetPortDescription (hab, hModule, pszPortName, chPortDesc))
  575.    {
  576.       /*
  577.       ** Port description not found, use port name
  578.       */
  579.       strcpy( chPortDesc, pszPortName );
  580.    }
  581.  
  582.       /*
  583.       ** Free the module
  584.       */
  585.    DosFreeModule (hModule);
  586.  
  587.       /*
  588.       ** Make Application name string.
  589.       */
  590.    strcpy (chBuf, APPNAME_LEAD_STR);
  591.    strcat (chBuf, pszPortName);
  592.  
  593.       /*
  594.       ** Write data for this port in ini file with new format.
  595.       */
  596.    PrfWriteProfileString (HINI_SYSTEMPROFILE,
  597.                           chBuf,
  598.                           KEY_DESCRIPTION,
  599.                           chPortDesc);
  600.  
  601.    PrfWriteProfileString (HINI_SYSTEMPROFILE,
  602.                           chBuf,
  603.                           KEY_INITIALIZATION,
  604.                           DEF_INITIALIZATION);
  605.  
  606.    PrfWriteProfileString (HINI_SYSTEMPROFILE,
  607.                           chBuf,
  608.                           KEY_TERMINATION,
  609.                           DEF_TERMINATION);
  610.  
  611.    PrfWriteProfileString (HINI_SYSTEMPROFILE,
  612.                           chBuf,
  613.                           KEY_TIMEOUT,
  614.                           DEF_TIMEOUT);
  615.  
  616.    PrfWriteProfileString (HINI_SYSTEMPROFILE,
  617.                           chBuf,
  618.                           KEY_PORTDRIVER,
  619.                           DEF_PORTDRIVER);
  620.  
  621.       /*
  622.       ** Write data for this port in ini file with old format.
  623.       */
  624.    PrfWriteProfileString (HINI_SYSTEMPROFILE,
  625.                           APPNAME_PM_SPOOLER_PORT,
  626.                           pszPortName,
  627.                           DEF_OLD_INITIALIZATION);
  628.  
  629.    return(NO_ERROR);
  630. }
  631.  
  632. /****************************************************************************
  633.  *
  634.  * FUNCTION NAME = SplPdGetPortIcon
  635.  *
  636.  * DESCRIPTION   = Return Resource ID of icon representing this port.
  637.  *                 Note: only one icon will represent all ports supported
  638.  *                       by a port driver.
  639.  *
  640.  * INPUT         = hab         - Anchor block handle
  641.  *                 idIcon      - gets Resource ID of icon bit map
  642.  *
  643.  * OUTPUT        =
  644.  *
  645.  * RETURN-NORMAL = TRUE
  646.  *
  647.  * RETURN-ERROR  = FALSE - if unable to return icon Resource ID
  648.  *
  649.  ****************************************************************************/
  650.  
  651. BOOL   APIENTRY SplPdGetPortIcon ( HAB hab,
  652.                                    PULONG idIcon )
  653. {
  654.       /*
  655.       ** Check for our global port icon ID(is always set)
  656.       */
  657.    if (idIcon)
  658.    {
  659.       *idIcon = PARALLEL_ICON;
  660.    }
  661.    return(TRUE);
  662. }
  663.  
  664. /****************************************************************************
  665.  *
  666.  * FUNCTION NAME = SplPdQueryPort
  667.  *
  668.  * DESCRIPTION   = Returns textual data that describes the port configuration.
  669.  *
  670.  * INPUT         = hab         - Anchor block handle
  671.  *                 pszPortName - name of port to get configuration for
  672.  *                 pBufIn      - pointer to buffer of returned data structures
  673.  *                 cbBuf       - Size of pBufIn in bytes
  674.  *                 cItems      - Count of number of strings of descriptions
  675.  *                               returned
  676.  *
  677.  * OUTPUT        =
  678.  *
  679.  * RETURN-NORMAL = 0
  680.  *
  681.  * RETURN-ERROR  = ERROR_INSUFFICIENT_BUFFER - if buffer is too small
  682.  *                 ERROR_INVALID_PARAMETER - if     port name given
  683.  *
  684.  ****************************************************************************/
  685.  
  686. APIRET APIENTRY SplPdQueryPort ( HAB hab,
  687.                                  PSZ pszPortName,
  688.                                  PVOID pBufIn,
  689.                                  ULONG cbBuf,
  690.                                  PULONG cItems )
  691. {
  692.    HMODULE hModule;
  693.    CHAR chString[STR_LEN_DESC];
  694.    USHORT usNumLines;
  695.    USHORT usLineID;
  696.    USHORT usStrLength;
  697.    ULONG  ulBootDrive;
  698.    PCH    pBuf = (PCH)pBufIn;
  699.    CHAR   szPathName[260];    /* will contain full path to this port driver */
  700.  
  701.       /*
  702.       ** check pointer to all the return variables is not null
  703.       */
  704.    if (!cItems)
  705.    {
  706.       return(ERROR_INVALID_PARAMETER);
  707.    }
  708.  
  709.       /*
  710.       ** if pBuf or cbBuf is NULL - it is an error.
  711.       */
  712.    if (!pBuf || !cbBuf)
  713.    {
  714.       return(ERROR_INVALID_PARAMETER);
  715.    }
  716.  
  717.       /*
  718.       ** We need our module handle.
  719.       ** Easiest way to do this is to find the path to our port driver
  720.       **  from the system INI file.
  721.       ** If not found in the INI file
  722.       **  assume it is in the boot drive's \OS2\DLL directory
  723.       */
  724.  
  725.    /* change ? in szDefaultPortDrvPath to boot drive */
  726.    DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
  727.                     sizeof (ULONG));
  728.    szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
  729.  
  730.    PrfQueryProfileString (HINI_SYSTEMPROFILE,
  731.                           "PM_PORT_DRIVER",
  732.                           "PARALLEL",
  733.                           szDefaultPortDrvPath,
  734.                           szPathName,
  735.                           256 );
  736.  
  737.    hModule = 0L ;                             /* Init module handle to null */
  738.  
  739.       /*
  740.       ** get module handle for our dll
  741.       */
  742.    DosLoadModule (NULL, 0, szPathName, &hModule);
  743.  
  744.    chString[0] = '\0' ;
  745.  
  746.       /*
  747.       ** get number of lines.
  748.       */
  749.    WinLoadString(hab, hModule, (USHORT)ID_NUMBER_OF_DESC_LINES, STR_LEN_DESC,
  750.                  chString);
  751.    usNumLines = (USHORT)atoi (chString);
  752.    usLineID = ID_FIRST_DESC_LINES;
  753.    for (*cItems = 0; *cItems < usNumLines; *cItems++)
  754.    {
  755.       WinLoadString(hab, hModule, usLineID, STR_LEN_DESC, chString);
  756.       if (cbBuf >= (usStrLength = (USHORT)(strlen (chString) + 1)))
  757.       {
  758.          strcpy (pBuf, chString);
  759.          pBuf += usStrLength;
  760.          cbBuf -= usStrLength;
  761.       }
  762.       else
  763.       {
  764.          DosFreeModule (hModule);
  765.          return(ERROR_INSUFFICIENT_BUFFER);
  766.       }
  767.    }
  768.    DosFreeModule (hModule);
  769.    return(NO_ERROR);
  770.  
  771. }
  772.  
  773. /****************************************************************************
  774.  *
  775.  * FUNCTION NAME = SplPdSetPort
  776.  *
  777.  * DESCRIPTION   = Display a dialog to allow the user to browse and modify
  778.  *                 port configurations.
  779.  *
  780.  * INPUT         = hab         - Anchor block handle
  781.  *                 pszPortName - name of port to configure
  782.  *                 flModified  - Flag to indicate that the configuration
  783.  *                               has been modified.(TRUE if modified).
  784.  *
  785.  * OUTPUT        =
  786.  *
  787.  * RETURN-NORMAL = 0
  788.  *
  789.  * RETURN-ERROR  = ERROR_INVALID_PARAMETER - if     port name given
  790.  *
  791.  ****************************************************************************/
  792.  
  793. APIRET APIENTRY SplPdSetPort ( HAB hab,
  794.                                PSZ pszPortName,
  795.                                PULONG flModified )
  796. {
  797.     CHAR chBuf[STR_LEN_PORTNAME];
  798.     CHAR chPortDriver[STR_LEN_PORTNAME];
  799.     HMODULE hModule;
  800.     ULONG   ulBootDrive;
  801.     CHAR    szPathName[260];   /* will contain full path to this port driver */
  802.  
  803.       /*
  804.       ** Check if port name string is NULL. This is an error.
  805.       */
  806.    if (!pszPortName || !flModified)
  807.    {
  808.       return(ERROR_INVALID_PARAMETER);
  809.    }
  810.  
  811.       /*
  812.       ** Make Application name string( "PM_PortName" ).
  813.       */
  814.    strcpy (chBuf, APPNAME_LEAD_STR);
  815.    strcat (chBuf, pszPortName);
  816.  
  817.       /*
  818.       ** Check if this port is parallel port.
  819.       */
  820.    if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
  821.                                 KEY_PORTDRIVER, NULL, chPortDriver,
  822.                                 STR_LEN_PORTNAME)))
  823.    {
  824.       return(ERROR_INVALID_PARAMETER);
  825.    }
  826.  
  827.    if (strcmp (chPortDriver, DEF_PORTDRIVER))
  828.    {
  829.       return(ERROR_INVALID_PARAMETER);
  830.    }
  831.  
  832.       /*
  833.       ** We need our module handle.
  834.       ** Easiest way to do this is to find the path to our port driver
  835.       **  from the system INI file.
  836.       ** If not found in the INI file
  837.       **  assume it is in the boot drive's \OS2\DLL directory
  838.       */
  839.  
  840.    /* change ? in szDefaultPortDrvPath to boot drive */
  841.    DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
  842.                     sizeof (ULONG));
  843.    szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
  844.  
  845.    PrfQueryProfileString (HINI_SYSTEMPROFILE,
  846.                           "PM_PORT_DRIVER",
  847.                           "PARALLEL",
  848.                           szDefaultPortDrvPath,
  849.                           szPathName,
  850.                           256 );
  851.  
  852.    hModule = 0L ;                             /* Init module handle to null */
  853.  
  854.       /*
  855.       ** get module handle for our dll
  856.       */
  857.    DosLoadModule (NULL, 0, szPathName, &hModule);
  858.  
  859.       /*
  860.       ** Load the dialog for user to change.
  861.       */
  862.    *flModified = OpenParallPortDlg (hab, hModule, pszPortName, chBuf);
  863.  
  864.       /*
  865.       ** free the module
  866.       */
  867.    DosFreeModule (hModule);
  868.    return(NO_ERROR);
  869. }
  870.  
  871. /****************************************************************************
  872.  *
  873.  * FUNCTION NAME = SplPdRemovePort
  874.  *
  875.  * DESCRIPTION   = Tells port driver the name of a port that needs to be removed.
  876.  *                 Port driver should remove its data from the INI file.
  877.  *
  878.  * INPUT         = hab         - Anchor block handle
  879.  *                 pszPortName - name of port to be removed
  880.  *
  881.  * OUTPUT        =
  882.  *
  883.  * RETURN-NORMAL = 0
  884.  *
  885.  * RETURN-ERROR  = ERROR_INVALID_PARAMETER - if     port name given
  886.  *
  887.  ****************************************************************************/
  888.  
  889. APIRET APIENTRY SplPdRemovePort ( HAB hab,
  890.                                   PSZ pszPortName )
  891. {
  892.     CHAR chBuf[STR_LEN_PORTNAME];
  893.     CHAR chPortDriver[STR_LEN_PORTNAME];
  894.  
  895.       /*
  896.       ** Check if port name string is NULL. This is an error.
  897.       */
  898.    if (!pszPortName)
  899.    {
  900.       return(ERROR_INVALID_PARAMETER);
  901.    }
  902.  
  903.       /*
  904.       ** Make Application name string.
  905.       */
  906.    strcpy (chBuf, APPNAME_LEAD_STR);
  907.    strcat (chBuf, pszPortName);
  908.  
  909.       /*
  910.       ** Check if this port is parallel port.
  911.       */
  912.    if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
  913.                                 KEY_PORTDRIVER, NULL, chPortDriver,
  914.                                 STR_LEN_PORTNAME)))
  915.    {
  916.       return(ERROR_INVALID_PARAMETER);
  917.    }
  918.  
  919.    if (strcmp (chPortDriver, DEF_PORTDRIVER))
  920.    {
  921.       return(ERROR_INVALID_PARAMETER);
  922.    }
  923.  
  924.       /*
  925.       ** We found port to be removed.
  926.       ** Remove it from new format "PM_portname"
  927.       */
  928.    PrfWriteProfileString (HINI_SYSTEMPROFILE, chBuf, NULL, NULL);
  929.  
  930.       /*
  931.       ** remove this port from old format.
  932.       */
  933.    PrfWriteProfileString (HINI_SYSTEMPROFILE,
  934.                           APPNAME_PM_SPOOLER_PORT,
  935.                           pszPortName,
  936.                           NULL);
  937.    return(NO_ERROR);
  938.  
  939. }
  940.  
  941. /****************************************************************************
  942.  *
  943.  * FUNCTION NAME = SplPdTermPort
  944.  *
  945.  * DESCRIPTION   = Terminate port on behalf of the spooler
  946.  *
  947.  * INPUT         = hFile       - File handle to port
  948.  *                 pszPortName - name of port whose job is completing
  949.  *
  950.  * OUTPUT        = Sets Parallel port settings(port timeout)
  951.  *
  952.  * RETURN-NORMAL = 0
  953.  *
  954.  * RETURN-ERROR  = ERROR_INVALID_PARAMETER - if     port name given
  955.  *
  956.  ****************************************************************************/
  957.  
  958. SPLERR EXPENTRY SplPdTermPort ( HFILE hFile,
  959.                                 PSZ pszPortName )
  960. {
  961.     CHAR chBuf[STR_LEN_PORTNAME];
  962.     PCH chPortDriver[STR_LEN_PORTNAME];
  963.  
  964.       /*
  965.       ** We do not have to take any action. Return NO_ERROR
  966.       */
  967.    return(NO_ERROR);
  968.  
  969. #ifdef TERM_ACTION_NEEDED
  970.       /*
  971.       ** Check if port name string is NULL. This is an error.
  972.       */
  973.    if (!pszPortName)
  974.    {
  975.       return(ERROR_INVALID_PARAMETER);
  976.    }
  977.  
  978.       /*
  979.       ** Make Application name string.
  980.       */
  981.    strcpy (chBuf, APPNAME_LEAD_STR);
  982.    strcat (chBuf, pszPortName);
  983.  
  984.       /*
  985.       ** Check if this port is parallel port.
  986.       */
  987.    if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE, chBuf,
  988.                                   KEY_PORTDRIVER, NULL, chPortDriver, 64)))
  989.    {
  990.       return(ERROR_INVALID_PARAMETER);
  991.    }
  992.  
  993.    if (strcmp ((PSZ)chPortDriver, DEF_PORTDRIVER))
  994.    {
  995.       return(ERROR_INVALID_PARAMETER);
  996.    }
  997.  
  998.       /*
  999.       ** We do not have to take any action - return NO_ERROR
  1000.       */
  1001.    return(NO_ERROR);
  1002.  
  1003. #endif
  1004.  
  1005. }
  1006.  
  1007. /****************************************************************************
  1008.  *
  1009.  * FUNCTION NAME = CalcBufLength
  1010.  *
  1011.  * DESCRIPTION   = Determine how big buffer is needed to store all PORTNAMES
  1012.  *                 structures
  1013.  *
  1014.  * INPUT         = hab - anchor block handle
  1015.  *                 hModule - this port driver's module handle
  1016.  *
  1017.  * OUTPUT        = length of buffer necessary to store all default port names
  1018.  *                 supported by this port driver.
  1019.  *
  1020.  * RETURN-NORMAL =
  1021.  * RETURN-ERROR  =
  1022.  *
  1023.  ****************************************************************************/
  1024.  
  1025. ULONG CalcBufLength ( HAB hab,
  1026.                       HMODULE hModule )
  1027. {
  1028.    ULONG cbRequired;
  1029.    USHORT usID;
  1030.  
  1031.    cbRequired = 0;
  1032.  
  1033.       /*
  1034.       ** calculate length required to fit all the port info.
  1035.       */
  1036.    for (usID = PORT_ID_FIRST; usID <= PORT_ID_LAST; usID += 2)
  1037.    {
  1038.       cbRequired += CalcStructLength (hab, hModule, usID);
  1039.    }
  1040.  
  1041.    return(cbRequired);
  1042. }
  1043.  
  1044. /****************************************************************************
  1045.  *
  1046.  * FUNCTION NAME = CalcStructLength
  1047.  *
  1048.  * DESCRIPTION   = Determine size of buffer needed to store PORTNAMES structure
  1049.  *                 for given string ID.
  1050.  *
  1051.  * INPUT         = hab     - anchor block handle
  1052.  *                 hModule - this port driver's module handle
  1053.  *                 usID    - string ID for port name
  1054.  *
  1055.  * OUTPUT        = length of buffer necessary to store this port name
  1056.  *
  1057.  * RETURN-NORMAL =
  1058.  * RETURN-ERROR  =
  1059.  *
  1060.  ****************************************************************************/
  1061.  
  1062. ULONG CalcStructLength ( HAB hab,
  1063.                          HMODULE hModule,
  1064.                          USHORT usID )
  1065. {
  1066.    ULONG cbRequired;
  1067.    CHAR chString[STR_LEN_PORTDESC];
  1068.  
  1069.    cbRequired = 0;
  1070.  
  1071.    WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, chString);
  1072.    cbRequired += strlen (chString) + 1;
  1073.    WinLoadString(hab, hModule, (USHORT)(usID + 1), STR_LEN_PORTDESC, chString);
  1074.    cbRequired += strlen (chString) + 1;
  1075.    cbRequired += sizeof (PORTNAMES);
  1076.    return(cbRequired);
  1077. }
  1078.  
  1079. /****************************************************************************
  1080.  *
  1081.  * FUNCTION NAME = NumPortsCanFit
  1082.  *
  1083.  * DESCRIPTION   = Determine how many ports can fit in buffer
  1084.  *
  1085.  * INPUT         = hab     - anchor block handle
  1086.  *                 hModule - this port driver's module handle
  1087.  *                 cbBuf   - size in bytes of buffer to hold PORTNAMES
  1088.  *
  1089.  * OUTPUT        = count of PORTNAMES structures that can fit in buffer
  1090.  *
  1091.  * RETURN-NORMAL =
  1092.  * RETURN-ERROR  =
  1093.  *
  1094.  ****************************************************************************/
  1095.  
  1096. ULONG NumPortsCanFit ( HAB hab,
  1097.                        HMODULE hModule,
  1098.                        ULONG cbBuf )
  1099. {
  1100.    ULONG cbRequired;
  1101.    USHORT usID;
  1102.    ULONG ulNumPort;
  1103.  
  1104.    cbRequired = 0;
  1105.    ulNumPort = 0;
  1106.  
  1107.       /*
  1108.       ** calculate how many ports we can fit in buf.
  1109.       */
  1110.    for (usID = PORT_ID_FIRST; usID <= PORT_ID_LAST; usID += 2)
  1111.    {
  1112.       cbRequired += CalcStructLength (hab, hModule, usID);
  1113.       if (cbRequired > cbBuf)
  1114.       {
  1115.          return(ulNumPort);
  1116.       }
  1117.       ulNumPort++;
  1118.    }
  1119.  
  1120.    return(ulNumPort);
  1121. }
  1122.  
  1123. /****************************************************************************
  1124.  *
  1125.  * FUNCTION NAME = CopyNPorts
  1126.  *
  1127.  * DESCRIPTION   = Copy given number of ports into buffer
  1128.  *
  1129.  * INPUT         = hab     - anchor block handle
  1130.  *                 hModule - this port driver's module handle
  1131.  *                 pBuf    - buffer to get PORTNAMES structures
  1132.  *                 ulReturned - number of ports to return
  1133.  *
  1134.  * OUTPUT        = pBuf is updated
  1135.  *
  1136.  * RETURN-NORMAL =
  1137.  * RETURN-ERROR  =
  1138.  *
  1139.  ****************************************************************************/
  1140.  
  1141. VOID  CopyNPorts ( HAB hab,
  1142.                    HMODULE hModule,
  1143.                    PCH pBuf,
  1144.                    ULONG ulReturned )
  1145. {
  1146.    USHORT usID;
  1147.    ULONG ulBeginText;
  1148.    ULONG ulBeginStruct;
  1149.  
  1150.    ulBeginText = ulReturned * sizeof (PORTNAMES);
  1151.    ulBeginStruct = 0;
  1152.  
  1153.    for (usID = PORT_ID_FIRST;
  1154.         usID <= PORT_ID_LAST && ulReturned;
  1155.         usID += 2, --ulReturned)
  1156.    {
  1157.       CopyStruct (hab, hModule, usID, pBuf, &ulBeginStruct, &ulBeginText);
  1158.    }
  1159. }
  1160.  
  1161. /****************************************************************************
  1162.  *
  1163.  * FUNCTION NAME = CopyStruct
  1164.  *
  1165.  * DESCRIPTION   = Copy single PORTNAMES structure to buffer
  1166.  *
  1167.  * INPUT         = hab     - anchor block handle
  1168.  *                 hModule - this port driver's module handle
  1169.  *                 usID    - string ID for port to return
  1170.  *                 pBuf    - buffer to get PORTNAMES structures
  1171.  *                 pulBeginStruct - offset from begin of pBuf to store next
  1172.  *                                  PORTNAMES
  1173.  *                 pulBeginText   - offset from pBuf to store next string
  1174.  *
  1175.  * OUTPUT        = pBuf is updated
  1176.  *
  1177.  * RETURN-NORMAL =
  1178.  * RETURN-ERROR  =
  1179.  *
  1180.  ****************************************************************************/
  1181.  
  1182. VOID CopyStruct ( HAB hab,
  1183.                   HMODULE hModule,
  1184.                   USHORT usID,
  1185.                   PCH pBuf,
  1186.                   PULONG pulBeginStruct,
  1187.                   PULONG pulBeginText )
  1188. {
  1189.    PPORTNAMES pPortNames;
  1190.  
  1191.    pPortNames = (PPORTNAMES)(pBuf + *pulBeginStruct);
  1192.    *pulBeginStruct += sizeof (PORTNAMES);
  1193.  
  1194.       /*
  1195.       ** copy port name in the structure
  1196.       */
  1197.    pPortNames->pszPortName = pBuf + *pulBeginText;
  1198.    WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, pPortNames->pszPortName);
  1199.    *pulBeginText += strlen (pPortNames->pszPortName) + 1;
  1200.  
  1201.       /*
  1202.       ** copy port description to the structure
  1203.       */
  1204.    pPortNames->pszPortDesc = pBuf + *pulBeginText;
  1205.    WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, pPortNames->pszPortDesc);
  1206.    *pulBeginText += strlen (pPortNames->pszPortDesc) + 1;
  1207. }
  1208.  
  1209. /****************************************************************************
  1210.  *
  1211.  * FUNCTION NAME = GetPortDescription
  1212.  *
  1213.  * DESCRIPTION   = Get port description from our string resources.
  1214.  *
  1215.  * INPUT         = hab     - anchor block handle
  1216.  *                 hModule - this port driver's module handle
  1217.  *                 pszPortName - name of port to get description for
  1218.  *                 pszPortDesc - gets port description
  1219.  *
  1220.  * OUTPUT        = TRUE  - if portname description is found
  1221.  *                 FALSE - if not
  1222.  *
  1223.  * RETURN-NORMAL =
  1224.  * RETURN-ERROR  =
  1225.  *
  1226.  ****************************************************************************/
  1227.  
  1228. BOOL GetPortDescription ( HAB hab,
  1229.                           HMODULE hModule,
  1230.                           PSZ pszPortName,
  1231.                           PSZ pszPortDesc )
  1232. {
  1233.    USHORT usID;
  1234.    CHAR chBuf[STR_LEN_PORTDESC];
  1235.  
  1236.    for (usID = PORT_ID_FIRST; usID <= PORT_ID_LAST; usID += 2)
  1237.    {
  1238.       WinLoadString(hab, hModule, usID, STR_LEN_PORTDESC, chBuf);
  1239.       if (!strcmp (pszPortName, chBuf))
  1240.       {
  1241.          strcpy (pszPortDesc, chBuf);
  1242.          return(TRUE);
  1243.       }
  1244.    }
  1245.    return(FALSE);
  1246. }
  1247.  
  1248. /****************************************************************************
  1249.  *
  1250.  * FUNCTION NAME = OpenParallPortDlg
  1251.  *
  1252.  * DESCRIPTION   = Display port settings dialog
  1253.  *
  1254.  * INPUT         = hab     - anchor block handle
  1255.  *                 hModule - this port driver's module handle
  1256.  *                 pszPortName - name of port to get description for
  1257.  *                 pszAppName  - INI Appname for port( "PM_Portname").
  1258.  *
  1259.  * OUTPUT        = TRUE  - if port settings changed
  1260.  *                 FALSE - if port settings not changed
  1261.  *
  1262.  * RETURN-NORMAL =
  1263.  * RETURN-ERROR  =
  1264.  *
  1265.  ****************************************************************************/
  1266.  
  1267. ULONG OpenParallPortDlg ( HAB hab,
  1268.                           HMODULE hModule,
  1269.                           PSZ pszPortName,
  1270.                           PSZ pszAppName )
  1271. {
  1272.    PARALLDATA ParallData;
  1273.  
  1274.    memset (&ParallData, 0, sizeof (PARALLDATA));
  1275.    ParallData.hAB = hab;
  1276.    ParallData.hModule = hModule;
  1277.    ParallData.pszPortName = pszPortName;
  1278.    ParallData.pszAppName = pszAppName;
  1279.  
  1280.    WinDlgBox  (HWND_DESKTOP,
  1281.                HWND_DESKTOP,
  1282.                (PFNWP)ParallDlg,
  1283.                (HMODULE)hModule,
  1284.                IDD_PORTPARALLEL,
  1285.                &ParallData);
  1286.  
  1287.    return ParallData.lfModified;
  1288. }
  1289.  
  1290. /****************************************************************************
  1291.  *
  1292.  * FUNCTION NAME = ParallDlg
  1293.  *
  1294.  * DESCRIPTION   = Port settings dialog procedure
  1295.  *
  1296.  * INPUT         = hDlg: HWND
  1297.  *                 msg:  message
  1298.  *                 mp1:  message parameter
  1299.  *                 mp2:     "       "
  1300.  *
  1301.  * OUTPUT        =
  1302.  *
  1303.  * RETURN-NORMAL =
  1304.  * RETURN-ERROR  =
  1305.  *
  1306.  ****************************************************************************/
  1307.  
  1308. MRESULT EXPENTRY ParallDlg( HWND hDlg,
  1309.                             USHORT msg,
  1310.                             MPARAM mp1,
  1311.                             MPARAM mp2 )
  1312. {
  1313.     PPARALLDATA pParallData;
  1314.     /*
  1315.     **ULONG       ulTimeOut;
  1316.     **HWND        hwndMenu;
  1317.     **HWND        hwndHelpInstance;
  1318.     */
  1319.     switch (msg) {
  1320.  
  1321.         case WM_INITDLG:
  1322.             pParallData = (PPARALLDATA)mp2;
  1323.             WinSetWindowULong (hDlg, QWL_USER, (ULONG)pParallData);
  1324.  
  1325.             WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
  1326.                                    SPBM_SETLIMITS,
  1327.                                    MPFROMP(TIMEOUT_UPPER_LIMIT),
  1328.                                    MPFROMP(TIMEOUT_LOWER_LIMIT));
  1329.  
  1330.             {
  1331.                CHAR szDesc[ STR_LEN_PORTDESC];
  1332.                CHAR szTitle[ STR_LEN_TITLE + 1];
  1333.  
  1334.                if (PrfQueryProfileString (HINI_SYSTEMPROFILE,
  1335.                                           pParallData->pszAppName,
  1336.                                           KEY_DESCRIPTION,
  1337.                                           NULL,
  1338.                                           (PSZ)szDesc,
  1339.                                           STR_LEN_PORTDESC))
  1340.                {
  1341.                    WinSetWindowText (WinWindowFromID (hDlg,
  1342.                                                       (USHORT)IDC_PPA_DESC),
  1343.                                      szDesc);
  1344.                      /*
  1345.                      ** full description port name
  1346.                      */
  1347.                   WinQueryWindowText (hDlg, STR_LEN_TITLE, szTitle);
  1348.                   strcat (szTitle, szDesc);
  1349.                   WinSetWindowText (hDlg, szTitle);
  1350.                }
  1351.             }
  1352.  
  1353.             GetPortSettings (pParallData);
  1354.  
  1355.             WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
  1356.                                    SPBM_SETCURRENTVALUE,
  1357.                                    MPFROMSHORT(pParallData->usOrgTimeOut),
  1358.                                    MPFROMSHORT(NULL));
  1359.                /*
  1360.                ** added setting - new checkbox for share access
  1361.                */
  1362.             WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
  1363.                                    BM_SETCHECK,
  1364.                                    MPFROMSHORT(pParallData->fOrgShareAccess),
  1365.                                    MPFROMSHORT(NULL));
  1366.                /*
  1367.                ** create help hook for helps
  1368.                */
  1369.             SetHelpStubHook();
  1370.  
  1371.             break;
  1372.  
  1373.         case WM_COMMAND:
  1374.             pParallData = (PPARALLDATA)WinQueryWindowULong (hDlg, QWL_USER);
  1375.             switch (SHORT1FROMMP(mp1)) {
  1376.                case IDC_OK:
  1377.                      /*
  1378.                      ** Call function to save any changed port settings
  1379.                      */
  1380.                   if (SavePortSettings(pParallData, hDlg))
  1381.                   {
  1382.                      WinDismissDlg(hDlg, 0);
  1383.                   }
  1384.                   break;
  1385.  
  1386.                case IDC_RESET:
  1387.                   WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
  1388.                                      SPBM_SETCURRENTVALUE,
  1389.                                     MPFROMSHORT(pParallData->usOrgTimeOut),
  1390.                                     MPFROMSHORT(NULL));
  1391.                      /*
  1392.                      ** added setting new checkbox for share access
  1393.                      */
  1394.                   WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
  1395.                                     BM_SETCHECK,
  1396.                                     MPFROMSHORT(pParallData->fOrgShareAccess),
  1397.                                     MPFROMSHORT(NULL));
  1398.  
  1399.                   break;
  1400.  
  1401.                case IDC_DEFAULT:
  1402.                   WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT,
  1403.                                      SPBM_SETCURRENTVALUE,
  1404.                                     MPFROMSHORT(DEF_TIMEOUT_VALUE),
  1405.                                     MPFROMSHORT(NULL));
  1406.                      /*
  1407.                      ** added setting new checkbox for share access
  1408.                      */
  1409.                   WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
  1410.                                     BM_SETCHECK,
  1411.                                     MPFROMSHORT(FALSE),
  1412.                                     MPFROMSHORT(NULL));
  1413.  
  1414.                   break;
  1415.  
  1416.                case IDC_CANCEL:
  1417.                   WinDismissDlg(hDlg, MBID_CANCEL);
  1418.                   break;
  1419.  
  1420.                default:
  1421.                   return(WinDefDlgProc(hDlg, msg, mp1, mp2) );
  1422.                   break;
  1423.             }
  1424.            break;
  1425.  
  1426.         case WM_HELP:
  1427.             InitializeHelp();
  1428.             if (hwndHelp)
  1429.             {
  1430.                WinSendMsg (hwndHelp, HM_DISPLAY_HELP,
  1431.                                          (MPARAM)IDH_DLG_EXTENDED, NULL);
  1432.                return (MRESULT)TRUE;
  1433.             }
  1434.             break;
  1435.  
  1436.         case WM_DESTROY:
  1437.  
  1438.                /*
  1439.                ** if we have a help instance destroy it.
  1440.                */
  1441.             if (HelpAlreadyInitialized)
  1442.             {
  1443.                CALLDestroyHelpInstance(hwndHelp);
  1444.                hwndHelp = (HWND) NULL;
  1445.                HelpAlreadyInitialized = FALSE;
  1446.                HelpStubHookIsSet=FALSE;
  1447.             }
  1448.             ReleaseHelpStubHook();
  1449.              break;
  1450.  
  1451.         default:
  1452.             return(WinDefDlgProc(hDlg, msg, mp1, mp2) );
  1453.             break;
  1454.     }
  1455.     return FALSE;
  1456. }
  1457.  
  1458. /****************************************************************************
  1459.  *
  1460.  * FUNCTION NAME = GetPortSettings
  1461.  *
  1462.  * DESCRIPTION   = Get port Initialization settings from INI file
  1463.  *
  1464.  * INPUT         = pParallData -> structure containing port name.
  1465.  *                                On return this will have port timeout
  1466.  *                                and share access flag.
  1467.  *
  1468.  * OUTPUT        = TRUE  - if INI information found for port
  1469.  *                 FALSE - if INI info not found
  1470.  *
  1471.  * RETURN-NORMAL =
  1472.  * RETURN-ERROR  =
  1473.  *
  1474.  ****************************************************************************/
  1475.  
  1476. BOOL GetPortSettings( PPARALLDATA pParallData )
  1477. {
  1478.    CHAR szBuf[20];
  1479.    PSZ  p;
  1480.  
  1481.       /*
  1482.       ** Get port timeout value ( "PM_LPT1" "TIMEOUT" "timeout;" )
  1483.       */
  1484.    if (!(PrfQueryProfileString (HINI_SYSTEMPROFILE,
  1485.                                 pParallData->pszAppName,
  1486.                                 KEY_TIMEOUT,
  1487.                                 NULL,
  1488.                                 (PSZ)szBuf,
  1489.                                 20)))
  1490.     {
  1491.       return FALSE;
  1492.     }
  1493.     RemoveLeadTrailBlanks ((PSZ)szBuf, (PSZ)szBuf);
  1494.     if (p = strchr(szBuf, ';'))
  1495.     {
  1496.        *p = '\0';
  1497.     }
  1498.     if (*szBuf)
  1499.     {
  1500.        pParallData->usOrgTimeOut = (USHORT)atoi (szBuf);
  1501.     }
  1502.     else
  1503.     {
  1504.        pParallData->usOrgTimeOut = DEF_TIMEOUT_VALUE;
  1505.     }
  1506.     pParallData->usSaveTimeOut = pParallData->usOrgTimeOut;
  1507.  
  1508.        /*
  1509.        ** Get port's share access flag (part of initialization string)
  1510.        */
  1511.     if ( (PrfQueryProfileString (HINI_SYSTEMPROFILE, pParallData->pszAppName,
  1512.                                 KEY_INITIALIZATION, NULL,
  1513.                                 (PSZ)szBuf,
  1514.                                 20))
  1515.         && (szBuf[0] == '1') )
  1516.     {
  1517.       pParallData->fOrgShareAccess = TRUE ;
  1518.       pParallData->fShareAccess    = TRUE ;
  1519.     }
  1520.     else
  1521.     {
  1522.       pParallData->fOrgShareAccess = FALSE;
  1523.       pParallData->fShareAccess    = FALSE;
  1524.     }
  1525.  
  1526.     return(TRUE);
  1527. }
  1528.  
  1529. /****************************************************************************
  1530.  *
  1531.  * FUNCTION NAME = SavePortSettings
  1532.  *
  1533.  * DESCRIPTION   = save any changed values for this LPT port in INI file
  1534.  *
  1535.  * INPUT         = pParallalData -> this port's information
  1536.  *                 hDlg          -  handle of dialog window
  1537.  *
  1538.  * OUTPUT        = TRUE          -  successful
  1539.  *                 FALSE         -  PrfWrite failed
  1540.  *
  1541.  * RETURN-NORMAL =
  1542.  * RETURN-ERROR  =
  1543.  *
  1544.  ****************************************************************************/
  1545.  
  1546. BOOL SavePortSettings( PPARALLDATA pParallData,
  1547.                        HWND hDlg )
  1548. {
  1549.    CHAR szBuf[20];
  1550.    PSZ  pszInitialization ;
  1551.    ULONG       ulTimeOut;
  1552.    HFILE  hFile ;
  1553.    ULONG  ActionTaken ;
  1554.    USHORT usParamPacket= 0;
  1555.    USHORT usDataPacket = 0;
  1556.    ULONG  ulReturned1;
  1557.    ULONG  ulReturned2;
  1558.  
  1559.       /*
  1560.       ** Get current status of share access checkbox
  1561.       */
  1562.    pParallData->fShareAccess =
  1563.                 SHORT1FROMMP( WinSendDlgItemMsg (hDlg, IDC_PPA_SHAREHW,
  1564.                                                  BM_QUERYCHECK,
  1565.                                                  MPFROMSHORT(NULL),
  1566.                                                  MPFROMSHORT(NULL)) );
  1567.  
  1568.    if (pParallData->fShareAccess != pParallData->fOrgShareAccess)
  1569.    {
  1570.  
  1571.       if (pParallData->fShareAccess)
  1572.          pszInitialization = "1;" ;
  1573.       else
  1574.          pszInitialization = "0;" ;
  1575.  
  1576.       pParallData->lfModified = TRUE;
  1577.  
  1578.          /*
  1579.          ** If user selects to change parallel port access mode,
  1580.          **   we must issue IOCtl to PRINT02.SYS to set the
  1581.          **   share mode now. (Open port direct, NONSPOOLED!).
  1582.          **   It could be possible the user will use programs
  1583.          **   that do not print, but still require the parallel
  1584.          **   port's hardware registers
  1585.          */
  1586.       if ( DosOpen(pParallData->pszPortName,     /* port "LPT1"          */
  1587.                    &hFile,
  1588.                    &ActionTaken,
  1589.                    0L,                           /* filesize             */
  1590.                    0L,                           /* attribute            */
  1591.                    FILE_OPEN|FILE_CREATE,        /* open flags           */
  1592.  
  1593.                    OPEN_FLAGS_NONSPOOLED |       /* open mode            */
  1594.                    OPEN_FLAGS_FAIL_ON_ERROR |
  1595.                    OPEN_ACCESS_WRITEONLY |
  1596.                    OPEN_SHARE_DENYNONE,
  1597.                    NULL ) == 0)                  /* No EAs               */
  1598.       {
  1599.             /*
  1600.             ** flag byte: bit 0 off -> don't allow more than one process
  1601.             **                         to access parallel port at one time
  1602.             **                  on  -> allow multiple processes to access
  1603.             **                         parallel port simultaneously
  1604.             */
  1605.          usDataPacket = (USHORT)pParallData->fShareAccess ;
  1606.  
  1607.          ulReturned1 = 1 ;             /* length of in/output parameters */
  1608.          ulReturned2 = 1 ;
  1609.  
  1610.          DosDevIOCtl(
  1611.                 hFile,                    /* port file handle            */
  1612.                 0x5,                      /* Category number             */
  1613.                 0x51,                     /* Function - set share access */
  1614.                 (PVOID) &usParamPacket,   /* Not needed for IOCTL        */
  1615.                 sizeof (BYTE),
  1616.                 &ulReturned1,
  1617.                 (PVOID) &usDataPacket,    /* 1 = allow multiple access   */
  1618.                 sizeof (BYTE),
  1619.                 &ulReturned2);
  1620.  
  1621.          DosClose(hFile) ;
  1622.       }
  1623.          /*
  1624.          ** Write initialization string to ini file
  1625.          */
  1626.       if (!PrfWriteProfileString (HINI_SYSTEMPROFILE,
  1627.                                  pParallData->pszAppName,
  1628.                                  KEY_INITIALIZATION,
  1629.                                  pszInitialization))
  1630.        {
  1631.           DE ("Error in writing to system ini file");
  1632.           return FALSE;
  1633.        }
  1634.    }
  1635.  
  1636.  
  1637.    WinSendDlgItemMsg (hDlg, IDC_PPA_TIMEOUT, SPBM_QUERYVALUE,
  1638.                       (MPARAM)&ulTimeOut, (MPARAM)NULL);
  1639.    if (pParallData->usSaveTimeOut != (USHORT)ulTimeOut)
  1640.     {
  1641.  
  1642.       pParallData->usSaveTimeOut = (USHORT)ulTimeOut;
  1643.       pParallData->lfModified = TRUE;
  1644.       _itoa (pParallData->usSaveTimeOut, szBuf, 10);
  1645.       strcat (szBuf, ";");
  1646.          /*
  1647.          ** Write data for this port in ini file with new format.
  1648.          */
  1649.       if (!PrfWriteProfileString (HINI_SYSTEMPROFILE,
  1650.                                  pParallData->pszAppName,
  1651.                                  KEY_TIMEOUT,
  1652.                                  szBuf))
  1653.        {
  1654.           DE ("Error in writing to system init file");
  1655.           return FALSE;
  1656.        }
  1657.  
  1658.     }
  1659.  
  1660.    return TRUE;
  1661. }
  1662.  
  1663. /****************************************************************************
  1664.  *
  1665.  * FUNCTION NAME = RemoveLeadTrailBlanks
  1666.  *
  1667.  * DESCRIPTION   = Remove all the leading blanks and all the trailing blanks
  1668.  *                 from the source string. The target string contains no lead
  1669.  *                 or trail blanks. Source string is not altered.
  1670.  *
  1671.  * INPUT         = pTarget   - Target string.
  1672.  *                 pSource   - Source string.
  1673.  *
  1674.  * OUTPUT        = Void function.
  1675.  *
  1676.  * RETURN-NORMAL =
  1677.  * RETURN-ERROR  =
  1678.  *
  1679.  *      Note : Function accepts the same pointer for both source and target.
  1680.  *             This means that same buffer can be used as input and output.
  1681.  *
  1682.  ****************************************************************************/
  1683.  
  1684. VOID RemoveLeadTrailBlanks ( PCH pTarget,
  1685.                              PCH pSource )
  1686. {
  1687.    for (; *pSource == ' ' || *pSource == '\t' || *pSource == '\n'; pSource++);
  1688.    if (!(*pSource))
  1689.    {
  1690.       *pTarget = '\0';
  1691.       return;
  1692.    }
  1693.    for (; *pSource; *pTarget++ = *pSource++);
  1694.    for (pTarget--; *pTarget == ' ' || *pTarget == '\t' || *pTarget == '\n';
  1695.                                                                  pTarget--);
  1696.    *++pTarget = '\0';
  1697.  
  1698. }
  1699.  
  1700. /****************************************************************************
  1701.  *
  1702.  * FUNCTION NAME = DisplayError
  1703.  *
  1704.  * DESCRIPTION   = Display error having string from the resource file.
  1705.  *
  1706.  * INPUT         = hwndOwner     - Owner of message box.
  1707.  *                                    if NULL, default is last active window.
  1708.  *                 usStringID    - ID of string in resource file.
  1709.  *                 usWinStyle    - Window style of message box.
  1710.  *                                    if NULL, default is MB_OK.
  1711.  *
  1712.  * OUTPUT        = User-response value returned by WimMessageBox API.
  1713.  *
  1714.  * RETURN-NORMAL =
  1715.  * RETURN-ERROR  =
  1716.  *
  1717.  ****************************************************************************/
  1718.  
  1719. USHORT DisplayError ( HWND hwndOwner,
  1720.                       HMODULE hModule,
  1721.                       USHORT usStringID,
  1722.                       USHORT usWinStyle )
  1723. {
  1724.    CHAR pszTitle[256];                       /*  Message-box window title   */
  1725.    CHAR pszText[256];                        /*  Message-box window message */
  1726.    USHORT usResponse;
  1727.    HAB    hAB;
  1728.    ULONG  ulLen = 255L;
  1729.  
  1730.    hAB = WinQueryAnchorBlock (HWND_DESKTOP);
  1731.    WinLoadString (hAB, hModule, PORT_ERR_TITLE, 255, (PSZ)pszTitle);
  1732.    WinLoadString (hAB, hModule, usStringID, 255, (PSZ)pszText);
  1733.    if (!hwndOwner)
  1734.    {
  1735.       hwndOwner = WinQueryActiveWindow (HWND_DESKTOP);
  1736.    }
  1737.    if (!usWinStyle)
  1738.    {
  1739.       usWinStyle = MB_OK;
  1740.    }
  1741.    usResponse = WinMessageBox (HWND_DESKTOP, hwndOwner, pszText, pszTitle, 1,
  1742.                                                            (ULONG)usWinStyle);
  1743.    return (usResponse);
  1744.  
  1745. }
  1746.  
  1747. /****************************************************************************
  1748.  *
  1749.  * FUNCTION NAME = DE
  1750.  *
  1751.  * DESCRIPTION   = Display Error message
  1752.  *
  1753.  * INPUT         = str  - error message string to display
  1754.  *
  1755.  * OUTPUT        = None
  1756.  *
  1757.  * RETURN-NORMAL =
  1758.  * RETURN-ERROR  =
  1759.  *
  1760.  ****************************************************************************/
  1761.  
  1762. VOID DE ( PCH str )
  1763. {
  1764.        WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
  1765.                  (PCH)str,
  1766.                  (PCH)"Error",
  1767.                  1,
  1768.                  MB_OKCANCEL | MB_APPLMODAL |
  1769.                  MB_MOVEABLE | MB_ICONASTERISK);
  1770.  
  1771. }
  1772.  
  1773. /*
  1774. ** Following routines replace Win help manager function calls.
  1775. ** This is done to avoid automatically loading the help manager
  1776. ** when the port driver is used.
  1777. ** DosLoadModule is used to get the help manager function addresses
  1778. ** and WinHook mechanism is used to get notified of F1 key.
  1779. **
  1780. ** All CallxxHelpxx call equivalent WinxxHelpxx
  1781. */
  1782. /****************************************************************************
  1783.  *
  1784.  * FUNCTION NAME = CALLAssociateHelpInstance
  1785.  *
  1786.  * DESCRIPTION   =
  1787.  *
  1788.  * INPUT         =
  1789.  *
  1790.  * OUTPUT        =
  1791.  *
  1792.  * RETURN-NORMAL =
  1793.  * RETURN-ERROR  =
  1794.  *
  1795.  ****************************************************************************/
  1796.  
  1797. BOOL APIENTRY CALLAssociateHelpInstance ( HWND hwndHelpInstance,
  1798.                                           HWND hwndApp )
  1799. {
  1800.    ULONG    rc = 0;
  1801.    HMODULE  hModule;
  1802.  
  1803.    if (!hvHelpmgrModule)
  1804.    {
  1805.          /*
  1806.          ** If there is an error display it and return.
  1807.          ** This call should only be made if CreateHelpInstance was called.
  1808.          **
  1809.          ** This uses an error message from print object and should
  1810.          ** be replaced with custom message.
  1811.          */
  1812.       DosQueryModuleHandle ("WPPRINT", &hModule);
  1813. #define STR_BASE                   7000
  1814. #define STR_DLL_LOAD_ERROR         (STR_BASE + 36)
  1815.       DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
  1816.                               MB_OK | MB_APPLMODAL | MB_MOVEABLE);
  1817.    }
  1818.    else
  1819.    {
  1820.          /*
  1821.          ** Check to see if we have the pointer from a previous call
  1822.          */
  1823.       if (!pfnWinAssociateHelpInstance)
  1824.       {
  1825.             /*
  1826.             ** Get pointer to the location of the function we want.
  1827.             */
  1828.          rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
  1829.                                      (PSZ)"WIN32ASSOCIATEHELPINSTANCE",
  1830.                                      (PFN *)&pfnWinAssociateHelpInstance);
  1831.       }
  1832.          /*
  1833.          ** If no error continue.
  1834.          */
  1835.       if (!rc )
  1836.       {
  1837.          rc = (*pfnWinAssociateHelpInstance)(hwndHelpInstance, hwndApp);
  1838.             /*
  1839.             ** Function returns a bool
  1840.             */
  1841.          if (rc == TRUE)
  1842.             return(TRUE);
  1843.       }
  1844.    }
  1845.    return(FALSE);
  1846. }
  1847.  
  1848. /****************************************************************************
  1849.  *
  1850.  * FUNCTION NAME = CALLCreateHelpInstance
  1851.  *
  1852.  * DESCRIPTION   =
  1853.  *
  1854.  * INPUT         =
  1855.  *
  1856.  * OUTPUT        =
  1857.  *
  1858.  * RETURN-NORMAL =
  1859.  * RETURN-ERROR  =
  1860.  *
  1861.  ****************************************************************************/
  1862.  
  1863. HWND APIENTRY  CALLCreateHelpInstance ( HAB hab,
  1864.                                         PHELPINIT phinitHMInitStructure )
  1865. {
  1866.    ULONG    rc = 0;
  1867.    HWND     hwnd = (HWND)NULLHANDLE;
  1868.    HMODULE  hModule;
  1869.  
  1870.       /*
  1871.       ** Check to see if we already have the handle
  1872.       */
  1873.    if (!hvHelpmgrModule)
  1874.       rc = DosLoadModule((PSZ)NULL, 0,
  1875.                          (PSZ)"HELPMGR", (PHMODULE)&hvHelpmgrModule);
  1876.    if (rc)
  1877.    {
  1878.          /*
  1879.          ** If there is an error display it and return.
  1880.          */
  1881.       DosQueryModuleHandle ("WPPRINT", &hModule);
  1882.       DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
  1883.                               MB_OK | MB_APPLMODAL | MB_MOVEABLE);
  1884.    }
  1885.    else
  1886.    {
  1887.       if (!pfnWinCreateHelpInstance)
  1888.             /*
  1889.             ** Next get pointer to the location of the function we want.
  1890.             */
  1891.          rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
  1892.                                      (PSZ)"WIN32CREATEHELPINSTANCE",
  1893.                                      (PFN *)&pfnWinCreateHelpInstance);
  1894.          /*
  1895.          ** If no error continue.
  1896.          */
  1897.       if (!rc )
  1898.          hwnd = (*pfnWinCreateHelpInstance)(hab, phinitHMInitStructure );
  1899.  
  1900.    }
  1901.    return(hwnd);
  1902. }
  1903.  
  1904. /****************************************************************************
  1905.  *
  1906.  * FUNCTION NAME = CALLDestroyHelpInstance
  1907.  *
  1908.  * DESCRIPTION   =
  1909.  *
  1910.  * INPUT         =
  1911.  *
  1912.  * OUTPUT        =
  1913.  *
  1914.  * RETURN-NORMAL =
  1915.  * RETURN-ERROR  =
  1916.  *
  1917.  ****************************************************************************/
  1918.  
  1919. BOOL APIENTRY   CALLDestroyHelpInstance ( HWND hwndHelpInstance )
  1920. {
  1921.  
  1922.    ULONG    rc = 0;
  1923.    HMODULE  hModule;
  1924.  
  1925.    if (!hvHelpmgrModule)
  1926.    {
  1927.          /*
  1928.          ** If there is an error display it and return.
  1929.          */
  1930.       DosQueryModuleHandle ("WPPRINT", &hModule);
  1931.       DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
  1932.                               MB_OK | MB_APPLMODAL | MB_MOVEABLE);
  1933.    }
  1934.    else
  1935.    {
  1936.       if (!pfnWinDestroyHelpInstance)
  1937.             /*
  1938.             ** Next get pointer to the location of the function we want.
  1939.             */
  1940.          rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
  1941.                                      (PSZ)"WIN32DESTROYHELPINSTANCE",
  1942.                                      (PFN *)&pfnWinDestroyHelpInstance);
  1943.          /*
  1944.          ** If no error continue.
  1945.          */
  1946.       if (!rc )
  1947.       {
  1948.          rc = (*pfnWinDestroyHelpInstance)(hwndHelpInstance);
  1949.             /*
  1950.             ** Function returns a bool
  1951.             */
  1952.          if (rc == TRUE)
  1953.          {
  1954.            /* DosFreeModule(hvHelpmgrModule); */
  1955.             return(TRUE);
  1956.          }
  1957.       }
  1958.    }
  1959.    return(FALSE);
  1960. }
  1961.  
  1962. /****************************************************************************
  1963.  *
  1964.  * FUNCTION NAME = CALLQueryHelpInstance
  1965.  *
  1966.  * DESCRIPTION   =
  1967.  *
  1968.  * INPUT         =
  1969.  *
  1970.  * OUTPUT        =
  1971.  *
  1972.  * RETURN-NORMAL =
  1973.  * RETURN-ERROR  =
  1974.  *
  1975.  ****************************************************************************/
  1976.  
  1977. HWND APIENTRY   CALLQueryHelpInstance ( HWND hwndApp )
  1978. {
  1979.    ULONG    rc = 0;
  1980.    HWND     hwnd = (HWND)NULLHANDLE;
  1981.    HMODULE  hModule;
  1982.  
  1983.    if (!hvHelpmgrModule)
  1984.    {
  1985.          /*
  1986.          ** If there is an error display it and return.
  1987.          */
  1988.       DosQueryModuleHandle ("WPPRINT", &hModule);
  1989.       DisplayError (HWND_DESKTOP, hModule, STR_DLL_LOAD_ERROR,
  1990.                               MB_OK | MB_APPLMODAL | MB_MOVEABLE);
  1991.    }
  1992.    else
  1993.    {
  1994.       if (!pfnWinQueryHelpInstance)
  1995.             /*
  1996.             ** Get pointer to the location of the function we want.
  1997.             */
  1998.          rc = DosQueryProcAddr (hvHelpmgrModule,(ULONG)NULL,
  1999.                                      (PSZ)"WIN32QUERYHELPINSTANCE",
  2000.                                      (PFN *)&pfnWinQueryHelpInstance);
  2001.          /*
  2002.          ** If no error continue.
  2003.          */
  2004.       if (!rc )
  2005.       {
  2006.             /*
  2007.             ** Make sure that the handle is associated with this instance
  2008.             **
  2009.             ** Make call
  2010.             */
  2011.          hwnd = (*pfnWinQueryHelpInstance)( hwndApp);
  2012.  
  2013.       }
  2014.    }
  2015.    return(hwnd);
  2016. }
  2017.  
  2018. /****************************************************************************
  2019.  *
  2020.  * FUNCTION NAME = SetHelpStubHook
  2021.  *
  2022.  * DESCRIPTION   =
  2023.  *
  2024.  * INPUT         =
  2025.  *
  2026.  * OUTPUT        =
  2027.  *
  2028.  * RETURN-NORMAL =
  2029.  * RETURN-ERROR  =
  2030.  *
  2031.  ****************************************************************************/
  2032.  
  2033. BOOL EXPENTRY SetHelpStubHook()
  2034. {
  2035.     if(!HelpStubHookIsSet)
  2036.     {
  2037.         if(WinSetHook(0L, HMQ_CURRENT, HK_HELP, (PFN)HelpStubHook, 0L))
  2038.         {
  2039.             HelpStubHookIsSet = TRUE;
  2040.             return TRUE;
  2041.         }
  2042.     }
  2043.     return FALSE;
  2044. }
  2045.  
  2046. /****************************************************************************
  2047.  *
  2048.  * FUNCTION NAME = ReleaseHelpStubHook
  2049.  *
  2050.  * DESCRIPTION   =
  2051.  *
  2052.  * INPUT         =
  2053.  *
  2054.  * OUTPUT        =
  2055.  *
  2056.  * RETURN-NORMAL =
  2057.  * RETURN-ERROR  =
  2058.  *
  2059.  ****************************************************************************/
  2060.  
  2061. VOID EXPENTRY ReleaseHelpStubHook()
  2062. {
  2063.     if(HelpStubHookIsSet)
  2064.     {
  2065.         WinReleaseHook(0L, HMQ_CURRENT, HK_HELP, (PFN)HelpStubHook, 0L);
  2066.         HelpStubHookIsSet = FALSE;
  2067.     }
  2068. }
  2069.  
  2070. /****************************************************************************
  2071.  *
  2072.  * FUNCTION NAME = HelpStubHook
  2073.  *
  2074.  * DESCRIPTION   =
  2075.  *
  2076.  * INPUT         =
  2077.  *
  2078.  * OUTPUT        =
  2079.  *
  2080.  * RETURN-NORMAL =
  2081.  * RETURN-ERROR  =
  2082.  *
  2083.  ****************************************************************************/
  2084.  
  2085. INT EXPENTRY HelpStubHook( HAB AppHAB,
  2086.                            USHORT Context,
  2087.                            USHORT IdTopic,
  2088.                            USHORT IdSubTopic,
  2089.                            PRECTL RectLPtr )
  2090. {
  2091.  
  2092.     InitializeHelp();
  2093.  
  2094.     return FALSE;
  2095. }
  2096.  
  2097. /****************************************************************************
  2098.  *
  2099.  * FUNCTION NAME = InitializeHelp
  2100.  *
  2101.  * DESCRIPTION   =
  2102.  *
  2103.  * INPUT         =
  2104.  *
  2105.  * OUTPUT        =
  2106.  *
  2107.  * RETURN-NORMAL =
  2108.  * RETURN-ERROR  =
  2109.  *
  2110.  ****************************************************************************/
  2111.  
  2112. VOID EXPENTRY InitializeHelp()
  2113. {
  2114.     HAB     hAB;
  2115.     HWND    hWnd;
  2116.     HWND    hWndActive;
  2117.     ULONG   ulBootDrive;
  2118.     HMODULE hModule;
  2119.     CHAR    szBuf[256];
  2120.     CHAR    szPathName[260]; /* will contain full path to this port driver */
  2121.  
  2122.     if(HelpAlreadyInitialized)   return;
  2123.  
  2124.        /*
  2125.        ** Initialize Help
  2126.        ** ---------------
  2127.        **
  2128.        ** Create an instance of the Help Manager, and associate it
  2129.        ** with the Frame.  If the Association fails, we handle it
  2130.        ** the same way as if the creation fails, ie hwndHelp
  2131.        ** (the Help Manager Object Window handle) is set to NULL.
  2132.        ** If we can't load the Module containing the Help Panel
  2133.        ** definitions, we forget Help altogether.
  2134.        */
  2135.     hWndActive = WinQueryActiveWindow(HWND_DESKTOP);
  2136.     hWnd = WinQueryWindow(hWndActive,QW_OWNER);
  2137.        /*
  2138.        ** if unable to get active window's owner
  2139.        **    use active window
  2140.        */
  2141.     if (hWnd == (HWND)NULL)
  2142.        hWnd = hWndActive ;
  2143.  
  2144.        /*
  2145.        ** We need our module handle.
  2146.        ** Easiest way to do this is to find the path to our port driver
  2147.        **  from the system INI file.
  2148.        ** If not found in the INI file
  2149.        **  assume it is in the boot drive's \OS2\DLL directory
  2150.        */
  2151.  
  2152.     /* change ? in szDefaultPortDrvPath to boot drive */
  2153.     DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &ulBootDrive,
  2154.                     sizeof (ULONG));
  2155.     szDefaultPortDrvPath[0] = (CHAR)(ulBootDrive + 'A' - 1);
  2156.  
  2157.     PrfQueryProfileString (HINI_SYSTEMPROFILE,
  2158.                           "PM_PORT_DRIVER",
  2159.                           "PARALLEL",
  2160.                           szDefaultPortDrvPath,
  2161.                           szPathName,
  2162.                           256 );
  2163.        /*
  2164.        ** get module handle for our dll
  2165.        */
  2166.     DosQueryModuleHandle ( szPathName, &hModule);
  2167.  
  2168.        /*
  2169.        ** Initialize a couple of the helpmgr structure elements
  2170.        ** First, get the title
  2171.        **
  2172.        ** Now load the title
  2173.        */
  2174.     WinLoadString (hAB, hModule,
  2175.                    (USHORT)(PORT_HELP_TITLE), (SHORT)(256), szBuf);
  2176.  
  2177.     hmiHelpData.pszHelpWindowTitle = (PSZ)szBuf;
  2178.     hmiHelpData.pszHelpLibraryName = "WPHELP.HLP";
  2179.  
  2180.     hAB = WinQueryAnchorBlock(hWnd);
  2181.  
  2182.        /*
  2183.        ** Only create a handle if we don't have one.
  2184.        */
  2185.     if (hwndHelp == 0L)
  2186.        hwndHelp = CALLCreateHelpInstance(hAB, &hmiHelpData);
  2187.  
  2188.        /*
  2189.        ** Always associate the helpmgr handle with the active window
  2190.        */
  2191.     if (hwndHelp != 0L)
  2192.     {
  2193.        if(!CALLAssociateHelpInstance(hwndHelp, hWnd) )
  2194.        {
  2195.            CALLDestroyHelpInstance(hwndHelp);
  2196.            hwndHelp = (HWND)NULL;
  2197.        }
  2198.     }
  2199.  
  2200.        /*
  2201.        ** If help was initialized, get rid of our hook. Otherwise, we have
  2202.        ** to ensure that our stub hook is the FIRST hook in the HK_HELP
  2203.        ** hook chain.
  2204.        */
  2205.     if(hwndHelp != 0L)
  2206.     {
  2207.         HelpAlreadyInitialized = TRUE;
  2208.         ReleaseHelpStubHook();
  2209.     }
  2210.     else
  2211.     {
  2212.         ReleaseHelpStubHook();
  2213.         SetHelpStubHook();
  2214.     }
  2215. }
  2216.