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.
 
 
 
 
 
 

399 lines
12 KiB

/********************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
PCH_SystemHook.CPP
Abstract:
WBEM provider class implementation for PCH_SystemHook class
Revision History:
Ghim-Sim Chua (gschua) 05/05/99
- Created
Jim Martin (a-jammar) 06/01/99
- Populated data, added Dr. Watson code.
********************************************************************/
#include "pchealth.h"
#include "PCH_SystemHook.h"
/////////////////////////////////////////////////////////////////////////////
// tracing stuff
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
#define TRACE_ID DCID_SYSTEMHOOK
CPCH_SystemHook MyPCH_SystemHookSet (PROVIDER_NAME_PCH_SYSTEMHOOK, PCH_NAMESPACE);
// Property names
const static WCHAR * pTimeStamp = L"TimeStamp";
const static WCHAR * pChange = L"Change";
const static WCHAR * pApplication = L"Application";
const static WCHAR * pApplicationPath = L"ApplicationPath";
const static WCHAR * pDLLPath = L"DLLPath";
const static WCHAR * pFullPath = L"FullPath";
const static WCHAR * pHookedBy = L"HookedBy";
const static WCHAR * pHookType = L"HookType";
//-----------------------------------------------------------------------------
// Here's a simple collection class to hold the hook information.
//-----------------------------------------------------------------------------
class CHookInfo
{
public:
CHookInfo() : m_pList(NULL) {};
~CHookInfo();
BOOL QueryHooks();
BOOL GetHook(DWORD dwIndex, int * iHook, char ** pszDll, char ** pszExe);
private:
// Functions pulled from the Dr. Watson code.
BOOL NTAPI Hook_PreInit();
void NTAPI Hook_RecordHook(PHOOK16 phk, PHOOKWALKINFO phwi);
// A struct to hold each parsed hook.
struct SHookItem
{
int m_iHook;
char m_szHookDll[MAX_PATH];
char m_szHookExe[MAX_PATH];
SHookItem * m_pNext;
SHookItem(int iHook, const char * szDll, const char * szExe, SHookItem * pNext)
: m_iHook(iHook), m_pNext(pNext)
{
strcpy(m_szHookDll, szDll);
strcpy(m_szHookExe, szExe);
}
};
SHookItem * m_pList;
};
//-----------------------------------------------------------------------------
// The destructor gets rid of the list of hooks.
//-----------------------------------------------------------------------------
CHookInfo::~CHookInfo()
{
TraceFunctEnter("CHookInfo::~CHookInfo");
SHookItem * pNext;
while (m_pList)
{
pNext = m_pList->m_pNext;
delete m_pList;
m_pList = pNext;
}
TraceFunctLeave();
}
//-----------------------------------------------------------------------------
// QueryHooks creates the list of system hooks (by calling the Dr. Watson code).
//-----------------------------------------------------------------------------
extern "C" void ThunkInit(void);
BOOL CHookInfo::QueryHooks()
{
ThunkInit();
return Hook_PreInit();
}
//-----------------------------------------------------------------------------
// GetHook returns information for the hook specified by dwIndex. If there is
// no hook at that index, FALSE is returned. The string pointers are changed
// to point at the appropriate strings in the CHookInfo list. This pointers
// will be invalid when the CHookInfo object is destroyed.
//-----------------------------------------------------------------------------
BOOL CHookInfo::GetHook(DWORD dwIndex, int * iHook, char ** pszDll, char ** pszExe)
{
TraceFunctEnter("CHookInfo::GetHook");
SHookItem * pItem = m_pList;
BOOL fReturn = FALSE;
for (DWORD i = 0; i < dwIndex && pItem; i++)
pItem = pItem->m_pNext;
if (pItem)
{
*iHook = pItem->m_iHook;
*pszDll = pItem->m_szHookDll;
*pszExe = pItem->m_szHookExe;
fReturn = TRUE;
}
TraceFunctLeave();
return fReturn;
}
//-----------------------------------------------------------------------------
// The following table is used for indicating the hook type. It's referenced
// by the iHook value returned from CHookInfo::GetHook. One has to be added
// to the iHook value to reference this table, since it starts from -1.
//-----------------------------------------------------------------------------
LPCTSTR aszHookType[] =
{
_T("Message Filter"),
_T("Journal Record"),
_T("Journal Playback"),
_T("Keyboard"),
_T("GetMessage"),
_T("Window Procedure"),
_T("CBT"),
_T("System MsgFilter"),
_T("Mouse"),
_T("Hardware"),
_T("Debug"),
_T("Shell"),
_T("Foreground Idle"),
_T("Window Procedure Result")
};
//-----------------------------------------------------------------------------
// The EnumeratInstances function is called by WMI to enurate the instances
// of the class. Here we use the CHookInfo class to create a list of system
// hooks which we enumerate, creating a WMI object for each one.
//-----------------------------------------------------------------------------
HRESULT CPCH_SystemHook::EnumerateInstances(MethodContext * pMethodContext, long lFlags)
{
TraceFunctEnter("CPCH_SystemHook::EnumerateInstances");
HRESULT hRes = WBEM_S_NO_ERROR;
// Get the date and time
SYSTEMTIME stUTCTime;
GetSystemTime(&stUTCTime);
CHookInfo hookinfo;
if (hookinfo.QueryHooks())
{
int iHook;
char * szDll;
char * szExe;
for (DWORD dwIndex = 0; hookinfo.GetHook(dwIndex, &iHook, &szDll, &szExe); dwIndex++)
{
CInstancePtr pInstance(CreateNewInstance(pMethodContext), false);
// Set the change and timestamp fields to "Snapshot" and the current time.
if (!pInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime)))
ErrorTrace(TRACE_ID, "SetDateTime on Timestamp field failed.");
if (!pInstance->SetCHString(pChange, L"Snapshot"))
ErrorTrace(TRACE_ID, "SetCHString on Change field failed.");
// Set the properties we found for the hook.
if (!pInstance->SetCHString(pDLLPath, szDll))
ErrorTrace(TRACE_ID, "SetCHString on DLL field failed.");
if (!pInstance->SetCHString(pApplicationPath, szExe))
ErrorTrace(TRACE_ID, "SetCHString on application path field failed.");
if (!pInstance->SetCHString(pApplication, PathFindFileName(szExe)))
ErrorTrace(TRACE_ID, "SetCHString on application field failed.");
if (!pInstance->SetCHString(pFullPath, szDll))
ErrorTrace(TRACE_ID, "SetCHString on pFullPath field failed.");
if (!pInstance->SetCHString(pHookedBy, PathFindFileName(szDll)))
ErrorTrace(TRACE_ID, "SetCHString on pHookedBy field failed.");
if (iHook >= -1 && iHook <= 12)
{
if (!pInstance->SetCHString(pHookType, aszHookType[iHook + 1]))
ErrorTrace(TRACE_ID, "SetCHString on pHookType field failed.");
}
else
ErrorTrace(TRACE_ID, "Bad hook type.");
hRes = pInstance->Commit();
if (FAILED(hRes))
ErrorTrace(TRACE_ID, "Commit on Instance failed.");
}
}
TraceFunctLeave();
return hRes;
}
//-----------------------------------------------------------------------------
// Gather the system hook information.
//-----------------------------------------------------------------------------
TCHAR g_tszShell[MAX_PATH];
BOOL NTAPI CHookInfo::Hook_PreInit()
{
TraceFunctEnter("CHookInfo::Hook_PreInit");
BOOL fRc = FALSE;
// Initialize the g_tszShell variable if necessary.
if (!g_tszShell[0])
{
TCHAR tszPath[MAX_PATH];
GetPrivateProfileString(TEXT("boot"), TEXT("shell"), TEXT("explorer.exe"), tszPath, cA(tszPath), TEXT("system.ini"));
lstrcpy(g_tszShell, PathFindFileName(tszPath));
}
if (g_pvWin16Lock)
{
PV pvUser = MapSL((PV)MAKELONG(0, (DWORD)g_hinstUser));
LPWORD pwRghhk;
DWORD dwHhk;
dwHhk = GetUserHookTable();
switch (HIWORD(dwHhk))
{
case 1:
// We "know" the structure of the USER hook chain
// of type 1.
pwRghhk = (LPWORD)pvAddPvCb(pvUser, LOWORD(dwHhk) + 2);
break;
default:
// Unknown hook style. Oh well.
pwRghhk = 0;
break;
}
if (pwRghhk)
{
// Walk the hook list (under the Win16 lock)
// and parse out each installed hook.
int ihk;
HOOKWALKINFO hwi;
EnterSysLevel(g_pvWin16Lock);
for (ihk = WH_MIN; ihk <= WH_MAX; ihk++)
{
WORD hhk = pwRghhk[ihk];
while (hhk)
{
PHOOK16 phk = (PHOOK16)pvAddPvCb(pvUser, hhk);
if (phk->hkMagic != HK_MAGIC || phk->idHook != ihk)
break; // Weird. Stop before we GPF
Hook_RecordHook(phk, &hwi);
hhk = phk->phkNext;
fRc = TRUE;
}
}
LeaveSysLevel(g_pvWin16Lock);
}
}
TraceFunctLeave();
return fRc;
}
//-----------------------------------------------------------------------------
// Record information about a single hook during the hookwalk process.
//-----------------------------------------------------------------------------
void NTAPI CHookInfo::Hook_RecordHook(PHOOK16 phk, PHOOKWALKINFO phwi)
{
TraceFunctEnter("CHookInfo::Hook_RecordHook");
HOOKINFO hi;
PQ16 pq;
ZeroX(hi);
hi.iHook = phk->idHook;
// Get the name of the app that installed the hook.
// We wished we could pass the queue handle to GetModuleFileName,
// but that will just return USER.
//
// It is possible that the queue is null; this means that the
// hook was installed by a device driver (like XMOUSE).
pq = (PQ16)MapSL((PV)MAKELONG(0, phk->hqCreator));
if (pq)
GetModuleFileName16(pq->htask, hi.szHookExe, cA(hi.szHookExe));
else
hi.szHookExe[0] = TEXT('\0');
// Now get the DLL name. This varies depending on whether the
// DLL is 16-bit or 32-bit.
if (phk->uiFlags & HOOK_32BIT)
{
// If a 32-bit hook, then the DLL name is saved in an atom.
GetUserAtomName(phk->atomModule, hi.szHookDll);
PathAdjustCase(hi.szHookDll, 0);
}
else
{
// If a 16-bit hook, then the DLL name is saved as hmodule16.
GetModuleFileName16((HMODULE16)phk->hmodOwner, hi.szHookDll, cA(hi.szHookDll));
PathAdjustCase(hi.szHookDll, 1);
}
// Add the hook to the collection of hooks. Don't add the explorer shell to the
// list.
if (hi.iHook != WH_SHELL || lstrcmpi(PathFindFileName(hi.szHookExe), g_tszShell) != 0)
{
SHookItem * pNew = new SHookItem(hi.iHook, hi.szHookDll, hi.szHookExe, m_pList);
if (pNew)
m_pList = pNew;
else
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
TraceFunctLeave();
}
//-----------------------------------------------------------------------------
// Function pulled in from Dr. Watson.
//
// If f16, then it is a 16-bit thing, and we uppercase it all.
// If !f16, then it is a 32-bit thing, and we uppercase the
// first and downcase the rest.
//
// If the first letter is a DBCS thing, then we don't touch it.
//-----------------------------------------------------------------------------
void NTAPI PathAdjustCase(LPSTR psz, BOOL f16)
{
TraceFunctEnter("PathAdjustCase");
psz = PathFindFileName(psz);
if (f16)
CharUpper(psz);
else if (!IsDBCSLeadByte(*psz))
{
CharUpperBuff(psz, 1);
CharLower(psz+1);
}
TraceFunctLeave();
}