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.

2509 lines
63 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. exts.c
  5. Abstract:
  6. This file implements the debugger extentions for shimeng/shims.
  7. Environment:
  8. User Mode
  9. History:
  10. 03/14/2002 maonis Created
  11. --*/
  12. #include "precomp.h"
  13. extern "C" {
  14. #include "shimdb.h"
  15. }
  16. // We're using the high 4 bits of the TAGID to say what PDB the TAGID is from.
  17. #define PDB_MAIN 0x00000000
  18. #define PDB_TEST 0x10000000
  19. #define PDB_LOCAL 0x20000000
  20. // Used to get the tag ref from the tagid, the low 28 bits
  21. #define TAGREF_STRIP_TAGID 0x0FFFFFFF
  22. // Used to get the PDB from the tagid, the high 4 bits
  23. #define TAGREF_STRIP_PDB 0xF0000000
  24. BOOL
  25. GetData(
  26. IN ULONG64 Address,
  27. IN OUT LPVOID ptr,
  28. IN ULONG size)
  29. {
  30. BOOL b;
  31. ULONG BytesRead = 0;
  32. b = ReadMemory(Address, ptr, size, &BytesRead );
  33. if (!b || BytesRead != size ) {
  34. return FALSE;
  35. }
  36. return TRUE;
  37. }
  38. //void
  39. //GetAndCheckFieldValue(
  40. // IN ULONG64 p,
  41. // IN LPCSTR pszType,
  42. // IN LPCSTR pszField,
  43. // OUT ULONG64 value
  44. // )
  45. #define GET_AND_CHECK_FIELDVALUE(p, Type, Field, value) \
  46. { \
  47. if (GetFieldValue(p, Type, Field, value)) { \
  48. dprintf("failed to get the value of %s for %08x of type %s\n", \
  49. Field, p, Type); \
  50. goto EXIT; \
  51. } \
  52. }
  53. #define GET_AND_CHECK_FIELDVALUE_DATA(p, Type, Field, data, length) \
  54. { \
  55. ULONG64 value; \
  56. GET_AND_CHECK_FIELDVALUE(p, Type, Field, value); \
  57. if (!GetData(value, data, length)) { \
  58. dprintf("failed to read in %d bytes at %08x\n", length, value); \
  59. goto EXIT; \
  60. } \
  61. }
  62. #define GET_AND_CHECK_DATA(value, data,length) \
  63. { \
  64. if (!GetData(value, data, length)) { \
  65. dprintf("failed to read in %d bytes at %08x\n", length, value); \
  66. goto EXIT; \
  67. } \
  68. }
  69. #define GET_SHIMINFO_eInExMode(p, eInExMode) \
  70. GET_AND_CHECK_FIELDVALUE(p, "shimeng!tagSHIMINFO", "eInExMode", eInExMode);
  71. #define GET_SHIMINFO_pFirstExclude(p, pFirstExclude) \
  72. GET_AND_CHECK_FIELDVALUE(p, "shimeng!tagSHIMINFO", "pFirstExclude", pFirstExclude);
  73. #define GET_SHIMINFO_pFirstInclude(p, pFirstInclude) \
  74. GET_AND_CHECK_FIELDVALUE(p, "shimeng!tagSHIMINFO", "pFirstExclude", pFirstInclude);
  75. #define GET_SHIMINFO_wszName(p, wszName) \
  76. if (GetFieldData( \
  77. p, \
  78. "shimeng!tagSHIMINFO", \
  79. "wszName", \
  80. MAX_SHIM_NAME_LEN * sizeof(WCHAR), \
  81. wszName)) \
  82. { \
  83. dprintf("Failed to get the wszName field of shim info %08x\n", p); \
  84. goto EXIT; \
  85. }
  86. #define SHIM_DEBUG_LEVEL_SYMBOL_SUFFIX "!ShimLib::g_DebugLevel"
  87. #define SHIM_DEBUG_LEVEL_TYPE_SUFFIX "!ShimLib::DEBUGLEVEL"
  88. typedef enum tagINEX_MODE {
  89. INEX_UNINITIALIZED = 0,
  90. EXCLUDE_SYSTEM32,
  91. EXCLUDE_ALL,
  92. INCLUDE_ALL
  93. } INEX_MODE, *PINEX_MODE;
  94. #define MAX_SHIM_NAME_LEN 64
  95. #define MAX_SHIM_DLLS 8
  96. #define MAX_SHIM_DEBUGLEVEL_SYMBOL_LEN 64
  97. #define MAX_SHIM_DLL_BASE_NAME_LEN 32
  98. typedef struct tagSHIMDLLINFO {
  99. ULONG64 pDllBase;
  100. char szDllBaseName[MAX_SHIM_DLL_BASE_NAME_LEN];
  101. } SHIMDLLINFO, *PSHIMDLLINFO;
  102. SHIMDLLINFO g_rgShimDllNames[MAX_SHIM_DLLS];
  103. DWORD g_dwShimDlls = 0;
  104. #define MAX_API_NAME_LEN 32
  105. #define MAX_MODULE_NAME_LEN 16
  106. #define MAX_DLL_IMAGE_NAME_LEN 128
  107. char g_szSystem32Dir[MAX_DLL_IMAGE_NAME_LEN] = "";
  108. DWORD g_dwSystem32DirLen = 0;
  109. //
  110. // Valid for the lifetime of the debug session.
  111. //
  112. WINDBG_EXTENSION_APIS ExtensionApis;
  113. //
  114. // Valid only during an extension API call
  115. //
  116. PDEBUG_ADVANCED g_ExtAdvanced;
  117. PDEBUG_CLIENT g_ExtClient;
  118. PDEBUG_CONTROL g_ExtControl;
  119. PDEBUG_DATA_SPACES g_ExtData;
  120. PDEBUG_REGISTERS g_ExtRegisters;
  121. PDEBUG_SYMBOLS2 g_ExtSymbols;
  122. PDEBUG_SYSTEM_OBJECTS3 g_ExtSystem;
  123. // Queries for all debugger interfaces.
  124. extern "C" HRESULT
  125. ExtQuery(PDEBUG_CLIENT Client)
  126. {
  127. HRESULT Status;
  128. if ((Status = Client->QueryInterface(__uuidof(IDebugAdvanced),
  129. (void **)&g_ExtAdvanced)) != S_OK)
  130. {
  131. goto Fail;
  132. }
  133. if ((Status = Client->QueryInterface(__uuidof(IDebugControl),
  134. (void **)&g_ExtControl)) != S_OK)
  135. {
  136. goto Fail;
  137. }
  138. if ((Status = Client->QueryInterface(__uuidof(IDebugDataSpaces),
  139. (void **)&g_ExtData)) != S_OK)
  140. {
  141. goto Fail;
  142. }
  143. if ((Status = Client->QueryInterface(__uuidof(IDebugRegisters),
  144. (void **)&g_ExtRegisters)) != S_OK)
  145. {
  146. goto Fail;
  147. }
  148. if ((Status = Client->QueryInterface(__uuidof(IDebugSymbols2),
  149. (void **)&g_ExtSymbols)) != S_OK)
  150. {
  151. goto Fail;
  152. }
  153. if ((Status = Client->QueryInterface(__uuidof(IDebugSystemObjects),
  154. (void **)&g_ExtSystem)) != S_OK)
  155. {
  156. goto Fail;
  157. }
  158. g_ExtClient = Client;
  159. return S_OK;
  160. Fail:
  161. ExtRelease();
  162. return Status;
  163. }
  164. // Cleans up all debugger interfaces.
  165. void
  166. ExtRelease(void)
  167. {
  168. g_ExtClient = NULL;
  169. EXT_RELEASE(g_ExtAdvanced);
  170. EXT_RELEASE(g_ExtControl);
  171. EXT_RELEASE(g_ExtData);
  172. EXT_RELEASE(g_ExtRegisters);
  173. EXT_RELEASE(g_ExtSymbols);
  174. EXT_RELEASE(g_ExtSystem);
  175. }
  176. // Normal output.
  177. void __cdecl
  178. ExtOut(PCSTR Format, ...)
  179. {
  180. va_list Args;
  181. va_start(Args, Format);
  182. g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
  183. va_end(Args);
  184. }
  185. // Error output.
  186. void __cdecl
  187. ExtErr(PCSTR Format, ...)
  188. {
  189. va_list Args;
  190. va_start(Args, Format);
  191. g_ExtControl->OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
  192. va_end(Args);
  193. }
  194. // Warning output.
  195. void __cdecl
  196. ExtWarn(PCSTR Format, ...)
  197. {
  198. va_list Args;
  199. va_start(Args, Format);
  200. g_ExtControl->OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
  201. va_end(Args);
  202. }
  203. // Verbose output.
  204. void __cdecl
  205. ExtVerb(PCSTR Format, ...)
  206. {
  207. va_list Args;
  208. va_start(Args, Format);
  209. g_ExtControl->OutputVaList(DEBUG_OUTPUT_VERBOSE, Format, Args);
  210. va_end(Args);
  211. }
  212. extern "C"
  213. HRESULT
  214. CALLBACK
  215. DebugExtensionInitialize(PULONG Version, PULONG Flags)
  216. {
  217. IDebugClient *DebugClient;
  218. PDEBUG_CONTROL DebugControl;
  219. HRESULT Hr;
  220. *Version = DEBUG_EXTENSION_VERSION(1, 0);
  221. *Flags = 0;
  222. if ((Hr = DebugCreate(__uuidof(IDebugClient),
  223. (void **)&DebugClient)) != S_OK)
  224. {
  225. return Hr;
  226. }
  227. if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
  228. (void **)&DebugControl)) != S_OK)
  229. {
  230. return Hr;
  231. }
  232. ExtensionApis.nSize = sizeof (ExtensionApis);
  233. if ((Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis)) != S_OK) {
  234. return Hr;
  235. }
  236. DebugControl->Release();
  237. DebugClient->Release();
  238. return S_OK;
  239. }
  240. extern "C"
  241. void
  242. CALLBACK
  243. DebugExtensionNotify(ULONG Notify, ULONG64 Argument)
  244. {
  245. return;
  246. }
  247. extern "C"
  248. void
  249. CALLBACK
  250. DebugExtensionUninitialize(void)
  251. {
  252. return;
  253. }
  254. DllInit(
  255. HANDLE hModule,
  256. DWORD dwReason,
  257. DWORD dwReserved
  258. )
  259. {
  260. switch (dwReason) {
  261. case DLL_THREAD_ATTACH:
  262. break;
  263. case DLL_THREAD_DETACH:
  264. break;
  265. case DLL_PROCESS_DETACH:
  266. break;
  267. case DLL_PROCESS_ATTACH:
  268. break;
  269. }
  270. return TRUE;
  271. }
  272. /*++
  273. Function Description:
  274. This reads a ULONG64 value for the specified variable name from the debugee.
  275. History:
  276. 03/14/2002 maonis Created
  277. --*/
  278. BOOL
  279. GetVarValueULONG64(
  280. IN LPCSTR pszVarName,
  281. OUT ULONG64* pVarValue
  282. )
  283. {
  284. ULONG64 VarAddr = GetExpression(pszVarName);
  285. if (!VarAddr) {
  286. dprintf("Failed to get the address of %s\n", pszVarName);
  287. return FALSE;
  288. }
  289. if (!ReadPointer(VarAddr, pVarValue)) {
  290. dprintf("Failed to read the value of %s\n", pszVarName);
  291. return FALSE;
  292. }
  293. return TRUE;
  294. }
  295. /*++
  296. Function Description:
  297. This writes a ULONG64 value for the specified variable name from the debugee.
  298. History:
  299. 03/14/2002 maonis Created
  300. --*/
  301. BOOL
  302. SetVarValueULONG64(
  303. IN LPCSTR pszVarName,
  304. IN ULONG64 VarValue
  305. )
  306. {
  307. ULONG64 VarAddr = GetExpression(pszVarName);
  308. if (!VarAddr) {
  309. dprintf("Failed to get the address of %s\n", pszVarName);
  310. return FALSE;
  311. }
  312. if (!WritePointer(VarAddr, VarValue)) {
  313. dprintf("Failed to read the value of %s\n", pszVarName);
  314. return FALSE;
  315. }
  316. return TRUE;
  317. }
  318. /*++
  319. Function Description:
  320. Returns a string for the symbol that matches the value at
  321. address dwAddr, or "".
  322. History:
  323. 03/12/2002 maonis Created
  324. --*/
  325. void
  326. PrintSymbolAtAddress(ULONG64 Addr)
  327. {
  328. CHAR szSymbol[128];
  329. ULONG64 Displacement;
  330. GetSymbol(Addr, szSymbol, &Displacement);
  331. if (strcmp(szSymbol, "") != 0) {
  332. dprintf(" (%s", szSymbol);
  333. if (Displacement) {
  334. dprintf("+%08x", Displacement);
  335. }
  336. dprintf(") ");
  337. }
  338. }
  339. BOOL
  340. IsShimInitialized()
  341. {
  342. ULONG64 Value;
  343. BOOL bIsShimInitialized;
  344. if (GetVarValueULONG64("shimeng!g_bShimInitialized", &Value)) {
  345. bIsShimInitialized = (BOOL)Value;
  346. if (bIsShimInitialized) {
  347. //dprintf("Shim has been initialized\n");
  348. return TRUE;
  349. }
  350. }
  351. dprintf("Shim(s) have not been initialized\n");
  352. return FALSE;
  353. }
  354. BOOL
  355. CheckForFullPath(
  356. LPSTR pszPath
  357. )
  358. {
  359. if (pszPath) {
  360. LPSTR pszSlash = strchr(pszPath, L'\\');
  361. if (pszSlash) {
  362. return TRUE;
  363. }
  364. }
  365. dprintf("The module info is not yet fully available to us. Please "
  366. "do .reload -s to load the module info.\n");
  367. return FALSE;
  368. }
  369. /*++
  370. Function Description:
  371. Get the module and the loaded module name. The former is the base name;
  372. the latter has the full path.
  373. Note that if the symbols are not loaded correctly, or if the load module
  374. event hasn't occured, we can't get the full path to some modules. In this
  375. case the user will be prompted to do a .reload -s to make the full path of
  376. the loaded modules available.
  377. --*/
  378. HRESULT
  379. GetDllNamesByIndexAndBase(
  380. ULONG Index,
  381. ULONG64 Base,
  382. LPSTR pszModuleName,
  383. DWORD dwModuleNameSize,
  384. LPSTR pszImageName,
  385. DWORD dwImageNameSize
  386. )
  387. {
  388. HRESULT hr = g_ExtSymbols->GetModuleNames(
  389. Index,
  390. Base,
  391. pszImageName,
  392. dwImageNameSize,
  393. NULL,
  394. pszModuleName,
  395. dwModuleNameSize,
  396. NULL,
  397. NULL,
  398. 0,
  399. NULL);
  400. if (hr == S_OK) {
  401. if (pszImageName && !CheckForFullPath(pszImageName)) {
  402. hr = E_FAIL;
  403. }
  404. } else {
  405. dprintf(
  406. "GetModuleName returned %08x for index %d, base %08x\n",
  407. hr,
  408. Index,
  409. Base);
  410. }
  411. return hr;
  412. }
  413. HRESULT
  414. GetDllNameByOffset(
  415. PVOID pDllBase,
  416. LPSTR pszModuleName,
  417. DWORD dwModuleNameSize,
  418. LPSTR pszImageName,
  419. DWORD dwImageNameSize
  420. )
  421. {
  422. ULONG64 Base = 0;
  423. ULONG Index = 0;
  424. HRESULT hr;
  425. hr = g_ExtSymbols->GetModuleByOffset((ULONG64)pDllBase, 0, &Index, &Base);
  426. if (hr != S_OK) {
  427. dprintf("GetModuleByOffset returned %08x for dll base %08x\n", hr, pDllBase);
  428. return hr;
  429. }
  430. if (Base) {
  431. hr = GetDllNamesByIndexAndBase(
  432. Index,
  433. Base,
  434. pszModuleName,
  435. dwModuleNameSize,
  436. pszImageName,
  437. dwImageNameSize);
  438. } else {
  439. dprintf("GetModuleByOffset succeeded but couldn't get the base address?!\n");
  440. hr = E_UNEXPECTED;
  441. }
  442. return hr;
  443. }
  444. HRESULT
  445. GetDllImageNameByModuleName(
  446. PCSTR pszModuleName, // dll name withOUT extension
  447. PSTR pszImageName,
  448. DWORD dwImageNameSize
  449. )
  450. {
  451. ULONG64 Base = 0;
  452. ULONG Index = 0;
  453. HRESULT hr;
  454. hr = g_ExtSymbols->GetModuleByModuleName(pszModuleName, 0, &Index, &Base);
  455. if (hr != S_OK) {
  456. dprintf("GetModuleByModuleName returned %08x for dll %s\n", hr, pszModuleName);
  457. return hr;
  458. }
  459. if (Base) {
  460. hr = GetDllNamesByIndexAndBase(
  461. Index,
  462. Base,
  463. NULL,
  464. 0,
  465. pszImageName,
  466. dwImageNameSize);
  467. //dprintf("the image name is %s, the size is %d\n", pszImageName, dwImageNameSize);
  468. } else {
  469. dprintf("GetModuleByModuleName succeeded but couldn't get the base address?!\n");
  470. hr = E_UNEXPECTED;
  471. }
  472. return hr;
  473. }
  474. /*++
  475. Function Description:
  476. Prints out the names of the shims applied to this process.
  477. History:
  478. 03/12/2002 maonis Created
  479. --*/
  480. DECLARE_API( shimnames )
  481. {
  482. ULONG64 Value, CurrentShimInfo;
  483. DWORD dwShimsCount = 0;
  484. DWORD dwShimInfoSize = 0;
  485. DWORD i;
  486. ULONG64 pDllBase;
  487. DWORD dwHookedAPIs;
  488. char szShimDllName[MAX_SHIM_DLL_BASE_NAME_LEN];
  489. WCHAR wszShimName[MAX_SHIM_NAME_LEN];
  490. INIT_API();
  491. if (!IsShimInitialized()) {
  492. goto EXIT;
  493. }
  494. if (!GetVarValueULONG64("shimeng!g_dwShimsCount", &Value)) {
  495. dprintf("failed to get the number of shims applied to this process\n");
  496. goto EXIT;
  497. }
  498. //
  499. // The last entry is shimeng.dll which hooks getprocaddress, we don't need
  500. // to show this to the user.
  501. //
  502. dwShimsCount = (DWORD)Value - 1;
  503. dprintf("there are %d shim(s) applied to this process\n", dwShimsCount);
  504. //
  505. // Read the name of the shims.
  506. //
  507. if (!GetVarValueULONG64("shimeng!g_pShimInfo", &Value)) {
  508. dprintf("failed to get the address of shiminfo\n");
  509. goto EXIT;
  510. }
  511. CurrentShimInfo = Value;
  512. dwShimInfoSize = GetTypeSize("shimeng!tagSHIMINFO");
  513. dprintf(" #\t%-64s%-16s%-16s\n",
  514. "shim name",
  515. "shim dll",
  516. "# of hooks");
  517. for (i = 0; i < dwShimsCount; ++i) {
  518. GET_AND_CHECK_FIELDVALUE(
  519. CurrentShimInfo,
  520. "shimeng!tagSHIMINFO",
  521. "pDllBase",
  522. pDllBase);
  523. if (GetDllNameByOffset(
  524. (PVOID)pDllBase,
  525. szShimDllName,
  526. sizeof(szShimDllName),
  527. NULL,
  528. 0) != S_OK) {
  529. goto EXIT;
  530. }
  531. GET_SHIMINFO_wszName(CurrentShimInfo, wszShimName);
  532. GET_AND_CHECK_FIELDVALUE(
  533. CurrentShimInfo,
  534. "shimeng!tagSHIMINFO",
  535. "dwHookedAPIs",
  536. dwHookedAPIs);
  537. dprintf("%2d\t%-64S%-16s%-16d\n\n",
  538. i + 1,
  539. wszShimName,
  540. szShimDllName,
  541. dwHookedAPIs);
  542. CurrentShimInfo += dwShimInfoSize;
  543. }
  544. EXIT:
  545. EXIT_API();
  546. return S_OK;
  547. }
  548. /*++
  549. Function Description:
  550. Given the value of an enum var, prints out the name of that enum value.
  551. eg:
  552. enum TEST {TEST0, TEST1, TEST2};
  553. given 0 we'll print out " ( TEST0 )".
  554. --*/
  555. void
  556. PrintEnumVarName(
  557. LPCSTR pszEnumTypeName,
  558. ULONG ulValueOfEnum
  559. )
  560. {
  561. ULONG64 Module;
  562. ULONG ulTypeId;
  563. CHAR szName[32];
  564. HRESULT hr;
  565. hr = g_ExtSymbols->GetSymbolTypeId(pszEnumTypeName, &ulTypeId, &Module);
  566. if (hr != S_OK) {
  567. dprintf("GetSymbolTypeId returned %08x for %s\n", hr, pszEnumTypeName);
  568. return;
  569. }
  570. hr = g_ExtSymbols->GetConstantName(Module, ulTypeId, ulValueOfEnum, szName, MAX_PATH, NULL);
  571. if (hr != S_OK) {
  572. dprintf("GetConstantName failed to get the name of value %d\n", ulValueOfEnum);
  573. return;
  574. }
  575. dprintf(" ( %s )", szName);
  576. }
  577. /*++
  578. Function Description:
  579. IN OUT ppszArgs - beginning of the arguments. Upon return this is advanced to pass
  580. an argument X (using ' ' as the delimiter).
  581. OUT pszArg - Upon return this points to the beginning of X.
  582. History:
  583. 03/26/2002 maonis Created
  584. --*/
  585. BOOL
  586. GetArg(
  587. PCSTR* ppszArgs,
  588. PCSTR* ppszArg
  589. )
  590. {
  591. BOOL bIsSuccess = FALSE;
  592. PCSTR pszArgs = *ppszArgs;
  593. while (*pszArgs && *pszArgs == ' ') {
  594. ++pszArgs;
  595. }
  596. if (!*pszArgs) {
  597. goto EXIT;
  598. }
  599. *ppszArg = pszArgs;
  600. while (*pszArgs && *pszArgs != ' ') {
  601. ++pszArgs;
  602. }
  603. *ppszArgs = pszArgs;
  604. bIsSuccess = TRUE;
  605. EXIT:
  606. return bIsSuccess;
  607. }
  608. DECLARE_API( debuglevel )
  609. {
  610. ULONG64 DebugLevel;
  611. INIT_API();
  612. if (!GetExpressionEx(args, &DebugLevel, NULL)) {
  613. //
  614. // If there's no args, we print out the current debug level.
  615. //
  616. if (GetVarValueULONG64("shimeng!g_DebugLevel", &DebugLevel)) {
  617. dprintf("The current debug level is %d", DebugLevel);
  618. PrintEnumVarName("shimeng!DEBUGLEVEL", (ULONG)DebugLevel);
  619. dprintf("\n");
  620. } else {
  621. dprintf("Can't find shimeng!g_DebugLevel\n");
  622. }
  623. goto EXIT;
  624. }
  625. if (!DebugLevel) {
  626. if (SetVarValueULONG64("shimeng!g_bDbgPrintEnabled", 0)) {
  627. dprintf("Disabled debug spew\n");
  628. } else {
  629. dprintf("Failed to set shimeng!g_bDbgPrintEnabled to FALSE\n");
  630. }
  631. goto EXIT;
  632. }
  633. if (DebugLevel > 0) {
  634. if (!SetVarValueULONG64("shimeng!g_bDbgPrintEnabled", 1)) {
  635. dprintf("Failed to set shimeng!g_bDbgPrintEnabled to TRUE\n");
  636. goto EXIT;
  637. }
  638. }
  639. if (SetVarValueULONG64("shimeng!g_DebugLevel", DebugLevel)) {
  640. dprintf("Debug level changed to %d", DebugLevel);
  641. PrintEnumVarName("shimeng!DEBUGLEVEL", (ULONG)DebugLevel);
  642. dprintf("\n");
  643. } else {
  644. dprintf("Failed to change the debug level\n");
  645. }
  646. EXIT:
  647. EXIT_API();
  648. return S_OK;
  649. }
  650. BOOL
  651. GetAllShimDllNames()
  652. {
  653. ULONG64 Value, CurrentShimInfo;
  654. DWORD dwShimsCount = 0;
  655. DWORD i, j, dwShimInfoSize;
  656. ULONG64 pDllBase;
  657. BOOL bIsSuccess = FALSE;
  658. g_dwShimDlls = 0;
  659. if (!GetVarValueULONG64("shimeng!g_dwShimsCount", &Value)) {
  660. dprintf("failed to get the number of shims applied to this process\n");
  661. goto EXIT;
  662. }
  663. //
  664. // The last entry is shimeng.dll which hooks getprocaddress, we don't need
  665. // to show this to the user.
  666. //
  667. dwShimsCount = (DWORD)Value - 1;
  668. if (!GetVarValueULONG64("shimeng!g_pShimInfo", &Value)) {
  669. dprintf("failed to get the address of shiminfo\n");
  670. goto EXIT;
  671. }
  672. CurrentShimInfo = Value;
  673. dwShimInfoSize = GetTypeSize("shimeng!tagSHIMINFO");
  674. for (i = 0; i < dwShimsCount; ++i) {
  675. GET_AND_CHECK_FIELDVALUE(
  676. CurrentShimInfo,
  677. "shimeng!tagSHIMINFO",
  678. "pDllBase",
  679. pDllBase);
  680. //
  681. // Check if we've seen this dll yet.
  682. //
  683. for (j = 0; j < g_dwShimDlls; ++j)
  684. {
  685. if (g_rgShimDllNames[j].pDllBase == pDllBase) {
  686. goto NextShim;
  687. }
  688. }
  689. char szShimDllBaseName[MAX_SHIM_DLL_BASE_NAME_LEN];
  690. if (SUCCEEDED(
  691. GetDllNameByOffset(
  692. (PVOID)pDllBase,
  693. szShimDllBaseName,
  694. sizeof(szShimDllBaseName),
  695. NULL,
  696. 0))) {
  697. if (g_dwShimDlls >= MAX_SHIM_DLLS) {
  698. dprintf("%d shim dlls? too many\n", g_dwShimDlls);
  699. } else {
  700. g_rgShimDllNames[g_dwShimDlls].pDllBase = pDllBase;
  701. StringCchCopy(
  702. g_rgShimDllNames[g_dwShimDlls++].szDllBaseName,
  703. MAX_SHIM_DLL_BASE_NAME_LEN,
  704. szShimDllBaseName);
  705. }
  706. } else {
  707. goto EXIT;
  708. }
  709. NextShim:
  710. CurrentShimInfo += dwShimInfoSize;
  711. }
  712. bIsSuccess = TRUE;
  713. EXIT:
  714. if (!bIsSuccess) {
  715. dprintf("Failed to get the debug level symbols for all loaded shim dlls\n");
  716. }
  717. return bIsSuccess;
  718. }
  719. enum SHIM_DEBUG_LEVEL_MODE {
  720. PRINT_SHIM_DEBUG_LEVEL,
  721. CHANGE_SHIM_DEBUG_LEVEL
  722. };
  723. void
  724. ProcessShimDllDebugLevel(
  725. PCSTR pszDllBaseName,
  726. SHIM_DEBUG_LEVEL_MODE eShimDebugLevelMode,
  727. ULONG64 DebugLevel
  728. )
  729. {
  730. char szDebugLevelSymbol[MAX_SHIM_DEBUGLEVEL_SYMBOL_LEN];
  731. char szDebugLevelType[MAX_SHIM_DEBUGLEVEL_SYMBOL_LEN];
  732. StringCchCopy(
  733. szDebugLevelSymbol,
  734. MAX_SHIM_DEBUGLEVEL_SYMBOL_LEN,
  735. pszDllBaseName);
  736. StringCchCat(
  737. szDebugLevelSymbol,
  738. MAX_SHIM_DEBUGLEVEL_SYMBOL_LEN,
  739. SHIM_DEBUG_LEVEL_SYMBOL_SUFFIX);
  740. StringCchCopy(
  741. szDebugLevelType,
  742. MAX_SHIM_DEBUGLEVEL_SYMBOL_LEN,
  743. pszDllBaseName);
  744. StringCchCat(
  745. szDebugLevelType,
  746. MAX_SHIM_DEBUGLEVEL_SYMBOL_LEN,
  747. SHIM_DEBUG_LEVEL_TYPE_SUFFIX);
  748. if (eShimDebugLevelMode == PRINT_SHIM_DEBUG_LEVEL) {
  749. ULONG64 DebugLevelTemp;
  750. if (GetVarValueULONG64(szDebugLevelSymbol, &DebugLevelTemp)) {
  751. dprintf("The debug level for %s.dll is %d", pszDllBaseName, DebugLevelTemp);
  752. PrintEnumVarName(szDebugLevelType, (ULONG)DebugLevelTemp);
  753. dprintf("\n");
  754. } else {
  755. dprintf("Failed to get the value of %s\n", szDebugLevelSymbol);
  756. }
  757. } else if (eShimDebugLevelMode == CHANGE_SHIM_DEBUG_LEVEL) {
  758. if (SetVarValueULONG64(szDebugLevelSymbol, DebugLevel)) {
  759. dprintf(
  760. "Changed the debug level for %s.dll to %d",
  761. pszDllBaseName,
  762. DebugLevel);
  763. PrintEnumVarName(szDebugLevelType, (ULONG)DebugLevel);
  764. dprintf("\n");
  765. } else {
  766. dprintf("Failed to set %s to %d\n", szDebugLevelSymbol, DebugLevel);
  767. }
  768. } else {
  769. dprintf("%d is an invalid arg to ProcessShimDllDebugLevel\n", eShimDebugLevelMode);
  770. }
  771. }
  772. void
  773. PrintAllShimsDebugLevel()
  774. {
  775. for (DWORD i = 0; i < g_dwShimDlls; ++i) {
  776. ProcessShimDllDebugLevel(
  777. g_rgShimDllNames[i].szDllBaseName,
  778. PRINT_SHIM_DEBUG_LEVEL,
  779. 0);
  780. }
  781. }
  782. void
  783. ChangeAllShimsDebugLevel(
  784. ULONG64 DebugLevel)
  785. {
  786. for (DWORD i = 0; i < g_dwShimDlls; ++i) {
  787. ProcessShimDllDebugLevel(
  788. g_rgShimDllNames[i].szDllBaseName,
  789. CHANGE_SHIM_DEBUG_LEVEL,
  790. DebugLevel);
  791. }
  792. }
  793. DECLARE_API( sdebuglevel )
  794. {
  795. ULONG64 DebugLevel;
  796. char szDllBaseName[MAX_SHIM_DLL_BASE_NAME_LEN];
  797. char szDebugLevel[2];
  798. PCSTR pszArg;
  799. INIT_API();
  800. if (!IsShimInitialized()) {
  801. goto EXIT;
  802. }
  803. if (!GetAllShimDllNames()) {
  804. goto EXIT;
  805. }
  806. //
  807. // Get the dll name.
  808. //
  809. if (!GetArg(&args, &pszArg)) {
  810. PrintAllShimsDebugLevel();
  811. goto EXIT;
  812. }
  813. if (isdigit(*pszArg) && ((args - pszArg) == 1)) {
  814. szDebugLevel[0] = *pszArg;
  815. szDebugLevel[1] = 0;
  816. DebugLevel = (ULONG64)atol(szDebugLevel);
  817. ChangeAllShimsDebugLevel(DebugLevel);
  818. goto EXIT;
  819. }
  820. //
  821. // If we get here it means we have a dll base name.
  822. //
  823. StringCchCopyN(szDllBaseName, MAX_SHIM_DLL_BASE_NAME_LEN, pszArg, args - pszArg);
  824. for (DWORD i = 0; i < g_dwShimDlls; ++i)
  825. {
  826. if (!_stricmp(szDllBaseName, g_rgShimDllNames[i].szDllBaseName)) {
  827. if (GetArg(&args, &pszArg)) {
  828. if (isdigit(*pszArg) && ((args - pszArg) == 1)) {
  829. szDebugLevel[0] = *pszArg;
  830. szDebugLevel[1] = 0;
  831. DebugLevel = (ULONG64)atol(szDebugLevel);
  832. ProcessShimDllDebugLevel(
  833. szDllBaseName,
  834. CHANGE_SHIM_DEBUG_LEVEL,
  835. DebugLevel);
  836. } else {
  837. dprintf("You specified an invalid debug level value\n");
  838. }
  839. } else {
  840. ProcessShimDllDebugLevel(
  841. szDllBaseName,
  842. PRINT_SHIM_DEBUG_LEVEL,
  843. 0);
  844. }
  845. goto EXIT;
  846. }
  847. }
  848. if (i == g_dwShimDlls) {
  849. dprintf("%s.dll is not loaded\n", szDllBaseName);
  850. }
  851. EXIT:
  852. EXIT_API();
  853. return S_OK;
  854. }
  855. DECLARE_API( loadshims )
  856. {
  857. INIT_API();
  858. if (GetExpression("shimeng!SeiInit")) {
  859. g_ExtControl->Execute(
  860. DEBUG_OUTCTL_IGNORE,
  861. "g shimeng!SeiInit;g@$ra", // stop right after SeiInit is executed.
  862. DEBUG_EXECUTE_DEFAULT);
  863. } else {
  864. dprintf("wrong symbols for shimeng.dll - is shimeng.dll even loaded?\n");
  865. }
  866. EXIT_API();
  867. return S_OK;
  868. }
  869. /*++
  870. Function Decription:
  871. Given a HOOKAPI pointer pHook, this gets you pHook->pHookEx->pNext.
  872. History:
  873. 03/20/2002 maonis Created
  874. --*/
  875. BOOL
  876. GetNextHook(
  877. ULONG64 Hook,
  878. PULONG64 pNextHook
  879. )
  880. {
  881. BOOL bIsSuccess = FALSE;
  882. ULONG64 HookEx;
  883. ULONG64 NextHook;
  884. GET_AND_CHECK_FIELDVALUE(Hook, "shimeng!tagHOOKAPI", "pHookEx", HookEx);
  885. GET_AND_CHECK_FIELDVALUE(HookEx, "shimeng!tagHOOKAPIEX", "pNext", NextHook);
  886. *pNextHook = NextHook;
  887. bIsSuccess = TRUE;
  888. EXIT:
  889. return bIsSuccess;
  890. }
  891. DECLARE_API( displaychain )
  892. {
  893. ULONG64 Value;
  894. ULONG64 CurrentHookAPIArray;
  895. ULONG64 CurrentHookAPI;
  896. ULONG64 CurrentShimInfo;
  897. ULONG64 Hook;
  898. ULONG64 NextHook;
  899. ULONG64 HookEx;
  900. ULONG64 HookAddress;
  901. ULONG64 PfnNew;
  902. ULONG64 PfnOld;
  903. ULONG64 TopOfChain;
  904. DWORD i, j;
  905. DWORD dwHookAPISize;
  906. DWORD dwShimInfoSize;
  907. DWORD dwHookedAPIs;
  908. DWORD dwShimsCount;
  909. INIT_API();
  910. if (!IsShimInitialized()) {
  911. goto EXIT;
  912. }
  913. if (!GetExpressionEx(args, &HookAddress, NULL)) {
  914. dprintf("Usage: !displaychain address_to_check\n");
  915. goto EXIT;
  916. }
  917. if (!GetVarValueULONG64("shimeng!g_dwShimsCount", &Value)) {
  918. dprintf("failed to get the number of shims applied to this process\n");
  919. goto EXIT;
  920. }
  921. dwShimsCount = (DWORD)Value - 1;
  922. if (!GetVarValueULONG64("shimeng!g_pShimInfo", &Value)) {
  923. dprintf("failed to get the address of shiminfo\n");
  924. goto EXIT;
  925. }
  926. CurrentShimInfo = Value;
  927. dwShimInfoSize = GetTypeSize("shimeng!tagSHIMINFO");
  928. dwHookAPISize = GetTypeSize("shimeng!tagHOOKAPI");
  929. if (!dwHookAPISize) {
  930. dprintf("failed to get the HOOKAPI size\n");
  931. goto EXIT;
  932. }
  933. if (!GetVarValueULONG64("shimeng!g_pHookArray", &Value)) {
  934. dprintf("failed to get the address of shiminfo\n");
  935. goto EXIT;
  936. }
  937. CurrentHookAPIArray = Value;
  938. for (i = 0; i < dwShimsCount; ++i) {
  939. //
  940. // Get the number of hooks this shim has.
  941. //
  942. if (GetFieldValue(CurrentShimInfo, "shimeng!tagSHIMINFO", "dwHookedAPIs", dwHookedAPIs)) {
  943. dprintf("failed to get the number of hooked APIs for shim #%d\n",
  944. i);
  945. goto EXIT;
  946. }
  947. if (!ReadPointer(CurrentHookAPIArray, &CurrentHookAPI)) {
  948. dprintf("failed to get the begining of hook api array\n");
  949. goto EXIT;
  950. }
  951. for (j = 0; j < dwHookedAPIs; ++j) {
  952. GET_AND_CHECK_FIELDVALUE(CurrentHookAPI, "shimeng!tagHOOKAPI", "pfnNew", PfnNew);
  953. if (HookAddress == PfnNew) {
  954. //
  955. // We found the address, now get top of the chain so we can print it.
  956. //
  957. GET_AND_CHECK_FIELDVALUE(CurrentHookAPI, "shimeng!tagHOOKAPI", "pHookEx", HookEx);
  958. GET_AND_CHECK_FIELDVALUE(HookEx, "shimeng!tagHOOKAPIEX", "pTopOfChain", TopOfChain);
  959. //dprintf("top of chain is %08x\n", TopOfChain);
  960. Hook = TopOfChain;
  961. GET_AND_CHECK_FIELDVALUE(Hook, "shimeng!tagHOOKAPI", "pfnNew", PfnNew);
  962. dprintf(" %08x", PfnNew);
  963. PrintSymbolAtAddress(PfnNew);
  964. dprintf("\n");
  965. while (TRUE) {
  966. if (!GetNextHook(Hook, &NextHook)) {
  967. dprintf("failed to get next hook\n");
  968. goto EXIT;
  969. }
  970. if (!NextHook) {
  971. //
  972. // We are at the end of the chain, get the original API address.
  973. //
  974. GET_AND_CHECK_FIELDVALUE(Hook, "shimeng!tagHOOKAPI", "pfnOld", PfnOld);
  975. dprintf(" -> %08x", PfnOld);
  976. PrintSymbolAtAddress(PfnOld);
  977. dprintf("\n");
  978. break;
  979. }
  980. Hook = NextHook;
  981. if (Hook) {
  982. GET_AND_CHECK_FIELDVALUE(Hook, "shimeng!tagHOOKAPI", "pfnNew", PfnNew);
  983. dprintf(" -> %08x", PfnNew);
  984. PrintSymbolAtAddress(PfnNew);
  985. dprintf("\n");
  986. }
  987. }
  988. dprintf("\n");
  989. goto EXIT;
  990. }
  991. CurrentHookAPI += dwHookAPISize;
  992. }
  993. CurrentShimInfo += dwShimInfoSize;
  994. CurrentHookAPIArray += sizeof(ULONG_PTR);
  995. }
  996. EXIT:
  997. EXIT_API();
  998. return S_OK;
  999. }
  1000. BOOL
  1001. CheckSymbols(
  1002. LPCSTR pszSymbolName
  1003. )
  1004. {
  1005. ULONG64 Value;
  1006. HRESULT hr = g_ExtSymbols->GetOffsetByName(pszSymbolName, &Value);
  1007. return (hr == S_OK);
  1008. }
  1009. #define CHECKSYM(s) if (!CheckSymbols(s)) bIsSymbolGood = FALSE; goto EXIT;
  1010. #define CHECKTYPE(t) if (!GetTypeSize(t)) bIsSymbolGood = FALSE; goto EXIT;
  1011. DECLARE_API ( shimengsym )
  1012. {
  1013. INIT_API();
  1014. BOOL bIsSymbolGood = TRUE;
  1015. //
  1016. // Check a few important structures and stuff.
  1017. //
  1018. CHECKSYM("shimeng!SeiInit");
  1019. CHECKSYM("shimeng!g_pHookArray");
  1020. CHECKSYM("shimeng!g_pShiminfo");
  1021. CHECKSYM("shimeng!g_dwShimsCount");
  1022. CHECKTYPE("shimeng!tagHOOKAPI");
  1023. CHECKTYPE("shimeng!tagSHIMINFO");
  1024. EXIT:
  1025. EXIT_API();
  1026. if (bIsSymbolGood) {
  1027. dprintf("shimeng symbols look good\n");
  1028. } else {
  1029. dprintf("You have wrong symbols for shimeng\n");
  1030. }
  1031. return S_OK;
  1032. }
  1033. DECLARE_API ( displayhooks )
  1034. {
  1035. ULONG64 Value;
  1036. ULONG64 CurrentHookAPIArray;
  1037. ULONG64 CurrentHookAPI;
  1038. ULONG64 CurrentShimInfo;
  1039. ULONG64 FunctionName;
  1040. ULONG64 ModuleName;
  1041. ULONG64 ShimName;
  1042. ULONG64 PfnNew;
  1043. DWORD i, j;
  1044. DWORD dwHookAPISize;
  1045. DWORD dwShimInfoSize;
  1046. DWORD dwHookedAPIs;
  1047. DWORD dwShimsCount;
  1048. DWORD dwBytesRead;
  1049. char szAPIName[MAX_API_NAME_LEN];
  1050. char szModuleName[MAX_MODULE_NAME_LEN];
  1051. WCHAR wszShimName[MAX_SHIM_NAME_LEN];
  1052. char szShimName[MAX_SHIM_NAME_LEN];
  1053. LPCSTR pszShimName = args;
  1054. INIT_API();
  1055. if (!IsShimInitialized()) {
  1056. goto EXIT;
  1057. }
  1058. if (!pszShimName || !*pszShimName) {
  1059. dprintf("Usage: !displayhooks shimname\n");
  1060. goto EXIT;
  1061. }
  1062. if (!GetVarValueULONG64("shimeng!g_dwShimsCount", &Value)) {
  1063. dprintf("failed to get the number of shims applied to this process\n");
  1064. goto EXIT;
  1065. }
  1066. dwShimsCount = (DWORD)Value - 1;
  1067. if (!GetVarValueULONG64("shimeng!g_pShimInfo", &Value)) {
  1068. dprintf("failed to get the address of shiminfo\n");
  1069. goto EXIT;
  1070. }
  1071. CurrentShimInfo = Value;
  1072. dwShimInfoSize = GetTypeSize("shimeng!tagSHIMINFO");
  1073. dwHookAPISize = GetTypeSize("shimeng!tagHOOKAPI");
  1074. if (!dwHookAPISize) {
  1075. dprintf("failed to get the HOOKAPI size\n");
  1076. goto EXIT;
  1077. }
  1078. if (!GetVarValueULONG64("shimeng!g_pHookArray", &Value)) {
  1079. dprintf("failed to get the address of shiminfo\n");
  1080. goto EXIT;
  1081. }
  1082. CurrentHookAPIArray = Value;
  1083. dprintf("%-8s%-32s%-16s %8s\n",
  1084. "hook #",
  1085. "hook name",
  1086. "dll it's in",
  1087. "new addr");
  1088. for (i = 0; i < dwShimsCount; ++i) {
  1089. //
  1090. // Get the shim name.
  1091. //
  1092. if (GetFieldValue(CurrentShimInfo, "shimeng!tagSHIMINFO", "wszName", wszShimName)) {
  1093. dprintf("failed to get the shim name address for shim #%d\n",
  1094. i);
  1095. goto EXIT;
  1096. }
  1097. if (!WideCharToMultiByte(CP_ACP, 0, wszShimName, -1, szShimName, MAX_SHIM_NAME_LEN, NULL, NULL)) {
  1098. dprintf("failed to convert %S to ansi: %d\n", wszShimName, GetLastError());
  1099. goto EXIT;
  1100. }
  1101. if (lstrcmpi(szShimName, pszShimName)) {
  1102. goto TryNext;
  1103. }
  1104. //
  1105. // Get the number of hooks this shim has.
  1106. //
  1107. if (GetFieldValue(CurrentShimInfo, "shimeng!tagSHIMINFO", "dwHookedAPIs", dwHookedAPIs)) {
  1108. dprintf("failed to get the number of hooked APIs for shim #%d\n",
  1109. i);
  1110. goto EXIT;
  1111. }
  1112. if (!ReadPointer(CurrentHookAPIArray, &CurrentHookAPI)) {
  1113. dprintf("failed to get the begining of hook api array\n");
  1114. goto EXIT;
  1115. }
  1116. for (j = 0; j < dwHookedAPIs; ++j) {
  1117. GET_AND_CHECK_FIELDVALUE(CurrentHookAPI, "shimeng!tagHOOKAPI", "pszFunctionName", FunctionName);
  1118. if (!GetData(FunctionName, szAPIName, MAX_API_NAME_LEN)) {
  1119. dprintf("failed to read in the API name at %08x\n", FunctionName);
  1120. goto EXIT;
  1121. }
  1122. GET_AND_CHECK_FIELDVALUE(CurrentHookAPI, "shimeng!tagHOOKAPI", "pszModule", ModuleName);
  1123. if (!GetData(ModuleName, szModuleName, MAX_MODULE_NAME_LEN)) {
  1124. dprintf("failed to read in the module name at %08x\n", ModuleName);
  1125. goto EXIT;
  1126. }
  1127. GET_AND_CHECK_FIELDVALUE(CurrentHookAPI, "shimeng!tagHOOKAPI", "pfnNew", PfnNew);
  1128. dprintf("%-8d%-32s%-16s %08x\n",
  1129. j + 1,
  1130. szAPIName,
  1131. szModuleName,
  1132. PfnNew);
  1133. CurrentHookAPI += dwHookAPISize;
  1134. }
  1135. TryNext:
  1136. CurrentShimInfo += dwShimInfoSize;
  1137. CurrentHookAPIArray += sizeof(ULONG_PTR);
  1138. }
  1139. EXIT:
  1140. EXIT_API();
  1141. return S_OK;
  1142. }
  1143. /*++
  1144. Function Description:
  1145. This is a helper function for IsExcluded.
  1146. History:
  1147. 03/26/2002 maonis Created
  1148. --*/
  1149. BOOL
  1150. GetModuleNameAndAPIAddress(
  1151. IN ULONG64 pHook,
  1152. OUT ULONG64* pFunctionAddress,
  1153. IN OUT LPSTR szModuleName
  1154. )
  1155. {
  1156. BOOL bIsSuccess = FALSE;
  1157. ULONG64 FunctionAddress;
  1158. GET_AND_CHECK_FIELDVALUE(
  1159. pHook,
  1160. "shimeng!tagHOOKAPI",
  1161. "pszFunctionName",
  1162. FunctionAddress);
  1163. GET_AND_CHECK_FIELDVALUE_DATA(
  1164. pHook,
  1165. "shimeng!tagHOOKAPI",
  1166. "pszModule",
  1167. szModuleName,
  1168. MAX_MODULE_NAME_LEN);
  1169. *pFunctionAddress = FunctionAddress;
  1170. bIsSuccess = TRUE;
  1171. EXIT:
  1172. return bIsSuccess;
  1173. }
  1174. /*++
  1175. Function Description:
  1176. This is modified from the SeiIsExcluded function in
  1177. %sdxroot%\windows\appcompat\shimengines\engiat\shimeng.c
  1178. --*/
  1179. BOOL
  1180. IsExcluded(
  1181. IN LPCSTR pszModule, // The module to test for exclusion.
  1182. IN ULONG64 pTopHookAPI, // The HOOKAPI for which we test for exclusion.
  1183. IN BOOL bInSystem32 // Whether the module is located in the System32 directory.
  1184. )
  1185. {
  1186. BOOL bExclude = TRUE;
  1187. BOOL bShimWantsToExclude = FALSE; // was there a shim that wanted to exclude?
  1188. ULONG64 pHook = pTopHookAPI;
  1189. ULONG64 pHookEx;
  1190. ULONG64 pShimInfo, pCurrentShimInfo;
  1191. ULONG64 pIncludeMod;
  1192. ULONG64 pExcludeMod;
  1193. ULONG64 eInExMode;
  1194. ULONG64 ModuleName;
  1195. ULONG64 FunctionName;
  1196. ULONG64 Temp;
  1197. DWORD dwCounter;
  1198. char szCurrentModuleName[MAX_MODULE_NAME_LEN];
  1199. char szCurrentAPIName[MAX_API_NAME_LEN];
  1200. WCHAR wszName[MAX_SHIM_NAME_LEN];
  1201. DWORD dwShimInfoSize = GetTypeSize("shimeng!tagSHIMINFO");
  1202. if (!GetVarValueULONG64("shimeng!g_pShimInfo", &pShimInfo)) {
  1203. dprintf("failed to get the address of shiminfo\n");
  1204. goto EXIT;
  1205. }
  1206. //
  1207. // The current process is to only exclude a chain if every shim in the chain wants to
  1208. // exclude. If one shim needs to be included, the whole chain is included.
  1209. //
  1210. while (pHook) {
  1211. GET_AND_CHECK_FIELDVALUE(pHook, "shimeng!tagHOOKAPI", "pHookEx", pHookEx);
  1212. if (!pHookEx) {
  1213. break;
  1214. }
  1215. GET_AND_CHECK_FIELDVALUE(pHookEx, "shimeng!tagHOOKAPIEX", "dwShimID", dwCounter);
  1216. //if (!GetData(pShimInfo + dwShimInfoSize * dwCounter, &si, dwShimInfoSize)) {
  1217. // dprintf("Failed to get the shiminfo for shim #%d\n", dwCounter + 1);
  1218. // goto EXIT;
  1219. //}
  1220. pCurrentShimInfo = pShimInfo + dwShimInfoSize * dwCounter;
  1221. GET_SHIMINFO_eInExMode(pCurrentShimInfo, eInExMode);
  1222. GET_SHIMINFO_wszName(pCurrentShimInfo, wszName);
  1223. switch (eInExMode) {
  1224. case INCLUDE_ALL:
  1225. {
  1226. //
  1227. // We include everything except what's in the exclude list.
  1228. //
  1229. GET_SHIMINFO_pFirstExclude(pCurrentShimInfo, pExcludeMod);
  1230. while (pExcludeMod != NULL) {
  1231. GET_AND_CHECK_FIELDVALUE_DATA(
  1232. pExcludeMod,
  1233. "shimeng!tagINEXMOD",
  1234. "pszModule",
  1235. szCurrentModuleName,
  1236. MAX_MODULE_NAME_LEN);
  1237. if (lstrcmpi(szCurrentModuleName, pszModule) == 0) {
  1238. if (!GetModuleNameAndAPIAddress(pTopHookAPI, &FunctionName, szCurrentModuleName)) {
  1239. goto EXIT;
  1240. }
  1241. if ((ULONG_PTR)FunctionName < 0x0000FFFF) {
  1242. dprintf(
  1243. "Module \"%s\" excluded for shim %S, API \"%s!#%d\","
  1244. "because it is in the exclude list (MODE: IA).\n",
  1245. pszModule,
  1246. wszName,
  1247. szCurrentModuleName,
  1248. FunctionName);
  1249. } else {
  1250. GET_AND_CHECK_DATA(FunctionName, szCurrentAPIName, MAX_API_NAME_LEN);
  1251. dprintf(
  1252. "Module \"%s\" excluded for shim %S, API \"%s!%s\","
  1253. "because it is in the exclude list (MODE: IA).\n",
  1254. pszModule,
  1255. wszName,
  1256. szCurrentModuleName,
  1257. szCurrentAPIName);
  1258. }
  1259. //
  1260. // this wants to be excluded, so we go to the next
  1261. // shim, and see if it wants to be included
  1262. //
  1263. bShimWantsToExclude = TRUE;
  1264. goto nextShim;
  1265. }
  1266. Temp = pExcludeMod;
  1267. GET_AND_CHECK_FIELDVALUE(Temp, "shimeng!tagINEXMOD", "pNext", pExcludeMod);
  1268. }
  1269. //
  1270. // we should include this shim, and therefore, the whole chain
  1271. //
  1272. bExclude = FALSE;
  1273. goto EXIT;
  1274. break;
  1275. }
  1276. case EXCLUDE_SYSTEM32:
  1277. {
  1278. //
  1279. // In this case, we first check the include list,
  1280. // then exclude it if it's in System32, then exclude it if
  1281. // it's in the exclude list.
  1282. //
  1283. GET_SHIMINFO_pFirstInclude(pCurrentShimInfo, pIncludeMod);
  1284. GET_SHIMINFO_pFirstExclude(pCurrentShimInfo, pExcludeMod);
  1285. //
  1286. // First, check the include list.
  1287. //
  1288. while (pIncludeMod != NULL) {
  1289. GET_AND_CHECK_FIELDVALUE_DATA(
  1290. pIncludeMod,
  1291. "shimeng!tagINEXMOD",
  1292. "pszModule",
  1293. szCurrentModuleName,
  1294. MAX_MODULE_NAME_LEN);
  1295. if (lstrcmpi(szCurrentModuleName, pszModule) == 0) {
  1296. //
  1297. // we should include this shim, and therefore, the whole chain
  1298. //
  1299. bExclude = FALSE;
  1300. goto EXIT;
  1301. }
  1302. Temp = pIncludeMod;
  1303. GET_AND_CHECK_FIELDVALUE(Temp, "shimeng!tagINEXMOD", "pNext", pIncludeMod);
  1304. }
  1305. //
  1306. // it wasn't in the include list, so is it in System32?
  1307. //
  1308. if (bInSystem32) {
  1309. if (!GetModuleNameAndAPIAddress(pTopHookAPI, &FunctionName, szCurrentModuleName)) {
  1310. goto EXIT;
  1311. }
  1312. if ((ULONG_PTR)FunctionName < 0x0000FFFF) {
  1313. dprintf(
  1314. "module \"%s\" excluded for shim %S, API \"%s!#%d\", because it is in System32.\n",
  1315. pszModule,
  1316. wszName,
  1317. szCurrentModuleName,
  1318. FunctionName);
  1319. } else {
  1320. GET_AND_CHECK_DATA(FunctionName, szCurrentAPIName, MAX_API_NAME_LEN);
  1321. dprintf(
  1322. "module \"%s\" excluded for shim %S, API \"%s!%s\", because it is in System32.\n",
  1323. pszModule,
  1324. wszName,
  1325. szCurrentModuleName,
  1326. szCurrentAPIName);
  1327. }
  1328. //
  1329. // this wants to be excluded, so we go to the next
  1330. // shim, and see if it wants to be included
  1331. //
  1332. bShimWantsToExclude = TRUE;
  1333. goto nextShim;
  1334. }
  1335. //
  1336. // it wasn't in System32, so is it in the exclude list?
  1337. //
  1338. while (pExcludeMod != NULL) {
  1339. if (!GetModuleNameAndAPIAddress(pTopHookAPI, &FunctionName, szCurrentModuleName)) {
  1340. goto EXIT;
  1341. }
  1342. GET_AND_CHECK_FIELDVALUE_DATA(
  1343. pExcludeMod,
  1344. "shimeng!tagINEXMOD",
  1345. "pszModule",
  1346. szCurrentModuleName,
  1347. MAX_MODULE_NAME_LEN);
  1348. if (lstrcmpi(szCurrentModuleName, pszModule) == 0) {
  1349. if ((ULONG_PTR)FunctionName < 0x0000FFFF) {
  1350. dprintf(
  1351. "module \"%s\" excluded for shim %S, API \"%s!#%d\", because it is in the exclude list (MODE: ES).\n",
  1352. pszModule,
  1353. wszName,
  1354. szCurrentModuleName,
  1355. FunctionName);
  1356. } else {
  1357. GET_AND_CHECK_DATA(FunctionName, szCurrentAPIName, MAX_API_NAME_LEN);
  1358. dprintf(
  1359. "module \"%s\" excluded for shim %S, API \"%s!%s\", because it is in the exclude list (MODE: ES).\n",
  1360. pszModule,
  1361. wszName,
  1362. szCurrentModuleName,
  1363. szCurrentAPIName);
  1364. }
  1365. //
  1366. // this wants to be excluded, so we go to the next
  1367. // shim, and see if it wants to be included
  1368. //
  1369. bShimWantsToExclude = TRUE;
  1370. goto nextShim;
  1371. }
  1372. Temp = pExcludeMod;
  1373. GET_AND_CHECK_FIELDVALUE(Temp, "shimeng!tagINEXMOD", "pNext", pExcludeMod);
  1374. }
  1375. //
  1376. // we should include this shim, and therefore, the whole chain
  1377. //
  1378. bExclude = FALSE;
  1379. goto EXIT;
  1380. break;
  1381. }
  1382. case EXCLUDE_ALL:
  1383. {
  1384. //
  1385. // We exclude everything except what is in the include list.
  1386. //
  1387. GET_SHIMINFO_pFirstInclude(pCurrentShimInfo, pIncludeMod);
  1388. while (pIncludeMod != NULL) {
  1389. GET_AND_CHECK_FIELDVALUE_DATA(
  1390. pIncludeMod,
  1391. "shimeng!tagINEXMOD",
  1392. "pszModule",
  1393. szCurrentModuleName,
  1394. MAX_MODULE_NAME_LEN);
  1395. if (lstrcmpi(szCurrentModuleName, pszModule) == 0) {
  1396. //
  1397. // we should include this shim, and therefore, the whole chain
  1398. //
  1399. bExclude = FALSE;
  1400. goto EXIT;
  1401. }
  1402. Temp = pIncludeMod;
  1403. GET_AND_CHECK_FIELDVALUE(Temp, "shimeng!tagINEXMOD", "pNext", pIncludeMod);
  1404. }
  1405. if (!GetModuleNameAndAPIAddress(pTopHookAPI, &FunctionName, szCurrentModuleName)) {
  1406. goto EXIT;
  1407. }
  1408. if ((ULONG_PTR)FunctionName < 0x0000FFFF) {
  1409. dprintf(
  1410. "module \"%s\" excluded for shim %S, API \"%s!#%d\", because it is not in the include list (MODE: EA).\n",
  1411. pszModule,
  1412. wszName,
  1413. szCurrentModuleName,
  1414. FunctionName);
  1415. } else {
  1416. GET_AND_CHECK_DATA(FunctionName, szCurrentAPIName, MAX_API_NAME_LEN);
  1417. dprintf(
  1418. "module \"%s\" excluded for shim %S, API \"%s!%s\", because it is not in the include list (MODE: EA).\n",
  1419. pszModule,
  1420. wszName,
  1421. szCurrentModuleName,
  1422. szCurrentAPIName);
  1423. }
  1424. //
  1425. // this wants to be excluded, so we go to the next
  1426. // shim, and see if it wants to be included
  1427. //
  1428. bShimWantsToExclude = TRUE;
  1429. goto nextShim;
  1430. break;
  1431. }
  1432. }
  1433. nextShim:
  1434. Temp = pHook;
  1435. if (!GetNextHook(Temp, &pHook)) {
  1436. dprintf("failed to get next hook\n");
  1437. goto EXIT;
  1438. }
  1439. }
  1440. EXIT:
  1441. if (!bExclude && bShimWantsToExclude) {
  1442. if (GetModuleNameAndAPIAddress(pTopHookAPI, &FunctionName, szCurrentModuleName)) {
  1443. if ((ULONG_PTR)FunctionName < 0x0000FFFF) {
  1444. dprintf(
  1445. "Module \"%s\" mixed inclusion/exclusion for "
  1446. "API \"%s!#%d\". Included.\n",
  1447. pszModule,
  1448. szCurrentModuleName,
  1449. FunctionName);
  1450. } else {
  1451. GET_AND_CHECK_DATA(FunctionName, szCurrentAPIName, MAX_API_NAME_LEN);
  1452. dprintf(
  1453. "Module \"%s\" mixed inclusion/exclusion for "
  1454. "API \"%s!%s\". Included.\n",
  1455. pszModule,
  1456. szCurrentModuleName,
  1457. szCurrentAPIName);
  1458. }
  1459. }
  1460. }
  1461. return bExclude;
  1462. }
  1463. /*++
  1464. Function Decription:
  1465. The way we get the system32 directory is just to get the loaded image name for kernel32.dll.
  1466. History:
  1467. 03/26/2002 maonis Created
  1468. --*/
  1469. BOOL
  1470. GetSystem32Directory()
  1471. {
  1472. if (g_dwSystem32DirLen) {
  1473. return TRUE;
  1474. }
  1475. BOOL bIsSuccess = FALSE;
  1476. char szImageName[MAX_DLL_IMAGE_NAME_LEN];
  1477. PSTR pszBaseDllName = NULL;
  1478. DWORD dwLen = 0;
  1479. if (GetDllImageNameByModuleName("kernel32", szImageName, MAX_DLL_IMAGE_NAME_LEN) != S_OK) {
  1480. dprintf("can't get the dll path for kernel32.dll!!\n");
  1481. goto EXIT;
  1482. }
  1483. //
  1484. // Get the beginning of the base dll name.
  1485. //
  1486. dwLen = lstrlen(szImageName) - 1;
  1487. pszBaseDllName = szImageName + dwLen;
  1488. while (*pszBaseDllName && *pszBaseDllName != '\\') {
  1489. --pszBaseDllName;
  1490. }
  1491. if (!*pszBaseDllName) {
  1492. dprintf("%s doesn't contain a full path\n", szImageName);
  1493. goto EXIT;
  1494. }
  1495. ++pszBaseDllName;
  1496. *pszBaseDllName = '\0';
  1497. StringCchCopy(g_szSystem32Dir, MAX_DLL_IMAGE_NAME_LEN, szImageName);
  1498. g_dwSystem32DirLen = (DWORD)(pszBaseDllName - szImageName);
  1499. bIsSuccess = TRUE;
  1500. EXIT:
  1501. return bIsSuccess;
  1502. }
  1503. BOOL
  1504. IsInSystem32(
  1505. PCSTR szModuleName,
  1506. BOOL* pbInSystem32
  1507. )
  1508. {
  1509. BOOL bIsSuccess = FALSE;
  1510. char szImageName[MAX_DLL_IMAGE_NAME_LEN];
  1511. if (!GetSystem32Directory()) {
  1512. goto EXIT;
  1513. }
  1514. if (GetDllImageNameByModuleName(szModuleName, szImageName, MAX_DLL_IMAGE_NAME_LEN) != S_OK) {
  1515. goto EXIT;
  1516. }
  1517. dprintf("the image name is %s\n", szImageName);
  1518. *pbInSystem32 = !_strnicmp(g_szSystem32Dir, szImageName, g_dwSystem32DirLen);
  1519. dprintf("%s %s in system32\n", szModuleName, (*pbInSystem32 ? "is" : "is not"));
  1520. bIsSuccess = TRUE;
  1521. EXIT:
  1522. return bIsSuccess;
  1523. }
  1524. /*++
  1525. Function Description:
  1526. !checkinex dllname apiname
  1527. dllname is without the .dll extention. eg:
  1528. !checkinex kernel32 createfilea
  1529. History:
  1530. 03/26/2002 maonis Created
  1531. --*/
  1532. DECLARE_API ( checkex )
  1533. {
  1534. ULONG64 DllName;
  1535. char szAPIName[MAX_API_NAME_LEN];
  1536. char szCurrentAPIName[MAX_API_NAME_LEN];
  1537. char szModuleName[MAX_MODULE_NAME_LEN];
  1538. PCSTR pszModuleName, pszAPIName;
  1539. BOOL bInSystem32 = FALSE;
  1540. ULONG64 Value;
  1541. ULONG64 CurrentHookAPIArray;
  1542. ULONG64 CurrentHookAPI;
  1543. ULONG64 CurrentShimInfo;
  1544. ULONG64 FunctionName;
  1545. ULONG64 Hook;
  1546. ULONG64 NextHook;
  1547. ULONG64 HookEx;
  1548. ULONG64 HookAddress;
  1549. ULONG64 PfnNew;
  1550. ULONG64 PfnOld;
  1551. ULONG64 TopOfChain;
  1552. DWORD i, j;
  1553. DWORD dwHookAPISize;
  1554. DWORD dwShimInfoSize;
  1555. DWORD dwHookedAPIs;
  1556. DWORD dwShimsCount;
  1557. INIT_API();
  1558. if (!IsShimInitialized()) {
  1559. goto EXIT;
  1560. }
  1561. //
  1562. // Get the dll name.
  1563. //
  1564. if (!GetArg(&args, &pszModuleName)) {
  1565. dprintf("Usage: !checkinex dllname apiname\n");
  1566. goto EXIT;
  1567. }
  1568. StringCchCopyN(szModuleName, MAX_MODULE_NAME_LEN, pszModuleName, args - pszModuleName);
  1569. //
  1570. // Get the API name.
  1571. //
  1572. if (!GetArg(&args, &pszAPIName)) {
  1573. dprintf("Usage: !checkinex dllname apiname\n");
  1574. goto EXIT;
  1575. }
  1576. StringCchCopyN(szAPIName, MAX_API_NAME_LEN, pszAPIName, args - pszAPIName);
  1577. //
  1578. // Check to see if it's in system32.
  1579. //
  1580. if (!IsInSystem32(szModuleName, &bInSystem32)) {
  1581. dprintf("Failed to determine if %s is in system32 or not\n", szModuleName);
  1582. goto EXIT;
  1583. }
  1584. //
  1585. // Get the chain with this API.
  1586. //
  1587. if (!GetVarValueULONG64("shimeng!g_dwShimsCount", &Value)) {
  1588. dprintf("failed to get the number of shims applied to this process\n");
  1589. goto EXIT;
  1590. }
  1591. dwShimsCount = (DWORD)Value - 1;
  1592. if (!GetVarValueULONG64("shimeng!g_pShimInfo", &Value)) {
  1593. dprintf("failed to get the address of shiminfo\n");
  1594. goto EXIT;
  1595. }
  1596. CurrentShimInfo = Value;
  1597. dwShimInfoSize = GetTypeSize("shimeng!tageSHIMINFO");
  1598. dwHookAPISize = GetTypeSize("shimeng!tagHOOKAPI");
  1599. if (!dwHookAPISize) {
  1600. dprintf("failed to get the HOOKAPI size\n");
  1601. goto EXIT;
  1602. }
  1603. if (!GetVarValueULONG64("shimeng!g_pHookArray", &Value)) {
  1604. dprintf("failed to get the address of shiminfo\n");
  1605. goto EXIT;
  1606. }
  1607. CurrentHookAPIArray = Value;
  1608. for (i = 0; i < dwShimsCount; ++i) {
  1609. //
  1610. // Get the number of hooks this shim has.
  1611. //
  1612. if (GetFieldValue(CurrentShimInfo, "shimeng!tagSHIMINFO", "dwHookedAPIs", dwHookedAPIs)) {
  1613. dprintf("failed to get the number of hooked APIs for shim #%d\n",
  1614. i);
  1615. goto EXIT;
  1616. }
  1617. if (!ReadPointer(CurrentHookAPIArray, &CurrentHookAPI)) {
  1618. dprintf("failed to get the begining of hook api array\n");
  1619. goto EXIT;
  1620. }
  1621. for (j = 0; j < dwHookedAPIs; ++j) {
  1622. GET_AND_CHECK_FIELDVALUE(CurrentHookAPI, "shimeng!tagHOOKAPI", "pszFunctionName", FunctionName);
  1623. if (!GetData(FunctionName, szCurrentAPIName, MAX_API_NAME_LEN)) {
  1624. dprintf("failed to read in the API name at %08x\n", FunctionName);
  1625. }
  1626. if (!lstrcmpi(szAPIName, szCurrentAPIName)) {
  1627. //
  1628. // We found the API, now get top of the chain.
  1629. //
  1630. GET_AND_CHECK_FIELDVALUE(CurrentHookAPI, "shimeng!tagHOOKAPI", "pHookEx", HookEx);
  1631. GET_AND_CHECK_FIELDVALUE(HookEx, "shimeng!tagHOOKAPIEX", "pTopOfChain", TopOfChain);
  1632. //dprintf("top of chain is %08x\n", TopOfChain);
  1633. //
  1634. // Found the API, now see why this API is shimmed or unshimmed.
  1635. //
  1636. IsExcluded(szModuleName, TopOfChain, bInSystem32);
  1637. goto EXIT;
  1638. }
  1639. CurrentHookAPI += dwHookAPISize;
  1640. }
  1641. CurrentShimInfo += dwShimInfoSize;
  1642. CurrentHookAPIArray += sizeof(ULONG_PTR);
  1643. }
  1644. dprintf("No shims are hooking API %s\n", szAPIName);
  1645. EXIT:
  1646. EXIT_API();
  1647. return S_OK;
  1648. }
  1649. BOOL
  1650. GetExeNameWithFullPath(
  1651. PSTR pszExeName,
  1652. DWORD dwExeNameSize
  1653. )
  1654. {
  1655. BOOL bIsSuccess = FALSE;
  1656. HRESULT hr;
  1657. if ((hr = g_ExtSystem->GetCurrentProcessExecutableName(
  1658. pszExeName,
  1659. dwExeNameSize,
  1660. NULL)) == S_OK)
  1661. {
  1662. if (CheckForFullPath(pszExeName)) {
  1663. bIsSuccess = TRUE;
  1664. }
  1665. } else {
  1666. dprintf("GetCurrentProcessExecutableName returned %08x\n", hr);
  1667. }
  1668. return bIsSuccess;
  1669. }
  1670. void
  1671. ConvertMatchModeToString(
  1672. DWORD dwMatchMode,
  1673. LPSTR pszMatchMode,
  1674. DWORD dwLen
  1675. )
  1676. {
  1677. switch (dwMatchMode)
  1678. {
  1679. case MATCH_NORMAL:
  1680. StringCchCopy(pszMatchMode, dwLen, "NORMAL");
  1681. break;
  1682. case MATCH_EXCLUSIVE:
  1683. StringCchCopy(pszMatchMode, dwLen, "EXCLUSIVE");
  1684. break;
  1685. case MATCH_ADDITIVE:
  1686. StringCchCopy(pszMatchMode, dwLen, "ADDITIVE");
  1687. break;
  1688. default:
  1689. StringCchCopy(pszMatchMode, dwLen, "UNKNOWN");
  1690. }
  1691. }
  1692. void
  1693. ConvertDBLocationToString(
  1694. TAGREF trExe,
  1695. LPSTR pszDBLocation,
  1696. DWORD dwLen
  1697. )
  1698. {
  1699. switch (trExe & TAGREF_STRIP_PDB) {
  1700. case PDB_MAIN:
  1701. StringCchCopy(pszDBLocation, dwLen, "MAIN");
  1702. break;
  1703. case PDB_TEST:
  1704. StringCchCopy(pszDBLocation, dwLen, "TEST");
  1705. break;
  1706. //
  1707. // Everything else is local.
  1708. //
  1709. case PDB_LOCAL:
  1710. default:
  1711. StringCchCopy(pszDBLocation, dwLen, "CUSTOM");
  1712. break;
  1713. }
  1714. }
  1715. BOOL
  1716. CheckEqualGUIDs(
  1717. const GUID* guid1,
  1718. const GUID* guid2
  1719. )
  1720. {
  1721. return (
  1722. ((PLONG)guid1)[0] == ((PLONG)guid2)[0] &&
  1723. ((PLONG)guid1)[1] == ((PLONG)guid2)[1] &&
  1724. ((PLONG)guid1)[2] == ((PLONG)guid2)[2] &&
  1725. ((PLONG)guid1)[3] == ((PLONG)guid2)[3]);
  1726. }
  1727. void
  1728. GetDBInfo(
  1729. PDB pdb,
  1730. LPWSTR pwszDBInfo,
  1731. DWORD dwLen
  1732. )
  1733. {
  1734. TAGID tiDatabase, tiDatabaseID;
  1735. GUID* pGuid;
  1736. WCHAR wszGuid[64];
  1737. NTSTATUS status;
  1738. tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
  1739. if (tiDatabase == TAGID_NULL) {
  1740. dprintf("Failed to find TAG_DATABASE\n");
  1741. return;
  1742. }
  1743. tiDatabaseID = SdbFindFirstTag(pdb, tiDatabase, TAG_DATABASE_ID);
  1744. if (tiDatabaseID == TAGID_NULL) {
  1745. dprintf("Failed to find TAG_DATABASE_ID\n");
  1746. return;
  1747. }
  1748. pGuid = (GUID*)SdbGetBinaryTagData(pdb, tiDatabaseID);
  1749. if (!pGuid) {
  1750. dprintf("Failed to read the GUID for this Database ID %08x\n", tiDatabaseID);
  1751. return;
  1752. }
  1753. if (CheckEqualGUIDs(pGuid, &GUID_SYSMAIN_SDB)) {
  1754. StringCchCopyW(pwszDBInfo, dwLen, L"sysmain.sdb");
  1755. } else if (CheckEqualGUIDs(pGuid, &GUID_MSIMAIN_SDB)) {
  1756. StringCchCopyW(pwszDBInfo, dwLen, L"msimain.sdb");
  1757. } else if (CheckEqualGUIDs(pGuid, &GUID_DRVMAIN_SDB)) {
  1758. StringCchCopyW(pwszDBInfo, dwLen, L"drvmain.sdb");
  1759. } else if (CheckEqualGUIDs(pGuid, &GUID_APPHELP_SDB)) {
  1760. StringCchCopyW(pwszDBInfo, dwLen, L"apphelp.sdb");
  1761. } else if (CheckEqualGUIDs(pGuid, &GUID_SYSTEST_SDB)) {
  1762. StringCchCopyW(pwszDBInfo, dwLen, L"systest.sdb");
  1763. } else {
  1764. //
  1765. // None of the above, so it's a custom sdb.
  1766. //
  1767. SdbGUIDToString(pGuid, wszGuid, CHARCOUNT(wszGuid));
  1768. StringCchCopyW(pwszDBInfo, dwLen, wszGuid);
  1769. StringCchCatW(pwszDBInfo, dwLen, L".sdb");
  1770. }
  1771. }
  1772. void
  1773. ShowSdbEntryInfo(
  1774. HSDB hSDB,
  1775. PSDBQUERYRESULT psdbQuery
  1776. )
  1777. {
  1778. DWORD dw, dwMatchMode;
  1779. TAGREF trExe;
  1780. PDB pdb;
  1781. TAGID tiExe, tiExeID, tiAppName, tiVendor, tiMatchMode;
  1782. GUID* pGuidExeID;
  1783. WCHAR wszGuid[64];
  1784. PWSTR pwszAppName, pwszVendorName;
  1785. char szMatchMode[8];
  1786. char szDBLocation[8];
  1787. WCHAR wszDBInfo[48];
  1788. dprintf("%-42s%-16s%-16s%-12s%-20s\n",
  1789. "EXE GUID",
  1790. "App Name",
  1791. "Vendor",
  1792. "Match Mode",
  1793. "Database");
  1794. for (dw = 0; dw < SDB_MAX_EXES; dw++) {
  1795. trExe = psdbQuery->atrExes[dw];
  1796. if (trExe == TAGREF_NULL) {
  1797. break;
  1798. }
  1799. if (!SdbTagRefToTagID(hSDB, trExe, &pdb, &tiExe) || pdb == NULL) {
  1800. dprintf("Failed to get tag id from tag ref\n");
  1801. return;
  1802. }
  1803. //
  1804. // Get the GUID of this EXE tag.
  1805. //
  1806. tiExeID = SdbFindFirstTag(pdb, tiExe, TAG_EXE_ID);
  1807. if (tiExeID == TAGID_NULL) {
  1808. dprintf("Failed to get the name tag id\n");
  1809. return;
  1810. }
  1811. pGuidExeID = (GUID*)SdbGetBinaryTagData(pdb, tiExeID);
  1812. if (!pGuidExeID) {
  1813. dprintf("Cannot read the ID for EXE tag 0x%x.\n", tiExe);
  1814. return;
  1815. }
  1816. SdbGUIDToString(pGuidExeID, wszGuid, CHARCOUNT(wszGuid));
  1817. //
  1818. // Get the App Name for this Exe.
  1819. //
  1820. tiAppName = SdbFindFirstTag(pdb, tiExe, TAG_APP_NAME);
  1821. if (tiAppName != TAGID_NULL) {
  1822. pwszAppName = SdbGetStringTagPtr(pdb, tiAppName);
  1823. }
  1824. //
  1825. // Get the vendor Name for this Exe.
  1826. //
  1827. tiVendor = SdbFindFirstTag(pdb, tiExe, TAG_VENDOR);
  1828. if (tiVendor != TAGID_NULL) {
  1829. pwszVendorName = SdbGetStringTagPtr(pdb, tiVendor);
  1830. }
  1831. tiMatchMode = SdbFindFirstTag(pdb, tiExe, TAG_MATCH_MODE);
  1832. dwMatchMode = SdbReadWORDTag(pdb, tiMatchMode, MATCHMODE_DEFAULT_MAIN);
  1833. ConvertMatchModeToString(dwMatchMode, szMatchMode, sizeof(szMatchMode));
  1834. ConvertDBLocationToString(trExe, szDBLocation, sizeof(szDBLocation));
  1835. GetDBInfo(pdb, wszDBInfo, sizeof(wszDBInfo) /sizeof(wszDBInfo[0]));
  1836. dprintf("%-42S%-16S%-16S%-12s%16S (%s)\n",
  1837. wszGuid,
  1838. pwszAppName,
  1839. pwszVendorName,
  1840. szMatchMode,
  1841. wszDBInfo,
  1842. szDBLocation);
  1843. }
  1844. }
  1845. LPWSTR
  1846. AnsiToUnicode(
  1847. LPCSTR psz)
  1848. {
  1849. LPWSTR pwsz = NULL;
  1850. if (psz) {
  1851. int nChars = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  1852. pwsz = (LPWSTR)malloc(nChars * sizeof(WCHAR));
  1853. if (pwsz) {
  1854. nChars = MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, nChars);
  1855. if (!nChars) {
  1856. dprintf("Failed to convert %s to unicode: %d\n", psz, GetLastError());
  1857. free(pwsz);
  1858. pwsz = NULL;
  1859. }
  1860. } else {
  1861. dprintf("Failed to allocate memory to convert %s to unicode\n", psz);
  1862. }
  1863. }
  1864. return pwsz;
  1865. }
  1866. DECLARE_API ( matchmode )
  1867. {
  1868. HSDB hSDB = NULL;
  1869. SDBQUERYRESULT sdbQuery;
  1870. BOOL bResult;
  1871. char szExeName[MAX_PATH];
  1872. LPWSTR pwszExeName = NULL;
  1873. INIT_API();
  1874. hSDB = SdbInitDatabase(0, NULL);
  1875. if (hSDB == NULL) {
  1876. dprintf("Failed to open the shim database.\n");
  1877. return NULL;
  1878. }
  1879. ZeroMemory(&sdbQuery, sizeof(SDBQUERYRESULT));
  1880. //
  1881. // Get the full path to the exe.
  1882. //
  1883. if (!GetExeNameWithFullPath(szExeName, sizeof(szExeName))) {
  1884. dprintf("failed to get exe name\n");
  1885. goto EXIT;
  1886. }
  1887. //dprintf("the exe name is %s\n", szExeName);
  1888. pwszExeName = AnsiToUnicode(szExeName);
  1889. if (!pwszExeName) {
  1890. goto EXIT;
  1891. }
  1892. bResult = SdbGetMatchingExe(hSDB, pwszExeName, NULL, NULL, 0, &sdbQuery);
  1893. if (!bResult) {
  1894. dprintf("Failed to get the matching info for this process\n");
  1895. goto EXIT;
  1896. } else {
  1897. ShowSdbEntryInfo(hSDB, &sdbQuery);
  1898. }
  1899. EXIT:
  1900. if (hSDB) {
  1901. SdbReleaseDatabase(hSDB);
  1902. }
  1903. if (pwszExeName) {
  1904. free(pwszExeName);
  1905. }
  1906. EXIT_API();
  1907. return S_OK;
  1908. }
  1909. DECLARE_API ( help )
  1910. {
  1911. dprintf("Help for extension dll shimexts.dll\n\n"
  1912. " !loadshims - This will stop right after the shims are loaded so if !shimnames\n"
  1913. " says the shims are not initialized, try this then !shimnames again.\n\n"
  1914. " !shimnames - It displays the name of the shims and how many APIs each shim hooks.\n\n"
  1915. " !debuglevel <val> - It changes the shimeng debug level to val (0 to 9).\n\n"
  1916. " !sdebuglevel <shim> <val>- It changes the shim's debug level to val (0 to 9). If no shim is\n"
  1917. " specified, it changes all shims'd debug level to val.\n\n"
  1918. " !displayhooks shim - Given the name of a shim, it displays the APIs it hooks.\n\n"
  1919. " !displaychain addr - If addr is one of the hooked API address, we print out the chain that\n"
  1920. " contains that addr.\n\n"
  1921. " !shimengsym - Checks if you have correct symbols for shimeng.\n\n"
  1922. " !checkex dllname apiname - It tells why this API called by this DLL is not shimmed.\n\n"
  1923. " !matchmode - It tells why this module is shimmed with these shims.\n\n"
  1924. " !help - It displays this help.\n"
  1925. );
  1926. return S_OK;
  1927. }