home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / findex.zip / FINDEC.ZIP / FINDEXEC.C next >
Encoding:
C/C++ Source or Header  |  1993-09-08  |  28.0 KB  |  1,078 lines

  1. //===================================================================
  2. // FINDEXEC - FAPI Path search utility
  3. // Copyright 1993 Douglas Boling
  4. //
  5. // Release History:
  6. //      Version 1.0     Initial Release PC Mag Vol 12, No 14.
  7. //
  8. //      Version 1.1     Increased read buff to 16384 for big reference
  9. //                      tables.
  10. //
  11. //                      Save/Restored Program directory in recursive
  12. //                      calls to GetxxRefs.
  13. //
  14. //                      If WinDir not found, check for WIN.COM in PATH
  15. //      
  16. //===================================================================
  17.  
  18. #define MAXFNAMELEN      256
  19. #define MAXPATHLEN       260
  20. #define BUFFSIZE         16384
  21. #define CBUFFSIZE        16384
  22.  
  23. #define ERR_SYNTAX       10
  24. #define ERR_NOFILESFOUND 11
  25. #define ERR_OUTOFMEM     12
  26. #define ERR_NOOPENEXE    13
  27. #define ERR_NOLIBPATH    14
  28. #define ERR_NOWINDIR     15
  29. #define ERR_NOWININI     16
  30. #define ERR_2SWITCHES    17
  31. #define ERR_LIMTOHIGH    18
  32. #define ERR_HELP         100
  33.  
  34. #define INCL_VIO
  35. #define INCL_KBD
  36. #define INCL_NOPM
  37. #define INCL_DOS
  38.  
  39. #include <os2.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <direct.h>
  44. #include <dos.h>
  45.  
  46. #include "findexec.h"
  47. typedef struct find_t FIND_T;
  48.  
  49. //
  50. // Function Prototypes
  51. //
  52. INT    Search4EXE (char *, INT);
  53. BOOL    DOSSearch (char *, char *, INT);
  54. BOOL    WinSearch (char *, char *, INT);
  55. INT    GetPIFRefs (char *);
  56. INT    GetNERefs (char *, INT, ULONG, INT);
  57. INT    GetLXRefs (char *, INT, ULONG);
  58. INT    GetEXEType (char *, INT *, LONG *);
  59. char    *FindEnvVar (PSZ, char *, char *,INT);
  60. BOOL    FindFile (char *, char *, INT);
  61. void    CombinePath (char *, char *, INT);
  62. BOOL    SearchPath (char *, char *, char *, INT);
  63. BOOL    SearchPath2 (char *, char *, char *, INT, INT);
  64. BOOL    GetPathDir (char *, char *, INT);
  65. BOOL    GetItem (char *, char *, char *, INT);
  66. BOOL    AddExt (char *, char *, INT);
  67. void    PrintFName (char *, INT, INT);
  68. INT     ParseCmdLine (INT, char **, char *, INT *);
  69. void    DirQCur (char *, INT);
  70. HFILE    FileOpen (char *);
  71. INT    FileClose (HFILE);
  72.  
  73. //
  74. // Global Data
  75. //
  76. char    szProgram[] = "\nFINDEXEC 1.1 Copyright 1993 Douglas Boling\n";
  77. char    szProgram1[] = "First Published in PC Magazine, August 1993\n\n";
  78.  
  79. char    *szErrMsgs[] = {"Syntax error.  Type FINDEXEC /? for help\n",
  80.                       "No executable files found\n",
  81.                       "\nOut of Memory\n",
  82.                       "\nCan\'t open executable file\n",
  83.                       "\nCan\'t find LIBPATH parameter in CONFIG.SYS\n",
  84.                       "\nCan\'t find Windows directory\n",
  85.                       "\nCan\'t find Programs= parameter in WIN.INI\n",
  86.                       "\nMore than 1 search option requested\n",
  87.                       "\nLevel must be between 0 and 9\n",
  88.                       }; 
  89.  
  90. char    *szHelpMsgs[] = {"\nUSAGE: FINDEXEC [/?][/W] [/V | /Ln] program_name\n",
  91.                     "\nSearch for program name using proper program search ",
  92.                     "method.\nUses DOS search method under DOS and ",
  93.                     "OS/2 search method under OS/2.\n\n",
  94.                     "/W  - Perform Windows search.  Use only in a ",
  95.                     "Windows DOS Box.\n",
  96.                     "/V  - Verbose output.  Print all included DLLs\n",
  97.                     "/Ln - Display to level n.  Displays included DLLs ",
  98.                     "to the nth level.\n      n must be between 0 and 9.\n",
  99.                     "/?  - Display this help message.\n",
  100.                     }; 
  101.  
  102. char    szDOSExts[] = "COM EXE BAT";
  103. char    szWinExts[128] = "";
  104. char    szWinLExts[] = "DLL EXE DRV";
  105. char    szOS2Exts[] = "COM EXE CMD BAT";
  106. char    szOS2LExts[] = "DLL EXE";
  107.  
  108. PSZ        lpszEnv;
  109. char        szProgDir[MAXFNAMELEN] = "";
  110. INT        sLevel = 0, sMaxLevel = 1;
  111. char        szLibPath[MAXPATHLEN] = "";
  112. char        szPath[MAXPATHLEN] = "";
  113. USHORT    usDosVer;
  114.  
  115. //===================================================================
  116. // Program Entry Point
  117. //===================================================================
  118. main (int argc, char *argv[]) {
  119.  
  120.     char    szExeName[MAXFNAMELEN] = "";
  121.     USHORT    usEnvSel, usCmdOffset;
  122.     PSZ        lpszCmdLine;
  123.     PSZ        lpszPtr;
  124.     INT        i, rc, sSrchType = 0;
  125.  
  126.     printf (szProgram);               //Print Copyright
  127.     printf (szProgram1);
  128.  
  129.     DosGetVersion (&usDosVer);        //If OS/2, def to OS/2 search
  130.     if (usDosVer >= 0xa00)
  131.         sSrchType = 2;
  132.     //
  133.     // Get Ptrs to environment and Cmd line
  134.     //
  135.     DosGetEnv (&usEnvSel, &usCmdOffset);
  136.     lpszEnv = MAKEP (usEnvSel, 0);
  137.     lpszCmdLine = MAKEP (usEnvSel, usCmdOffset);
  138.     //
  139.     // Get program's directory from program name
  140.     //
  141.     lpszPtr = lpszEnv;
  142.     while (*lpszPtr != 0) {           //Find end of env strings
  143.         for (;*lpszPtr != 0; lpszPtr++)
  144.             ;
  145.         lpszPtr++;
  146.     }
  147.     lpszPtr++;
  148.     for (i = 0; i < sizeof (szProgDir) && *lpszPtr != 0; i++)
  149.         szProgDir[i] = *lpszPtr++;
  150.     *strrchr (szProgDir, '\\') = '\0';
  151.     strupr (szProgDir);
  152.     //
  153.     //Get PATH env var
  154.     //
  155.     FindEnvVar (lpszEnv, "PATH", szPath, sizeof (szPath));
  156.     //
  157.     //Parse the command line
  158.     //
  159.     rc = ParseCmdLine (argc, argv, szExeName, &sSrchType);
  160.     if (rc) {
  161.         if (rc == ERR_HELP)
  162.             for (i = 0; i < 10; i++)
  163.                 printf (szHelpMsgs[i]);
  164.         else
  165.             printf (szErrMsgs[rc-10]);
  166.         DosExit (1, rc);
  167.     }
  168.     //
  169.     //Search for the EXE
  170.     //
  171.     rc = Search4EXE (szExeName, sSrchType);
  172.     if (rc > 10)
  173.         printf (szErrMsgs[rc-10]);
  174.     printf("\n");
  175.     DosExit (1, rc);
  176.     return 0;
  177. }
  178. //-------------------------------------------------------------------
  179. // Search4EXE - Searches the system for an executable file
  180. //
  181. //-------------------------------------------------------------------
  182. INT Search4EXE (char *szFName, INT sSrchType) {
  183.  
  184.     BOOL        fFound = FALSE;
  185.     SHORT        sExeType, sNumRefEnt;
  186.     ULONG        ulFPtr;
  187.     char        szWinDir[128];
  188.  
  189.     switch (sSrchType) {
  190.         //
  191.         // DOS
  192.         //
  193.         case 0:
  194.             fFound = DOSSearch(szFName, szDOSExts, -1);
  195.             if (fFound) {
  196.                 PrintFName (szFName, GetEXEType (szFName, 0, 0), sLevel);
  197.                 return 0;
  198.             }
  199.             break;
  200.         //
  201.         // Windows
  202.         //
  203.         case 1:
  204.             if (!FindEnvVar (lpszEnv, "windir", szLibPath, sizeof (szLibPath))) {
  205.                 strcpy (szLibPath, "WIN.COM");
  206.                 if (!DOSSearch(szLibPath, szDOSExts, -1))
  207.                     return ERR_NOWINDIR;
  208.                 if (strlen (szLibPath) < 12)
  209.                     return ERR_NOWINDIR;
  210.                 szLibPath[strlen(szLibPath)-8] = '\0';
  211.             }
  212.             strcpy (szWinDir, szLibPath);
  213.             strcat (szWinDir, "\\WIN.INI");
  214.             if (!GetItem (szWinDir, "Programs=", szWinExts, sizeof (szWinExts)))
  215.                 return ERR_NOWININI;
  216.             fFound = WinSearch(szFName, szWinExts, -1);
  217.             if (fFound) {
  218.                 sExeType = GetEXEType (szFName, &sNumRefEnt, &ulFPtr);
  219.                 PrintFName (szFName, sExeType, sLevel);
  220.  
  221.                 if ((sExeType == 1) && (sNumRefEnt)) {
  222.                     if (sMaxLevel) {
  223.                         printf ("Loads:\n");
  224.                          return GetNERefs (szFName, sNumRefEnt, ulFPtr, 1);
  225.                     }
  226.                 } else if (sExeType == 7) 
  227.                      return GetPIFRefs (szFName);
  228.                 return 0;    
  229.             }
  230.             break;
  231.         //
  232.         // OS/2
  233.         //
  234.         case 2:
  235.             fFound = DOSSearch(szFName, szOS2Exts, 4);
  236.             if (!fFound)
  237.                 fFound = DOSSearch(szFName, szDOSExts, 2);
  238.             if (!fFound)
  239.                 fFound = DOSSearch(szFName, szDOSExts, -1);
  240.             if (fFound) {
  241.                 sExeType = GetEXEType (szFName, &sNumRefEnt, &ulFPtr);
  242.                 PrintFName (szFName, sExeType, sLevel);
  243.  
  244.                 if ((sNumRefEnt) && sMaxLevel && 
  245.                     ((sExeType == 2) || (sExeType == 4))) {
  246.  
  247.                     if (!GetItem ("c:\\CONFIG.SYS", "LIBPATH=",
  248.                                   szLibPath, sizeof (szLibPath)))
  249.                         return ERR_NOLIBPATH;
  250.                     printf ("Loads:\n");
  251.                     if (sExeType == 4) 
  252.                         return GetLXRefs (szFName, sNumRefEnt, ulFPtr);
  253.                     return GetNERefs (szFName, sNumRefEnt, ulFPtr, 2);
  254.                 }
  255.                 return 0;
  256.             }
  257.             break;
  258.     }
  259.     return ERR_NOFILESFOUND;
  260. }
  261. //-------------------------------------------------------------------
  262. // DOSSearch - DOS program search method
  263. //
  264. // DOS search method
  265. //   current dir
  266. //   path
  267. //
  268. //-------------------------------------------------------------------
  269. BOOL DOSSearch (char *pszFName, char *pszExts, INT sFType) {
  270.     char    szDir[MAXFNAMELEN];
  271.     BOOL    fFound;
  272.      
  273.     if ((*(pszFName+1) == ':') || (strchr (pszFName, '\\'))) {
  274.         fFound = FindFile (pszFName, pszExts, sFType);
  275.         return fFound;
  276.     }    
  277.     DirQCur (szDir, sizeof (szDir));
  278.     CombinePath (szDir, pszFName, sizeof (szDir));
  279.     if (FindFile (szDir, pszExts, sFType)) {
  280.         strcpy (pszFName, szDir);
  281.         return TRUE;
  282.     }
  283.     return SearchPath (pszFName, szPath, pszExts, sFType);
  284. }
  285. //-------------------------------------------------------------------
  286. // WinSearch - Windows executable search method
  287. //
  288. // Windows search method
  289. //   current dir
  290. //   Win directory
  291. //   Win System directory
  292. //   EXE file's directory
  293. //   path
  294. //   net path
  295. //
  296. //-------------------------------------------------------------------
  297. BOOL WinSearch (char *pszFName, char *pszExts, INT sFType) {
  298.     char    szDir[MAXFNAMELEN];
  299.  
  300.     if ((*(pszFName+1) == ':') || (strchr (pszFName, '\\')))
  301.         return FindFile (pszFName, pszExts, sFType);
  302.     //
  303.     // Current dir
  304.     //
  305.     DirQCur (szDir, sizeof (szDir));
  306.     CombinePath (szDir, pszFName, sizeof (szDir));
  307.     if (FindFile (szDir, pszExts, sFType)) {
  308.         strcpy (pszFName, szDir);
  309.         return TRUE;
  310.     }
  311.     //
  312.     // Windows dir
  313.     //
  314.     strcpy (szDir, szLibPath);
  315.     CombinePath (szDir, pszFName, sizeof (szDir));
  316.     if (FindFile (szDir, pszExts, sFType)) {
  317.         strcpy (pszFName, szDir);
  318.         return TRUE;
  319.     }
  320.     //
  321.     // Windows System dir
  322.     //
  323.     strcpy (szDir, szLibPath);
  324.     strcat (szDir, "\\SYSTEM");
  325.     CombinePath (szDir, pszFName, sizeof (szDir));
  326.     if (FindFile (szDir, pszExts, sFType)) {
  327.         strcpy (pszFName, szDir);
  328.         return TRUE;
  329.     }
  330.     //
  331.     // This program's dir
  332.     //
  333.     strcpy (szDir, szProgDir);
  334.     CombinePath (szDir, pszFName, sizeof (szDir));
  335.     if (FindFile (szDir, pszExts, sFType)) {
  336.         strcpy (pszFName, szDir);
  337.         return TRUE;
  338.     }
  339.     //
  340.     // Search DOS's PATH
  341.     //
  342.     return SearchPath (pszFName, szPath, pszExts, sFType);
  343. }
  344. //-------------------------------------------------------------------
  345. // GetPIFRefs - Prints the DOS file the PIF file loads
  346. //-------------------------------------------------------------------
  347. INT GetPIFRefs (char *szFName) {
  348.  
  349.     USHORT    usSel, usBytesRead;
  350.     SHORT        i;
  351.     PBYTE        lpbData;
  352.     HFILE        hFile;
  353.     char        szPIFName[128];
  354.  
  355.     //
  356.     //Read PIF file
  357.     //
  358.     if (DosAllocSeg (BUFFSIZE, &usSel, 0))
  359.         return ERR_OUTOFMEM;
  360.     lpbData = MAKEP (usSel, 0);
  361.     hFile = FileOpen (szFName);
  362.     DosRead (hFile, lpbData, BUFFSIZE, &usBytesRead);
  363.     FileClose (hFile);
  364.     //
  365.     //Copy program name
  366.     //
  367.     lpbData += 0x24;
  368.     for (i = 0; i < sizeof (szPIFName)-1 && *lpbData != '\0'; i++)
  369.         szPIFName[i] = *lpbData++;
  370.  
  371.     szPIFName[i] = '\0';
  372.     DosFreeSeg (usSel);
  373.  
  374.     if (DOSSearch (szPIFName, szDOSExts, -1)) {
  375.         printf ("\n Runs ");
  376.         PrintFName (szPIFName, GetEXEType (szPIFName, 0, 0), sLevel);
  377.         return 0;
  378.     }
  379.     printf ("\nWarning!  Program file: ");
  380.     printf (szPIFName);
  381.     printf (" not found.\n\n");
  382.     return 2;
  383. }
  384. //-------------------------------------------------------------------
  385. // GetNERefs - Prints a list of an NE file's refs and their refs.
  386. //-------------------------------------------------------------------
  387. INT GetNERefs (char *szFName, INT sNumRefEnt, ULONG ulFPtr, INT sType) {
  388.  
  389.     char        szOldProgDir[MAXFNAMELEN];
  390.     USHORT    usSel, usBytesRead;
  391.     SHORT        i, j, sSubRef, rc = 0;
  392.     PBYTE        lpbData;
  393.     HFILE        hFile;
  394.     PSZ        lpszName;
  395.     BYTE        bNameLen;
  396.     BOOL        fGetRef;
  397.  
  398.     if (sLevel >= sMaxLevel)
  399.         return 0;
  400.     sLevel++;
  401.     //
  402.     //Read Mod Ref table
  403.     //
  404.     if (DosAllocSeg (BUFFSIZE, &usSel, 0))
  405.         return ERR_OUTOFMEM;
  406.     lpbData = MAKEP (usSel, 0);
  407.     hFile = FileOpen (szFName);
  408.     DosChgFilePtr (hFile, (LONG) ulFPtr, 0, &ulFPtr);
  409.     DosRead (hFile, lpbData, BUFFSIZE, &usBytesRead);
  410.     FileClose (hFile);
  411.     //
  412.     //Find file for each entry in the table.
  413.     //
  414.     strcpy (szOldProgDir, szProgDir);
  415.     strcpy (szProgDir, szFName);
  416.     *strrchr (szProgDir, '\\') = '\0';
  417.     for (i = 0; i < sNumRefEnt; i++) {
  418.         //
  419.         // Copy file name in ref table
  420.         //
  421.         lpszName = lpbData + *((PUINT)lpbData+i) + (sNumRefEnt*2);
  422.         bNameLen = (BYTE) *lpszName++;
  423.         for (j = 0; j < (SHORT) bNameLen; j++)
  424.             szFName[j] = *lpszName++;
  425.         szFName[j] = '\0';
  426.         //
  427.         fGetRef = TRUE;
  428.         switch (sType) {
  429.             case 1:
  430.                 if ((strcmp (szFName, "KERNEL") == 0) || 
  431.                     (strcmp (szFName, "DISPLAY") == 0)) {
  432.                     PrintFName (szFName, 0x101, sLevel);
  433.                     fGetRef = FALSE;
  434.                 }
  435.                 break;
  436.             case 2:
  437.                 if (strcmp (szFName, "DOSCALLS") == 0) {
  438.                     PrintFName (szFName, 0x106, sLevel);
  439.                     fGetRef = FALSE;
  440.                 }
  441.                 break;
  442.         }
  443.         if (fGetRef) {
  444.             switch (sType) {
  445.                 case 1:
  446.                     fGetRef = WinSearch(szFName, szWinLExts, sType + 0x100);
  447.                     break;
  448.                 case 2:
  449.                     fGetRef = SearchPath2 (szFName, szLibPath, szOS2LExts, 
  450.                                            0x102, 0x104);
  451.                     break;
  452.                 default:
  453.                     fGetRef = FALSE;
  454.             }
  455.             if (fGetRef) {
  456.                 j = GetEXEType (szFName, &sSubRef, &ulFPtr);
  457.                 PrintFName (szFName, j, sLevel);
  458.                 if ((sType) && (j-0x100 == sType)) {
  459.                     if (sNumRefEnt) 
  460.                         GetNERefs (szFName, sSubRef, ulFPtr, sType);
  461.                 }
  462.             } else {
  463.                 printf ("\nWarning!  Library file: ");
  464.                 printf (szFName);
  465.                 printf (" not found.\n\n");
  466.                 rc = 2;
  467.             }
  468.         }
  469.     }
  470.     strcpy (szProgDir, szOldProgDir);
  471.     DosFreeSeg (usSel);
  472.     sLevel--;
  473.     return rc;
  474. }
  475. //-------------------------------------------------------------------
  476. // GetLXRefs - Prints a list of an NE file's refs and their refs.
  477. //-------------------------------------------------------------------
  478. INT GetLXRefs (char *szFName, INT sNumRefEnt, ULONG ulFPtr) {
  479.  
  480.     char        szOldProgDir[MAXFNAMELEN];
  481.     USHORT    usSel, usBytesRead;
  482.     SHORT        i, j, sSubRef, rc = 0;
  483.     PBYTE        lpbData;
  484.     HFILE        hFile;
  485.     PSZ        lpszName;
  486.     BYTE        bNameLen;
  487.     BOOL        fGetRef;
  488.  
  489.     if (sLevel >= sMaxLevel)
  490.         return 0;
  491.     sLevel++;
  492.     //
  493.     //Read Mod Ref table
  494.     //
  495.     if (DosAllocSeg (BUFFSIZE, &usSel, 0))
  496.         return ERR_OUTOFMEM;
  497.     lpbData = MAKEP (usSel, 0);
  498.     hFile = FileOpen (szFName);
  499.     DosChgFilePtr (hFile, (LONG) ulFPtr, 0, &ulFPtr);
  500.     DosRead (hFile, lpbData, BUFFSIZE, &usBytesRead);
  501.     FileClose (hFile);
  502.     //
  503.     //Find file for each entry in the table.
  504.     //
  505.     strcpy (szOldProgDir, szProgDir);
  506.     strcpy (szProgDir, szFName);
  507.     *strrchr (szProgDir, '\\') = '\0';
  508.     lpszName = lpbData;
  509.     for (i = 0; i < sNumRefEnt; i++) {
  510.         // 
  511.         // Copy entry table file name
  512.         //
  513.         bNameLen = (BYTE) *lpszName++;
  514.         for (j = 0; j < (SHORT) bNameLen; j++)
  515.             szFName[j] = *lpszName++;
  516.         szFName[j] = '\0';
  517.         //    
  518.         // Don't look up kernel file.
  519.         //
  520.         fGetRef = TRUE;
  521.         if (strcmp (szFName, "DOSCALLS") == 0) {
  522.             PrintFName (szFName, 0x104, sLevel);
  523.             fGetRef = FALSE;
  524.         } else {
  525.             //
  526.             // Find File
  527.             //
  528.             if (SearchPath (szFName, szLibPath, szOS2LExts, 0x104)) {
  529.                 PrintFName (szFName, GetEXEType (szFName, &sSubRef, &ulFPtr),
  530.                             sLevel);
  531.                 if (sSubRef) 
  532.                     GetLXRefs (szFName, sSubRef, ulFPtr);
  533.             } else {
  534.                 printf ("\nWarning!  Library file: ");
  535.                 printf (szFName);
  536.                 printf (" not found.\n\n");
  537.                 rc = 2;
  538.             }
  539.         }
  540.     }
  541.     strcpy (szProgDir, szOldProgDir);
  542.     DosFreeSeg (usSel);
  543.     sLevel--;
  544.     return rc;
  545. }
  546. //-------------------------------------------------------------------
  547. // GetEXEType - Loads a file and returns its dest OS.
  548. //-------------------------------------------------------------------
  549. INT GetEXEType (char *szFName, INT *psNumRefEnt, LONG *plFPtr) {
  550.  
  551.     PBYTE        lpbData;
  552.     USHORT    usSel, usBytesRead;
  553.     INT        sTargOS;
  554.     HFILE        hFile;
  555.  
  556.     if (DosAllocSeg (BUFFSIZE, &usSel, 0))
  557.         return ERR_OUTOFMEM;
  558.     lpbData = MAKEP (usSel, 0);
  559.  
  560.     hFile = FileOpen (szFName);
  561.     if (hFile == -1) {
  562.         DosFreeSeg (usSel);
  563.         return (ERR_NOOPENEXE);
  564.     }                    
  565.     DosRead (hFile, lpbData, BUFFSIZE, &usBytesRead);
  566.     if (usBytesRead < 0x40) {                
  567.         FileClose (hFile);
  568.         DosFreeSeg (usSel);
  569.         return 0;
  570.     }
  571.     //Check for "MZ"
  572.     if (*(PUSHORT)lpbData != 0x5a4d) {
  573.         FileClose (hFile);
  574.         sTargOS = 0;                 //DOS            
  575.         if (*(PLONG)(lpbData+0x171) == 0x5243494d) 
  576.             sTargOS = 7;              //Window PIF            
  577.         DosFreeSeg (usSel);
  578.         return sTargOS;
  579.     }
  580.     //Check for New EXE header
  581.     if (*((PSHORT)(lpbData+0x18)) < 0x40) {
  582.         FileClose (hFile);
  583.         DosFreeSeg (usSel);
  584.         return 0;
  585.     }
  586.     //Read New EXE header
  587.     *plFPtr = (LONG) *((PLONG)(lpbData+0x3C));
  588.     DosChgFilePtr (hFile, (LONG) *plFPtr, 0, plFPtr);
  589.  
  590.     DosRead (hFile, lpbData, BUFFSIZE, &usBytesRead);
  591.     FileClose (hFile);
  592.  
  593.     switch (*(PUSHORT)lpbData) {
  594.  
  595.         //Check for NewEXE (NE)
  596.         case 0x454E:
  597.             if (*(lpbData+0x36) & 2) 
  598.                 sTargOS = 1;                 //Windows
  599.             else if (*(lpbData+0x36) & 1) 
  600.                 sTargOS = 2;                 //OS/2 1.x
  601.  
  602.             if (*(PUSHORT)(lpbData+0x0C) & 0x8000) 
  603.                 sTargOS += 0x100;            //Library
  604.  
  605.             if (psNumRefEnt != 0)             
  606.                 *psNumRefEnt = *((PSHORT)(lpbData+0x1E));
  607.             if (plFPtr != 0) 
  608.                 *plFPtr += (LONG) *((PUINT)(lpbData+0x28));
  609.  
  610.             break;
  611.  
  612.         //Check for LinearEXE (LE)
  613.         case 0x454C:
  614.             sTargOS = 3;                    //Win 3.x Enh mode
  615.             if (*(PULONG)(lpbData+0x10) & 0x8000) 
  616.                 sTargOS += 0x100;            //Library
  617.  
  618.             if (psNumRefEnt != 0)
  619.                 *psNumRefEnt = (INT) *((PULONG)(lpbData+0x74));
  620.             if (plFPtr != 0) 
  621.                 *plFPtr += (LONG) *((PULONG)(lpbData+0x70));
  622.             break;
  623.  
  624.         //Check for LinearEXE (LX)
  625.         case 0x584C:
  626.             sTargOS = 4;                    //OS/2 2.x
  627.             if (*(PULONG)(lpbData+0x10) & 0x8000) 
  628.                 sTargOS += 0x100;            //Library
  629.  
  630.             if (psNumRefEnt != 0)
  631.                 *psNumRefEnt = (INT) *((PULONG)(lpbData+0x74));
  632.             if (plFPtr != 0) 
  633.                 *plFPtr += (LONG) *((PULONG)(lpbData+0x70));
  634.             break;
  635.  
  636.         //Check for LinearEXE (PE)
  637.         case 0x4550:
  638.             sTargOS = 5;                    //Win/NT
  639.             if (psNumRefEnt != 0)             
  640.                 *psNumRefEnt = 0;
  641.             break;
  642.     
  643.     }
  644.     DosFreeSeg (usSel);
  645.     return sTargOS;
  646. }
  647.  
  648. //-------------------------------------------------------------------
  649. // CombinePath - Appends a file name to a Path string
  650. //-------------------------------------------------------------------
  651. void CombinePath (char *pszOut, char *pszIn, INT sOutSize) {
  652.  
  653.     if ((INT) strlen (pszIn) > sOutSize - strlen (pszOut))
  654.         return;
  655.  
  656.     if (pszOut[strlen (pszOut)-1] != '\\')
  657.         strcat (pszOut, "\\");
  658.     strcat (pszOut, pszIn);
  659.     return;
  660. }
  661. //-------------------------------------------------------------------
  662. // SearchPath - Searches for a file along a path 
  663. //-------------------------------------------------------------------
  664. BOOL SearchPath (char *pszFName, char *szPath, char *pszExts, INT sFType) {
  665.     char    szDir[MAXPATHLEN];
  666.     INT    j;
  667.  
  668.     j = 0;        
  669.     while (GetPathDir (szPath, szDir, j++)) {
  670.         CombinePath (szDir, pszFName, sizeof (szDir));
  671.         if (FindFile (szDir, pszExts, sFType)) {
  672.             strcpy (pszFName, szDir);
  673.             return TRUE;
  674.         }
  675.     }
  676.     return FALSE;
  677. }
  678. //-------------------------------------------------------------------
  679. // SearchPath2 - Searches for a file along a path.  Looks for 2
  680. // types of files.
  681. //-------------------------------------------------------------------
  682. BOOL SearchPath2 (char *pszFName, char *szPath, char *pszExts, 
  683.                   INT sFType1, INT sFType2) {
  684.     char    szDir[MAXPATHLEN];
  685.     INT    j;
  686.  
  687.     j = 0;        
  688.     while (GetPathDir (szPath, szDir, j++)) {
  689.         CombinePath (szDir, pszFName, sizeof (szDir));
  690.         if (FindFile (szDir, pszExts, sFType1)) {
  691.             strcpy (pszFName, szDir);
  692.             return TRUE;
  693.         } else if (FindFile (szDir, pszExts, sFType2)) {
  694.             strcpy (pszFName, szDir);
  695.             return TRUE;
  696.         }
  697.     }
  698.     return FALSE;
  699. }
  700.  
  701. //-------------------------------------------------------------------
  702. // FindFile - Searches for a file in a directory
  703. //-------------------------------------------------------------------
  704. BOOL FindFile (char *pszDir, char *pszExts, INT sFType) {
  705.     char    szTemp[MAXFNAMELEN];
  706.     INT    i, rc = 0, sFHdl = 1;
  707.     char    *pszNameEnd;
  708.     BOOL    fExt;
  709.     FILEFINDBUF    ffb;
  710.     
  711.     strcpy (szTemp, pszDir);
  712.  
  713.     for (i = 0; szTemp[i] != 0; i++) {
  714.         if (szTemp[i] == '.')
  715.             fExt = TRUE;
  716.         else if (szTemp[i] == '\\')
  717.             fExt = FALSE;
  718.     }
  719.     if (fExt) {
  720.         rc = 1;
  721.         sFHdl = 1;
  722.         DosFindFirst (szTemp, &sFHdl, 0x27, &ffb, sizeof (ffb), &rc, 0);
  723.     } else {
  724.         pszNameEnd = &szTemp[strlen (szTemp)];
  725.         for (i = 0; AddExt (pszNameEnd, pszExts, i); i++) {
  726.             rc = 1;
  727.             sFHdl = 1;
  728.             DosFindFirst (szTemp, &sFHdl, 0x27, &ffb, sizeof (ffb), &rc, 0);
  729.             if (rc != 0)
  730.                 break;
  731.         }
  732.     }
  733.     if (rc != 0) {
  734.         if ((sFType != -1) && (GetEXEType (szTemp, 0, 0) != sFType)) 
  735.             return FALSE;
  736.         strcpy (pszDir, szTemp);
  737.         strupr (pszDir);
  738.         return TRUE;
  739.     } else
  740.         return FALSE;
  741. }
  742. //-------------------------------------------------------------------
  743. // AddExt - Appends an extension from a list of extensions to a filename.
  744. //-------------------------------------------------------------------
  745. BOOL AddExt (char *pszOut, char *pszExt, INT sNum) {
  746.     
  747.     while (*pszExt != '\0') {
  748.         //
  749.         // Find non-space char
  750.         //        
  751.         while (*pszExt <= ' ') {
  752.             if (*pszExt == '\0')
  753.                 break;
  754.             pszExt++;
  755.         }
  756.         if (sNum == 0)
  757.             break;
  758.         pszExt += min (3, strlen (pszExt));
  759.         sNum--;
  760.     }
  761.     if (*pszExt == '\0')
  762.         return FALSE;
  763.  
  764.     strcpy (pszOut, ".");
  765.     strncpy (pszOut+1, pszExt, 3);
  766.     *(pszOut+4) = '\0';
  767.     return TRUE;
  768. }    
  769. //-------------------------------------------------------------------
  770. // GetPathDir - Returns a drectory from the path
  771. //-------------------------------------------------------------------
  772. BOOL GetPathDir (char *pszPath, char *pszDir, INT sDirNum) {
  773.     char    *pszEnd;
  774.     char    chChar;
  775.     INT    i;
  776.  
  777.     pszEnd = strchr (pszPath, ';');
  778.     for (i = 0; i < sDirNum && pszEnd != 0; i++) {
  779.         pszPath = pszEnd+1;
  780.         pszEnd = strchr (pszPath, ';');
  781.     }
  782.     if (i == sDirNum) {
  783.         chChar = 0;
  784.         if (pszEnd != 0) {
  785.             chChar = *pszEnd;
  786.             *pszEnd = '\0';
  787.         }
  788.         strcpy (pszDir, pszPath);
  789.         if (chChar)
  790.             *pszEnd = chChar;
  791.         return TRUE;
  792.     }
  793.     return FALSE;
  794. }
  795. //-------------------------------------------------------------------
  796. // FindEnvVar - Returnss the environment for a variable
  797. //-------------------------------------------------------------------
  798. char *FindEnvVar (PSZ lpszEnv, char *pszVarName, char *pszOut, 
  799.                   INT sOutSize) {
  800.  
  801.     INT    i, sVarSize;
  802.     char    *pszPtr;
  803.     char    *pszOutSave;
  804.  
  805.     sVarSize = strlen (pszVarName);
  806.     pszOutSave = pszOut;
  807.     while (*lpszEnv != 0) {
  808.         pszPtr = pszVarName;
  809.         for (i = 0; i < sVarSize && *lpszEnv != '\0'; i++) {
  810.             if (*pszPtr++ != (char) *lpszEnv++)
  811.                 break;
  812.         }
  813.         if ((i == sVarSize) && (*lpszEnv == '=')) {
  814.             lpszEnv++;
  815.             for (i = 0; i < sOutSize-1 && *lpszEnv != '\0'; i++)
  816.                 *pszOut++ = *lpszEnv++;
  817.             *pszOut = '\0';
  818.             return pszOutSave;
  819.         } else {
  820.             for (i = 0; i < MAXPATHLEN && *lpszEnv != '\0'; i++)
  821.                 lpszEnv++;
  822.              lpszEnv++;
  823.         }
  824.     }
  825.     return 0;
  826. }
  827. //-------------------------------------------------------------------
  828. // GetItem - Returns an item from a file
  829. //-------------------------------------------------------------------
  830. BOOL GetItem (char *pszFName, char *pszSrchStr, char *pszOut, INT sOutSize ) {
  831.  
  832.     PSZ        lpszData, lpszSrc, lpszName;
  833.     USHORT    i, usSel, usBytesRead, usSrchLen;
  834.     HFILE        hFile;
  835.  
  836.     usSrchLen = strlen (pszSrchStr);
  837.     if (DosAllocSeg (CBUFFSIZE, &usSel, 0))
  838.         return ERR_OUTOFMEM;
  839.     lpszData = MAKEP (usSel, 0);
  840.  
  841.     hFile = FileOpen (pszFName);
  842.     if (hFile == -1) {
  843.         DosFreeSeg (usSel);
  844.         return FALSE;
  845.     }
  846.     DosRead (hFile, lpszData, CBUFFSIZE, &usBytesRead);
  847.     FileClose (hFile);
  848.     if (usBytesRead < usSrchLen) {
  849.         DosFreeSeg (usSel);
  850.         return FALSE;
  851.     }
  852.     while (usBytesRead >= usSrchLen) {
  853.         //
  854.         // Find nonspace character
  855.         //
  856.         while (usBytesRead >= usSrchLen) {
  857.             if (*lpszData > ' ')
  858.                 break;
  859.             usBytesRead--;    
  860.         }    
  861.         //
  862.         // See if 1st char matches
  863.         //            
  864.         if ((char) *lpszData == pszSrchStr[0]) {
  865.             lpszSrc = lpszData;
  866.             lpszName = (PSZ) pszSrchStr;
  867.             i = 0;
  868.             while ((*lpszSrc == *lpszName) && (i < usBytesRead)    &&
  869.                    (*lpszSrc != 0) && (*lpszName != 0)) {
  870.                 lpszName++;
  871.                 lpszSrc++;
  872.                 i++;
  873.             }
  874.             if (*lpszName == 0)
  875.                 break;
  876.         }
  877.         //
  878.         // Skip to end of line
  879.         //
  880.         for (i = 0; i < usBytesRead; i++) {
  881.             usBytesRead--;
  882.             if (*lpszData++ == 0x0d)
  883.                 break;
  884.         }            
  885.         usBytesRead--;
  886.         lpszData++;
  887.     }
  888.     if (*lpszName == 0)
  889.         for (i = 0; i < (USHORT) sOutSize && *lpszSrc != 0x0d; i++)
  890.             *pszOut++ = *lpszSrc++;
  891.     *pszOut = 0;
  892.  
  893.     DosFreeSeg (usSel);
  894.     if (*lpszName == 0)
  895.         return TRUE;
  896.     else
  897.         return FALSE;
  898. }
  899. //-------------------------------------------------------------------
  900. // ParseCmdLine - Parses the command line.
  901. //-------------------------------------------------------------------
  902. INT ParseCmdLine (INT argc, char **argv, char *pszExeName, INT *psSrchType) {
  903.     BOOL    fExt, fPathInc = FALSE, fFirst = TRUE, fSwitch = FALSE;
  904.     INT    i, j;
  905.     char    szFName[MAXFNAMELEN];
  906.  
  907.     fExt = FALSE;
  908.     szFName[0] = '\0';
  909.     
  910.     if (argc < 2)
  911.         return ERR_SYNTAX;
  912.  
  913.     for (i = 1; i < argc; i++) {
  914.  
  915.         if (*argv[i] == '/' || *argv[i] == '-') {
  916.             switch (*(argv[i]+1)) {
  917.                 case '?':
  918.                     return ERR_HELP;
  919.  
  920.                 case 'd':
  921.                 case 'D':
  922.                     if (fSwitch)
  923.                         return ERR_2SWITCHES;
  924.                     *psSrchType = 0;
  925.                     fSwitch = TRUE;
  926.                     break;
  927.  
  928.                 case 'w':
  929.                 case 'W':
  930.                     if (fSwitch)
  931.                         return ERR_2SWITCHES;
  932.                     *psSrchType = 1;
  933.                     fSwitch = TRUE;
  934.                     break;
  935.  
  936.                 case '2':
  937.                     if (fSwitch)
  938.                         return ERR_2SWITCHES;
  939.                     *psSrchType = 2;
  940.                     fSwitch = TRUE;
  941.                     break;
  942.  
  943.                 case 'v':
  944.                 case 'V':
  945.                     sMaxLevel = 20;
  946.                     break;
  947.  
  948.                 case 'l':
  949.                 case 'L':
  950.                     if ((*(argv[i]+2) >= '0') && (*(argv[i]+2) <= '9')) {
  951.                         sMaxLevel = *(argv[i]+2) - '0';
  952.                         if ((*(argv[i]+3) >= '0') && (*(argv[i]+3) <= '9')) 
  953.                             return ERR_LIMTOHIGH;
  954.                     } else
  955.                         return ERR_SYNTAX;
  956.                     break;
  957.  
  958.                 default:
  959.                     return ERR_SYNTAX;
  960.             }
  961.         } else {
  962.             if (!fFirst)
  963.                 return ERR_SYNTAX;
  964.             fFirst = FALSE;
  965.             for (j = 0; (j < MAXFNAMELEN) && (argv[i][j] > ' ') &&                
  966.                          !strchr ("?*-+/<>", argv[i][j]); j++) {
  967.  
  968.                 if (argv[i][j] == '.')
  969.                     fExt = TRUE;
  970.                 else if (argv[i][j] == '\\') {
  971.                     fExt = FALSE;
  972.                     fPathInc = TRUE;
  973.                 }                    
  974.                 szFName[j] = argv[i][j];
  975.             }
  976.             szFName[j] = '\0';
  977.             if (szFName[1] == ':')
  978.                 fPathInc = TRUE;
  979.             if (usDosVer < 0x400)
  980.                 if (fExt)
  981.                     *strrchr (szFName, '.') = '\0';
  982.         }
  983.     }
  984.     if (szFName[0] == 0)
  985.         return ERR_SYNTAX;
  986.     if (fPathInc)
  987.         _fullpath (pszExeName, szFName, MAXFNAMELEN);
  988.     else
  989.         strcpy (pszExeName, szFName);
  990.  
  991.     return 0;
  992. }
  993. //-------------------------------------------------------------------
  994. // PrintFName - Long ptr string cmp
  995. //-------------------------------------------------------------------
  996. void PrintFName (char *pszFName, INT sExeType, INT sLevel) {
  997.  
  998.     INT    i;
  999.  
  1000.      for (i = 0; i < sLevel; i++)
  1001.          printf("   ");
  1002.  
  1003.     switch (sExeType & 0xff) {
  1004.         case 0:
  1005.             printf ("DOS ");
  1006.             break;
  1007.         case 1:
  1008.             printf ("Windows ");
  1009.             break;
  1010.         case 2:
  1011.             printf ("OS/2 1.x ");
  1012.             break;
  1013.         case 3:
  1014.             printf ("Windows Enhanced Mode ");
  1015.             break;
  1016.         case 4:
  1017.             printf ("OS/2 2.x ");
  1018.             break;
  1019.         case 5:
  1020.             printf ("Windows/NT ");
  1021.             break;
  1022.         case 6:
  1023.             printf ("OS/2 ");
  1024.             break;
  1025.         case 7:
  1026.             printf ("Windows PIF ");
  1027.             sExeType = 0x207;
  1028.             break;
  1029.     }
  1030.     if (sExeType > 0x200)
  1031.         printf ("File: ");
  1032.     else if (sExeType > 0x100)
  1033.         printf ("DLL: ");
  1034.     else
  1035.         printf ("Program: ");
  1036.  
  1037.     printf (pszFName);
  1038.     printf ("\n");
  1039. }
  1040.  
  1041. //-------------------------------------------------------------------
  1042. // DirQCur - Returns the current drive and dir
  1043. //-------------------------------------------------------------------
  1044. void DirQCur (char *pszDir, INT sMaxLen) {
  1045.  
  1046.     DosQCurDisk ((PUSHORT)pszDir, (PLONG)&pszDir[2]);
  1047.     pszDir[0] += 0x40;
  1048.     pszDir[1] = ':';
  1049.     pszDir[2] = '\\';
  1050.     sMaxLen -= 3;
  1051.     DosQCurDir (0, &pszDir[3], &sMaxLen);
  1052.     if (pszDir[3] == '\\')
  1053.         pszDir[3] = '\0';
  1054.     return;
  1055. }
  1056. //-------------------------------------------------------------------
  1057. // FileOpen - Opens a file for editing
  1058. //-------------------------------------------------------------------
  1059. HFILE FileOpen (char *szFileName) {
  1060.     UINT    usAction, rc;
  1061.     HFILE    hFile;
  1062.  
  1063.     rc = DosOpen (szFileName, &hFile, &usAction, 0, 0, FILE_OPEN,
  1064.                       OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,  0L);
  1065.  
  1066.     if (rc == 0)
  1067.        return hFile;
  1068.     else
  1069.         return -1;
  1070. }                    
  1071. //-------------------------------------------------------------------
  1072. // FileClose - Closes a file
  1073. //-------------------------------------------------------------------
  1074. INT FileClose (HFILE hFile) {
  1075.  
  1076.     return DosClose (hFile);
  1077. }                    
  1078.