| 1 | /* $Id: windlllx.cpp,v 1.9 2000-03-09 19:03:21 sandervl Exp $ */ | 
|---|
| 2 |  | 
|---|
| 3 | /* | 
|---|
| 4 | * Win32 LX Dll class (compiled in OS/2 using Odin32 api) | 
|---|
| 5 | * | 
|---|
| 6 | * Copyright 1999-2000 Sander van Leeuwen (sandervl@xs4all.nl) | 
|---|
| 7 | * | 
|---|
| 8 | * TODO: Unloading of dlls probably needs to be fixed due to OS/2 bug | 
|---|
| 9 | *       (wrong unload order of dlls) | 
|---|
| 10 | * | 
|---|
| 11 | * Project Odin Software License can be found in LICENSE.TXT | 
|---|
| 12 | * | 
|---|
| 13 | */ | 
|---|
| 14 | #define INCL_DOSFILEMGR          /* File Manager values      */ | 
|---|
| 15 | #define INCL_DOSERRORS           /* DOS Error values         */ | 
|---|
| 16 | #define INCL_DOSPROCESS          /* DOS Process values       */ | 
|---|
| 17 | #define INCL_DOSMODULEMGR | 
|---|
| 18 | #define INCL_DOSMISC             /* DOS Miscellanous values  */ | 
|---|
| 19 | #define INCL_WIN | 
|---|
| 20 | #include <os2wrap.h>    //Odin32 OS/2 api wrappers | 
|---|
| 21 | #include <os2newapi.h> | 
|---|
| 22 | #include <stdio.h> | 
|---|
| 23 | #include <string.h> | 
|---|
| 24 | #include <stdlib.h> | 
|---|
| 25 | #include <iostream.h> | 
|---|
| 26 | #include <fstream.h> | 
|---|
| 27 | #include <misc.h> | 
|---|
| 28 | #include <win32type.h> | 
|---|
| 29 | #include <windllbase.h> | 
|---|
| 30 | #include <windlllx.h> | 
|---|
| 31 | #include "winexepe2lx.h" | 
|---|
| 32 | #include <odinlx.h> | 
|---|
| 33 | #include "oslibmisc.h" | 
|---|
| 34 |  | 
|---|
| 35 | #include <exe386.h> | 
|---|
| 36 |  | 
|---|
| 37 | #define DBG_LOCALLOG    DBG_windlllx | 
|---|
| 38 | #include "dbglocal.h" | 
|---|
| 39 |  | 
|---|
| 40 | //****************************************************************************** | 
|---|
| 41 | //Create LX Dll object and send process attach message | 
|---|
| 42 | //System dlls set EntryPoint to 0 | 
|---|
| 43 | //Returns: Odin32 module handle | 
|---|
| 44 | //****************************************************************************** | 
|---|
| 45 | DWORD WIN32API RegisterLxDll(HINSTANCE hInstance, WIN32DLLENTRY EntryPoint, | 
|---|
| 46 | PVOID pResData) | 
|---|
| 47 | { | 
|---|
| 48 | Win32LxDll *windll; | 
|---|
| 49 | Win32DllBase *windlldep; | 
|---|
| 50 |  | 
|---|
| 51 | windll = (Win32LxDll *)Win32DllBase::findModule(hInstance); | 
|---|
| 52 | if(windll) { | 
|---|
| 53 | char *name = OSLibGetDllName(hInstance); | 
|---|
| 54 | dprintf(("RegisterLxDll: Register existing dll %x %s", hInstance, name)); | 
|---|
| 55 | return FALSE; | 
|---|
| 56 | } | 
|---|
| 57 | windll = new Win32LxDll(hInstance, EntryPoint, pResData); | 
|---|
| 58 | if(windll == NULL) { | 
|---|
| 59 | dprintf(("RegisterLxDll: windll == NULL!!!")); | 
|---|
| 60 | return FALSE; | 
|---|
| 61 | } | 
|---|
| 62 | if(fPe2Lx) { | 
|---|
| 63 | windll->AddRef(); | 
|---|
| 64 |  | 
|---|
| 65 | if(windll->attachProcess() == 0) | 
|---|
| 66 | return 0; | 
|---|
| 67 |  | 
|---|
| 68 | return windll->getInstanceHandle(); | 
|---|
| 69 | } | 
|---|
| 70 | IMAGE_DOS_HEADER doshdr; | 
|---|
| 71 | struct e32_exe   lxhdr; | 
|---|
| 72 | ULONG            offset; | 
|---|
| 73 | char             modulename[CCHMAXPATH]; | 
|---|
| 74 | char             modsize; | 
|---|
| 75 | APIRET           rc; | 
|---|
| 76 | int              i; | 
|---|
| 77 |  | 
|---|
| 78 | //SvL: This code reads the import name table of the dll to get the dependencies | 
|---|
| 79 | //     on other dlls. | 
|---|
| 80 | //DosQueryHeaderInfo is an undocumented api, but works very well. | 
|---|
| 81 | //(no need to save FS here as we'll return to OS/2 immediately) | 
|---|
| 82 | rc = DosQueryHeaderInfo(hInstance, 0, &doshdr, sizeof(IMAGE_DOS_HEADER), QHINF_READFILE); | 
|---|
| 83 | if(rc) { | 
|---|
| 84 | goto hdrerror; | 
|---|
| 85 | } | 
|---|
| 86 | rc = DosQueryHeaderInfo(hInstance, doshdr.e_lfanew, &lxhdr, sizeof(e32_exe), QHINF_READFILE); | 
|---|
| 87 | if(rc) { | 
|---|
| 88 | goto hdrerror; | 
|---|
| 89 | } | 
|---|
| 90 | offset = doshdr.e_lfanew + lxhdr.e32_impmod; | 
|---|
| 91 | for(i=0;i<lxhdr.e32_impmodcnt;i++) { | 
|---|
| 92 | rc = DosQueryHeaderInfo(hInstance, offset, &modsize, 1, QHINF_READFILE); | 
|---|
| 93 | if(rc) { | 
|---|
| 94 | goto hdrerror; | 
|---|
| 95 | } | 
|---|
| 96 | rc = DosQueryHeaderInfo(hInstance, offset+1, &modulename, min(modsize, sizeof(modulename)), QHINF_READFILE); | 
|---|
| 97 | if(rc) { | 
|---|
| 98 | goto hdrerror; | 
|---|
| 99 | } | 
|---|
| 100 | modulename[modsize] = 0; | 
|---|
| 101 | windlldep = Win32DllBase::findModule(modulename, TRUE); | 
|---|
| 102 | if(windlldep) { | 
|---|
| 103 | dprintf(("RegisterLxDll: Add dependency %s -> %s", windll->getModuleName(), modulename)); | 
|---|
| 104 | windll->addDependency(windlldep); | 
|---|
| 105 | } | 
|---|
| 106 | offset += modsize + 1; | 
|---|
| 107 | } | 
|---|
| 108 | return windll->getInstanceHandle(); | 
|---|
| 109 |  | 
|---|
| 110 | hdrerror: | 
|---|
| 111 | dprintf(("DosQueryHeaderInfo returned %d", rc)); | 
|---|
| 112 | return windll->getInstanceHandle(); | 
|---|
| 113 | } | 
|---|
| 114 | //****************************************************************************** | 
|---|
| 115 | //Destroy LX Dll object | 
|---|
| 116 | //****************************************************************************** | 
|---|
| 117 | BOOL WIN32API UnregisterLxDll(HINSTANCE hInstance) | 
|---|
| 118 | { | 
|---|
| 119 | Win32LxDll *windll; | 
|---|
| 120 |  | 
|---|
| 121 | //Don't proceed for pe2lx/win32k (os/2 dll unload dependency bug) | 
|---|
| 122 | //Don't do it either after ExitProcess has been called | 
|---|
| 123 | if(fPe2Lx || WinExe == NULL) | 
|---|
| 124 | return TRUE; | 
|---|
| 125 |  | 
|---|
| 126 | windll = (Win32LxDll *)Win32DllBase::findModule(hInstance); | 
|---|
| 127 | if(!windll) { | 
|---|
| 128 | dprintf(("UnregisterLxDll: Can't find dll with handle %x (already deleted)", hInstance)); | 
|---|
| 129 | return TRUE; //already deleted by Win32LxDll::Release | 
|---|
| 130 | } | 
|---|
| 131 | dprintf(("UnregisterLxDll %s", windll->getModuleName())); | 
|---|
| 132 | //This can only happen for LX dependencies (i.e. wininet loads wsock32) | 
|---|
| 133 | delete windll; | 
|---|
| 134 | return TRUE; | 
|---|
| 135 | } | 
|---|
| 136 | //****************************************************************************** | 
|---|
| 137 | //****************************************************************************** | 
|---|
| 138 | Win32LxDll::Win32LxDll(HINSTANCE hInstance, WIN32DLLENTRY EntryPoint, PVOID pResData) | 
|---|
| 139 | : Win32ImageBase(hInstance), | 
|---|
| 140 | Win32LxImage(hInstance, pResData), | 
|---|
| 141 | Win32DllBase(hInstance, EntryPoint) | 
|---|
| 142 | { | 
|---|
| 143 | if(EntryPoint == NULL) { | 
|---|
| 144 | fSkipEntryCalls    = TRUE; | 
|---|
| 145 | fAttachedToProcess = TRUE; | 
|---|
| 146 | } | 
|---|
| 147 | } | 
|---|
| 148 | //****************************************************************************** | 
|---|
| 149 | //****************************************************************************** | 
|---|
| 150 | Win32LxDll::~Win32LxDll() | 
|---|
| 151 | { | 
|---|
| 152 | } | 
|---|
| 153 | //****************************************************************************** | 
|---|
| 154 | //Load it again so OS/2 takes care of the reference count (to make sure | 
|---|
| 155 | //a dll isn't unloaded when the win32 app still needs it) | 
|---|
| 156 | //****************************************************************************** | 
|---|
| 157 | void Win32LxDll::loadLibrary() | 
|---|
| 158 | { | 
|---|
| 159 | char   szModuleFailure[CCHMAXPATH] = ""; | 
|---|
| 160 | ULONG  hInstanceNewDll; | 
|---|
| 161 | APIRET rc; | 
|---|
| 162 |  | 
|---|
| 163 | if(fLoadLibrary) { | 
|---|
| 164 | DebugInt3(); | 
|---|
| 165 | return; | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | dprintf(("Win32LxDll::loadLibrary %s", getModuleName())); | 
|---|
| 169 | rc = DosLoadModule(szModuleFailure, sizeof(szModuleFailure), getFullPath(), (HMODULE *)&hInstanceNewDll); | 
|---|
| 170 | if(rc) { | 
|---|
| 171 | dprintf(("DosLoadModule returned %X for %s\n", rc, szModuleFailure)); | 
|---|
| 172 | DebugInt3(); //should NEVER happen | 
|---|
| 173 | return; | 
|---|
| 174 | } | 
|---|
| 175 | //only do this once, so set the fLoadLibrary flag to true | 
|---|
| 176 | setLoadLibrary(); | 
|---|
| 177 | } | 
|---|
| 178 | //****************************************************************************** | 
|---|
| 179 | //****************************************************************************** | 
|---|
| 180 | #ifdef DEBUG | 
|---|
| 181 | ULONG Win32LxDll::AddRef(char *parentname) | 
|---|
| 182 | #else | 
|---|
| 183 | ULONG Win32LxDll::AddRef() | 
|---|
| 184 | #endif | 
|---|
| 185 | { | 
|---|
| 186 | Win32DllBase *dll; | 
|---|
| 187 | QueueItem    *item; | 
|---|
| 188 | ULONG         ret; | 
|---|
| 189 |  | 
|---|
| 190 | #ifdef DEBUG | 
|---|
| 191 | ret = Win32DllBase::AddRef(parentname); | 
|---|
| 192 | #else | 
|---|
| 193 | ret = Win32DllBase::AddRef(); | 
|---|
| 194 | #endif | 
|---|
| 195 |  | 
|---|
| 196 | if(fPe2Lx) | 
|---|
| 197 | return ret; | 
|---|
| 198 |  | 
|---|
| 199 | if(referenced == 1) | 
|---|
| 200 | { | 
|---|
| 201 | item = loadedDlls.Head(); | 
|---|
| 202 | while(item) { | 
|---|
| 203 | dll = (Win32DllBase *)loadedDlls.getItem(item); | 
|---|
| 204 | if(dll == NULL) { | 
|---|
| 205 | dprintf(("ERROR: Win32DllBase::AddRef: dll item == NULL!!")); | 
|---|
| 206 | DebugInt3(); | 
|---|
| 207 | return -1; | 
|---|
| 208 | } | 
|---|
| 209 | #ifdef DEBUG | 
|---|
| 210 | dll->AddRef(getModuleName()); | 
|---|
| 211 | #else | 
|---|
| 212 | dll->AddRef(); | 
|---|
| 213 | #endif | 
|---|
| 214 | item = loadedDlls.getNext(item); | 
|---|
| 215 | } | 
|---|
| 216 | if(attachProcess() == 0) | 
|---|
| 217 | return 0; | 
|---|
| 218 | } | 
|---|
| 219 | return ret; | 
|---|
| 220 | } | 
|---|
| 221 | //****************************************************************************** | 
|---|
| 222 | //****************************************************************************** | 
|---|
| 223 | ULONG Win32LxDll::Release() | 
|---|
| 224 | { | 
|---|
| 225 | HINSTANCE hinst; | 
|---|
| 226 | ULONG     ret; | 
|---|
| 227 | APIRET    rc; | 
|---|
| 228 | BOOL      fLoadLib = fLoadLibrary; | 
|---|
| 229 |  | 
|---|
| 230 | if(fDisableUnload) {//only set for kernel32.dll | 
|---|
| 231 | fLoadLib = FALSE; | 
|---|
| 232 | } | 
|---|
| 233 | hinst = hinstance; | 
|---|
| 234 | ret = Win32DllBase::Release(); | 
|---|
| 235 | if(ret == 0 && fLoadLib) { | 
|---|
| 236 | //DosFreeModule sends a termination message to the dll. | 
|---|
| 237 | //The LX dll informs us when it's removed (UnregisterDll call) | 
|---|
| 238 | rc = DosFreeModule(hinst); | 
|---|
| 239 | if(rc) { | 
|---|
| 240 | dprintf(("Win32LxDll::Release: DosFreeModule %x returned %d", hinst, rc)); | 
|---|
| 241 | } | 
|---|
| 242 | } | 
|---|
| 243 | return(ret); | 
|---|
| 244 | } | 
|---|
| 245 | //****************************************************************************** | 
|---|
| 246 | //****************************************************************************** | 
|---|
| 247 | BOOL Win32LxDll::isLxDll() | 
|---|
| 248 | { | 
|---|
| 249 | return TRUE; | 
|---|
| 250 | } | 
|---|
| 251 | //****************************************************************************** | 
|---|
| 252 | //****************************************************************************** | 
|---|