Source code of Windows XP (NT5)
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.

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