Leaked source code of windows server 2003
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

/****************************** 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);
}
}
}