source: trunk/src/odincrt/dos.cpp@ 21425

Last change on this file since 21425 was 21425, checked in by dmik, 15 years ago

Added DosQueryModuleHandleStrict() that is able to find modules loaded when LIBPATHSTRICT=T is in effect.

File size: 4.1 KB
Line 
1/*
2 * Project Odin Software License can be found in LICENSE.TXT
3 *
4 * OS/2 Dos API extensions
5 *
6 * Copyright 2010 Dmitry A. Kuminov
7 *
8 */
9
10/* Include files */
11#define INCL_DOSMODULEMGR
12#define INCL_DOSPROCESS
13#define INCL_DOSPROFILE
14#define INCL_DOSERRORS
15#include <os2wrap.h> //Odin32 OS/2 api wrappers
16#include <stdlib.h>
17#include <string.h>
18
19#include "odincrt.h"
20
21static BOOL matchModuleName(PCSZ pszFullModname, PCSZ pszModname)
22{
23 // the staright case:
24 if (stricmp(pszFullModname, pszModname) == 0)
25 return TRUE;
26
27 char fullFname[_MAX_FNAME];
28 char fullExt[_MAX_EXT];
29 _splitpath((char *)pszFullModname, NULL, NULL, fullFname, fullExt);
30
31 char modFname[_MAX_FNAME];
32 char modExt[_MAX_EXT];
33 _splitpath((char *)pszModname, NULL, NULL, modFname, modExt);
34
35 if (*modExt == 0)
36 strcpy(modExt, ".DLL");
37
38 return stricmp(fullFname, modFname) == 0 && stricmp(fullExt, modExt) == 0;
39}
40static BOOL walkModules(QSPTRREC *pPtrRec, USHORT hmteStart,
41 PCSZ pszModname, PHMODULE pHmod)
42{
43 QSLREC *pLibRec = pPtrRec->pLibRec;
44
45 while (pLibRec) {
46 // It happens that for some modules ctObj is > 0 but pbjInfo is
47 // NULL. This seems to be an OS/2 FP13 bug. Here is the solution from
48 // winimagepe2lx.cpp. We need it too because of pNextRec.
49 if (pLibRec->ctObj > 0 && pLibRec->pObjInfo == NULL)
50 {
51 pLibRec->pObjInfo = (QSLOBJREC *)
52 ((char*) pLibRec
53 + ((sizeof(QSLREC) /* size of the lib record */
54 + pLibRec->ctImpMod * sizeof(USHORT) /* size of the array of imported modules */
55 + strlen((char*)pLibRec->pName) + 1 /* size of the filename */
56 + 3) & ~3)); /* the size is align on 4 bytes boundrary */
57 pLibRec->pNextRec = (PVOID *)((char *)pLibRec->pObjInfo
58 + sizeof(QSLOBJREC) * pLibRec->ctObj);
59 }
60 if (pLibRec->hmte == hmteStart)
61 {
62 if (matchModuleName((PCSZ)pLibRec->pName, pszModname))
63 {
64 *pHmod = pLibRec->hmte;
65 return TRUE;
66 }
67 // mark as already walked
68 pLibRec->hmte = NULLHANDLE;
69 // walk through imported modules of this module
70 USHORT *pImpMods = (USHORT *)(((ULONG) pLibRec) + sizeof(*pLibRec));
71 for (ULONG i = 0; i < pLibRec->ctImpMod; ++i) {
72 if (walkModules(pPtrRec, pImpMods[i], pszModname, pHmod))
73 return TRUE;
74 }
75 }
76 pLibRec = (QSLREC *)pLibRec->pNextRec;
77 }
78
79 return FALSE;
80}
81
82APIRET WIN32API DosQueryModuleHandleStrict(PCSZ pszModname, PHMODULE pHmod)
83{
84 PPIB ppib;
85 APIRET arc = DosGetInfoBlocks(NULL, &ppib);
86 if (arc != NO_ERROR)
87 return arc;
88
89 *pHmod = NULLHANDLE;
90
91 // In LIBPATHSTRICT=T mode, there mey be more than one module with the
92 // given name loaded into the memory. For this reason, when looking for a
93 // module by its basename, we first walk the modules belonging to the
94 // current process (which is in effect of LIBPATHSTRICT=T) to pick up the
95 // ones loaded due to this effect.
96 char *buf = (char *)malloc(64 * 1024);
97 arc = DosQuerySysState(QS_PROCESS | QS_MTE, QS_MTE,
98 ppib->pib_ulpid, 0, buf, 64 * 1024);
99 if (arc != NO_ERROR)
100 {
101 free(buf);
102 return arc;
103 }
104
105 QSPTRREC *pPtrRec = (QSPTRREC *)buf;
106 QSPREC *pProcRec = pPtrRec->pProcRec;
107 if (!walkModules(pPtrRec, pProcRec->hMte, pszModname, pHmod))
108 {
109 arc = ERROR_INVALID_NAME;
110 for (USHORT i = 0; i < pProcRec->cLib; ++i) {
111 USHORT hmte = pProcRec->pLibRec[i];
112 if (walkModules(pPtrRec, hmte, pszModname, pHmod))
113 {
114 arc = NO_ERROR;
115 break;
116 }
117 }
118 if (arc != NO_ERROR)
119 {
120 // last chance: fallback to DosQueryModuleHandle
121 arc = DosQueryModuleHandle(pszModname, pHmod);
122 }
123 }
124
125 free(buf);
126 return arc;
127}
Note: See TracBrowser for help on using the repository browser.