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.

499 lines
12 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: stdexts.c
  3. *
  4. * Copyright (c) 1995-1998, Microsoft Corporation
  5. *
  6. * This module contains standard routines for creating sane debuging extensions.
  7. * It is meant to be included after stdexts.h in one of the files comprising
  8. * the debug extsnsions for a given product or module.
  9. *
  10. * History:
  11. * 11-Apr-1995 Sanfords Created
  12. \***************************************************************************/
  13. HANDLE hCurrentProcess;
  14. HANDLE hCurrentThread;
  15. ULONG64 dwCurrentPc;
  16. WINDBG_EXTENSION_APIS *lpExtensionApis;
  17. DWORD dwProcessor;
  18. PSTR pszAccessViolation = "%s: Access violation on \"%s\".\n";
  19. PSTR pszMoveException = "%s: exception in moveBlock()\n";
  20. PSTR pszReadFailure = "%s: lpReadProcessMemoryRoutine failed!\n";
  21. PSTR pszCantContinue = "%s: Non-continuable exception.\n";
  22. BOOL fCtrlCHit = FALSE;
  23. /*
  24. * This function returns TRUE once the user has hit a Ctrl-C.
  25. * This allows proper operation of nested SAFEWHILE loops so
  26. * that all levels exit.
  27. *
  28. * The globall fCtrlCHit flag needs to be reset manually and
  29. * is done so in the CommandEP function.
  30. */
  31. BOOL IsCtrlCHit(
  32. VOID)
  33. {
  34. if ((lpExtensionApis->lpCheckControlCRoutine)()) {
  35. fCtrlCHit = TRUE;
  36. }
  37. return fCtrlCHit;
  38. }
  39. VOID moveBlock(
  40. PVOID pdst,
  41. ULONG64 src,
  42. DWORD size)
  43. {
  44. BOOL fSuccess = TRUE;
  45. ULONG Result;
  46. try {
  47. if (IsWinDbg()) {
  48. if (!ReadMem(src, pdst, size, &Result)) {
  49. fSuccess = FALSE;
  50. }
  51. } else {
  52. if (!NT_SUCCESS(NtReadVirtualMemory(hCurrentProcess,
  53. (PVOID)src, pdst, size, NULL))) {
  54. fSuccess = FALSE;
  55. }
  56. }
  57. } except (EXCEPTION_EXECUTE_HANDLER) {
  58. Print(pszMoveException, pszExtName);
  59. fSuccess = FALSE;
  60. }
  61. if (!fSuccess) {
  62. DEBUGPRINT("%s: moveBlock(%p, %p, %x) failed.\n",
  63. pszExtName, pdst, src, size);
  64. OUTAHERE();
  65. }
  66. }
  67. BOOL tryMoveBlock(
  68. PVOID pdst,
  69. ULONG64 src,
  70. DWORD size)
  71. {
  72. BOOL fSuccess = TRUE;
  73. ULONG Result;
  74. try {
  75. if (IsWinDbg()) {
  76. if (!ReadMem(src, pdst, size, &Result)) {
  77. DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) failed.\n", pszExtName, pdst, src, size);
  78. fSuccess = FALSE;
  79. }
  80. } else {
  81. if (!NT_SUCCESS(NtReadVirtualMemory(hCurrentProcess, (PVOID)src, pdst, size, NULL))) {
  82. DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) failed.\n", pszExtName, pdst, src, size);
  83. fSuccess = FALSE;
  84. }
  85. }
  86. } except (EXCEPTION_EXECUTE_HANDLER) {
  87. DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) faulted.\n", pszExtName, pdst, src, size);
  88. fSuccess = FALSE;
  89. }
  90. return fSuccess;
  91. }
  92. VOID moveExp(
  93. PULONG64 pdst,
  94. LPSTR pszExp)
  95. {
  96. BOOL fSuccess = TRUE;
  97. try {
  98. *pdst = EvalExp(pszExp);
  99. } except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  100. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  101. Print(pszAccessViolation, pszExtName, pszExp);
  102. fSuccess = FALSE;
  103. }
  104. if (!fSuccess) {
  105. Print("%s: moveExp failed on %s.\n", pszExtName, pszExp);
  106. OUTAHERE();
  107. }
  108. }
  109. BOOL tryMoveExp(
  110. PULONG64 pdst,
  111. LPSTR pszExp)
  112. {
  113. BOOL fSuccess = TRUE;
  114. try {
  115. *pdst = EvalExp(pszExp);
  116. } except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  117. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  118. Print(pszAccessViolation, pszExtName, pszExp);
  119. DEBUGPRINT("%s: tryMoveExp(%p, %s) faulted.\n", pszExtName, pdst, pszExp);
  120. fSuccess = FALSE;
  121. }
  122. return fSuccess;
  123. }
  124. VOID moveExpValue(
  125. PVOID pdst,
  126. LPSTR pszExp)
  127. {
  128. DWORD dw;
  129. ULONG64 addr;
  130. if (tryMoveExp(&addr, pszExp)) {
  131. if (tryMoveBlock(&dw, addr, sizeof(DWORD))) {
  132. *((PDWORD)pdst) = dw;
  133. return;
  134. }
  135. }
  136. Print("%s: moveExpValue failed on %s.\n", pszExtName, pszExp);
  137. OUTAHERE();
  138. }
  139. BOOL tryMoveExpValue(
  140. PVOID pdst,
  141. LPSTR pszExp)
  142. {
  143. DWORD dw;
  144. ULONG64 addr;
  145. if (tryMoveExp(&addr, pszExp)) {
  146. if (tryMove(dw, addr)) {
  147. *((PDWORD)pdst) = dw;
  148. return TRUE;
  149. }
  150. }
  151. DEBUGPRINT("%s: tryMoveExpValue failed on %s.\n", pszExtName, pszExp);
  152. return FALSE;
  153. }
  154. BOOL tryMoveExpPtr(
  155. PULONG64 pdst,
  156. LPSTR pszExp)
  157. {
  158. BOOL fSuccess = TRUE;
  159. try {
  160. *pdst = EvalExp(pszExp);
  161. } except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  162. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  163. Print(pszAccessViolation, pszExtName, pszExp);
  164. DEBUGPRINT("%s: tryMoveExpPtr(%p, %s) faulted.\n", pszExtName, pdst, pszExp);
  165. fSuccess = FALSE;
  166. }
  167. return fSuccess;
  168. }
  169. VOID moveExpValuePtr(
  170. PULONG64 pdst,
  171. LPSTR pszExp)
  172. {
  173. ULONG64 dw;
  174. if (tryMoveExpPtr(&dw, pszExp)) {
  175. if (tryMoveBlock(&dw, dw, sizeof(dw))) {
  176. *pdst = dw;
  177. return;
  178. }
  179. }
  180. Print("%s: moveExpValue failed on %s.\n", pszExtName, pszExp);
  181. OUTAHERE();
  182. }
  183. ULONG64 EvalExp(
  184. LPSTR psz)
  185. {
  186. ULONG64 p;
  187. p = (lpExtensionApis->lpGetExpressionRoutine)(psz);
  188. if (p == 0) {
  189. Print("%s: EvalExp failed to evaluate %s.\n", pszExtName, psz);
  190. }
  191. return p;
  192. }
  193. ULONG64 OptEvalExp(
  194. LPSTR psz)
  195. {
  196. while (*psz == ' ') {
  197. psz++;
  198. }
  199. if (*psz == '\0') {
  200. return 0;
  201. }
  202. return EvalExp(psz);
  203. }
  204. ULONG64 OptEvalExp2(
  205. LPSTR *ppsz)
  206. {
  207. LPSTR psz = *ppsz;
  208. ULONG64 dwRet = 0;
  209. while (*psz == ' ') {
  210. psz++;
  211. }
  212. if (*psz != '\0') {
  213. dwRet = EvalExp(psz);
  214. while (*psz != '\0' && *psz != ' ') {
  215. psz++;
  216. }
  217. }
  218. *ppsz = psz;
  219. return dwRet;
  220. }
  221. DWORD StringToOpts(
  222. LPSTR psz)
  223. {
  224. DWORD opts = 0;
  225. while (*psz != '\0' && *psz != ' ') {
  226. if (*psz >= 'a' && *psz <= 'z') {
  227. opts |= 1 << (*psz - 'a');
  228. } else if (*psz >= 'A' && *psz <= 'Z') {
  229. opts |= 1 << (*psz - 'A');
  230. } else {
  231. return OPTS_ERROR; // any non-letter option is an error.
  232. }
  233. psz++;
  234. }
  235. return opts;
  236. }
  237. /*
  238. * Function to convert an option string to a DWORD of flags. pszLegalArgs
  239. * is used to allow option validation at the same time.
  240. *
  241. * *ppszArgs is set to point to after the options on exit.
  242. * On error, returns OPTS_ERROR.
  243. */
  244. DWORD GetOpts(
  245. LPSTR *ppszArgs,
  246. LPSTR pszLegalArgs OPTIONAL)
  247. {
  248. DWORD Opts = 0;
  249. LPSTR pszArgs = *ppszArgs;
  250. /*
  251. * Skip whitespace
  252. */
  253. while (*pszArgs == ' ') {
  254. pszArgs++;
  255. }
  256. /*
  257. * process '-' prepended options.
  258. */
  259. while (*pszArgs == '-') {
  260. pszArgs++;
  261. Opts = StringToOpts(pszArgs);
  262. /*
  263. * skip to whitespace or end.
  264. */
  265. while (*pszArgs != '\0' && *pszArgs != ' ') {
  266. pszArgs++;
  267. }
  268. /*
  269. * skip trailing whitespace.
  270. */
  271. while (*pszArgs == ' ') {
  272. pszArgs++;
  273. }
  274. *ppszArgs = pszArgs;
  275. /*
  276. * optionally validate against LegalArgs
  277. */
  278. if (pszLegalArgs != NULL && ((Opts & StringToOpts(pszLegalArgs)) != Opts)) {
  279. Opts = OPTS_ERROR;
  280. Print("Bad options.\n");
  281. return Opts;
  282. }
  283. }
  284. return Opts;
  285. }
  286. /*
  287. * Dispatcher function used by generated entrypoint functions.
  288. */
  289. VOID CommonEP(
  290. PVOID pFunction,
  291. LPSTR pszName,
  292. int type,
  293. LPSTR pszLegalOpts,
  294. HANDLE hcp,
  295. HANDLE hct,
  296. ULONG64 dwcp,
  297. DWORD dwp,
  298. LPSTR lpas)
  299. {
  300. BOOL dwOptions, fSuccess;
  301. ULONG64 param1, param2, param3;
  302. hCurrentProcess = hcp;
  303. hCurrentThread = hct;
  304. dwCurrentPc = dwcp;
  305. dwProcessor = dwp;
  306. lpExtensionApis = &ExtensionApis;
  307. fCtrlCHit = FALSE; // reset this with each command. (SAFEWHILE fix)
  308. switch (type) {
  309. case NOARGS:
  310. fSuccess = ((TYPE_NOARGS)pFunction)();
  311. goto Exit;
  312. }
  313. dwOptions = GetOpts(&lpas, pszLegalOpts);
  314. if (dwOptions == OPTS_ERROR) {
  315. fSuccess = Ihelp(0, pszName);
  316. goto Exit;
  317. }
  318. try {
  319. switch (type) {
  320. case CUSTOM:
  321. fSuccess = ((TYPE_CUSTOM)pFunction)(dwOptions, lpas);
  322. break;
  323. case STDARGS0:
  324. fSuccess = ((TYPE_STDARGS0)pFunction)(dwOptions);
  325. break;
  326. case STDARGS1:
  327. fSuccess = ((TYPE_STDARGS1)pFunction)(dwOptions, OptEvalExp(lpas));
  328. break;
  329. case STDARGS2:
  330. param1 = OptEvalExp2(&lpas);
  331. fSuccess = ((TYPE_STDARGS2)pFunction)(dwOptions, param1, OptEvalExp(lpas));
  332. break;
  333. case STDARGS3:
  334. param1 = OptEvalExp2(&lpas);
  335. param2 = OptEvalExp2(&lpas);
  336. fSuccess = ((TYPE_STDARGS3)pFunction)(dwOptions, param1, param2, OptEvalExp(lpas));
  337. break;
  338. case STDARGS4:
  339. param1 = OptEvalExp2(&lpas);
  340. param2 = OptEvalExp2(&lpas);
  341. param3 = OptEvalExp2(&lpas);
  342. fSuccess = ((TYPE_STDARGS4)pFunction)(dwOptions, param1, param2, param3, OptEvalExp(lpas));
  343. break;
  344. default:
  345. Print("CommonEP: Don't recognize function type %d.\n", type);
  346. break;
  347. }
  348. } except (GetExceptionCode() == STATUS_NONCONTINUABLE_EXCEPTION ?
  349. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  350. Print(pszCantContinue, pszExtName);
  351. }
  352. Exit:
  353. if (!fSuccess) {
  354. Print("%s failed.\n", pszName);
  355. Ihelp(0, pszName);
  356. }
  357. }
  358. /*
  359. * Entrypoint functions (generated from exts.h)
  360. */
  361. #define DOIT(name, h1, h2, opts, type) \
  362. VOID name##( \
  363. HANDLE hcp, \
  364. HANDLE hct, \
  365. ULONG64 dwcp, \
  366. DWORD dwp, \
  367. LPSTR lpas) \
  368. { \
  369. CommonEP(I##name, #name, type, opts, hcp, hct, dwcp, dwp, lpas); \
  370. }
  371. #include "exts.h"
  372. #undef DOIT
  373. /*
  374. * Standard help extension - present in all standard extensions.
  375. */
  376. BOOL Ihelp(
  377. DWORD opts,
  378. LPSTR lpas)
  379. {
  380. #define DOIT(name, help1, help2, opts, type) { #name, help1, help2 },
  381. static struct {
  382. LPSTR pszCmdName;
  383. LPSTR pszHelp1;
  384. LPSTR pszHelp2;
  385. } he[] = {
  386. #include "exts.h"
  387. };
  388. #undef DOIT
  389. int i;
  390. while (*lpas == ' ') {
  391. lpas++;
  392. }
  393. if (*lpas == '\0') {
  394. Print("-------------- %s Debug Extension help:--------------\n\n", pszExtName);
  395. for (i = 0; i < sizeof(he) / sizeof(he[0]); i++) {
  396. if (IsCtrlCHit()) {
  397. break;
  398. }
  399. Print(he[i].pszHelp1);
  400. if (opts & OFLAG(v)) {
  401. Print(he[i].pszHelp2);
  402. }
  403. }
  404. return TRUE;
  405. } else {
  406. for (i = 0; i < sizeof(he) / sizeof(he[0]); i++) {
  407. if (IsCtrlCHit()) {
  408. break;
  409. }
  410. if (strcmp(lpas, he[i].pszCmdName) == 0) {
  411. Print(he[i].pszHelp1);
  412. Print(he[i].pszHelp2);
  413. return TRUE;
  414. }
  415. }
  416. Print("%s is not supported.\n", lpas);
  417. }
  418. return FALSE;
  419. }