Changeset 3059 for trunk/src/kernel32/windllbase.cpp
- Timestamp:
- Mar 9, 2000, 8:03:23 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/windllbase.cpp
r3005 r3059 1 /* $Id: windllbase.cpp,v 1.1 0 2000-03-04 19:52:36sandervl Exp $ */1 /* $Id: windllbase.cpp,v 1.11 2000-03-09 19:03:20 sandervl Exp $ */ 2 2 3 3 /* … … 6 6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl) 7 7 * 8 * TODO: Unloading of system dlls is not correct for the PE loader 9 * (they're always put at the head of the list even though there 10 * might be a dependency with a win32 dll) 8 * Unloading of a dll always happens in order of dependency (taking nr of 9 * loads into account) 10 * Unloading of dynamically loaded dll (with LoadLibrary) in deleteAll 11 * is done in LIFO order (NT exhibits the same behaviour) 12 * 13 * RemoveCircularDependency: TODO: Send process detach message here?? 11 14 * 12 15 * Project Odin Software License can be found in LICENSE.TXT … … 26 29 #include <fstream.h> 27 30 #include <misc.h> 28 #include <win32 type.h>31 #include <win32api.h> 29 32 #include <pefile.h> 30 33 #include <windllbase.h> … … 48 51 Win32ImageBase *parent) 49 52 : Win32ImageBase(hinstance), 50 referenced(0), fSkipEntryCalls(FALSE), 51 fAttachedToProcess(FALSE), fUnloaded(FALSE), fDynamicLoad(FALSE) 53 referenced(0), fSkipEntryCalls(FALSE), next(NULL), fInserted(FALSE), 54 fAttachedToProcess(FALSE), fUnloaded(FALSE), 55 nrDynamicLibRef(0), fLoadLibrary(FALSE), fDisableUnload(FALSE) 52 56 { 53 57 dllEntryPoint = DllEntryPoint; 54 58 55 dlllistmutex.enter(); 56 //unload of dlls needs to be done in reverse order of dependencies 57 //Note: Only necessary for pe loader; the OS/2 loader takes care of this 58 //for win32k/pe2lx 59 if(parent && parent->isDll()) { 60 Win32DllBase *dll = head; 61 while(dll) { 62 if(dll->getInstanceHandle() == parent->getInstanceHandle()) { 63 break; 64 } 65 dll = dll->next; 66 } 67 if(dll) { 68 //insert this dll in list after it's parent 69 next = dll->next; 70 dll->next = this; 71 } 72 else DebugInt3(); 73 } 74 else { 75 next = head; 76 head = this; 77 } 78 dlllistmutex.leave(); 79 80 #ifdef DEBUG_ENABLELOG_LEVEL2 81 dlllistmutex.enter(); 82 Win32DllBase *dll = head; 83 84 dprintf2(("Win32DllBase::Win32DllBase: List of loaded dlls:")); 85 while(dll) { 86 dprintf2(("DLL %s", dll->szModule)); 87 dll = dll->next; 88 } 89 dlllistmutex.leave(); 90 #endif 91 59 setUnloadOrder(parent); 60 92 61 dprintf(("Win32DllBase::Win32DllBase %x %s", hinstance, szModule)); 93 62 } … … 122 91 } 123 92 //****************************************************************************** 124 //ASSUMPTION: called by FreeLibrary 93 //****************************************************************************** 94 void Win32DllBase::loadLibrary() 95 { 96 //dummy 97 } 98 //****************************************************************************** 99 //****************************************************************************** 100 void Win32DllBase::incDynamicLib() 101 { 102 if(nrDynamicLibRef == 0) { 103 dlllistmutex.enter(); 104 loadLibDlls.Push((ULONG)this); 105 dlllistmutex.leave(); 106 } 107 nrDynamicLibRef++; 108 } 109 //****************************************************************************** 110 //****************************************************************************** 111 void Win32DllBase::decDynamicLib() 112 { 113 nrDynamicLibRef--; 114 if(nrDynamicLibRef == 0) { 115 dlllistmutex.enter(); 116 loadLibDlls.Remove((ULONG)this); 117 dlllistmutex.leave(); 118 } 119 } 120 //****************************************************************************** 121 //unload of dlls needs to be done in reverse order of dependencies 122 //Note: Only necessary for pe loader; the OS/2 loader takes care of this 123 //for win32k/pe2lx 124 //****************************************************************************** 125 void Win32DllBase::setUnloadOrder(Win32ImageBase *parent) 126 { 127 Win32DllBase *dll; 128 Win32DllBase *parentdll = NULL; 129 130 dlllistmutex.enter(); 131 if(parent) { 132 dll = head; 133 while(dll) { 134 if(dll->getInstanceHandle() == parent->getInstanceHandle()) { 135 parentdll = dll; 136 break; 137 } 138 dll = dll->next; 139 } 140 } 141 142 //first check if this dll is already at a lower position (further down the list) 143 //than the parent 144 if(parentdll && fInserted) {//already in the list? 145 dll = parentdll->next; 146 while(dll) { 147 if(dll->getInstanceHandle() == getInstanceHandle()) { 148 dlllistmutex.leave(); 149 return; //it's at a lower position, so no need to change anything 150 } 151 dll = dll->next; 152 } 153 154 //it's already in the list but not at the right position; remove it now 155 if(head == this) { 156 head = next; 157 } 158 else { 159 dll = head; 160 while(dll->next) { 161 if(dll->next == this) { 162 dll->next = next; 163 break; 164 } 165 dll = dll->next; 166 } 167 } 168 } 169 else 170 if(fInserted) {//already in the list? 171 dlllistmutex.leave(); 172 return; 173 } 174 //(re)insert it in the list after it's parent 175 if(parentdll) { 176 next = parentdll->next; 177 parentdll->next = this; 178 } 179 else {//no parent or exe, just add it at the start of the list 180 next = head; 181 head = this; 182 } 183 fInserted = TRUE; 184 185 //Now do the same thing for the child dependencies 186 QueueItem *item; 187 188 item = loadedDlls.Head(); 189 while(item) { 190 dll = (Win32DllBase *)loadedDlls.getItem(item); 191 //Check for circular dependencies (i.e. in Lotus Notes) 192 if(dll != parentdll) { 193 dll->setUnloadOrder(this); 194 } 195 196 item = loadedDlls.getNext(item); 197 } 198 199 dlllistmutex.leave(); 200 } 201 //****************************************************************************** 202 //****************************************************************************** 203 #ifdef DEBUG 204 ULONG Win32DllBase::AddRef(char *parentname) 205 #else 206 ULONG Win32DllBase::AddRef() 207 #endif 208 { 209 Win32DllBase *dll; 210 211 dprintf(("Win32DllBase::AddRef %s->%s %d", parentname, getModuleName(), referenced+1)); 212 ++referenced; 213 #ifdef DEBUG 214 if(referenced == 1) { 215 #ifdef DEBUG_ENABLELOG_LEVEL2 216 printListOfDlls(); 217 #endif 218 //printDependencies(NULL); 219 } 220 #endif 221 222 return referenced; 223 } 224 //****************************************************************************** 125 225 //****************************************************************************** 126 226 ULONG Win32DllBase::Release() 127 227 { 128 ULONG ret = --referenced; 129 130 if(ret == 0) { 131 dprintf(("Win32DllBase::Release, referenced == 0\n")); 228 Queue queue; 229 QueueItem *item; 230 Win32DllBase *dll; 231 LONG ret; 232 233 dprintf(("Win32DllBase::Release %s %d", getModuleName(), referenced-1)); 234 235 ret = --referenced; 236 if(ret <= 0) { 237 //make copy of linked list of dependencies 238 queue = loadedDlls; 239 240 //remove any circular dependencies on this dll that might be present 241 item = queue.Head(); 242 while(item) { 243 dll = (Win32DllBase *)queue.getItem(item); 244 if(dll == NULL) { 245 dprintf(("ERROR: Win32DllBase::Release: dll item == NULL!!")); 246 DebugInt3(); 247 return -1; 248 } 249 dll->RemoveCircularDependency(this); 250 item = queue.getNext(item); 251 } 252 #ifdef DEBUG 253 //printDependencies(NULL); 254 #endif 255 dprintf(("Win32DllBase::Release %s referenced == 0", getModuleName())); 256 257 //delete dll object 132 258 delete this; 259 260 //unreference all of it's dependencies 261 item = queue.Head(); 262 while(item) { 263 dll = (Win32DllBase *)queue.getItem(item); 264 if(dll == NULL) { 265 dprintf(("ERROR: Win32DllBase::Release: dll item == NULL!!")); 266 DebugInt3(); 267 return -1; 268 } 269 dll->Release(); 270 item = queue.getNext(item); 271 } 133 272 } 134 273 return(ret); 135 274 } 275 //****************************************************************************** 276 //Lotus Notes has several ugly circular dependencies in it's dlls. 277 //Remove them before they cause problems. 278 //****************************************************************************** 279 BOOL Win32DllBase::RemoveCircularDependency(Win32DllBase *parent) 280 { 281 QueueItem *item, *tmp; 282 Win32DllBase *dll; 283 BOOL ret = FALSE; 284 285 //remove any circular dependencies on this dll that might be present 286 item = loadedDlls.Head(); 287 while(item) { 288 dll = (Win32DllBase *)loadedDlls.getItem(item); 289 if(dll == NULL) { 290 dprintf(("ERROR: Win32DllBase::Release: dll item == NULL!!")); 291 DebugInt3(); 292 return FALSE; 293 } 294 tmp = loadedDlls.getNext(item); 295 if(dll == parent) { 296 dprintf(("Removing CIRCULAR dependency %s->%s", parent->getModuleName(), dll->getModuleName())); 297 loadedDlls.Remove(item); 298 ret = TRUE; 299 } 300 //// else ret |= dll->RemoveCircularDependency(parent); 301 item = tmp; 302 } 303 //TODO: Send process detach message here?? 304 return ret; 305 } 306 //****************************************************************************** 307 //There's a slight problem with our dependency procedure. 308 //example: gdi32 is loaded -> depends on kernel32 (which is already loaded) 309 // kernel32's reference count isn't updated 310 // (when we load gdi32, we don't know which dlls it depends on and which 311 // of those are already loaded and which aren't) 312 //-> solution: Determine reference counts of dependant lx dlls and update those 313 // reference counts 314 //****************************************************************************** 315 void Win32DllBase::updateDependencies() 316 { 317 QueueItem *item; 318 Win32DllBase *dll, *depdll; 319 ULONG refcount; 320 321 dlllistmutex.enter(); 322 item = loadedDlls.Head(); 323 while(item) { 324 depdll = (Win32DllBase *)loadedDlls.getItem(item); 325 if(depdll == NULL) { 326 dprintf(("updateDependencies: depdll == NULL!!")); 327 DebugInt3(); 328 return; 329 } 330 refcount = 0; 331 dll = head; 332 333 while(dll) { 334 if(dll->dependsOn(depdll)) { 335 refcount++; 336 } 337 dll = dll->getNext(); 338 } 339 if(refcount > depdll->referenced) { 340 dprintf(("Win32DllBase::updateDependencies changing refcount of %s to %d (old=%d)", depdll->getModuleName(), refcount, depdll->referenced)); 341 depdll->referenced = refcount; 342 } 343 344 item = loadedDlls.getNext(item); 345 } 346 dlllistmutex.leave(); 347 } 348 //****************************************************************************** 349 //****************************************************************************** 350 #ifdef DEBUG 351 void Win32DllBase::printDependencies(char *parent) 352 { 353 QueueItem *item; 354 Win32DllBase *dll; 355 ULONG ret; 356 357 dprintf(("Dependency list: %s->%s %d", parent, getModuleName(), referenced)); 358 item = loadedDlls.Head(); 359 while(item) { 360 dll = (Win32DllBase *)loadedDlls.getItem(item); 361 if(dll == NULL) { 362 return; 363 } 364 dll->printDependencies(getModuleName()); 365 item = loadedDlls.getNext(item); 366 } 367 } 368 //****************************************************************************** 369 //****************************************************************************** 370 #ifdef DEBUG_ENABLELOG_LEVEL2 371 void Win32DllBase::printListOfDlls() 372 { 373 Win32DllBase *dll; 374 375 dll = head; 376 377 dprintf2(("Win32DllBase::Win32DllBase: List of loaded dlls:")); 378 while(dll) { 379 dprintf2(("DLL %s %d", dll->szModule, dll->referenced)); 380 dll = dll->next; 381 } 382 } 383 #endif 384 #endif 136 385 //****************************************************************************** 137 386 //****************************************************************************** … … 252 501 void Win32DllBase::attachThreadToAllDlls() 253 502 { 503 dlllistmutex.enter(); 254 504 Win32DllBase *dll = Win32DllBase::head; 255 505 while(dll) { … … 257 507 dll = dll->getNext(); 258 508 } 509 dlllistmutex.leave(); 259 510 } 260 511 //****************************************************************************** … … 263 514 void Win32DllBase::detachThreadFromAllDlls() 264 515 { 516 dlllistmutex.enter(); 265 517 Win32DllBase *dll = Win32DllBase::head; 266 518 while(dll) { … … 268 520 dll = dll->getNext(); 269 521 } 522 dlllistmutex.leave(); 270 523 } 271 524 //****************************************************************************** … … 274 527 void Win32DllBase::tlsAttachThreadToAllDlls() 275 528 { 529 dlllistmutex.enter(); 276 530 Win32DllBase *dll = Win32DllBase::head; 277 531 while(dll) { … … 279 533 dll = dll->getNext(); 280 534 } 535 dlllistmutex.leave(); 281 536 } 282 537 //****************************************************************************** … … 285 540 void Win32DllBase::tlsDetachThreadFromAllDlls() 286 541 { 542 dlllistmutex.enter(); 287 543 Win32DllBase *dll = Win32DllBase::head; 288 544 while(dll) { … … 290 546 dll = dll->getNext(); 291 547 } 292 } 293 //****************************************************************************** 294 //****************************************************************************** 295 void Win32DllBase::deleteAll(BOOL fDynamicLoad) 296 { 297 Win32DllBase *dll = Win32DllBase::head, *tmp; 298 299 #ifdef DEBUG 300 dlllistmutex.enter(); 301 302 dprintf(("Win32DllBase::deleteAll: List of loaded dlls:")); 548 dlllistmutex.leave(); 549 } 550 //****************************************************************************** 551 //****************************************************************************** 552 void Win32DllBase::deleteAll() 553 { 554 Win32DllBase *dll = Win32DllBase::head; 555 556 dprintf(("Win32DllBase::deleteAll")); 557 558 #ifdef DEBUG_ENABLELOG_LEVEL2 559 if(dll) dll->printListOfDlls(); 560 #endif 561 562 dlllistmutex.enter(); 303 563 while(dll) { 304 dprintf(("DLL %s", dll->szModule)); 305 dll = dll->next; 306 } 307 dlllistmutex.leave(); 308 dll = Win32DllBase::head; 564 dll->Release(); 565 dll = Win32DllBase::head; 566 } 567 dlllistmutex.leave(); 568 dprintf(("Win32DllBase::deleteAll Done!")); 569 } 570 //****************************************************************************** 571 //Delete dlls loaded by LoadLibrary(Ex) in LIFO order 572 //****************************************************************************** 573 void Win32DllBase::deleteDynamicLibs() 574 { 575 Win32DllBase *dll = head; 576 QueueItem *item; 577 578 dprintf(("Win32DllBase::deleteDynamicLibs")); 579 #ifdef DEBUG_ENABLELOG_LEVEL2 580 if(dll) dll->printListOfDlls(); 309 581 #endif 310 582 311 while(dll) { 312 if(fDynamicLoad || !dll->fDynamicLoad) { 313 tmp = dll->next; 314 dll->Release(); 315 dll = tmp; 316 } 317 else dll = dll->next; 318 } 583 dlllistmutex.enter(); 584 585 item = loadLibDlls.Head(); 586 while(item) { 587 dll = (Win32DllBase *)loadLibDlls.getItem(item); 588 int dynref = dll->nrDynamicLibRef; 589 if(dynref) { 590 while(dynref) { 591 dynref--; 592 dll->decDynamicLib(); 593 dll->Release(); 594 } 595 } 596 else DebugInt3(); 597 item = loadLibDlls.Head(); //queue could have been changed, so start from the beginning 598 } 599 600 dlllistmutex.leave(); 601 } 602 //****************************************************************************** 603 //****************************************************************************** 604 Win32DllBase *Win32DllBase::getFirst() 605 { 606 return head; 319 607 } 320 608 //****************************************************************************** … … 386 674 //****************************************************************************** 387 675 //****************************************************************************** 388 Win32DllBase *Win32DllBase::findModule(char *dllname )676 Win32DllBase *Win32DllBase::findModule(char *dllname, BOOL fRenameFirst) 389 677 { 390 678 Win32DllBase *dll; … … 392 680 char *dot, *temp; 393 681 394 dprintf(("findModule %s", dllname));682 //// dprintf2(("findModule %s", dllname)); 395 683 396 684 strcpy(szDllName, OSLibStripPath(dllname)); 397 685 strupr(szDllName); 686 687 if(fRenameFirst) { 688 renameDll(szDllName, FALSE); 689 } 690 398 691 dot = strstr(szDllName, "."); 399 692 if(dot) … … 417 710 Win32DllBase *Win32DllBase::findModule(WIN32DLLENTRY DllEntryPoint) 418 711 { 419 dprintf (("findModule %X", DllEntryPoint));712 dprintf2(("findModule %X", DllEntryPoint)); 420 713 421 714 dlllistmutex.enter(); … … 468 761 //****************************************************************************** 469 762 Win32DllBase *Win32DllBase::head = NULL; 763 Queue Win32DllBase::loadLibDlls;
Note:
See TracChangeset
for help on using the changeset viewer.