Ignore:
Timestamp:
Apr 16, 2000, 12:42:13 PM (25 years ago)
Author:
sandervl
Message:

put back dll search method + loadlibraryex fix

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/winimagebase.cpp

    r3399 r3404  
    1 /* $Id: winimagebase.cpp,v 1.17 2000-04-16 06:47:22 bird Exp $ */
     1/* $Id: winimagebase.cpp,v 1.18 2000-04-16 10:42:12 sandervl Exp $ */
    22
    33/*
    44 * Win32 PE Image base class
    55 *
    6  * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
    7  * Copyright 1998-2000 Knut St. Osmundsen (knut.stange.osmundsen@pmsc.no)
     6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
     7 * Copyright 1998 Knut St. Osmundsen
    88 *
    99 * Project Odin Software License can be found in LICENSE.TXT
     
    1111 */
    1212
    13 #define INCL_DOSFILEMGR                 /* File Manager values */
    14 #define INCL_DOSMODULEMGR               /* DOS Module manager */
    15 #define INCL_DOSERRORS                  /* DOS Error values */
    16 #define INCL_DOSPROCESS                 /* DOS Process values */
    17 #define INCL_DOSMISC                    /* DOS Miscellanous values */
    18 #define INCL_WIN                        /* All Win API */
    19 #define INCL_BASE                       /* All Dos API */
    20 #include <os2wrap.h>                    /* Odin32 OS/2 API wrappers. */
    21 
    22 #include <stdio.h>                      /* C Library Standard I/O */
    23 #include <string.h>                     /* C Library string operations */
    24 #include <stdlib.h>                     /* C Library Standard stuff */
    25 
    26 #include <misc.h>                       /* Odin32 Miscellaneous definitions, debug stuff*/
    27 #include <win32type.h>                  /* Odin32 Common types and definition. */
    28 #include "winimagebase.h"               /* Odin32 Executable Image Base Class */
    29 #include "windllbase.h"                 /* Odin32 Dll Base Class */
    30 #include "winexebase.h"                 /* Odin32 Exe Base Class */
    31 #include <pefile.h>                     /* Odin32 PE definitions */
    32 #include <unicode.h>                    /* Odin32 Unicode conversion */
    33 #include <winres.h>                     /* Odin32 Resource Class */
     13#define INCL_DOSFILEMGR          /* File Manager values      */
     14#define INCL_DOSMODULEMGR
     15#define INCL_DOSERRORS           /* DOS Error values         */
     16#define INCL_DOSPROCESS          /* DOS Process values       */
     17#define INCL_DOSMISC             /* DOS Miscellanous values  */
     18#define INCL_WIN
     19#define INCL_BASE
     20#include <os2wrap.h>             //Odin32 OS/2 api wrappers
     21
     22#include <stdio.h>
     23#include <string.h>
     24#include <stdlib.h>
     25
     26#include <assert.h>
     27#include <misc.h>
     28#include <win32type.h>
     29#include <winimagebase.h>
     30#include <windllbase.h>
     31#include <winexebase.h>
     32#include <pefile.h>
     33#include <unicode.h>
     34#include <winres.h>
    3435#include "oslibmisc.h"
    3536#include "oslibdos.h"
    3637#include "initterm.h"
     38#include "directory.h"
    3739#include <win\virtual.h>
    38 #include "directory.h"                  /* InternalGet<Windows/System>Directory. */
    39 #include <os2newapi.h>                  /* DosQueryHeaderInfo. */
    40 
    41 #define DBG_LOCALLOG    DBG_winimagebase
     40
     41#define DBG_LOCALLOG    DBG_winimagebase
    4242#include "dbglocal.h"
    4343
     
    115115  item = loadedDlls.Head();
    116116  while(item) {
    117     if(loadedDlls.getItem(item) == (ULONG)image) {
    118         ret = TRUE;
    119         break;
    120     }
    121     item = loadedDlls.getNext(item);
     117        if(loadedDlls.getItem(item) == (ULONG)image) {
     118                ret = TRUE;
     119                break;
     120        }         
     121        item = loadedDlls.getNext(item);
    122122  }
    123123  dlllistmutex.leave();
     
    132132  return 0x40000; //NT 4
    133133}
    134 
    135 
    136 /**
    137  * Finds a executable module (or really any file) using the DLL search order.
    138  * The search order used is:
    139  *      1. The directory from which the application loaded.
    140  *      2. The current directory.
    141  *      3. System directory. (GetSystemDirectory returns its path)
    142  *         (Windows NT/2k directory name: SYSTEM32)
    143  *      4. (Windows NT/2k: The 16-bit Windows system directory. There
    144  *         is no function that obtains the path of this directory.
    145  *         (Directory name: SYSTEM)
    146  *         THIS IS NOT SEARCHED BY ODIN.)
    147  *      5. The Windows directory. (GetWindowsDirectory returns its path)
    148  *      6. The Directories listed in the PATH environment variable.
    149  *      7. The Directories listed in the BEGINLIBPATH.
    150  *      8. The Directories listed in the LIBPATH.
    151  *      9. The Directories listed in the ENDLIBPATH.
    152  *
    153  * @returns   Success indicator. TRUE: found  FALSE: not found.
    154  *            Note! pszFullname will normally contain the contents of
    155  *            pszFilename upon return, there is one case FALSE case when
    156  *            pszFullname will be empty upon return. That's when the buffer
    157  *            isn't large enough to hold the content of pszFilename including
    158  *            an extention.
    159  *            So, please check for the return value!
    160  * @param     pszFilename   File to find. This name should not have a path!
    161  *                          If it don't contains an '.', ".DLL" is appended to
    162  *                          the name.
    163  * @param     pszFullname   Pointer to output buffer, this will hold the
    164  *                          a fully qualified, uppercased, filename upon
    165  *                          successful return.
    166  * @param     cchFullname   Size of the buffer pointer to by pszFullname.
    167  *                          (A length of at least CCHMAXPATH is recommended.)
    168  * @parm      pszAltPath    Pointer to alternate first executable path. This
    169  *                          will include a filename or at least a backslash at
    170  *                          the end.
    171  *                          If this is NULL (which is it by default) the
    172  *                          executable path is used. If this is specified,
    173  *                          this path is used instead. This is intented used
    174  *                          to implement the LoadLibraryEx flag
    175  *                          LOAD_WITH_ALTERED_SEARCH_PATH.
    176  *
    177  * @status    Completely implemented.
    178  * @author    Sander van Leeuwen (sandervl@xs4all.nl)
    179  *            knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
    180  * @remark
    181  */
    182 BOOL Win32ImageBase::findDll(const char *pszFileName,
    183                              char *pszFullName, int cchFullName,
    184                              const char *pszAltPath /*=NULL*/)
    185 {
    186     BOOL            fRet = FALSE;       /* Return value. (Pessimistic attitude! Init it to FALSE...) */
    187     char *          psz;                /* General string pointer. */
    188     int             cchFileName;        /* Length of the normalized filename (after ".DLL" is added). */
    189     struct localvars                    /* local variables which are to big to fit onto the stack. */
    190     {
    191         char            szPath[1024];   /* Path buffer. Used to store pathlists. 1024 should be enough */
    192                                         /* for LIBPATH (which at least had a limit of ca. 750 chars). */
    193         char            sz[CCHMAXPATH]; /* Filename/path buffer. (Normally used to build filenames */
    194                                         /* which are passed in as search experessions to DosFindFirst.) */
    195         FILEFINDBUF3    findbuf3;       /* DosFindFirst buffer. */
    196     } *             plv;
    197     int             iPath;              /* Current path or pathlist being examined. This is the loop */
    198                                         /* variable looping on the FINDDLL_* defines. */
    199 
    200     /* These defines sets the order the paths and pathlists are examined. */
    201     #define FINDDLL_EXECUTABLEDIR   1
    202     #define FINDDLL_CURRENTDIR      2
    203     #define FINDDLL_SYSTEM32DIR     3
    204     #define FINDDLL_SYSTEM16DIR     4
    205     #define FINDDLL_WINDIR          5
    206     #define FINDDLL_PATH            6
    207     #define FINDDLL_BEGINLIBPATH    7
    208     #define FINDDLL_LIBPATH         8
    209     #define FINDDLL_ENDLIBPATH      9
    210     #define FINDDLL_FIRST           FINDDLL_EXECUTABLEDIR
    211     #define FINDDLL_LAST            FINDDLL_ENDLIBPATH
    212 
    213 
    214     /** @sketch
    215      * Copy the filename to be found to the outputbuffer, and add .DLL if not '.'
    216      * is found in the name. This has two reasons:
    217      *  1) When searching paths we simply append the buffer contents to the path
    218      *     being examined.
    219      *  2) The buffer will at least return the passed in filename.
    220      */
    221     psz = strchr(pszFileName, '.');
    222     cchFileName = strlen(pszFileName) + (psz ? 0 : 4);
    223     if (cchFileName >= cchFullName)
    224     {
    225         dassert(cchFileName < cchFullName, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    226                  "cchFileName (%d) >= cchFullName (%d)",
    227                  pszFileName, pszFullName, cchFullName, cchFileName, cchFullName));
    228         *pszFullName = '\0';
    229         return FALSE;
    230     }
    231     strcpy(pszFullName, pszFileName);
    232     if (psz == NULL)
    233         strcpy(pszFullName + cchFileName - 4, ".DLL");
    234 
    235 
    236     /** @sketch
    237      * Allocate memory for local variables.
    238      */
    239     plv = (struct localvars *)malloc(sizeof(*plv));
    240     if (!plv)
    241     {
    242         dassert(plv, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    243                 "malloc failed allocating %d bytes of memory for local variables.",
    244                 pszFileName, pszFullName, cchFullName, sizeof(*plv)));
    245         return FALSE;
    246     }
    247 
    248 
    249     /** @sketch
    250      * Loop thru the paths and pathlists searching them for the filename.
    251      */
    252     for (iPath = FINDDLL_FIRST; iPath <= FINDDLL_LAST; iPath++)
    253     {
    254         APIRET          rc;             /* Returncode from OS/2 APIs. */
    255         const char  *   pszPath;        /* Pointer to the path being examined. */
    256 
    257         /** @sketch
    258          * Get the path/dir to examin. (This is determined by the value if iPath.)
    259          */
    260         switch (iPath)
    261         {
    262             case FINDDLL_EXECUTABLEDIR:
    263                 if (pszAltPath)
    264                     pszPath = strcpy(plv->szPath, pszAltPath);
    265                 else
    266                 {
    267                     /* ASSUMES: getFullPath allways returns a fully qualified
    268                      *      path, ie. with at least one backslash. and that all
    269                      *      slashes are backslashes!
    270                      */
    271                     if (!WinExe) continue;
    272                     pszPath = strcpy(plv->szPath, WinExe->getFullPath());
    273                 }
    274                 psz = strrchr(plv->szPath, '\\');
    275                 dassert(psz, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    276                         "WinExe->getFullPath returned a path not fully qualified: %s",
    277                         pszFileName, pszFullName, cchFullName, pszPath));
    278                 if (psz)
    279                     *psz = '\0';
    280                 else
    281                     continue;
    282                 break;
    283 
    284             case FINDDLL_CURRENTDIR:
    285                 pszPath = ".";
    286                 break;
    287 
    288             case FINDDLL_SYSTEM32DIR:
    289                 pszPath = InternalGetSystemDirectoryA();
    290                 break;
    291 
    292             case FINDDLL_SYSTEM16DIR:
    293                 #if 1
    294                 continue;               /* Skip this index */
    295                 #else
    296                 pszPath = InternalGetWindowsDirectoryA();
    297                 strcpy(plv->sz2, InternalGetWindowsDirectoryA());
    298                 strcat(plv->sz2, "\SYSTEM");
    299                 break;
    300                 #endif
    301 
    302             case FINDDLL_WINDIR:
    303                 pszPath = InternalGetWindowsDirectoryA();
    304                 break;
    305 
    306             case FINDDLL_PATH:
    307                 pszPath = getenv("PATH");
    308                 break;
    309 
    310             case FINDDLL_BEGINLIBPATH:
    311                 rc = DosQueryExtLIBPATH(plv->szPath, BEGIN_LIBPATH);
    312                 if (rc != NO_ERROR)
    313                 {
    314                     dassert(rc == NO_ERROR, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    315                              "DosQueryExtLIBPATH failed with rc=%d, iPath=%d",
    316                              pszFileName, pszFullName, cchFullName, rc, iPath));
    317                     continue;
    318                 }
    319                 pszPath = plv->szPath;
    320                 break;
    321 
    322             case FINDDLL_LIBPATH:
    323                 rc = DosQueryHeaderInfo(NULLHANDLE, 0, plv->szPath, sizeof(plv->szPath), QHINF_LIBPATH);
    324                 if (rc != NO_ERROR)
    325                 {
    326                     dassert(rc == NO_ERROR, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    327                              "DosQueryHeaderInfo failed with rc=%d, iPath=%d",
    328                              pszFileName, pszFullName, cchFullName, rc, iPath));
    329                     continue;
    330                 }
    331                 pszPath = plv->szPath;
    332                 break;
    333 
    334             case FINDDLL_ENDLIBPATH:
    335                 rc = DosQueryExtLIBPATH(plv->szPath, END_LIBPATH);
    336                 if (rc != NO_ERROR)
    337                 {
    338                     dassert(rc == NO_ERROR, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    339                              "DosQueryExtLIBPATH failed with rc=%d, iPath=%d",
    340                              pszFileName, pszFullName, cchFullName, rc, iPath));
    341                     continue;
    342                 }
    343                 pszPath = plv->szPath;
    344                 break;
    345 
    346             default: /* !internalerror! */
    347                 goto end;
    348         }
    349 
    350 
    351         /** @sketch
    352          * pszPath is now set to the pathlist to be searched.
    353          * So we'll loop thru all the paths in the list.
    354          */
    355         while (pszPath != NULL && *pszPath != '\0')
    356         {
    357             HDIR    hDir;               /* Find handle used when calling FindFirst. */
    358             ULONG   culFiles;           /* Number of files to find / found. */
    359             char *  pszNext;            /* Pointer to the next pathlist path */
    360             int     cch;                /* Length of path (including the slash after the slash is added). */
    361 
    362             /** @sketch
    363              * Find the end of the path.
    364              * Copy the path into the plv->sz buffer.
    365              * Set pszNext.
    366              */
    367             pszNext = strchr(pszPath, ';');
    368             if (pszNext != NULL)
    369             {
    370                 cch = pszNext - pszPath;
    371                 pszNext++;
    372             }
    373             else
    374                 cch = strlen(pszPath);
    375 
    376             if (cch + cchFileName + 1 >= sizeof(plv->sz)) /* assertion */
    377             {
    378                 dassert(cch + cchFileName + 1 < sizeof(plv->sz), ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    379                         "cch (%d) + cchFileName (%d) + 1 < sizeof(plv->sz) (%d) - paths too long!, iPath=%d",
    380                         pszFileName, pszFullName, cchFullName, cch, cchFileName, sizeof(plv->sz), iPath));
    381                 pszPath = pszNext;
    382                 continue;
    383             }
    384             memcpy(plv->sz, pszPath, cch); //arg! Someone made strncpy not work as supposed!
    385 
    386 
    387             /** @sketch
    388              * Add a '\\' and the filename (pszFullname) to the path;
    389              * then we'll have a fullpath.
    390              */
    391             plv->sz[cch++] = '\\';
    392             strcpy(&plv->sz[cch], pszFullName);
    393 
    394 
    395             /** @sketch
    396              *  Use DosFindFirst to check if the file exists.
    397              *  IF the file exists THEN
    398              *      Query Fullpath using OS/2 API.
    399              *      IF unsuccessful THEN return relative name.
    400              *          Check that the fullname buffer is large enough.
    401              *          Copy the filename found to the fullname buffer.
    402              *      ENDIF
    403              *      IF successful THEN uppercase the fullname buffer.
    404              *      goto end
    405              *  ENDIF
    406              */
    407             hDir = HDIR_CREATE;
    408             culFiles = 1;
    409             rc = DosFindFirst(plv->sz, &hDir, FILE_NORMAL,
    410                               &plv->findbuf3, sizeof(plv->findbuf3),
    411                               &culFiles, FIL_STANDARD);
    412             DosFindClose(hDir);
    413             if (culFiles >= 1 && rc == NO_ERROR)
    414             {
    415                 /* Return full path - we'll currently return a relative path. */
    416                 rc = DosQueryPathInfo(plv->sz, FIL_QUERYFULLNAME, pszFullName, cchFullName);
    417                 fRet = rc == NO_ERROR;
    418                 if (!fRet)
    419                 {
    420                     /* Return a relative path - probably better that failing... */
    421                     dassert(rc == NO_ERROR, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    422                             "rc = %d",
    423                             pszFileName, pszFullName, cchFullName, rc));
    424 
    425                     if (cch + cchFileName + 1 <= cchFullName)
    426                     {
    427                         strcpy(pszFullName, plv->sz);
    428                         strcpy(pszFullName + cch, plv->findbuf3.achName);
    429                         fRet = TRUE;
    430                     }
    431                     else
    432                     {
    433                         dassert(cch + cchFileName + 1 > cchFullName, ("KERNEL32:Win32ImageBase::findDll(%s, 0x%08x, %d): "
    434                                 "cch (%d) + cchFileName (%d) + 1 < cchFullName (%d); %s",
    435                                 pszFileName, pszFullName, cchFullName, cch, cchFileName, cchFullName, plv->sz));
    436                     }
    437                 }
    438                 if (fRet) strupr(pszFullName);
    439                 goto end;
    440             }
    441 
    442             pszPath = pszNext;
    443         }
    444     } /* for iPath */
    445 
    446 
    447 end:
    448     /*
    449      * Cleanup: free local variables.
    450      */
    451     free(plv);
    452     return fRet;
    453 }
    454 
    455 
    456 //******************************************************************************
    457 //******************************************************************************
    458 /**
    459  * Checks if a file is a PE executable image valid to be executed on this machine.
    460  * @returns   FALSE if not PE image.
    461  *            > 0 if valid PE image.
    462  *                1 DLL
    463  *                2 EXE
    464  * @param     szFilename    Pointer to filename
    465  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
    466  * @remark    Should not call findDll!
    467  */
     134//******************************************************************************
     135//******************************************************************************
     136BOOL Win32ImageBase::findDll(const char *szFileName, char *szFullName,
     137                             int cchFullFileName, const char *pszAltPath)
     138{
     139 char   modname[CCHMAXPATH];
     140 HFILE  dllfile = NULL;
     141 char  *imagepath;
     142
     143  strcpy(szFullName, szFileName);
     144  strupr(szFullName);
     145  if(!strchr(szFullName, (int)'.')) {
     146        strcat(szFullName,".DLL");
     147  }
     148
     149  //search order:
     150  //1) exe dir
     151  //2) current dir
     152  //3) windows system dir (kernel32 path)
     153  //4) windows dir
     154  //5) path
     155  if(WinExe) {
     156        strcpy(modname, WinExe->getFullPath());
     157        //remove file name from full path
     158        imagepath = modname + strlen(modname) - 1;
     159        while(*imagepath != '\\') imagepath--;
     160        imagepath[1] = 0;
     161        strcat(modname, szFullName);
     162        dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
     163  }
     164  if(dllfile == NULL) {
     165        strcpy(modname, szFullName);
     166        dllfile = OSLibDosOpen(szFullName, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
     167        if(dllfile == NULL) {
     168                strcpy(modname, InternalGetSystemDirectoryA());
     169                strcat(modname, "\\");
     170                strcat(modname, szFullName);
     171                dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
     172                if(dllfile == NULL) {
     173                        strcpy(modname, InternalGetWindowsDirectoryA());
     174                        strcat(modname, "\\");
     175                        strcat(modname, szFullName);
     176                        dllfile = OSLibDosOpen(modname, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
     177                        if(dllfile == NULL) {
     178                                if(OSLibDosSearchPath(OSLIB_SEARCHENV, "PATH", szFullName, modname, sizeof(modname)) == 0) {
     179                                        return FALSE;
     180                                }
     181                        }
     182                }
     183        }
     184  }
     185  strcpy(szFullName, modname);
     186  if(dllfile) OSLibDosClose(dllfile);
     187  return TRUE;
     188}
     189//******************************************************************************
     190//******************************************************************************
    468191BOOL Win32ImageBase::isPEImage(char *szFileName)
    469192{
     
    486209        return FALSE;
    487210  }
    488 
    489211  rc = DosOpen(filename,                       /* File path name */
    490212               &win32handle,                   /* File handle */
     
    550272  }
    551273  DosClose(win32handle);
    552   return (fh.Characteristics & IMAGE_FILE_DLL ? 1 : 2);
     274  return(TRUE);
    553275
    554276failure:
Note: See TracChangeset for help on using the changeset viewer.