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

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

general: Corrected spelling of my name.

File size: 4.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
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}
40
41static BOOL walkModules(QSPTRREC *pPtrRec, USHORT hmteStart,
42 PCSZ pszModname, PHMODULE pHmod)
43{
44 QSLREC *pLibRec = pPtrRec->pLibRec;
45
46 while (pLibRec)
47 {
48 // It happens that for some modules ctObj is > 0 but pObjInfo is
49 // NULL and pNextRec points right to the object table instead of the
50 // next record. This seems to be an OS/2 FP13 bug. Here is the solution
51 // from winimagepe2lx.cpp. We need it too because of pNextRec.
52 if (pLibRec->ctObj > 0 && pLibRec->pObjInfo == NULL)
53 {
54 pLibRec->pObjInfo = (QSLOBJREC *)
55 ((char*) pLibRec
56 + ((sizeof(QSLREC) /* size of the lib record */
57 + pLibRec->ctImpMod * sizeof(USHORT) /* size of the array of imported modules */
58 + strlen((char*)pLibRec->pName) + 1 /* size of the filename */
59 + 3) & ~3)); /* the size is align on 4 bytes boundrary */
60 pLibRec->pNextRec = (PVOID *)((char *)pLibRec->pObjInfo
61 + sizeof(QSLOBJREC) * pLibRec->ctObj);
62 }
63 if (pLibRec->hmte == hmteStart)
64 {
65 if (matchModuleName((PCSZ)pLibRec->pName, pszModname))
66 {
67 *pHmod = pLibRec->hmte;
68 return TRUE;
69 }
70 // mark as already walked
71 pLibRec->hmte = NULLHANDLE;
72 // walk through imported modules of this module
73 USHORT *pImpMods = (USHORT *)(((ULONG) pLibRec) + sizeof(*pLibRec));
74 for (ULONG i = 0; i < pLibRec->ctImpMod; ++i) {
75 if (walkModules(pPtrRec, pImpMods[i], pszModname, pHmod))
76 return TRUE;
77 }
78
79 // break the loop since we already walked the module in question
80 break;
81 }
82 pLibRec = (QSLREC *)pLibRec->pNextRec;
83 }
84
85 return FALSE;
86}
87
88APIRET WIN32API DosQueryModuleHandleStrict(PCSZ pszModname, PHMODULE pHmod)
89{
90 PPIB ppib;
91 APIRET arc = DosGetInfoBlocks(NULL, &ppib);
92 if (arc != NO_ERROR)
93 return arc;
94
95 *pHmod = NULLHANDLE;
96
97 // In LIBPATHSTRICT=T mode, there may be more than one module with the
98 // given name loaded into the memory. For this reason, when looking for a
99 // module by its basename, we first walk the modules belonging to the
100 // current process (which is in effect of LIBPATHSTRICT=T) to pick up the
101 // ones loaded due to this effect.
102 char *buf = (char *)malloc(64 * 1024);
103 arc = DosQuerySysState(QS_PROCESS | QS_MTE, QS_MTE,
104 ppib->pib_ulpid, 0, buf, 64 * 1024);
105 if (arc != NO_ERROR)
106 {
107 free(buf);
108 return arc;
109 }
110
111 QSPTRREC *pPtrRec = (QSPTRREC *)buf;
112 QSPREC *pProcRec = pPtrRec->pProcRec;
113
114 // first walk the EXE's imported modules
115 if (!walkModules(pPtrRec, pProcRec->hMte, pszModname, pHmod))
116 {
117 arc = ERROR_MOD_NOT_FOUND;
118
119 // next, walk the modules loaded by the process
120 for (USHORT i = 0; i < pProcRec->cLib; ++i)
121 {
122 USHORT hmte = pProcRec->pLibRec[i];
123 if (walkModules(pPtrRec, hmte, pszModname, pHmod))
124 {
125 arc = NO_ERROR;
126 break;
127 }
128 }
129 if (arc != NO_ERROR)
130 {
131 // last chance: fallback to DosQueryModuleHandle
132 arc = DosQueryModuleHandle(pszModname, pHmod);
133 }
134 }
135
136 free(buf);
137 return arc;
138}
Note: See TracBrowser for help on using the repository browser.