You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
7.8 KiB
294 lines
7.8 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: libmgmt.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* This module contains the code to manage loading and freeing libraries
|
|
* in use by USER.
|
|
*
|
|
* History:
|
|
* 02-04-91 DavidPe Created.
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
/*
|
|
* Globals local to this file
|
|
*
|
|
*
|
|
* Number of hmodule entries in the module management table.
|
|
*/
|
|
int catomSysTableEntries;
|
|
|
|
/*
|
|
* Array of atoms that are the fully qualified path names of each managed
|
|
* module.
|
|
*/
|
|
ATOM aatomSysLoaded[CLIBS];
|
|
|
|
/*
|
|
* Count of processes that have LoadModule()'d each module.
|
|
*/
|
|
int acatomSysUse[CLIBS];
|
|
|
|
/*
|
|
* Count of hooks set into each module.
|
|
*/
|
|
int acatomSysDepends[CLIBS];
|
|
|
|
|
|
/****************************************************************************\
|
|
* GetHmodTableIndex
|
|
*
|
|
* This routine is used to return the index of a given atom within the system
|
|
* wide hmod atom table. If the atom is not found, an attempt to allocate a
|
|
* new table entry is made. If the attempt fails, -1 is returned.
|
|
*
|
|
* History:
|
|
* 02-04-91 DavidPe Ported.
|
|
\****************************************************************************/
|
|
|
|
int GetHmodTableIndex(
|
|
PUNICODE_STRING pstrLibName)
|
|
{
|
|
int i;
|
|
ATOM atom;
|
|
UNICODE_STRING strLibName;
|
|
|
|
/*
|
|
* Probe string
|
|
*/
|
|
try {
|
|
strLibName = ProbeAndReadUnicodeString(pstrLibName);
|
|
ProbeForReadUnicodeStringBuffer(strLibName);
|
|
atom = UserAddAtom(strLibName.Buffer, FALSE);
|
|
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* If we can't add the atom we're hosed
|
|
* so return an error.
|
|
*/
|
|
if (atom == 0) {
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Search for atom index
|
|
*/
|
|
for (i = 0; i < catomSysTableEntries && aatomSysLoaded[i] != atom; i++)
|
|
;
|
|
|
|
if (i == catomSysTableEntries) {
|
|
|
|
/*
|
|
* Find empty entry for atom
|
|
*/
|
|
for (i = 0; i < catomSysTableEntries && aatomSysLoaded[i]; i++)
|
|
;
|
|
|
|
/*
|
|
* Check if no empty entry found
|
|
*/
|
|
if (i == catomSysTableEntries) {
|
|
if (i == CLIBS) {
|
|
UserDeleteAtom(atom);
|
|
RIPERR0(ERROR_NOT_ENOUGH_MEMORY,
|
|
RIP_WARNING,
|
|
"Memory allocation failed in GetHmodTableIndex");
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Increase table size
|
|
*/
|
|
catomSysTableEntries++;
|
|
}
|
|
|
|
/*
|
|
* Set entry
|
|
*/
|
|
aatomSysLoaded[i] = atom;
|
|
acatomSysUse[i] = 0;
|
|
acatomSysDepends[i] = 0;
|
|
} else {
|
|
UserDeleteAtom(atom);
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* AddHmodDependency
|
|
*
|
|
* This function merely increments the dependency count of a given hmod
|
|
* atom table index.
|
|
*
|
|
* History:
|
|
* 02-04-91 DavidPe Ported.
|
|
\*****************************************************************************/
|
|
|
|
VOID AddHmodDependency(
|
|
int iatom)
|
|
{
|
|
UserAssert(iatom >= 0);
|
|
if (iatom < catomSysTableEntries) {
|
|
acatomSysDepends[iatom]++;
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* RemoveHmodDependency
|
|
*
|
|
* This function removes a system dependency on a given index into the hmod
|
|
* atom table. If all dependencies on the hmod have been removed (the Depends
|
|
* count reaches zero) then the QS_SYSEXPUNGE bit is set in all message
|
|
* queues so the eventually each process will do a free module on it.
|
|
*
|
|
* History:
|
|
* 02-04-91 DavidPe Ported.
|
|
\*****************************************************************************/
|
|
|
|
VOID RemoveHmodDependency(
|
|
int iatom)
|
|
{
|
|
|
|
UserAssert(iatom >= 0);
|
|
if (iatom < catomSysTableEntries &&
|
|
--acatomSysDepends[iatom] == 0) {
|
|
|
|
if (acatomSysUse[iatom]) {
|
|
|
|
/*
|
|
* Cause each thread to check for expunged dlls
|
|
* the next time they awake.
|
|
*/
|
|
gcSysExpunge++;
|
|
gdwSysExpungeMask |= (1 << iatom);
|
|
} else {
|
|
aatomSysLoaded[iatom] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* xxxLoadHmodIndex
|
|
*
|
|
* This function attempts to load the hmodule specified by iatom into the
|
|
* system hmod table. Updates the per-process bitmap accordingly. Returns
|
|
* NULL on success.
|
|
*
|
|
* History:
|
|
* 02-04-91 DavidPe Ported.
|
|
\*****************************************************************************/
|
|
|
|
HANDLE xxxLoadHmodIndex(
|
|
int iatom)
|
|
{
|
|
WCHAR pszLibName[MAX_PATH];
|
|
HANDLE hmod;
|
|
UNICODE_STRING strLibrary;
|
|
PTHREADINFO ptiCurrent = PtiCurrent();
|
|
|
|
UserAssert((!gptiRit || gptiRit->ppi != PtiCurrent()->ppi) &&
|
|
"Shouldn't load global hooks on system process - gptiRit->ppi is the system process");
|
|
|
|
if (iatom >= catomSysTableEntries) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Index out of range");
|
|
return NULL;
|
|
}
|
|
|
|
UserGetAtomName(aatomSysLoaded[iatom], pszLibName, sizeof(pszLibName)/sizeof(WCHAR));
|
|
|
|
/*
|
|
* Call back the client to load the library.
|
|
*/
|
|
RtlInitUnicodeString(&strLibrary, pszLibName);
|
|
hmod = ClientLoadLibrary(&strLibrary, (iatom == gihmodUserApiHook) ? goffPfnInitUserApiHook : 0);
|
|
|
|
if (hmod != NULL) {
|
|
/*
|
|
* Check to make sure another thread hasn't loaded this library
|
|
* while we were outside the critical section.
|
|
*/
|
|
if (!TESTHMODLOADED(ptiCurrent, iatom)) {
|
|
/*
|
|
* Go ahead and bump the reference count.
|
|
*/
|
|
acatomSysUse[iatom]++;
|
|
SETHMODLOADED(ptiCurrent, iatom, hmod);
|
|
|
|
} else {
|
|
/*
|
|
* Another thread loaded it while we were outside the
|
|
* critical section. Unload it so the system's
|
|
* reference count is correct.
|
|
*/
|
|
ClientFreeLibrary(ptiCurrent->ppi->ahmodLibLoaded[iatom]);
|
|
}
|
|
}
|
|
|
|
return hmod;
|
|
}
|
|
|
|
|
|
/***********************************************************************\
|
|
* DoSysExpunge
|
|
*
|
|
* This function is called when a thread wakes up and finds its
|
|
* QS_SYSEXPUNGE wakebit set.
|
|
*
|
|
* History:
|
|
* 02-04-91 DavidPe Ported.
|
|
\***********************************************************************/
|
|
|
|
VOID xxxDoSysExpunge(
|
|
PTHREADINFO pti)
|
|
{
|
|
int i;
|
|
|
|
/*
|
|
* Clear this first before we potentially leave the critical section.
|
|
*/
|
|
pti->ppi->cSysExpunge = gcSysExpunge;
|
|
|
|
/*
|
|
* Scan for libraries that have been freed
|
|
*/
|
|
for (i = 0; i < catomSysTableEntries; i++) {
|
|
if ((acatomSysDepends[i] == 0) && (aatomSysLoaded[i] != 0) &&
|
|
TESTHMODLOADED(pti, i)) {
|
|
|
|
HANDLE hmodFree = pti->ppi->ahmodLibLoaded[i];
|
|
|
|
/*
|
|
* Clear this hmod for this process before we leave the
|
|
* critical section.
|
|
*/
|
|
CLEARHMODLOADED(pti, i);
|
|
|
|
/*
|
|
* Decrement the count of processes that have loaded this
|
|
* .dll. If there are no more, then destroy the reference
|
|
* to this .dll.
|
|
*/
|
|
if (--acatomSysUse[i] == 0) {
|
|
UserDeleteAtom(aatomSysLoaded[i]);
|
|
aatomSysLoaded[i] = 0;
|
|
gdwSysExpungeMask &= ~(1 << i);
|
|
}
|
|
|
|
/*
|
|
* Call back the client to free the library...
|
|
*/
|
|
ClientFreeLibrary(hmodFree);
|
|
}
|
|
}
|
|
}
|