Files
silverf0x-RpcView/RpcView/InterfacesWidget.cpp
T
Martin Rakhmanov eac145f455 Add runtime version 10.0.19041.630, got rid of Qt build warnings when
built against Qt 5.15.2 (deprecated APIs replaced with recommended
ones).
2021-03-06 12:19:25 +01:00

490 lines
17 KiB
C++

#include <conio.h>
#include "InterfacesWidget.h"
#include "..\RpcCommon\RpcCommon.h"
static const char WidgetName[] = "Interfaces";
//8a885d04-1ceb-11c9-9fe8-08002b104860 V2.0
RPC_SYNTAX_IDENTIFIER DceRpcSyntaxUuid =
{
{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},
{2,0}
};
//71710533-beba-4937-8319-b5dbef9ccc36 V1.0
RPC_SYNTAX_IDENTIFIER Ndr64SyntaxUuid =
{
{0x71710533,0xbeba,0x4937,{0x83,0x19,0xb5,0xdb,0xef,0x9c,0xcc,0x36}},
{1,0}
};
//------------------------------------------------------------------------------
QString InterfacesWidget_C::GetColumName(Column_T Column)
{
switch(Column)
{
case Column_Uuid : return (QString("Uuid"));
case Column_Pid : return (QString("Pid"));
case Column_Version : return (QString("Ver"));
case Column_Flags : return (QString("Flags"));
case Column_Name : return (QString("Name"));
case Column_Base : return (QString("Base"));
case Column_Location : return (QString("Location"));
case Column_Description : return (QString("Description"));
case Column_NumberOfProcedures : return (QString("Procs"));
case Column_IfType : return (QString("Type"));
case Column_IsRegistered : return (QString("EpMapper"));
case Column_Annotation : return (QString("Annotation"));
case Column_HasMarshallingInfo : return (QString("Stub"));
case Column_IfCallbackFn : return (QString("Callback"));
case Column_TransfertSyntax : return (QString("Syntax"));
default : return (QString("Unknown"));
}
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::InterfaceSelected(const QModelIndex& Index)
{
QStringList PidStringList;
QStringList VersionStringList;
QByteArray UuidStringARef;
RPC_IF_ID RpcIfId;
UCHAR* pUuidStringA;
QString PidString = pProxyModel->data( pProxyModel->index(Index.row(), Column_Pid) ).toString();
UuidStringARef = pProxyModel->data(pProxyModel->index(Index.row(), Column_Uuid)).toString().toLatin1();
pUuidStringA = (UCHAR*)UuidStringARef.data();
QString VersionString = pProxyModel->data( pProxyModel->index(Index.row(), Column_Version) ).toString();
VersionStringList = VersionString.split(".", Qt::SkipEmptyParts, Qt::CaseSensitive);
if (VersionStringList.isEmpty())
{
RpcIfId.VersMajor = 0;
RpcIfId.VersMinor = 0;
}
else
{
RpcIfId.VersMajor= VersionStringList.at(0).toUShort();
RpcIfId.VersMinor= VersionStringList.at(1).toUShort();
}
UuidFromStringA( pUuidStringA, &RpcIfId.Uuid);
if (QApplication::mouseButtons() & Qt::RightButton)
{
QMenu myMenu;
QAction* pActionDecompile = myMenu.addAction("Decompile");
QAction* selectedItem = myMenu.exec(QCursor::pos());
if (selectedItem == pActionDecompile)
{
emit SigDecompileInterface(PidString.toUInt(), &RpcIfId);
delete selectedItem;
}
else
{
delete selectedItem;
delete pActionDecompile;
}
}
else
{
//Select the interface
emit InterfaceSelected(PidString.toUInt(), &RpcIfId);
}
return;
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::ApplyProcessFilter(quint32 Pid)
{
pProxyModel->setFilterRegExp( QString("^%1$").arg(Pid) );
if (pProxyModel->rowCount() == 0) pProxyModel->setFilterRegExp( QRegExp(".*") );
pFilterWidget->Reset();
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::SnapInterfaces()
{
PrivateItemList = pModel->findItems(".*", Qt::MatchRegExp, Column_Uuid);
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::RemoveUnregisteredInterfaces()
{
for (auto Iter=PrivateItemList.begin();Iter!=PrivateItemList.end();Iter++)
{
if (*Iter!=NULL) pModel->removeRow( (*Iter)->row());
}
}
//------------------------------------------------------------------------------
bool InterfacesWidget_C::IsInterfacePresent(quint32 Pid, RPC_IF_ID* pIfId)
{
QList<QStandardItem*> ItemList;
UCHAR* pUuidString = NULL;
bool bResult = false;
if ( UuidToStringA(&pIfId->Uuid,&pUuidString)!=RPC_S_OK ) goto End;
ItemList = pModel->findItems(QString::fromLatin1((const char*)pUuidString), Qt::MatchFixedString, Column_Uuid);
if (ItemList.isEmpty()) goto End;
for (auto Iter=ItemList.begin();Iter!=ItemList.end();Iter++)
{
if (*Iter!=NULL)
{
if (pModel->data(pModel->index((*Iter)->row(), Column_Pid)).toUInt() == Pid)
{
PrivateItemList.removeOne(*Iter);
bResult = true;
goto End;
}
}
}
End:
RpcStringFreeA(&pUuidString);
return (bResult);
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::UpdateUserFilter()
{
if (pFilterWidget->GetText()!="") ApplyUserFilter( pFilterWidget->GetText() );
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::ApplyUserFilter(const QString & FilterText)
{
QRegExp FilterRegExp;
FilterRegExp.setPattern( FilterText );
FilterRegExp.setCaseSensitivity( Qt::CaseInsensitive );
pProxyModel->setFilterKeyColumn(-1);
pProxyModel->setFilterRegExp( FilterRegExp );
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::ShowUserFilter()
{
pFilterWidget->show();
pUserFilter->setFocus();
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::HideUserFilter()
{
pFilterWidget->hide();
}
//------------------------------------------------------------------------------
ULONG InterfacesWidget_C::GetInterfaces()
{
return (pProxyModel->rowCount());
}
//------------------------------------------------------------------------------
ULONG InterfacesWidget_C::GetTotalInterfaces()
{
return (pModel->rowCount());
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::resizeColumnsToContents()
{
int Index;
for( Index=0; Index < Column_Last; Index++)
{
pInterfaces->resizeColumnToContents(Index);
}
}
//------------------------------------------------------------------------------
QString GetInterfaceFlagsString(quint32 Flags)
{
QString FlagsString;
if (Flags & RPC_IF_AUTOLISTEN) FlagsString.append("RPC_IF_AUTOLISTEN\n");
if (Flags & RPC_IF_OLE) FlagsString.append("RPC_IF_OLE\n");
if (Flags & RPC_IF_ALLOW_UNKNOWN_AUTHORITY) FlagsString.append("RPC_IF_ALLOW_UNKNOWN_AUTHORITY\n");
if (Flags & RPC_IF_ALLOW_SECURE_ONLY) FlagsString.append("RPC_IF_ALLOW_SECURE_ONLY\n");
if (Flags & RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH) FlagsString.append("RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH\n");
if (Flags & RPC_IF_ALLOW_LOCAL_ONLY) FlagsString.append("RPC_IF_ALLOW_LOCAL_ONLY\n");
if (Flags & RPC_IF_SEC_NO_CACHE) FlagsString.append("RPC_IF_SEC_NO_CACHE\n");
if (Flags & RPC_IF_SEC_CACHE_PER_PROC) FlagsString.append("RPC_IF_SEC_CACHE_PER_PROC\n");
if (Flags & RPC_IF_ASYNC_CALLBACK) FlagsString.append("RPC_IF_ASYNC_CALLBACK\n");
return (FlagsString);
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::SetRowColor(int Index, const QColor& Color)
{
int i;
for (i=0;i<Column_Last;i++)
{
pModel->setData(pModel->index(Index,i), QBrush(Color), Qt::BackgroundRole);
}
}
//------------------------------------------------------------------------------
bool InterfacesWidget_C::AddInterfaces(RpcInterfaceInfo_T* pRpcInterfaceInfo)
{
int Index;
QString PidString;
WCHAR* pUuidString = NULL;
WCHAR* pTypeW = NULL;
WCHAR* pStubW = NULL;
if (pRpcInterfaceInfo==NULL) goto End;
//=====
if (pRpcInterfaceInfo->IfType!=IfType_RPC) goto End; //NO DCOM!!!!
//====
if ( UuidToStringW(&pRpcInterfaceInfo->If.Uuid,(RPC_WSTR*)&pUuidString)!=RPC_S_OK ) goto End;
Index = pModel->rowCount();
pModel->setRowCount(Index+1);
pModel->setData(pModel->index(Index, Column_Pid), QString("%1").arg(pRpcInterfaceInfo->Pid) );
pModel->setData(pModel->index(Index, Column_Uuid), QString::fromUtf16((const ushort*)pUuidString));
pModel->setData(pModel->index(Index, Column_Flags), QString("0x%1").arg(pRpcInterfaceInfo->Flags,0,16));
pModel->setData(pModel->index(Index, Column_Flags), GetInterfaceFlagsString(pRpcInterfaceInfo->Flags), Qt::ToolTipRole );
pModel->setData(pModel->index(Index, Column_Name), QString::fromUtf16((const ushort*)pRpcInterfaceInfo->Name));
pModel->setData(pModel->index(Index, Column_Base), QString("0x%1").arg((quintptr)pRpcInterfaceInfo->pLocationBase, 16, 16, QLatin1Char('0')));
pModel->setData(pModel->index(Index, Column_Base), (quintptr)pRpcInterfaceInfo->pLocationBase, Qt::UserRole);
pModel->setData(pModel->index(Index, Column_Location), QString::fromUtf16((const ushort*)pRpcInterfaceInfo->Location));
pModel->setData(pModel->index(Index, Column_Description), QString::fromUtf16((const ushort*)pRpcInterfaceInfo->Description));
if (pRpcInterfaceInfo->NumberOfProcedures==INVALID_PROC_COUNT) pModel->setData(pModel->index(Index, Column_NumberOfProcedures), 0);
else pModel->setData(pModel->index(Index, Column_NumberOfProcedures), pRpcInterfaceInfo->NumberOfProcedures);
switch(pRpcInterfaceInfo->IfType)
{
case IfType_RPC:
//Only RPC interfaces have versions
pTypeW = L"RPC";
pModel->setData(pModel->index(Index, Column_Version), QString("%1.%2").arg(pRpcInterfaceInfo->If.VersMajor).arg(pRpcInterfaceInfo->If.VersMinor));
break;
case IfType_OLE:
pTypeW = L"OLE";
if (pRpcInterfaceInfo->TypeOfStub==TypeOfStub_TypeLib) SetRowColor(Index,QColor(255, 200, 255, 180));
else SetRowColor(Index,QColor(255, 255, 200, 180));
break;
case IfType_DCOM:
pTypeW = L"DCOM";
SetRowColor(Index,QColor(200, 200, 255, 180));
break;
}
pModel->setData(pModel->index(Index, Column_IfType), QString::fromUtf16((const ushort*)pTypeW));
if (!pRpcInterfaceInfo->bIsRegistered)
{
pModel->setData(pModel->index(Index, Column_IsRegistered), "");
}
else
{
pModel->setData(pModel->index(Index, Column_IsRegistered), QString("Registered"));
}
pModel->setData(pModel->index(Index, Column_Annotation), QString::fromLatin1((const char*)pRpcInterfaceInfo->Annotation));
switch(pRpcInterfaceInfo->TypeOfStub)
{
case TypeOfStub_Interpreted:pStubW = L"Interpreted"; break;
case TypeOfStub_Inlined: pStubW = L"Inlined"; break;
case TypeOfStub_TypeLib: pStubW = L"TypeLib"; break;
case TypeOfStub_Hybrid: pStubW = L"Hybrid"; break;
default: pStubW = NULL; break;
}
pModel->setData(pModel->index(Index, Column_HasMarshallingInfo), QString::fromUtf16((const ushort*)pStubW));
if ((pRpcInterfaceInfo->IfCallbackFn != 0) && (pRpcInterfaceInfo->IfCallbackFn != (RPC_IF_CALLBACK_FN*)INVALID_IF_CALLBACK_ADDRESS))
{
pModel->setData(pModel->index(Index, Column_IfCallbackFn), QString("0x%1").arg((quintptr)pRpcInterfaceInfo->IfCallbackFn, 16, 16, QLatin1Char('0')));
pModel->setData(pModel->index(Index, Column_IfCallbackFn), (quintptr)pRpcInterfaceInfo->IfCallbackFn,Qt::UserRole);
}
if (pRpcInterfaceInfo->bIsRegistered) SetRowColor(Index,QColor(200, 255, 200, 180));
if (pRpcInterfaceInfo->LocationState & MEM_FREE) SetRowColor(Index, QColor(200, 200, 200, 180));
if (!memcmp(&pRpcInterfaceInfo->TransfertSyntax,&DceRpcSyntaxUuid,sizeof(DceRpcSyntaxUuid)))
pModel->setData(pModel->index(Index, Column_TransfertSyntax), QString::fromLatin1("DCE"));
else if (!memcmp(&pRpcInterfaceInfo->TransfertSyntax,&Ndr64SyntaxUuid,sizeof(Ndr64SyntaxUuid)))
pModel->setData(pModel->index(Index, Column_TransfertSyntax), QString::fromUtf16((const ushort*)L"NDR64"));
else
pModel->setData(pModel->index(Index, Column_TransfertSyntax), QString::fromUtf16((const ushort*)L"unknown"));
End:
if (pUuidString!=NULL) RpcStringFreeW((RPC_WSTR*)&pUuidString);
return (true);
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::AcceptVisitor(ViewVisitor_C* pVisitor)
{
pVisitor->Visit(this);
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::SaveConfiguration(QSettings* pSettings)
{
pSettings->setValue("Interfaces/geometry",pInterfaces->header()->saveState());
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::LoadConfiguration(QSettings* pSettings)
{
pInterfaces->header()->restoreState( pSettings->value("Interfaces/geometry").toByteArray() );
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::CreateColumnsSelectionWidget()
{
pColumnsSelectionWidget = new QGroupBox(WidgetName,this);
QVBoxLayout* pLayout = new QVBoxLayout(pColumnsSelectionWidget);
for (int i = 0; i < Column_Last; i++)
{
ColumnsCheckBoxArray[i] = new QCheckBox(GetColumName((Column_T)i), pColumnsSelectionWidget);
pLayout->addWidget(ColumnsCheckBoxArray[i]);
}
pLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
pColumnsSelectionWidget->setLayout(pLayout);
}
//------------------------------------------------------------------------------
QWidget* InterfacesWidget_C::GetColumnsSelectionWidget()
{
for (int i = 0; i < Column_Last; i++)
{
ColumnsCheckBoxArray[i]->setChecked(!pInterfaces->header()->isSectionHidden(i));
}
return pColumnsSelectionWidget;
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::UpdateColumnsVisibility()
{
for (int i = 0; i < Column_Last; i++)
{
pInterfaces->header()->setSectionHidden(i, !ColumnsCheckBoxArray[i]->isChecked());
}
}
//------------------------------------------------------------------------------
void InterfacesWidget_C::SetAddressRepresentation(AddressRepresentation_T AddrRepresentation)
{
switch (AddrRepresentation)
{
case AddressRepresentation_RVA:
for (int i = 0; i < pModel->rowCount(); i++)
{
pModel->setData(pModel->index(i, Column_IfCallbackFn), "");
quintptr IfCallback = pModel->data(pModel->index(i, Column_IfCallbackFn), Qt::UserRole).toULongLong();
if ((IfCallback != 0) && (IfCallback != INVALID_IF_CALLBACK_ADDRESS))
{
quintptr Base = pModel->data(pModel->index(i, Column_Base), Qt::UserRole).toULongLong();
pModel->setData(pModel->index(i, Column_IfCallbackFn), QString("+0x%1").arg(IfCallback - Base, 8, 16, QLatin1Char('0')));
}
}
break;
//--
case AddressRepresentation_Absolute:
for (int i = 0; i < pModel->rowCount(); i++)
{
pModel->setData(pModel->index(i, Column_IfCallbackFn), "");
quintptr IfCallback = pModel->data(pModel->index(i, Column_IfCallbackFn), Qt::UserRole).toULongLong();
if ((IfCallback != 0) && (IfCallback != INVALID_IF_CALLBACK_ADDRESS))
{
pModel->setData(pModel->index(i, Column_IfCallbackFn), QString("0x%1").arg(IfCallback, HEX_SIZE_OF_PTR, 16, QLatin1Char('0')));
}
}
break;
//--
default:
break;
}
}
//------------------------------------------------------------------------------
InterfacesWidget_C::InterfacesWidget_C(QWidget* pParent):QDockWidget(WidgetName)
{
unsigned int i;
QGridLayout* pGridLayout;
QGroupBox* pGroupBox;
pGroupBox = new QGroupBox(this);
pGridLayout = new QGridLayout(pGroupBox);
setObjectName(WidgetName);
pProxyModel = new QSortFilterProxyModel(this);
pProxyModel->setDynamicSortFilter(true);
pProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
pModel = new QStandardItemModel(0, Column_Last, this);
for(i=0;i<Column_Last;i++)
{
pModel->setHeaderData(i, Qt::Horizontal, GetColumName( (Column_T)i ) );
}
pInterfaces = new QTreeView(this);
pInterfaces->setEditTriggers(QAbstractItemView::NoEditTriggers);
pInterfaces->setSelectionBehavior(QAbstractItemView::SelectRows);
pInterfaces->setSelectionMode(QAbstractItemView::SingleSelection);
pInterfaces->setRootIsDecorated(false);
pInterfaces->setSortingEnabled(true);
pInterfaces->setAnimated(true);
pInterfaces->setModel(pProxyModel);
pInterfaces->sortByColumn(Column_Uuid, Qt::AscendingOrder);
pInterfaces->header()->installEventFilter(pParent);
pProxyModel->setSourceModel(pModel);
connect( pInterfaces, SIGNAL(pressed(const QModelIndex&)), this, SLOT(InterfaceSelected(const QModelIndex&)));
connect( pInterfaces, SIGNAL(activated(const QModelIndex&)), this, SLOT(InterfaceSelected(const QModelIndex&)));
connect( this, SIGNAL(InterfaceSelected(quint32, RPC_IF_ID*)), pParent, SLOT(InterfaceSelected(quint32, RPC_IF_ID*)) );
connect( this, SIGNAL(SigDecompileInterface(quint32, RPC_IF_ID*)), pParent, SLOT(SlotDecompileInterface(quint32, RPC_IF_ID*)) );
//
// Add user filtering (CTL+F) support
//
pFilterWidget = new FilterWidget_C(this);
pGridLayout->addWidget(pInterfaces,0,0);
pGridLayout->addWidget(pFilterWidget,1,0);
pGroupBox->setLayout(pGridLayout);
setWidget(pGroupBox);
//
// Create the widgets for column selection
//
CreateColumnsSelectionWidget();
AddressRepresentation = AddressRepresentation_Absolute;
}