source: trunk/src/odincrt/dos.cpp

Last change on this file was 21972, checked in by dmik, 14 years ago

Add extra logging to DosQueryModuleHandleStrict().

File size: 5.4 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 Dmitriy 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
21//#define EXTRALOG
22
23#undef dprintf
24#ifdef EXTRALOG
25
26#include <stdio.h>
27#include <stdarg.h>
28
29void dbg(const char *fmt, ...)
30{
31 static FILE *f = 0;
32 if (!f)
33 {
34 f = fopen ("/odin32_odincrt_dos.log", "w+");
35 setbuf (f, NULL);
36 }
37 if (f)
38 {
39 va_list args;
40 va_start (args, fmt);
41 vfprintf (f, fmt, args);
42 fprintf (f, "\n");
43 va_end (args);
44 }
45}
46
47#define dprintf(a) do { dbg a; } while(0)
48
49#else // EXTRALOG
50#define dprintf(a) do {} while(0)
51#endif // EXTRALOG
52
53static BOOL matchModuleName(PCSZ pszFullModname, PCSZ pszModname)
54{
55 // the staright case:
56 if (stricmp(pszFullModname, pszModname) == 0)
57 return TRUE;
58
59 char fullFname[_MAX_FNAME];
60 char fullExt[_MAX_EXT];
61 _splitpath((char *)pszFullModname, NULL, NULL, fullFname, fullExt);
62
63 char modFname[_MAX_FNAME];
64 char modExt[_MAX_EXT];
65 _splitpath((char *)pszModname, NULL, NULL, modFname, modExt);
66
67 if (*modExt == 0)
68 strcpy(modExt, ".DLL");
69
70 return stricmp(fullFname, modFname) == 0 && stricmp(fullExt, modExt) == 0;
71}
72
73static BOOL walkModules(QSPTRREC *pPtrRec, USHORT hmteStart,
74 PCSZ pszModname, PHMODULE pHmod)
75{
76 QSLREC *pLibRec = pPtrRec->pLibRec;
77
78 while (pLibRec)
79 {
80 // It happens that for some modules ctObj is > 0 but pObjInfo is
81 // NULL and pNextRec points right to the object table instead of the
82 // next record. This seems to be an OS/2 FP13 bug. Here is the solution
83 // from winimagepe2lx.cpp. We need it too because of pNextRec.
84 if (pLibRec->ctObj > 0 && pLibRec->pObjInfo == NULL)
85 {
86 pLibRec->pObjInfo = (QSLOBJREC *)
87 ((char*) pLibRec
88 + ((sizeof(QSLREC) /* size of the lib record */
89 + pLibRec->ctImpMod * sizeof(USHORT) /* size of the array of imported modules */
90 + strlen((char*)pLibRec->pName) + 1 /* size of the filename */
91 + 3) & ~3)); /* the size is align on 4 bytes boundrary */
92 pLibRec->pNextRec = (PVOID *)((char *)pLibRec->pObjInfo
93 + sizeof(QSLOBJREC) * pLibRec->ctObj);
94 }
95 if (pLibRec->hmte == hmteStart)
96 {
97 if (matchModuleName((PCSZ)pLibRec->pName, pszModname))
98 {
99 *pHmod = pLibRec->hmte;
100 return TRUE;
101 }
102 // mark as already walked
103 pLibRec->hmte = NULLHANDLE;
104 // walk through imported modules of this module
105 USHORT *pImpMods = (USHORT *)(((ULONG) pLibRec) + sizeof(*pLibRec));
106 for (ULONG i = 0; i < pLibRec->ctImpMod; ++i) {
107 if (walkModules(pPtrRec, pImpMods[i], pszModname, pHmod))
108 return TRUE;
109 }
110
111 // break the loop since we already walked the module in question
112 break;
113 }
114 pLibRec = (QSLREC *)pLibRec->pNextRec;
115 }
116
117 return FALSE;
118}
119
120APIRET WIN32API DosQueryModuleHandleStrict(PCSZ pszModname, PHMODULE pHmod)
121{
122 dprintf(("DosQueryModuleHandleStrict: BEGIN (%s, %p)", pszModname, pHmod));
123
124 PPIB ppib;
125 APIRET arc = DosGetInfoBlocks(NULL, &ppib);
126 if (arc != NO_ERROR)
127 {
128 dprintf(("DosQueryModuleHandleStrict: DosGetInfoBlocks failed with %d", arc));
129 return arc;
130 }
131
132 *pHmod = NULLHANDLE;
133
134 // In LIBPATHSTRICT=T mode, there may be more than one module with the
135 // given name loaded into the memory. For this reason, when looking for a
136 // module by its basename, we first walk the modules belonging to the
137 // current process (which is in effect of LIBPATHSTRICT=T) to pick up the
138 // ones loaded due to this effect.
139 char *buf = (char *)malloc(64 * 1024);
140 if (buf == NULL)
141 {
142 dprintf(("DosQueryModuleHandleStrict: not enough memory"));
143 return ERROR_NOT_ENOUGH_MEMORY;
144 }
145
146 arc = DosQuerySysState(QS_PROCESS | QS_MTE, QS_MTE,
147 ppib->pib_ulpid, 0, buf, 64 * 1024);
148 if (arc != NO_ERROR)
149 {
150 dprintf(("DosQueryModuleHandleStrict: DosQuerySysState failed with %d", arc));
151 free(buf);
152 return arc;
153 }
154
155 QSPTRREC *pPtrRec = (QSPTRREC *)buf;
156 QSPREC *pProcRec = pPtrRec->pProcRec;
157
158 // first walk the EXE's imported modules
159 if (!walkModules(pPtrRec, pProcRec->hMte, pszModname, pHmod))
160 {
161 arc = ERROR_MOD_NOT_FOUND;
162
163 // next, walk the modules loaded by the process
164 for (USHORT i = 0; i < pProcRec->cLib; ++i)
165 {
166 USHORT hmte = pProcRec->pLibRec[i];
167 if (walkModules(pPtrRec, hmte, pszModname, pHmod))
168 {
169 dprintf(("DosQueryModuleHandleStrict: found pHmod %x", *pHmod));
170 arc = NO_ERROR;
171 break;
172 }
173 }
174 if (arc != NO_ERROR)
175 {
176 // last chance: fallback to DosQueryModuleHandle
177 arc = DosQueryModuleHandle(pszModname, pHmod);
178 }
179 }
180
181 dprintf(("DosQueryModuleHandleStrict: END (%d)", arc));
182 free(buf);
183 return arc;
184}
Note: See TracBrowser for help on using the repository browser.