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.

876 lines
24 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. wdbgxlib.c
  5. Abstract:
  6. This module realizes most of the routines needed for the rdbss/smbmini debugger extension.
  7. Author:
  8. Balan Sethu Raman (SethuR) 11-May-1994
  9. Notes:
  10. Revision History:
  11. 11-Nov-1994 SethuR Created
  12. 11-Nov-1995 Changed to newer windbg apis
  13. --*/
  14. #include "rxovride.h" //common compile flags
  15. #include <ntos.h>
  16. #include <nturtl.h>
  17. #include "ntverp.h"
  18. #include <windows.h>
  19. #include <wdbgexts.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <kdextlib.h>
  24. #include <dav2kd.h>
  25. #include <ntrxdef.h>
  26. #include <rxtypes.h>
  27. #include <rxlog.h>
  28. WINDBG_EXTENSION_APIS ExtensionApis;
  29. EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 };
  30. #define ERRPRT dprintf
  31. #define NL 1
  32. #define NONL 0
  33. USHORT SavedMajorVersion;
  34. USHORT SavedMinorVersion;
  35. BOOL ChkTarget; // is debuggee a CHK build?
  36. /*
  37. * Print out an optional message, an ANSI_STRING, and maybe a new-line
  38. */
  39. BOOL
  40. wPrintStringA( IN LPSTR msg OPTIONAL, IN PANSI_STRING pStr, IN BOOL nl )
  41. {
  42. PCHAR StringData;
  43. ULONG BytesRead;
  44. if( msg )
  45. dprintf( msg );
  46. if( pStr->Length == 0 ) {
  47. if( nl )
  48. dprintf( "\n" );
  49. return TRUE;
  50. }
  51. StringData = (PCHAR)LocalAlloc( LPTR, pStr->Length + 1 );
  52. if( StringData == NULL ) {
  53. ERRPRT( "Out of memory!\n" );
  54. return FALSE;
  55. }
  56. ReadMemory( (ULONG_PTR)pStr->Buffer,
  57. StringData,
  58. pStr->Length,
  59. &BytesRead );
  60. if ( BytesRead ) {
  61. StringData[ pStr->Length ] = '\0';
  62. dprintf("%s%s", StringData, nl ? "\n" : "" );
  63. }
  64. LocalFree((HLOCAL)StringData);
  65. return BytesRead;
  66. }
  67. /*
  68. * Fetches the data at the given address
  69. */
  70. BOOLEAN
  71. wGetData( ULONG_PTR dwAddress, PVOID ptr, ULONG size, IN PSZ type)
  72. {
  73. BOOL b;
  74. ULONG BytesRead;
  75. b = ReadMemory( dwAddress, ptr, size, &BytesRead );
  76. if (!b || BytesRead != size ) {
  77. dprintf( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  78. return FALSE;
  79. }
  80. return TRUE;
  81. }
  82. /*
  83. * Fetch the null terminated ASCII string at dwAddress into buf
  84. */
  85. BOOL
  86. wGetString( ULONG_PTR dwAddress, PSZ buf )
  87. {
  88. for(;;) {
  89. if( !wGetData( dwAddress,buf, 1, "..stringfetch") ){
  90. //dprintf("readfailure at %08lx\n",dwAddress);
  91. return FALSE;
  92. }
  93. //dprintf ("stringing %08lx %08lx %c\n", dwAddress, buf,
  94. // ((*buf==0)?'.':*buf) );
  95. if ( *buf == '\0' ) { break; }
  96. dwAddress++;
  97. buf++;
  98. };
  99. return TRUE;
  100. }
  101. #if 0
  102. /*
  103. * Get 'size' bytes from the debuggee program at 'dwAddress' and place it
  104. * in our address space at 'ptr'. Use 'type' in an error printout if necessary
  105. */
  106. BOOL
  107. wGetData_srv( IN LPVOID ptr, IN ULONG_PTR dwAddress, IN ULONG size, IN PCSTR type )
  108. {
  109. BOOL b;
  110. ULONG BytesRead;
  111. ULONG count;
  112. while( size > 0 ) {
  113. count = min( size, 3000 );
  114. b = ReadMemory((ULONG) dwAddress, ptr, count, &BytesRead );
  115. if (!b || BytesRead != count ) {
  116. ERRPRT( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  117. return FALSE;
  118. }
  119. dwAddress += count;
  120. size -= count;
  121. ptr = (LPVOID)((ULONG)ptr + count);
  122. }
  123. return TRUE;
  124. }
  125. /*
  126. * Follow a LIST_ENTRY list beginning with a head at dwListHeadAddr in the debugee's
  127. * address space. For each element in the list, print out the pointer value at 'offset'
  128. */
  129. BOOL
  130. PrintListEntryList( IN ULONG_PTR dwListHeadAddr, IN LONG offset )
  131. {
  132. LIST_ENTRY ListEntry;
  133. ULONG i=0;
  134. BOOL retval = TRUE;
  135. ULONG count = 20;
  136. if( !wGetData_srv( &ListEntry, dwListHeadAddr, sizeof( ListEntry ), "LIST_ENTRY" ) )
  137. return FALSE;
  138. while( count-- ) {
  139. if( (ULONG_PTR)ListEntry.Flink == dwListHeadAddr || (ULONG_PTR)ListEntry.Flink == 0 )
  140. break;
  141. if( !wGetData_srv( &ListEntry, (ULONG_PTR)ListEntry.Flink, sizeof( ListEntry ), "ListEntry" ) ) {
  142. retval = FALSE;
  143. break;
  144. }
  145. dprintf( "%16X%s", (LONG)ListEntry.Flink + offset, (i && !(i&3)) ? "\n" : "" );
  146. i++;
  147. }
  148. if( count == 0 && (ULONG_PTR)ListEntry.Flink != dwListHeadAddr && ListEntry.Flink ) {
  149. dprintf( "\nTruncated list dump\n" );
  150. } else if( ! ( i && !(i&3) ) ) {
  151. dprintf( "\n" );
  152. }
  153. return retval;
  154. }
  155. #endif
  156. /*
  157. * Print out a single HEX character
  158. */
  159. VOID
  160. wPrintHexChar( IN UCHAR c )
  161. {
  162. dprintf( "%c%c", "0123456789abcdef"[ (c>>4)&0xf ], "0123456789abcdef"[ c&0xf ] );
  163. }
  164. /*
  165. * Print out 'buf' of 'cbuf' bytes as HEX characters
  166. */
  167. VOID
  168. wPrintHexBuf( IN PUCHAR buf, IN ULONG cbuf )
  169. {
  170. while( cbuf-- ) {
  171. wPrintHexChar( *buf++ );
  172. dprintf( " " );
  173. }
  174. }
  175. #if 0
  176. /*
  177. * Fetch the null terminated UNICODE string at dwAddress into buf
  178. */
  179. BOOL
  180. GetString( IN ULONG_PTR dwAddress, IN LPWSTR buf, IN ULONG MaxChars )
  181. {
  182. do {
  183. if( !wGetData_srv( buf, dwAddress, sizeof( *buf ), "UNICODE Character" ) )
  184. return FALSE;
  185. dwAddress += sizeof( *buf );
  186. } while( --MaxChars && *buf++ != '\0' );
  187. return TRUE;
  188. }
  189. #endif
  190. VOID
  191. WinDbgExtensionDllInit(
  192. PWINDBG_EXTENSION_APIS lpExtensionApis,
  193. USHORT MajorVersion,
  194. USHORT MinorVersion
  195. )
  196. {
  197. ExtensionApis = *lpExtensionApis;
  198. SavedMajorVersion = MajorVersion;
  199. SavedMinorVersion = MinorVersion;
  200. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  201. }
  202. DECLARE_API( version )
  203. {
  204. #if DBG
  205. PCSTR kind = "Checked";
  206. #else
  207. PCSTR kind = "Free";
  208. #endif
  209. dprintf(
  210. "%s RDBSS+SMBmini Extension dll for Build %d debugging %s kernel for Build %d\n",
  211. kind,
  212. VER_PRODUCTBUILD,
  213. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  214. SavedMinorVersion
  215. );
  216. }
  217. VOID
  218. CheckVersion(
  219. VOID
  220. )
  221. {
  222. #if DBG
  223. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  224. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  225. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  226. }
  227. #else
  228. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  229. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  230. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  231. }
  232. #endif
  233. }
  234. LPEXT_API_VERSION
  235. ExtensionApiVersion(
  236. VOID
  237. )
  238. {
  239. return &ApiVersion;
  240. }
  241. LPSTR LibCommands[] = {
  242. "dump <Struct Type Name>@<address expr> ",
  243. "ddd <address expr> -- dump using context"
  244. "columns <d> -- controls the number of columns in the display ",
  245. "lg [<logentries>][@filename] -- dump the log",
  246. "gv -- dump out important variables",
  247. "activerx [fcbtomatch]-- dump the list of active contexts",
  248. "flags <value>-- print which flags are actually set (no text yet)",
  249. "cxr -- looks up cxr value from memory and does !cxr/!kb",
  250. "irp,thread,fcb,fobx,srvopen,exchange,stuff,smbbuf -- dumps the named item from the last dumpee",
  251. "version",
  252. 0
  253. };
  254. DECLARE_API( help )
  255. {
  256. int i;
  257. dprintf( "\nRDBSS debugger extensions:\n");
  258. for( i=0; LibCommands[i]; i++ )
  259. dprintf( " %s\n", LibCommands[i] );
  260. }
  261. ULONG FieldOffsetOfContextListEntryInRxC();
  262. VOID ReadRxContextFields(ULONG_PTR RxContext,PULONG_PTR pFcb,PULONG_PTR pThread, PULONG_PTR pMiniCtx2);
  263. DECLARE_API( dump );
  264. DECLARE_API( activerx )
  265. {
  266. //ULONG dwAddress;
  267. LIST_ENTRY LEbuffer;
  268. PLIST_ENTRY pRxActiveContexts,pListEntry;
  269. ULONG_PTR RxContext,CapturedFcb,LastThread,MinirdrCtx2;
  270. ULONG_PTR MatchFcb = 0x1badf00d;
  271. pRxActiveContexts = pListEntry = (PLIST_ENTRY)GetExpression("mrxdav!RxActiveContexts");
  272. if( args && *args ) {
  273. MatchFcb = GetExpression( args );
  274. }
  275. dprintf("\n Firstplentry: %08lx\n", pListEntry);
  276. for (;;) {
  277. if (!wGetData((ULONG_PTR)pListEntry,&LEbuffer,sizeof(LEbuffer),"RxActiveContexts")) return;
  278. if (LEbuffer.Flink == pRxActiveContexts) {
  279. if (pRxActiveContexts == pListEntry){
  280. dprintf("Active RxContext List Empty!\n");
  281. }
  282. return;
  283. }
  284. RxContext = ((ULONG_PTR)LEbuffer.Flink)-FieldOffsetOfContextListEntryInRxC();
  285. CapturedFcb = LastThread = 0x0badf00d;
  286. ReadRxContextFields(RxContext,&CapturedFcb,&LastThread,&MinirdrCtx2);
  287. if (MatchFcb == 0x1badf00d) {
  288. dprintf("%08lx: %08lx %08lx: %08lx %08lx %08lx %08lx\n", pListEntry,
  289. LEbuffer.Flink,LEbuffer.Blink,RxContext,CapturedFcb,LastThread,MinirdrCtx2);
  290. } else if ((MatchFcb == CapturedFcb)
  291. || (MatchFcb == LastThread) ) {
  292. // if a matchfcb is specified and we have a match, the print and dump
  293. char Bufferqq[100];
  294. dprintf("%08lx: %08lx %08lx: %08lx %08lx %08lx %08lx\n", pListEntry,
  295. LEbuffer.Flink,LEbuffer.Blink,RxContext,CapturedFcb,LastThread,MinirdrCtx2);
  296. sprintf(Bufferqq," %08lx ",RxContext);
  297. dump( hCurrentProcess,
  298. hCurrentThread,
  299. dwCurrentPc,
  300. dwProcessor,
  301. Bufferqq
  302. );
  303. }
  304. pListEntry = LEbuffer.Flink;
  305. }
  306. }
  307. #define GV_dprintf(__FORMAT__,__NAME__,__VALUE__) { \
  308. dprintf( "%s%-30s %08lx " __FORMAT__ "%s", \
  309. c&1 ? " " : "", \
  310. __NAME__, \
  311. dwAddress, \
  312. __VALUE__, \
  313. c&1 ? "\n" : "" ); \
  314. }
  315. DECLARE_API( gv )
  316. {
  317. ULONG_PTR dwAddress;
  318. CHAR buf[ 100 ];
  319. int i;
  320. int c=0;
  321. //CODE.IMPROVEMENT maybe we should hallucinate the moduleprefix instead
  322. // of having to specify it
  323. //CODE.IMPROVEMENT if we're not doing that, we shouldn't copy the name!
  324. //cause stuff to be loaded before we start printing
  325. dwAddress = GetExpression( "mrxdav!RxExpCXR" );
  326. dwAddress = GetExpression( "mrxsmb!SmbMmExchangesInUse" );
  327. for( i=0; GlobalBool[i]; i++, c++ ) {
  328. BOOL b;
  329. strcpy( &buf[0], GlobalBool[i] );
  330. dwAddress = GetExpression( buf );
  331. if( dwAddress == 0 ) {
  332. ERRPRT( "Unable to get address of %s\n", GlobalBool[i] );
  333. continue;
  334. }
  335. if( !wGetData( dwAddress,&b, sizeof(b), "global BOOL") ) continue;
  336. GV_dprintf("%10s",GlobalBool[i],(b ? " TRUE" : "FALSE"));
  337. }
  338. for( i=0; GlobalShort[i]; i++, c++ ) {
  339. SHORT s;
  340. strcpy( &buf[0], GlobalShort[i] );
  341. dwAddress = GetExpression( buf );
  342. if( dwAddress == 0 ) {
  343. ERRPRT( "Unable to get address of %s\n", GlobalShort[i] );
  344. continue;
  345. }
  346. if( !wGetData( dwAddress,&s,sizeof(s), "global SHORT") ) continue;
  347. GV_dprintf("%10d",GlobalShort[i],s);
  348. }
  349. for( i=0; GlobalLong[i]; i++, c++ ) {
  350. LONG l;
  351. strcpy( &buf[0], GlobalLong[i] );
  352. dwAddress = GetExpression( buf );
  353. if( dwAddress == 0 ) {
  354. ERRPRT( "Unable to get address of %s\n", GlobalLong[i] );
  355. continue;
  356. }
  357. if( !wGetData( dwAddress,&l, sizeof(l), "global LONG") ) continue;
  358. GV_dprintf("%10d",GlobalLong[i],l);
  359. }
  360. for( i=0; GlobalPtrs[i]; i++, c++ ) {
  361. LONG l;
  362. //ERRPRT( "zaaaaa %s\n", GlobalPtrs[i] );
  363. strcpy( &buf[0], GlobalPtrs[i] );
  364. dwAddress = GetExpression( buf );
  365. //ERRPRT( "zbbbbb %s %08lx\n", GlobalPtrs[i], dwAddress );
  366. if( dwAddress == 0 ) {
  367. ERRPRT( "Unable to get address of %s\n", GlobalPtrs[i] );
  368. continue;
  369. }
  370. if( !wGetData( dwAddress,&l, sizeof(l), "global PTR") ) continue;
  371. //ERRPRT( "zccccc %s %08lx\n", GlobalPtrs[i], dwAddress );
  372. GV_dprintf(" %08lx",GlobalPtrs[i],l);
  373. }
  374. dprintf( "\n" );
  375. }
  376. HANDLE DumpFile;
  377. CHAR wwDumpFormat[] = "-%06d: %s\n";
  378. VOID DumpRoutine(
  379. ULONG EntryNumber,
  380. PSZ OriginalStringToPrint
  381. )
  382. {
  383. UCHAR Buffer[200];
  384. UCHAR StringToPrint[160];
  385. PUCHAR p,q,r; LONG i;
  386. ULONG n,l3,l2,l1,l0; UCHAR Numbuf[32];
  387. ULONG ReturnedSize;
  388. //dprintf("before %d\n",EntryNumber);
  389. for (p=OriginalStringToPrint,q=StringToPrint,i=160;;) {
  390. PSZ format=NULL;
  391. if (*p==0) break;
  392. if (*p==0x4) {
  393. format = "%lx";
  394. } else if (*p==0x5) {
  395. format = "%ld";
  396. } else if (*p < ' ') {
  397. p++;i--;continue;
  398. }
  399. if (format!=NULL) {
  400. LONG Length;
  401. //translate the number
  402. p++;
  403. l0=*p++;
  404. l1=(*p++)<<8;
  405. l2=(*p++)<<16;
  406. l3=(*p++)<<24;
  407. n = l0 + l1 + l2 + l3;
  408. //dprintf("yaya %d %08lx %08lx %08lx %08lx %08lx\n",n,n,l0,l1,l2,l3);
  409. Length = sprintf(Numbuf,format,n);
  410. if (Length <= i) {
  411. for (r=Numbuf;*r;) { *q++ = *r++; }
  412. i -= Length;
  413. } else {
  414. i = 0;
  415. }
  416. if (i>0) continue;
  417. }
  418. if (i<=0) break;
  419. *q++ = *p++; i--;
  420. }
  421. *q = 0;
  422. //dprintf("after %d\n",EntryNumber);
  423. if (DumpFile == INVALID_HANDLE_VALUE) {
  424. dprintf(wwDumpFormat,EntryNumber,StringToPrint);
  425. return;
  426. }
  427. sprintf(Buffer,wwDumpFormat,EntryNumber,StringToPrint);
  428. WriteFile(DumpFile,Buffer,strlen(Buffer),&ReturnedSize,NULL);
  429. //should i check??
  430. return;
  431. }
  432. DECLARE_API( lg )
  433. {
  434. ULONG_PTR dwAddress;
  435. BYTE DataBuffer[MAX_RX_LOG_ENTRY_SIZE];
  436. BYTE AlternateLine[110];
  437. RX_LOG RxLog;
  438. ULONG LogEntries = 30;
  439. BOOLEAN LogEntriesSpecified = FALSE;
  440. PRX_LOG_ENTRY_HEADER CurrentEntry;
  441. //SETCALLBACKS();
  442. dwAddress = GetExpression("mrxdav!s_RxLog");
  443. if (!wGetData(dwAddress,&RxLog,sizeof(RX_LOG),"RxLog")) return;
  444. DumpFile = INVALID_HANDLE_VALUE;
  445. if( args && *args ) {
  446. LPSTR lpArgs;
  447. for (;*args;) {
  448. if (*args=='@') { break;}
  449. if ((*args>='0') && (*args<='9')) {
  450. sscanf(args,"%ld",&LogEntries);
  451. LogEntriesSpecified = TRUE;
  452. break;
  453. }
  454. args++;
  455. }
  456. lpArgs = strpbrk(args, "@");
  457. if (lpArgs) {
  458. DumpFile = CreateFileA(lpArgs+1,
  459. GENERIC_READ|GENERIC_WRITE,0,
  460. NULL,
  461. CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,
  462. INVALID_HANDLE_VALUE);
  463. if (DumpFile == INVALID_HANDLE_VALUE){
  464. ULONG rc = LOWORD(GetLastError());
  465. dprintf("Error Opening <%s> is %d.",lpArgs+1,rc);
  466. return;
  467. }
  468. if (!LogEntriesSpecified) {
  469. LogEntries = 99999999; //this will be reset to the right size
  470. }
  471. }
  472. }
  473. // Dump the log header followed by the log entries ...
  474. dprintf("s_RxLog.State %lx\n",RxLog.State);
  475. dprintf("s_RxLog.CurrentEntry %lx\n",RxLog.CurrentEntry);
  476. dprintf("s_RxLog.BaseEntry %lx\n",RxLog.BaseEntry);
  477. dprintf("s_RxLog.EntryLimit %lx\n",RxLog.EntryLimit);
  478. dprintf("s_RxLog.LogBufferSizeInEntries %ld\n",RxLog.LogBufferSizeInEntries);
  479. dprintf("s_RxLog.NumberOfEntriesIgnored %ld\n",RxLog.NumberOfEntriesIgnored);
  480. dprintf("s_RxLog.NumberOfLogWriteAttempts %ld\n",RxLog.NumberOfLogWriteAttempts);
  481. dprintf("s_RxLog.NumberOfLogWraps %ld\n",RxLog.NumberOfLogWraps);
  482. if (LogEntries > RxLog.LogBufferSizeInEntries) {
  483. LogEntries = RxLog.LogBufferSizeInEntries;
  484. }
  485. if (LogEntries < 1) {
  486. LogEntries = 1;
  487. }
  488. CurrentEntry = RxLog.CurrentEntry;
  489. CurrentEntry -= (LogEntries-1);
  490. if (CurrentEntry < RxLog.BaseEntry) {
  491. CurrentEntry += (RxLog.EntryLimit - RxLog.BaseEntry);
  492. }
  493. for (;;) {
  494. ULONG TextPtr;
  495. BOOLEAN ExtraOrdinaryLogEntry;
  496. LogEntries--;
  497. if ( CheckControlC() ) {
  498. return;
  499. }
  500. if (!wGetData((ULONG_PTR)CurrentEntry,&TextPtr,sizeof(TextPtr),"TextPtr")) return;
  501. if (!wGetData(TextPtr,&DataBuffer[0],sizeof(DataBuffer),"LogEntryBuffer")) return;
  502. ExtraOrdinaryLogEntry = (DataBuffer[0] == '#')&&(DataBuffer[1] == '>')&&(DataBuffer[3] == 0);
  503. if (!ExtraOrdinaryLogEntry) {
  504. //dprintf("-%06d: %s\n",LogEntries,DataBuffer);
  505. DumpRoutine(LogEntries,DataBuffer);
  506. } else {
  507. ULONG BinaryArgs = DataBuffer[2]-'0';
  508. PULONG_PTR x = (PULONG_PTR)&DataBuffer[sizeof(ULONG_PTR)];
  509. char Buffers[12*100]; //CODE.IMPROVEMENT this is poor but effective
  510. ULONG i;
  511. ULONG_PTR BinaryStringMask;
  512. PSZ ffFormat;
  513. //dprintf("textptr = %08lx, binaryString = %08lx\n", TextPtr, x[0]);
  514. for (i=1,BinaryStringMask=x[0];i<=BinaryArgs;i++) {
  515. if (BinaryStringMask & (1<<(i-1))) {
  516. //dprintf("Stringing %d\n",i);
  517. wGetString(x[i],&Buffers[i*100]); //this could fail!!!!
  518. x[i] = ((ULONG_PTR)&Buffers[i*100]);
  519. //dprintf(" string is %s\n",x[i]);
  520. }
  521. }
  522. ffFormat = (PSZ)(x[1]);
  523. switch (BinaryArgs) {
  524. case 9:
  525. sprintf(AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9]);
  526. break;
  527. case 8:
  528. sprintf(AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6],x[7],x[8]);
  529. break;
  530. case 7:
  531. sprintf(AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6],x[7]);
  532. break;
  533. case 6:
  534. sprintf(AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6]);
  535. break;
  536. case 5:
  537. sprintf(AlternateLine,ffFormat,x[2],x[3],x[4],x[5]);
  538. break;
  539. case 4:
  540. sprintf(AlternateLine,ffFormat,x[2],x[3],x[4]);
  541. break;
  542. case 3:
  543. sprintf(AlternateLine,ffFormat,x[2],x[3]);
  544. break;
  545. case 2:
  546. sprintf(AlternateLine,ffFormat,x[2]);
  547. break;
  548. case 1:
  549. sprintf(AlternateLine,ffFormat);
  550. break;
  551. }
  552. DumpRoutine(LogEntries,AlternateLine);
  553. }
  554. if (LogEntries==0) break;
  555. CurrentEntry++;
  556. if (CurrentEntry==RxLog.EntryLimit) {
  557. CurrentEntry = RxLog.BaseEntry;
  558. }
  559. }
  560. if (DumpFile != INVALID_HANDLE_VALUE) {
  561. CloseHandle(DumpFile);
  562. DumpFile = INVALID_HANDLE_VALUE;
  563. }
  564. }
  565. PCWSTR ExtensionLib = NULL;
  566. HANDLE hExtensionMod = NULL;
  567. ULONG DebugeeArchitecture = 0;
  568. PCWSTR GetExtensionLibPerDebugeeArchitecture(ULONG DebugeeArchitecture);
  569. PWINDBG_EXTENSION_ROUTINE
  570. GetKdExtProcAddress(
  571. IN PCSTR FuncName
  572. )
  573. {
  574. PWINDBG_EXTENSION_ROUTINE WindbgExtRoutine = NULL;
  575. //dprintf( "yaya\n");
  576. if (hExtensionMod == NULL) {
  577. if (DebugeeArchitecture == 0) {
  578. ULONG_PTR pArchitecture;
  579. ReloadSymbols(" rdbss.sys");
  580. pArchitecture = GetExpression("mrxdav!RxProcessorArchitecture");
  581. if (pArchitecture==0) {
  582. dprintf("couldn't get architecture value...\n");
  583. return NULL;
  584. }
  585. if (!wGetData(pArchitecture,&DebugeeArchitecture,sizeof(DebugeeArchitecture),"RxArch")) return NULL;
  586. if ((DebugeeArchitecture&0x0fff0000) != 0xabc0000) {
  587. dprintf("\n Bad DebugeeArchitecture %08lx\n", DebugeeArchitecture);
  588. return(NULL);
  589. }
  590. DebugeeArchitecture &= 0xffff;
  591. }
  592. ExtensionLib = GetExtensionLibPerDebugeeArchitecture(DebugeeArchitecture);
  593. if (ExtensionLib == NULL) {
  594. dprintf( "bad debuggee arch\n");
  595. return(NULL);
  596. }
  597. hExtensionMod = LoadLibrary( ExtensionLib );
  598. if (hExtensionMod == NULL) {
  599. dprintf( "couldn't load %ws\n", ExtensionLib );
  600. return(NULL);
  601. }
  602. }
  603. WindbgExtRoutine = (PWINDBG_EXTENSION_ROUTINE)GetProcAddress( hExtensionMod, FuncName );
  604. if (WindbgExtRoutine == NULL) {
  605. dprintf( "couldn't find %ws%s\n", ExtensionLib, FuncName );
  606. }
  607. return WindbgExtRoutine;
  608. }
  609. #define CALL_THRU(NAME,ARGS) { \
  610. PWINDBG_EXTENSION_ROUTINE WindbgExtRoutine = GetKdExtProcAddress(NAME); \
  611. if (WindbgExtRoutine != NULL) { \
  612. (WindbgExtRoutine)( hCurrentProcess, \
  613. hCurrentThread, \
  614. dwCurrentPc, \
  615. dwProcessor, \
  616. ARGS \
  617. ); \
  618. } \
  619. }
  620. DECLARE_API( testr )
  621. {
  622. CALL_THRU ( "threadfields", "");
  623. }
  624. DECLARE_API( dump );
  625. VOID
  626. __FollowOnHelper (
  627. PFOLLOWON_HELPER_ROUTINE Callee,
  628. HANDLE hCurrentProcess,
  629. HANDLE hCurrentThread,
  630. ULONG dwCurrentPc,
  631. ULONG dwProcessor,
  632. PCSTR args
  633. )
  634. {
  635. BYTE Name[100], Buffer2[200];
  636. FOLLOWON_HELPER_RETURNS ret;
  637. PPERSISTENT_RDR2KD_INFO p;
  638. p = LocatePersistentInfoFromView();
  639. if (!p) {
  640. dprintf("Couldn't allocate perstistent info buffer...sorry...\n");
  641. return;
  642. }
  643. ret = Callee(p,Name,Buffer2);
  644. if (p!= NULL) FreePersistentInfoView(p);
  645. p = NULL;
  646. switch (ret) {
  647. case FOLLOWONHELPER_DUMP:
  648. dump(hCurrentProcess,
  649. hCurrentThread,
  650. dwCurrentPc,
  651. dwProcessor,
  652. Buffer2
  653. );
  654. break;
  655. case FOLLOWONHELPER_CALLTHRU:
  656. CALL_THRU ( Name, Buffer2);
  657. break;
  658. case FOLLOWONHELPER_ERROR:
  659. dprintf("%s",Buffer2);
  660. break;
  661. case FOLLOWONHELPER_DONE:
  662. break;
  663. }
  664. return;
  665. }
  666. #define FollowOnHelper(a) { \
  667. __FollowOnHelper(a, \
  668. hCurrentProcess, \
  669. hCurrentThread, \
  670. dwCurrentPc, \
  671. dwProcessor, \
  672. args); \
  673. }
  674. DECLARE_FOLLOWON_HELPER_CALLEE(FcbFollowOn);
  675. DECLARE_API( fcb )
  676. {
  677. FollowOnHelper(FcbFollowOn);
  678. }
  679. DECLARE_API( flags )
  680. {
  681. ULONG i,mask,newline,value;
  682. if( args && *args ) {
  683. sscanf(args,"%lx",&value);
  684. dprintf("Flags for %08lx\n",value);
  685. } else {
  686. dprintf("error in flags: no value presented\n");
  687. return;
  688. }
  689. for (i=newline=0,mask=1;i<32;i++,mask<<=1) {
  690. if (value&mask) {
  691. dprintf(" %02d 0x%08lx%c",i,mask,(newline==0)?' ':'\n');
  692. newline ^= 1;
  693. }
  694. }
  695. if (newline) {
  696. dprintf("\n");
  697. }
  698. }
  699. DECLARE_API( cxr )
  700. {
  701. ULONG_PTR dwAddress,cxr;
  702. BYTE NumBuffer[16];
  703. RX_LOG RxLog;
  704. ULONG LogEntries = 30;
  705. PRX_LOG_ENTRY_HEADER CurrentEntry;
  706. //SETCALLBACKS();
  707. dwAddress = GetExpression("mrxdav!RxExpCXR");
  708. if (!wGetData(dwAddress,&cxr,sizeof(cxr),"cxr")) return;
  709. dprintf("\nRxExpCXR=%08lx\n",cxr);
  710. sprintf(NumBuffer,"%08lx \n",cxr);
  711. CALL_THRU ( "cxr", NumBuffer);
  712. if (DebugeeArchitecture==0) {
  713. CALL_THRU ( "kb", "");
  714. }
  715. }
  716. VOID dprintfsprintfbuffer(BYTE *Buffer)
  717. {
  718. dprintf("%s\n",Buffer);
  719. }