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

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. PCH_SystemHook.CPP
  5. Abstract:
  6. WBEM provider class implementation for PCH_SystemHook class
  7. Revision History:
  8. Ghim-Sim Chua (gschua) 05/05/99
  9. - Created
  10. Jim Martin (a-jammar) 06/01/99
  11. - Populated data, added Dr. Watson code.
  12. ********************************************************************/
  13. #include "pchealth.h"
  14. #include "PCH_SystemHook.h"
  15. /////////////////////////////////////////////////////////////////////////////
  16. // tracing stuff
  17. #ifdef THIS_FILE
  18. #undef THIS_FILE
  19. #endif
  20. static char __szTraceSourceFile[] = __FILE__;
  21. #define THIS_FILE __szTraceSourceFile
  22. #define TRACE_ID DCID_SYSTEMHOOK
  23. CPCH_SystemHook MyPCH_SystemHookSet (PROVIDER_NAME_PCH_SYSTEMHOOK, PCH_NAMESPACE);
  24. // Property names
  25. const static WCHAR * pTimeStamp = L"TimeStamp";
  26. const static WCHAR * pChange = L"Change";
  27. const static WCHAR * pApplication = L"Application";
  28. const static WCHAR * pApplicationPath = L"ApplicationPath";
  29. const static WCHAR * pDLLPath = L"DLLPath";
  30. const static WCHAR * pFullPath = L"FullPath";
  31. const static WCHAR * pHookedBy = L"HookedBy";
  32. const static WCHAR * pHookType = L"HookType";
  33. //-----------------------------------------------------------------------------
  34. // Here's a simple collection class to hold the hook information.
  35. //-----------------------------------------------------------------------------
  36. class CHookInfo
  37. {
  38. public:
  39. CHookInfo() : m_pList(NULL) {};
  40. ~CHookInfo();
  41. BOOL QueryHooks();
  42. BOOL GetHook(DWORD dwIndex, int * iHook, char ** pszDll, char ** pszExe);
  43. private:
  44. // Functions pulled from the Dr. Watson code.
  45. BOOL NTAPI Hook_PreInit();
  46. void NTAPI Hook_RecordHook(PHOOK16 phk, PHOOKWALKINFO phwi);
  47. // A struct to hold each parsed hook.
  48. struct SHookItem
  49. {
  50. int m_iHook;
  51. char m_szHookDll[MAX_PATH];
  52. char m_szHookExe[MAX_PATH];
  53. SHookItem * m_pNext;
  54. SHookItem(int iHook, const char * szDll, const char * szExe, SHookItem * pNext)
  55. : m_iHook(iHook), m_pNext(pNext)
  56. {
  57. strcpy(m_szHookDll, szDll);
  58. strcpy(m_szHookExe, szExe);
  59. }
  60. };
  61. SHookItem * m_pList;
  62. };
  63. //-----------------------------------------------------------------------------
  64. // The destructor gets rid of the list of hooks.
  65. //-----------------------------------------------------------------------------
  66. CHookInfo::~CHookInfo()
  67. {
  68. TraceFunctEnter("CHookInfo::~CHookInfo");
  69. SHookItem * pNext;
  70. while (m_pList)
  71. {
  72. pNext = m_pList->m_pNext;
  73. delete m_pList;
  74. m_pList = pNext;
  75. }
  76. TraceFunctLeave();
  77. }
  78. //-----------------------------------------------------------------------------
  79. // QueryHooks creates the list of system hooks (by calling the Dr. Watson code).
  80. //-----------------------------------------------------------------------------
  81. extern "C" void ThunkInit(void);
  82. BOOL CHookInfo::QueryHooks()
  83. {
  84. ThunkInit();
  85. return Hook_PreInit();
  86. }
  87. //-----------------------------------------------------------------------------
  88. // GetHook returns information for the hook specified by dwIndex. If there is
  89. // no hook at that index, FALSE is returned. The string pointers are changed
  90. // to point at the appropriate strings in the CHookInfo list. This pointers
  91. // will be invalid when the CHookInfo object is destroyed.
  92. //-----------------------------------------------------------------------------
  93. BOOL CHookInfo::GetHook(DWORD dwIndex, int * iHook, char ** pszDll, char ** pszExe)
  94. {
  95. TraceFunctEnter("CHookInfo::GetHook");
  96. SHookItem * pItem = m_pList;
  97. BOOL fReturn = FALSE;
  98. for (DWORD i = 0; i < dwIndex && pItem; i++)
  99. pItem = pItem->m_pNext;
  100. if (pItem)
  101. {
  102. *iHook = pItem->m_iHook;
  103. *pszDll = pItem->m_szHookDll;
  104. *pszExe = pItem->m_szHookExe;
  105. fReturn = TRUE;
  106. }
  107. TraceFunctLeave();
  108. return fReturn;
  109. }
  110. //-----------------------------------------------------------------------------
  111. // The following table is used for indicating the hook type. It's referenced
  112. // by the iHook value returned from CHookInfo::GetHook. One has to be added
  113. // to the iHook value to reference this table, since it starts from -1.
  114. //-----------------------------------------------------------------------------
  115. LPCTSTR aszHookType[] =
  116. {
  117. _T("Message Filter"),
  118. _T("Journal Record"),
  119. _T("Journal Playback"),
  120. _T("Keyboard"),
  121. _T("GetMessage"),
  122. _T("Window Procedure"),
  123. _T("CBT"),
  124. _T("System MsgFilter"),
  125. _T("Mouse"),
  126. _T("Hardware"),
  127. _T("Debug"),
  128. _T("Shell"),
  129. _T("Foreground Idle"),
  130. _T("Window Procedure Result")
  131. };
  132. //-----------------------------------------------------------------------------
  133. // The EnumeratInstances function is called by WMI to enurate the instances
  134. // of the class. Here we use the CHookInfo class to create a list of system
  135. // hooks which we enumerate, creating a WMI object for each one.
  136. //-----------------------------------------------------------------------------
  137. HRESULT CPCH_SystemHook::EnumerateInstances(MethodContext * pMethodContext, long lFlags)
  138. {
  139. TraceFunctEnter("CPCH_SystemHook::EnumerateInstances");
  140. HRESULT hRes = WBEM_S_NO_ERROR;
  141. // Get the date and time
  142. SYSTEMTIME stUTCTime;
  143. GetSystemTime(&stUTCTime);
  144. CHookInfo hookinfo;
  145. if (hookinfo.QueryHooks())
  146. {
  147. int iHook;
  148. char * szDll;
  149. char * szExe;
  150. for (DWORD dwIndex = 0; hookinfo.GetHook(dwIndex, &iHook, &szDll, &szExe); dwIndex++)
  151. {
  152. CInstancePtr pInstance(CreateNewInstance(pMethodContext), false);
  153. // Set the change and timestamp fields to "Snapshot" and the current time.
  154. if (!pInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime)))
  155. ErrorTrace(TRACE_ID, "SetDateTime on Timestamp field failed.");
  156. if (!pInstance->SetCHString(pChange, L"Snapshot"))
  157. ErrorTrace(TRACE_ID, "SetCHString on Change field failed.");
  158. // Set the properties we found for the hook.
  159. if (!pInstance->SetCHString(pDLLPath, szDll))
  160. ErrorTrace(TRACE_ID, "SetCHString on DLL field failed.");
  161. if (!pInstance->SetCHString(pApplicationPath, szExe))
  162. ErrorTrace(TRACE_ID, "SetCHString on application path field failed.");
  163. if (!pInstance->SetCHString(pApplication, PathFindFileName(szExe)))
  164. ErrorTrace(TRACE_ID, "SetCHString on application field failed.");
  165. if (!pInstance->SetCHString(pFullPath, szDll))
  166. ErrorTrace(TRACE_ID, "SetCHString on pFullPath field failed.");
  167. if (!pInstance->SetCHString(pHookedBy, PathFindFileName(szDll)))
  168. ErrorTrace(TRACE_ID, "SetCHString on pHookedBy field failed.");
  169. if (iHook >= -1 && iHook <= 12)
  170. {
  171. if (!pInstance->SetCHString(pHookType, aszHookType[iHook + 1]))
  172. ErrorTrace(TRACE_ID, "SetCHString on pHookType field failed.");
  173. }
  174. else
  175. ErrorTrace(TRACE_ID, "Bad hook type.");
  176. hRes = pInstance->Commit();
  177. if (FAILED(hRes))
  178. ErrorTrace(TRACE_ID, "Commit on Instance failed.");
  179. }
  180. }
  181. TraceFunctLeave();
  182. return hRes;
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Gather the system hook information.
  186. //-----------------------------------------------------------------------------
  187. TCHAR g_tszShell[MAX_PATH];
  188. BOOL NTAPI CHookInfo::Hook_PreInit()
  189. {
  190. TraceFunctEnter("CHookInfo::Hook_PreInit");
  191. BOOL fRc = FALSE;
  192. // Initialize the g_tszShell variable if necessary.
  193. if (!g_tszShell[0])
  194. {
  195. TCHAR tszPath[MAX_PATH];
  196. GetPrivateProfileString(TEXT("boot"), TEXT("shell"), TEXT("explorer.exe"), tszPath, cA(tszPath), TEXT("system.ini"));
  197. lstrcpy(g_tszShell, PathFindFileName(tszPath));
  198. }
  199. if (g_pvWin16Lock)
  200. {
  201. PV pvUser = MapSL((PV)MAKELONG(0, (DWORD)g_hinstUser));
  202. LPWORD pwRghhk;
  203. DWORD dwHhk;
  204. dwHhk = GetUserHookTable();
  205. switch (HIWORD(dwHhk))
  206. {
  207. case 1:
  208. // We "know" the structure of the USER hook chain
  209. // of type 1.
  210. pwRghhk = (LPWORD)pvAddPvCb(pvUser, LOWORD(dwHhk) + 2);
  211. break;
  212. default:
  213. // Unknown hook style. Oh well.
  214. pwRghhk = 0;
  215. break;
  216. }
  217. if (pwRghhk)
  218. {
  219. // Walk the hook list (under the Win16 lock)
  220. // and parse out each installed hook.
  221. int ihk;
  222. HOOKWALKINFO hwi;
  223. EnterSysLevel(g_pvWin16Lock);
  224. for (ihk = WH_MIN; ihk <= WH_MAX; ihk++)
  225. {
  226. WORD hhk = pwRghhk[ihk];
  227. while (hhk)
  228. {
  229. PHOOK16 phk = (PHOOK16)pvAddPvCb(pvUser, hhk);
  230. if (phk->hkMagic != HK_MAGIC || phk->idHook != ihk)
  231. break; // Weird. Stop before we GPF
  232. Hook_RecordHook(phk, &hwi);
  233. hhk = phk->phkNext;
  234. fRc = TRUE;
  235. }
  236. }
  237. LeaveSysLevel(g_pvWin16Lock);
  238. }
  239. }
  240. TraceFunctLeave();
  241. return fRc;
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Record information about a single hook during the hookwalk process.
  245. //-----------------------------------------------------------------------------
  246. void NTAPI CHookInfo::Hook_RecordHook(PHOOK16 phk, PHOOKWALKINFO phwi)
  247. {
  248. TraceFunctEnter("CHookInfo::Hook_RecordHook");
  249. HOOKINFO hi;
  250. PQ16 pq;
  251. ZeroX(hi);
  252. hi.iHook = phk->idHook;
  253. // Get the name of the app that installed the hook.
  254. // We wished we could pass the queue handle to GetModuleFileName,
  255. // but that will just return USER.
  256. //
  257. // It is possible that the queue is null; this means that the
  258. // hook was installed by a device driver (like XMOUSE).
  259. pq = (PQ16)MapSL((PV)MAKELONG(0, phk->hqCreator));
  260. if (pq)
  261. GetModuleFileName16(pq->htask, hi.szHookExe, cA(hi.szHookExe));
  262. else
  263. hi.szHookExe[0] = TEXT('\0');
  264. // Now get the DLL name. This varies depending on whether the
  265. // DLL is 16-bit or 32-bit.
  266. if (phk->uiFlags & HOOK_32BIT)
  267. {
  268. // If a 32-bit hook, then the DLL name is saved in an atom.
  269. GetUserAtomName(phk->atomModule, hi.szHookDll);
  270. PathAdjustCase(hi.szHookDll, 0);
  271. }
  272. else
  273. {
  274. // If a 16-bit hook, then the DLL name is saved as hmodule16.
  275. GetModuleFileName16((HMODULE16)phk->hmodOwner, hi.szHookDll, cA(hi.szHookDll));
  276. PathAdjustCase(hi.szHookDll, 1);
  277. }
  278. // Add the hook to the collection of hooks. Don't add the explorer shell to the
  279. // list.
  280. if (hi.iHook != WH_SHELL || lstrcmpi(PathFindFileName(hi.szHookExe), g_tszShell) != 0)
  281. {
  282. SHookItem * pNew = new SHookItem(hi.iHook, hi.szHookDll, hi.szHookExe, m_pList);
  283. if (pNew)
  284. m_pList = pNew;
  285. else
  286. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  287. }
  288. TraceFunctLeave();
  289. }
  290. //-----------------------------------------------------------------------------
  291. // Function pulled in from Dr. Watson.
  292. //
  293. // If f16, then it is a 16-bit thing, and we uppercase it all.
  294. // If !f16, then it is a 32-bit thing, and we uppercase the
  295. // first and downcase the rest.
  296. //
  297. // If the first letter is a DBCS thing, then we don't touch it.
  298. //-----------------------------------------------------------------------------
  299. void NTAPI PathAdjustCase(LPSTR psz, BOOL f16)
  300. {
  301. TraceFunctEnter("PathAdjustCase");
  302. psz = PathFindFileName(psz);
  303. if (f16)
  304. CharUpper(psz);
  305. else if (!IsDBCSLeadByte(*psz))
  306. {
  307. CharUpperBuff(psz, 1);
  308. CharLower(psz+1);
  309. }
  310. TraceFunctLeave();
  311. }