/*++ Copyright (c) 1992 Microsoft Corporation Module Name: afds.c Abstract: Implements afds command Author: Vadim Eydelman, March 2000 Environment: User Mode. Revision History: --*/ #include "afdkdp.h" #pragma hdrstop #define AFDKD_TOKEN "@$." #define AFDKD_TOKSZ (sizeof (AFDKD_TOKEN)-1) ULONG ListCallback ( PFIELD_INFO pField, PVOID UserContext ); // // Public functions. // ULONG LinkOffset; DECLARE_API( afds ) /*++ Routine Description: Dumps afd endpoints Arguments: None. Return Value: None. --*/ { ULONG64 address; CHAR expr[MAX_ADDRESS_EXPRESSION]; PCHAR argp; INT i; ULONG result; gClient = pClient; argp = ProcessOptions ((PCHAR)args); if (argp==NULL) return E_INVALIDARG; if ((Options & (AFDKD_LINK_FIELD|AFDKD_LIST_TYPE)) != (AFDKD_LINK_FIELD|AFDKD_LIST_TYPE)) { dprintf ("\nafds: Missing link or list type specification"); dprintf ("\nUsage:\nafds -l link -t type [options] address\n"); return E_INVALIDARG; } if (sscanf( argp, "%s%n", expr, &i )!=1) { dprintf ("\nafds: Missing address specification"); dprintf ("\nUsage:\nafds -l link -t type [options] address\n"); return E_INVALIDARG; } argp += i; address = GetExpression (expr); if (Options & AFDKD_LINK_SELF) { result = GetFieldOffset (ListedType, LinkField, &LinkOffset); if (result!=0) { dprintf ("\nafds: Cannot get offset of %s in %s, err: %ld\n", LinkField, ListedType, result); return E_INVALIDARG; } } ListType ( (Options & AFDKD_LINK_SELF) ? "LIST_ENTRY" : ListedType, // Type address, // Address (Options & AFDKD_LINK_AOF) ? 1 : 0, // ListByFieldAddress (Options & AFDKD_LINK_SELF) ? "Flink" : LinkField, // NextPointer ListedType, // Context ListCallback); dprintf ("\n"); return S_OK; } ULONG ListCallback ( PFIELD_INFO pField, PVOID UserContext ) { ULONG64 address; address = pField->address; if (Options & AFDKD_LINK_SELF) { address -= LinkOffset; } if (!(Options & AFDKD_CONDITIONAL) || CheckConditional (address, UserContext)) { dprintf ("\n%s @ %p", UserContext, address); ProcessFieldOutput (address, UserContext); } else { dprintf ("."); } return 0; } /* { ULONG64 GetExpressionFromType ( ULONG64 Address, PCHAR Type, PCHAR Expression ) CHAR expr[MAX_CONDITIONAL_EXPRESSION]; PCHAR argp = Expression, pe = expr, pestop=pe+sizeof(expr)-1; ULONG result; ULONG64 value; PCHAR type = Type; ULONG64 address = Address; while (*argp) { if (*argp=='@' && strncmp (argp, AFDKD_TOKEN, AFDKD_TOKSZ)==0) { PCHAR end = pe; argp+= AFDKD_TOKSZ; while (isalnum (*argp) || *argp=='[' || *argp==']' || *argp=='_' || *argp=='.' || *argp=='-') { if (*argp=='-') { if (*(argp+1)=='>') { if (*(argp+2)=='(') { *end = 0; result = GetFieldValue (address, type, pe, value); if (result!=0) { dprintf ("\nCheckConditional: Can't get %s.%s at %p (err:%d)\n", type, pe, address, result); return FALSE; } if (value==0) return FALSE; argp += 3; type = argp; while (*argp && *argp!=')') { argp += 1; } *argp++ = 0; address = value; end = pe; continue; } if (end>=pestop) break; *end++ = *argp++; } else break; } if (end>=pestop) break; *end++ = *argp++; } *end = 0; result = GetFieldValue (address, type, pe, value); if (result!=0) { dprintf ("\nCheckConditional: Can't get %s.%s at %p (err:%d)\n", type, pe, address, result); return FALSE; } pe += _snprintf (pe, pestop-pe, "0x%I64X", value); address = Address; type = Type; } else { if (pe>=pestop) break; *pe++ = *argp++; } } *pe = 0; return GetExpression (expr); } */ BOOLEAN CheckConditional ( ULONG64 Address, PCHAR Type ) { DEBUG_VALUE val; if (GetExpressionFromType (Address, Type, Conditional, DEBUG_VALUE_INT64, &val)==S_OK) return val.I64!=0; else return FALSE; } VOID ProcessFieldOutput ( ULONG64 Address, PCHAR Type ) { ULONG result; FldParam.addr = Address; FldParam.sName = Type; if (Options & AFDKD_NO_DISPLAY) { FldParam.Options |= DBG_DUMP_COMPACT_OUT; } dprintf ("\n"); if (FldParam.nFields>0 || (FldParam.nFields==0 && CppFieldEnd==0)) { result = Ioctl (IG_DUMP_SYMBOL_INFO, &FldParam, FldParam.size ); if (result!=0) { dprintf ("\nProcessFieldOutput: IG_DUMP_SYMBOL_INFO failed, err: %ld\n", result); } } if (CppFieldEnd>FldParam.nFields) { ULONG i; for (i=FldParam.nFields; i("))!=NULL) { *p = 0; result = Ioctl (IG_DUMP_SYMBOL_INFO, &fldParam, fldParam.size ); if (result!=0) { dprintf ("\nProcessFieldOutput: GetFieldValue (%p,%s,%s) failed, err: %ld\n", fldParam.addr, fldParam.sName, field.fName, result); goto DoneField; } fldParam.addr = value; p += sizeof ("->(")-1; fldParam.sName = p; p = strchr (p, ')'); if (p==NULL) { dprintf ("\nProcessFieldOutput: missing ')' in %s\n", fldParam.sName); goto DoneField; } *p++ = 0; skip += 3; dprintf ("%*.80s%s : %I64x->(%s)\n", skip, " ", field.fName, DISP_PTR(value), fldParam.sName); field.fName = p; if (value==0) { goto DoneField; } } //fldParam.Options &= (~DBG_DUMP_NO_PRINT); field.fOptions &= ~(DBG_DUMP_FIELD_COPY_FIELD_DATA); field.fieldCallBack = NULL; result = Ioctl (IG_DUMP_SYMBOL_INFO, &fldParam, fldParam.size ); if (result!=0) { dprintf ("\nProcessFieldOutput: IG_DUMP_SYMBOL_INFO %p %s %s failed, err: %ld\n", fldParam.addr, fldParam.sName, field.fName, result); break; } DoneField: ; */ } } } DECLARE_API( filefind ) /*++ Routine Description: Searches non-paged pool for FILE_OBJECT given its FsContext field. Arguments: None. Return Value: None. --*/ { ULONG64 FsContext; ULONG64 PoolStart, PoolEnd, PoolPage; ULONG64 PoolExpansionStart, PoolExpansionEnd; ULONG result; ULONG64 val; BOOLEAN twoPools; gClient = pClient; if (!CheckKmGlobals ()) { return E_INVALIDARG; } FsContext = GetExpression (args); if (FsContext==0 || FsContext