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.

630 lines
19 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. strucsup.c
  5. Abstract:
  6. Library routines for dumping data structures given a meta level descrioption
  7. Author:
  8. Balan Sethu Raman (SethuR) 11-May-1994
  9. Notes:
  10. Revision History:
  11. 11-Nov-1994 SethuR Created
  12. --*/
  13. #define KDEXT_32BIT
  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 <rdpdrkd.h>
  25. #include <ntrxdef.h>
  26. #include <rxtypes.h>
  27. //#include <rxlog.h>
  28. //need this for unaligned smbget macros
  29. #include <smbgtpt.h>
  30. extern WINDBG_EXTENSION_APIS ExtensionApis;
  31. //EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 };
  32. #define ERRPRT dprintf
  33. #define PRINTF dprintf
  34. #define NL 1
  35. #define NONL 0
  36. BOOLEAN
  37. wGetData( ULONG_PTR dwAddress, PVOID ptr, ULONG size, IN PSZ type);
  38. //
  39. // No. of columns used to display struct fields;
  40. //
  41. ULONG s_MaxNoOfColumns = 3;
  42. #ifndef RXKD_2col
  43. ULONG s_NoOfColumns = 1;
  44. #else
  45. ULONG s_NoOfColumns = 2;
  46. #endif
  47. /*
  48. * Displays all the fields of a given struct. This is the driver routine that is called
  49. * with the appropriate descriptor array to display all the fields in a given struct.
  50. */
  51. char *NewLine = "\n";
  52. char *FieldSeparator = " ";
  53. #define NewLineForFields(FieldNo) \
  54. ((((FieldNo) % s_NoOfColumns) == 0) ? NewLine : FieldSeparator)
  55. #define FIELD_NAME_LENGTH 30
  56. /*
  57. * Print out an optional message, a UNICODE_STRING, and maybe a new-line
  58. */
  59. BOOL
  60. wPrintStringU( IN LPSTR PrefixMsg OPTIONAL, IN PUNICODE_STRING puStr, IN LPSTR SuffixMsg OPTIONAL )
  61. {
  62. PWCHAR StringData;
  63. UNICODE_STRING UnicodeString;
  64. ULONG BytesRead;
  65. if (PrefixMsg == NULL) {
  66. PrefixMsg = "";
  67. }
  68. if (SuffixMsg == NULL) {
  69. SuffixMsg = "";
  70. }
  71. StringData = (PWCHAR)LocalAlloc( LPTR, puStr->Length + sizeof(UNICODE_NULL));
  72. if( StringData == NULL ) {
  73. dprintf( "Out of memory!\n" );
  74. return FALSE;
  75. }
  76. UnicodeString.Buffer = StringData; //puStr->Buffer;
  77. UnicodeString.Length = puStr->Length;
  78. UnicodeString.MaximumLength = puStr->MaximumLength;
  79. ReadMemory( (ULONG_PTR)puStr->Buffer,
  80. StringData,
  81. puStr->Length,
  82. &BytesRead);
  83. if (BytesRead) {
  84. dprintf("%s%wZ%s", PrefixMsg, &UnicodeString, SuffixMsg );
  85. } else {
  86. dprintf("MEMORYREAD FAILED %s%s",PrefixMsg,SuffixMsg);
  87. }
  88. LocalFree( (HLOCAL)StringData );
  89. return BytesRead;
  90. }
  91. VOID
  92. SetFlagString(
  93. ULONG Value,
  94. PCHAR FlagString
  95. )
  96. {
  97. ULONG i,t,mask;
  98. *FlagString = '('; FlagString++;
  99. for (i=t=0,mask=1;i<32;i++,mask<<=1) {
  100. //PRINTF("hithere %08lx %08lx %08lx\n",Value,mask,i);
  101. if (i==t+10) {
  102. *FlagString = ':'; FlagString++;
  103. t=t+10;
  104. }
  105. if (Value&mask) {
  106. *FlagString = '0'+(UCHAR)(i-t); FlagString++;
  107. }
  108. }
  109. *FlagString = ')'; FlagString++;
  110. *FlagString = 0;
  111. }
  112. VOID
  113. PrintStructFields( ULONG_PTR dwAddress, VOID *ptr, FIELD_DESCRIPTOR *pFieldDescriptors )
  114. {
  115. int i;
  116. // Display the fields in the struct.
  117. for( i=0; pFieldDescriptors->Name; i++, pFieldDescriptors++ ) {
  118. // Indentation to begin the struct display.
  119. PRINTF( " " );
  120. if( strlen( pFieldDescriptors->Name ) > FIELD_NAME_LENGTH ) {
  121. PRINTF( "%-17s...%s ", pFieldDescriptors->Name, pFieldDescriptors->Name+strlen(pFieldDescriptors->Name)-10 );
  122. } else {
  123. PRINTF( "%-30s ", pFieldDescriptors->Name );
  124. }
  125. switch( pFieldDescriptors->FieldType ) {
  126. case FieldTypeByte:
  127. case FieldTypeChar:
  128. PRINTF( "%-16X%s",
  129. *(BYTE *)(((char *)ptr) + pFieldDescriptors->Offset ),
  130. NewLineForFields(i) );
  131. break;
  132. case FieldTypeBoolean:
  133. PRINTF( "%-16s%s",
  134. *(BOOLEAN *)(((char *)ptr) + pFieldDescriptors->Offset ) ? "TRUE" : "FALSE",
  135. NewLineForFields(i));
  136. break;
  137. case FieldTypeBool:
  138. PRINTF( "%-16s%s",
  139. *(BOOLEAN *)(((char *)ptr) + pFieldDescriptors->Offset ) ? "TRUE" : "FALSE",
  140. NewLineForFields(i));
  141. break;
  142. case FieldTypePointer:
  143. PRINTF( "%-16X%s",
  144. *(ULONG *)(((char *)ptr) + pFieldDescriptors->Offset ),
  145. NewLineForFields(i) );
  146. break;
  147. case FieldTypeULong:
  148. case FieldTypeLong:
  149. PRINTF( "%-16X%s",
  150. *(ULONG *)(((char *)ptr) + pFieldDescriptors->Offset ),
  151. NewLineForFields(i) );
  152. break;
  153. case FieldTypeULongUnaligned:
  154. case FieldTypeLongUnaligned:
  155. PRINTF( "%-16X%s",
  156. SmbGetUlong( (BYTE *)(((char *)ptr) + pFieldDescriptors->Offset ) ),
  157. NewLineForFields(i) );
  158. break;
  159. case FieldTypeShort:
  160. PRINTF( "%-16X%s",
  161. *(SHORT *)(((char *)ptr) + pFieldDescriptors->Offset ),
  162. NewLineForFields(i) );
  163. break;
  164. case FieldTypeUShort:
  165. PRINTF( "%-16X%s",
  166. *(USHORT *)(((char *)ptr) + pFieldDescriptors->Offset ),
  167. NewLineForFields(i) );
  168. break;
  169. case FieldTypeUShortUnaligned:
  170. PRINTF( "%-16X%s",
  171. SmbGetUshort( (BYTE *)(((char *)ptr) + pFieldDescriptors->Offset ) ),
  172. NewLineForFields(i) );
  173. break;
  174. case FieldTypeULongFlags:{ULONG Value; char FlagString[60];
  175. Value = *(ULONG *)(((char *)ptr) + pFieldDescriptors->Offset );
  176. SetFlagString(Value,FlagString);
  177. PRINTF( "%-16X%s%s", Value, FlagString,
  178. NewLineForFields(i) );
  179. break;}
  180. case FieldTypeUShortFlags:{USHORT Value; char FlagString[60];
  181. Value = *(USHORT *)(((char *)ptr) + pFieldDescriptors->Offset ),
  182. SetFlagString(Value,FlagString);
  183. PRINTF( "%-16X%s%s", Value, FlagString,
  184. NewLineForFields(i) );
  185. break;}
  186. case FieldTypeUnicodeString:
  187. wPrintStringU( NULL, (UNICODE_STRING *)(((char *)ptr) + pFieldDescriptors->Offset ), NULL );
  188. PRINTF( NewLine );
  189. break;
  190. //case FieldTypeAnsiString:
  191. // //PrintStringA( NULL, (ANSI_STRING *)(((char *)ptr) + pFieldDescriptors->Offset ), NONL );
  192. // //PRINTF( NewLine );
  193. // PRINTF( NewLine );
  194. // break;
  195. case FieldTypeSymbol:
  196. {
  197. UCHAR SymbolName[ 200 ];
  198. ULONG_PTR Displacement;
  199. ULONG sym = (*(ULONG *)(((char *)ptr) + pFieldDescriptors->Offset ));
  200. GetSymbol( sym, SymbolName, &Displacement );
  201. PRINTF( "%-16s%s",
  202. SymbolName,
  203. NewLineForFields(i) );
  204. }
  205. break;
  206. case FieldTypeEnum:
  207. {
  208. ULONG EnumValue;
  209. ENUM_VALUE_DESCRIPTOR *pEnumValueDescr;
  210. // Get the associated numericla value.
  211. EnumValue = *((ULONG *)(((BYTE *)ptr) + pFieldDescriptors->Offset));
  212. if ((pEnumValueDescr = pFieldDescriptors->AuxillaryInfo.pEnumValueDescriptor)
  213. != NULL) {
  214. //
  215. // An auxilary textual description of the value is
  216. // available. Display it instead of the numerical value.
  217. //
  218. LPSTR pEnumName = NULL;
  219. while (pEnumValueDescr->EnumName != NULL) {
  220. if (EnumValue == pEnumValueDescr->EnumValue) {
  221. pEnumName = pEnumValueDescr->EnumName;
  222. break;
  223. }
  224. pEnumValueDescr++;
  225. }
  226. if (pEnumName != NULL) {
  227. PRINTF( "%-16s ", pEnumName );
  228. } else {
  229. PRINTF( "%-4d (%-10s) ", EnumValue,"@$#%^&*");
  230. }
  231. } else {
  232. //
  233. // No auxilary information is associated with the ehumerated type
  234. // print the numerical value.
  235. //
  236. PRINTF( "%-16d",EnumValue);
  237. }
  238. PRINTF( NewLine );
  239. }
  240. break;
  241. case FieldTypeStruct:
  242. PRINTF( "@%-15X%s",
  243. (dwAddress + pFieldDescriptors->Offset ),
  244. NewLineForFields(i) );
  245. break;
  246. case FieldTypeLargeInteger:
  247. case FieldTypeFileTime:
  248. default:
  249. ERRPRT( "Unrecognized field type %c for %s\n", pFieldDescriptors->FieldType, pFieldDescriptors->Name );
  250. break;
  251. }
  252. }
  253. }
  254. DECLARE_API( columns )
  255. {
  256. ULONG NoOfColumns;
  257. int i;
  258. //SETCALLBACKS();
  259. //sscanf(lpArgumentString,"%ld",&NoOfColumns);
  260. sscanf(args,"%ld",&NoOfColumns);
  261. if (NoOfColumns > s_MaxNoOfColumns) {
  262. // PRINTF( "No. Of Columns exceeds maximum(%ld) -- directive Ignored\n", s_MaxNoOfColumns );
  263. } else {
  264. s_NoOfColumns = NoOfColumns;
  265. }
  266. PRINTF("Not Yet Implemented\n");
  267. return;
  268. }
  269. #define NAME_DELIMITER '@'
  270. #define NAME_DELIMITERS "@"
  271. #define INVALID_INDEX 0xffffffff
  272. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  273. ULONG SearchStructs(LPSTR lpArgument)
  274. {
  275. ULONG i = 0;
  276. STRUCT_DESCRIPTOR *pStructs = Structs;
  277. ULONG NameIndex = INVALID_INDEX;
  278. ULONG ArgumentLength = strlen(lpArgument);
  279. BOOLEAN fAmbigous = FALSE;
  280. while ((pStructs->StructName != 0)) {
  281. int Result = _strnicmp(lpArgument,
  282. pStructs->StructName,
  283. MIN(strlen(pStructs->StructName),ArgumentLength));
  284. if (Result == 0) {
  285. if (NameIndex != INVALID_INDEX) {
  286. // We have encountered duplicate matches. Print out the
  287. // matching strings and let the user disambiguate.
  288. fAmbigous = TRUE;
  289. break;
  290. } else {
  291. NameIndex = i;
  292. }
  293. }
  294. pStructs++;i++;
  295. }
  296. if (fAmbigous) {
  297. PRINTF("Ambigous Name Specification -- The following structs match\n");
  298. PRINTF("%s\n",Structs[NameIndex].StructName);
  299. PRINTF("%s\n",Structs[i].StructName);
  300. while (pStructs->StructName != 0) {
  301. if (_strnicmp(lpArgument,
  302. pStructs->StructName,
  303. MIN(strlen(pStructs->StructName),ArgumentLength)) == 0) {
  304. PRINTF("%s\n",pStructs->StructName);
  305. }
  306. pStructs++;
  307. }
  308. PRINTF("Dumping Information for %s\n",Structs[NameIndex].StructName);
  309. }
  310. return(NameIndex);
  311. }
  312. VOID DisplayStructs()
  313. {
  314. STRUCT_DESCRIPTOR *pStructs = Structs;
  315. PRINTF("The following structs are handled .... \n");
  316. while (pStructs->StructName != 0) {
  317. PRINTF("\t%s\n",pStructs->StructName);
  318. pStructs++;
  319. }
  320. }
  321. PPERSISTENT_RDPDRKD_INFO
  322. LocatePersistentInfoFromView()
  323. /*
  324. the purpose of this routine is to allocate or find the named section that holds the
  325. data we expect to find across calls. the way that we make this persitent is that we
  326. do not close the handle used to create the view. it will go away when the process does.
  327. */
  328. {
  329. BYTE SectionName[128];
  330. DWORD SectionSize;
  331. DWORD ProcessId;
  332. HANDLE h;
  333. BOOLEAN CreatedSection = FALSE;
  334. PPERSISTENT_RDPDRKD_INFO p;
  335. ProcessId = GetCurrentProcessId();
  336. SectionSize = sizeof(PERSISTENT_RDPDRKD_INFO);
  337. sprintf((char *)SectionName,"RdpDrKdSection_%08lx",ProcessId);
  338. //PRINTF("sectionname=%s, size=%x\n",SectionName,SectionSize);
  339. h = OpenFileMappingA(
  340. FILE_MAP_WRITE, //DWORD dwDesiredAccess, // access mode
  341. FALSE, //BOOL bInheritHandle, // inherit flag
  342. (char *)SectionName //LPCTSTR lpName // address of name of file-mapping object
  343. );
  344. if (h==NULL) {
  345. h = CreateFileMappingA(
  346. (HANDLE)0xFFFFFFFF, // HANDLE hFile, // handle of file to map
  347. NULL, //LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // optional security attributes
  348. PAGE_READWRITE, //DWORD flProtect, // protection for mapping object
  349. 0, //DWORD dwMaximumSizeHigh, // high-order 32 bits of object size
  350. SectionSize, //DWORD dwMaximumSizeLow, // low-order 32 bits of object size
  351. (char *)SectionName //LPCTSTR lpName // name of file-mapping object
  352. );
  353. if (h==NULL) {
  354. return(FALSE);
  355. }
  356. CreatedSection = TRUE;
  357. }
  358. //now we have a filemapping....get a view.....
  359. p = (PPERSISTENT_RDPDRKD_INFO)MapViewOfFile(h,FILE_MAP_WRITE,0,0,0);
  360. if (p==NULL) {
  361. CloseHandle(h);
  362. return(NULL);
  363. }
  364. if (CreatedSection) {
  365. //zero the stuff that needs to be zeroed....
  366. ULONG i;
  367. p->IdOfLastDump = 0;
  368. for (i=0;i<100;i++) {
  369. p->LastAddressDumped[i] = 0;
  370. }
  371. p->OpenCount = 100;
  372. } else {
  373. CloseHandle(h);
  374. p->OpenCount++;
  375. }
  376. //PRINTF("Opencount for persistent section = %08lx\n",p->OpenCount);
  377. return(p);
  378. }
  379. VOID
  380. FreePersistentInfoView (
  381. PPERSISTENT_RDPDRKD_INFO p
  382. )
  383. {
  384. UnmapViewOfFile(p);
  385. }
  386. VOID
  387. DumpAStruct (
  388. ULONG_PTR dwAddress,
  389. STRUCT_DESCRIPTOR *pStruct
  390. )
  391. {
  392. DWORD Index = (DWORD)(pStruct - Structs);
  393. DWORD SizeToRead = min(pStruct->StructSize,2048);
  394. PPERSISTENT_RDPDRKD_INFO p;
  395. p = LocatePersistentInfoFromView();
  396. PRINTF("top @ %lx and %lx for %s(%d,%d)\n",dwAddress,p,pStruct->StructName,Index,p->IdOfLastDump);
  397. if (!p) {
  398. PRINTF("Couldn't allocate perstistent info buffer...sorry...\n");
  399. return;
  400. }
  401. if ((dwAddress==0) &&(Index<100)) {
  402. dwAddress = p->LastAddressDumped[Index];
  403. PRINTF("setting @ %lx and %lx for %s\n",dwAddress,p->LastAddressDumped[Index],pStruct->StructName);
  404. }
  405. if (wGetData(dwAddress,&p->StructDumpBuffer[0],SizeToRead,pStruct->StructName)) {
  406. p->LastAddressDumped[Index] = dwAddress;
  407. p->IdOfLastDump = pStruct->EnumManifest;
  408. p->IndexOfLastDump = Index;
  409. PRINTF("++++++++++++++++ %s(%d/%d)@%lx ---+++++++++++++\n",
  410. pStruct->StructName,
  411. p->IdOfLastDump,p->IndexOfLastDump,
  412. dwAddress);
  413. PrintStructFields(
  414. dwAddress,
  415. &p->StructDumpBuffer[0],
  416. pStruct->FieldDescriptors);
  417. PRINTF("---------------- %s@%lx ----------------\n",
  418. pStruct->StructName,
  419. dwAddress);
  420. }
  421. if (p!= NULL) FreePersistentInfoView(p);
  422. return;
  423. }
  424. DECLARE_API( dump )
  425. {
  426. ULONG_PTR dwAddress;
  427. //SETCALLBACKS();
  428. if( args && *args ) {
  429. // Parse the argument string to determine the structure to be displayed.
  430. // Scan for the NAME_DELIMITER ( '@' ).
  431. LPSTR lpName = (PSTR)args;
  432. LPSTR lpArgs = strpbrk(args, NAME_DELIMITERS);
  433. ULONG Index;
  434. if (lpArgs) {
  435. //
  436. // The specified command is of the form
  437. // dump <name>@<address expr.>
  438. //
  439. // Locate the matching struct for the given name. In the case
  440. // of ambiguity we seek user intervention for disambiguation.
  441. //
  442. // We do an inplace modification of the argument string to
  443. // facilitate matching.
  444. //
  445. *lpArgs = '\0';
  446. for (;*lpName==' ';) { lpName++; } //skip leading blanks
  447. Index = SearchStructs(lpName);
  448. //
  449. // Let us restore the original value back.
  450. //
  451. *lpArgs = NAME_DELIMITER;
  452. if (INVALID_INDEX != Index) {
  453. BYTE DataBuffer[512];
  454. dwAddress = GetExpression( ++lpArgs );
  455. DumpAStruct(dwAddress,&Structs[Index]);
  456. //if (wGetData(dwAddress,DataBuffer,Structs[Index].StructSize,"..structure")) {
  457. //
  458. // PRINTF(
  459. // "++++++++++++++++ %s@%lx ++++++++++++++++\n",
  460. // Structs[Index].StructName,
  461. // dwAddress);
  462. // PrintStructFields(
  463. // dwAddress,
  464. // &DataBuffer,
  465. // Structs[Index].FieldDescriptors);
  466. // PRINTF(
  467. // "---------------- %s@%lx ----------------\n",
  468. // Structs[Index].StructName,
  469. // dwAddress);
  470. //} else {
  471. // PRINTF("Error reading Memory @ %lx\n",dwAddress);
  472. //}
  473. } else {
  474. // No matching struct was found. Display the list of
  475. // structs currently handled.
  476. DisplayStructs();
  477. }
  478. } else {
  479. #if 0
  480. //
  481. // The command is of the form
  482. // dump <name>
  483. //
  484. // Currently we do not handle this. In future we will map it to
  485. // the name of a global variable and display it if required.
  486. //
  487. DisplayStructs();
  488. #endif
  489. //
  490. // here we try to figure out what to display based on the context....whoa, nellie!
  491. //
  492. USHORT Tag;
  493. STRUCT_DESCRIPTOR *pStructs = Structs;
  494. ULONG NameIndex = INVALID_INDEX;
  495. BYTE DataBuffer[512];
  496. //ULONG ArgumentLength = strlen(lpArgument);
  497. //BOOLEAN fAmbigous = FALSE;
  498. dwAddress = GetExpression( args );
  499. if (!wGetData(dwAddress,&Tag,sizeof(Tag),"..structure TAG")) return;
  500. PRINTF("here's the tag: %04lx\n",Tag);
  501. //look thru the table for matching structs
  502. while ((pStructs->StructName != 0)) {
  503. int Result = (Tag&pStructs->MatchMask)==pStructs->MatchValue;
  504. if (Result != 0) {
  505. DumpAStruct(dwAddress,pStructs);
  506. break;
  507. }
  508. pStructs++;
  509. }
  510. }
  511. } else {
  512. DisplayStructs();
  513. }
  514. return;
  515. }
  516. DECLARE_API( ddd )
  517. {
  518. dump( hCurrentProcess,
  519. hCurrentThread,
  520. dwCurrentPc,
  521. dwProcessor,
  522. args
  523. );
  524. }