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.

1152 lines
32 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. #define KDEXT_32BIT
  15. #include "rxovride.h" //common compile flags
  16. #include <ntos.h>
  17. #include <nturtl.h>
  18. #include "ntverp.h"
  19. #include <windows.h>
  20. #include <wdbgexts.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include <kdextlib.h>
  25. #include <rdpdrkd.h>
  26. #include <ntrxdef.h>
  27. #include <rxtypes.h>
  28. extern "C" {
  29. #include <rxlog.h>
  30. }
  31. #include "dbg.h"
  32. #include "topobj.h"
  33. #include "smartptr.h"
  34. #include "trc.h"
  35. WINDBG_EXTENSION_APIS ExtensionApis;
  36. EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 };
  37. BOOL ParseTrc(PCSTR args, DWORD *dwLines);
  38. #define ERRPRT dprintf
  39. #define NL 1
  40. #define NONL 0
  41. USHORT SavedMajorVersion;
  42. USHORT SavedMinorVersion;
  43. BOOL ChkTarget; // is debuggee a CHK build?
  44. /*
  45. * Print out an optional message, an ANSI_STRING, and maybe a new-line
  46. */
  47. BOOL
  48. wPrintStringA( IN LPSTR msg OPTIONAL, IN PANSI_STRING pStr, IN BOOL nl )
  49. {
  50. PCHAR StringData;
  51. ULONG BytesRead;
  52. if( msg )
  53. dprintf( msg );
  54. if( pStr->Length == 0 ) {
  55. if( nl )
  56. dprintf( "\n" );
  57. return TRUE;
  58. }
  59. StringData = (PCHAR)LocalAlloc( LPTR, pStr->Length + 1 );
  60. if( StringData == NULL ) {
  61. ERRPRT( "Out of memory!\n" );
  62. return FALSE;
  63. }
  64. ReadMemory( (ULONG_PTR)pStr->Buffer,
  65. StringData,
  66. pStr->Length,
  67. &BytesRead );
  68. if ( BytesRead ) {
  69. StringData[ pStr->Length ] = '\0';
  70. dprintf("%s%s", StringData, nl ? "\n" : "" );
  71. }
  72. LocalFree((HLOCAL)StringData);
  73. return BytesRead;
  74. }
  75. /*
  76. * Fetches the data at the given address
  77. */
  78. BOOLEAN
  79. wGetData( ULONG_PTR dwAddress, PVOID ptr, ULONG size, IN PSZ type)
  80. {
  81. BOOL b;
  82. ULONG BytesRead;
  83. b = ReadMemory( dwAddress, ptr, size, &BytesRead );
  84. if (!b || BytesRead != size ) {
  85. dprintf( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  86. return FALSE;
  87. }
  88. return TRUE;
  89. }
  90. /*
  91. * Fetch the null terminated ASCII string at dwAddress into buf
  92. */
  93. BOOL
  94. wGetString( ULONG_PTR dwAddress, PSZ buf )
  95. {
  96. for(;;) {
  97. if( !wGetData( dwAddress,buf, 1, "..stringfetch") ){
  98. //dprintf("readfailure at %08lx\n",dwAddress);
  99. return FALSE;
  100. }
  101. //dprintf ("stringing %08lx %08lx %c\n", dwAddress, buf,
  102. // ((*buf==0)?'.':*buf) );
  103. if ( *buf == '\0' ) { break; }
  104. dwAddress++;
  105. buf++;
  106. };
  107. return TRUE;
  108. }
  109. #if 0
  110. /*
  111. * Get 'size' bytes from the debuggee program at 'dwAddress' and place it
  112. * in our address space at 'ptr'. Use 'type' in an error printout if necessary
  113. */
  114. BOOL
  115. wGetData_srv( IN LPVOID ptr, IN ULONG_PTR dwAddress, IN ULONG size, IN PCSTR type )
  116. {
  117. BOOL b;
  118. ULONG BytesRead;
  119. ULONG count;
  120. while( size > 0 ) {
  121. count = min( size, 3000 );
  122. b = ReadMemory((ULONG) dwAddress, ptr, count, &BytesRead );
  123. if (!b || BytesRead != count ) {
  124. ERRPRT( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  125. return FALSE;
  126. }
  127. dwAddress += count;
  128. size -= count;
  129. ptr = (LPVOID)((ULONG)ptr + count);
  130. }
  131. return TRUE;
  132. }
  133. /*
  134. * Follow a LIST_ENTRY list beginning with a head at dwListHeadAddr in the debugee's
  135. * address space. For each element in the list, print out the pointer value at 'offset'
  136. */
  137. BOOL
  138. PrintListEntryList( IN ULONG_PTR dwListHeadAddr, IN LONG offset )
  139. {
  140. LIST_ENTRY ListEntry;
  141. ULONG i=0;
  142. BOOL retval = TRUE;
  143. ULONG count = 20;
  144. if( !wGetData_srv( &ListEntry, dwListHeadAddr, sizeof( ListEntry ), "LIST_ENTRY" ) )
  145. return FALSE;
  146. while( count-- ) {
  147. if( (ULONG_PTR)ListEntry.Flink == dwListHeadAddr || (ULONG_PTR)ListEntry.Flink == 0 )
  148. break;
  149. if( !wGetData_srv( &ListEntry, (ULONG_PTR)ListEntry.Flink, sizeof( ListEntry ), "ListEntry" ) ) {
  150. retval = FALSE;
  151. break;
  152. }
  153. dprintf( "%16X%s", (LONG)ListEntry.Flink + offset, (i && !(i&3)) ? "\n" : "" );
  154. i++;
  155. }
  156. if( count == 0 && (ULONG_PTR)ListEntry.Flink != dwListHeadAddr && ListEntry.Flink ) {
  157. dprintf( "\nTruncated list dump\n" );
  158. } else if( ! ( i && !(i&3) ) ) {
  159. dprintf( "\n" );
  160. }
  161. return retval;
  162. }
  163. #endif
  164. /*
  165. * Print out a single HEX character
  166. */
  167. VOID
  168. wPrintHexChar( IN UCHAR c )
  169. {
  170. dprintf( "%c%c", "0123456789abcdef"[ (c>>4)&0xf ], "0123456789abcdef"[ c&0xf ] );
  171. }
  172. /*
  173. * Print out 'buf' of 'cbuf' bytes as HEX characters
  174. */
  175. VOID
  176. wPrintHexBuf( IN PUCHAR buf, IN ULONG cbuf )
  177. {
  178. while( cbuf-- ) {
  179. wPrintHexChar( *buf++ );
  180. dprintf( " " );
  181. }
  182. }
  183. #if 0
  184. /*
  185. * Fetch the null terminated UNICODE string at dwAddress into buf
  186. */
  187. BOOL
  188. GetString( IN ULONG_PTR dwAddress, IN LPWSTR buf, IN ULONG MaxChars )
  189. {
  190. do {
  191. if( !wGetData_srv( buf, dwAddress, sizeof( *buf ), "UNICODE Character" ) )
  192. return FALSE;
  193. dwAddress += sizeof( *buf );
  194. } while( --MaxChars && *buf++ != '\0' );
  195. return TRUE;
  196. }
  197. #endif
  198. VOID
  199. WinDbgExtensionDllInit(
  200. PWINDBG_EXTENSION_APIS lpExtensionApis,
  201. USHORT MajorVersion,
  202. USHORT MinorVersion
  203. )
  204. {
  205. // ExtensionApis = *lpExtensionApis;
  206. memcpy(&ExtensionApis, lpExtensionApis, sizeof(ExtensionApis));
  207. SavedMajorVersion = MajorVersion;
  208. SavedMinorVersion = MinorVersion;
  209. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  210. }
  211. DECLARE_API( version )
  212. {
  213. #if DBG
  214. PCSTR kind = "Checked";
  215. #else
  216. PCSTR kind = "Free";
  217. #endif
  218. dprintf(
  219. "%s RDBSS+RdpDr Extension dll for Build %d debugging %s kernel for Build %d\n",
  220. kind,
  221. VER_PRODUCTBUILD,
  222. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  223. SavedMinorVersion
  224. );
  225. }
  226. VOID
  227. CheckVersion(
  228. VOID
  229. )
  230. {
  231. #if DBG
  232. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  233. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  234. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  235. }
  236. #else
  237. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  238. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  239. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  240. }
  241. #endif
  242. }
  243. LPEXT_API_VERSION
  244. ExtensionApiVersion(
  245. VOID
  246. )
  247. {
  248. return &ApiVersion;
  249. }
  250. LPSTR LibCommands[] = {
  251. "dump <Struct Type Name>@<address expr> ",
  252. "listref [address of specific RefCount object]"
  253. "ddd <address expr> -- dump using context"
  254. "columns <d> -- controls the number of columns in the display ",
  255. "lg [<logentries>][@filename] -- dump the log",
  256. "gv -- dump out important variables",
  257. "activerx [fcbtomatch]-- dump the list of active contexts",
  258. "flags <value>-- print which flags are actually set (no text yet)",
  259. "cxr -- looks up cxr value from memory and does !cxr/!kb",
  260. "irp,thread,fcb,fobx,srvopen,exchange,stuff,smbbuf -- dumps the named item from the last dumpee",
  261. "version",
  262. 0
  263. };
  264. DECLARE_API( help )
  265. {
  266. int i;
  267. dprintf( "\nRDBSS debugger extensions:\n");
  268. for( i=0; LibCommands[i]; i++ )
  269. dprintf( " %s\n", LibCommands[i] );
  270. }
  271. ULONG FieldOffsetOfContextListEntryInRxC();
  272. VOID ReadRxContextFields(ULONG_PTR RxContext,PULONG_PTR pFcb,PULONG_PTR pThread, PULONG_PTR pMiniCtx2);
  273. DECLARE_API( dump );
  274. DECLARE_API( activerx )
  275. {
  276. //ULONG dwAddress;
  277. LIST_ENTRY LEbuffer;
  278. PLIST_ENTRY pRxActiveContexts,pListEntry;
  279. ULONG_PTR RxContext,CapturedFcb,LastThread,MinirdrCtx2;
  280. ULONG_PTR MatchFcb = 0x1badf00d;
  281. pRxActiveContexts = pListEntry = (PLIST_ENTRY)GetExpression("rdpdr!RxActiveContexts");
  282. if( args && *args ) {
  283. MatchFcb = GetExpression( args );
  284. }
  285. dprintf("\n Firstplentry: %08lx\n", pListEntry);
  286. for (;;) {
  287. if (!wGetData((ULONG_PTR)pListEntry,&LEbuffer,sizeof(LEbuffer),"RxActiveContexts")) return;
  288. if (LEbuffer.Flink == pRxActiveContexts) {
  289. if (pRxActiveContexts == pListEntry){
  290. dprintf("Active RxContext List Empty!\n");
  291. }
  292. return;
  293. }
  294. RxContext = ((ULONG_PTR)LEbuffer.Flink)-FieldOffsetOfContextListEntryInRxC();
  295. CapturedFcb = LastThread = 0x0badf00d;
  296. ReadRxContextFields(RxContext,&CapturedFcb,&LastThread,&MinirdrCtx2);
  297. if (MatchFcb == 0x1badf00d) {
  298. dprintf("%08lx: %08lx %08lx: %08lx %08lx %08lx %08lx\n", pListEntry,
  299. LEbuffer.Flink,LEbuffer.Blink,RxContext,CapturedFcb,LastThread,MinirdrCtx2);
  300. } else if ((MatchFcb == CapturedFcb)
  301. || (MatchFcb == LastThread) ) {
  302. // if a matchfcb is specified and we have a match, the print and dump
  303. char Bufferqq[100];
  304. dprintf("%08lx: %08lx %08lx: %08lx %08lx %08lx %08lx\n", pListEntry,
  305. LEbuffer.Flink,LEbuffer.Blink,RxContext,CapturedFcb,LastThread,MinirdrCtx2);
  306. sprintf(Bufferqq," %08lx ",RxContext);
  307. dump( hCurrentProcess,
  308. hCurrentThread,
  309. dwCurrentPc,
  310. dwProcessor,
  311. Bufferqq
  312. );
  313. }
  314. pListEntry = LEbuffer.Flink;
  315. }
  316. }
  317. #define GV_dprintf(__FORMAT__,__NAME__,__VALUE__) { \
  318. dprintf( "%s%-30s %08lx " __FORMAT__ "%s", \
  319. c&1 ? " " : "", \
  320. __NAME__, \
  321. dwAddress, \
  322. __VALUE__, \
  323. c&1 ? "\n" : "" ); \
  324. }
  325. DECLARE_API( gv )
  326. {
  327. ULONG_PTR dwAddress;
  328. CHAR buf[ 100 ];
  329. int i;
  330. int c=0;
  331. //CODE.IMPROVEMENT maybe we should hallucinate the moduleprefix instead
  332. // of having to specify it
  333. //CODE.IMPROVEMENT if we're not doing that, we shouldn't copy the name!
  334. //cause stuff to be loaded before we start printing
  335. dwAddress = GetExpression( "rdpdr!RxExpCXR" );
  336. dwAddress = GetExpression( "mrxsmb!SmbMmExchangesInUse" );
  337. for( i=0; GlobalBool[i]; i++, c++ ) {
  338. BOOL b;
  339. strcpy( &buf[0], GlobalBool[i] );
  340. dwAddress = GetExpression( buf );
  341. if( dwAddress == 0 ) {
  342. ERRPRT( "Unable to get address of %s\n", GlobalBool[i] );
  343. continue;
  344. }
  345. if( !wGetData( dwAddress,&b, sizeof(b), "global BOOL") ) continue;
  346. GV_dprintf("%10s",GlobalBool[i],(b ? " TRUE" : "FALSE"));
  347. }
  348. for( i=0; GlobalShort[i]; i++, c++ ) {
  349. SHORT s;
  350. strcpy( &buf[0], GlobalShort[i] );
  351. dwAddress = GetExpression( buf );
  352. if( dwAddress == 0 ) {
  353. ERRPRT( "Unable to get address of %s\n", GlobalShort[i] );
  354. continue;
  355. }
  356. if( !wGetData( dwAddress,&s,sizeof(s), "global SHORT") ) continue;
  357. GV_dprintf("%10d",GlobalShort[i],s);
  358. }
  359. for( i=0; GlobalLong[i]; i++, c++ ) {
  360. LONG l;
  361. strcpy( &buf[0], GlobalLong[i] );
  362. dwAddress = GetExpression( buf );
  363. if( dwAddress == 0 ) {
  364. ERRPRT( "Unable to get address of %s\n", GlobalLong[i] );
  365. continue;
  366. }
  367. if( !wGetData( dwAddress,&l, sizeof(l), "global LONG") ) continue;
  368. GV_dprintf("%10d",GlobalLong[i],l);
  369. }
  370. for( i=0; GlobalPtrs[i]; i++, c++ ) {
  371. LONG l;
  372. //ERRPRT( "zaaaaa %s\n", GlobalPtrs[i] );
  373. strcpy( &buf[0], GlobalPtrs[i] );
  374. dwAddress = GetExpression( buf );
  375. //ERRPRT( "zbbbbb %s %08lx\n", GlobalPtrs[i], dwAddress );
  376. if( dwAddress == 0 ) {
  377. ERRPRT( "Unable to get address of %s\n", GlobalPtrs[i] );
  378. continue;
  379. }
  380. if( !wGetData( dwAddress,&l, sizeof(l), "global PTR") ) continue;
  381. //ERRPRT( "zccccc %s %08lx\n", GlobalPtrs[i], dwAddress );
  382. GV_dprintf(" %08lx",GlobalPtrs[i],l);
  383. }
  384. dprintf( "\n" );
  385. }
  386. HANDLE DumpFile;
  387. CHAR wwDumpFormat[] = "-%06d: %s\n";
  388. VOID DumpRoutine(
  389. ULONG EntryNumber,
  390. PSZ OriginalStringToPrint
  391. )
  392. {
  393. UCHAR Buffer[200];
  394. UCHAR StringToPrint[160];
  395. PUCHAR p,q,r; LONG i;
  396. ULONG n,l3,l2,l1,l0; UCHAR Numbuf[32];
  397. ULONG ReturnedSize;
  398. //dprintf("before %d\n",EntryNumber);
  399. for (p=(PUCHAR)OriginalStringToPrint,q=StringToPrint,i=160;;) {
  400. PSZ format=NULL;
  401. if (*p==0) break;
  402. if (*p==0x4) {
  403. format = "%lx";
  404. } else if (*p==0x5) {
  405. format = "%ld";
  406. } else if (*p < ' ') {
  407. p++;i--;continue;
  408. }
  409. if (format!=NULL) {
  410. LONG Length;
  411. //translate the number
  412. p++;
  413. l0=*p++;
  414. l1=(*p++)<<8;
  415. l2=(*p++)<<16;
  416. l3=(*p++)<<24;
  417. n = l0 + l1 + l2 + l3;
  418. //dprintf("yaya %d %08lx %08lx %08lx %08lx %08lx\n",n,n,l0,l1,l2,l3);
  419. Length = sprintf((char *)Numbuf,format,n);
  420. if (Length <= i) {
  421. for (r=Numbuf;*r;) { *q++ = *r++; }
  422. i -= Length;
  423. } else {
  424. i = 0;
  425. }
  426. if (i>0) continue;
  427. }
  428. if (i<=0) break;
  429. *q++ = *p++; i--;
  430. }
  431. *q = 0;
  432. //dprintf("after %d\n",EntryNumber);
  433. if (DumpFile == INVALID_HANDLE_VALUE) {
  434. dprintf(wwDumpFormat,EntryNumber,StringToPrint);
  435. return;
  436. }
  437. sprintf((char *)Buffer,wwDumpFormat,EntryNumber,StringToPrint);
  438. WriteFile(DumpFile,Buffer,strlen((char *)Buffer),&ReturnedSize,NULL);
  439. //should i check??
  440. return;
  441. }
  442. DECLARE_API( lg )
  443. {
  444. ULONG_PTR dwAddress;
  445. BYTE DataBuffer[MAX_RX_LOG_ENTRY_SIZE];
  446. BYTE AlternateLine[110];
  447. RX_LOG RxLog;
  448. ULONG LogEntries = 30;
  449. BOOLEAN LogEntriesSpecified = FALSE;
  450. PRX_LOG_ENTRY_HEADER CurrentEntry;
  451. //SETCALLBACKS();
  452. dwAddress = GetExpression("rdpdr!s_RxLog");
  453. if (!wGetData(dwAddress,&RxLog,sizeof(RX_LOG),"RxLog")) return;
  454. DumpFile = INVALID_HANDLE_VALUE;
  455. if( args && *args ) {
  456. LPSTR lpArgs;
  457. for (;*args;) {
  458. if (*args=='@') { break;}
  459. if ((*args>='0') && (*args<='9')) {
  460. sscanf(args,"%ld",&LogEntries);
  461. LogEntriesSpecified = TRUE;
  462. break;
  463. }
  464. args++;
  465. }
  466. lpArgs = strpbrk(args, "@");
  467. if (lpArgs) {
  468. DumpFile = CreateFileA(lpArgs+1,
  469. GENERIC_READ|GENERIC_WRITE,0,
  470. NULL,
  471. CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,
  472. INVALID_HANDLE_VALUE);
  473. if (DumpFile == INVALID_HANDLE_VALUE){
  474. ULONG rc = LOWORD(GetLastError());
  475. dprintf("Error Opening <%s> is %d.",lpArgs+1,rc);
  476. return;
  477. }
  478. if (!LogEntriesSpecified) {
  479. LogEntries = 99999999; //this will be reset to the right size
  480. }
  481. }
  482. }
  483. // Dump the log header followed by the log entries ...
  484. dprintf("s_RxLog.State %lx\n",RxLog.State);
  485. dprintf("s_RxLog.CurrentEntry %lx\n",RxLog.CurrentEntry);
  486. dprintf("s_RxLog.BaseEntry %lx\n",RxLog.BaseEntry);
  487. dprintf("s_RxLog.EntryLimit %lx\n",RxLog.EntryLimit);
  488. dprintf("s_RxLog.LogBufferSizeInEntries %ld\n",RxLog.LogBufferSizeInEntries);
  489. dprintf("s_RxLog.NumberOfEntriesIgnored %ld\n",RxLog.NumberOfEntriesIgnored);
  490. dprintf("s_RxLog.NumberOfLogWriteAttempts %ld\n",RxLog.NumberOfLogWriteAttempts);
  491. dprintf("s_RxLog.NumberOfLogWraps %ld\n",RxLog.NumberOfLogWraps);
  492. if (LogEntries > RxLog.LogBufferSizeInEntries) {
  493. LogEntries = RxLog.LogBufferSizeInEntries;
  494. }
  495. if (LogEntries < 1) {
  496. LogEntries = 1;
  497. }
  498. CurrentEntry = RxLog.CurrentEntry;
  499. CurrentEntry -= (LogEntries-1);
  500. if (CurrentEntry < RxLog.BaseEntry) {
  501. CurrentEntry += (RxLog.EntryLimit - RxLog.BaseEntry);
  502. }
  503. for (;;) {
  504. ULONG TextPtr;
  505. BOOLEAN ExtraOrdinaryLogEntry;
  506. LogEntries--;
  507. if ( CheckControlC() ) {
  508. return;
  509. }
  510. if (!wGetData((ULONG_PTR)CurrentEntry,&TextPtr,sizeof(TextPtr),"TextPtr")) return;
  511. if (!wGetData(TextPtr,&DataBuffer[0],sizeof(DataBuffer),"LogEntryBuffer")) return;
  512. ExtraOrdinaryLogEntry = (DataBuffer[0] == '#')&&(DataBuffer[1] == '>')&&(DataBuffer[3] == 0);
  513. if (!ExtraOrdinaryLogEntry) {
  514. //dprintf("-%06d: %s\n",LogEntries,DataBuffer);
  515. DumpRoutine(LogEntries,(char *)DataBuffer);
  516. } else {
  517. ULONG BinaryArgs = DataBuffer[2]-'0';
  518. PULONG_PTR x = (PULONG_PTR)&DataBuffer[sizeof(ULONG_PTR)];
  519. char Buffers[12*100]; //CODE.IMPROVEMENT this is stupid but effective
  520. ULONG i;
  521. ULONG_PTR BinaryStringMask;
  522. PSZ ffFormat;
  523. //dprintf("textptr = %08lx, binaryString = %08lx\n", TextPtr, x[0]);
  524. for (i=1,BinaryStringMask=x[0];i<=BinaryArgs;i++) {
  525. if (BinaryStringMask & (1<<(i-1))) {
  526. //dprintf("Stringing %d\n",i);
  527. wGetString(x[i],&Buffers[i*100]); //this could fail!!!!
  528. x[i] = ((ULONG_PTR)&Buffers[i*100]);
  529. //dprintf(" string is %s\n",x[i]);
  530. }
  531. }
  532. ffFormat = (PSZ)(x[1]);
  533. switch (BinaryArgs) {
  534. case 9:
  535. sprintf((char *)AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9]);
  536. break;
  537. case 8:
  538. sprintf((char *)AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6],x[7],x[8]);
  539. break;
  540. case 7:
  541. sprintf((char *)AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6],x[7]);
  542. break;
  543. case 6:
  544. sprintf((char *)AlternateLine,ffFormat,x[2],x[3],x[4],x[5],x[6]);
  545. break;
  546. case 5:
  547. sprintf((char *)AlternateLine,ffFormat,x[2],x[3],x[4],x[5]);
  548. break;
  549. case 4:
  550. sprintf((char *)AlternateLine,ffFormat,x[2],x[3],x[4]);
  551. break;
  552. case 3:
  553. sprintf((char *)AlternateLine,ffFormat,x[2],x[3]);
  554. break;
  555. case 2:
  556. sprintf((char *)AlternateLine,ffFormat,x[2]);
  557. break;
  558. case 1:
  559. sprintf((char *)AlternateLine,ffFormat);
  560. break;
  561. }
  562. DumpRoutine(LogEntries,(char *)AlternateLine);
  563. }
  564. if (LogEntries==0) break;
  565. CurrentEntry++;
  566. if (CurrentEntry==RxLog.EntryLimit) {
  567. CurrentEntry = RxLog.BaseEntry;
  568. }
  569. }
  570. if (DumpFile != INVALID_HANDLE_VALUE) {
  571. CloseHandle(DumpFile);
  572. DumpFile = INVALID_HANDLE_VALUE;
  573. }
  574. }
  575. PCWSTR ExtensionLib = NULL;
  576. HANDLE hExtensionMod = NULL;
  577. ULONG DebugeeArchitecture = 0;
  578. PCWSTR GetExtensionLibPerDebugeeArchitecture(ULONG DebugeeArchitecture);
  579. PWINDBG_EXTENSION_ROUTINE
  580. GetKdExtProcAddress(
  581. IN PCSTR FuncName
  582. )
  583. {
  584. PWINDBG_EXTENSION_ROUTINE WindbgExtRoutine = NULL;
  585. //dprintf( "yaya\n");
  586. if (hExtensionMod == NULL) {
  587. if (DebugeeArchitecture == 0) {
  588. ULONG_PTR pArchitecture;
  589. ReloadSymbols(" rdbss.sys");
  590. pArchitecture = GetExpression("rdpdr!RxProcessorArchitecture");
  591. if (pArchitecture==0) {
  592. dprintf("couldn't get architecture value...\n");
  593. return NULL;
  594. }
  595. if (!wGetData(pArchitecture,&DebugeeArchitecture,sizeof(DebugeeArchitecture),"RxArch")) return NULL;
  596. if ((DebugeeArchitecture&0x0fff0000) != 0xabc0000) {
  597. dprintf("\n Bad DebugeeArchitecture %08lx\n", DebugeeArchitecture);
  598. return(NULL);
  599. }
  600. DebugeeArchitecture &= 0xffff;
  601. }
  602. ExtensionLib = GetExtensionLibPerDebugeeArchitecture(DebugeeArchitecture);
  603. if (ExtensionLib == NULL) {
  604. dprintf( "bad debuggee arch\n");
  605. return(NULL);
  606. }
  607. hExtensionMod = LoadLibrary( ExtensionLib );
  608. if (hExtensionMod == NULL) {
  609. dprintf( "couldn't load %ws\n", ExtensionLib );
  610. return(NULL);
  611. }
  612. }
  613. WindbgExtRoutine = (PWINDBG_EXTENSION_ROUTINE)GetProcAddress( (HINSTANCE)hExtensionMod, FuncName );
  614. if (WindbgExtRoutine == NULL) {
  615. dprintf( "couldn't find %ws%s\n", ExtensionLib, FuncName );
  616. }
  617. return WindbgExtRoutine;
  618. }
  619. #define CALL_THRU(NAME,ARGS) { \
  620. PWINDBG_EXTENSION_ROUTINE WindbgExtRoutine = GetKdExtProcAddress(NAME); \
  621. if (WindbgExtRoutine != NULL) { \
  622. (WindbgExtRoutine)( hCurrentProcess, \
  623. hCurrentThread, \
  624. dwCurrentPc, \
  625. dwProcessor, \
  626. ARGS \
  627. ); \
  628. } \
  629. }
  630. DECLARE_API( testr )
  631. {
  632. CALL_THRU ( "threadfields", "");
  633. }
  634. DECLARE_API( dump );
  635. VOID
  636. __FollowOnHelper (
  637. PFOLLOWON_HELPER_ROUTINE Callee,
  638. HANDLE hCurrentProcess,
  639. HANDLE hCurrentThread,
  640. ULONG dwCurrentPc,
  641. ULONG dwProcessor,
  642. PCSTR args
  643. )
  644. {
  645. BYTE Name[100], Buffer2[200];
  646. FOLLOWON_HELPER_RETURNS ret;
  647. PPERSISTENT_RDPDRKD_INFO p;
  648. p = LocatePersistentInfoFromView();
  649. if (!p) {
  650. dprintf("Couldn't allocate perstistent info buffer...sorry...\n");
  651. return;
  652. }
  653. ret = Callee(p,Name,Buffer2);
  654. if (p!= NULL) FreePersistentInfoView(p);
  655. p = NULL;
  656. switch (ret) {
  657. case FOLLOWONHELPER_DUMP:
  658. dump(hCurrentProcess,
  659. hCurrentThread,
  660. dwCurrentPc,
  661. dwProcessor,
  662. (char *)Buffer2
  663. );
  664. break;
  665. case FOLLOWONHELPER_CALLTHRU:
  666. CALL_THRU ( (char *)Name, (char *)Buffer2);
  667. break;
  668. case FOLLOWONHELPER_ERROR:
  669. dprintf("%s",Buffer2);
  670. break;
  671. case FOLLOWONHELPER_DONE:
  672. break;
  673. }
  674. return;
  675. }
  676. #define FollowOnHelper(a) { \
  677. __FollowOnHelper(a, \
  678. hCurrentProcess, \
  679. hCurrentThread, \
  680. dwCurrentPc, \
  681. dwProcessor, \
  682. args); \
  683. }
  684. DECLARE_FOLLOWON_HELPER_CALLEE(FcbFollowOn);
  685. DECLARE_API( fcb )
  686. {
  687. FollowOnHelper(FcbFollowOn);
  688. }
  689. DECLARE_API( flags )
  690. {
  691. ULONG i,mask,newline,value;
  692. if( args && *args ) {
  693. sscanf(args,"%lx",&value);
  694. dprintf("Flags for %08lx\n",value);
  695. } else {
  696. dprintf("error in flags: no value presented\n");
  697. return;
  698. }
  699. for (i=newline=0,mask=1;i<32;i++,mask<<=1) {
  700. if (value&mask) {
  701. dprintf(" %02d 0x%08lx%c",i,mask,(newline==0)?' ':'\n');
  702. newline ^= 1;
  703. }
  704. }
  705. if (newline) {
  706. dprintf("\n");
  707. }
  708. }
  709. DECLARE_API( cxr )
  710. {
  711. ULONG_PTR dwAddress,cxr;
  712. BYTE NumBuffer[16];
  713. RX_LOG RxLog;
  714. ULONG LogEntries = 30;
  715. PRX_LOG_ENTRY_HEADER CurrentEntry;
  716. //SETCALLBACKS();
  717. dwAddress = GetExpression("rdpdr!RxExpCXR");
  718. if (!wGetData(dwAddress,&cxr,sizeof(cxr),"cxr")) return;
  719. dprintf("\nRxExpCXR=%08lx\n",cxr);
  720. sprintf((char *)NumBuffer,"%08lx \n",cxr);
  721. CALL_THRU ( "cxr", (char *)NumBuffer);
  722. if (DebugeeArchitecture==0) {
  723. CALL_THRU ( "kb", "");
  724. }
  725. }
  726. VOID dprintfsprintfbuffer(BYTE *Buffer)
  727. {
  728. dprintf("%s\n",Buffer);
  729. }
  730. DECLARE_API(ddd);
  731. #if DBG
  732. VOID ListRefs(ULONG_PTR dwAddress, BOOL ShowStack,
  733. HANDLE hCurrentProcess,
  734. HANDLE hCurrentThread,
  735. ULONG dwCurrentPc,
  736. ULONG dwProcessor)
  737. {
  738. ULONG_PTR dwRecordListAddr;
  739. ULONG_PTR dwCurrentAddr;
  740. ULONG_PTR dwAddr;
  741. ReferenceTraceRecord CurrentRecord;
  742. ULONG_PTR dwTotalRefs;
  743. ULONG_PTR dwRefs;
  744. ULONG_PTR dwRefsPrinted;
  745. char szObjectName[32];
  746. dwRecordListAddr = GetExpression("rdpdr!RefCount___TraceRecordList");
  747. if (dwRecordListAddr == 0) {
  748. dprintf("Unable to get address of rdpdr!RefCount___TraceRecordList\n");
  749. return;
  750. }
  751. dwAddr = GetExpression("rdpdr!RefCount___dwReferenceTraceIndex");
  752. if (dwAddr == 0) {
  753. dprintf("Unable to get address of rdpdr!RefCount___dwReferenceTraceIndex\n");
  754. return;
  755. }
  756. if (!wGetData(dwAddr, &dwTotalRefs, sizeof(dwTotalRefs), "ULONG_PTR")) {
  757. return;
  758. }
  759. if (dwAddress != 0xFFFFFFFF) {
  760. dprintf("dumping references to object %p\n", dwAddress);
  761. }
  762. dprintf("TraceRecord References ObjectPointer ObjectType\n");
  763. dwCurrentAddr = dwRecordListAddr;
  764. dwRefs = 0;
  765. dwRefsPrinted = 0;
  766. while(dwRefs < dwTotalRefs && dwCurrentAddr < dwRecordListAddr + sizeof(RefCount::_TraceRecordList))
  767. {
  768. if (wGetData(dwCurrentAddr, &CurrentRecord, sizeof(CurrentRecord), "ReferenceTraceRecord")) {
  769. if (wGetData((ULONG_PTR)CurrentRecord.ClassName, &szObjectName, sizeof(szObjectName), "Object Name")) {
  770. szObjectName[sizeof(szObjectName) - 1] = 0;
  771. } else {
  772. szObjectName[0] = 0;
  773. }
  774. if (dwAddress == 0xFFFFFFFF || (ULONG_PTR)CurrentRecord.pRefCount == dwAddress) {
  775. dprintf("%p %p %p %s\n", dwCurrentAddr, CurrentRecord.refs, CurrentRecord.pRefCount, szObjectName);
  776. dwRefsPrinted++;
  777. if (ShowStack) {
  778. char szCmd[32];
  779. sprintf(szCmd, "ReferenceTraceRecord@%p", dwCurrentAddr);
  780. ddd(hCurrentProcess, hCurrentThread, dwCurrentPc, dwProcessor, szCmd);
  781. }
  782. }
  783. } else {
  784. break;
  785. }
  786. dwCurrentAddr += sizeof(CurrentRecord);
  787. dwRefs++;
  788. }
  789. dprintf("Printed %ld of %ld paged in objects of %ld records\n", dwRefsPrinted, dwRefs, dwTotalRefs);
  790. }
  791. #endif
  792. DECLARE_API( trc )
  793. {
  794. #if DBG
  795. ULONG_PTR dwRecentTracesAddr;
  796. ULONG_PTR dwCurrentMsgAddr;
  797. ULONG_PTR dwCurrentAddr;
  798. ULONG_PTR dwCurrentMsg;
  799. ULONG_PTR dwFirstLine;
  800. ULONG_PTR dwFinalLine;
  801. ULONG_PTR dwCurrentLine;
  802. ULONG_PTR dwLinesToPrint;
  803. ULONG_PTR dwLines = 0;
  804. char szTraceLine[TRC_BUFFER_SIZE];
  805. if (!ParseTrc(args, &dwLines)) {
  806. return;
  807. }
  808. dwRecentTracesAddr = GetExpression("rdpdr!TRC_RecentTraces");
  809. if (dwRecentTracesAddr == 0) {
  810. dprintf("Unable to get address of rdpdr!TRC_RecentTraces\n");
  811. return;
  812. }
  813. dwCurrentMsgAddr = GetExpression("rdpdr!TRC_CurrentMsg");
  814. if (dwCurrentMsgAddr == 0) {
  815. dprintf("Unable to get address of rdpdr!TRC_CurrentMsg\n");
  816. return;
  817. }
  818. //
  819. // Look up how many traces have been done
  820. //
  821. if (!wGetData(dwCurrentMsgAddr, &dwCurrentMsg, sizeof(dwCurrentMsg), "ULONG_PTR")) {
  822. return;
  823. }
  824. if (dwCurrentMsg == 0xFFFFFFFF) {
  825. dprintf("No tracing\n");
  826. return;
  827. }
  828. dprintf("Total Traces: %ld\n", dwCurrentMsg);
  829. if (dwCurrentMsg > TRC_RamMsgMask) {
  830. //
  831. // We wrapped at least once
  832. //
  833. dwFirstLine = (dwCurrentMsg + 1) & TRC_RamMsgMask;
  834. dwFinalLine = (dwCurrentMsg) & TRC_RamMsgMask;
  835. dwLinesToPrint = TRC_RamMsgMax;
  836. } else {
  837. dwFirstLine = 0;
  838. dwFinalLine = dwCurrentMsg;
  839. dwLinesToPrint = dwFinalLine + 1;
  840. }
  841. if (dwLinesToPrint > dwLines) {
  842. // Advance first line by the difference
  843. dwFirstLine = (dwFirstLine + (dwLinesToPrint - dwLines)) & TRC_RamMsgMask;
  844. // Adjust number of lines downward
  845. dwLinesToPrint = dwLines;
  846. }
  847. dwCurrentLine = dwFirstLine;
  848. while(dwLinesToPrint > 0)
  849. {
  850. dwCurrentAddr = dwRecentTracesAddr + dwCurrentLine * TRC_BUFFER_SIZE;
  851. if (wGetData(dwCurrentAddr, &szTraceLine[0], sizeof(szTraceLine), "TraceLine")) {
  852. dprintf("%s", szTraceLine);
  853. } else {
  854. break;
  855. }
  856. dwCurrentLine = (dwCurrentLine + 1) & TRC_RamMsgMask;
  857. dwLinesToPrint--;
  858. }
  859. #endif
  860. }
  861. #if DBG
  862. BOOL ParseTrc(PCSTR args, DWORD *dwLines)
  863. {
  864. PCSTR p = args;
  865. enum tagParseState {
  866. Nominal,
  867. Usage,
  868. PostMinus,
  869. StartLines,
  870. Lines
  871. } ParseState = Nominal;
  872. DWORD LinesT = 0;
  873. if (args == NULL) {
  874. return TRUE;
  875. }
  876. while (ParseState != Usage && *p) {
  877. switch(ParseState) {
  878. case Nominal:
  879. switch (*p) {
  880. case '-':
  881. ParseState = PostMinus;
  882. break;
  883. case ' ':
  884. case '\t':
  885. break;
  886. default:
  887. ParseState = Usage;
  888. }
  889. break;
  890. case PostMinus:
  891. switch (*p) {
  892. case 'l':
  893. ParseState = StartLines;
  894. break;
  895. default:
  896. ParseState = Usage;
  897. }
  898. break;
  899. case Lines:
  900. case StartLines:
  901. int i;
  902. i = (*p) - '0';
  903. if (i >= 0 && i <= 9) {
  904. //
  905. // Now past initial whitespace
  906. //
  907. ParseState = Lines;
  908. LinesT *= 10;
  909. LinesT += i;
  910. } else {
  911. switch (*p) {
  912. case ' ':
  913. case '\t':
  914. if (ParseState == Lines) {
  915. // Must be done
  916. ParseState = Nominal;
  917. } // else skip initial whitespace
  918. break;
  919. default:
  920. ParseState = Usage;
  921. }
  922. }
  923. break;
  924. }
  925. p++;
  926. }
  927. if (ParseState == Usage) {
  928. dprintf("Error in arguments: %s\n", args);
  929. dprintf(" %*c\n", p - args, '^');
  930. dprintf("usage: trc [-l] [<numlines>]\n\n");
  931. dprintf(" numlines: number of lines to trace\n");
  932. return FALSE;
  933. } else {
  934. *dwLines = LinesT;
  935. return TRUE;
  936. }
  937. }
  938. #endif // DBG
  939. DECLARE_API( listref )
  940. {
  941. ULONG_PTR RefObj = 0xFFFFFFFF;
  942. if( args && *args ) {
  943. RefObj = GetExpression( args );
  944. }
  945. #if DBG
  946. ListRefs(RefObj, FALSE, hCurrentProcess, hCurrentThread, dwCurrentPc, dwProcessor);
  947. #endif
  948. }
  949. DECLARE_API( listreff )
  950. {
  951. ULONG_PTR RefObj = 0xFFFFFFFF;
  952. if( args && *args ) {
  953. RefObj = GetExpression( args );
  954. }
  955. #if DBG
  956. ListRefs(RefObj, TRUE, hCurrentProcess, hCurrentThread, dwCurrentPc, dwProcessor);
  957. #endif
  958. }