359 lines
9.2 KiB
C
359 lines
9.2 KiB
C
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corp., 1991 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
user.c
|
|
This module implements the "user" command of the W3 Server
|
|
debugger extension DLL.
|
|
|
|
The "user" command dumps the info pertaining to a specific user.
|
|
There is one parameter to this command. If this parameter is
|
|
positive, it is assumed to be the address of a USER_DATA structure
|
|
for a specific user. If the parameter is negative, its absolute
|
|
value is assumed to be a user ID. If no parameter is given, info
|
|
for all connected users is dumped.
|
|
|
|
|
|
FILE HISTORY:
|
|
KeithMo 13-Aug-1992 Created.
|
|
|
|
*/
|
|
|
|
|
|
#include "w3dbg.h"
|
|
|
|
|
|
//
|
|
// Private prototypes.
|
|
//
|
|
|
|
VOID DumpUserInfo( HANDLE hCurrentProcess,
|
|
USER_DATA * puser );
|
|
|
|
CHAR * InterpretState( USER_STATE state );
|
|
|
|
CHAR * InterpretXferType( XFER_TYPE xferType );
|
|
|
|
CHAR * InterpretXferMode( XFER_MODE xferMode );
|
|
|
|
VOID InterpretFlags( DWORD dwFlags );
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: user
|
|
|
|
SYNOPSIS: Displays the info for a specific user.
|
|
|
|
ENTRY: hCurrentProcess - Handle to the current process.
|
|
|
|
hCurrentThread - Handle to the current thread.
|
|
|
|
dwCurrentPc - The current program counter
|
|
(EIP for x86, FIR for MIPS).
|
|
|
|
lpExtensionApis - Points to a structure containing
|
|
pointers to the debugger functions
|
|
that the command may invoke.
|
|
|
|
lpArgumentString - Points to any arguments passed
|
|
to the command.
|
|
|
|
NOTES: The argument string must contain either the address of
|
|
a USER_DATA structure (if positive) or a user ID (if
|
|
negative).
|
|
|
|
HISTORY:
|
|
KeithMo 13-Aug-1992 Created.
|
|
|
|
********************************************************************/
|
|
VOID user( HANDLE hCurrentProcess,
|
|
HANDLE hCurrentThread,
|
|
DWORD dwCurrentPc,
|
|
LPVOID lpExtensionApis,
|
|
LPSTR lpArgumentString )
|
|
{
|
|
LONG lParam;
|
|
USER_DATA user;
|
|
|
|
//
|
|
// Grab the debugger entrypoints.
|
|
//
|
|
|
|
GrabDebugApis( lpExtensionApis );
|
|
|
|
//
|
|
// Evaluate the parameter (if present).
|
|
//
|
|
|
|
if( ( lpArgumentString == NULL ) || ( *lpArgumentString == '\0' ) )
|
|
{
|
|
lParam = 0;
|
|
}
|
|
else
|
|
{
|
|
lParam = (LONG)DebugEval( lpArgumentString );
|
|
}
|
|
|
|
//
|
|
// Interpret the parameter.
|
|
//
|
|
|
|
if( lParam > 0 )
|
|
{
|
|
//
|
|
// User specified an address. Dump the user info
|
|
// at that address.
|
|
//
|
|
|
|
ReadProcessMemory( hCurrentProcess,
|
|
(LPVOID)lParam,
|
|
(LPVOID)&user,
|
|
sizeof(user),
|
|
(LPDWORD)NULL );
|
|
|
|
DumpUserInfo( hCurrentProcess, &user );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// User specified either nothing (0) or a user ID (< 0).
|
|
//
|
|
|
|
LIST_ENTRY list;
|
|
LIST_ENTRY * plist;
|
|
LIST_ENTRY * plistHead;
|
|
|
|
lParam = -lParam;
|
|
|
|
plistHead = (LIST_ENTRY *)DebugEval( "listUserData" );
|
|
|
|
ReadProcessMemory( hCurrentProcess,
|
|
(LPVOID)plistHead,
|
|
(LPVOID)&list,
|
|
sizeof(list),
|
|
(LPDWORD)NULL );
|
|
|
|
plist = list.Flink;
|
|
|
|
while( plist != plistHead )
|
|
{
|
|
ReadProcessMemory( hCurrentProcess,
|
|
(LPVOID)CONTAINING_RECORD( plist,
|
|
USER_DATA,
|
|
link ),
|
|
(LPVOID)&user,
|
|
sizeof(user),
|
|
(LPDWORD)NULL );
|
|
|
|
if( ( lParam == 0 ) || ( user.idUser == (DWORD)lParam ) )
|
|
{
|
|
DumpUserInfo( hCurrentProcess, &user );
|
|
|
|
if( lParam != 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
plist = user.link.Flink;
|
|
|
|
//
|
|
// Check for CTRL-C, to let the user bag-out early.
|
|
//
|
|
|
|
if( DebugCheckCtrlC() )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( ( lParam != 0 ) && ( plist == plistHead ) )
|
|
{
|
|
DebugPrint( "user ID %ld not found\n", lParam );
|
|
}
|
|
}
|
|
|
|
} // user
|
|
|
|
|
|
VOID DumpUserInfo( HANDLE hCurrentProcess,
|
|
USER_DATA * puser )
|
|
{
|
|
char szDir[MAX_PATH];
|
|
int i;
|
|
|
|
DebugPrint( "user @ %08lX:\n", puser );
|
|
DebugPrint( " link.Flink = %08lX\n", puser->link.Flink );
|
|
DebugPrint( " link.Blink = %08lX\n", puser->link.Blink );
|
|
DebugPrint( " dwFlags = %08lX\n", puser->dwFlags );
|
|
InterpretFlags( puser->dwFlags );
|
|
DebugPrint( " sControl = %d\n", puser->sControl );
|
|
DebugPrint( " sData = %d\n", puser->sData );
|
|
DebugPrint( " hToken = %08lX\n", puser->hToken );
|
|
DebugPrint( " state = %s\n", InterpretState( puser->state ) );
|
|
DebugPrint( " idUser = %lu\n", puser->idUser );
|
|
DebugPrint( " tConnect = %08lX\n", puser->tConnect );
|
|
DebugPrint( " tAccess = %08lX\n", puser->tAccess );
|
|
DebugPrint( " xferType = %s\n", InterpretXferType( puser->xferType ) );
|
|
DebugPrint( " xferMode = %s\n", InterpretXferMode( puser->xferMode ) );
|
|
DebugPrint( " inetLocal = %s\n", inet_ntoa( puser->inetLocal ) );
|
|
DebugPrint( " inetHost = %s\n", inet_ntoa( puser->inetHost ) );
|
|
DebugPrint( " inetData = %s\n", inet_ntoa( puser->inetData ) );
|
|
DebugPrint( " portData = %u\n", puser->portData );
|
|
DebugPrint( " hDir = %08lX\n", puser->hDir );
|
|
DebugPrint( " pIoBuffer = %08lX\n", puser->pIoBuffer );
|
|
DebugPrint( " pszRename = %s\n", puser->pszRename );
|
|
for( i = 0 ; i < 26 ; i++ )
|
|
{
|
|
if( puser->apszDirs[i] != NULL )
|
|
{
|
|
ReadProcessMemory( hCurrentProcess,
|
|
puser->apszDirs[i],
|
|
szDir,
|
|
sizeof(szDir),
|
|
(LPDWORD)NULL );
|
|
|
|
DebugPrint( " dir %c: = %s\n", 'A'+i, szDir );
|
|
}
|
|
}
|
|
DebugPrint( " szDir = %s\n", puser->szDir );
|
|
DebugPrint( " szUser = %s\n", puser->szUser );
|
|
DebugPrint( " idThread = %lu\n", puser->idThread );
|
|
|
|
DebugPrint( "\n" );
|
|
|
|
} // DumpUserInfo
|
|
|
|
|
|
CHAR * InterpretState( USER_STATE state )
|
|
{
|
|
CHAR * pszResult = "unknown";
|
|
|
|
switch( state )
|
|
{
|
|
case Embryonic :
|
|
pszResult = "Embryonic";
|
|
break;
|
|
|
|
case WaitingForUser :
|
|
pszResult = "WaitingForUser";
|
|
break;
|
|
|
|
case WaitingForPass :
|
|
pszResult = "WaitingForPass";
|
|
break;
|
|
|
|
case LoggedOn :
|
|
pszResult = "LoggedOn";
|
|
break;
|
|
|
|
case Disconnected :
|
|
pszResult = "Disconnected";
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
|
|
return pszResult;
|
|
|
|
} // InterpretState
|
|
|
|
|
|
CHAR * InterpretXferType( XFER_TYPE xferType )
|
|
{
|
|
CHAR * pszResult = "unknown";
|
|
|
|
switch( xferType )
|
|
{
|
|
case AsciiType :
|
|
pszResult = "ASCII";
|
|
break;
|
|
|
|
case BinaryType :
|
|
pszResult = "BINARY";
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
|
|
return pszResult;
|
|
|
|
} // InterpretXferType
|
|
|
|
|
|
CHAR * InterpretXferMode( XFER_MODE xferMode )
|
|
{
|
|
CHAR * pszResult = "unknown";
|
|
|
|
switch( xferMode )
|
|
{
|
|
case StreamMode :
|
|
pszResult = "STREAM";
|
|
break;
|
|
|
|
case BlockMode :
|
|
pszResult = "BLOCK";
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
|
|
return pszResult;
|
|
|
|
} // InterpretXferMode
|
|
|
|
|
|
typedef struct FLAG_MAP
|
|
{
|
|
DWORD flag;
|
|
CHAR * pszName;
|
|
|
|
} FLAG_MAP;
|
|
|
|
FLAG_MAP flag_map[] =
|
|
{
|
|
{ UF_MSDOS_DIR_OUTPUT, "UF_MSDOS_DIR_OUTPUT" },
|
|
{ UF_ANNOTATE_DIRS, "UF_ANNOTATE_DIRS" },
|
|
{ UF_READ_ACCESS, "UF_READ_ACCESS" },
|
|
{ UF_WRITE_ACCESS, "UF_WRITE_ACCESS" },
|
|
{ UF_OOB_ABORT, "UF_OOB_ABORT" },
|
|
{ UF_RENAME, "UF_RENAME" },
|
|
{ UF_PASSIVE, "UF_PASSIVE" },
|
|
{ UF_ANONYMOUS, "UF_ANONYMOUS" },
|
|
{ UF_TRANSFER, "UF_TRANSFER" },
|
|
{ UF_OOB_DATA, "UF_OOB_DATA" }
|
|
};
|
|
#define NUM_FLAG_MAP (sizeof(flag_map) / sizeof(flag_map[0]))
|
|
|
|
|
|
VOID InterpretFlags( DWORD dwFlags )
|
|
{
|
|
INT i;
|
|
FLAG_MAP * pmap = flag_map;
|
|
|
|
for( i = 0 ; i < NUM_FLAG_MAP ; i++ )
|
|
{
|
|
if( dwFlags & pmap->flag )
|
|
{
|
|
DebugPrint( " %s\n", pmap->pszName );
|
|
dwFlags &= ~pmap->flag;
|
|
}
|
|
|
|
pmap++;
|
|
}
|
|
|
|
if( dwFlags != 0 )
|
|
{
|
|
DebugPrint( " Remaining flags = %08lX\n", dwFlags );
|
|
}
|
|
|
|
} // InterpretFlags
|
|
|