[10397] | 1 | /* $Id: windlllx.cpp,v 1.29 2004-01-15 10:39:07 sandervl Exp $ */
|
---|
[956] | 2 |
|
---|
| 3 | /*
|
---|
| 4 | * Win32 LX Dll class (compiled in OS/2 using Odin32 api)
|
---|
| 5 | *
|
---|
[3059] | 6 | * Copyright 1999-2000 Sander van Leeuwen (sandervl@xs4all.nl)
|
---|
[10397] | 7 | * Copyright 2003 Innotek Systemberatung GmbH (sandervl@innotek.de)
|
---|
[956] | 8 | *
|
---|
[6015] | 9 | * TODO: Unloading of dlls probably needs to be fixed due to OS/2 bug
|
---|
[956] | 10 | * (wrong unload order of dlls)
|
---|
| 11 | *
|
---|
| 12 | * Project Odin Software License can be found in LICENSE.TXT
|
---|
| 13 | *
|
---|
| 14 | */
|
---|
| 15 | #define INCL_DOSFILEMGR /* File Manager values */
|
---|
| 16 | #define INCL_DOSERRORS /* DOS Error values */
|
---|
| 17 | #define INCL_DOSPROCESS /* DOS Process values */
|
---|
| 18 | #define INCL_DOSMODULEMGR
|
---|
| 19 | #define INCL_DOSMISC /* DOS Miscellanous values */
|
---|
| 20 | #define INCL_WIN
|
---|
[6015] | 21 | #include <os2wrap.h> //Odin32 OS/2 api wrappers
|
---|
[3059] | 22 | #include <os2newapi.h>
|
---|
[956] | 23 | #include <stdio.h>
|
---|
| 24 | #include <string.h>
|
---|
| 25 | #include <stdlib.h>
|
---|
[21916] | 26 | #ifndef __GNUC__
|
---|
[956] | 27 | #include <iostream.h>
|
---|
| 28 | #include <fstream.h>
|
---|
[21916] | 29 | #endif
|
---|
[956] | 30 | #include <misc.h>
|
---|
| 31 | #include <win32type.h>
|
---|
[21916] | 32 | #include "windllbase.h"
|
---|
| 33 | #include "windlllx.h"
|
---|
[3059] | 34 | #include "winexepe2lx.h"
|
---|
[3375] | 35 | #include "winexepeldr.h"
|
---|
[956] | 36 | #include <odinlx.h>
|
---|
[5075] | 37 | #include <wprocess.h>
|
---|
[956] | 38 | #include "oslibmisc.h"
|
---|
[9828] | 39 | #include <custombuild.h>
|
---|
[956] | 40 |
|
---|
[3059] | 41 | #include <exe386.h>
|
---|
| 42 |
|
---|
[6015] | 43 | #define DBG_LOCALLOG DBG_windlllx
|
---|
[2802] | 44 | #include "dbglocal.h"
|
---|
| 45 |
|
---|
[9828] | 46 | /*******************************************************************************
|
---|
| 47 | * Global Variables *
|
---|
| 48 | *******************************************************************************/
|
---|
[9411] | 49 | char *lpszCustomDllName = NULL;
|
---|
[10397] | 50 | PIMAGE_FILE_HEADER lpCustomDllPEHdr = NULL;
|
---|
[6401] | 51 |
|
---|
[9828] | 52 | /**
|
---|
| 53 | * FreeLibrary callback for LX Dlls, it's call only when the library is actually
|
---|
| 54 | * being unloaded.
|
---|
| 55 | * Maintained by ODIN_SetLxDllUnLoadCallback().
|
---|
| 56 | */
|
---|
| 57 | PFNLXDLLUNLOAD pfnLxDllUnLoadCallback = NULL;
|
---|
| 58 |
|
---|
[956] | 59 | //******************************************************************************
|
---|
[6401] | 60 | //******************************************************************************
|
---|
[10397] | 61 | void WIN32API SetCustomBuildName(char *lpszName, PIMAGE_FILE_HEADER pfh)
|
---|
[6401] | 62 | {
|
---|
[9411] | 63 | lpszCustomDllName = lpszName;
|
---|
[10397] | 64 | lpCustomDllPEHdr = pfh;
|
---|
[6401] | 65 | }
|
---|
| 66 | //******************************************************************************
|
---|
[956] | 67 | //Create LX Dll object and send process attach message
|
---|
| 68 | //System dlls set EntryPoint to 0
|
---|
[3993] | 69 | //Parameters:
|
---|
[6015] | 70 | // HINSTANCE hInstance - OS/2 module handle
|
---|
[3993] | 71 | // WIN32DLLENTRY EntryPoint - Win32 dll entrypoint address
|
---|
| 72 | // PVOID pResData - pointer to win32 resource data
|
---|
| 73 | // DWORD MajorImageVersion - major image/os version (for fake win32 header)
|
---|
| 74 | // DWORD MinorImageVersion - minor image/os version (for fake win32 header)
|
---|
| 75 | // DWORD Subsystem - subsystem type (for fake win32 header)
|
---|
| 76 | // (IMAGE_SUBSYSTEM_WINDOWS_CUI/IMAGE_SUBSYSTEM_WINDOWS_GUI)
|
---|
| 77 | //
|
---|
[1423] | 78 | //Returns: Odin32 module handle
|
---|
[956] | 79 | //******************************************************************************
|
---|
[6015] | 80 | DWORD WIN32API RegisterLxDll(HINSTANCE hInstance, WIN32DLLENTRY EntryPoint,
|
---|
| 81 | PVOID pResData,
|
---|
| 82 | DWORD MajorImageVersion,
|
---|
[3993] | 83 | DWORD MinorImageVersion,
|
---|
| 84 | DWORD Subsystem)
|
---|
[6015] | 85 | {
|
---|
[3993] | 86 | APIRET rc;
|
---|
| 87 | Win32LxDll *windll;
|
---|
[3059] | 88 | Win32DllBase *windlldep;
|
---|
[3993] | 89 | char szFileName[CCHMAXPATH], szErrName[CCHMAXPATH];
|
---|
[956] | 90 |
|
---|
[6401] | 91 | if(!lpszCustomDllName) {
|
---|
| 92 | if(OSLibGetDllName(hInstance, szFileName, sizeof(szFileName)) == FALSE) {
|
---|
| 93 | dprintf(("ERROR: RegisterLxDll: OSLibGetDllName %x failed!!", hInstance));
|
---|
| 94 | return 0;
|
---|
| 95 | }
|
---|
| 96 | dprintf(("RegisterLxDll %x %s", hInstance, szFileName));
|
---|
| 97 | //Make sure DosLoadModule is called at least once for a dll (to make sure
|
---|
| 98 | //OS/2 doesn't unload the dll when it's still needed)
|
---|
| 99 | rc = DosLoadModule(szErrName, sizeof(szErrName), szFileName, &hInstance);
|
---|
| 100 | if(rc != 0) {
|
---|
| 101 | dprintf(("ERROR: RegisterLxDll: DosLoadModule %s failed (rc=%d)!!", szFileName, rc));
|
---|
| 102 | return 0;
|
---|
| 103 | }
|
---|
[956] | 104 | }
|
---|
[10397] | 105 | else {
|
---|
| 106 | //make sure this dll hasn't already been loaded
|
---|
| 107 | if(Win32DllBase::findModule(lpszCustomDllName) != NULL) {
|
---|
| 108 | dprintf(("ERROR: RegisterLxDll: module %s already loaded!!", lpszCustomDllName));
|
---|
| 109 | DebugInt3();
|
---|
| 110 | return 0;
|
---|
| 111 | }
|
---|
| 112 | }
|
---|
[3993] | 113 | windll = new Win32LxDll(hInstance, EntryPoint, pResData, MajorImageVersion,
|
---|
| 114 | MinorImageVersion, Subsystem);
|
---|
[956] | 115 | if(windll == NULL) {
|
---|
[6401] | 116 | dprintf(("RegisterLxDll: windll == NULL!!!"));
|
---|
| 117 | return 0;
|
---|
[956] | 118 | }
|
---|
[7075] | 119 | //clear name override in case dll init loads another dll
|
---|
| 120 | lpszCustomDllName = NULL;
|
---|
[10397] | 121 | lpCustomDllPEHdr = NULL;
|
---|
[7075] | 122 |
|
---|
[3375] | 123 | if(!fPeLoader) {
|
---|
[6401] | 124 | windll->AddRef();
|
---|
[1423] | 125 |
|
---|
[6401] | 126 | if(windll->attachProcess() == 0)
|
---|
| 127 | return 0;
|
---|
[3059] | 128 |
|
---|
[6401] | 129 | return windll->getInstanceHandle();
|
---|
[3059] | 130 | }
|
---|
| 131 | IMAGE_DOS_HEADER doshdr;
|
---|
| 132 | struct e32_exe lxhdr;
|
---|
| 133 | ULONG offset;
|
---|
| 134 | char modulename[CCHMAXPATH];
|
---|
| 135 | char modsize;
|
---|
| 136 | int i;
|
---|
| 137 |
|
---|
| 138 | //SvL: This code reads the import name table of the dll to get the dependencies
|
---|
| 139 | // on other dlls.
|
---|
| 140 | //DosQueryHeaderInfo is an undocumented api, but works very well.
|
---|
| 141 | //(no need to save FS here as we'll return to OS/2 immediately)
|
---|
| 142 | rc = DosQueryHeaderInfo(hInstance, 0, &doshdr, sizeof(IMAGE_DOS_HEADER), QHINF_READFILE);
|
---|
| 143 | if(rc) {
|
---|
[6401] | 144 | goto hdrerror;
|
---|
[3059] | 145 | }
|
---|
| 146 | rc = DosQueryHeaderInfo(hInstance, doshdr.e_lfanew, &lxhdr, sizeof(e32_exe), QHINF_READFILE);
|
---|
| 147 | if(rc) {
|
---|
[6401] | 148 | goto hdrerror;
|
---|
[3059] | 149 | }
|
---|
| 150 | offset = doshdr.e_lfanew + lxhdr.e32_impmod;
|
---|
| 151 | for(i=0;i<lxhdr.e32_impmodcnt;i++) {
|
---|
[6401] | 152 | rc = DosQueryHeaderInfo(hInstance, offset, &modsize, 1, QHINF_READFILE);
|
---|
| 153 | if(rc) {
|
---|
| 154 | goto hdrerror;
|
---|
| 155 | }
|
---|
| 156 | rc = DosQueryHeaderInfo(hInstance, offset+1, &modulename, min(modsize, sizeof(modulename)), QHINF_READFILE);
|
---|
| 157 | if(rc) {
|
---|
| 158 | goto hdrerror;
|
---|
| 159 | }
|
---|
| 160 | modulename[modsize] = 0;
|
---|
| 161 | windlldep = Win32DllBase::findModule(modulename, TRUE);
|
---|
| 162 | if(windlldep && strcmp(windlldep->getModuleName(), windll->getModuleName())) {
|
---|
| 163 | dprintf(("RegisterLxDll: Add dependency %s -> %s", windll->getModuleName(), modulename));
|
---|
| 164 | windll->addDependency(windlldep);
|
---|
| 165 | }
|
---|
| 166 | else dprintf(("HARMLESS WARNING: Can't find dll %s referenced by %s", modulename, windll->getModuleName()));
|
---|
| 167 |
|
---|
| 168 | offset += modsize + 1;
|
---|
[3059] | 169 | }
|
---|
[8462] | 170 | #ifdef HACK_NEVER_UNLOAD_LX_DLLS
|
---|
| 171 | //HACK ALERT!!
|
---|
| 172 | //This makes sure the LX dll never gets unloaded.
|
---|
| 173 | //Necessary since unloading doesn't work due to dependencies on dlls
|
---|
| 174 | //with exitlist handlers.
|
---|
| 175 | windll->AddRef();
|
---|
| 176 | #endif
|
---|
[1423] | 177 | return windll->getInstanceHandle();
|
---|
[3059] | 178 |
|
---|
| 179 | hdrerror:
|
---|
| 180 | dprintf(("DosQueryHeaderInfo returned %d", rc));
|
---|
| 181 | return windll->getInstanceHandle();
|
---|
[956] | 182 | }
|
---|
| 183 | //******************************************************************************
|
---|
| 184 | //Destroy LX Dll object
|
---|
| 185 | //******************************************************************************
|
---|
| 186 | BOOL WIN32API UnregisterLxDll(HINSTANCE hInstance)
|
---|
| 187 | {
|
---|
[3993] | 188 | Win32DllBase *windll;
|
---|
[956] | 189 |
|
---|
[3059] | 190 | //Don't proceed for pe2lx/win32k (os/2 dll unload dependency bug)
|
---|
| 191 | //Don't do it either after ExitProcess has been called
|
---|
[3375] | 192 | if(!fPeLoader || WinExe == NULL)
|
---|
[6015] | 193 | return TRUE;
|
---|
[3059] | 194 |
|
---|
[3993] | 195 | windll = Win32DllBase::findModule(hInstance);
|
---|
[956] | 196 | if(!windll) {
|
---|
[6015] | 197 | dprintf(("UnregisterLxDll: Can't find dll with handle %x (already deleted)", hInstance));
|
---|
| 198 | return TRUE; //already deleted by Win32LxDll::Release
|
---|
[956] | 199 | }
|
---|
[3059] | 200 | dprintf(("UnregisterLxDll %s", windll->getModuleName()));
|
---|
| 201 | //This can only happen for LX dependencies (i.e. wininet loads wsock32)
|
---|
[956] | 202 | delete windll;
|
---|
| 203 | return TRUE;
|
---|
| 204 | }
|
---|
| 205 | //******************************************************************************
|
---|
| 206 | //******************************************************************************
|
---|
[3993] | 207 | Win32LxDll::Win32LxDll(HINSTANCE hInstance, WIN32DLLENTRY EntryPoint, PVOID pResData,
|
---|
| 208 | DWORD MajorImageVersion, DWORD MinorImageVersion,
|
---|
[6015] | 209 | DWORD Subsystem)
|
---|
[956] | 210 | : Win32ImageBase(hInstance),
|
---|
[6015] | 211 | Win32LxImage(hInstance, pResData),
|
---|
[956] | 212 | Win32DllBase(hInstance, EntryPoint)
|
---|
| 213 | {
|
---|
[5075] | 214 | this->MajorImageVersion = MajorImageVersion;
|
---|
| 215 | this->MinorImageVersion = MinorImageVersion;
|
---|
| 216 | this->Subsystem = Subsystem;
|
---|
[6015] | 217 |
|
---|
[956] | 218 | if(EntryPoint == NULL) {
|
---|
[6015] | 219 | fSkipThreadEntryCalls = TRUE;
|
---|
| 220 | fAttachedToProcess = TRUE;
|
---|
[956] | 221 | }
|
---|
[3993] | 222 | hinstanceOS2 = hInstance;
|
---|
| 223 | //new win32 instance handle must be pointer to PE header
|
---|
| 224 | hinstance = (HINSTANCE)buildHeader(MajorImageVersion, MinorImageVersion,
|
---|
| 225 | Subsystem);
|
---|
[4433] | 226 | dprintf(("Fake PE header %x for dll %s", hinstance, getModuleName()));
|
---|
[956] | 227 | }
|
---|
| 228 | //******************************************************************************
|
---|
| 229 | //******************************************************************************
|
---|
| 230 | Win32LxDll::~Win32LxDll()
|
---|
| 231 | {
|
---|
| 232 | }
|
---|
| 233 | //******************************************************************************
|
---|
[4407] | 234 | //Returns reference count or -1 if load failed (PE loader only!)
|
---|
[956] | 235 | //******************************************************************************
|
---|
[3059] | 236 | #ifdef DEBUG
|
---|
| 237 | ULONG Win32LxDll::AddRef(char *parentname)
|
---|
| 238 | #else
|
---|
| 239 | ULONG Win32LxDll::AddRef()
|
---|
| 240 | #endif
|
---|
| 241 | {
|
---|
| 242 | Win32DllBase *dll;
|
---|
| 243 | QueueItem *item;
|
---|
| 244 | ULONG ret;
|
---|
| 245 |
|
---|
| 246 | #ifdef DEBUG
|
---|
| 247 | ret = Win32DllBase::AddRef(parentname);
|
---|
| 248 | #else
|
---|
| 249 | ret = Win32DllBase::AddRef();
|
---|
| 250 | #endif
|
---|
| 251 |
|
---|
[3375] | 252 | if(!fPeLoader)
|
---|
[6015] | 253 | return ret;
|
---|
[3059] | 254 |
|
---|
[6015] | 255 | if(referenced == 1)
|
---|
[3059] | 256 | {
|
---|
[6015] | 257 | item = loadedDlls.Head();
|
---|
| 258 | while(item) {
|
---|
| 259 | dll = (Win32DllBase *)loadedDlls.getItem(item);
|
---|
| 260 | if(dll == NULL) {
|
---|
| 261 | dprintf(("ERROR: Win32DllBase::AddRef: dll item == NULL!!"));
|
---|
| 262 | DebugInt3();
|
---|
| 263 | return -1;
|
---|
| 264 | }
|
---|
[3059] | 265 | #ifdef DEBUG
|
---|
[6015] | 266 | dll->AddRef(getModuleName());
|
---|
[3059] | 267 | #else
|
---|
[6015] | 268 | dll->AddRef();
|
---|
[3059] | 269 | #endif
|
---|
[6015] | 270 | item = loadedDlls.getNext(item);
|
---|
| 271 | }
|
---|
| 272 | if(attachProcess() == 0) {
|
---|
| 273 | dprintf(("WARNING: Dll %s refused to be loaded; aborting", getName()));
|
---|
| 274 | return -1;
|
---|
| 275 | }
|
---|
[3059] | 276 | }
|
---|
[6015] | 277 | return ret;
|
---|
[3059] | 278 | }
|
---|
| 279 | //******************************************************************************
|
---|
| 280 | //******************************************************************************
|
---|
[956] | 281 | ULONG Win32LxDll::Release()
|
---|
[6015] | 282 | {
|
---|
[9828] | 283 | HINSTANCE hinst = hinstanceOS2;
|
---|
| 284 | HINSTANCE hinstOdin = hinstance;
|
---|
[5075] | 285 | WIN32DLLENTRY EntryPointTmp = dllEntryPoint;
|
---|
| 286 | PVOID pResDataTmp = (PVOID)pResRootDir;
|
---|
| 287 | DWORD MajorImageVersionTmp = MajorImageVersion;
|
---|
| 288 | DWORD MinorImageVersionTmp = MinorImageVersion;
|
---|
| 289 | DWORD SubsystemTmp = Subsystem;
|
---|
[9828] | 290 | BOOL fNoUnload = fDisableUnload; //only set for kernel32.dll
|
---|
| 291 | BOOL fDynLoaded = isDynamicLib();
|
---|
[5075] | 292 | ULONG ret;
|
---|
| 293 | APIRET rc;
|
---|
[956] | 294 |
|
---|
[3059] | 295 | ret = Win32DllBase::Release();
|
---|
[9828] | 296 |
|
---|
| 297 | /** @sketch
|
---|
| 298 | * If this module is not unreference and it was loaded using LoadLibrary() then
|
---|
| 299 | * call the custombuild callback if present.
|
---|
| 300 | * The callback should call UnRegisterLxDll().
|
---|
| 301 | * Endif
|
---|
| 302 | *
|
---|
| 303 | * @remark
|
---|
| 304 | * #ifdef HACK_NEVER_UNLOAD_LX_DLLS
|
---|
| 305 | * This will never be called!
|
---|
| 306 | * #endif
|
---|
| 307 | *
|
---|
| 308 | * @todo: call pfnLxDllLoadCallback if DosFreeModule failes.
|
---|
| 309 | * It's not implemented because it's complex and at the moment we will
|
---|
| 310 | * never actually get here.
|
---|
| 311 | * So, this callback is here just as a reminder eventhough it's working..
|
---|
| 312 | */
|
---|
| 313 | if (!ret && fDynLoaded && pfnLxDllUnLoadCallback)
|
---|
| 314 | {
|
---|
| 315 | pfnLxDllUnLoadCallback(hinstanceOS2, hinstance);
|
---|
| 316 | }
|
---|
| 317 |
|
---|
| 318 | if (ret == 0 && !fNoUnload) {//only set for kernel32.dll (fDisableUnload)
|
---|
[6015] | 319 | //DosFreeModule sends a termination message to the dll.
|
---|
[8459] | 320 | //The LX dll informs us when it's removed (UnregisterDll call)
|
---|
[6015] | 321 | rc = DosFreeModule(hinst);
|
---|
| 322 | if(rc) {
|
---|
[5075] | 323 | dprintf(("Win32LxDll::Release: DosFreeModule %x returned %d", hinst, rc));
|
---|
[9828] | 324 | if(rc == ERROR_INVALID_ACCESS && !fExitProcess)
|
---|
[8459] | 325 | {
|
---|
[9828] | 326 | #ifndef HACK_NEVER_UNLOAD_LX_DLLS
|
---|
| 327 | #error @todo: call pfnLxDllLoadCallback and let it do the registering if it did that on the initial load..
|
---|
| 328 | #endif
|
---|
[5075] | 329 | //Dll refused to unload because it has an active exitlist handler
|
---|
| 330 | //or depends on a dll that registered an exitlist handler
|
---|
| 331 | //In this case the handle remains valid and the entrypoint of
|
---|
| 332 | //the dll is NOT called for DLL_PROCESS_DETACH
|
---|
| 333 | //WORKAROUND: Re-register the dll so future LoadLibrary calls
|
---|
| 334 | // don't fail!
|
---|
| 335 | dprintf(("WORKAROUND: Re-register the dll so future LoadLibrary calls don't fail!"));
|
---|
[6015] | 336 | RegisterLxDll(hinst, EntryPointTmp, pResDataTmp,
|
---|
| 337 | MajorImageVersionTmp,
|
---|
[5075] | 338 | MinorImageVersionTmp,
|
---|
| 339 | SubsystemTmp);
|
---|
| 340 |
|
---|
| 341 | /* OS/2 dll, system dll, converted dll or win32k took care of it. */
|
---|
[9828] | 342 | Win32LxDll *pModule = Win32LxDll::findModuleByOS2Handle(hinst);
|
---|
[5075] | 343 | if(pModule)
|
---|
| 344 | {
|
---|
| 345 | pModule->setDllHandleOS2(hinst);
|
---|
| 346 | if(fPeLoader)
|
---|
| 347 | {
|
---|
| 348 | if(pModule->AddRef() == -1) {//-1 -> load failed (attachProcess)
|
---|
| 349 | dprintf(("ERROR Dll refused to be loaded; aborting"));
|
---|
| 350 | DebugInt3();
|
---|
| 351 | delete pModule;
|
---|
| 352 | return 0;
|
---|
| 353 | }
|
---|
| 354 | }
|
---|
| 355 | pModule->incDynamicLib();
|
---|
| 356 | }
|
---|
| 357 | else DebugInt3();
|
---|
| 358 | }
|
---|
[6015] | 359 | }
|
---|
[956] | 360 | }
|
---|
| 361 | return(ret);
|
---|
| 362 | }
|
---|
| 363 | //******************************************************************************
|
---|
| 364 | //******************************************************************************
|
---|
[6015] | 365 | BOOL Win32LxDll::isPe2LxDll() const
|
---|
[956] | 366 | {
|
---|
[6015] | 367 | return FALSE;
|
---|
| 368 | }
|
---|
| 369 | //******************************************************************************
|
---|
| 370 | //******************************************************************************
|
---|
| 371 | BOOL Win32LxDll::isLxDll() const
|
---|
| 372 | {
|
---|
[956] | 373 | return TRUE;
|
---|
| 374 | }
|
---|
| 375 | //******************************************************************************
|
---|
| 376 | //******************************************************************************
|
---|
[6015] | 377 | void Win32LxDll::setDllHandleOS2(HINSTANCE hInstanceOS2)
|
---|
| 378 | {
|
---|
[3993] | 379 | //Loaded with LoadLibrary(Ex); no need for a 2nd DosLoadModule
|
---|
| 380 | //Dlls that are indirectly loaded (i.e. GDI32->KERNEL32 dependancy) need
|
---|
| 381 | //this additional DosLoadModule (and setDllHandleOS2 isn't called for those)
|
---|
| 382 | if(this->hinstanceOS2) {
|
---|
[6015] | 383 | DosFreeModule(this->hinstanceOS2);
|
---|
[3993] | 384 | }
|
---|
| 385 | this->hinstanceOS2 = hInstanceOS2;
|
---|
| 386 | }
|
---|
| 387 | //******************************************************************************
|
---|
| 388 | //******************************************************************************
|
---|
| 389 | Win32LxDll *Win32LxDll::findModuleByOS2Handle(HINSTANCE hinstance)
|
---|
| 390 | {
|
---|
[6015] | 391 | dlllistmutex.enter();
|
---|
[3993] | 392 |
|
---|
[6015] | 393 | Win32DllBase *mod = Win32DllBase::getFirst();
|
---|
| 394 | while (mod != NULL)
|
---|
| 395 | {
|
---|
| 396 | if (mod->isLxDll())
|
---|
| 397 | {
|
---|
| 398 | Win32LxDll *lxdll = (Win32LxDll *)mod;
|
---|
| 399 | if (lxdll->hinstanceOS2 == hinstance)
|
---|
| 400 | {
|
---|
| 401 | dlllistmutex.leave();
|
---|
| 402 | return(lxdll);
|
---|
| 403 | }
|
---|
[3993] | 404 | }
|
---|
[6015] | 405 | mod = mod->getNext();
|
---|
| 406 | }
|
---|
| 407 | dlllistmutex.leave();
|
---|
| 408 | return(NULL);
|
---|
[3993] | 409 | }
|
---|
| 410 | //******************************************************************************
|
---|
| 411 | //******************************************************************************
|
---|
[9828] | 412 |
|
---|
| 413 | /**
|
---|
| 414 | * Custombuild API for registering a callback for LX Dll loading thru LoadLibrary*().
|
---|
| 415 | * @returns Success indicator.
|
---|
| 416 | * @param pfn Pointer to callback.
|
---|
| 417 | * NULL if callback is deregistered.
|
---|
| 418 | */
|
---|
| 419 | BOOL WIN32API ODIN_SetLxDllUnLoadCallback(PFNLXDLLUNLOAD pfn)
|
---|
| 420 | {
|
---|
| 421 | pfnLxDllUnLoadCallback = pfn;
|
---|
| 422 | return TRUE;
|
---|
| 423 | }
|
---|
| 424 |
|
---|