/*++ Copyright (c) 1990 Microsoft Corporation Module Name: Abstract: This function contains the default ntsd debugger extensions Author: Revision History: --*/ char * AccessMask[] = { "Delete", "ReadControl", "WriteDac", "WriteOwner", "Synch", "", "", "", "Sacl", "MaxAllowed", "", "", "GenericAll", "GenericExec", "GenericWrite", "GenericRead"}; char * TokenRights[] = {"AssignPrimary", "Duplicate", "Impersonate", "Query", "QuerySource", "AdjustPriv", "AdjustGroup", "AdjustDef"}; char * KeyRights[] = { "QueryValue", "SetValue", "CreateSubKey", "EnumSubKey", "Notify", "CreateLink", "", "" }; char * EventRights[] = {"QueryState", "ModifyState" }; char * MutantRights[]={ "QueryState" }; char * SemaphoreRights[] = { "QueryState", "ModifyState" }; char * TimerRights[] = {"QueryState", "ModifyState" }; char * ProfileRights[]={"Control"}; char * ProcessRights[]={"Terminate", "CreateThread", "", "VMOp", "VMRead", "VMWrite", "DupHandle", "CreateProcess", "SetQuota", "SetInfo", "QueryInfo", "SetPort" }; char * ThreadRights[] ={"Terminate", "Suspend", "Alert", "GetContext", "SetContext", "SetInfo", "QueryInfo", "SetToken", "Impersonate", "DirectImpersonate" }; char * SectionRights[]={"Query", "MapWrite", "MapRead", "MapExecute", "Extend"}; char * FileRights[] = { "Read/List", "Write/Add", "Append/SubDir/CreatePipe", "ReadEA", "WriteEA", "Execute/Traverse", "DelChild", "ReadAttr", "WriteAttr"}; char * PortRights[] = { "Connect" }; char * DirRights[] = { "Query", "Traverse", "Create", "CreateSubdir" }; char * SymLinkRights[]={"Query" }; char * WinstaRights[]={ "EnumDesktops", "ReadAttr", "Clipboard", "CreateDesktop", "WriteAttr", "GlobalAtom", "ExitWindows", "", "Enumerate", "ReadScreen" }; char * DesktopRights[]={"ReadObjects", "CreateWindow", "CreateMenu", "HookControl", "JournalRecord", "JournalPlayback", "Enumerate", "WriteObjects", "SwitchDesktop" }; char * CompletionRights[] = { "Query", "Modify" }; char * ChannelRights[] = { "ReadMessage", "WriteMessage", "Query", "SetInfo" }; char * JobRights[] = { "AssignProcess", "SetAttr", "Query", "Terminate", "SetSecAttr" }; TCHAR * PrivNames[] = { TEXT("Invalid"), TEXT("Invalid"), SE_CREATE_TOKEN_NAME, SE_ASSIGNPRIMARYTOKEN_NAME, SE_LOCK_MEMORY_NAME, SE_MACHINE_ACCOUNT_NAME, SE_TCB_NAME, SE_SECURITY_NAME, SE_TAKE_OWNERSHIP_NAME, SE_LOAD_DRIVER_NAME, SE_SYSTEM_PROFILE_NAME, SE_PROF_SINGLE_PROCESS_NAME, SE_INC_BASE_PRIORITY_NAME, SE_CREATE_PAGEFILE_NAME, SE_CREATE_PERMANENT_NAME, SE_BACKUP_NAME, SE_RESTORE_NAME, SE_SHUTDOWN_NAME, SE_DEBUG_NAME, SE_AUDIT_NAME, SE_SYSTEM_ENVIRONMENT_NAME, SE_CHANGE_NOTIFY_NAME, SE_REMOTE_SHUTDOWN_NAME, SE_UNDOCK_NAME, SE_SYNC_AGENT_NAME, SE_ENABLE_DELEGATION_NAME }; /////////////////////////////// char * TokenImpLevels[] = { "Anonymous", "Identification", "Impersonation", "Delegation" }; #define GetTokenImpersonationLevel( x ) \ ( x <= SecurityDelegation ? TokenImpLevels[ x ] : "Invalid" ) #define GHI_TYPE 0x00000001 #define GHI_BASIC 0x00000002 #define GHI_NAME 0x00000004 #define GHI_SPECIFIC 0x00000008 #define GHI_VERBOSE 0x00000010 #define GHI_NOLOOKUP 0x00000020 #define GHI_SILENT 0x00000100 #define TYPE_NONE 0 #define TYPE_EVENT 1 #define TYPE_SECTION 2 #define TYPE_FILE 3 #define TYPE_PORT 4 #define TYPE_DIRECTORY 5 #define TYPE_LINK 6 #define TYPE_MUTANT 7 #define TYPE_WINSTA 8 #define TYPE_SEM 9 #define TYPE_KEY 10 #define TYPE_TOKEN 11 #define TYPE_PROCESS 12 #define TYPE_THREAD 13 #define TYPE_DESKTOP 14 #define TYPE_COMPLETE 15 #define TYPE_CHANNEL 16 #define TYPE_TIMER 17 #define TYPE_JOB 18 #define TYPE_WPORT 19 #define TYPE_MAX 20 LPWSTR pszTypeNames[TYPE_MAX] = { L"None", L"Event", L"Section", L"File", L"Port", L"Directory", L"SymbolicLink", L"Mutant", L"WindowStation", L"Semaphore", L"Key", L"Token", L"Process", L"Thread", L"Desktop", L"IoCompletion", L"Channel", L"Timer", L"Job", L"WaitablePort" }; LPSTR pszTypeNamesA[TYPE_MAX] = { "None", "Event", "Section", "File", "Port", "Directory", "SymbolicLink", "Mutant", "WindowStation", "Semaphore", "Key", "Token", "Process", "Thread", "Desktop", "IoCompletion", "Channe", "Timer", "Job", "WaitablePort" }; typedef VOID ( * TYPEINFOFN)(HANDLE hObject, DWORD Flags); VOID EventInfo(HANDLE, ULONG); VOID MutantInfo(HANDLE, ULONG); VOID SemaphoreInfo(HANDLE, ULONG); VOID TimerInfo(HANDLE, ULONG); VOID SectionInfo(HANDLE, ULONG); VOID KeyInfo(HANDLE, ULONG); VOID ProcessInfo(HANDLE, ULONG); VOID ThreadInfo(HANDLE, ULONG); VOID TokenInfo(HANDLE, ULONG); VOID IoCompleteInfo(HANDLE, ULONG); VOID JobInfo( HANDLE, ULONG ); typedef struct _TYPEINFO { PWSTR pszName; char * * AccessRights; DWORD NumberRights; TYPEINFOFN Func; } TYPEINFO, * PTYPEINFO; TYPEINFO TypeNames[TYPE_MAX] = { { L"None", NULL, 0, 0 }, { L"Event", EventRights, 2, EventInfo }, { L"Section", SectionRights, 5, SectionInfo }, { L"File", FileRights, 9, 0 }, { L"Port", PortRights, 1, 0 }, { L"Directory", DirRights, 4, 0 }, { L"SymbolicLink", SymLinkRights, 1, 0 }, { L"Mutant", MutantRights, 2, MutantInfo }, { L"WindowStation", WinstaRights, 10, 0 }, { L"Semaphore", SemaphoreRights, 2, SemaphoreInfo }, { L"Key", KeyRights, 6, KeyInfo }, { L"Token", TokenRights, 8, TokenInfo }, { L"Process", ProcessRights, 12, ProcessInfo }, { L"Thread", ThreadRights, 10, ThreadInfo }, { L"Desktop", DesktopRights, 10, 0 }, { L"IoCompletion", CompletionRights, 2, IoCompleteInfo }, { L"Channel", ChannelRights, 4, 0}, { L"Timer", TimerRights, 2, TimerInfo }, { L"Job", JobRights, 5, JobInfo }, { L"WaitablePort", PortRights, 1, 0 } }; void DisplayFlags( DWORD Flags, DWORD FlagLimit, char *flagset[], UCHAR * buffer) { char * offset; DWORD mask, test, i; DWORD scratch; if (!Flags) { strcpy((CHAR *)buffer, "None"); return; } mask = 0; offset = (CHAR *) buffer; test = 1; for (i = 0 ; i < FlagLimit ; i++ ) { if (Flags & test) { scratch = sprintf(offset, "%s", flagset[i]); offset += scratch; mask |= test; if (Flags & (~mask)) { *offset++ = ','; } } test <<= 1; } } VOID EventInfo( HANDLE hEvent, DWORD Flags) { EVENT_BASIC_INFORMATION Info; NTSTATUS Status; Status = NtQueryEvent( hEvent, EventBasicInformation, &Info, sizeof( Info ), NULL ); if (NT_SUCCESS( Status ) ) { dprintf(" Event Type %s\n", Info.EventType == SynchronizationEvent ? "Auto Reset" : "Manual Reset" ); dprintf(" Event is %s\n", Info.EventState ? "Set" : "Waiting" ); } } VOID SemaphoreInfo( HANDLE hSem, DWORD Flags) { SEMAPHORE_BASIC_INFORMATION Info; NTSTATUS Status; Status = NtQuerySemaphore( hSem, SemaphoreBasicInformation, &Info, sizeof( Info ), NULL ); if (NT_SUCCESS( Status ) ) { dprintf(" Semaphore Count %d\n", Info.CurrentCount ); dprintf(" Semaphore Limit %d\n", Info.MaximumCount ); } } VOID MutantInfo( HANDLE hMutant, DWORD Flags) { MUTANT_BASIC_INFORMATION Info; NTSTATUS Status; Status = NtQueryMutant( hMutant, MutantBasicInformation, &Info, sizeof( Info ), NULL ); if (NT_SUCCESS( Status ) ) { dprintf(" Mutex is %s\n", Info.CurrentCount ? "Free" : "Owned" ); if ( Info.AbandonedState ) { dprintf(" Mutex is abandoned\n"); } } } VOID TimerInfo( HANDLE hTimer, DWORD Flags) { TIMER_BASIC_INFORMATION Info; NTSTATUS Status; Status = NtQueryTimer( hTimer, TimerBasicInformation, &Info, sizeof( Info ), NULL ); if (NT_SUCCESS( Status ) ) { dprintf(" Timer is %s\n", Info.TimerState ? "signalled" : "waiting" ); dprintf(" Remaining time %d\n", (DWORD) Info.RemainingTime.QuadPart ); } } VOID SectionInfo( HANDLE hSection, DWORD Flags) { SECTION_BASIC_INFORMATION Info; NTSTATUS Status; Status = NtQuerySection( hSection, SectionBasicInformation, &Info, sizeof( Info ), NULL ); if ( NT_SUCCESS( Status ) ) { dprintf(" Section base address %#x\n", Info.BaseAddress ); dprintf(" Section attributes %#x\n", Info.AllocationAttributes ); dprintf(" Section max size %#x\n", (DWORD) Info.MaximumSize.QuadPart ); } } VOID KeyInfo( HANDLE hKey, DWORD Flags) { PKEY_BASIC_INFORMATION pInfo; NTSTATUS Status; SYSTEMTIME st; FILETIME lft; ULONG Length; pInfo = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, 1024); if ( pInfo ) { Status = NtQueryKey( hKey, KeyBasicInformation, pInfo, 1024, &Length ); if ( NT_SUCCESS( Status ) ) { FileTimeToLocalFileTime( (FILETIME *) &pInfo->LastWriteTime, & lft ); FileTimeToSystemTime( &lft, &st ); dprintf(" Key last write time: %02d:%02d:%02d. %d/%d/%d\n", st.wHour, st.wMinute, st.wSecond, st.wMonth, st.wDay, st.wYear ); dprintf(" Key name %ws\n", pInfo->Name ); } LocalFree( pInfo ); } } VOID ProcessInfo( HANDLE hProcess, DWORD Flags) { PROCESS_BASIC_INFORMATION Info; NTSTATUS Status; Status = NtQueryInformationProcess( hProcess, ProcessBasicInformation, &Info, sizeof( Info ), NULL ); if ( NT_SUCCESS( Status ) ) { dprintf(" Process Id %d\n", Info.UniqueProcessId ); dprintf(" Parent Process %d\n", Info.InheritedFromUniqueProcessId ); dprintf(" Base Priority %d\n", Info.BasePriority ); } } VOID ThreadInfo( HANDLE hThread, DWORD Flags) { THREAD_BASIC_INFORMATION Info; NTSTATUS Status; PVOID StartAddr ; CHAR Buffer[ 128 ]; DWORD_PTR Offset ; Status = NtQueryInformationThread( hThread, ThreadBasicInformation, &Info, sizeof( Info ), NULL ); if ( NT_SUCCESS( Status ) ) { dprintf(" Thread Id %d.%d\n", Info.ClientId.UniqueProcess, Info.ClientId.UniqueThread ); dprintf(" Priority %d\n", Info.Priority ); dprintf(" Base Priority %d\n", Info.BasePriority ); } Status = NtQueryInformationThread( hThread, ThreadQuerySetWin32StartAddress, &StartAddr, sizeof( PVOID ), NULL ); if ( NT_SUCCESS( Status ) ) { Buffer[0] = '\0'; GetSymbol( StartAddr, Buffer, &Offset ); dprintf(" Start Address %x %s\n", StartAddr, Buffer[0] ? Buffer : "" ); } } VOID IoCompleteInfo( HANDLE hIoCompletionPort, DWORD Flags) { IO_COMPLETION_BASIC_INFORMATION Info; NTSTATUS Status; Status = NtQueryIoCompletion( hIoCompletionPort, IoCompletionBasicInformation, &Info, sizeof( Info ), NULL ); if ( NT_SUCCESS( Status ) ) { dprintf(" Depth %d\n", Info.Depth ); } } VOID TokenInfo( HANDLE hToken, DWORD Flags) { TOKEN_STATISTICS Stats; UCHAR Buffer[ 1024 ]; PTOKEN_USER pUser; PTOKEN_GROUPS pGroups; PTOKEN_PRIVILEGES pPrivs ; ULONG Size; NTSTATUS Status; UNICODE_STRING s; WCHAR Name[ 64 ]; WCHAR Domain[ 64 ]; DWORD NameSize; DWORD DomainSize; SID_NAME_USE Use; BOOL FoundName; ULONG Index; Status = NtQueryInformationToken( hToken, TokenStatistics, &Stats, sizeof(Stats), &Size ); if ( NT_SUCCESS( Status ) ) { dprintf(" Auth Id %#x : %#x\n", Stats.AuthenticationId.HighPart, Stats.AuthenticationId.LowPart ); dprintf(" Type %s\n", Stats.TokenType == TokenPrimary ? "Primary" : "Impersonation" ); dprintf(" Imp Level %s\n", GetTokenImpersonationLevel( Stats.ImpersonationLevel ) ); if ( Flags & GHI_VERBOSE ) { dprintf(" Token Id %#x : %#x \n", Stats.TokenId.HighPart, Stats.TokenId.LowPart ); dprintf(" Mod Id %#x : %#x \n", Stats.ModifiedId.HighPart, Stats.ModifiedId.LowPart ); dprintf(" Dyn Chg %#x\n", Stats.DynamicCharged ); dprintf(" Dyn Avail %#x\n", Stats.DynamicAvailable ); dprintf(" Groups %d\n", Stats.GroupCount ); dprintf(" Privs %d\n", Stats.PrivilegeCount ); pUser = (PTOKEN_USER) Buffer; Status = NtQueryInformationToken( hToken, TokenUser, Buffer, sizeof(Buffer), &Size ); if (NT_SUCCESS( Status ) ) { FoundName = FALSE ; if ( !(Flags & GHI_NOLOOKUP) ) { NameSize = 64 ; DomainSize = 64 ; if ( LookupAccountSidW( NULL, pUser->User.Sid, Name, &NameSize, Domain, &DomainSize, &Use ) ) { dprintf(" User %ws\\%ws\n", Domain, Name ); FoundName = TRUE; } } if ( (Flags & GHI_NOLOOKUP) || (!FoundName) ) { RtlConvertSidToUnicodeString( &s, pUser->User.Sid, TRUE ); dprintf(" User %ws\n", s.Buffer ); RtlFreeUnicodeString( &s ); } } pGroups = (PTOKEN_GROUPS) Buffer; Status = NtQueryInformationToken( hToken, TokenGroups, Buffer, sizeof(Buffer), &Size ); if ( NT_SUCCESS( Status ) ) { dprintf(" Groups %d\n", pGroups->GroupCount ); for ( Index = 0 ; Index < pGroups->GroupCount ; Index++ ) { FoundName = FALSE ; if ( !(Flags & GHI_NOLOOKUP) ) { NameSize = 64 ; DomainSize = 64 ; if ( LookupAccountSidW( NULL, pGroups->Groups[Index].Sid, Name, &NameSize, Domain, &DomainSize, &Use ) ) { dprintf(" %ws\\%ws\n", Domain, Name ); FoundName = TRUE; } } if ( ( Flags & GHI_NOLOOKUP ) || ( !FoundName ) ) { RtlConvertSidToUnicodeString( &s, pGroups->Groups[Index].Sid, TRUE ); dprintf(" %ws\n", s.Buffer ); RtlFreeUnicodeString( &s ); } } } pPrivs = (PTOKEN_PRIVILEGES) Buffer ; Status = NtQueryInformationToken( hToken, TokenPrivileges, Buffer, sizeof(Buffer), &Size ); if ( NT_SUCCESS( Status ) ) { dprintf(" Privileges %d\n", pPrivs->PrivilegeCount ); for ( Index = 0 ; Index < pPrivs->PrivilegeCount ; Index++ ) { dprintf(" %s (%s%s)\n", PrivNames[ pPrivs->Privileges[ Index ].Luid.LowPart ], pPrivs->Privileges[ Index ].Attributes & SE_PRIVILEGE_ENABLED ? " Enabled " : " ", pPrivs->Privileges[ Index ].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT ? "Default " : "" ); } } } } } VOID JobInfo( HANDLE Job, ULONG Flags ) { JOBOBJECT_BASIC_ACCOUNTING_INFORMATION BasicInfo ; UCHAR Buffer[ 128 * sizeof( ULONG_PTR ) ]; PJOBOBJECT_BASIC_PROCESS_ID_LIST ProcList ; NTSTATUS Status ; ULONG Size ; TIME_FIELDS Time ; // // Delay load this API since it does not exist on NT 4 // typedef NTSTATUS (NTAPI* PNTQUERYJOB)(HANDLE, JOBOBJECTINFOCLASS, PVOID, LONG, PULONG); HMODULE hNtdll; PNTQUERYJOB pNtQueryJob; hNtdll = GetModuleHandle( "ntdll.dll" ); if (!hNtdll) { dprintf("Unable to get module handle for ntdll.dll\n"); return; } pNtQueryJob = (PNTQUERYJOB)GetProcAddress( hNtdll, "NtQueryInformationJobObject" ); if (pNtQueryJob == NULL) { dprintf("Unable to get address of NtQueryInformationJobObject\n"); return; } Status = pNtQueryJob( Job, JobObjectBasicAccountingInformation, &BasicInfo, sizeof( BasicInfo ), &Size ); if ( NT_SUCCESS( Status ) ) { RtlTimeToElapsedTimeFields( &BasicInfo.TotalUserTime, &Time ); dprintf( " TotalUserTime \t%3ld:%02ld:%02ld.%04ld\n", Time.Hour, Time.Minute, Time.Second, Time.Milliseconds ); RtlTimeToElapsedTimeFields( &BasicInfo.TotalKernelTime, &Time ); dprintf( " TotalKernelTime \t%3ld:%02ld:%02ld.%04ld\n", Time.Hour, Time.Minute, Time.Second, Time.Milliseconds ); dprintf( " TotalProcesses \t%x\n", BasicInfo.TotalProcesses ); dprintf( " ActiveProcesses \t%x\n", BasicInfo.ActiveProcesses ); dprintf( " TotalPageFaultCount\t%x\n", BasicInfo.TotalPageFaultCount ); if ( BasicInfo.ActiveProcesses ) { ProcList = (PJOBOBJECT_BASIC_PROCESS_ID_LIST) Buffer ; Status = pNtQueryJob( Job, JobObjectBasicProcessIdList, ProcList, sizeof( Buffer ), &Size ); if ( NT_SUCCESS( Status ) ) { ULONG i ; dprintf( " Processes:\n" ); for (i = 0 ; i < ProcList->NumberOfProcessIdsInList ; i++ ) { dprintf( " %x\n", ProcList->ProcessIdList[ i ] ); } } } } } DWORD GetObjectTypeIndex( LPCSTR pszTypeName ) { WCHAR TypeName[ MAX_PATH ]; DWORD i; mbstowcs( TypeName, pszTypeName, strlen( pszTypeName ) + 1 ); for ( i = 1 ; i < TYPE_MAX ; i++ ) { if (_wcsicmp( TypeNames[i].pszName, TypeName ) == 0 ) { return( i ); } } return( (DWORD) -1 ); } DWORD GetHandleInfoDirect( HANDLE hProcess, HANDLE hThere, DWORD Flags, DWORD * Type) { HANDLE hHere; NTSTATUS Status; POBJECT_TYPE_INFORMATION pTypeInfo; POBJECT_NAME_INFORMATION pNameInfo; POBJECT_BASIC_INFORMATION pBasicInfo; UCHAR Buffer[1024]; DWORD SuccessCount = 0; DWORD i; UCHAR szBuf[256]; if (!DuplicateHandle( hProcess, hThere, GetCurrentProcess(), &hHere, 0, FALSE, DUPLICATE_SAME_ACCESS) ) { if ( (Flags & GHI_SILENT) == 0) { dprintf("Could not duplicate handle %x, error %d\n", hThere, GetLastError() ); } return( 0 ); } pTypeInfo = (POBJECT_TYPE_INFORMATION) Buffer; pNameInfo = (POBJECT_NAME_INFORMATION) Buffer; pBasicInfo = (POBJECT_BASIC_INFORMATION) Buffer; if ( (Flags & GHI_SILENT) == 0) { dprintf("Handle %x\n", hThere ); } if (Flags & GHI_TYPE) { ZeroMemory( Buffer, 1024 ); Status = NtQueryObject( hHere, ObjectTypeInformation, pTypeInfo, 1024, NULL ); if (NT_SUCCESS(Status)) { if ((Flags & GHI_SILENT) == 0) { dprintf(" Type \t%ws\n", pTypeInfo->TypeName.Buffer ); } for (i = 1; i < TYPE_MAX ; i++ ) { if (wcscmp(pTypeInfo->TypeName.Buffer, TypeNames[i].pszName) == 0) { *Type = i; break; } } if (i == TYPE_MAX) { *Type = 0; } SuccessCount++; } } if (Flags & GHI_BASIC) { ZeroMemory( Buffer, 1024 ); Status = NtQueryObject(hHere, ObjectBasicInformation, pBasicInfo, sizeof( OBJECT_BASIC_INFORMATION), NULL); if (NT_SUCCESS(Status)) { dprintf(" Attributes \t%#x\n", pBasicInfo->Attributes ); dprintf(" GrantedAccess\t%#x:\n", pBasicInfo->GrantedAccess ); DisplayFlags( pBasicInfo->GrantedAccess >> 16, 16, AccessMask, szBuf); dprintf(" %s\n", szBuf); DisplayFlags( pBasicInfo->GrantedAccess & 0xFFFF, TypeNames[ *Type ].NumberRights, TypeNames[ *Type ].AccessRights, szBuf); dprintf(" %s\n", szBuf); dprintf(" HandleCount \t%d\n", pBasicInfo->HandleCount ); dprintf(" PointerCount \t%d\n", pBasicInfo->PointerCount ); SuccessCount++; } else { if ( Status != STATUS_INVALID_HANDLE ) { dprintf("unable to query object information\n"); } } } if ( (Flags & GHI_NAME) && (*Type != TYPE_FILE ) ) { ZeroMemory( Buffer, 1024 ); Status = NtQueryObject( hHere, ObjectNameInformation, pNameInfo, 1024, NULL ); if (NT_SUCCESS(Status)) { dprintf(" Name \t%ws\n", pNameInfo->Name.Buffer ? pNameInfo->Name.Buffer : L"" ); SuccessCount++; } else { if ( Status != STATUS_INVALID_HANDLE ) { dprintf("unable to query object information\n"); } } } if ( Flags & GHI_SPECIFIC ) { if ( TypeNames[ *Type ].Func ) { dprintf(" Object Specific Information\n"); TypeNames[ *Type ].Func( hHere, Flags ); } } NtClose( hHere ); return( SuccessCount ); } DWORD GetHandleInfoInterface( HANDLE hThere, DWORD Flags, DWORD * Type) { ULONG64 IfHandle = (ULONG_PTR)hThere; HRESULT Status; DWORD SuccessCount = 0; DWORD i; UCHAR Buffer[1024]; UCHAR szBuf[256]; if ( (Flags & GHI_SILENT) == 0) { dprintf("Handle %I64x\n", IfHandle ); } if (Flags & GHI_TYPE) { if (g_ExtData2->lpVtbl-> ReadHandleData(g_ExtData2, IfHandle, DEBUG_HANDLE_DATA_TYPE_TYPE_NAME, Buffer, sizeof(Buffer), NULL) == S_OK) { if ((Flags & GHI_SILENT) == 0) { dprintf(" Type \t%s\n", Buffer); } for (i = 1; i < TYPE_MAX ; i++ ) { if (strcmp((LPSTR)Buffer, pszTypeNamesA[i]) == 0) { *Type = i; break; } } if (i == TYPE_MAX) { *Type = 0; } SuccessCount++; } } if (Flags & GHI_BASIC) { DEBUG_HANDLE_DATA_BASIC Basic; if (g_ExtData2->lpVtbl-> ReadHandleData(g_ExtData2, IfHandle, DEBUG_HANDLE_DATA_TYPE_BASIC, &Basic, sizeof(Basic), NULL) == S_OK) { dprintf(" Attributes \t%#x\n", Basic.Attributes ); dprintf(" GrantedAccess\t%#x:\n", Basic.GrantedAccess ); DisplayFlags( Basic.GrantedAccess >> 16, 16, AccessMask, szBuf); dprintf(" %s\n", szBuf); DisplayFlags( Basic.GrantedAccess & 0xFFFF, TypeNames[ *Type ].NumberRights, TypeNames[ *Type ].AccessRights, szBuf); dprintf(" %s\n", szBuf); dprintf(" HandleCount \t%d\n", Basic.HandleCount ); dprintf(" PointerCount \t%d\n", Basic.PointerCount ); SuccessCount++; } else { dprintf("unable to query object information\n"); } } if ( (Flags & GHI_NAME) && (*Type != TYPE_FILE ) ) { if (g_ExtData2->lpVtbl-> ReadHandleData(g_ExtData2, IfHandle, DEBUG_HANDLE_DATA_TYPE_OBJECT_NAME, Buffer, sizeof(Buffer), NULL) == S_OK) { dprintf(" Name \t%s\n", Buffer[0] ? Buffer : "" ); SuccessCount++; } else { dprintf("unable to query object information\n"); } } if ( Flags & GHI_SPECIFIC ) { dprintf(" No object specific information available\n"); } return( SuccessCount ); } DWORD GetHandleInfo( BOOL Direct, HANDLE hProcess, HANDLE hThere, DWORD Flags, DWORD * Type) { if (Direct) { return GetHandleInfoDirect(hProcess, hThere, Flags, Type); } else { return GetHandleInfoInterface(hThere, Flags, Type); } }