/*++ Copyright (c) 1992-2000 Microsoft Corporation Module Name: util.c Abstract: WinDbg Extension Api Environment: User Mode. Revision History: --*/ #include "precomp.h" #pragma hdrstop ULONG GetBitFieldOffset ( IN LPSTR Type, IN LPSTR Field, OUT PULONG pOffset, OUT PULONG pSize ) { FIELD_INFO flds = { Field, "", 0, DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS | DBG_DUMP_FIELD_SIZE_IN_BITS, 0, NULL}; SYM_DUMP_PARAM Sym = { sizeof (SYM_DUMP_PARAM), Type, DBG_DUMP_NO_PRINT, 0, NULL, NULL, NULL, 1, &flds }; ULONG Err, i=0; LPSTR dot, last=Field; Sym.nFields = 1; Err = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size ); *pOffset = (ULONG) (flds.address - Sym.addr); *pSize = flds.size; return Err; } ULONG GetUlongFromAddress ( ULONG64 Location ) { ULONG Value; ULONG result; if ((!ReadMemory(Location,&Value,sizeof(ULONG),&result)) || (result < sizeof(ULONG))) { dprintf("unable to read from %08x\n",Location); return 0; } return Value; } ULONG64 GetPointerFromAddress ( ULONG64 Location ) { ULONG64 Value; ULONG result; if (!ReadPointer(Location,&Value)) { dprintf("unable to read from %08p\n",Location); return 0; } return Value; } ULONG GetUlongValue ( PCHAR String ) { ULONG64 Location; ULONG Value; ULONG result; Location = GetExpression( String ); if (!Location) { dprintf("unable to get %s\n",String); return 0; } return GetUlongFromAddress( Location ); } ULONG64 GetPointerValue ( PCHAR String ) { ULONG64 Location, Val=0; Location = GetExpression( String ); if (!Location) { dprintf("unable to get %s\n",String); return 0; } ReadPointer(Location, &Val); return Val; } #if 0 VOID DumpImageName( IN ULONG64 Process ) { ULONG64 ImageFileName; STRING String; ULONG Result; IN WCHAR Buf[512]; if ( !GetFieldValue(Process, "EPROCESS", "ImageFileName.Buffer", ImageFileName ) ){ wcscpy(Buf,L"*** image name unavailable ***"); if ( ReadMemory( ImageFileName, &String, sizeof(STRING), &Result) ) { if ( ReadMemory( (DWORD)String.Buffer, &Buf[0], String.Length, &Result) ) { Buf[String.Length/sizeof(WCHAR)] = UNICODE_NULL; } } } else { wcscpy(Buf,L"System Process"); } dprintf("%ws",Buf); } #endif BOOLEAN DbgRtlIsRightChild( ULONG64 pLinks, ULONG64 Parent ) { ULONG64 RightChild; if (Parent == pLinks) { return FALSE; } if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "RightChild", RightChild)) { return FALSE; } if (RightChild == pLinks) { return TRUE; } return FALSE; } BOOLEAN DbgRtlIsLeftChild( ULONG64 pLinks, ULONG64 Parent ) { ULONG64 LeftChild; if (Parent == pLinks) { return FALSE; } if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "LeftChild", LeftChild)) { return FALSE; } if (LeftChild == pLinks) { return TRUE; } return FALSE; } ULONG DumpSplayTree( IN ULONG64 pSplayLinks, IN PDUMP_SPLAY_NODE_FN DumpNodeFn ) /*++ Purpose: Perform an in-order iteration across a splay tree, calling a user supplied function with a pointer to each RTL_SPLAY_LINKS structure encountered in the tree, and the level in the tree at which it was encountered (zero based). Arguments: pSplayLinks - pointer to root of a splay tree DumpNodeFn - user supplied dumping function Returns: Count of nodes encountered in the tree. Notes: Errors reading memory do not terminate the iteration if more work is possible. Consumes the Control-C flag to terminate possible loops in corrupt structures. --*/ { ULONG Level = 0; ULONG NodeCount = 0; if (pSplayLinks) { ULONG64 LeftChild, RightChild, Parent, Current; // // Retrieve the root links, find the leftmost node in the tree // if (GetFieldValue(Current = pSplayLinks, "RTL_SPLAY_LINKS", "LeftChild", LeftChild)) { return NodeCount; } while (LeftChild != 0) { if ( CheckControlC() ) { return NodeCount; } if (GetFieldValue(Current = LeftChild, "RTL_SPLAY_LINKS", "LeftChild", LeftChild)) { // // We can try to continue from this // break; } Level++; } while (TRUE) { if ( CheckControlC() ) { return NodeCount; } NodeCount++; pSplayLinks = Current; (*DumpNodeFn)(pSplayLinks, Level); /* first check to see if there is a right subtree to the input link if there is then the real successor is the left most node in the right subtree. That is find and return P in the following diagram Links \ . . . / P \ */ GetFieldValue(Current, "RTL_SPLAY_LINKS", "RightChild", RightChild); if (RightChild != 0) { if (GetFieldValue(Current = RightChild, "RTL_SPLAY_LINKS", "RightChild", RightChild)) { // // We've failed to step through to a successor, so // there is no more to do // return NodeCount; } Level++; GetFieldValue(Current,"RTL_SPLAY_LINKS","LeftChild",LeftChild); while (LeftChild != 0) { if ( CheckControlC() ) { return NodeCount; } if (GetFieldValue(Current = LeftChild, "RTL_SPLAY_LINKS", "LeftChild", LeftChild)) { // // We can continue from this // break; } Level++; } } else { /* we do not have a right child so check to see if have a parent and if so find the first ancestor that we are a left decendent of. That is find and return P in the following diagram P / . . . Links */ // // If the IsLeft or IsRight functions fail to read through a parent // pointer, then we will quickly exit through the break below // GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent); while (DbgRtlIsRightChild(Current, Parent)) { if ( CheckControlC() ) { return NodeCount; } Level--; pSplayLinks = (Current = Parent); } GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent); if (!DbgRtlIsLeftChild(Current, Parent)) { // // we do not have a real successor so we break out // break; } else { Level--; pSplayLinks = (Current = Parent); } } } } return NodeCount; } VOID DumpUnicode64( UNICODE_STRING64 u ) { UNICODE_STRING v; DWORD BytesRead; // dprintf("L %x, M %x, B %p ", u.Length, u.MaximumLength, u.Buffer); if ((u.Length <= u.MaximumLength) && (u.Buffer) && (u.Length > 0)) { v.Buffer = LocalAlloc(LPTR, u.MaximumLength+2); if (v.Buffer != NULL) { v.MaximumLength = u.MaximumLength; v.Length = u.Length; if (ReadMemory(u.Buffer, v.Buffer, u.Length, (PULONG) &u.Buffer) && (v.Buffer[0] != 0)) { v.Buffer[v.Length/sizeof(WCHAR)] = 0; dprintf("%ws", v.Buffer); } else { dprintf("< Name not readable >"); } LocalFree(v.Buffer); return; } } dprintf("< Name not readable >"); } BOOLEAN IsHexNumber( const char *szExpression ) { if (!szExpression[0]) { return FALSE ; } for(;*szExpression; szExpression++) { if ((*szExpression)< '0') { return FALSE ; } else if ((*szExpression)> 'f') { return FALSE ; } else if ((*szExpression)>='a') { continue ; } else if ((*szExpression)> 'F') { return FALSE ; } else if ((*szExpression)<='9') { continue ; } else if ((*szExpression)>='A') { continue ; } else { return FALSE ; } } return TRUE ; } BOOLEAN IsDecNumber( const char *szExpression ) { if (!szExpression[0]) { return FALSE ; } while(*szExpression) { if ((*szExpression)<'0') { return FALSE ; } else if ((*szExpression)>'9') { return FALSE ; } szExpression ++ ; } return TRUE ; }