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.

561 lines
14 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: stdext64.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 stdext64.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. {
  33. if ((lpExtensionApis->lpCheckControlCRoutine)()) {
  34. fCtrlCHit = TRUE;
  35. }
  36. return fCtrlCHit;
  37. }
  38. VOID moveBlock(
  39. PVOID pdst,
  40. ULONG64 src,
  41. DWORD size)
  42. {
  43. BOOL fSuccess = TRUE;
  44. ULONG Result;
  45. __try {
  46. if (IsWinDbg()) {
  47. if (!ReadMem(src, pdst, size, &Result)) {
  48. fSuccess = FALSE;
  49. }
  50. } else {
  51. if (!NT_SUCCESS(NtReadVirtualMemory(hCurrentProcess,
  52. (PVOID)src, pdst, size, NULL))) {
  53. fSuccess = FALSE;
  54. }
  55. }
  56. } __except (EXCEPTION_EXECUTE_HANDLER) {
  57. Print(pszMoveException, pszExtName);
  58. fSuccess = FALSE;
  59. }
  60. if (!fSuccess) {
  61. DEBUGPRINT("%s: moveBlock(%p, %p, %x) failed.\n",
  62. pszExtName, pdst, src, size);
  63. OUTAHERE();
  64. }
  65. }
  66. BOOL tryMoveBlock(
  67. PVOID pdst,
  68. ULONG64 src,
  69. DWORD size)
  70. {
  71. BOOL fSuccess = TRUE;
  72. ULONG Result;
  73. __try {
  74. if (IsWinDbg()) {
  75. if (!ReadMem(src, pdst, size, &Result)) {
  76. DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) failed.\n", pszExtName, pdst, src, size);
  77. fSuccess = FALSE;
  78. }
  79. } else {
  80. if (!NT_SUCCESS(NtReadVirtualMemory(hCurrentProcess, (PVOID)src, pdst, size, NULL))) {
  81. DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) failed.\n", pszExtName, pdst, src, size);
  82. fSuccess = FALSE;
  83. }
  84. }
  85. } __except (EXCEPTION_EXECUTE_HANDLER) {
  86. DEBUGPRINT("%s: tryMoveBlock(%p, %p, %x) faulted.\n", pszExtName, pdst, src, size);
  87. fSuccess = FALSE;
  88. }
  89. return(fSuccess);
  90. }
  91. VOID moveExp(
  92. PULONG64 pdst,
  93. LPSTR pszExp)
  94. {
  95. ULONG64 dwGlobal;
  96. BOOL fSuccess = TRUE;
  97. __try {
  98. dwGlobal = EvalExp(pszExp);
  99. #if 0
  100. if (IsWinDbg()) {
  101. fSuccess = tryMove(dwGlobal, dwGlobal);
  102. }
  103. #endif // !KERNEL
  104. *pdst = dwGlobal;
  105. } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  106. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  107. Print(pszAccessViolation, pszExtName, pszExp);
  108. fSuccess = FALSE;
  109. }
  110. if (!fSuccess) {
  111. Print("%s: moveExp failed on %s.\n", pszExtName, pszExp);
  112. OUTAHERE();
  113. }
  114. }
  115. BOOL tryMoveExp(
  116. PULONG64 pdst,
  117. LPSTR pszExp)
  118. {
  119. ULONG64 dwGlobal;
  120. BOOL fSuccess = TRUE;
  121. __try {
  122. dwGlobal = EvalExp(pszExp);
  123. #if 0
  124. if (IsWinDbg()) {
  125. if (!tryMove(dwGlobal, dwGlobal)) {
  126. DEBUGPRINT("%s: tryMoveExp(%p, %s) failed.\n", pszExtName, pdst, pszExp);
  127. fSuccess = FALSE;
  128. }
  129. }
  130. #endif // !KERNEL
  131. *pdst = dwGlobal;
  132. } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  133. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  134. Print(pszAccessViolation, pszExtName, pszExp);
  135. DEBUGPRINT("%s: tryMoveExp(%p, %s) faulted.\n", pszExtName, pdst, pszExp);
  136. fSuccess = FALSE;
  137. }
  138. return(fSuccess);
  139. }
  140. VOID moveExpValue(
  141. PVOID pdst,
  142. LPSTR pszExp)
  143. {
  144. DWORD dw;
  145. ULONG64 addr;
  146. if (tryMoveExp(&addr, pszExp)) {
  147. if (tryMoveBlock(&dw, addr, sizeof(DWORD))) {
  148. *((PDWORD)pdst) = dw;
  149. return;
  150. }
  151. }
  152. Print("%s: moveExpValue failed on %s.\n", pszExtName, pszExp);
  153. OUTAHERE();
  154. }
  155. BOOL tryMoveExpValue(
  156. PVOID pdst,
  157. LPSTR pszExp)
  158. {
  159. DWORD dw;
  160. ULONG64 addr;
  161. if (tryMoveExp(&addr, pszExp)) {
  162. if (tryMove(dw, addr)) {
  163. *((PDWORD)pdst) = dw;
  164. return(TRUE);
  165. }
  166. }
  167. DEBUGPRINT("%s: tryMoveExpValue failed on %s.\n", pszExtName, pszExp);
  168. return(FALSE);
  169. }
  170. BOOL tryMoveExpPtr(
  171. PULONG64 pdst,
  172. LPSTR pszExp)
  173. {
  174. ULONG64 dwGlobal;
  175. BOOL fSuccess = TRUE;
  176. __try {
  177. dwGlobal = EvalExp(pszExp);
  178. #if 0
  179. if (IsWinDbg()) {
  180. if (!tryMove(dwGlobal, dwGlobal)) {
  181. DEBUGPRINT("%s: tryMoveExpPtr(%p, %s) failed.\n", pszExtName, pdst, pszExp);
  182. fSuccess = FALSE;
  183. }
  184. }
  185. #endif // !KERNEL
  186. *pdst = dwGlobal;
  187. } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  188. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  189. Print(pszAccessViolation, pszExtName, pszExp);
  190. DEBUGPRINT("%s: tryMoveExpPtr(%p, %s) faulted.\n", pszExtName, pdst, pszExp);
  191. fSuccess = FALSE;
  192. }
  193. return(fSuccess);
  194. }
  195. VOID moveExpValuePtr(
  196. PULONG64 pdst,
  197. LPSTR pszExp)
  198. {
  199. ULONG64 dw;
  200. if (tryMoveExpPtr(&dw, pszExp)) {
  201. if (tryMoveBlock(&dw, dw, sizeof(dw))) {
  202. *pdst = dw;
  203. return;
  204. }
  205. }
  206. Print("%s: moveExpValue failed on %s.\n", pszExtName, pszExp);
  207. OUTAHERE();
  208. }
  209. /***************************************************************************
  210. * Common command parsing stuff *
  211. ***************************************************************************/
  212. ULONG64 EvalExp(
  213. LPSTR psz)
  214. {
  215. ULONG64 p;
  216. p = (lpExtensionApis->lpGetExpressionRoutine)(psz);
  217. if (p == 0) {
  218. Print("%s: EvalExp failed to evaluate %s.\n", pszExtName, psz);
  219. }
  220. return p;
  221. }
  222. ULONG64 OptEvalExp(
  223. LPSTR psz)
  224. {
  225. while (*psz == ' ')
  226. psz++;
  227. if (*psz == '\0') {
  228. return(0);
  229. }
  230. return(EvalExp(psz));
  231. }
  232. ULONG64 OptEvalExp2(
  233. LPSTR *ppsz)
  234. {
  235. LPSTR psz = *ppsz;
  236. ULONG64 dwRet = 0;
  237. while (*psz == ' ')
  238. psz++;
  239. if (*psz != '\0') {
  240. dwRet = EvalExp(psz);
  241. while (*psz != '\0' && *psz != ' ') {
  242. psz++;
  243. }
  244. }
  245. *ppsz = psz;
  246. return(dwRet);
  247. }
  248. DWORD StringToOpts(
  249. LPSTR psz)
  250. {
  251. DWORD opts = 0;
  252. while (*psz != '\0' && *psz != ' ') {
  253. if (*psz >= 'a' && *psz <= 'z') {
  254. opts |= 1 << (*psz - 'a');
  255. } else if (*psz >= 'A' && *psz <= 'Z') {
  256. opts |= 1 << (*psz - 'A');
  257. } else {
  258. return(OPTS_ERROR); // any non-letter option is an error.
  259. }
  260. psz++;
  261. }
  262. return(opts);
  263. }
  264. /*
  265. * Function to convert an option string to a DWORD of flags. pszLegalArgs
  266. * is used to allow option validation at the same time.
  267. *
  268. * *ppszArgs is set to point to after the options on exit.
  269. * On error, returns OPTS_ERROR.
  270. */
  271. DWORD GetOpts(
  272. LPSTR *ppszArgs,
  273. LPSTR pszLegalArgs) // OPTIONAL
  274. {
  275. DWORD Opts = 0;
  276. LPSTR pszArgs = *ppszArgs;
  277. /*
  278. * Skip whitespace
  279. */
  280. while (*pszArgs == ' ') {
  281. pszArgs++;
  282. }
  283. /*
  284. * process '-' prepended options.
  285. */
  286. while (*pszArgs == '-') {
  287. pszArgs++;
  288. Opts = StringToOpts(pszArgs);
  289. /*
  290. * skip to whitespace or end.
  291. */
  292. while (*pszArgs != '\0' && *pszArgs != ' ') {
  293. pszArgs++;
  294. }
  295. /*
  296. * skip trailing whitespace.
  297. */
  298. while (*pszArgs == ' ') {
  299. pszArgs++;
  300. }
  301. *ppszArgs = pszArgs;
  302. /*
  303. * optionally validate against LegalArgs
  304. */
  305. if (pszLegalArgs != NULL && ((Opts & StringToOpts(pszLegalArgs)) != Opts)) {
  306. Opts = OPTS_ERROR;
  307. Print("Bad options.\n");
  308. return(Opts);
  309. }
  310. }
  311. return(Opts);
  312. }
  313. VOID PrintHuge(
  314. LPSTR psz)
  315. {
  316. /*
  317. * Looks like this is faulting these days - Print seems to be fixed
  318. * so I'm leaving this entry point for compatibility. (SAS)
  319. */
  320. #ifdef ITWORKS
  321. #define HUNK_SIZE 400
  322. int cch;
  323. CHAR chSave;
  324. /*
  325. * since Print extension can't handle very long strings,
  326. * break it up into peices for it to chew.
  327. */
  328. cch = strlen(psz);
  329. while (cch > HUNK_SIZE) {
  330. chSave = psz[HUNK_SIZE];
  331. psz[HUNK_SIZE] = '\0';
  332. Print(psz);
  333. psz[HUNK_SIZE] = chSave;
  334. psz += HUNK_SIZE;
  335. cch -= HUNK_SIZE;
  336. }
  337. #endif
  338. Print(psz);
  339. }
  340. /*
  341. * Dispatcher function used by generated entrypoint functions.
  342. */
  343. VOID CommonEP(
  344. PVOID pFunction,
  345. LPSTR pszName,
  346. int type,
  347. LPSTR pszLegalOpts,
  348. HANDLE hcp,
  349. HANDLE hct,
  350. ULONG64 dwcp,
  351. DWORD dwp,
  352. LPSTR lpas)
  353. {
  354. BOOL dwOptions, fSuccess;
  355. ULONG64 param1, param2, param3;
  356. hCurrentProcess = hcp;
  357. hCurrentThread = hct;
  358. dwCurrentPc = dwcp;
  359. dwProcessor = dwp;
  360. lpExtensionApis = &ExtensionApis;
  361. #if 0
  362. DEBUGPRINT("CommonEP(%x, \"%s\", %d, \"%s\", %x, %x, %x, %x, \"%s\")\n",
  363. pFunction,
  364. pszName,
  365. type,
  366. pszLegalOpts,
  367. hcp,
  368. hct,
  369. dwcp,
  370. dwp,
  371. lpas);
  372. #endif
  373. fCtrlCHit = FALSE; // reset this with each command. (SAFEWHILE fix)
  374. switch (type) {
  375. case NOARGS:
  376. fSuccess = ((TYPE_NOARGS)pFunction)();
  377. goto Exit;
  378. }
  379. dwOptions = GetOpts(&lpas, pszLegalOpts);
  380. if (dwOptions == OPTS_ERROR) {
  381. fSuccess = Ihelp(0, pszName);
  382. goto Exit;
  383. }
  384. __try {
  385. switch (type) {
  386. case CUSTOM:
  387. fSuccess = ((TYPE_CUSTOM)pFunction)(dwOptions, lpas);
  388. break;
  389. case STDARGS0:
  390. fSuccess = ((TYPE_STDARGS0)pFunction)(dwOptions);
  391. break;
  392. case STDARGS1:
  393. fSuccess = ((TYPE_STDARGS1)pFunction)(dwOptions, OptEvalExp(lpas));
  394. break;
  395. case STDARGS2:
  396. param1 = OptEvalExp2(&lpas);
  397. fSuccess = ((TYPE_STDARGS2)pFunction)(dwOptions, param1, OptEvalExp(lpas));
  398. break;
  399. case STDARGS3:
  400. param1 = OptEvalExp2(&lpas);
  401. param2 = OptEvalExp2(&lpas);
  402. fSuccess = ((TYPE_STDARGS3)pFunction)(dwOptions, param1, param2, OptEvalExp(lpas));
  403. break;
  404. case STDARGS4:
  405. param1 = OptEvalExp2(&lpas);
  406. param2 = OptEvalExp2(&lpas);
  407. param3 = OptEvalExp2(&lpas);
  408. fSuccess = ((TYPE_STDARGS4)pFunction)(dwOptions, param1, param2, param3, OptEvalExp(lpas));
  409. break;
  410. default:
  411. Print("CommonEP: Don't recognize function type %d.\n", type);
  412. break;
  413. }
  414. } __except (GetExceptionCode() == STATUS_NONCONTINUABLE_EXCEPTION ?
  415. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  416. Print(pszCantContinue, pszExtName);
  417. }
  418. Exit:
  419. if (!fSuccess) {
  420. Print("%s failed.\n", pszName);
  421. Ihelp(0, pszName);
  422. }
  423. }
  424. /*
  425. * Entrypoint functions (generated from exts.h)
  426. */
  427. #define DOIT(name, h1, h2, opts, type) \
  428. VOID name##( \
  429. HANDLE hcp, \
  430. HANDLE hct, \
  431. ULONG64 dwcp, \
  432. DWORD dwp, \
  433. LPSTR lpas) \
  434. { \
  435. CommonEP(I##name, #name, type, opts, hcp, hct, dwcp, dwp, lpas); \
  436. }
  437. #include "exts.h"
  438. #undef DOIT
  439. /*
  440. * Standard help extension - present in all standard extensions.
  441. */
  442. BOOL Ihelp(
  443. DWORD opts,
  444. LPSTR lpas)
  445. {
  446. #define DOIT(name, help1, help2, opts, type) { #name, help1, help2 },
  447. static struct {
  448. LPSTR pszCmdName;
  449. LPSTR pszHelp1;
  450. LPSTR pszHelp2;
  451. } he[] = {
  452. #include "exts.h"
  453. };
  454. #undef DOIT
  455. int i;
  456. while (*lpas == ' ')
  457. lpas++;
  458. if (*lpas == '\0') {
  459. Print("-------------- %s Debug Extension help:--------------\n\n", pszExtName);
  460. for (i = 0; i < sizeof(he) / sizeof(he[0]); i++) {
  461. if (IsCtrlCHit()) {
  462. break;
  463. }
  464. Print(he[i].pszHelp1);
  465. if (opts & OFLAG(v)) {
  466. PrintHuge(he[i].pszHelp2);
  467. }
  468. }
  469. return(TRUE);
  470. } else {
  471. for (i = 0; i < sizeof(he) / sizeof(he[0]); i++) {
  472. if (IsCtrlCHit()) {
  473. break;
  474. }
  475. if (strcmp(lpas, he[i].pszCmdName) == 0) {
  476. Print(he[i].pszHelp1);
  477. PrintHuge(he[i].pszHelp2);
  478. return(TRUE);
  479. }
  480. }
  481. Print("%s is not supported.\n", lpas);
  482. }
  483. return(FALSE);
  484. }