diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b84ede5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/Build diff --git a/Build/x64/bin/Release/QtCore4.dll b/Build/x64/bin/Release/QtCore4.dll new file mode 100644 index 0000000..18c7cc3 Binary files /dev/null and b/Build/x64/bin/Release/QtCore4.dll differ diff --git a/Build/x64/bin/Release/QtGui4.dll b/Build/x64/bin/Release/QtGui4.dll new file mode 100644 index 0000000..4a86575 Binary files /dev/null and b/Build/x64/bin/Release/QtGui4.dll differ diff --git a/Build/x86/bin/Release/QtCore4.dll b/Build/x86/bin/Release/QtCore4.dll new file mode 100644 index 0000000..b5ebe81 Binary files /dev/null and b/Build/x86/bin/Release/QtCore4.dll differ diff --git a/Build/x86/bin/Release/QtGui4.dll b/Build/x86/bin/Release/QtGui4.dll new file mode 100644 index 0000000..4f6dc13 Binary files /dev/null and b/Build/x86/bin/Release/QtGui4.dll differ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ec8def8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required (VERSION 3.0.2) + +project(RpcView) + +set(RPCVIEW_VERSION_MAJOR 0) +set(RPCVIEW_VERSION_MINOR 2) +set(RPCVIEW_VERSION_RELEASE 0) + +# configure a header file to pass some of the CMake settings to the source code +configure_file ( + "RpcView/RpcViewVersion.h.in" + "${PROJECT_BINARY_DIR}/RpcViewVersion.h" + ) + +# add the binary tree to the search path for include files +# so that we will find RpcViewVersion.h +include_directories("${PROJECT_BINARY_DIR}") + +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) + +set(CMAKE_CXX_FLAGS_DEBUG "/W3 /WX /MTd /EHsc /Zi") +set(CMAKE_C_FLAGS_DEBUG "/W4 /WX /MTd /EHsc /Zi") + +set(CMAKE_CXX_FLAGS_RELEASE "/W3 /WX /O2 /Oi /Ot /Gy /MT /EHsc /MP") +set(CMAKE_C_FLAGS_RELEASE "/W4 /WX /O2 /Oi /Ot /Gy /MT /EHsc /MP") + +set(CMAKE_EXE_LINKER_FLAGS "/INCREMENTAL:NO /OPT:REF /OPT:ICF") + +add_definitions(-D_MBCS) + +add_subdirectory(RpcView) +add_subdirectory(RpcDecompiler) +add_subdirectory(RpcCore) \ No newline at end of file diff --git a/Qt/Qt.h b/Qt/Qt.h new file mode 100644 index 0000000..4a7b77a --- /dev/null +++ b/Qt/Qt.h @@ -0,0 +1,47 @@ +#ifndef _RPCVIEW_QT_H_ +#define _RPCVIEW_QT_H_ + +#define QT_BUILD_CONFIGURE +#define NOMINMAX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif \ No newline at end of file diff --git a/Qt/lib/x64/QtCore.lib b/Qt/lib/x64/QtCore.lib new file mode 100644 index 0000000..78e967b Binary files /dev/null and b/Qt/lib/x64/QtCore.lib differ diff --git a/Qt/lib/x64/QtGui.lib b/Qt/lib/x64/QtGui.lib new file mode 100644 index 0000000..46e8338 Binary files /dev/null and b/Qt/lib/x64/QtGui.lib differ diff --git a/Qt/lib/x86/QtCore.lib b/Qt/lib/x86/QtCore.lib new file mode 100644 index 0000000..395a766 Binary files /dev/null and b/Qt/lib/x86/QtCore.lib differ diff --git a/Qt/lib/x86/QtGui.lib b/Qt/lib/x86/QtGui.lib new file mode 100644 index 0000000..2e2c547 Binary files /dev/null and b/Qt/lib/x86/QtGui.lib differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..5c024a2 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +# RpcView # + +RpcView is a free tool to explore and decompile all RPC functionalities present on a Microsoft system. + +## Compilation ## + +Required elements to compiled the project: + +* Visual Studio (currently Visual Studio 2015 community) +* CMake (at least 3.0.2) +* Qt4 (currently 4.8.6) + +Before running CMake you have to set the CMAKE_PREFIX_PATH environment variable with the current Qt path, for instance: +``` +set CMAKE_PREFIX_PATH=C:\Qt\4.8.6 +``` +Then you can run CMake to produce the project solution. +Here is an example to generate the x64 solution with Visual Studio 2053 from the ```RpcView/Build/x64``` directory: + +```cmake +cmake -G"Visual Studio 14 2015 Win64" ../../ +-- The C compiler identification is MSVC 19.0.24215.1 +-- The CXX compiler identification is MSVC 19.0.24215.1 +-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe +-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe +-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/x86_amd64/cl.exe -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +[RpcView] +-- Looking for Q_WS_X11 +-- Looking for Q_WS_X11 - not found +-- Looking for Q_WS_WIN +-- Looking for Q_WS_WIN - found +-- Looking for Q_WS_QWS +-- Looking for Q_WS_QWS - not found +-- Looking for Q_WS_MAC +-- Looking for Q_WS_MAC - not found +-- Found Qt4: C:/Qt/4.8.6/bin/qmake.exe (found version "4.8.6") +-- Target is 64 bits +[RpcDecompiler] +[RpcCore1_32bits] +[RpcCore2_32bits] +[RpcCore2_64bits] +[RpcCore3_32bits] +[RpcCore3_64bits] +[RpcCore4_32bits] +[RpcCore4_64bits] +-- Configuring done +-- Generating done +-- Build files have been written to: C:/Dev/RpcView/Build/x64 +``` + +To produce the Win32 solution with Visual Studio 2015 from the ```RpcView/Build/x86``` directory: +```cmake +cmake -G"Visual Studio 14 2015" ../../ +-- The C compiler identification is MSVC 19.0.24215.1 +-- The CXX compiler identification is MSVC 19.0.24215.1 +-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe +-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe +-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +[RpcView] +-- Looking for Q_WS_X11 +-- Looking for Q_WS_X11 - not found +-- Looking for Q_WS_WIN +-- Looking for Q_WS_WIN - found +-- Looking for Q_WS_QWS +-- Looking for Q_WS_QWS - not found +-- Looking for Q_WS_MAC +-- Looking for Q_WS_MAC - not found +-- Found Qt4: C:/Qt/4.8.6/bin/qmake.exe (found version "4.8.6") +-- Target is 32 bits +[RpcDecompiler] +[RpcCore1_32bits] +[RpcCore2_32bits] +[RpcCore3_32bits] +[RpcCore4_32bits] +-- Configuring done +-- Generating done +-- Build files have been written to: C:/Dev/RpcView/Build/x86 +``` +Now you can compile the solution with Visual Studio or CMAKE: + +``` +cmake --build . --config Release +``` + +RpcView32 binaries are produced in the ```RpcView/Build/bin/x86``` directory and RpcView64 ones in the ```RpcView/Build/bin/x64``` + +## Acknowledgements ## +* Jeremy +* Julien +* Yoanne +* Bruno \ No newline at end of file diff --git a/RpcCommon/Misc.c b/RpcCommon/Misc.c new file mode 100644 index 0000000..77b85eb --- /dev/null +++ b/RpcCommon/Misc.c @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include +#include "Misc.h" +#include "RpcCommon.h" +#include "ntdll.h" + +#pragma comment(lib,"psapi.lib") +#pragma comment(lib,"strsafe.lib") +#pragma comment(lib,"Version.lib") + +#define MAX_DRIVE_INDEX 26 + +typedef struct _LanguageCodePage_T { + WORD wLanguage; + WORD wCodePage; +} LanguageCodePage_T; + + +//------------------------------------------------------------------------------ +BOOL WINAPI AdjustPrivilege(LPCTSTR lpPrivilegeName,BOOL bEnablePrivilege) +{ + TOKEN_PRIVILEGES TokenPrivilege; + LUID Luid; + HANDLE hToken = NULL; + BOOL bResult=FALSE; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) { goto End; } + if (!LookupPrivilegeValue(NULL,lpPrivilegeName,&Luid)) {goto End;} + TokenPrivilege.PrivilegeCount =1; + TokenPrivilege.Privileges[0].Luid=Luid; + if (bEnablePrivilege) TokenPrivilege.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; + else TokenPrivilege.Privileges[0].Attributes=0; + if (!AdjustTokenPrivileges(hToken,FALSE,&TokenPrivilege,sizeof(TOKEN_PRIVILEGES),NULL,NULL)) {goto End;} + if (GetLastError() == ERROR_SUCCESS) bResult=TRUE; +End: + if (hToken != NULL) CloseHandle(hToken); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI EnumProcess(EnumProcessCallbackFn_T EnumProcessCallbackFn,void* pCallbackCtxt) +{ + BOOL bResult=FALSE; + HANDLE hSnapshot; + PROCESSENTRY32W ProcessEntry; + BOOL bContinue=TRUE; + + hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); + if (hSnapshot==NULL) goto End; + ProcessEntry.dwSize=sizeof(ProcessEntry); + if (!Process32FirstW(hSnapshot,&ProcessEntry)) goto End; + do + { + bResult=EnumProcessCallbackFn(ProcessEntry.th32ProcessID,ProcessEntry.th32ParentProcessID,pCallbackCtxt,&bContinue); + if (!bResult) goto End; + if (!bContinue) break; + + }while(Process32NextW(hSnapshot,&ProcessEntry)); +End: + if (hSnapshot!=NULL) CloseHandle(hSnapshot); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetModuleDescription(WCHAR* pModulePath,WCHAR* pDescription,UINT Bytes) +{ + DWORD dwHandle; + DWORD InfoSize; + UINT cbTranslate; + LanguageCodePage_T* lpTranslate; + UINT Size; + UINT i; + WCHAR SubBlock[MAX_PATH]; + WCHAR* lpBuffer; + BOOL bResult=FALSE; + VOID* pData=NULL; + // + // Read the list of languages and code pages. + // + InfoSize=GetFileVersionInfoSizeW(pModulePath,&dwHandle); + pData=OS_ALLOC(InfoSize); + if (pData==NULL) goto End; + + if (!GetFileVersionInfoW(pModulePath,0,InfoSize,pData)) goto End; + + if (!VerQueryValueW(pData, L"\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate,&cbTranslate)) goto End; + // + // Read the file description for each language and code page. + // + for(i=0; i < (cbTranslate/sizeof(LanguageCodePage_T)); i++) + { + StringCbPrintfW(SubBlock,sizeof(SubBlock),L"\\StringFileInfo\\%04x%04x\\FileDescription",lpTranslate[i].wLanguage,lpTranslate[i].wCodePage); + // + // Retrieve file description for language and code page "i". + // + if (VerQueryValueW(pData,SubBlock,(LPVOID*)&lpBuffer,&Size)) + { + StringCbPrintfW(pDescription,Bytes,L"%s",lpBuffer); + break; + } + } + bResult=TRUE; +End: + if (pData!=NULL) OS_FREE(pData); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetLocationInfo(HANDLE hProcess, VOID* pAddress, LocationInfo_T* pLocationInfo) +{ + MEMORY_BASIC_INFORMATION MemBasicInfo; + DWORD DriveMask; + WCHAR DriveIdx; + WCHAR NativeLocation[RPC_MAX_LENGTH]; + WCHAR DeviceName[RPC_MAX_LENGTH]; + WCHAR* pPath; + WCHAR DosDevice[]=L"X:"; + BOOL bResult=FALSE; + + if (pLocationInfo == NULL) goto End; + // + // Get Memory location informations + // + ZeroMemory(pLocationInfo, sizeof(LocationInfo_T)); + if (!VirtualQueryEx(hProcess, pAddress, &MemBasicInfo, sizeof(MemBasicInfo))) goto End; + pLocationInfo->pBaseAddress = MemBasicInfo.BaseAddress; + pLocationInfo->State = MemBasicInfo.State; + pLocationInfo->Type = MemBasicInfo.Type; + pLocationInfo->Size = MemBasicInfo.RegionSize; + // + // Get the native mapped file name containing the specified address + // + if (!GetMappedFileNameW(hProcess, pAddress, NativeLocation, _countof(NativeLocation))) goto End; + // + // Get the correponding Win32 path + // + DriveMask=GetLogicalDrives(); + for (DriveIdx=0; DriveIdx < MAX_DRIVE_INDEX; DriveIdx++) + { + if (DriveMask & (1 << DriveIdx)) + { + DosDevice[0]=L'A'+DriveIdx; + if (QueryDosDeviceW(DosDevice,DeviceName,_countof(DeviceName))!=0) + { + pPath=wcsstr(NativeLocation,DeviceName); + if (pPath!=NULL) + { + StringCbPrintfW(pLocationInfo->Location, sizeof(pLocationInfo->Location), L"%s%s", DosDevice, NativeLocation + wcslen(DeviceName)); + bResult=TRUE; + break; + } + } + } + } +End: + return (bResult); +} + +typedef VOID (WINAPI* RtlGetUnloadEventTraceExFn_T)( + _Out_ PULONG *ElementSize, + _Out_ PULONG *ElementCount, + _Out_ PVOID *EventTrace + ); + +#pragma pack(1) +typedef struct _RTL_UNLOAD_EVENT_TRACE { + void* BaseAddress; // Base address of dll + SIZE_T SizeOfImage; // Size of image + ULONG Sequence; // Sequence number for this event + ULONG TimeDateStamp; // Time and date of image + ULONG CheckSum; // Image checksum + WCHAR ImageName[32]; // Image name +} RTL_UNLOAD_EVENT_TRACE, *PRTL_UNLOAD_EVENT_TRACE; +#pragma pack() + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetUnloadedLocationInfo(HANDLE hProcess, VOID* pAddress, LocationInfo_T* pLocationInfo) +{ + RtlGetUnloadEventTraceExFn_T RtlGetUnloadEventTraceExFn = NULL; + ULONG* pElementSize = NULL; + ULONG* pElementCount = NULL; + UCHAR* pEventTrace = NULL; + RTL_UNLOAD_EVENT_TRACE* pUnloadEventTrace = NULL; + ULONG ElementSize = 0; + ULONG ElementCount = 0; + BOOL bResult = FALSE; + ULONG i = 0; + + RtlGetUnloadEventTraceExFn = (RtlGetUnloadEventTraceExFn_T)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetUnloadEventTraceEx"); + if (RtlGetUnloadEventTraceExFn == NULL) goto End; + // + // Get addresses of ElementSize, ElementCount and pEventTrace in the ntdll + // + RtlGetUnloadEventTraceExFn(&pElementSize, &pElementCount, &pEventTrace); + // + // Read their values in the target process + // + if (!ReadProcessMemory(hProcess, pElementSize, &ElementSize, sizeof(ElementSize), NULL)) goto End; + pUnloadEventTrace = (RTL_UNLOAD_EVENT_TRACE*)OS_ALLOC(ElementSize); + if (pUnloadEventTrace == NULL) goto End; + if (!ReadProcessMemory(hProcess, pElementCount, &ElementCount, sizeof(ElementCount), NULL)) goto End; + if (!ReadProcessMemory(hProcess, pEventTrace, &pEventTrace, sizeof(pEventTrace), NULL)) goto End; + // + // Look for the unloaded module + // + for (i = 0; i < ElementCount; i++) + { + if (!ReadProcessMemory(hProcess, pEventTrace, pUnloadEventTrace, ElementSize, NULL)) goto End; + if (pUnloadEventTrace->BaseAddress == NULL) break; + if (((SIZE_T)pAddress >= (SIZE_T)pUnloadEventTrace->BaseAddress) && + ((SIZE_T)pAddress < ((SIZE_T)pUnloadEventTrace->BaseAddress + pUnloadEventTrace->SizeOfImage))) + { + pLocationInfo->pBaseAddress = pUnloadEventTrace->BaseAddress; + pLocationInfo->Size = pUnloadEventTrace->SizeOfImage; + memcpy(pLocationInfo->Location, pUnloadEventTrace->ImageName, sizeof(pLocationInfo->Location)); + break; + } + pEventTrace += ElementSize; + } +End: + if (pUnloadEventTrace != NULL) OS_FREE(pUnloadEventTrace); + return (bResult); +} + + +//------------------------------------------------------------------------------ +UINT64 WINAPI GetModuleVersion(WCHAR* pModulePath) +{ + DWORD dwHandle; + DWORD VersionInfoSize; + VS_FIXEDFILEINFO* pFixedFileInfo; + LARGE_INTEGER ModuleVersion; + UINT Size; + VOID* pVersionData = NULL; + + ModuleVersion.QuadPart = 0; + VersionInfoSize = GetFileVersionInfoSizeW(pModulePath, &dwHandle); + pVersionData = OS_ALLOC( VersionInfoSize ); + if (pVersionData==NULL) goto End; + + if (!GetFileVersionInfoW(pModulePath, 0, VersionInfoSize, pVersionData)) goto End; + + if (!VerQueryValueW( pVersionData, L"\\", (VOID**)&pFixedFileInfo, &Size )) goto End; + ModuleVersion.HighPart = pFixedFileInfo->dwProductVersionMS; + ModuleVersion.LowPart = pFixedFileInfo->dwProductVersionLS; +End: + if (pVersionData!=NULL) OS_FREE(pVersionData); + return (ModuleVersion.QuadPart); +} + +//------------------------------------------------------------------------------ +BOOL WINAPI GetProcessPebInfo(HANDLE hProcess,WCHAR* pCmdLine,UINT CmdLineLength,WCHAR* pDesktop,UINT DesktopLength) +{ + PROCESS_PARAMETERS ProcessParameters; + NTSTATUS Status; + PEB Peb; + WCHAR TmpBuffer[MAX_PATH]; + BOOL bResult=FALSE; + PROCESS_BASIC_INFORMATION ProcessBasicInfo; + // + // Get process Basic Info + // + Status=NtQueryInformationProcess(hProcess,ProcessBasicInformation,&ProcessBasicInfo,sizeof(ProcessBasicInfo),NULL); + if (Status != STATUS_SUCCESS) goto End; + // + // Read the PEB + // + if (!ReadProcessMemory(hProcess,ProcessBasicInfo.PebBaseAddress,&Peb,sizeof(Peb),NULL)) goto End; + // + // Read the process parameters + // + ZeroMemory(&ProcessParameters,sizeof(ProcessParameters)); + if (!ReadProcessMemory(hProcess,Peb.ProcessParameters,&ProcessParameters,sizeof(ProcessParameters),NULL)) goto End; + // + // Read the CmdLine + // + if (!ReadProcessMemory(hProcess,ProcessParameters.CommandLine.Buffer,TmpBuffer,sizeof(TmpBuffer),NULL)) goto End; + StringCbPrintfW(pCmdLine,CmdLineLength,L"%s",TmpBuffer); + // + // Read the Desktop + // + if (!ReadProcessMemory(hProcess,ProcessParameters.Desktop.Buffer,TmpBuffer,sizeof(TmpBuffer),NULL)) goto End; + StringCbPrintfW(pDesktop,DesktopLength,L"%s",TmpBuffer); + bResult=TRUE; +End: + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetProcessNameFromPid(DWORD Pid,WCHAR* pName,UINT NameSizeInBytes) +{ + HANDLE hProcessSnapshot = INVALID_HANDLE_VALUE; + BOOL bResult = FALSE; + PROCESSENTRY32W ProcessEntry; + + hProcessSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); + if (hProcessSnapshot==INVALID_HANDLE_VALUE) goto End; + ProcessEntry.dwSize=sizeof(ProcessEntry); + if (!Process32FirstW(hProcessSnapshot,&ProcessEntry)) goto End; + do + { + if (Pid==ProcessEntry.th32ProcessID) + { + StringCbPrintfW(pName,NameSizeInBytes,L"%s",ProcessEntry.szExeFile); + break; + } + }while( Process32NextW(hProcessSnapshot,&ProcessEntry) ); + bResult=TRUE; +End: + if (hProcessSnapshot!=INVALID_HANDLE_VALUE) CloseHandle(hProcessSnapshot); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetProcessPath(DWORD Pid, WCHAR* pProcessPath, DWORD ProcessPathLength) +{ + HANDLE hProcess; + BOOL bResult = FALSE; + DWORD Size; + + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); + if (hProcess == NULL) goto End; + Size = ProcessPathLength; + bResult = QueryFullProcessImageNameW(hProcess, 0, pProcessPath, &Size); +End: + if (hProcess!=NULL) CloseHandle(hProcess); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetRegValueData(HKEY hRootKey,WCHAR* pSubkeyName,WCHAR* pValueName,VOID* pData,UINT DataLength) +{ + DWORD Size; + HKEY hKey = NULL; + BOOL bResult = FALSE; + + if (RegOpenKeyExW(hRootKey,pSubkeyName,0,KEY_READ,&hKey)!=ERROR_SUCCESS) goto End; + Size = DataLength; + if (RegQueryValueExW(hKey,pValueName,NULL,NULL,(LPBYTE)pData,&Size)!=ERROR_SUCCESS) goto End; + bResult=TRUE; +End: + if (hKey!=NULL) RegCloseKey(hKey); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetUserAndDomainName(DWORD Pid, WCHAR* Buffer, ULONG BufferLengthInBytes) +{ + HANDLE hProcess = NULL; + HANDLE hToken = NULL; + DWORD Bytes; + TOKEN_USER* pTokenUser=NULL; + WCHAR UserName[RPC_MAX_LENGTH]; + WCHAR DomainName[RPC_MAX_LENGTH]; + DWORD dwSize; + SID_NAME_USE SidType; + BOOL bResult = FALSE; + + hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION,FALSE,Pid); + if (hProcess==NULL) goto End; + + if (!OpenProcessToken(hProcess,TOKEN_QUERY,&hToken)) goto End; + GetTokenInformation(hToken,TokenUser,NULL,0,&Bytes); + pTokenUser=(TOKEN_USER*)OS_ALLOC(Bytes); + if (pTokenUser==NULL) goto End; + if (!GetTokenInformation(hToken,TokenUser,pTokenUser,Bytes,&Bytes)) goto End; + dwSize=sizeof(UserName); + if (!LookupAccountSidW(NULL,pTokenUser->User.Sid,UserName,&dwSize,DomainName,&dwSize,&SidType)) goto End; + StringCbPrintfW(Buffer,BufferLengthInBytes,L"%s\\%s",DomainName,UserName); + bResult=TRUE; +End: + if (pTokenUser!=NULL) OS_FREE(pTokenUser); + if (hToken!=NULL) CloseHandle(hToken); + if (hProcess!=NULL) CloseHandle(hProcess); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI IsProcessWow64(ULONG Pid) +{ + BOOL bWow64 = FALSE; + HANDLE hProcess = NULL; + + hProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_QUERY_INFORMATION,FALSE,Pid); + if (hProcess==NULL) goto End; + IsWow64Process(hProcess,&bWow64); +End: + if (hProcess!=NULL) CloseHandle(hProcess); + return (bWow64); +} \ No newline at end of file diff --git a/RpcCommon/Misc.h b/RpcCommon/Misc.h new file mode 100644 index 0000000..3d95a9c --- /dev/null +++ b/RpcCommon/Misc.h @@ -0,0 +1,56 @@ +#ifndef _MISC_H_ +#define _MISC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma warning(push) +#pragma warning(disable:4201) +//To represent a version as either 64bits value or x.x.x.x +typedef struct _Version_T{ + union{ + UINT64 As64BitsValue; + struct{ + USHORT Part1; + USHORT Part2; + USHORT Part3; + USHORT Part4; + }As16BitsValues; + }; +}Version_T; +#pragma warning(pop) + +typedef struct _LocationInfo_T{ + WCHAR Location[MAX_PATH]; + VOID* pBaseAddress; + DWORD State; + DWORD Type; + SIZE_T Size; +}LocationInfo_T; + + +BOOL WINAPI AdjustPrivilege(LPCTSTR lpPrivilegeName,BOOL bEnablePrivilege); +BOOL WINAPI GetModuleDescription(WCHAR* pModulePath,WCHAR* pDescription,UINT Bytes); +UINT64 WINAPI GetModuleVersion(WCHAR* pModulePath); +BOOL WINAPI GetLocationInfo(HANDLE hProcess, VOID* pAddress, LocationInfo_T* pLocationInfo); +BOOL WINAPI GetUnloadedLocationInfo(HANDLE hProcess, VOID* pAddress, LocationInfo_T* pLocationInfo); +BOOL WINAPI GetProcessNameFromPid(DWORD Pid,WCHAR* pName,UINT NameSizeInBytes); +BOOL WINAPI GetProcessPath(DWORD Pid, WCHAR* pProcessPath, DWORD ProcessPathLength); +BOOL WINAPI GetProcessPebInfo(HANDLE hProcess,WCHAR* pCmdLine,UINT CmdLineLength,WCHAR* pDesktop,UINT DesktopLength); +BOOL WINAPI GetRegValueData(HKEY hRootKey,WCHAR* pSubkeyName,WCHAR* pValueName,VOID* pData,UINT DataLength); +BOOL WINAPI GetUserAndDomainName(DWORD Pid, WCHAR* Buffer, ULONG BufferLengthInBytes); +BOOL WINAPI IsProcessWow64(ULONG Pid); +VOID WINAPI PrintUUID(UUID* pUUID); +HANDLE WINAPI KphOpenProcess(_In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ DWORD dwProcessId); + +typedef BOOL (WINAPI* EnumProcessCallbackFn_T)(DWORD Pid, DWORD Ppid, VOID* pContext, BOOL* pbContinue); +BOOL WINAPI EnumProcess(EnumProcessCallbackFn_T EnumProcessCallbackFn, void* pCallbackCtxt); + +#ifdef __cplusplus +} +#endif + +#endif //_MISC_H_ \ No newline at end of file diff --git a/RpcCommon/RpcCommon.h b/RpcCommon/RpcCommon.h new file mode 100644 index 0000000..27161da --- /dev/null +++ b/RpcCommon/RpcCommon.h @@ -0,0 +1,46 @@ +#ifndef _RPC_COMMON_H_ +#define _RPC_COMMON_H_ + +#include +#include + +#define INVALID_PID_VALUE ((UINT)-1) +#define INVALID_PROC_COUNT ((UINT)-1) +#define RPC_MAX_LENGTH 260 +#define INVALID_IF_CALLBACK_ADDRESS 0x400000 +#define HEX_SIZE_OF_PTR (2*sizeof(void*)) + +typedef enum _AddressRepresentation_T{ + AddressRepresentation_Unknown = 0, + AddressRepresentation_Absolute, + AddressRepresentation_RVA +}AddressRepresentation_T; + +#ifdef _DEBUG + // + // DEBUG + // + #ifndef DBG_NEW + #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ ) + #define new DBG_NEW + #endif + + #define _CRTDBG_MAP_ALLOC + #include + #include + + #define OS_FREE(pMem) free(pMem) + #define OS_ALLOC(Size) calloc(Size,1); + #define OS_DEBUG(...) _cprintf(__VA_ARGS__) + #define DEBUG_BREAK() __debugbreak() +#else + // + // RELEASE + // + #define OS_FREE(pMem) HeapFree(GetProcessHeap(), 0, pMem) + #define OS_ALLOC(Size) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size) + #define OS_DEBUG(...) _cprintf(__VA_ARGS__) + #define DEBUG_BREAK() +#endif // _DEBUG + +#endif//_RPC_COMMON_H_ \ No newline at end of file diff --git a/RpcCommon/RpcView.h b/RpcCommon/RpcView.h new file mode 100644 index 0000000..a26458d --- /dev/null +++ b/RpcCommon/RpcView.h @@ -0,0 +1,33 @@ +#ifndef _RPC_VIEW_H_ +#define _RPC_VIEW_H_ + +#include "RpcCommon.h" +#include + +typedef ULONG RVA_T; + +typedef struct _RpcModuleInfo_T +{ + UINT Pid; + UINT64 pModuleBase; +}RpcModuleInfo_T; + +typedef VOID* (__fastcall* RpcAllocFn_T)(SIZE_T Size); +typedef VOID (__fastcall* RpcFreeFn_T)(VOID* pMem); +typedef BOOL (__fastcall* RpcGetProcessDataFn_T)(RpcModuleInfo_T* pRpcModuleInfo, RVA_T rva, VOID* pBuffer, UINT BufferLength); +typedef VOID (__cdecl* RpcPrintFn_T)(void* pContext, const char* pTxt); +typedef VOID (__cdecl* RpcDebugFn_T)(const char* pFunction, ULONG Line, const char* pFormatString,...); +typedef BOOL (__fastcall* RpcGetInterfaceNameFn_T)(GUID* pIfId,UCHAR* pName,ULONG NameLength); + +//Framework helper for decompilation plugin +typedef struct _RpcViewHelper_T{ + void* pContext; + RpcAllocFn_T RpcAlloc; + RpcFreeFn_T RpcFree; + RpcGetProcessDataFn_T RpcGetProcessData; + RpcPrintFn_T RpcPrint; + RpcDebugFn_T RpcDebug; + RpcGetInterfaceNameFn_T RpcGetInterfaceName; +}RpcViewHelper_T; + +#endif //_RPC_VIEW_H_ \ No newline at end of file diff --git a/RpcCommon/ntdll.c b/RpcCommon/ntdll.c new file mode 100644 index 0000000..9eb9c93 --- /dev/null +++ b/RpcCommon/ntdll.c @@ -0,0 +1,25 @@ +#include "ntdll.h" + +NtQueryInformationProcessFn_T NtQueryInformationProcessFn = NULL; + + +//----------------------------------------------------------------------------- +NTSTATUS NTAPI NtQueryInformationProcess( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength OPTIONAL + ) +{ + if (NtQueryInformationProcessFn == NULL) + { + NtQueryInformationProcessFn = (NtQueryInformationProcessFn_T)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationProcess"); + } + return NtQueryInformationProcessFn( + ProcessHandle, + ProcessInformationClass, + ProcessInformation, + ProcessInformationLength, + ReturnLength); +} \ No newline at end of file diff --git a/RpcCommon/ntdll.h b/RpcCommon/ntdll.h new file mode 100644 index 0000000..db6e348 --- /dev/null +++ b/RpcCommon/ntdll.h @@ -0,0 +1,351 @@ +#ifndef _NTDLL_H_ +#define _NTDLL_H_ + +#include + +typedef LONG KPRIORITY; + +typedef struct _UNICODE_STRING{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +}UNICODE_STRING,*PUNICODE_STRING; + + +typedef VOID (NTAPI* RtlInitUnicodeStringFn_T)( + __out PUNICODE_STRING DestinationString, + __in_z_opt __drv_aliasesMem PCWSTR SourceString + ); + +VOID NTAPI RtlInitUnicodeString( + __out PUNICODE_STRING DestinationString, + __in_z_opt __drv_aliasesMem PCWSTR SourceString + ); + + +typedef struct _PROCESS_PARAMETERS { + ULONG AllocationSize; + ULONG Size; + ULONG Flags; + ULONG Reserved; + ULONG_PTR Console; + ULONG ProcessGroup; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; + UNICODE_STRING CurrentDirectoryName; + HANDLE CurrentDirectoryHandle; + UNICODE_STRING DllPath; + UNICODE_STRING ImageFile; + UNICODE_STRING CommandLine; + PWSTR Environment; + ULONG dwX; + ULONG dwY; + ULONG dwXSize; + ULONG dwYSize; + ULONG dwXCountChars; + ULONG dwYCountChars; + ULONG dwFillAttribute; + ULONG dwFlags; + ULONG wShowWindow; + UNICODE_STRING WindowTitle; + UNICODE_STRING Desktop; + UNICODE_STRING Reserved1; + UNICODE_STRING Reserved2; +} PROCESS_PARAMETERS, *PPROCESS_PARAMETERS; + +#pragma warning(push) +#pragma warning(disable:4214) +typedef struct _PEB{ + UCHAR InheritedAddressSpace; + UCHAR ReadImageFileExecOptions; + UCHAR BeingDebugged; + UCHAR ImageUsesLargePages : 1; + UCHAR IsProtectedProcess : 1; + UCHAR IsLegacyProcess : 1; + UCHAR IsImageDynamicallyRelocated : 1; + UCHAR SpareBits : 4; + VOID* Mutant; + VOID* ImageBaseAddress; + VOID* Ldr; + PROCESS_PARAMETERS* ProcessParameters; +}PEB; +#pragma warning(pop) + +typedef enum _PROCESSINFOCLASS { + ProcessBasicInformation, // 0 + ProcessQuotaLimits, // 1 + ProcessIoCounters, // 2 + ProcessVmCounters, // 3 + ProcessTimes, // 4 + ProcessBasePriority, // 5 + ProcessRaisePriority, // 6 + ProcessDebugPort, // 7 + ProcessExceptionPort, // 8 + ProcessAccessToken, // 9 + ProcessLdtInformation, // 10 + ProcessLdtSize, // 11 + ProcessDefaultHardErrorMode, // 12 + ProcessIoPortHandlers, // 13 + ProcessPooledUsageAndLimits, // 14 + ProcessWorkingSetWatch, // 15 + ProcessUserModeIOPL, // 16 + ProcessEnableAlignmentFaultFixup, // 17 + ProcessPriorityClass, // 18 + ProcessWx86Information, // 19 + ProcessHandleCount, // 20 + ProcessAffinityMask, // 21 + ProcessPriorityBoost, // 22 + ProcessDeviceMap, // 23 + ProcessSessionInformation, // 24 + ProcessForegroundInformation, // 25 + ProcessWow64Information // 26 +} PROCESSINFOCLASS; + + +typedef NTSTATUS (NTAPI* NtQueryInformationProcessFn_T)( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength OPTIONAL + ); + +NTSTATUS NTAPI NtQueryInformationProcess( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength OPTIONAL +); + + +#define STATUS_SUCCESS 0 + +// +// Valid values for the Attributes field +// + +#define OBJ_INHERIT 0x00000002L +#define OBJ_PERMANENT 0x00000010L +#define OBJ_EXCLUSIVE 0x00000020L +#define OBJ_CASE_INSENSITIVE 0x00000040L +#define OBJ_OPENIF 0x00000080L +#define OBJ_OPENLINK 0x00000100L +#define OBJ_KERNEL_HANDLE 0x00000200L +#define OBJ_FORCE_ACCESS_CHECK 0x00000400L +#define OBJ_VALID_ATTRIBUTES 0x000007F2L + + +typedef struct _PROCESS_BASIC_INFORMATION { // Information Class 0 + ULONG_PTR ExitStatus; + PEB* PebBaseAddress; + ULONG_PTR AffinityMask; + ULONG_PTR BasePriority; + ULONG_PTR UniqueProcessId; + ULONG_PTR InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; + + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR + PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; +typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES; + +//++ +// +// VOID +// InitializeObjectAttributes( +// __out POBJECT_ATTRIBUTES p, +// __in PUNICODE_STRING n, +// __in ULONG a, +// __in HANDLE r, +// __in PSECURITY_DESCRIPTOR s +// ) +// +//-- + +#define InitializeObjectAttributes( p, n, a, r, s ) { \ + (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ + } + +typedef NTSTATUS (NTAPI* NtOpenSectionFn_T)( + __out PHANDLE SectionHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes + ); + + +NTSTATUS NTAPI NtOpenSection( + __out PHANDLE SectionHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes + ); + +// +// Section Information Structures. +// + +typedef enum _SECTION_INHERIT { + ViewShare = 1, + ViewUnmap = 2 +} SECTION_INHERIT; + +typedef NTSTATUS (NTAPI* NtCreateSectionFn_T)( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PLARGE_INTEGER MaximumSize, + _In_ ULONG SectionPageProtection, + _In_ ULONG AllocationAttributes, + _In_opt_ HANDLE FileHandle + ); + +NTSTATUS NTAPI NtCreateSection( + _Out_ PHANDLE SectionHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ PLARGE_INTEGER MaximumSize, + _In_ ULONG SectionPageProtection, + _In_ ULONG AllocationAttributes, + _In_opt_ HANDLE FileHandle +); + + +typedef NTSTATUS (NTAPI* NtMapViewOfSectionFn_T)( + __in HANDLE SectionHandle, + __in HANDLE ProcessHandle, + __inout PVOID *BaseAddress, + __in ULONG_PTR ZeroBits, + __in SIZE_T CommitSize, + __inout_opt PLARGE_INTEGER SectionOffset, + __inout PSIZE_T ViewSize, + __in SECTION_INHERIT InheritDisposition, + __in ULONG AllocationType, + __in ULONG Win32Protect + ); + + +NTSTATUS NTAPI NtMapViewOfSection( + __in HANDLE SectionHandle, + __in HANDLE ProcessHandle, + __inout PVOID *BaseAddress, + __in ULONG_PTR ZeroBits, + __in SIZE_T CommitSize, + __inout_opt PLARGE_INTEGER SectionOffset, + __inout PSIZE_T ViewSize, + __in SECTION_INHERIT InheritDisposition, + __in ULONG AllocationType, + __in ULONG Win32Protect + ); + + +typedef enum THREAD_INFORMATION_CLASS { + ThreadBasicInformation, + ThreadTimes, + ThreadPriority, + ThreadBasePriority, + ThreadAffinityMask, + ThreadImpersonationToken, + ThreadDescriptorTableEntry, + ThreadEnableAlignmentFaultFixup, + ThreadEventPair, + ThreadQuerySetWin32StartAddress, + ThreadZeroTlsCell, + ThreadPerformanceCount, + ThreadAmILastThread, + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, + ThreadIsIoPending, + ThreadHideFromDebugger +} THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS; + +typedef struct { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID; + +typedef struct _THREAD_BASIC_INFORMATION { + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + CLIENT_ID ClientId; + KAFFINITY AffinityMask; + KPRIORITY Priority; + KPRIORITY BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +typedef NTSTATUS (NTAPI* NtQueryInformationThreadFn_T)( + __in HANDLE ThreadHandle, + __in THREAD_INFORMATION_CLASS ThreadInformationClass, + __out PVOID ThreadInformation, + __in ULONG ThreadInformationLength, + __out PULONG ReturnLength OPTIONAL + ); + + +NTSTATUS NTAPI NtQueryInformationThread( + __in HANDLE ThreadHandle, + __in THREAD_INFORMATION_CLASS ThreadInformationClass, + __out PVOID ThreadInformation, + __in ULONG ThreadInformationLength, + __out PULONG ReturnLength OPTIONAL +); + + +typedef NTSTATUS (NTAPI* NtUnmapViewOfSectionFn_T)( + __in HANDLE ProcessHandle, + __in_opt PVOID BaseAddress + ); + +NTSTATUS NTAPI NtUnmapViewOfSection( + __in HANDLE ProcessHandle, + __in_opt PVOID BaseAddress + ); + +#pragma warning(push) +#pragma warning(disable:4201) +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; +#pragma warning(pop) + +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 + +typedef NTSTATUS (NTAPI* NtOpenFileFn_T)( + __out PHANDLE FileHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in ULONG ShareAccess, + __in ULONG OpenOptions +); + +NTSTATUS NTAPI NtOpenFile( + __out PHANDLE FileHandle, + __in ACCESS_MASK DesiredAccess, + __in POBJECT_ATTRIBUTES ObjectAttributes, + __out PIO_STATUS_BLOCK IoStatusBlock, + __in ULONG ShareAccess, + __in ULONG OpenOptions +); +#endif //_NTDLL_H_ \ No newline at end of file diff --git a/RpcCore/CMakeLists.txt b/RpcCore/CMakeLists.txt new file mode 100644 index 0000000..eea7194 --- /dev/null +++ b/RpcCore/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required (VERSION 3.0.2) + +function(AddRpcCore Directory) + message("[${Directory}]") + add_library(${Directory} SHARED + # ComInternals.c + RpcCore.c + ../RpcCommon/ntdll.c + ../RpcCommon/Misc.c + RpcCore.def + RpcCoreResource.rc + ) + + target_include_directories( + ${Directory} PUBLIC + ${Directory} + ) +endfunction(AddRpcCore) + +file(GLOB CoreFiles *) +foreach(Files ${CoreFiles}) + if (IS_DIRECTORY ${Files} ) + + get_filename_component(Dir ${Files} NAME) + + if(${CMAKE_GENERATOR} MATCHES "Win64") + AddRpcCore(${Dir}) + else(${CMAKE_GENERATOR} MATCHES "Win64") + if(${Dir} MATCHES "32bits") + AddRpcCore(${Dir}) + endif(${Dir} MATCHES "32bits") + endif(${CMAKE_GENERATOR} MATCHES "Win64") + endif (IS_DIRECTORY ${Files} ) +endforeach(Files) \ No newline at end of file diff --git a/RpcCore/RpcCore.c b/RpcCore/RpcCore.c new file mode 100644 index 0000000..9c093b2 --- /dev/null +++ b/RpcCore/RpcCore.c @@ -0,0 +1,1072 @@ +#define SECURITY_WIN32 + +#include +#include +#include +#include "RpcCore.h" +#include "..\RpcCommon\ntdll.h" +#include +#include +#include +#include +#include "..\..\RpcCommon\RpcCommon.h" +#include "..\..\RpcCommon\Misc.h" +#include + +#pragma comment(lib,"Rpcrt4.lib") +#pragma comment(lib,"Secur32.lib") +#pragma comment(lib,"Advapi32.lib") +#pragma comment(lib,"Version.lib") +#pragma comment(lib,"Userenv.lib") + +#define MAX_SIMPLE_DICT_ENTRIES 0x400 +#define RPC_MAX_ENDPOINT_PROTOCOL_SIZE 0x100 +#define RPC_MAX_ENDPOINT_NAME_SIZE 0x100 +#define RPC_MAX_DLL_NAME_SIZE 0x100 +#define RPC_IS_EPMAPPER_REGISTERED 0x20 + + +//////////////////////////////////////////////////////////////////////////////// +// Type definitions +//////////////////////////////////////////////////////////////////////////////// +typedef struct _RpcCoreInternalCtxt_T{ + VOID* pGlobalRpcServer; + UINT64 ModuleVersion; +}RpcCoreInternalCtxt_T; + +typedef struct _ModuleSectionInfo_T{ + VOID* pBase; + UINT Size; +}ModuleSectionInfo_T; + + +//////////////////////////////////////////////////////////////////////////////// +// Functions declarations +//////////////////////////////////////////////////////////////////////////////// + +// Misc +BOOL WINAPI GetModuleDataSection(HANDLE hProcess,VOID* pModule,ModuleSectionInfo_T* pModuleSectionInfo); +VOID* WINAPI GetProcessInterface(void* pRpcCoreCtxt,HANDLE hProcess,RPC_IF_ID* pIf); + +typedef BOOL (WINAPI* EnumSimpleDictCallbackFn_T)(HANDLE hProcess, UINT Index, VOID PTR_T pSimpleDictEntry, VOID* pContext, BOOL* pbContinue); +BOOL WINAPI EnumSimpleDict(HANDLE hProcess, SIMPLE_DICT_T* pSimpleDict, EnumSimpleDictCallbackFn_T EnumSimpleDictCallbackFn, VOID* pContext); + +// RpcCore +VOID* __fastcall RpcCoreInit(); //returns a private context for the RpcCoreEngine +VOID __fastcall RpcCoreUninit(VOID* pRpcCoreCtxt); +RpcProcessInfo_T* __fastcall RpcCoreGetProcessInfo(void* pRpcCoreCtxt,DWORD Pid,DWORD Ppid,ULONG ProcessInfoMask); +VOID __fastcall RpcCoreFreeProcessInfo(void* pRpcCoreCtxt,RpcProcessInfo_T* pRpcProcessInfo); +RpcInterfaceInfo_T* __fastcall RpcCoreGetInterfaceInfo(void* pRpcCoreCtxt,DWORD Pid,RPC_IF_ID* pIf,ULONG InterfaceInfoMask); +VOID __fastcall RpcCoreFreeInterfaceInfo(void* pRpcCoreCtxt,RpcInterfaceInfo_T* pRpcInterfaceInfo); +BOOL __fastcall RpcCoreEnumProcessInterfaces(void* pRpcCoreCtxt,DWORD Pid,RpcCoreEnumProcessInterfacesCallbackFn_T RpcCoreEnumProcessInterfacesCallbackFn,void* pCallbackCtxt,ULONG InterfaceInfoMask); +BOOL __fastcall RpcCoreEnumProcessEndpoints(void* pRpcCoreCtxt,DWORD Pid,RpcCoreEnumProcessEndpointsCallbackFn_T RpcCoreEnumProcessEndpointsCallbackFn,void* pCallbackCtxt); +BOOL __fastcall RpcCoreEnumProcessAuthInfo(void* pRpcCoreCtxt,DWORD Pid,RpcCoreEnumProcessAuthInfoCallbackFn_T RpcCoreEnumProcessAuthInfoCallbackFn,void* pCallbackCtxt); + +//////////////////////////////////////////////////////////////////////////////// +// Global declarations +//////////////////////////////////////////////////////////////////////////////// + +WCHAR gInterfaceFile[] = L"RpcView.ini"; +const char gRpcCoreDataSectionName[] = ".data"; + +RpcCore_T RpcCoreHelper = +{ + RPC_CORE_RUNTIME_VERSION, + RPC_CORE_IS_WOW64, + &RpcCoreInit, + &RpcCoreUninit, + &RpcCoreGetProcessInfo, + &RpcCoreFreeProcessInfo, + &RpcCoreGetInterfaceInfo, + &RpcCoreFreeInterfaceInfo, + &RpcCoreEnumProcessInterfaces, + &RpcCoreEnumProcessEndpoints, + &RpcCoreEnumProcessAuthInfo, +}; + + +const RPC_IF_ID gIorCallback = +{ + { 0x18f70770, 0x8e64, 0x11cf, { 0x9a, 0xf1, 0x00, 0x20, 0xAF, 0x6E, 0x72, 0xF4 } }, // Uuid + 0, // VersMajor + 0 // VersMinor +}; + +//------------------------------------------------------------------------------ +BOOL WINAPI EnumSimpleDict(HANDLE hProcess, SIMPLE_DICT_T* pSimpleDict, EnumSimpleDictCallbackFn_T EnumSimpleDictCallbackFn, VOID* pContext) +{ + //WARNING : in case of WOW64 core, pTable is an array of 32-bit pointers for which each address is itself a 64-bit pointer + VOID PTR_T * pTable=NULL; + UINT i; + UINT Size; + BOOL bResult = TRUE; + BOOL bContinue = TRUE; //Assume continue + + if ( pSimpleDict->NumberOfEntries > MAX_SIMPLE_DICT_ENTRIES) + { + goto End; + } + + Size=pSimpleDict->NumberOfEntries*sizeof(VOID PTR_T); + pTable=(VOID PTR_T *)OS_ALLOC(Size); + if (pTable==NULL) goto End; + ZeroMemory(pTable,Size); + + if (!ReadProcessMemory(hProcess,pSimpleDict->pArray,pTable,Size,NULL)) goto End; + for (i=0; iNumberOfEntries; i++) + { + bResult = EnumSimpleDictCallbackFn(hProcess,i,pTable[i],pContext,&bContinue); + if (!bResult) goto End; + if (!bContinue) break; + } + bResult=TRUE; +End: + if (pTable!=NULL) OS_FREE(pTable); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetModuleDataSection(HANDLE hProcess,VOID* pModule,ModuleSectionInfo_T* pModuleSectionInfo) +{ + IMAGE_DOS_HEADER ImageDosHeader; + IMAGE_NT_HEADERS ImageNtHeaders; + IMAGE_SECTION_HEADER* pImageSectionHeader; + UINT SectionIdx; + IMAGE_SECTION_HEADER ImageSectionHeader; + UCHAR* pBase = (UCHAR*)pModule; + BOOL bResult = FALSE; + + if (!ReadProcessMemory(hProcess,pBase,&ImageDosHeader,sizeof(ImageDosHeader), NULL)) goto End; + if (ImageDosHeader.e_magic!=IMAGE_DOS_SIGNATURE) goto End; + if (!ReadProcessMemory(hProcess,pBase+ImageDosHeader.e_lfanew,&ImageNtHeaders,sizeof(ImageNtHeaders), NULL)) goto End; + if (ImageNtHeaders.Signature!=IMAGE_NT_SIGNATURE) goto End; + // + // For 64bits, add the size of IMAGE_NT_HEADERS64 to its own base to get the base of the IMAGE_SECTION_HEADER table + // +#ifdef _WIN64 +#pragma warning(push) +#pragma warning(disable:4127) + if (RPC_CORE_IS_WOW64==TRUE) pImageSectionHeader = (IMAGE_SECTION_HEADER*) ((UINT_PTR)pBase+ImageDosHeader.e_lfanew+sizeof(IMAGE_NT_HEADERS32)); +#pragma warning(pop) + else +#endif + pImageSectionHeader = (IMAGE_SECTION_HEADER*) ((UINT_PTR)pBase+ImageDosHeader.e_lfanew+sizeof(IMAGE_NT_HEADERS)); + + for(SectionIdx=0; SectionIdxpBase = pBase + ImageSectionHeader.VirtualAddress; + pModuleSectionInfo->Size = ImageSectionHeader.Misc.VirtualSize; + bResult=TRUE; + break; + } + } +End: + return (bResult); +} + + +typedef struct{ + BOOL bFound; +}GetRpcServerAddressCallbackCtxt_T; + + +//8a885d04-1ceb-11c9-9fe8-08002b104860 V2.0 +RPC_SYNTAX_IDENTIFIER DceRpcSyntaxUuid = +{ + { 0x8a885d04,0x1ceb,0x11c9,{ 0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60 } }, + { 2,0 } +}; + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetRpcServerAddressCallback(HANDLE hProcess, UINT Index, VOID PTR_T pSimpleDictEntry, VOID* pContext, BOOL* pbContinue) +{ + RPC_INTERFACE_T RpcInterface; + GetRpcServerAddressCallbackCtxt_T* pGetRpcServerAddressCallbackCtxt=(GetRpcServerAddressCallbackCtxt_T*)pContext; + + UNREFERENCED_PARAMETER(Index); + + if (!ReadProcessMemory(hProcess,pSimpleDictEntry,&RpcInterface,sizeof(RpcInterface),NULL)) goto End; + + if ( (RpcInterface.RpcServerInterface.Length==sizeof(RPC_SERVER_INTERFACE_T)) && + (!memcmp(&RpcInterface.RpcServerInterface.TransferSyntax, &DceRpcSyntaxUuid, sizeof(DceRpcSyntaxUuid)))) + { + pGetRpcServerAddressCallbackCtxt->bFound = TRUE; + *pbContinue=FALSE; + } +End: + return (TRUE); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetRpcServerAddressInProcess(DWORD Pid,RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt) +{ + VOID PTR_T PTR_T pCandidate; + VOID PTR_T pRpcServer; + RPC_SERVER_T RpcServer; + ModuleSectionInfo_T ModuleSectionInfo; + HANDLE hProcess = NULL; + GetRpcServerAddressCallbackCtxt_T GetRpcServerAddressCallbackCtxt; + DWORD cbSize; + HMODULE* pHmodule = NULL; + CHAR ModuleFileName[MAX_PATH]; + BOOL bResult=FALSE; + + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); + if (hProcess == NULL) goto End; + + EnumProcessModulesEx(hProcess, NULL, 0, &cbSize, LIST_MODULES_ALL); + if (cbSize == 0) goto End; + pHmodule = (HMODULE*)malloc(cbSize); + EnumProcessModulesEx(hProcess, pHmodule, cbSize, &cbSize, LIST_MODULES_ALL); + + for(ULONG i=0;ipGlobalRpcServer=pCandidate; + bResult=TRUE; + break; + } +NextCandidate: + pCandidate++; + } + CloseHandle(hProcess); + hProcess=NULL; + goto End; +NextModule: ; + } +End: + if (hProcess!=NULL) CloseHandle(hProcess); + if (pHmodule !=NULL) free(pHmodule); + return (bResult); +} + + + +//------------------------------------------------------------------------------ +VOID* __fastcall RpcCoreInit() +{ + UINT64 RuntimVersion; + RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt=NULL; + WCHAR RpcRuntimePath[MAX_PATH]; + UINT i; + BOOL bFound = FALSE; + +#ifdef _DEBUG + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); +#endif + // + // Get the RPC runtime version (rpcrt4.dll) to verify if it is supported by this Core + // + if (GetSystemDirectoryW(RpcRuntimePath,_countof(RpcRuntimePath))==0) goto End; + StringCbPrintfW(RpcRuntimePath,sizeof(RpcRuntimePath),L"%s\\rpcrt4.dll",RpcRuntimePath); + RuntimVersion=GetModuleVersion(RpcRuntimePath); + for (i = 0; i < sizeof(RPC_CORE_RUNTIME_VERSION); i++) + { + if (RuntimVersion == RPC_CORE_RUNTIME_VERSION[i]) + { + bFound = TRUE; + break; + } + } + if (!bFound) goto End; + // + // Invoke CoInitialize, required by SHGetFileInfo + // + CoInitialize(NULL); + // + pRpcCoreInternalCtxt=(RpcCoreInternalCtxt_T*)OS_ALLOC(sizeof(RpcCoreInternalCtxt_T)); + if (pRpcCoreInternalCtxt==NULL) goto End; + + pRpcCoreInternalCtxt->ModuleVersion = RuntimVersion; + // + // Try to activate the DEBUG privilege to access all processes + // + AdjustPrivilege(SE_DEBUG_NAME,TRUE); +End: + return (pRpcCoreInternalCtxt); +} + + +//------------------------------------------------------------------------------ +VOID __fastcall RpcCoreUninit(VOID* pRpcCoreCtxt) +{ + OS_FREE(pRpcCoreCtxt); +#ifdef _DEBUG + _CrtDumpMemoryLeaks(); +#endif +} + + +//------------------------------------------------------------------------------ +RpcProcessType_T __fastcall GetProcessType(HANDLE hProcess, RPC_SERVER_T* pRpcServer) +{ + SIZE_T Size; + ULONG i; + RPC_INTERFACE_T RpcInterface; + RpcProcessType_T RpcProcessType = RpcProcessType_UNKNOWN; + VOID PTR_T * pTable = NULL; + + if (pRpcServer==NULL) goto End; + + Size=pRpcServer->InterfaceDict.NumberOfEntries*sizeof(VOID PTR_T); + pTable=(VOID PTR_T *)OS_ALLOC(Size); + if (pTable==NULL) goto End; + + if (!ReadProcessMemory(hProcess,pRpcServer->InterfaceDict.pArray,pTable,Size,NULL)) goto End; + for (i=0; iInterfaceDict.NumberOfEntries; i++) + { + if (!ReadProcessMemory(hProcess,pTable[i],&RpcInterface,sizeof(RpcInterface),NULL)) goto End; + if ((RpcInterface.Flags & RPC_IF_OLE) || (memcmp(&RpcInterface.RpcServerInterface.InterfaceId, &gIorCallback, sizeof(RPC_IF_ID)) == 0)) + { + //The interface is DCOM + if ( (RpcProcessType==RpcProcessType_UNKNOWN) || (RpcProcessType==RpcProcessType_DCOM) ) + { + RpcProcessType = RpcProcessType_DCOM; + } + else + { + RpcProcessType = RpcProcessType_HYBRID; + goto End; //we can stop now + } + } + else + { + //The interface is RPC + if ( (RpcProcessType==RpcProcessType_UNKNOWN) || (RpcProcessType==RpcProcessType_RPC) ) + { + RpcProcessType = RpcProcessType_RPC; + } + else + { + RpcProcessType = RpcProcessType_HYBRID; + goto End; //we can stop now + } + } + } +End: + if (pTable!=NULL) OS_FREE(pTable); + return (RpcProcessType); +} + + +//------------------------------------------------------------------------------ +RpcProcessInfo_T* __fastcall RpcCoreGetProcessInfo(void* pRpcCoreCtxt,DWORD Pid,DWORD Ppid,ULONG ProcessInfoMask) +{ + SHFILEINFOW ShFileInfo; + HANDLE hProcess; + VOID PTR_T pRpcServer; + RPC_SERVER_T RpcServer; + RpcProcessInfo_T* pRpcProcessInfo=NULL; + RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt=(RpcCoreInternalCtxt_T*)pRpcCoreCtxt; + + pRpcProcessInfo=(RpcProcessInfo_T*)OS_ALLOC(sizeof(RpcProcessInfo_T)); + if (pRpcProcessInfo==NULL) return (NULL); + // + // Process minimal info + // + pRpcProcessInfo->Pid = Pid; + pRpcProcessInfo->ParentPid = Ppid; + pRpcProcessInfo->RpcProcessType = RpcProcessType_UNKNOWN; + + hProcess=OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,Pid); + if (hProcess!=NULL) + { +#ifdef _WIN64 + IsWow64Process(hProcess, &pRpcProcessInfo->bIsWow64); +#endif + } + // + // Process general information + // + if (ProcessInfoMask & RPC_PROCESS_INFO_MISC) + { + GetProcessNameFromPid(Pid,pRpcProcessInfo->Name,sizeof(pRpcProcessInfo->Name)); + GetProcessPath(Pid,pRpcProcessInfo->Path,sizeof(pRpcProcessInfo->Path)); + pRpcProcessInfo->Version=GetModuleVersion(pRpcProcessInfo->Path); + GetModuleDescription(pRpcProcessInfo->Path,pRpcProcessInfo->Description,sizeof(pRpcProcessInfo->Description)); + GetUserAndDomainName(pRpcProcessInfo->Pid,pRpcProcessInfo->User,sizeof(pRpcProcessInfo->User)); + GetProcessPebInfo(hProcess,pRpcProcessInfo->CmdLine,sizeof(pRpcProcessInfo->CmdLine),pRpcProcessInfo->Desktop,sizeof(pRpcProcessInfo->Desktop)); + // Get icon + if (hProcess!=NULL) + { + ZeroMemory(&ShFileInfo,sizeof(ShFileInfo)); + if (SHGetFileInfoW(pRpcProcessInfo->Path,0,&ShFileInfo,sizeof(ShFileInfo),SHGFI_ICON|SHGFI_LARGEICON)) + { + pRpcProcessInfo->hIcon=ShFileInfo.hIcon; + } + } + } + // + // Process RPC information + // + if (ProcessInfoMask & RPC_PROCESS_INFO_RPC) + { + if (pRpcCoreInternalCtxt->pGlobalRpcServer==NULL) + { + GetRpcServerAddressInProcess(pRpcProcessInfo->Pid,pRpcCoreInternalCtxt); + if (pRpcCoreInternalCtxt->pGlobalRpcServer==NULL) goto End; + } + if (!ReadProcessMemory(hProcess,pRpcCoreInternalCtxt->pGlobalRpcServer,&pRpcServer,sizeof(VOID PTR_T),NULL)) goto End; + if (!ReadProcessMemory(hProcess,pRpcServer,&RpcServer,sizeof(RpcServer),NULL)) goto End; + + //If the number of endpoints is correct we have a RPC server + if (RpcServer.AddressDict.NumberOfEntries!=0) + { + pRpcProcessInfo->RpcProcessType = GetProcessType(hProcess,&RpcServer); + pRpcProcessInfo->bIsServer = TRUE; + pRpcProcessInfo->EndpointsCount = RpcServer.AddressDict.NumberOfEntries; + pRpcProcessInfo->SspCount = RpcServer.AuthenInfoDict.NumberOfEntries; + pRpcProcessInfo->InterfacesCount = RpcServer.InterfaceDict.NumberOfEntries; + pRpcProcessInfo->InCalls = RpcServer.InCalls; + pRpcProcessInfo->OutCalls = RpcServer.OutCalls; + pRpcProcessInfo->InPackets = RpcServer.InPackets; + pRpcProcessInfo->OutPackets = RpcServer.OutPackets; + pRpcProcessInfo->bIsListening = RpcServer.bIsListening; + pRpcProcessInfo->MaxCalls = RpcServer.MaxCalls; + } + } +End: + if (hProcess!=NULL) CloseHandle(hProcess); + return (pRpcProcessInfo); +} + + +//------------------------------------------------------------------------------ +VOID __fastcall RpcCoreFreeProcessInfo(void* pRpcCoreCtxt,RpcProcessInfo_T* pRpcProcessInfo) +{ + UNREFERENCED_PARAMETER(pRpcCoreCtxt); + OS_FREE(pRpcProcessInfo); +} + + +//------------------------------------------------------------------------------ +void GetInlineStubInfo(RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt,HANDLE hProcess,VOID* pRpcInterface,RpcInterfaceInfo_T* pRpcInterfaceInfo) +{ + RPC_INTERFACE_T RpcInterface; + RPC_DISPATCH_TABLE_T RpcDispatchTbl; + VOID PTR_T pProc; + UINT i; + + UNREFERENCED_PARAMETER(pRpcCoreInternalCtxt); + + if (pRpcInterfaceInfo==NULL) goto End; + if (!ReadProcessMemory(hProcess,pRpcInterface,&RpcInterface,sizeof(RpcInterface),NULL)) goto End; + // + // Get the interface procedures count + // + if (!ReadProcessMemory(hProcess,RpcInterface.RpcServerInterface.DispatchTable,&RpcDispatchTbl,sizeof(RpcDispatchTbl),NULL)) goto End; + + if (pRpcInterfaceInfo->IfType==IfType_RPC) + { + pRpcInterfaceInfo->NumberOfProcedures=RpcDispatchTbl.DispatchTableCount; + pRpcInterfaceInfo->TypeOfStub=TypeOfStub_Inlined; + // + // Get the interface procedure addresses table + // + pRpcInterfaceInfo->ppProcAddressTable=(ULONG*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(VOID *)); + if (pRpcInterfaceInfo->ppProcAddressTable==NULL) goto End; + + pRpcInterfaceInfo->pFormatStringOffsetTable = (USHORT*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(USHORT)); + if (pRpcInterfaceInfo->pFormatStringOffsetTable==NULL) goto End; + + for(i=0;iNumberOfProcedures;i++) + { + pProc=NULL; + if (!ReadProcessMemory(hProcess,((VOID PTR_T PTR_T)RpcDispatchTbl.DispatchTable)+i,&pProc,sizeof(VOID PTR_T),NULL)) goto End; + pRpcInterfaceInfo->ppProcAddressTable[i]=(ULONG)((ULONG_PTR)pProc - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + } + } +End: + return; +} + +#if (RPC_CORE_IS_WOW64==TRUE) +#define REG_PREFIX L"Wow6432Node\\" +#else +#define REG_PREFIX L"" +#endif + + +//------------------------------------------------------------------------------ +BOOL NTAPI GetComInterfaceName(const RPC_IF_ID* pInterfaceId, WCHAR* pName, UINT NameLength) +{ + WCHAR SubKeyName[MAX_PATH]; + RPC_WSTR pUuidString = NULL; + BOOL bResult = FALSE; + + if (UuidToStringW(&pInterfaceId->Uuid, &pUuidString) != RPC_S_OK) goto End; + StringCbPrintfW(SubKeyName, sizeof(SubKeyName), REG_PREFIX L"Interface\\{%s}", pUuidString); + if (GetRegValueData(HKEY_CLASSES_ROOT, SubKeyName, NULL, pName, NameLength) == FALSE) goto End; + + bResult = TRUE; +End: + if (pUuidString != NULL) RpcStringFreeW(&pUuidString); + return (bResult); +} + + +//------------------------------------------------------------------------------ +IfType_T WINAPI GetInterfaceType(const RPC_INTERFACE_T* pRpcInterface) +{ + WCHAR TmpPath[MAX_PATH]; + + if ( pRpcInterface->Flags & RPC_IF_OLE ) + { + return (IfType_OLE); + } + + if ( GetComInterfaceName(&pRpcInterface->RpcServerInterface.InterfaceId,TmpPath,sizeof(TmpPath)) == FALSE ) + { + return (IfType_RPC); + } + return (IfType_DCOM); +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall GetInterfaceName(RPC_IF_ID* pInterfaceId,WCHAR* pName,UINT NameLength) +{ + WCHAR FullPath[MAX_PATH]; + RPC_WSTR pUuidString=NULL; + BOOL bResult=FALSE; + + if (pInterfaceId==NULL) goto End; + + pName[0]=0; + bResult = GetComInterfaceName(pInterfaceId,pName,NameLength); + if (bResult==FALSE) + { + UuidToStringW(&pInterfaceId->Uuid,&pUuidString); + GetFullPathNameW(gInterfaceFile,_countof(FullPath),FullPath,NULL); + GetPrivateProfileStringW((LPCWSTR)pUuidString,L"Name",NULL,pName,NameLength/sizeof(WCHAR),FullPath); + } +End: + if (pUuidString!=NULL) RpcStringFreeW(&pUuidString); + return (bResult); +} + + +//------------------------------------------------------------------------------ +RpcInterfaceInfo_T* WINAPI InternalGetInterfaceInfo(RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt, HANDLE hProcess, VOID* pRpcInterface, DWORD Pid, ULONG InterfaceInfoMask) +{ + MIDL_SERVER_INFO_T MidlServerInfo; + MIDL_STUB_DESC_T MidlStubDesc; + RPC_DISPATCH_TABLE_T RpcDispatchTbl; + RPC_INTERFACE_T RpcInterface; + MODULEENTRY32W ModuleEntry; + UINT i; + NDR_EXPR_DESC_T NdrExprDesc; + VOID PTR_T pProc = NULL; + WCHAR* pModuleName = NULL; + HANDLE hModulesSnapshot = NULL; + RpcInterfaceInfo_T* pRpcInterfaceInfo = NULL; + LocationInfo_T LocationInfo = {0}; + + UNREFERENCED_PARAMETER(pRpcCoreInternalCtxt); + // + // Get the RPC_INTERFACE + // + if (!ReadProcessMemory(hProcess, pRpcInterface, &RpcInterface, sizeof(RpcInterface), NULL)) + { + //printf("ReadProcessMemory failed RpcInterface\n"); + goto End; + } + + pRpcInterfaceInfo=(RpcInterfaceInfo_T*)OS_ALLOC(sizeof(RpcInterfaceInfo_T)); + if (pRpcInterfaceInfo == NULL) { DEBUG_BREAK(); goto End; } + // + // Get Default interface information + // - Pid + // - Flags + // - Type + // - UUID + // - Transfert Syntax GUID + // - Name + // +#ifdef _WIN64 + pRpcInterfaceInfo->bWow64Process = RPC_CORE_IS_WOW64; +#endif + pRpcInterfaceInfo->Pid = Pid; + pRpcInterfaceInfo->Flags = RpcInterface.Flags; + pRpcInterfaceInfo->IfType = GetInterfaceType(&RpcInterface); + // + memcpy(&pRpcInterfaceInfo->If,&RpcInterface.RpcServerInterface.InterfaceId,sizeof(pRpcInterfaceInfo->If)); + memcpy(&pRpcInterfaceInfo->TransfertSyntax,&RpcInterface.RpcServerInterface.TransferSyntax,sizeof(pRpcInterfaceInfo->TransfertSyntax)); + // + GetInterfaceName(&RpcInterface.RpcServerInterface.InterfaceId,pRpcInterfaceInfo->Name,sizeof(pRpcInterfaceInfo->Name)); + + //!!!!!!to change!!!!!! + if (InterfaceInfoMask == 0) goto End; + + switch(pRpcInterfaceInfo->IfType) + { + case IfType_DCOM: + case IfType_OLE: + goto End; //NO DCOM now!! + break; + // + case IfType_RPC: + { + if (GetLocationInfo(hProcess, (void*)RpcInterface.RpcServerInterface.DispatchTable, &LocationInfo)) + { + memcpy(pRpcInterfaceInfo->Location, LocationInfo.Location, sizeof(pRpcInterfaceInfo->Location)); + } + pRpcInterfaceInfo->pLocationBase = LocationInfo.pBaseAddress; + pRpcInterfaceInfo->LocationState = LocationInfo.State; + pRpcInterfaceInfo->LocationType = LocationInfo.Type; + pRpcInterfaceInfo->LocationSize = LocationInfo.Size; + } + break; + // + default: + break; + } + // + // If we have a module path then we can get its real base and size + // + if (LocationInfo.Location[0] != 0) + { + pModuleName = wcsrchr(pRpcInterfaceInfo->Location, '\\'); + if (pModuleName == NULL) pModuleName = pRpcInterfaceInfo->Location; + else pModuleName++; + // + // Get module base and size + // + hModulesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, Pid); + if (hModulesSnapshot != INVALID_HANDLE_VALUE) + { + ModuleEntry.dwSize = sizeof(ModuleEntry); + if (Module32FirstW(hModulesSnapshot, &ModuleEntry)) + do + { + if (_wcsicmp(pModuleName, ModuleEntry.szModule) == 0) + { + pRpcInterfaceInfo->pLocationBase = ModuleEntry.modBaseAddr; + pRpcInterfaceInfo->LocationSize = ModuleEntry.modBaseSize; + break; + } + } while (Module32NextW(hModulesSnapshot, &ModuleEntry)); + CloseHandle(hModulesSnapshot); + } + else + { + ULONG_PTR Base = 0; + WORD Magic = 0; + IMAGE_DOS_HEADER ImageDosHeader; + IMAGE_NT_HEADERS ImageNtHeaders; + // + // Last chance approach + // + Base = ((ULONG_PTR)pRpcInterfaceInfo->pLocationBase) & (~0xFFFF); + while (Magic != IMAGE_DOS_SIGNATURE) + { + ReadProcessMemory(hProcess, (PVOID)Base, &Magic, sizeof(Magic), NULL); + Base -= 0x1000; + } + pRpcInterfaceInfo->pLocationBase = (PVOID)(Base + 0x1000); + ReadProcessMemory(hProcess, pRpcInterfaceInfo->pLocationBase, &ImageDosHeader, sizeof(ImageDosHeader), NULL); + ReadProcessMemory(hProcess, (PVOID)((ULONG_PTR)pRpcInterfaceInfo->pLocationBase + ImageDosHeader.e_lfanew), &ImageNtHeaders, sizeof(ImageNtHeaders), NULL); + } + } + // + // Get module display name + // + GetModuleDescription(pRpcInterfaceInfo->Location,pRpcInterfaceInfo->Description,sizeof(pRpcInterfaceInfo->Description)); + // + // Get the interface procedures count ony for RPC interfaces + // + if (pRpcInterfaceInfo->IfType == IfType_RPC) + { + if (ReadProcessMemory(hProcess,RpcInterface.RpcServerInterface.DispatchTable,&RpcDispatchTbl,sizeof(RpcDispatchTbl),NULL)) + { + pRpcInterfaceInfo->NumberOfProcedures=RpcDispatchTbl.DispatchTableCount; + } + else + { + ZeroMemory(pRpcInterfaceInfo, sizeof(*pRpcInterfaceInfo)); + goto End; + } + } + // + // Interpreted stub + // + if (RpcInterface.RpcServerInterface.InterpreterInfo!=NULL) + { + if (pRpcInterfaceInfo->IfType==IfType_RPC) + { + pRpcInterfaceInfo->TypeOfStub=TypeOfStub_Interpreted; + } + // + // Get NDR info + // + ZeroMemory(&MidlServerInfo,sizeof(MidlServerInfo)); + ZeroMemory(&MidlStubDesc,sizeof(MidlStubDesc)); + if (!ReadProcessMemory(hProcess, RpcInterface.RpcServerInterface.InterpreterInfo, &MidlServerInfo, sizeof(MidlServerInfo), NULL)) + { + goto End; + } + if (!ReadProcessMemory(hProcess, MidlServerInfo.pStubDesc, &MidlStubDesc, sizeof(MidlStubDesc), NULL)) + { + goto End; + } + // + pRpcInterfaceInfo->NdrInfo.Version = MidlStubDesc.Version; + pRpcInterfaceInfo->NdrInfo.MIDLVersion = MidlStubDesc.MIDLVersion; + pRpcInterfaceInfo->NdrInfo.mFlags = MidlStubDesc.mFlags; + pRpcInterfaceInfo->pTypeFormatString = (UCHAR*)MidlStubDesc.pFormatTypes; + pRpcInterfaceInfo->apfnExprEval = (void*)MidlStubDesc.apfnExprEval; + + if (MidlStubDesc.pExprInfo != NULL) + { + if (ReadProcessMemory(hProcess, MidlStubDesc.pExprInfo, &NdrExprDesc, sizeof(NdrExprDesc), NULL)) + { + pRpcInterfaceInfo->pExprOffset = (USHORT*)NdrExprDesc.pOffset; + pRpcInterfaceInfo->pExprFormatString = (UCHAR*)NdrExprDesc.pFormatExpr; + } + else + { + //printf("Unable to read the pExprInfo at address %p in process %u\n", MidlStubDesc.pExprInfo, pRpcInterfaceInfo->Pid); + } + } + + pRpcInterfaceInfo->pProcFormatString = (UCHAR*)MidlServerInfo.ProcString; + // + // Get the interface procedure addresses table + // + pRpcInterfaceInfo->ppProcAddressTable=(ULONG*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(VOID*)); + if (pRpcInterfaceInfo->ppProcAddressTable == NULL) { DEBUG_BREAK(); goto End; } + + for(i=0;iNumberOfProcedures;i++) + { + if (ReadProcessMemory(hProcess,((VOID PTR_T PTR_T)MidlServerInfo.DispatchTable)+i,&pProc,sizeof(VOID PTR_T),NULL)) + { + pRpcInterfaceInfo->ppProcAddressTable[i]= (ULONG) ((ULONG64)pProc - (ULONG64)pRpcInterfaceInfo->pLocationBase); + } + } + // + // Get the interface format string offset table + // + pRpcInterfaceInfo->pFormatStringOffsetTable=(USHORT*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(USHORT)); + if (pRpcInterfaceInfo->pFormatStringOffsetTable!=NULL) + { + ReadProcessMemory(hProcess,MidlServerInfo.FmtStringOffset,pRpcInterfaceInfo->pFormatStringOffsetTable,pRpcInterfaceInfo->NumberOfProcedures*sizeof(USHORT),NULL); + } + } + else + { + //!!!todo!!! + //GetInlineStubInfo(pRpcCoreInternalCtxt,hProcess,pRpcInterface,pRpcInterfaceInfo); + } + // + // Test if DCOM or simple RPC + // + if (pRpcInterfaceInfo->IfType==IfType_RPC) + { + pRpcInterfaceInfo->IfCallbackFn = RpcInterface.IfCallbackFn; + } + + if (RpcInterface.EpMapperFlags & RPC_IS_EPMAPPER_REGISTERED) + { + pRpcInterfaceInfo->bIsRegistered=TRUE; + StringCbPrintfA((STRSAFE_LPSTR)pRpcInterfaceInfo->Annotation,sizeof(pRpcInterfaceInfo->Annotation),"%s",(const char*)RpcInterface.Annotation); + } + else + { + pRpcInterfaceInfo->bIsRegistered=FALSE; + } +End: + return (pRpcInterfaceInfo); +} + + +//------------------------------------------------------------------------------ +RpcInterfaceInfo_T* __fastcall RpcCoreGetInterfaceInfo(void* pRpcCoreCtxt,DWORD Pid,RPC_IF_ID* pIf,ULONG InterfaceInfoMask) +{ + RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt; + VOID* pRpcInterface; + HANDLE hProcess = NULL; + RpcInterfaceInfo_T* pRpcInterfaceInfo = NULL; + + pRpcCoreInternalCtxt = (RpcCoreInternalCtxt_T*)pRpcCoreCtxt; + hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, Pid); + if (hProcess == NULL) { DEBUG_BREAK(); goto End; } + + pRpcInterface = GetProcessInterface(pRpcCoreInternalCtxt, hProcess, pIf); + if (pRpcInterface == NULL) { goto End; } + + pRpcInterfaceInfo = InternalGetInterfaceInfo(pRpcCoreInternalCtxt, hProcess, pRpcInterface, Pid, InterfaceInfoMask); +End: + if (hProcess != NULL) CloseHandle(hProcess); + return (pRpcInterfaceInfo); +} + + +//------------------------------------------------------------------------------ +VOID __fastcall RpcCoreFreeInterfaceInfo(void* pRpcCoreCtxt,RpcInterfaceInfo_T* pRpcInterfaceInfo) +{ + UNREFERENCED_PARAMETER(pRpcCoreCtxt); + + if (pRpcInterfaceInfo==NULL) goto End; + if (pRpcInterfaceInfo->ppProcAddressTable!=NULL) OS_FREE(pRpcInterfaceInfo->ppProcAddressTable); + if (pRpcInterfaceInfo->pFormatStringOffsetTable!=NULL) OS_FREE(pRpcInterfaceInfo->pFormatStringOffsetTable); + + OS_FREE(pRpcInterfaceInfo); +End: + return; +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcCoreEnumProcessInterfaces(void* pRpcCoreCtxt,DWORD Pid,RpcCoreEnumProcessInterfacesCallbackFn_T RpcCoreEnumProcessInterfacesCallbackFn,void* pCallbackCtxt,ULONG InterfaceInfoMask) +{ + HANDLE hProcess; + BOOL bResult=FALSE; + RPC_SERVER_T RpcServer; + UINT i; + UINT Size; + VOID PTR_T * pTable=NULL; + VOID PTR_T pRpcServer; + BOOL bContinue=TRUE; + RpcInterfaceInfo_T* pRpcInterfaceInfo = NULL; + RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt=(RpcCoreInternalCtxt_T*)pRpcCoreCtxt; + + hProcess=OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,Pid); + if (hProcess==NULL) goto End; + + if (!ReadProcessMemory(hProcess,pRpcCoreInternalCtxt->pGlobalRpcServer,&pRpcServer,sizeof(VOID PTR_T),NULL)) goto End; + if (!ReadProcessMemory(hProcess,pRpcServer,&RpcServer,sizeof(RpcServer),NULL)) goto End; + + if (RpcServer.InterfaceDict.NumberOfEntries > MAX_SIMPLE_DICT_ENTRIES) + { + goto End; + } + + Size=RpcServer.InterfaceDict.NumberOfEntries*sizeof(VOID PTR_T); + pTable=(VOID PTR_T *)OS_ALLOC(Size); + if (pTable==NULL) goto End; + + if (!ReadProcessMemory(hProcess,RpcServer.InterfaceDict.pArray,pTable,Size,NULL)) goto End; + for (i=0; ipGlobalRpcServer,&pRpcServer,sizeof(VOID PTR_T),NULL)) goto End; + if (!ReadProcessMemory(hProcess,pRpcServer,&RpcServer,sizeof(RpcServer),NULL)) goto End; + + if (RpcServer.AddressDict.NumberOfEntries > MAX_SIMPLE_DICT_ENTRIES) + { + goto End; + } + + Size=RpcServer.AddressDict.NumberOfEntries*sizeof(VOID PTR_T); + pTable=(VOID PTR_T *)OS_ALLOC(Size); + if (pTable==NULL) goto End; + + if (!ReadProcessMemory(hProcess,RpcServer.AddressDict.pArray,pTable,Size,NULL)) goto End; + for (i=0; ipGlobalRpcServer,&pRpcServer,sizeof(VOID PTR_T),NULL)) goto End; + if (!ReadProcessMemory(hProcess,pRpcServer,&RpcServer,sizeof(RpcServer),NULL)) goto End; + + if (RpcServer.InterfaceDict.NumberOfEntries > MAX_SIMPLE_DICT_ENTRIES) goto End; + + Size=RpcServer.InterfaceDict.NumberOfEntries*sizeof(VOID PTR_T); + pTable=(VOID PTR_T *)OS_ALLOC(Size); + if (pTable==NULL) goto End; + + if (!ReadProcessMemory(hProcess,RpcServer.InterfaceDict.pArray,pTable,Size,NULL)) goto End; + for (i=0; i OK + if (memcmp(&RpcInterface.RpcServerInterface.InterfaceId,pIf,sizeof(pRpcServerInterface->InterfaceId)) == 0) + { + pRpcInterface=pTable[i]; + break; + } + } +End: + if (pTable!=NULL) OS_FREE(pTable); + return(pRpcInterface); +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcCoreEnumProcessAuthInfo(void* pRpcCoreCtxt,DWORD Pid,RpcCoreEnumProcessAuthInfoCallbackFn_T RpcCoreEnumProcessAuthInfoCallbackFn,void* pCallbackCtxt) +{ + RPC_SERVER_T RpcServer; + UINT i; + UINT j; + DWORD Size; + RPC_AUTH_INFO_T RpcAuth; + RpcAuthInfo_T RpcAuthInfo; + ULONG PackagesCount; + VOID PTR_T pRpcServer = NULL; + HANDLE hProcess = NULL; + VOID PTR_T * pTable = NULL; + PSecPkgInfoW SecurityPackageInfoTbl = NULL; + HKEY hKey = NULL; + BOOL bContinue = TRUE; + BOOL bResult = FALSE; + WCHAR ValueName[RPC_MAX_DLL_NAME_SIZE]; + RpcCoreInternalCtxt_T* pRpcCoreInternalCtxt=(RpcCoreInternalCtxt_T*)pRpcCoreCtxt; + + ZeroMemory(&RpcAuthInfo,sizeof(RpcAuthInfo_T)); + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Rpc\\SecurityService",0,KEY_READ,&hKey)!=ERROR_SUCCESS) goto End; + if (EnumerateSecurityPackagesW(&PackagesCount,&SecurityPackageInfoTbl)!=SEC_E_OK) goto End; + + hProcess=OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,Pid); + if (hProcess==NULL) goto End; + + if (!ReadProcessMemory(hProcess,pRpcCoreInternalCtxt->pGlobalRpcServer,&pRpcServer,sizeof(VOID PTR_T), NULL)) goto End; + if (!ReadProcessMemory(hProcess,pRpcServer,&RpcServer,sizeof(RpcServer),NULL)) goto End; + + if (RpcServer.AuthenInfoDict.NumberOfEntries > MAX_SIMPLE_DICT_ENTRIES) goto End; + + Size=RpcServer.AuthenInfoDict.NumberOfEntries*sizeof(VOID PTR_T); + pTable=(VOID PTR_T *)OS_ALLOC(Size); + if (pTable==NULL) goto End; + + if (!ReadProcessMemory(hProcess,RpcServer.AuthenInfoDict.pArray,pTable,Size,NULL)) goto End; + for (i=0; i + +#define RPC_CORE_EXPORT_SYMBOL "RpcCoreHelper" +#define MAX_RPC_INTERFACE_ANNOTATION 64 +#define MAX_GUID 40 +#define MAX_CLSID_NAME 128 + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Type definitions +//////////////////////////////////////////////////////////////////////////////// + +#define RPC_PROCESS_INFO_DEFAULT 0x0 +#define RPC_PROCESS_INFO_MISC 0x1 +#define RPC_PROCESS_INFO_RPC 0x2 +#define RPC_PROCESS_INFO_ALL (RPC_PROCESS_INFO_MISC | RPC_PROCESS_INFO_RPC) + +typedef enum _RpcProcessType_T{ + RpcProcessType_UNKNOWN = 0, + RpcProcessType_RPC, + RpcProcessType_DCOM, + RpcProcessType_HYBRID +}RpcProcessType_T; + +typedef struct _RpcProcessInfo_T{ + //Default + DWORD Pid; + DWORD ParentPid; +#ifdef _WIN64 + BOOL bIsWow64; +#endif + //Misc + WCHAR Name[MAX_PATH]; + WCHAR Path[MAX_PATH]; + WCHAR CmdLine[MAX_PATH]; + WCHAR User[MAX_PATH]; + WCHAR Desktop[MAX_PATH]; + DWORD Session; + UINT64 Version; + HICON hIcon; + WCHAR Description[MAX_PATH]; + FILETIME CreationTime; + //Rpc + RpcProcessType_T RpcProcessType; + DWORD MaxCalls; + BOOL bIsServer; + BOOL bIsListening; + UINT InterfacesCount; + UINT EndpointsCount; + UINT SspCount; + DWORD InCalls; + DWORD OutCalls; + DWORD InPackets; + DWORD OutPackets; + //... +}RpcProcessInfo_T; + + +typedef struct _NdrInfo_T{ + ULONG Version; // NDR version required for the stub. + ULONG MIDLVersion; // Version of the MIDL compiler used to compile the .idl file + ULONG_PTR mFlags; // Flag describing the attributes of the stub (RPCFLG_HAS_MULTI_SYNTAXES, RPCFLG_HAS_CALLBACK, or RPC_INTERFACE_HAS_PIPES) +}NdrInfo_T; + + +typedef enum _TypeOfStub_T{ + TypeOfStub_Unknown = 0, + TypeOfStub_Interpreted, + TypeOfStub_Inlined, + TypeOfStub_TypeLib, + TypeOfStub_Hybrid +}TypeOfStub_T; + +typedef enum _IfType_T{ + IfType_Unknown = 0, + IfType_RPC, + IfType_DCOM, + IfType_OLE, +}IfType_T; + +#define RPC_INTERFACE_INFO_DEFAULT 0x0 +#define RPC_INTERFACE_INFO_MISC 0x1 +#define RPC_INTERFACE_INFO_RPC 0x2 +#define RPC_INTERFACE_INFO_NDR 0x4 +#define RPC_INTERFACE_INFO_DCOM 0x8 +#define RPC_INTERFACE_INFO_ALL (RPC_INTERFACE_INFO_MISC | RPC_INTERFACE_INFO_RPC | RPC_INTERFACE_INFO_NDR |RPC_INTERFACE_INFO_DCOM) + + +typedef struct _RpcInterfaceInfo_T{ + //Default + DWORD Pid; +#ifdef _WIN64 + BOOL bWow64Process; +#endif + RPC_IF_ID If; + RPC_SYNTAX_IDENTIFIER TransfertSyntax; + UINT Flags; + IfType_T IfType; + //Misc + WCHAR Name[MAX_PATH]; + WCHAR Location[MAX_PATH]; + DWORD LocationState; + DWORD LocationType; + VOID* pLocationBase; + SIZE_T LocationSize; + WCHAR Description[MAX_PATH]; + //RPC + BOOL bIsRegistered; //EP mapper + UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; //annotation is natively in UCHAR + RPC_IF_CALLBACK_FN* IfCallbackFn; //security callback if any + //NDR + UINT NumberOfProcedures; + NdrInfo_T NdrInfo; + TypeOfStub_T TypeOfStub; + ULONG* ppProcAddressTable; //Table containing the address of each function + USHORT* pFormatStringOffsetTable; //Table containing the offset of each function encoding + UCHAR* pProcFormatString; // Midl server info + UCHAR* pTypeFormatString; // Midl stub desc + VOID* apfnExprEval; // Midl stub desc + USHORT* pExprOffset; // Midl stub desc + UCHAR* pExprFormatString; // Midl stub desc + //DCOM information + WCHAR ProxyStubClsid32[MAX_GUID]; + WCHAR TypeLib[MAX_GUID]; + WCHAR TypeLibName[MAX_PATH]; + WCHAR ClsidName[MAX_CLSID_NAME]; + WCHAR InprocServer32[MAX_PATH]; + WCHAR TypeLibVersion[20]; + WCHAR TypeLibPath[MAX_PATH]; + //... +}RpcInterfaceInfo_T; + + +typedef struct _RpcEndpointInfo_T{ + WCHAR* pName; + WCHAR* pProtocole; + //... +}RpcEndpointInfo_T; + + +//Private name: unnamed in PDB file +typedef struct _RPC_AUTH_INFO_T{ + WCHAR* pPrincipalName; + ULONG AuthSvc; + VOID* pGetKeyFn; + VOID* pArg; +}RPC_AUTH_INFO_T; + + +typedef struct _RpcAuthInfo_T{ + ULONG Capabilities; + ULONG Version; + WCHAR PrincipalName[MAX_PATH]; + ULONG AuthSvc; + WCHAR Name[MAX_PATH]; + WCHAR Comment[MAX_PATH]; + WCHAR DllName[MAX_PATH]; + VOID* pGetKeyFn; + VOID* pArg; +}RpcAuthInfo_T; + + +//////////////////////////////////////////////////////////////////////////////// +// Callback function type definition +//////////////////////////////////////////////////////////////////////////////// +typedef BOOL (__fastcall* RpcCoreEnumProcessInterfacesCallbackFn_T)(RpcInterfaceInfo_T* pRpcInterfaceInfo, VOID* pContext, BOOL* pbContinue); +typedef BOOL (__fastcall* RpcCoreEnumProcessEndpointsCallbackFn_T)(DWORD Pid, RpcEndpointInfo_T* pRpcEndpointInfo, VOID* pContext, BOOL* pbContinue); +typedef BOOL (__fastcall* RpcCoreEnumProcessAuthInfoCallbackFn_T)(DWORD Pid, RpcAuthInfo_T* pRpcAuthInfo, VOID* pContext, BOOL* pbContinue); + + +//////////////////////////////////////////////////////////////////////////////// +// Type definitions +//////////////////////////////////////////////////////////////////////////////// + +typedef VOID* (__fastcall* RpcCoreInitFn_T)(); +typedef VOID (__fastcall* RpcCoreUninitFn_T)(VOID* pRpcCoreCtxt); +typedef RpcProcessInfo_T* (__fastcall* RpcCoreGetProcessInfoFn_T)(void* pRpcCoreCtxt, DWORD Pid, DWORD Ppid,ULONG ProcessInfoMask); +typedef VOID (__fastcall* RpcCoreFreeProcessInfoFn_T)(void* pRpcCoreCtxt, RpcProcessInfo_T* pRpcProcessInfo); +typedef RpcInterfaceInfo_T* (__fastcall* RpcCoreGetInterfaceInfoFn_T)(void* pRpcCoreCtxt, DWORD Pid, RPC_IF_ID* pIf,ULONG InterfaceInfoMask); +typedef VOID (__fastcall* RpcCoreFreeInterfaceInfoFn_T)(void* pRpcCoreCtxt, RpcInterfaceInfo_T* pRpcInterfaceInfo); +typedef BOOL (__fastcall* RpcCoreEnumProcessInterfacesFn_T)(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessInterfacesCallbackFn_T RpcCoreEnumProcessInterfacesCallbackFn, void* pCallbackCtxt,ULONG InterfaceInfoMask); +typedef BOOL (__fastcall* RpcCoreEnumProcessEndpointsFn_T)(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessEndpointsCallbackFn_T RpcCoreEnumProcessEndpointsCallbackFn, void* pCallbackCtxt); +typedef BOOL (__fastcall* RpcCoreEnumProcessAuthInfoFn_T)(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessAuthInfoCallbackFn_T RpcCoreEnumProcessAuthInfoCallbackFn, void* pCallbackCtxt); + + +typedef struct _RpcCore_T{ + UINT64* RuntimeVersion; //the supported version (forx example 0x600011DB04001LL (6.1.7600.16385) for Windows 7 64bits ) + //const char* pDescription; + BOOL bWow64Helper; + RpcCoreInitFn_T RpcCoreInitFn; + RpcCoreUninitFn_T RpcCoreUninitFn; + RpcCoreGetProcessInfoFn_T RpcCoreGetProcessInfoFn; + RpcCoreFreeProcessInfoFn_T RpcCoreFreeProcessInfoFn; + RpcCoreGetInterfaceInfoFn_T RpcCoreGetInterfaceInfoFn; + RpcCoreFreeInterfaceInfoFn_T RpcCoreFreeInterfaceInfoFn; + RpcCoreEnumProcessInterfacesFn_T RpcCoreEnumProcessInterfacesFn; + RpcCoreEnumProcessEndpointsFn_T RpcCoreEnumProcessEndpointsFn; + RpcCoreEnumProcessAuthInfoFn_T RpcCoreEnumProcessAuthInfoFn; +}RpcCore_T; + +#ifdef __cplusplus +} +#endif + +#endif //_RPC_CORE_H_ \ No newline at end of file diff --git a/RpcCore/RpcCore1_32bits/RpcInternals.h b/RpcCore/RpcCore1_32bits/RpcInternals.h new file mode 100644 index 0000000..ccf53af --- /dev/null +++ b/RpcCore/RpcCore1_32bits/RpcInternals.h @@ -0,0 +1,99 @@ +#ifndef _RPC_INTERNALS_H_ +#define _RPC_INTERNALS_H_ + +#include +#include + +static UINT64 RPC_CORE_RUNTIME_VERSION[] = { + 0x500010a280884LL, //5.1.2600.2180 + 0x500010a281588LL, //5.1.2600.5512 + 0x500010a281786LL, //5.1.2600.6022 + 0x500010a28194dLL, //5.1.2600.6477 + 0x500020ECE0F77LL //5.2.3790.3959 +}; + +#ifdef _WIN64 + #define RPC_CORE_IS_WOW64 TRUE + #define PTR_T *__ptr32 //WOW64!!! + #define ULONG_PTR_T ULONG +#else + #define RPC_CORE_IS_WOW64 FALSE + #define ULONG_PTR_T ULONG_PTR + #define PTR_T * +#endif + +#include "../RpcInternalsCommon.h" + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +#pragma pack(1) +typedef struct _RPC_SERVER_T{ + MUTEX_T MUTEX; + ULONG Unk1; + ULONG Unk2; + BOOL bIsListening; + ULONG MinimumCallThreads; + ULONG bWait; + ULONG OutCalls; + ULONG Unk3; + ULONG InCalls; + SIMPLE_DICT_T AddressDict; + ULONG Unk3_; + SIMPLE_DICT_T _ProtSeqQueue; + ULONG Unk4[4]; + ULONG OutPackets; + ULONG Unk5; + MUTEX_T Mutex2; + ULONG MaxCalls; + VOID PTR_T hEvent; + ULONG Unk6[6]; + SIMPLE_DICT_T InterfaceDict; + BOOL ___bIsListening; + BOOL bIsListenMaxCallsDefault; + ULONG Unk7[6]; + ULONG InPackets; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk8[6]; + SIMPLE_DICT_T AuthenInfoDict; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + +typedef struct _RPC_INTERFACE_T +{ + RPC_SERVER_T PTR_T pRpcServer; + ULONG Flags; + ULONG EpMapperFlags; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + RPC_SERVER_INTERFACE_T RpcServerInterface; + ULONG pSyntaxInfo; + ULONG pTransfertSyntaxes; + ULONG pTransfertSyntaxesCount; + ULONG Unk1; + ULONG NbTypeManager; + ULONG MaxRpcSize; + ULONG Unk2; + ULONG pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; + SIMPLE_DICT_T FwEpDict; + ULONG Unk3[6]; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; + +typedef struct _RPC_ADDRESS_T{ + VOID PTR_T PTR_T pVTable; + ULONG Magic; + ULONG TypeOfAddress; + ULONG ReferenceCounter; + WCHAR PTR_T Name; + WCHAR PTR_T Protocole; + WCHAR PTR_T Address; + ULONG bNamed; + ULONG EpAddAddressFlag; + ULONG unk4[6]; + MUTEX_T Mutex; +}RPC_ADDRESS_T; + +#pragma pack() +#endif // _RPC_INTERNALS_H_ \ No newline at end of file diff --git a/RpcCore/RpcCore2_32bits/RpcInternals.h b/RpcCore/RpcCore2_32bits/RpcInternals.h new file mode 100644 index 0000000..495277d --- /dev/null +++ b/RpcCore/RpcCore2_32bits/RpcInternals.h @@ -0,0 +1,115 @@ +#ifndef _RPC_INTERNALS_H_ +#define _RPC_INTERNALS_H_ + +#include +#include + + +static UINT64 RPC_CORE_RUNTIME_VERSION[] = { + 0x600011DB04001LL, //6.1.7600.16385 + 0x600011DB1446ALL, //6.1.7601.17514 + 0x600011DB1471DLL, //6.1.7601.18205 + 0x600011DB14864LL, //6.1.7601.18532 + 0x600011DB149E0LL, //6.1.7601.18912 + 0x600011DB149F5LL, //6.1.7601.18933 + 0x600011DB149FBLL, //6.1.7601.18939 + 0x600011DB15B7BLL //6.1.7601.23419 +}; + +#ifdef _WIN64 +#define RPC_CORE_DESCRIPTION "Windows 7 SP1 64bits Wow64 runtime core" +#define RPC_CORE_IS_WOW64 TRUE +#define PTR_T *__ptr32 //WOW64!!! +#define ULONG_PTR_T ULONG +#else +#define RPC_CORE_DESCRIPTION "Windows 7 SP1 32bits runtime core" +#define RPC_CORE_IS_WOW64 FALSE +#define ULONG_PTR_T ULONG_PTR +#define PTR_T * +#endif + + +#include "../RpcInternalsCommon.h" + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +#pragma pack(1) +typedef struct _RPC_SERVER_T { + MUTEX_T Mutex; + ULONG _bIslistening; + ULONG bIsListening; + ULONG MinimumCallThreads; + ULONG bWait; + ULONG OutCalls; + ULONG Unk1; + ULONG InCalls; + SIMPLE_DICT_T AddressDict; + ULONG lAvailableCalls; + SIMPLE_DICT_T _ProtSeqQueue; + ULONG Unk2[4]; + ULONG OutPackets; + MUTEX_T Mutex2; + ULONG MaxCalls; + VOID PTR_T hEvent; + ULONG Unk3[4]; + SIMPLE_DICT_T InterfaceDict; + ULONG __bIslistening; + ULONG bIsMaxCalls1234; + ULONG Unk4[6]; + ULONG InPackets; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk5[6]; + SIMPLE_DICT_T AuthenInfoDict; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + +typedef struct _RPC_INTERFACE_T +{ + PRPC_SERVER_T pRpcServer; + ULONG Flags; + ULONG EpMapperFlags; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfSecurityCallbackFn; + RPC_SERVER_INTERFACE_T RpcServerInterface; + ULONG unk2[2]; + BOOL bInterfaceSupportMultipleTransferSyntaxes; + ULONG unk3; + ULONG NbTypeManager; + ULONG MaxRpcSize; + UUID_VECTOR PTR_T pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + ULONG CurrentNullManagerCalls; + ULONG CurrentAutoListenCalls; + ULONG __Field_DC; + ULONG unk5; + ULONG SecurityCallbackInProgress; + ULONG __Field_E8; + VOID PTR_T pSecurityEntryHashTable; + SIMPLE_DICT_T FwEpDict; + ULONG field_10C; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; + +typedef struct _RPC_ADDRESS_T { + VOID PTR_T PTR_T pVTable; + ULONG Magic; + ULONG TypeOfAddress; + ULONG ReferenceCounter; + ULONG unk1; + WCHAR PTR_T Name; + WCHAR PTR_T Protocole; + WCHAR PTR_T Address; + ULONG bNamed; + ULONG EpAddAddressFlag; + SIMPLE_DICT_T __LRPCSassociationDict; + ULONG unk3[2]; + ULONG NbActiveCalls; + ULONG unk4[4]; + MUTEX_T Mutex; +}RPC_ADDRESS_T; + +#pragma pack() + +#endif // _RPC_INTERNALS_H_ \ No newline at end of file diff --git a/RpcCore/RpcCore2_64bits/RpcInternals.h b/RpcCore/RpcCore2_64bits/RpcInternals.h new file mode 100644 index 0000000..bb818c4 --- /dev/null +++ b/RpcCore/RpcCore2_64bits/RpcInternals.h @@ -0,0 +1,119 @@ +#ifndef _RPC_INTERNALS_H_ +#define _RPC_INTERNALS_H_ + +#include +#include + +static UINT64 RPC_CORE_RUNTIME_VERSION[] = { + 0x600011DB04001LL, //6.1.7600.16385 + 0x600011DB1446ALL, //6.1.7601.17514 + 0x600011DB1471DLL, //6.1.7601.18205 + 0x600011DB14864LL, //6.1.7601.18532 + 0x600011DB149E0LL, //6.1.7601.18912 + 0x600011DB149F5LL, //6.1.7601.18933 + 0x600011DB149FBLL, //6.1.7601.18939 + 0x600011DB15B7BLL //6.1.7601.23419 +}; + +#define RPC_CORE_DESCRIPTION "Windows 7 SP1 64bits runtime core" +#define RPC_CORE_IS_WOW64 FALSE + +#define ULONG_PTR_T ULONG_PTR +#define PTR_T * + +#include "../RpcInternalsCommon.h" + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +#pragma pack(1) + +typedef struct _RPC_SERVER_T { + MUTEX_T Mutex; + ULONG __bIslistening; + BOOL bIsListening; + ULONG MinimumCallThreads; + BOOL Wait; + ULONG OutCalls; + ULONG Unk1; + ULONG InCalls; + ULONG Unk2; + SIMPLE_DICT_T AddressDict; + ULONG lAvailableCalls; + ULONG Unk3; + SIMPLE_DICT_T _ProtSeqQueue; + ULONG Unk4[8]; + ULONG OutPackets; + ULONG Unk5; + MUTEX_T Mutex2; + ULONG MaxCalls; + ULONG Unk6; + VOID PTR_T hEvent; + ULONG Unk7[4]; + SIMPLE_DICT_T InterfaceDict; + BOOL _bIsListening; + BOOL bIsMaxCalls1234; + ULONG Unk8[6]; + ULONG InPackets; + ULONG Unk9; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk10[6]; + SIMPLE_DICT_T AuthenInfoDict; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + + +typedef struct _RPC_INTERFACE_T { + PRPC_SERVER_T pRpcServer; + ULONG Flags; + ULONG EpMapperFlags; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + RPC_SERVER_INTERFACE_T RpcServerInterface; + PMIDL_SYNTAX_INFO pSyntaxInfo; + VOID PTR_T pTransfertSyntaxes; + ULONG TransfertSyntaxesCount; + ULONG __Field_C4; + ULONG NbTypeManager; + ULONG MaxRpcSize; + UUID_VECTOR PTR_T pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; + ULONG IsCallSizeLimitReached; + ULONG currentNullManagerCalls; + ULONG __Field_150; + ULONG __Field_154; + ULONG bRundownsBlocked; + ULONG SecurityCallbackInProgress; + ULONG SecurityCacheEntry; + ULONG field_164; + VOID PTR_T __SecurityCacheEntries; + SIMPLE_DICT_T FwEpDict; + ULONG __Field_218; + ULONG Unk1; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; + + +typedef struct _RPC_ADDRESS_T { + VOID PTR_T pVtable; + ULONG Magic; + ULONG TypeOfAddress; + ULONG ReferenceCounter; + ULONG Unk1[3]; + WCHAR PTR_T Name; + WCHAR PTR_T Protocole; + WCHAR PTR_T Address; + ULONG bNamed; + ULONG EpAddAddressFlag; + SIMPLE_DICT_T __LRPCSassociationSimpleDict; + ULONG __Field_68; + ULONG Unk2; + ULONG EpAddOnFlag; + ULONG NbActiveCalls; + ULONG Unk3[6]; + MUTEX_T Mutex; +}RPC_ADDRESS_T; + +#pragma pack() + +#endif // _RPC_INTERNALS_H_ \ No newline at end of file diff --git a/RpcCore/RpcCore3_32bits/RpcInternals.h b/RpcCore/RpcCore3_32bits/RpcInternals.h new file mode 100644 index 0000000..196ad1a --- /dev/null +++ b/RpcCore/RpcCore3_32bits/RpcInternals.h @@ -0,0 +1,116 @@ +#ifndef _RPC_INTERNALS_H_ +#define _RPC_INTERNALS_H_ + +#include +#include + + +static UINT64 RPC_CORE_RUNTIME_VERSION[] = { + 0x6000223f04000LL, //6.2.9200.16384 + 0x6000223f040eeLL //6.2.9200.16622 +}; + +#ifdef _WIN64 +#define RPC_CORE_DESCRIPTION "Windows 8 64bits Wow64 runtime core" +#define RPC_CORE_IS_WOW64 TRUE +#define PTR_T *__ptr32 //WOW64!!! +#define ULONG_PTR_T ULONG +#else +#define RPC_CORE_DESCRIPTION "Windows 8 32bits runtime core" +#define RPC_CORE_IS_WOW64 FALSE +#define ULONG_PTR_T ULONG_PTR +#define PTR_T * +#endif + +#include "../RpcInternalsCommon.h" + + +#pragma pack(1) +typedef struct _RPC_SERVER_T { + MUTEX_T MUTEX; + BOOL _bIslistening; + BOOL bIsListening; + ULONG MinimumCallThreads; + BOOL bWait; + ULONG OutCalls; + ULONG Unk1; + ULONG InCalls; + SIMPLE_DICT_T AddressDict; + ULONG lAvailableCalls; + ULONG Unk2[11]; + ULONG OutPackets; + MUTEX_T Mutex2; + ULONG MaxCalls; + VOID PTR_T hEvent; + ULONG Unk4[4]; + SIMPLE_DICT_T InterfaceDict; + BOOL __bIslistening; + BOOL bIsMaxCall1234; + ULONG Unk5[6]; + ULONG InPackets; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk6[6]; + SIMPLE_DICT_T AuthenInfoDict; + LIST_ENTRY_T RpcIfGroupListEntry; + ULONG PTR_T __SRWLock; + LIST_ENTRY_T __138; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + +typedef struct _RPC_INTERFACE_T +{ + PRPC_SERVER_T pRpcServer; + ULONG Flags; + MUTEX_T Mutex; + ULONG EpMapperFlags; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfSecurityCallback; + RPC_SERVER_INTERFACE_T RpcServerInterface; + MIDL_SYNTAX_INFO PTR_T pSyntaxInfo; + VOID PTR_T pTransfertSyntaxes; + ULONG TransfertSyntaxesCount; + ULONG Unk1; + ULONG NbTypeManager; + ULONG MaxRpcSize; + UUID_VECTOR PTR_T pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[64]; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + ULONG IsCallSizeLimitReached; + ULONG currentNullManagerCalls; + ULONG currentAutoListenCalls; + ULONG Unk2[2]; + ULONG SecurityCallbackInProgress; + ULONG SecurityCacheEntry; + ULONG __SecurityCacheEntries[16]; + SIMPLE_DICT_T FwEpDict; + ULONG Unk3[4]; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +typedef struct _RPC_ADDRESS_T { + VOID PTR_T PTR_T pVTable; + ULONG Magic; + ULONG TypeOfAddress; + ULONG ReferenceCounter; + ULONG Unk1; + WCHAR PTR_T Name; + WCHAR PTR_T Protocole; + WCHAR PTR_T Address; + BOOL bNamed; + ULONG EpAddAddressFlag; + SIMPLE_DICT_T __LRPCSassociationSimpleDict; + ULONG __Field_68; + ULONG Unk3; + ULONG NbActiveCalls; + ULONG __Field_74; + ULONG Unk4[6]; + ULONG __Field_90; + MUTEX_T Mutex; +}RPC_ADDRESS_T; + +#pragma pack() + +#endif // _RPC_INTERNALS_H_ \ No newline at end of file diff --git a/RpcCore/RpcCore3_64bits/RpcInternals.h b/RpcCore/RpcCore3_64bits/RpcInternals.h new file mode 100644 index 0000000..461f181 --- /dev/null +++ b/RpcCore/RpcCore3_64bits/RpcInternals.h @@ -0,0 +1,117 @@ +#ifndef _RPC_INTERNALS_H_ +#define _RPC_INTERNALS_H_ + +#include +#include + +static UINT64 RPC_CORE_RUNTIME_VERSION[] = { + 0x6000223f04000LL, //6.2.9200.16384 + 0x6000223f040eeLL //6.2.9200.16622 +}; + +#define RPC_CORE_DESCRIPTION "Windows 8 64bits runtime core" +#define RPC_CORE_IS_WOW64 FALSE + +#define ULONG_PTR_T ULONG_PTR +#define PTR_T * + +#include "../RpcInternalsCommon.h" + +#pragma pack(1) +typedef struct _RPC_SERVER_T { + MUTEX_T Mutex; + ULONG __bIslistening; + ULONG bIsListening; + ULONG MinimumCallThreads; + ULONG Wait; + ULONG OutCalls; + ULONG Unk1; + ULONG InCalls; + ULONG Unk2; + SIMPLE_DICT_T AddressDict; + ULONG lAvailableCalls; + ULONG Unk3; + ULONG Unk4[20]; + ULONG OutPackets; + ULONG Unk5; + MUTEX_T Mutex2; + ULONG MaxCalls; + ULONG Unk6; + VOID PTR_T hEvent; + ULONG Unk7[4]; + SIMPLE_DICT_T InterfaceDict; + ULONG _bIsListening; + ULONG bIsMaxCalls1234; + ULONG Unk8[6]; + ULONG InPackets; + ULONG Unk9; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk10[6]; + SIMPLE_DICT_T AuthenInfoDict; + LIST_ENTRY_T RpcIfGroupListEntry; + ULONG PTR_T __SRWLock; + LIST_ENTRY_T field_1E0; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + +typedef struct _RPC_INTERFACE_T +{ + PRPC_SERVER_T pRpcServer; + ULONG Flags; + ULONG Unk1; + MUTEX_T Mutex; + ULONG EpMapperFlags; + ULONG Unk2; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + RPC_SERVER_INTERFACE_T RpcServerInterface; + PMIDL_SYNTAX_INFO pSyntaxInfo; + VOID PTR_T pTransfertSyntaxes; + ULONG TransfertSyntaxesCount; + ULONG __Field_C4; + ULONG NbTypeManager; + ULONG MaxRpcSize; + UUID_VECTOR PTR_T pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; + ULONG IsCallSizeLimitReached; + ULONG currentNullManagerCalls; + ULONG __Field_150; + ULONG __Field_154; + ULONG __Field_158; + ULONG SecurityCallbackInProgress; + ULONG SecurityCacheEntry; + ULONG field_164; + VOID PTR_T __SecurityCacheEntries[16]; + SIMPLE_DICT_T FwEpDict; + ULONG Unk3[6]; + struct RPCP_INTERFACE_GROUP PTR_T pRpcpInterfaceGroup; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +typedef struct _RPC_ADDRESS_T { + VOID PTR_T pVtable; + ULONG Magic; + ULONG TypeOfAddress; + ULONG ReferenceCounter; + ULONG Unk1[3]; + WCHAR PTR_T Name; + WCHAR PTR_T Protocole; + WCHAR PTR_T Address; + ULONG bNamed; + ULONG EpAddAddressFlag; + SIMPLE_DICT_T __LRPCSassociationSimpleDict; + ULONG __Field_68; + ULONG Unk3; + ULONG NbActiveCalls; + ULONG __Field_74; + ULONG Unk4[6]; + ULONG __Field_90; + MUTEX_T Mutex; +}RPC_ADDRESS_T; + +#pragma pack() + +#endif // _RPC_INTERNALS_H_ \ No newline at end of file diff --git a/RpcCore/RpcCore4_32bits/RpcInternals.h b/RpcCore/RpcCore4_32bits/RpcInternals.h new file mode 100644 index 0000000..8072475 --- /dev/null +++ b/RpcCore/RpcCore4_32bits/RpcInternals.h @@ -0,0 +1,129 @@ +#ifndef _RPC_INTERNALS_H_ +#define _RPC_INTERNALS_H_ + +#include +#include + + +static UINT64 RPC_CORE_RUNTIME_VERSION[] = { + 0x6000324D70000LL, //6.3.9431.0000 + 0x6000325804000LL, //6.3.9600.16384 + 0x6000325804340LL, //6.3.9600.17216 + 0x6000325804407LL, //6.3.9600.17415 + 0x60003258045FFLL, //6.3.9600.17919 + + 0xA000028004000LL, //10.0.10240.16384 + 0xA00002800401CLL, //10.0.10240.16412 + 0xA0000295A0000LL, //10.0.10586.0 + 0xA0000295A0132LL, //10.0.10586.306 + 0xA0000380603E8LL, //10.0.14342.1000 + 0xA000038190000LL, //10.0.14361.0 + 0xA000038390000LL, //10.0.14393.0 + 0xA000038390052LL //10.0.14393.82 +}; + +#ifdef _WIN64 + #define RPC_CORE_DESCRIPTION "Windows 10 64bits wow64 runtime core" + #define RPC_CORE_IS_WOW64 TRUE + #define PTR_T *__ptr32 //WOW64!!! + #define ULONG_PTR_T ULONG +#else + #define RPC_CORE_DESCRIPTION "Windows 10 32bits runtime core" + #define RPC_CORE_IS_WOW64 FALSE + #define ULONG_PTR_T ULONG_PTR + #define PTR_T * +#endif + +#include "../RpcInternalsCommon.h" + + +#pragma pack(1) +typedef struct _RPC_SERVER_T{ + MUTEX_T MUTEX; + BOOL _bIslistening; + BOOL bIsListening; + ULONG MinimumCallThreads; + BOOL bWait; + ULONG OutCalls; + ULONG Unk1; + ULONG InCalls; + SIMPLE_DICT_T AddressDict; + ULONG lAvailableCalls; + SIMPLE_DICT_T _ProtSeqQueue; + ULONG Unk2[4]; + ULONG OutPackets; + MUTEX_T Mutex2; + ULONG MaxCalls; + VOID PTR_T hEvent; + ULONG Unk4[4]; + SIMPLE_DICT_T InterfaceDict; + BOOL __bIslistening; + BOOL bIsMaxCall1234; + ULONG Unk5[6]; + ULONG InPackets; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk6[6]; + SIMPLE_DICT_T AuthenInfoDict; + LIST_ENTRY_T RpcIfGroupListEntry; + ULONG PTR_T __SRWLock; + LIST_ENTRY_T __138; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + +typedef struct _RPC_INTERFACE_T +{ + PRPC_SERVER_T pRpcServer; + ULONG Flags; + MUTEX_T Mutex; + ULONG EpMapperFlags; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfSecurityCallback; + RPC_SERVER_INTERFACE_T RpcServerInterface; + MIDL_SYNTAX_INFO PTR_T pSyntaxInfo; + VOID PTR_T pTransfertSyntaxes; + ULONG TransfertSyntaxesCount; + ULONG Unk1; + ULONG NbTypeManager; + ULONG MaxRpcSize; + UUID_VECTOR PTR_T pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[64]; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + ULONG IsCallSizeLimitReached; + ULONG currentNullManagerCalls; + ULONG currentAutoListenCalls; + ULONG Unk2[2]; + ULONG SecurityCallbackInProgress; + ULONG SecurityCacheEntry; + ULONG __SecurityCacheEntries[16]; + SIMPLE_DICT_T FwEpDict; + ULONG Unk3[4]; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +typedef struct _RPC_ADDRESS_T{ + VOID PTR_T PTR_T pVTable; + ULONG Magic; + ULONG TypeOfAddress; + ULONG ReferenceCounter; + ULONG Unk1; + WCHAR PTR_T Name; + WCHAR PTR_T Protocole; + WCHAR PTR_T Address; + BOOL bNamed; + ULONG EpAddAddressFlag; + SIMPLE_DICT_T __LRPCSassociationSimpleDict; + ULONG __Field_68; + ULONG Unk3; + ULONG NbActiveCalls; + ULONG __Field_74; + ULONG Unk4[6]; + ULONG __Field_90; + MUTEX_T Mutex; +}RPC_ADDRESS_T; + +#pragma pack() + +#endif // _RPC_INTERNALS_H_ \ No newline at end of file diff --git a/RpcCore/RpcCore4_64bits/RpcInternals.h b/RpcCore/RpcCore4_64bits/RpcInternals.h new file mode 100644 index 0000000..8ef6ae9 --- /dev/null +++ b/RpcCore/RpcCore4_64bits/RpcInternals.h @@ -0,0 +1,130 @@ +#ifndef _RPC_INTERNALS_H_ +#define _RPC_INTERNALS_H_ + +#include +#include + +static UINT64 RPC_CORE_RUNTIME_VERSION[] = { + 0x6000324D70000LL, //6.3.9431.0000 + 0x6000325804000LL, //6.3.9600.16384 + 0x6000325804340LL, //6.3.9600.17216 + 0x6000325804407LL, //6.3.9600.17415 + 0x60003258045FFLL, //6.3.9600.17919 + + 0xA000028004000LL, //10.0.10240.16384 + 0xA00002800401CLL, //10.0.10240.16412 + 0xA0000295A0000LL, //10.0.10586.0 + 0xA0000295A0132LL, //10.0.10586.306 + 0xA0000380603E8LL, //10.0.14342.1000 + 0xA000038190000LL, //10.0.14361.0 + 0xA000038390000LL, //10.0.14393.0 + 0xA000038390052LL //10.0.14393.82 +}; + +#define RPC_CORE_DESCRIPTION "Windows 10 64bits runtime core" +#define RPC_CORE_IS_WOW64 FALSE + +#define ULONG_PTR_T ULONG_PTR +#define PTR_T * + +#include "../RpcInternalsCommon.h" + +#pragma pack(1) +typedef struct _RPC_SERVER_T{ + MUTEX_T Mutex; + ULONG __bIslistening; + ULONG bIsListening; + ULONG MinimumCallThreads; + ULONG Wait; + ULONG OutCalls; + ULONG Unk1; + ULONG InCalls; + ULONG Unk2; + SIMPLE_DICT_T AddressDict; + ULONG lAvailableCalls; + ULONG Unk3; + SIMPLE_DICT_T _ProtSeqQueue; + ULONG Unk4[8]; + ULONG OutPackets; + ULONG Unk5; + MUTEX_T Mutex2; + ULONG MaxCalls; + ULONG Unk6; + VOID PTR_T hEvent; + ULONG Unk7[4]; + SIMPLE_DICT_T InterfaceDict; + ULONG _bIsListening; + ULONG bIsMaxCalls1234; + ULONG Unk8[6]; + ULONG InPackets; + ULONG Unk9; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk10[6]; + SIMPLE_DICT_T AuthenInfoDict; + LIST_ENTRY_T RpcIfGroupListEntry; + ULONG PTR_T __SRWLock; + LIST_ENTRY_T field_1E0; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + +typedef struct _RPC_INTERFACE_T +{ + PRPC_SERVER_T pRpcServer; + ULONG Flags; + ULONG Unk1; + MUTEX_T Mutex; + ULONG EpMapperFlags; + ULONG Unk2; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + RPC_SERVER_INTERFACE_T RpcServerInterface; + PMIDL_SYNTAX_INFO pSyntaxInfo; + VOID PTR_T pTransfertSyntaxes; + ULONG TransfertSyntaxesCount; + ULONG __Field_C4; + ULONG NbTypeManager; + ULONG MaxRpcSize; + UUID_VECTOR PTR_T pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; + ULONG IsCallSizeLimitReached; + ULONG currentNullManagerCalls; + ULONG __Field_150; + ULONG __Field_154; + ULONG __Field_158; + ULONG SecurityCallbackInProgress; + ULONG SecurityCacheEntry; + ULONG field_164; + VOID PTR_T __SecurityCacheEntries[16]; + SIMPLE_DICT_T FwEpDict; + ULONG Unk3[6]; + struct RPCP_INTERFACE_GROUP PTR_T pRpcpInterfaceGroup; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +typedef struct _RPC_ADDRESS_T{ + VOID PTR_T pVtable; + ULONG Magic; + ULONG TypeOfAddress; + ULONG ReferenceCounter; + ULONG Unk1[3]; + WCHAR PTR_T Name; + WCHAR PTR_T Protocole; + WCHAR PTR_T Address; + ULONG bNamed; + ULONG EpAddAddressFlag; + SIMPLE_DICT_T __LRPCSassociationSimpleDict; + ULONG __Field_68; + ULONG Unk3; + ULONG NbActiveCalls; + ULONG __Field_74; + ULONG Unk4[6]; + ULONG __Field_90; + MUTEX_T Mutex; +}RPC_ADDRESS_T; + +#pragma pack() + +#endif // _RPC_INTERNALS_H_ \ No newline at end of file diff --git a/RpcCore/RpcCoreResource.rc b/RpcCore/RpcCoreResource.rc new file mode 100644 index 0000000..685e8e1 --- /dev/null +++ b/RpcCore/RpcCoreResource.rc @@ -0,0 +1,90 @@ +// Microsoft Visual C++ generated resource script. +// +#include + +#define APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Français (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +#ifdef _WIN32 +//LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +1 VERSIONINFO + FILEVERSION _RPCVIEW_VERSION_MAJOR_,_RPCVIEW_VERSION_MINOR_,_RPCVIEW_VERSION_RELEASE_,0 + PRODUCTVERSION _RPCVIEW_VERSION_MAJOR_,_RPCVIEW_VERSION_MINOR_,_RPCVIEW_VERSION_RELEASE_,0 + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "RpcView" + VALUE "FileDescription", "RPC runtime analyzer module" + VALUE "InternalName", "RpcCore" + VALUE "LegalCopyright", "Copyright © 2012-2017 RpcView Team" + VALUE "LegalTrademarks", "Copyright (C) 2012-2017 RpcView Team" + VALUE "OriginalFilename", "RpcCore.dll" + VALUE "ProductName", "RpcCore" + VALUE "ProductVersion", _RPCVIEW_PRODUCT_VERSION_ + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.\0" +END + + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Français (France) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/RpcCore/RpcInternalsCommon.h b/RpcCore/RpcInternalsCommon.h new file mode 100644 index 0000000..5321637 --- /dev/null +++ b/RpcCore/RpcInternalsCommon.h @@ -0,0 +1,181 @@ +#ifndef _RPC_INTERNALS_COMMON_H_ +#define _RPC_INTERNALS_COMMON_H_ + +// Microsoft Remote Procedure Call (RPC) internals +// Undocumented structure from rpcrt4.dll +// +// global pointers : +// RPC_SERVER* GlobalRpcServer +// RPC_INTERFACE* GlobalManagementInterface +// ENDPOINT_MANAGER* EndpointManager +// LRPC_SERVER* GlobalLrpcServer +// SECURITY_PROVIDER_INFO* ProviderList +// +// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Rpc\ +// - the "ClientsProtocols" key contains protocole sequence accepted +// - the "Extensions" key ??? +// - the "SecurityService" key contains AuthnSvc constants and the corresponding DLLs +// the "InitSecurityInterfaceW" function is called as entry-point to initialize the Authentication service +// + +#include +#include "..\RpcCommon\ntdll.h" + +#define MAX_RPC_INTERFACE_ANNOTATION 64 +#define SIMPLE_DICT_SMALL_ARRAY 4 + + +//============================================================================== +// From Winnt.h +// The following structures are redefined to support Wow64 ptr +// +struct _RTL_CRITICAL_SECTION_T; + +typedef struct _LIST_ENTRY_T { + struct _LIST_ENTRY PTR_T Flink; + struct _LIST_ENTRY PTR_T Blink; +} LIST_ENTRY_T, *PLIST_ENTRY_T; + + +typedef struct _RTL_CRITICAL_SECTION_DEBUG_T { + WORD Type; + WORD CreatorBackTraceIndex; + struct _RTL_CRITICAL_SECTION_T PTR_T CriticalSection; + LIST_ENTRY_T ProcessLocksList; + DWORD EntryCount; + DWORD ContentionCount; + DWORD Flags; + WORD CreatorBackTraceIndexHigh; + WORD SpareWORD; +} RTL_CRITICAL_SECTION_DEBUG_T, PTR_T PRTL_CRITICAL_SECTION_DEBUG_T; + +typedef struct _RTL_CRITICAL_SECTION_T { + PRTL_CRITICAL_SECTION_DEBUG_T DebugInfo; + // + // The following three fields control entering and exiting the critical + // section for the resource + // + LONG LockCount; + LONG RecursionCount; + VOID PTR_T OwningThread; // from the thread's ClientId->UniqueThread + VOID PTR_T LockSemaphore; + VOID PTR_T SpinCount; // force size on 64-bit systems when packed +} RTL_CRITICAL_SECTION_T, PTR_T PRTL_CRITICAL_SECTION_T; + +//============================================================================== +// From RpcDceP.h +// +typedef struct _RPC_DISPATCH_TABLE_T{ + UINT DispatchTableCount; + RPC_DISPATCH_FUNCTION PTR_T DispatchTable; + ULONG_PTR_T Reserved; +} RPC_DISPATCH_TABLE_T, PTR_T PRPC_DISPATCH_TABLE_T; + +typedef struct _RPC_PROTSEQ_ENDPOINT_T{ + UCHAR PTR_T RpcProtocolSequence; + UCHAR PTR_T Endpoint; +} RPC_PROTSEQ_ENDPOINT_T, PTR_T PRPC_PROTSEQ_ENDPOINT_T; + +typedef struct _RPC_SERVER_INTERFACE_T{ + UINT Length; + RPC_IF_ID InterfaceId; + RPC_IF_ID TransferSyntax; + PRPC_DISPATCH_TABLE_T DispatchTable; + UINT RpcProtseqEndpointCount; + PRPC_PROTSEQ_ENDPOINT_T RpcProtseqEndpoint; + RPC_MGR_EPV PTR_T DefaultManagerEpv; + void const PTR_T InterpreterInfo; + UINT Flags ; +} RPC_SERVER_INTERFACE_T, PTR_T PRPC_SERVER_INTERFACE_T; + + +typedef struct _NDR_EXPR_DESC_T +{ + const unsigned short PTR_T pOffset; + const unsigned char PTR_T pFormatExpr; +} NDR_EXPR_DESC_T; + + +/* + * MIDL Stub Descriptor + */ +typedef struct _MIDL_STUB_DESC_T{ + void PTR_T RpcInterfaceInformation; + void PTR_T pfnAllocate; + void PTR_T pfnFree; + void PTR_T pAutoHandle; + const VOID PTR_T apfnNdrRundownRoutines; + const VOID PTR_T aGenericBindingRoutinePairs; + const VOID PTR_T apfnExprEval; + const VOID PTR_T aXmitQuintuple; + const unsigned char PTR_T pFormatTypes; + int fCheckBounds; + /* Ndr library version. */ + unsigned long Version; + VOID PTR_T pMallocFreeStruct; + long MIDLVersion; + const COMM_FAULT_OFFSETS PTR_T CommFaultOffsets; + // New fields for version 3.0+ + const VOID PTR_T aUserMarshalQuadruple; + // Notify routines - added for NT5, MIDL 5.0 + const VOID PTR_T NotifyRoutineTable; + /* + * Reserved for future use. + */ + ULONG_PTR_T mFlags; + // International support routines - added for 64bit post NT5 + const VOID PTR_T CsRoutineTables; + void PTR_T ProxyServerInfo; + const NDR_EXPR_DESC_T PTR_T pExprInfo; + // Fields up to now present in win2000 release. +} MIDL_STUB_DESC_T, PTR_T PMIDL_STUB_DESC_T; + + +/* + * Server Interpreter's information strucuture. + */ +typedef struct _MIDL_SERVER_INFO_T{ + PMIDL_STUB_DESC_T pStubDesc; + const VOID PTR_T PTR_T DispatchTable; + const unsigned char PTR_T ProcString; + const unsigned short PTR_T FmtStringOffset; + const VOID PTR_T PTR_T ThunkTable; + RPC_IF_ID PTR_T pTransferSyntax; + ULONG_PTR_T nCount; + VOID PTR_T pSyntaxInfo; +} MIDL_SERVER_INFO_T, PTR_T PMIDL_SERVER_INFO_T; + +//============================================================================== +// Common private structures from rpctr4.dll. +// These structures seems to be constant on all the runtime versions. +// +#pragma pack(1) +typedef struct _SIMPLE_DICT_T{ + VOID PTR_T PTR_T pArray; + UINT ArraySizeInBytes; //to change : countof array elements + UINT NumberOfEntries; + VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; +}SIMPLE_DICT_T, PTR_T PSIMPLE_DICT_T; + +typedef struct _QUEUE_T{ + VOID PTR_T Tail; + VOID PTR_T Head; + ULONG Lentgh; + VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; +}QUEUE_T; + +typedef struct _MUTEX_T{ + RTL_CRITICAL_SECTION_T CriticalSection; +}MUTEX_T; + +typedef struct _EVENT_T{ + ULONG hEvent; +} EVENT_T; + +#pragma pack() + +#define RPC_ADDRESS_TYPE_DG 0x400000 +#define RPC_ADDRESS_TYPE_LRPC 0x800000 +#define RPC_ADDRESS_TYPE_OSF 0x800 + +#endif //_RPC_INTERNALS_COMMON_H_ \ No newline at end of file diff --git a/RpcDecompiler/CMakeLists.txt b/RpcDecompiler/CMakeLists.txt new file mode 100644 index 0000000..21cc155 --- /dev/null +++ b/RpcDecompiler/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required (VERSION 3.0.2) + +message("[RpcDecompiler]") + +add_library(RpcDecompiler SHARED + internalComplexTypesArrays.cpp + internalComplexTypesArrays.h + InternalComplexTypesMisc.cpp + InternalComplexTypesMisc.h + internalComplexTypesPointers.cpp + internalComplexTypesPointers.h + internalComplexTypesStrings.cpp + internalComplexTypesStrings.h + internalComplexTypesStructs.cpp + internalComplexTypesStructs.h + internalComplexTypesUnions.cpp + internalComplexTypesUnions.h + internalRpcDecompiler.cpp + internalRpcDecompiler.h + InternalRpcDecompTypeDefs.cpp + internalRpcDecompTypeDefs.h + internalRpcDecompTypeDefs_LEGACY.h + internalRpcDecompTypeDefsNew.h + internalRpcUtils.h + InternalsRpcUtils.cpp + internalTypeTools.cpp + internalTypeTools.h + RpcDecompiler.cpp + RpcDecompiler.h + IdlFunction.h + IdlFunction.cpp + IdlType.h + IdlType.cpp + IdlInterface.h + IdlInterface.cpp + RpcDecompilerResource.rc) + + diff --git a/RpcDecompiler/IdlFunction.cpp b/RpcDecompiler/IdlFunction.cpp new file mode 100644 index 0000000..bcc3cfe --- /dev/null +++ b/RpcDecompiler/IdlFunction.cpp @@ -0,0 +1,447 @@ +#include "IdlFunction.h" +#include +#include "internalRpcDecompTypeDefsNew.h" +#include + + +// ====================================================================== +// CONSTRUCTOR +// ====================================================================== +IdlFunction::IdlFunction(unsigned int uProcIdx, IdlInterface* pIdlInterface) : + m_uProcIdx(uProcIdx), + m_pIdlInterface(pIdlInterface), + m_bHasRangeOnConformance(FALSE), + m_uOffsetFirstArg(0), + m_bDecoded(FALSE) +{ + memset(&m_ProcHeader, 0, sizeof(m_ProcHeader)); +} + + + + +// ====================================================================== +// ACCESSOR +// ====================================================================== +IdlInterface* IdlFunction::getpIdlInterface() const +{ + return m_pIdlInterface; +} + +size_t IdlFunction::getNbArguments() const +{ + return (size_t)m_ProcHeader.oifheader.bNumber_of_params; +} + +bool IdlFunction::hasRangeOnConformance() const +{ + return m_ProcHeader.win2KextHeader.interpreter_opt_flag2.HasRangeOnConf; +} + +const IdlType* IdlFunction::getReturnArg() const +{ + + for(auto iter= m_listArg.begin(); iter != m_listArg.end(); iter++) + { + if(iter->isReturnArg() == TRUE) + { + return &*iter; + } + } + + return NULL; + +} +// ====================================================================== +// OTHER METHODS +// ====================================================================== +DECOMP_STATUS IdlFunction::decode(void* pCtx) +{ + DECOMP_STATUS status = DS_ERR; + + // set function name + this->setName(pCtx); + + status = this->decodeProcHeader(pCtx); + + if(status != DS_SUCCESS) + { + RPC_ERROR_FN("decodeProcHeader failed\n"); + return DS_ERR_IN_DECODE_PROC_HEADER; + } + + status = this->decodeArguments(pCtx); + + if(status != DS_SUCCESS) + { + RPC_ERROR_FN("decodeArguments failed\n"); + return DS_ERR_IN_DECODE_PROC_PARAMS; + } + + m_bDecoded = TRUE; + + return DS_SUCCESS; +} + + +void IdlFunction::setName(void* pCtx) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *)pCtx; + std::stringstream ss; + + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable == NULL) + { + return; + } + + ss << "Proc" << std::dec << this->m_uProcIdx; + + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[this->m_uProcIdx] == NULL) + { + m_strFunctionName = ss.str(); + } + else + { + size_t sz = wcslen(pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[this->m_uProcIdx]) + 1; + size_t szConverted = 0; + + char* pTmp = (char*)pRpcDecompilerCtxt->pRpcViewHelper->RpcAlloc((UINT)sz); + + if (pTmp != NULL) + { + ZeroMemory(pTmp, sz); + wcstombs_s(&szConverted, pTmp, sz, pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[this->m_uProcIdx], sz); + + m_strFunctionName = ss.str() + std::string("_") + std::string(pTmp); + // + // We have to replace all ':' by '_' as MIDL doesn't support it + // example: NThreadingLibrary::TWorkItem::NotifyCancel + // + std::replace(m_strFunctionName.begin(), m_strFunctionName.end(), ':', '_'); + + pRpcDecompilerCtxt->pRpcViewHelper->RpcFree(pTmp); + } + } + + + return; +} + + + +DECOMP_STATUS IdlFunction::decodeProcHeader(void* pCtx) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *)pCtx; + UINT uOffsetInProcFmtString; + + + if (pRpcDecompilerCtxt == NULL) + { + return DS_ERR_INVALID_PARAM; + } + + // get proc offset in type format string + uOffsetInProcFmtString = pRpcDecompilerCtxt->pRpcDecompilerInfo->pFormatStringOffsetTable[this->m_uProcIdx]; + + // Init ProcHeader + memset(&this->m_ProcHeader, 0, sizeof(this->m_ProcHeader)); + + //======================================================== + // Read Oi Header part of header + //======================================================== + + + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.oiHeader.beginning), + sizeof(this->m_ProcHeader.oiHeader.beginning)); + + if (bResult == FALSE) + { + return DS_ERR_UNABLE_TO_READ_MEMORY; + } + + uOffsetInProcFmtString += sizeof(this->m_ProcHeader.oiHeader.beginning); + + // should we read rpc_flags ? + if ((this->m_ProcHeader.oiHeader.beginning.bOi_flags & Oi_HAS_RPCFLAGS) == Oi_HAS_RPCFLAGS) + { + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.oiHeader.dwRpc_flags), + sizeof(this->m_ProcHeader.oiHeader.dwRpc_flags)); + + if (bResult == FALSE){ + return DS_ERR_UNABLE_TO_READ_MEMORY; + } + + uOffsetInProcFmtString += sizeof(this->m_ProcHeader.oiHeader.dwRpc_flags); + } + + // read OiHeader end + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.oiHeader.end), + sizeof(this->m_ProcHeader.oiHeader.end)); + + if (bResult == FALSE){ + return DS_ERR_UNABLE_TO_READ_MEMORY; ; + } + + uOffsetInProcFmtString += sizeof(this->m_ProcHeader.oiHeader.dwRpc_flags); + + + //======================================================== + // If necessary read exeplicit_handle_description + //======================================================== + if(this->m_ProcHeader.oiHeader.beginning.bHandle_type == FC_EXPLICIT_HANDLE) + { + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.explicitHandle), + EXPLICIT_HANDLE_MIN_SIZE); + + if(bResult == FALSE) + { + return DS_ERR_UNABLE_TO_READ_MEMORY; + } + + switch(this->m_ProcHeader.explicitHandle.htype) + { + case FC_BIND_PRIMITIVE: + uOffsetInProcFmtString+= EXPLICIT_HANDLE_PRIMITIVE_SIZE; + break; + + case FC_BIND_GENERIC: + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.explicitHandle), + EXPLICIT_HANDLE_GENERIC_SIZE); + + if(bResult == FALSE) + { + return DS_ERR_UNABLE_TO_READ_MEMORY; + } + + uOffsetInProcFmtString+= EXPLICIT_HANDLE_GENERIC_SIZE; + break; + + case FC_BIND_CONTEXT: + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.explicitHandle), + EXPLICIT_HANDLE_CONTEXT_SIZE); + + if(bResult == FALSE) + { + return DS_ERR_UNABLE_TO_READ_MEMORY; + } + + uOffsetInProcFmtString+= EXPLICIT_HANDLE_CONTEXT_SIZE; + break; + + default: + RPC_ERROR_FN("invalid explicit handle type\n"); + return DS_ERR_INVALID_DATA; + break; + } + } + + + //======================================================== + // Read Oif header part of header + //======================================================== + + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.oifheader), + sizeof(this->m_ProcHeader.oifheader)); + + if (bResult == FALSE){ + return DS_ERR_UNABLE_TO_READ_MEMORY; ; + } + + uOffsetInProcFmtString += sizeof(this->m_ProcHeader.oifheader); + + //======================================================== + // Read Win32Ext header part of header + //======================================================== + + // TODO : check under which condition win32Kext header is present + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.win2KextHeader.extension_version), + sizeof(this->m_ProcHeader.win2KextHeader.extension_version)); + + if (bResult == FALSE){ + return DS_ERR_UNABLE_TO_READ_MEMORY; ; + } + + + switch (this->m_ProcHeader.win2KextHeader.extension_version) + { + case WIN2K_EXT_HEADER_32B_SIZE: + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.win2KextHeader.extension_version), + WIN2K_EXT_HEADER_32B_SIZE + ); + + uOffsetInProcFmtString += WIN2K_EXT_HEADER_32B_SIZE; + + break; + case WIN2K_EXT_HEADER_64B_SIZE: + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + uOffsetInProcFmtString), + &(this->m_ProcHeader.win2KextHeader.extension_version), + WIN2K_EXT_HEADER_64B_SIZE + ); + + uOffsetInProcFmtString += WIN2K_EXT_HEADER_64B_SIZE; + break; + + default: + return DS_ERR_INVALID_DATA; + } + + m_uOffsetFirstArg = uOffsetInProcFmtString; + + + return DS_SUCCESS; +} + + + +DECOMP_STATUS IdlFunction::decodeArguments(void* pCtx) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *)pCtx; + UINT uOffsetArg = 0; + + //======================================================== + // Check arg + //======================================================== + if(pRpcDecompilerCtxt == NULL) + { + return DS_ERR_INVALID_PARAM; + } + + // ensure that offset to first arg is properly set + if(m_uOffsetFirstArg == 0) + { + return DS_ERR_FUNCTION_NOT_PROPERLY_INITIALIZED; + } + + + uOffsetArg = m_uOffsetFirstArg; + + for(unsigned int i=0; igetNbArguments(); i++) + { + DECOMP_STATUS status; + IdlType idlArg(this, uOffsetArg); + + status = idlArg.decode(pRpcDecompilerCtxt); + + if(status != DS_SUCCESS) + { + RPC_ERROR_FN("decode failed\n"); + return status; + } + + m_listArg.push_back(idlArg); + + // TODO : check if this size is constant + uOffsetArg += OIF_PARAM_SIZE; + } + + + + + return DS_SUCCESS; + +} + + +std::ostream& IdlFunction::dump(std::ostream& o) const +{ + const IdlType* pReturnArg = this->getReturnArg(); + bool bFirst = true; + + + // ============================================= + // ensure that function has been correctly decoded + // ============================================= + if(m_bDecoded == FALSE) + { + o << DEFAULT_FN_PREFIX << m_uProcIdx << "_NotDecoded();" << std::endl; + return o; + } + + // ============================================= + // display return argument + // ============================================= + if(pReturnArg == NULL) + { + o << "void "; + } + else + { + o << *pReturnArg; + } + + // ============================================= + // display function name + // ============================================= + o << m_strFunctionName << "(" << std::endl; + +#ifdef _ADD_IMPLICIT_HANDLE + // ============================================= + // display every arguments + // ============================================= + // manage special handle case + // sometimes a handle should be add at the beginning + // let's check if the first argument start at offset 0 + for(auto it=m_listArg.begin(); it!=m_listArg.end(); it++) + { + if(it->getStackOffset() == 0) + { + bNeedFirstHandle = false; + break; + } + } + + if(bNeedFirstHandle == true) + { + o << "\t/*add default handle*/[in] handle_t arg_0"; + bFirst = false; + } +#endif + + // display every arguments in argList + for(auto it=m_listArg.begin(); it!=m_listArg.end(); it++) + { + if(it->isReturnArg() == false) + { + if(bFirst) + { + bFirst = false; + } + else + { + o <<", " << std::endl; + } + + + o << "\t" << *it; + } + } + + o << ");"; + + return o; +} + +std::ostream& operator<<(std::ostream& o, const IdlFunction& idlFunction) +{ + return idlFunction.dump(o); +} \ No newline at end of file diff --git a/RpcDecompiler/IdlFunction.h b/RpcDecompiler/IdlFunction.h new file mode 100644 index 0000000..d673331 --- /dev/null +++ b/RpcDecompiler/IdlFunction.h @@ -0,0 +1,66 @@ +#ifndef _RPC_DECOMP_FUNCTION_ +#define _RPC_DECOMP_FUNCTION_ + +#include + +#include +#include + +#include "IdlType.h" +#include "IdlInterface.h" +#include "internalRpcDecompTypeDefs.h" + +class IdlType; +class IdlInterface; + +//#define _ADD_IMPLICIT_HANDLE +#define DEFAULT_FN_PREFIX "_Function_" + +class IdlFunction +{ +private: + std::string m_strFunctionName; // function name + IdlInterface* m_pIdlInterface; // interface owning function + std::list m_listArg; // list of function argument + unsigned int m_uProcIdx; // function index in proc interface proc format string + BOOL m_bInlined; // TRUE if function is inlined + BOOL m_bHasRangeOnConformance; // TRUE if function has range on conformance + PROC_HEADER_T m_ProcHeader; + UINT m_uOffsetFirstArg; // Offset of first argument in proc format string + BOOL m_bDecoded; // BOOL indicating if function has been properly decoded +public: + + + // ====================================================================== + // CONSTRUCTOR + // ====================================================================== + IdlFunction(unsigned int uProcIdx, IdlInterface* pIdlInterface); + + + // ====================================================================== + // ACCESSOR + // ====================================================================== + IdlInterface* getpIdlInterface() const; + size_t getNbArguments() const; + bool hasRangeOnConformance() const; + + + const IdlType* getReturnArg() const; + + + // ====================================================================== + // OTHER METHODS + // ====================================================================== + DECOMP_STATUS decode(void* pCtx); + void setName(void* pCtx); + DECOMP_STATUS decodeProcHeader(void* pCtx); + DECOMP_STATUS decodeArguments(void* pCtx); + std::ostream& dump(std::ostream& o) const; + + +}; + + +std::ostream& operator<<(std::ostream& o, const IdlFunction& idlFunction); + +#endif \ No newline at end of file diff --git a/RpcDecompiler/IdlInterface.cpp b/RpcDecompiler/IdlInterface.cpp new file mode 100644 index 0000000..066d9bf --- /dev/null +++ b/RpcDecompiler/IdlInterface.cpp @@ -0,0 +1,229 @@ +#include "IdlInterface.h" +#include "internalRpcDecompiler.h" + +// ====================================================================== +// CONSTRUCTOR +// ====================================================================== +IdlInterface::IdlInterface(std::string strIfName, RPC_IF_ID& RpcIfId, size_t szNbFunctions): + m_strIfName(strIfName), + m_szNbFunctions(szNbFunctions), + m_vectFunctions(szNbFunctions), + m_RpcIfId(RpcIfId) +{ + +} + +IdlInterface::~IdlInterface() +{ + for(size_t i=0; i IdlInterface::getIntefaceFunctions() +{ + return m_vectFunctions; +} + +// ====================================================================== +// DECODING METHODS +// ====================================================================== +DECOMP_STATUS IdlInterface::decode(void* pCtx) +{ + DECOMP_STATUS dStatus = DS_ERR; + DECOMP_STATUS dStatusRet = DS_SUCCESS; + + // check param + if(pCtx == NULL) + { + RPC_ERROR_FN("pCtx NULL pointer\n"); + return DS_ERR_INVALID_PARAM; + } + + + // decode every functions + for(UINT i=0; idecodeFunction(i, pCtx); + + if(dStatus != DS_SUCCESS) + { + RPC_ERROR_FN("decodeFunction failed\n"); + printf("Idx %u\n", i); + std::ostringstream ossIf; + this->dumpIfInfo(ossIf); + printf("%s", ossIf.str().c_str()); + //DEBUG_BREAK(); + // don't stop at first failure in order to decompile every possible functions + dStatusRet = dStatus; + } + } + + if(dStatusRet == DS_SUCCESS) + { + // once every functions is decoded + dStatusRet = decodeInterfaceComplexTypes(pCtx); + } + + + return dStatusRet; +} + + + + + +DECOMP_STATUS IdlInterface::decodeFunction(UINT uFunctionIdx, void* pCtx) +{ + // check param + if(pCtx == NULL) + { + return DS_ERR_INVALID_PARAM; + } + if(uFunctionIdx > m_szNbFunctions) + { + return DS_ERR_INVALID_INDEX; + } + + // has function already been decoded + if(m_vectFunctions[uFunctionIdx] == NULL) + { + m_vectFunctions[uFunctionIdx] = new IdlFunction(uFunctionIdx, this); + + return (m_vectFunctions[uFunctionIdx])->decode(pCtx); + } + else + { + return DS_SUCCESS; + } +} + + + + + +DECOMP_STATUS IdlInterface::decodeInterfaceComplexTypes(void* pCtx) +{ + std::list listAllTypesSorted; + std::ostringstream ossUseless; + + + // check param + if(pCtx == NULL) + { + return DS_ERR_INVALID_PARAM; + } + + // clear string stream content + m_ossComplexTypes.flush(); + + + // recursively explore all list in order to get a complete list of types + if (getAllTypesSortedInAList(pCtx, m_listProcTypes, listAllTypesSorted, ossUseless) == FALSE) + { + m_ossComplexTypes<<"[ERROR] unable to get list of all types sorted" << std::endl; + return DS_ERR_UNABLE_TO_DECODE_COMPLEX_TYPE; + } + + if( dumpTypeList(pCtx, listAllTypesSorted, m_ossComplexTypes) == FALSE) + { + m_ossComplexTypes<<"[ERROR] unable to dump type list" << std::endl; + return DS_ERR_UNABLE_TO_DECODE_COMPLEX_TYPE; + } + + + return DS_SUCCESS; + +} + + +std::ostream& IdlInterface::dump(std::ostream& o) const +{ + dumpIfInfo(o); + + o << std::endl; + o << "interface "<< m_strIfName << std::endl; + o << "{" << std::endl; + + // display complex type + + o << m_ossComplexTypes.str(); + + // display functions + for(size_t i=0; i< m_szNbFunctions; i++) + { + o << std::endl; + + if(m_vectFunctions[i] == NULL) + { + o << "void Opnum"< +#include + +class IdlFunction; +class IdlType; + + + +// IdlInterface class definition + +class IdlInterface +{ + friend class IdlType; +private: + std::string m_strIfName; // Interface name + RPC_IF_ID m_RpcIfId; // inteface id + std::vector m_vectFunctions; // vector holding pointer to every function defined in interface + // this vector will be filled once functions are decompiled + + size_t m_szNbFunctions; // number of functions defined in interface + + std::list m_listProcTypes; // list of complex types (structure / union) found while decompiling functions + // once this list is filled it is parsed to produce declaration of these complex types + + std::ostringstream m_ossComplexTypes; // string stream that will contained decoded version of complex types + // (once they've all been found and decoded) +public: + // ====================================================================== + // CONSTRUCTOR + // ====================================================================== + IdlInterface(std::string strIfName, RPC_IF_ID& RpcIfId, size_t szNbFunctions); + ~IdlInterface(); + + // ====================================================================== + // ACCESSOR + // ====================================================================== + std::vector getIntefaceFunctions(); + std::list getListTypeToDefine(); + + // ====================================================================== + // DECODIND METHODS + // ====================================================================== + + DECOMP_STATUS decode(void* pCtx); + DECOMP_STATUS decodeFunction(UINT uFunctionIdx, void* pCtx); + DECOMP_STATUS decodeInterfaceComplexTypes(void* pCtx); + std::ostream& dump(std::ostream& o) const; + std::ostream& dumpIfInfo(std::ostream& o) const; +}; + + +std::ostream& operator<<(std::ostream& o, const IdlInterface& idlInterface); + +#endif \ No newline at end of file diff --git a/RpcDecompiler/IdlType.cpp b/RpcDecompiler/IdlType.cpp new file mode 100644 index 0000000..5763a9d --- /dev/null +++ b/RpcDecompiler/IdlType.cpp @@ -0,0 +1,168 @@ +#include "IdlType.h" +#include "internalRpcDecompiler.h" +#include + + +IdlType::IdlType(IdlFunction* pFunction, const UINT m_uOffsetInProcFmt): + m_pFunction(pFunction), + m_uOffsetInProcFmt(m_uOffsetInProcFmt) +{ + +} + + +// ====================================================================== +// ACCESSOR +// ====================================================================== +unsigned short IdlType::getStackOffset() const +{ + return m_paramDescription.oif_Format.stack_offset; +} + + +DECOMP_STATUS IdlType::decode(const void* pCtx) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *)pCtx; + BOOL bResult; + UINT32 argNbr = 0; + ParamDesc ParamDesc; + std::ostringstream ossTmp; + std::ostringstream oss; + + //======================================================== + // Check arg + //======================================================== + if(pRpcDecompilerCtxt == NULL) + { + return DS_ERR_INVALID_PARAM; + } + + + + //======================================================== + // Read param description + //======================================================== + bResult = RPC_GET_PROCESS_DATA2( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + m_uOffsetInProcFmt), + &m_paramDescription, + sizeof(m_paramDescription) + ); + + + + if(is64B) argNbr = m_paramDescription.oif_Format.stack_offset / VIRTUAL_STACK_OFFSET_GRANULARITY_64B; + else argNbr = m_paramDescription.oif_Format.stack_offset / VIRTUAL_STACK_OFFSET_GRANULARITY_32B; + + + // add param IdlFunctionDesc properties + if(m_pFunction->hasRangeOnConformance()) + { + ParamDesc.setHasRangeOnConformance(); + } + + // fill param desc with ParamAttr + ParamDesc.fillWithParamAttr(m_paramDescription.oif_Format.paramAttributes); + + + + // TODO : ParamDesc was used in old mode, remove it + if(m_paramDescription.oif_Format.paramAttributes.IsReturn == 0) + { + ossTmp << "arg_" << argNbr; + ParamDesc.setParamName(ossTmp.str()); + } + + + + + // param is base type + if(m_paramDescription.oif_Format.paramAttributes.IsBasetype) + { + bResult = processSimpleType( + pRpcDecompilerCtxt, + (FC_TYPE)m_paramDescription.oif_Format.paramType.base_type_format_char.type_format_char, + ParamDesc, + oss); + + if(FALSE == bResult) + { + RPC_ERROR_FN("processSimpleType failed\n"); + return DS_ERR_IN_SIMPLE_TYPE; + } + + + } //if(paramToPrint.oif_Format.paramAttributes.IsBasetype) + else + { + ParamDesc.setRva(pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString + m_paramDescription.oif_Format.paramType.other_type_offset); + + bResult = rpcDumpType( + pRpcDecompilerCtxt, + ParamDesc, + m_pFunction->getpIdlInterface()->m_listProcTypes, + oss); + + if(bResult == FALSE) + { + RPC_ERROR_FN("rpcDumpType failed\n"); + return DS_ERR_IN_SIMPLE_TYPE; + } + }// !(paramToPrint.oif_Format.paramAttributes.IsBasetype) + + + m_name = oss.str(); + + return DS_SUCCESS; +} + +bool IdlType::isReturnArg() const +{ + return (m_paramDescription.oif_Format.paramAttributes.IsReturn != 0); +} + + + +std::ostream& IdlType::dump(std::ostream& o) const +{ + + if( (m_paramDescription.oif_Format.paramAttributes.IsReturn) == 0) + { + + if(m_paramDescription.oif_Format.paramAttributes.IsIn) + { + o << "[in]"; + } + + if(m_paramDescription.oif_Format.paramAttributes.IsOut) + { + o << "[out]"; + } + + #ifdef _DEBUG + if(m_paramDescription.oif_Format.paramAttributes.IsSimpleRef) + { + o << "/* simple_ref */"; + } + #endif + // + // pipe appears to be an invalid attribute for MIDL + // see EfsRpc (c681d488-d850-11d0-8c52-00c04fd90f7e) EfsRpcReadFileRaw_Downlevel + // + /* + if(m_paramDescription.oif_Format.paramAttributes.IsPipe) + { + o << "[pipe]"; + } + */ + } + + o << m_name; + + return o; +} + + +std::ostream& operator<<(std::ostream& o, const IdlType& idlType) +{ + return idlType.dump(o); +} \ No newline at end of file diff --git a/RpcDecompiler/IdlType.h b/RpcDecompiler/IdlType.h new file mode 100644 index 0000000..c53edcc --- /dev/null +++ b/RpcDecompiler/IdlType.h @@ -0,0 +1,47 @@ +#ifndef _RPC_DECOMP_TYPE_ +#define _RPC_DECOMP_TYPE_ + +#include "IdlFunction.h" +#include "internalRpcDecompTypeDefs.h" +#include + + +class IdlFunction; + +class IdlType +{ +private: + std::string m_name; // Param name + IdlFunction* m_pFunction; // pointer to related function + UINT m_uOffsetInProcFmt; // offset where param is described in proc format string + ProcFormatStringParam_U m_paramDescription; // Parameter description in proc format string + + +public: + + + // ====================================================================== + // CONSTRUCTOR + // ====================================================================== + IdlType(IdlFunction* pFunction, const UINT m_uOffsetInProcFmt); + + + // ====================================================================== + // ACCESSOR + // ====================================================================== + unsigned short getStackOffset() const; + + + // ====================================================================== + // OTHER METHODS + // ====================================================================== + DECOMP_STATUS decode(const void* pCtx); + bool isReturnArg() const; + std::ostream& dump(std::ostream& o) const; + +}; + + +std::ostream& operator<<(std::ostream& o, const IdlType& idlType); + +#endif \ No newline at end of file diff --git a/RpcDecompiler/InternalComplexTypesMisc.cpp b/RpcDecompiler/InternalComplexTypesMisc.cpp new file mode 100644 index 0000000..5423b02 --- /dev/null +++ b/RpcDecompiler/InternalComplexTypesMisc.cpp @@ -0,0 +1,955 @@ +#include "InternalComplexTypesMisc.h" +#include "internalRpcDecompiler.h" +#include "internalRpcUtils.h" +#include + + +BOOL __fastcall processBindContext( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + UNREFERENCED_PARAMETER(listProcTypes); + UNREFERENCED_PARAMETER(pType); + UNREFERENCED_PARAMETER(pContext); + + oss << "[context_handle] void*"; + displayPtrLevel(ParamDesc.getuPtrLevel(), oss); + oss <<" "<& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = TRUE; + short wOffsetRange = 0; + DWORD dwRangeBegin = 0; + DWORD dwRangeEnd = 0; + RVA_T pNewType = NULL; + BYTE bRead = 0; + + + pType += sizeof(BYTE) + sizeof(BYTE); // skip FC_TYPE and first BYTE + + //read offset to complex type + RPC_GET_PROCESS_DATA(pType,&wOffsetRange,sizeof(wOffsetRange)); + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n"); + return FALSE; + } + + + + pNewType = pType + wOffsetRange; + pType += sizeof(wOffsetRange); + + // read FC_TYPE at given offset + RPC_GET_PROCESS_DATA(pNewType,&bRead,sizeof(bRead)); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n"); + return FALSE; + } + + + // if type is a FC_BIND_CONTEXT range doesn't make sense + // todo : check why this happen + if((FC_TYPE) bRead != FC_BIND_CONTEXT) + { + //read range begin + RPC_GET_PROCESS_DATA(pType,&dwRangeBegin,sizeof(dwRangeBegin)); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n"); + return FALSE; + } + + pType += sizeof(dwRangeBegin); + + //read range end + RPC_GET_PROCESS_DATA(pType,&dwRangeEnd,sizeof(dwRangeEnd)); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n"); + return FALSE; + } + + + + + oss<<"[range("<& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = TRUE; + std::ostringstream ossTmp; + + Range_t range; + + UNREFERENCED_PARAMETER(listProcTypes); + + RPC_GET_PROCESS_DATA(pType, &range, sizeof(range)); + + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processRange : unable to read process data\n"); + return FALSE; + } + + processSimpleType( + pContext, + (FC_TYPE)(range.flags_type & 0xF), //type is on lower byte + ParamDesc, + ossTmp); + + + if(ParamDesc.getuPtrLevel() != 0) + { + oss << "/*"; + } + oss << "[range(" << std::dec << range.lowValue << "," << range.highValue<< ")] "; + if(ParamDesc.getuPtrLevel() != 0) + { + oss << "*/"; + } + + + oss< v, UINT offset) +{ + for(UINT i=0; i& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = TRUE; + UserMarshal_t userMarshal; + RVA_T pUserMarshalTarget = NULL; + std::string strParamNameTmp; + + RPC_GET_PROCESS_DATA(pType, &userMarshal, sizeof(userMarshal)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processUserMarshal : unable to read process data\n"); + return FALSE; + } + + oss << "/* WARNING : user_marshall should be defined in ACF file */ [user_marshall("; + + // compute user marshal target offset + pUserMarshalTarget = pType + FIELD_OFFSET(UserMarshal_t, offset_to_the_transmitted_type) + userMarshal.offset_to_the_transmitted_type; + ParamDesc.setRva(pUserMarshalTarget); + + strParamNameTmp = ParamDesc.getStrTypeName(); + ParamDesc.setParamName(""); + + if (rpcDumpType(pContext, ParamDesc, listProcTypes, oss) == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processUserMarshal : unable to dump type\n"); + return FALSE; + } + + + oss << ")] " << strParamNameTmp; + + // set user_marshal size ?? + + + return TRUE; +} + + +BOOL __fastcall getUserMarshallMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = TRUE; + UserMarshal_t userMarshal; + + + RPC_GET_PROCESS_DATA(pType, &userMarshal, sizeof(userMarshal)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processUserMarshal : unable to read process data\n"); + return FALSE; + } + + *pszMemorySize = userMarshal.user_type_memory_size; + + return TRUE; +} + + +BOOL __fastcall processPipe( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = TRUE; + Pipe_t pipe; + RVA_T pPipeTarget = NULL; + std::string strParamNameTmp; + + RPC_GET_PROCESS_DATA(pType, &pipe, sizeof(pipe)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processPipe : unable to read process data\n"); + return FALSE; + } + + + + // compute pipe target offset + pPipeTarget = pType + FIELD_OFFSET(Pipe_t, offsetToType ) + pipe.offsetToType; + ParamDesc.setRva(pPipeTarget); + + + oss << "pipe "; + + if (rpcDumpType(pContext, ParamDesc, listProcTypes, oss) == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processPipe : unable to read process data\n"); + return FALSE; + } + + + + // set pipe size ?? + + return TRUE; +} + + +BOOL __fastcall getPipeMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize, + _In_ BOOL bHasRangeOnConformance) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = TRUE; + Pipe_t pipe; + RVA_T pPipeTarget = NULL; + + + RPC_GET_PROCESS_DATA(pType, &pipe, sizeof(pipe)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] getPipeMemorySize : unable to read process data\n"); + return FALSE; + } + + + + // compute pipe target offset + pPipeTarget = pType + FIELD_OFFSET(Pipe_t, offsetToType ) + pipe.offsetToType; + + bResult = getTypeMemorySize(pContext, pPipeTarget, pszMemorySize, bHasRangeOnConformance); + + return bResult; +} + + +BOOL __fastcall processCorrelationDescriptor( + _In_ VOID* pContext, + _In_ ConformanceDescr_T confDesc, + _Inout_ std::ostringstream& oss, + _Inout_ ParamDesc& paramDesc) +{ + + BOOL bResult = FALSE; + + oss<<"["; + + // display conformance type + switch(confDesc.confType) + { + case size_is: + oss<<"size_is("; + break; + case switch_is: + oss<<"switch_is("; + break; + case length_is: + oss<<"length_is("; + break; + case byte_count: + oss<<"byte_count("; + break; + default: + oss<<"unknow_corr_type("; + } + + // Check on which pointer level conformance should be applied + { + UINT uPtrLevel = paramDesc.getuPtrLevel(); + + if(uPtrLevel > 1) + { + while(--uPtrLevel > 1) + { + oss << ","; + } + } + } + + + bResult = processCorrelationDescriptorNaked(pContext, confDesc, oss, paramDesc); + + oss<<")]"; + + return bResult; +} + + +BOOL __fastcall processCorrelationDescriptorNaked( + _In_ VOID* pContext, + _In_ ConformanceDescr_T confDesc, + _Inout_ std::ostringstream& oss, + _Inout_ ParamDesc& paramDesc) +{ + + BOOL bResult; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + std::string strCorrelationItem; // string describing X in size_is(X) + + + // special cases : OperationType == FC_EXPR || OperationType === FC_CALLBACK + if(confDesc.corrDesc.correlation_operator == FC_EXPR ) + { + USHORT offset = 0; + + // read offset + RPC_GET_PROCESS_DATA( + ((RVA_T)pRpcDecompilerCtxt->pRpcDecompilerInfo->pExprOffset + confDesc.corrDesc.offset*sizeof(USHORT)), + &offset, + sizeof(USHORT)); + + if(bResult == FALSE) + { + oss << "/* ERROR unable to read ExprOffset table */"; + return FALSE; + } + + oss << "/* FC_EXPR */"; + + bResult = processFcExpr( + pContext, + pRpcDecompilerCtxt->pRpcDecompilerInfo->pExprFormatString + offset, + paramDesc, + confDesc, + oss); + + return bResult; + } + if(confDesc.corrDesc.correlation_operator == FC_CALLBACK ) + { + oss << "/*FC_CALLBACK not implemented */"; + return TRUE; + } + + // FIRST STEP : according to correlation type correlation item + + // case of a FC_CONSTANT_CONFORMANCE + if(confDesc.corrDesc.correlation_type & FC_CONSTANT_CONFORMANCE) + { + INT32 iSize = ((confDesc.corrDesc.correlation_operator << 16) | confDesc.corrDesc.offset) & 0xFFFFFF; + + oss<= OP_UNARY_PLUS && operation.Operator <= OP_UNARY_AND) // Unary operator + { + oss << getOperatorType(operation); + + pExpr += sizeof(EXPR_OPERATOR); + sizeToAdvance += sizeof(EXPR_OPERATOR); + + sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss); + sizeToAdvance += sizeOfExpr; + }else if(operation.Operator >= OP_PLUS && operation.Operator <= OP_LOGICAL_OR) // binary operator + { + std::string tmpOper = getOperatorType(operation); + oss << "("; + pExpr += sizeof(EXPR_OPERATOR); + sizeToAdvance += sizeof(EXPR_OPERATOR); + + sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss); + + pExpr += sizeOfExpr; + sizeToAdvance += sizeOfExpr; + + oss <<" "<< tmpOper.c_str()<<" "; + + sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss); + + sizeToAdvance += sizeOfExpr; + + oss << ")"; + }else{ // Ternary operator => (expr ? expr1 : expr2) + std::ostringstream tmpIfYes; + std::ostringstream tmpIfNo; + + pExpr += sizeof(EXPR_OPERATOR); + sizeToAdvance += sizeof(EXPR_OPERATOR); + + sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, tmpIfYes); + sizeToAdvance += sizeOfExpr; + pExpr += sizeOfExpr; + + sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc,confDesc, tmpIfNo); + sizeToAdvance += sizeOfExpr; + pExpr += sizeOfExpr; + + oss << "("; + + sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss); + sizeToAdvance += sizeOfExpr; + + oss << "?"; + oss << tmpIfYes.str(); + oss << ":"; + oss << tmpIfNo.str(); + oss << ")"; + } + break; + case FC_EXPR_VAR: + RPC_GET_PROCESS_DATA(pExpr, &var, sizeof(EXPR_VAR)); + + if(confDesc.corrDesc.correlation_type & FC_TOP_LEVEL_CONFORMANCE) + { + varNb = var.Offset / VIRTUAL_STACK_OFFSET_GRANULARITY; + oss << "arg_" << std::dec << varNb; + }else{ + INT uCorrDescMemberOffset; + INT uCorrDescMember; + std::stringstream ss; + // get member number according to its offset + if(paramDesc.getArrayIsAttributedPointer()) + { + uCorrDescMemberOffset = var.Offset; + }else{ + uCorrDescMemberOffset = paramDesc.getVectMembersOffset()[paramDesc.getuStructMemberNum()] + var.Offset; + } + uCorrDescMember = getElementByOffset(paramDesc.getVectMembersOffset(), uCorrDescMemberOffset); + + if(uCorrDescMember == -1) + { + oss << "/* [ERROR] invalid corrDescMember || var offset = " << std::dec << var.Offset << "*/"; + return FALSE; + } + + oss << "StructMember"<& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + TransmitRepresentAs_t transmit; + + RPC_GET_PROCESS_DATA(pType, &transmit, sizeof(TransmitRepresentAs_t)); + + RVA_T pTransmittedType = pType + sizeof(TransmitRepresentAs_t) + transmit.transmitted_type_offset - sizeof(transmit.transmitted_type_offset); + + oss << "/* data transmitted as */"; + ParamDesc.setRva(pTransmittedType); + if( rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss) == FALSE) + { + RPC_DEBUG_FN("[ERROR] processTransmitRepresentAs : dump type failed \n"); + return FALSE; + } + + return TRUE; +} + + +BOOL __fastcall getTransmitAsRepresentAsMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize) +{ + BOOL bResult; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + TransmitRepresentAs_t transmit; + + RPC_GET_PROCESS_DATA(pType, &transmit, sizeof(TransmitRepresentAs_t)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN("[ERROR] getTransmitAsRepresentAsMemorySize : unable to get process data\n"); + return FALSE; + } + + // TODO : check if this is this size and not target size that is used for conformance + *pszMemorySize = transmit.presented_type_memory_size; + + return TRUE; +} + + +UINT getCorrelationDescriptorSize( + _In_ BOOL bRobustFlagWasSet, + _In_ BOOL bHasRangeOnConformance) +{ + + UINT uSize = 0; + + UNREFERENCED_PARAMETER(bRobustFlagWasSet); + + if(robustFlagWasSet) + { + uSize = sizeof(CorrelationDescriptorRobust_t); + } + else + { + uSize = sizeof(CorrelationDescriptorNonRobust_t); + } + + if(bHasRangeOnConformance) + { + uSize += sizeof(Range_t); + } + + return uSize; +} \ No newline at end of file diff --git a/RpcDecompiler/InternalComplexTypesMisc.h b/RpcDecompiler/InternalComplexTypesMisc.h new file mode 100644 index 0000000..c2f399d --- /dev/null +++ b/RpcDecompiler/InternalComplexTypesMisc.h @@ -0,0 +1,144 @@ +#ifndef _INTERNAL_COMPLEX_TYPES_MISC_H_ +#define _INTERNAL_COMPLEX_TYPES_MISC_H_ + +#include +#include +#include "internalRpcDecompTypeDefs.h" + + +//--------------------------------------------------------------------------- +BOOL __fastcall processBindContext( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall process_FC_BLKHOLE( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall getFC_BLKHOLEMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize, + _In_ BOOL bHasRangeOnConformance); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processRange( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall getRangeMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize); + +BOOL __fastcall ProcessArrayRange( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::ostringstream& temp); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processUserMarshal( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall getUserMarshallMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processPipe( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall getPipeMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize, + _In_ BOOL bHasRangeOnConformance); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processCorrelationDescriptor( + _In_ VOID* pContext, + _In_ ConformanceDescr_T confDesc, + _Inout_ std::ostringstream& oss, + _Inout_ ParamDesc& paramDesc); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processCorrelationDescriptorNaked( + _In_ VOID* pContext, + _In_ ConformanceDescr_T confDesc, + _Inout_ std::ostringstream& oss, + _Inout_ ParamDesc& paramDesc); + + +//--------------------------------------------------------------------------- +UINT __fastcall processFcExpr( + _In_ VOID* pContext, + _In_ RVA_T pExpr, + _In_ ParamDesc& paramDesc, + _In_ ConformanceDescr_T confDesc, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +std::string __fastcall getOperatorType( + _In_ EXPR_OPERATOR oper); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processTransmitRepresentAs( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall getTransmitAsRepresentAsMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize); + + +//--------------------------------------------------------------------------- +UINT getCorrelationDescriptorSize( + _In_ BOOL bRobustFlagWasSet, + _In_ BOOL bHasRangeOnConformance); + + + + +#endif \ No newline at end of file diff --git a/RpcDecompiler/InternalRpcDecompTypeDefs.cpp b/RpcDecompiler/InternalRpcDecompTypeDefs.cpp new file mode 100644 index 0000000..a47df61 --- /dev/null +++ b/RpcDecompiler/InternalRpcDecompTypeDefs.cpp @@ -0,0 +1,222 @@ +#include "internalRpcDecompTypeDefs.h" +#include "internalRpcDecompiler.h" +#include + +// *********************************************** +// +// class used to describe an idl function +// +// *********************************************** + +IdlFunctionDesc::IdlFunctionDesc() : + m_uNbParam (0), + m_bHasRangeOnConformance (FALSE), + m_bHasReturn(FALSE) +{ + +} + + +IdlFunctionDesc::IdlFunctionDesc(std::string strFunctionName) : + m_uNbParam (0), + m_bHasRangeOnConformance (FALSE), + m_bHasReturn(FALSE), + m_strFunctionName(strFunctionName) +{ + +} + + +UINT32 IdlFunctionDesc::getNbParam() const +{ + return m_uNbParam; +} + + +VOID IdlFunctionDesc::setNbParam(UINT32 uNbParam) +{ + m_uNbParam = uNbParam; +} + +VOID IdlFunctionDesc::setHasReturn(BOOL hasReturn) +{ + m_bHasReturn = hasReturn; +} + +VOID IdlFunctionDesc::addParamToList(ParamDesc parameter) +{ + m_listParam.push_back(parameter); +} + +std::list& IdlFunctionDesc::getParamList() +{ + return m_listParam; +} + +BOOL IdlFunctionDesc::hasRangeOnConformance() const +{ + return m_bHasRangeOnConformance; +} +BOOL IdlFunctionDesc::hasReturn() const +{ + return m_bHasReturn; +} + +VOID IdlFunctionDesc::parseWin32ExtHeader(Win2kExt_Header_t* pWin32kExtHeader) +{ + m_bHasRangeOnConformance = pWin32kExtHeader->interpreter_opt_flag2.HasRangeOnConf; + +} + + +// *********************************************** +// +// class TypeToDefine +// +// *********************************************** +/*TypeToDefine::TypeToDefine() +{ + +}*/ + +TypeToDefine::TypeToDefine(const RVA_T rva, const ParamDesc& paramDesc): + m_rva(rva), + //m_uOffset(paramDesc.m_uOffset), + m_fcType(paramDesc.getFcType()), + m_bHasRangeOnConf(paramDesc.hasRangeOnConformance()) +{ + +} + +bool TypeToDefine::operator<( const TypeToDefine& right) +{ + return (this->m_rva < right.m_rva); +} +bool TypeToDefine::operator== ( const TypeToDefine& right) +{ + return (this->m_rva == right.m_rva); +} + + + +// *********************************************** +// +// class ParamDesc +// +// *********************************************** +ParamDesc::ParamDesc(): + m_bString(FALSE), + m_bIn(FALSE), + m_bUnique(FALSE), + m_bOut(FALSE), + m_bReturn(FALSE), + m_uPtrLevel(0), + m_hasRangeOnConformance(FALSE), + m_arrayIsAttributedPointer(FALSE), + m_uStructMemberNum(0), + m_uMemorySize(0), + m_fcType(FC_ZERO) +{ + +} + +ParamDesc::ParamDesc(std::string strTypeName): + m_strTypeName(strTypeName), + m_bString(FALSE), + m_bIn(FALSE), + m_bUnique(FALSE), + m_bOut(FALSE), + m_bReturn(FALSE), + m_arrayIsAttributedPointer(FALSE), + m_uPtrLevel(0), + m_hasRangeOnConformance(FALSE), + m_uStructMemberNum(0), + m_uMemorySize(0) +{ + +} + +ParamDesc::ParamDesc(std::string strTypeName, UINT uStructMemberNum, std::vector vectMemberOffset): + m_strTypeName(strTypeName), + m_bString(FALSE), + m_bIn(FALSE), + m_bUnique(FALSE), + m_bOut(FALSE), + m_bReturn(FALSE), + m_arrayIsAttributedPointer(FALSE), + m_uPtrLevel(0), + m_hasRangeOnConformance(FALSE), + m_uStructMemberNum(uStructMemberNum), + m_uMemorySize(0), + m_vectMembersOffset(vectMemberOffset) +{ + +} + +//ParamDesc::ParamDesc(const TypeToDefine& UnionStructDesc): +// m_strTypeName(), +// m_bString(FALSE), +// m_fcType(UnionStructDesc.getFcType()), +// m_bIn(FALSE), +// m_bUnique(FALSE), +// m_bOut(FALSE), +// m_uPtrLevel(0), +// m_hasRangeOnConformance(UnionStructDesc.getHasRangeOnConformance()), +// m_uStructMemberNum(0), +// m_uMemorySize(0) +//{ +// +//} + + +// used for structures/union in order to report properties such +// as hasRangeOnConformance on structure/union member +void ParamDesc::inheritProperties(_In_ const TypeToDefine& parentTypeDesc) +{ + if(parentTypeDesc.getHasRangeOnConformance()) + { + this->m_hasRangeOnConformance = TRUE; + } +} + + +void ParamDesc::gestDescr(_Inout_ std::string& strDesc) +{ + strDesc = "Todo"; +} + + + + + + + + + + + +void ParamDesc::addConformanceDescr(_In_ ConformanceDescr_T conformanceDescr) +{ + m_listConfDescr.push_back(conformanceDescr); +} + + +LONG ParamDesc::getRelativeOffsetFromFmtString(_In_ RVA_T pFormatString) const +{ + return (LONG)(m_rva - pFormatString); +} + + +void ParamDesc::fillWithParamAttr(_In_ PARAM_ATTRIBUTES paramAttr) +{ + if(paramAttr.IsIn) m_bIn = TRUE; + if(paramAttr.IsOut) m_bOut = TRUE; + + // TODO how to handle simple ref ? + if(paramAttr.IsSimpleRef) m_uPtrLevel++; + //.... +} + + + + diff --git a/RpcDecompiler/InternalsRpcUtils.cpp b/RpcDecompiler/InternalsRpcUtils.cpp new file mode 100644 index 0000000..e501c0a --- /dev/null +++ b/RpcDecompiler/InternalsRpcUtils.cpp @@ -0,0 +1,65 @@ +#include "internalRpcUtils.h" +#include +#include + + +//-------------------------------------------------------------------------- +BOOL __fastcall isStandardCharacter(_In_ const WCHAR wc) +{ + BOOL bResult = FALSE; + + if( ((wc >= L'a') && + (wc <= L'z')) + + || + + ((wc >= L'A') && + (wc <= L'Z')) + + || + + ((wc >= L'0') && + (wc <= L'9')) ) + { + bResult = TRUE; + } + + return (bResult); +} + + +//------------------------------------------------------------------------- +std::string narrow( + _In_ const std::wstring& ws) +{ + //std::vector buffer(ws.size()); + ////std::locale loc("english"); + //std::locale loc; + //std::use_facet< std::ctype > (loc).narrow(ws.data(), ws.data() + ws.size(), '?', &buffer[0]); + + //return std::string(&buffer[0], buffer.size()); + + return std::string(ws.begin(), ws.end()); +} + + +//------------------------------------------------------------------------- +VOID displayPtrLevel( + _In_ const UINT uPtrLevel, + _Inout_ std::ostringstream& oss) +{ + for(UINT i=0; i +#include +#include + +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#endif + +#include +#include +//DBG +#include +//DBG + +#include "..\RpcCommon\RpcView.h" +#include "internalRpcDecompTypeDefs.h" +#include "internalRpcDecompiler.h" +#include "RpcDecompiler.h" +#include "internalRpcUtils.h" +#include "internalTypeTools.h" +#include "IdlFunction.h" +#include "IdlInterface.h" + +#ifdef __cplusplus +extern "C" { +#endif + + //////////////////////////////////////////////////////////////////////////////// + // Function declaration + //////////////////////////////////////////////////////////////////////////////// + VOID* __fastcall RpcDecompilerInit(RpcViewHelper_T* pRpcViewHelper, RpcDecompilerInfo_T* pDecompilerInfo); //returns NULL in case of failure + VOID __fastcall RpcDecompilerUninit(VOID* pRpcDecompilerCtxt); + + + BOOL __fastcall RpcDecompilerPrintAllProcedures(VOID* pRpcDecompilerCtxt); + BOOL __fastcall RpcDecompilerPrintProcedure(VOID* pRpcDecompilerCtxt, UINT ProcIndex); + BOOL __fastcall RpcDecompilerPrintOneProcedure(VOID* pRpcDecompilerCtxt, UINT ProcIndex, std::list& listProcType, std::ostringstream& ossProc); + BOOL __fastcall RpcDecompilerDecodeOneProcedureInlined(VOID* pContext, UINT ProcIndex, IdlFunctionDesc& IdlFunctionDesc, std::list& listProcType); + BOOL __fastcall RpcDecompilerPrintOneProcedureInlined(VOID* pContext, UINT ProcOffset, IdlFunctionDesc& IdlFunctionDesc, std::list& listProcType, std::ostringstream& ossProc); + BOOL __fastcall RpcDecompilerPrintHiddenFUProcedure(VOID* pRpcDecompilerCtxt, UINT * procOffset, std::list& listProcType, std::ostringstream& ossProc); + + BOOL __fastcall RpcDecompilerPrintAllProceduresNew(VOID* pRpcDecompilerCtxt); + + + + VOID __fastcall RpcDecompilerPrintFunctionDbgInfo(VOID* pContext, UINT procIndex, std::ostringstream& oss); + +#pragma comment(lib,"Rpcrt4.lib") + + __declspec(dllexport) RpcDecompilerHelper_T RpcDecompilerHelper= + { + &RpcDecompilerInit, + &RpcDecompilerUninit, + &RpcDecompilerPrintProcedure, + &RpcDecompilerPrintAllProceduresNew, + }; + + + //------------------------------------------------------------------------------ + VOID* __fastcall RpcDecompilerInit(RpcViewHelper_T* pRpcViewHelper, RpcDecompilerInfo_T* pRpcDecompilerInfo) + { + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = NULL; + +#ifdef _DEBUG + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); +#endif + + if (pRpcViewHelper == NULL) goto End; + if (pRpcDecompilerInfo == NULL) goto End; + + //Alloc the private context + pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pRpcViewHelper->RpcAlloc( sizeof(RpcDecompilerCtxt_T) ); + if (pRpcDecompilerCtxt==NULL) goto End; + //Init the private context + pRpcDecompilerCtxt->pRpcViewHelper = pRpcViewHelper; + pRpcDecompilerCtxt->pRpcDecompilerInfo = pRpcDecompilerInfo; + pRpcDecompilerCtxt->pRpcModuleInfo = (RpcModuleInfo_T *) pRpcViewHelper->RpcAlloc( sizeof(RpcModuleInfo_T) ); + if (pRpcDecompilerCtxt->pRpcModuleInfo == NULL) + { + goto End; + } + + pRpcDecompilerCtxt->pRpcModuleInfo->Pid = pRpcDecompilerCtxt->pRpcDecompilerInfo->Pid; + pRpcDecompilerCtxt->pRpcModuleInfo->pModuleBase = pRpcDecompilerCtxt->pRpcDecompilerInfo->pModuleBase; + + + + + // set global var + + // is it a 64 bits application ? + is64B = pRpcDecompilerCtxt->pRpcDecompilerInfo->bIs64Bits; + + // robust flags case + if( pRpcDecompilerCtxt->pRpcDecompilerInfo->NDRVersion >= NDR_VERSION_5_2 ) + { + robustFlagWasSet = TRUE; + } + else + { + robustFlagWasSet = FALSE; + } + + RPC_DEBUG_FN((UCHAR*)"\nRpcDecompilerInit\n"); +End: + return (pRpcDecompilerCtxt); + } + + + //------------------------------------------------------------------------------ + VOID __fastcall RpcDecompilerUninit(VOID* pContext) + { + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T*) pContext; + + if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + + //Free the private the context + RPC_DEBUG_FN((UCHAR*)"\nRpcDecompilerUninit\n"); + RPC_FREE_FN(pRpcDecompilerCtxt->pRpcModuleInfo); + RPC_FREE_FN( pRpcDecompilerCtxt ); + + End: + return; + } + + + + BOOL __fastcall RpcDecompilerPrintProcedure(VOID* pContext, UINT ProcIndex) + { + UNREFERENCED_PARAMETER(ProcIndex); + UNREFERENCED_PARAMETER(pContext); + + return FALSE; + } + + + BOOL __fastcall RpcDecompilerDecodeOneProcedureInlined( + VOID* pContext, + UINT ProcIndex, + IdlFunctionDesc& IdlFunctionDesc, + std::list& listProcType + ) + { + BOOL bResult = FALSE; + RpcDecompilerCtxt_T* pRpcDecompilerCtxt = (RpcDecompilerCtxt_T*)pContext; + + inlinedParam param; + BOOL noMoreParameter = FALSE; + BOOL noMoreParameterBecauseOfReturn = FALSE; + UINT nbOfParameters = 0; + + UNREFERENCED_PARAMETER(listProcType); + + RVA_T pData = pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcFormatInlined[ProcIndex]; + + // check if we have an entry defined in ppProcFormatInlined + if(pData == NULL) + { + RPC_DEBUG_FN("no entry defined for this function in ppProcFormatInlined"); + bResult = FALSE; + + goto END; + } + + // Loop over each parameter and add them to the list + while(!noMoreParameter && !noMoreParameterBecauseOfReturn) + { + ParamDesc parameter; + RPC_GET_PROCESS_DATA(pData, ¶m, sizeof(param)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN("Failed to read proc format string in DecodeOneProcedureInlined"); + } + + // Set parameter flags (in, out) + switch(param.baseParam.bFcTypeParamProperties) + { + case FC_IN_PARAM_BASETYPE: + parameter.setFcType((FC_TYPE)param.baseParam.bFcType); + case FC_IN_PARAM: + parameter.setIsIn(); + break; + case FC_IN_PARAM_NO_FREE_INST: + // TODO + break; + case FC_IN_OUT_PARAM: + parameter.setIsIn(); + parameter.setIsOut(); + break; + case FC_OUT_PARAM: + parameter.setIsOut(); + break; + case FC_RETURN_PARAM_BASETYPE: + parameter.setFcType((FC_TYPE)param.baseParam.bFcType); + case FC_RETURN_PARAM: + parameter.setIsReturn(); + IdlFunctionDesc.setHasReturn(TRUE); + noMoreParameterBecauseOfReturn = TRUE; + // TODO : check in which case this is true + break; + // End of parameters + case FC_END: + case FC_ZERO: + noMoreParameter = TRUE; + break; + default: + bResult = FALSE; + break; + } + + //No parameter left, dont add anything to the list + if(!noMoreParameter) + { + // Jump to next parameter in the format string + if(isSimpleType(parameter.getFcType())) + { + + // Parameter type is right after the param description + parameter.setRva(pData + FIELD_OFFSET(INLINED_PARAM_BASE_T, bFcType)); + pData += sizeof(INLINED_PARAM_BASE_T); + }else{ + //FC_TYPE complexType; + BYTE bfcType; + + // Type given in the type format string + parameter.setRva(pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString + param.complexParam.offset); + + + RPC_GET_PROCESS_DATA(parameter.getRva(), &bfcType, sizeof(bfcType)); + parameter.setFcType((FC_TYPE)bfcType); + + pData += sizeof(INLINED_PARAM_COMPLEX_T); + } + + IdlFunctionDesc.addParamToList(parameter); + nbOfParameters++; + } + } + IdlFunctionDesc.setNbParam(nbOfParameters); + +END: + + return bResult; + } + + + + BOOL __fastcall RpcDecompilerPrintOneProcedureInlined( + VOID* pContext, + UINT ProcOffset, + IdlFunctionDesc& IdlFunctionDesc, + std::list& listProcType, + std::ostringstream& ossProc) + { + BOOL bResult = FALSE; + + UNREFERENCED_PARAMETER(ProcOffset); + + ossProc << "\t"; + + if(!IdlFunctionDesc.hasReturn()) + { + ossProc << "void "; + }else + { + for(auto iter = IdlFunctionDesc.getParamList().begin(); iter != IdlFunctionDesc.getParamList().end(); iter++) + { + if (iter->isReturn()) + { + rpcDumpType(pContext, *iter, listProcType, ossProc); + } + } + } + + ossProc << IdlFunctionDesc.getFunctionName() << " "; + ossProc << "("; + UINT32 i = 0; + for(auto iter = IdlFunctionDesc.getParamList().begin(); iter != IdlFunctionDesc.getParamList().end(); iter++) + { + ossProc << std::endl << "\t\t"; + + if (!(iter->isReturn())) + { + if(iter->isIn()) + { + ossProc << "[in]"; + } + if(iter->isOut()) + { + ossProc << "[out]"; + } + + ossProc << " "; + bResult = rpcDumpType(pContext, *iter, listProcType, ossProc); + ossProc << " arg_" << i; + // If this is not the last parameter (list contains all parameters including returned value) + if(i != (IdlFunctionDesc.getNbParam() - 2)) + { + ossProc << ","; + }// else nothing to do + + i++; + } + } + ossProc << ");\n"; + return bResult; + } + + + //------------------------------------------------------------------------------ + BOOL __fastcall RpcDecompilerPrintOneProcedure( + VOID* pContext, + UINT ProcIndex, + std::list& listProcType, + std::ostringstream& ossProc) + { + UINT formatStringOffset = 0; + UINT paramSizeInBytes = RPC_DECOMPILER_INVALID_PARAM_SIZE; + BOOL bResult = FALSE; + RpcDecompilerCtxt_T* pRpcDecompilerCtxt = (RpcDecompilerCtxt_T*)pContext; + + UINT paramOffset = 0; + UINT numParam = 0; + BOOL isReturnParam = FALSE; + BOOL nextIsReturnParam = FALSE; + UINT dummy; + + IdlFunctionDesc IdlFunctionDesc; + + + if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString == NULL) goto End; + + + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->pFormatStringOffsetTable==NULL) + { + formatStringOffset = 0; + } + else + { + formatStringOffset = pRpcDecompilerCtxt->pRpcDecompilerInfo->pFormatStringOffsetTable[ProcIndex]; + } + + // carriage return before display function + //ossProc << "\t/* Function 0x" << std::hex << ProcIndex<< " */"<< std::endl; + ossProc << std::endl; + ossProc << "[helpstring(\"RVA: 0x" << std::hex << pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcAddressTable[ProcIndex] << "\")]" << std::endl; + RpcDecompilerPrintFunctionDbgInfo(pContext, ProcIndex, ossProc); + + + //todo + bResult = RpcDecompilerDecodeAndPrintPrototypeReturnType( + /* in */ pRpcDecompilerCtxt, + /* in */ formatStringOffset, + /* out */ ¶mOffset, + /* out */ &dummy, + /* out */ IdlFunctionDesc, + /* in/out */listProcType, + /* in/out */ ossProc); + + if (bResult == FALSE) goto End; + + bResult = RpcDecompilerPrintPrototypeName( + /* in */ pRpcDecompilerCtxt, + /* in */ ProcIndex, + /* in/out */ ossProc); + + if (bResult == FALSE) goto End; + + RPC_DEBUG_FN((UCHAR*)"\nRpcDecompilerPrintProcedure: RpcDecompilerPrintPrototypeName returned nbParamToPrint = %d\n", IdlFunctionDesc.getNbParam()); + + + if(IdlFunctionDesc.getNbParam() == 0) + { + //No parameter to be printed + ossProc << " void "; + } + + + //Print each parameter + while( (numParam < IdlFunctionDesc.getNbParam()) ) + { + RPC_DEBUG_FN((UCHAR*)"\nRpcDecompilerPrintProcedure: numParam = 0x%x on total to print = 0x%x\n", numParam, IdlFunctionDesc.getNbParam()); + + bResult = RpcDecompilerGetReturnParamInfo(/* in */ pRpcDecompilerCtxt, /* in */ paramOffset, /* in */ paramDescrOif, /* out */ &isReturnParam); + if (bResult == FALSE) goto End; + + if( ! isReturnParam) + { + //Print the parameter + bResult = RpcDecompilerPrintParam( + /* in */ pRpcDecompilerCtxt, + /* in */ paramOffset, + /* in */ paramDescrOif, + /* out */ ¶mSizeInBytes, + /* in */ IdlFunctionDesc, + listProcType, + ossProc); //TODO : decompile paramDescrOi... + + if (bResult == FALSE || paramSizeInBytes == RPC_DECOMPILER_INVALID_PARAM_SIZE) + { + displayErrorMessage(ossProc, "RpcDecompilerPrintOneProcedure : unable to decode param"); + goto End; + } + } + else + { + paramSizeInBytes = OIF_PARAM_SIZE; //TODO : traiter le cas où codage pas OIF + } + paramOffset += paramSizeInBytes;//paramSizeInBytes; + numParam++; + RPC_DEBUG_FN((UCHAR*)"\nRpcDecompilerPrintProcedure: paramOffset = %d, numParam = %d\n", paramOffset, numParam); + + //Is there one additionnal parameter to be printed ? + if ( (! isReturnParam) && (numParam < IdlFunctionDesc.getNbParam()) ) + { + //The last parameter has been printed because it was not a return parameter + //There is still at least 1 parameter to be printed + bResult = RpcDecompilerGetReturnParamInfo(/* in */ pRpcDecompilerCtxt, /* in */ paramOffset, /* in */ paramDescrOif, /* out */ &nextIsReturnParam); + if (bResult == FALSE) goto End; + + if (! nextIsReturnParam) + { + //The next parameter will have to be printed because it is not a return parameter + ossProc << ", "; + } + + } + }//while(numParam <= IdlFunctionDesc.getNbParam()); + + + // Print the end of the procedure prototype + ossProc<<");"<& listProcType, std::ostringstream& ossProc) + { + UINT paramSizeInBytes = RPC_DECOMPILER_INVALID_PARAM_SIZE; + BOOL bResult = FALSE; + RpcDecompilerCtxt_T* pRpcDecompilerCtxt = (RpcDecompilerCtxt_T*)pContext; + + UINT paramOffset = 0; + UINT numParam = 0; + BOOL isReturnParam = FALSE; + BOOL nextIsReturnParam = FALSE; + UINT sizeOfProcDescr = 0; + + IdlFunctionDesc IdlFunctionDesc; + + + if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString == NULL) goto End; + + RVA_T pFunction = pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + *procOffset; + // carriage return before display function + //ossProc << "\t/* Function 0x" << std::hex << ProcIndex<< " */"<< std::endl; + ossProc << std::endl; + //RpcDecompilerPrintFunctionDbgInfo(pContext, *procOffset, ossProc); + ossProc << "\t /* Function index : 0x" << std::hex << *procOffset; + ossProc << "\t Module Base : 0x" << (unsigned long) pRpcDecompilerCtxt->pRpcDecompilerInfo->pModuleBase; + ossProc << "\t RVA of proc in format string : 0x" << (unsigned long) ((UINT64)pFunction - pRpcDecompilerCtxt->pRpcDecompilerInfo->pModuleBase); + ossProc << " */"<pRpcDecompilerInfo->pModuleBase; + RVA_T rvaFunction = pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcAddressTable[procIndex]; + + oss << "\t /* Function index : 0x" << std::hex << procIndex; + oss << "\t Module Base : 0x" << moduleBase; + oss << "\t RVA : 0x" << rvaFunction; + oss << " */"<pRpcViewHelper == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) goto End; + + + if ( UuidToStringA(&pRpcDecompilerCtxt->pRpcDecompilerInfo->pIfId->Uuid,&pUuidString) != RPC_S_OK ) + { + goto End; + } + oss<< "[\nuuid(" << pUuidString; + oss<<"),\nversion("<< pRpcDecompilerCtxt->pRpcDecompilerInfo->pIfId->VersMajor; + oss<<"."<pRpcDecompilerInfo->pIfId->VersMinor <<"),\n]\n"; +/* + RPC_DEBUG_FN((UCHAR*)"[\nuuid(%s),\nversion(%u.%u),\n]\n", + pUuidString, + pRpcDecompilerCtxt->pRpcDecompilerInfo->pIfId->SyntaxVersion.MajorVersion, + pRpcDecompilerCtxt->pRpcDecompilerInfo->pIfId->SyntaxVersion.MinorVersion + ); +*/ + +End: + if (pUuidString != NULL) RpcStringFreeA(&pUuidString); + return; + } + + //------------------------------------------------------------------------------ + VOID RpcPrintInformation(VOID* pContext, std::ostringstream& oss) + { + RpcDecompilerCtxt_T* pRpcDecompilerCtxt = (RpcDecompilerCtxt_T*)pContext; + + if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) goto End; + + + //TODO : fonction de lecture de tous les headers de proc pour lister tous les handles et ecrire le fichier ACF + oss << "\n/*****************************************************************"; + oss << "\n * Do not forget to write the ACF file using the following model:"; + oss << "\n // ACF file header"; + oss << "\n ["; + oss << "\n \t// List here the handles and other specific options.\n"; + oss << "\n ]\n"; + oss << "\n // ACF file body"; + //oss << "\n interface "<< narrow(std::wstring(DEFAULT_IF_NAME)) <<"\n {\n }"; + oss << "\n interface "<< DEFAULT_IF_NAME <<"\n {\n }"; + oss << "\n\n *"; + oss << "\n *****************************************************************/\n\n"; + +End:; + + } + + BOOL __fastcall RpcDecompilerPrintAllProceduresInlined(VOID* pContext) + { + UNREFERENCED_PARAMETER(pContext); + return FALSE; + /* */ + } + + //#define DBG_BUF_SIZE 512 + + //------------------------------------------------------------------------------ + BOOL __fastcall RpcDecompilerPrintAllProcedures(VOID* pContext) + { + + RpcDecompilerCtxt_T* pRpcDecompilerCtxt = (RpcDecompilerCtxt_T*)pContext; + UINT uProcIdx; + std::list listProcType; + std::ostringstream ossHeader; + std::ostringstream ossProc; + std::ostringstream ossType; + //BYTE dbgBuf[DBG_BUF_SIZE]; + + if (pRpcDecompilerCtxt == NULL) + { + return FALSE; + } + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) + { + return FALSE; + } + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) + { + return FALSE; + } + + RPC_DEBUG_FN((UCHAR*)"RpcDecompilerPrintAllProcedures\n"); + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString == NULL) + { + RPC_DEBUG_FN((UCHAR*)"Cannot decompile inlined stub!\n"); + //return FALSE; + } + + + //// + + //dump proc index offset : + + //ossHeader << "proc index offset "<pRpcDecompilerInfo->NumberOfProcedures; i++) + //{ + // ossHeader<<"proc "<pRpcDecompilerInfo->pFormatStringOffsetTable[i] << std::endl; + //} + // + //// Dump proc type and proc format string + //RPC_GET_PROCESS_DATA( + // pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString, + // dbgBuf, + // DBG_BUF_SIZE + // ); + + //ossHeader<<"ProcFormatString : "<pRpcDecompilerInfo->pTypeFormatString ), + // dbgBuf, + // DBG_BUF_SIZE + // ); + + //ossHeader<<"TypeFormatString : "< + + + RpcPrintInformation(pContext, ossHeader); + + RpcDecompilerPrintProlog(pContext, ossHeader); + + + // display Interface name + + ossHeader << "\n\ninterface "; + // is there a default if name defined ? + if(wcslen(pRpcDecompilerCtxt->pRpcDecompilerInfo->InterfaceName) > 0) + { + size_t szConverted = 0; + size_t sz = wcslen(pRpcDecompilerCtxt->pRpcDecompilerInfo->InterfaceName) + 1; + char* pTmp = (char*)pRpcDecompilerCtxt->pRpcViewHelper->RpcAlloc(sz); + + if(pTmp != NULL) + { + ZeroMemory(pTmp, sz); + + wcstombs_s(&szConverted, pTmp, sz, pRpcDecompilerCtxt->pRpcDecompilerInfo->InterfaceName, sz); + + ossHeader << pTmp; + pRpcDecompilerCtxt->pRpcViewHelper->RpcFree(pTmp); + } + + //ossHeader << narrow(std::wstring(pRpcDecompilerCtxt->pRpcDecompilerInfo->InterfaceName)) <<" \n{\n"; + + + /*RPC_DEBUG_FN((UCHAR*) "[ERROR] an error has occured while decompilating proc : %d \n",uProcIdx); + ossProc << "[ERROR] an error has occured while decompilating proc : "<pRpcDecompilerInfo->pFormatStringOffsetTable != NULL) + // { + + //Decompile each proc + for(uProcIdx = 0; uProcIdx < pRpcDecompilerCtxt->pRpcDecompilerInfo->NumberOfProcedures; uProcIdx++) + { + + // select decompile method + //if(pRpcDecompilerCtxt->pRpcDecompilerInfo->pbFunctionInterpreted[uProcIdx] == TRUE) + //{ + // interpreted case + if ( RpcDecompilerPrintOneProcedure(pContext, uProcIdx, listProcType, ossProc) == FALSE ) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] an error has occured while decompiling proc : %d \n",uProcIdx); + ossProc << "[ERROR] an error has occured while decompiling proc : "<pRpcViewHelper->pContext,(const char*)ossHeader.str().c_str()); + RPC_PRINT_FN(pRpcDecompilerCtxt->pRpcViewHelper->pContext,(const char*)ossType.str().c_str()); + RPC_PRINT_FN(pRpcDecompilerCtxt->pRpcViewHelper->pContext,(const char*)ossProc.str().c_str()); + + + return TRUE; + }//end RpcDecompilerPrintAllProcedures + + BOOL __fastcall RpcDecompilerPrintAllProceduresNew(VOID* pContext) + { + RpcDecompilerCtxt_T* pRpcDecompilerCtxt = (RpcDecompilerCtxt_T*)pContext; + std::ostringstream ossIf; + DECOMP_STATUS status; + std::string strIfname; + + if (pRpcDecompilerCtxt == NULL) + { + return FALSE; + } + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) + { + return FALSE; + } + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) + { + return FALSE; + } + + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString == NULL) + { + RPC_DEBUG_FN((UCHAR*)"Cannot decompile inlined stub!\n"); + //return FALSE; + } + + + // convert interface name to std::string + if(wcslen(pRpcDecompilerCtxt->pRpcDecompilerInfo->InterfaceName) == 0) + { + strIfname = DEFAULT_IF_NAME; + } + else + { + strIfname = narrow(std::wstring(pRpcDecompilerCtxt->pRpcDecompilerInfo->InterfaceName)); + } + + + // Create idlInterface used to decode interface + IdlInterface idlIf(strIfname, *(pRpcDecompilerCtxt->pRpcDecompilerInfo->pIfId), pRpcDecompilerCtxt->pRpcDecompilerInfo->NumberOfProcedures); + + status = idlIf.decode(pContext); + + if(status != DS_SUCCESS) + { + RPC_ERROR_FN("decompilation failed\n"); + } + ossIf << idlIf; + // and then dump content + RPC_PRINT_FN(pRpcDecompilerCtxt->pRpcViewHelper->pContext,ossIf.str().c_str()); + + return TRUE; + }//end RpcDecompilerPrintAllProcedures + + + //------------------------------------------------------------------------------ + BOOL WINAPI DllMain(HANDLE hInstDLL, DWORD dwReason, LPVOID lpvReserved) + { + UNREFERENCED_PARAMETER(hInstDLL); + UNREFERENCED_PARAMETER(dwReason); + UNREFERENCED_PARAMETER(lpvReserved); + //nothing to do here! + return (TRUE); + } + +#ifdef __cplusplus +} +#endif diff --git a/RpcDecompiler/RpcDecompiler.def b/RpcDecompiler/RpcDecompiler.def new file mode 100644 index 0000000..3fff369 --- /dev/null +++ b/RpcDecompiler/RpcDecompiler.def @@ -0,0 +1,2 @@ +EXPORTS + RpcDecompilerHelper \ No newline at end of file diff --git a/RpcDecompiler/RpcDecompiler.h b/RpcDecompiler/RpcDecompiler.h new file mode 100644 index 0000000..caea6e5 --- /dev/null +++ b/RpcDecompiler/RpcDecompiler.h @@ -0,0 +1,85 @@ +#ifndef _RPC_DECOMPILER_H_ +#define _RPC_DECOMPILER_H_ + +#include +#include + +#include "..\RpcCommon\RpcView.h" + +#define RPC_DECOMPILER_EXPORT_SYMBOL "RpcDecompilerHelper" + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Type definitions +//////////////////////////////////////////////////////////////////////////////// + + + +typedef struct _RpcDecompilerInfo_T{ + UINT Pid; + RPC_IF_ID* pIfId; + UINT64 pModuleBase; + UINT NDRVersion; + UINT MIDLVersion; + UINT NDRFags; + UINT NumberOfProcedures; + RVA_T* ppProcAddressTable; //A table containing the address of each function + RVA_T* ppDispatchProcAddressTable; + USHORT* pFormatStringOffsetTable; //A table containing the FormatStringOffset of each function + WCHAR** ppProcNameTable; //A table containing the name of each function if possible or a NULL pointer else + RVA_T/*UCHAR* */ pTypeFormatString; //Just a pointer to the type format string: must be read using + RVA_T/*UCHAR* */ pProcFormatString; + //RVA_T /*VOID* */ pExprInfo; // FC_EXPR : to be removed (replaced by following 2 elements) + RVA_T pExprOffset; + RVA_T pExprFormatString; + RVA_T apfnExprEval; // Callbacks + BOOL bIs64Bits; + WCHAR InterfaceName[RPC_MAX_LENGTH]; + RPC_SYNTAX_IDENTIFIER* pSyntaxId; + BOOL bIsInlined; + RVA_T* ppProcFormatInlined; + BOOL* pbFunctionInterpreted; // array containing for every function a boolean indicating if function is interpreted + //... +}RpcDecompilerInfo_T; + +typedef VOID* (__fastcall* RpcDecompilerInitFn_T)(RpcViewHelper_T* pRpcViewHelper, RpcDecompilerInfo_T* pDecompilerInfo); //returns NULL in case of failure +typedef VOID (__fastcall* RpcDecompilerUninitFn_T)(VOID* pRpcDecompilerCtxt); +typedef BOOL (__fastcall* RpcDecompilerPrintProcedureFn_T)(VOID* pRpcDecompilerCtxt, UINT ProcIndex); +typedef BOOL (__fastcall* RpcDecompilerPrintAllProceduresFn_T)(VOID* pRpcDecompilerCtxt); + +typedef struct _RpcDecompilerHelper_T{ + RpcDecompilerInitFn_T RpcDecompilerInitFn; + RpcDecompilerUninitFn_T RpcDecompilerUninitFn; + RpcDecompilerPrintProcedureFn_T RpcDecompilerPrintProcedureFn; + RpcDecompilerPrintAllProceduresFn_T RpcDecompilerPrintAllProceduresFn; +}RpcDecompilerHelper_T; + + +//////////////////////////////////////////////////////////////////////////////// +// STATUS DECLARATION +//////////////////////////////////////////////////////////////////////////////// +typedef enum _DECOMP_STATUS +{ + DS_SUCCESS = 0, + DS_ERR , + DS_ERR_UNABLE_TO_READ_MEMORY , + DS_ERR_INVALID_DATA , + DS_ERR_INVALID_PARAM , + DS_ERR_FUNCTION_NOT_PROPERLY_INITIALIZED , + DS_ERR_IN_SIMPLE_TYPE , + DS_ERR_IN_COMPLEX_TYPE , + DS_ERR_IN_DECODE_PROC_HEADER , + DS_ERR_IN_DECODE_PROC_PARAMS , + DS_ERR_INVALID_INDEX , + DS_ERR_UNABLE_TO_DECODE_COMPLEX_TYPE , +}DECOMP_STATUS; + + +#ifdef __cplusplus +} +#endif + +#endif//_RPC_DECOMPILER_H_ \ No newline at end of file diff --git a/RpcDecompiler/RpcDecompilerResource.rc b/RpcDecompiler/RpcDecompilerResource.rc new file mode 100644 index 0000000..6da3493 --- /dev/null +++ b/RpcDecompiler/RpcDecompilerResource.rc @@ -0,0 +1,90 @@ +// Microsoft Visual C++ generated resource script. +// +#include + +#define APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Français (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +#ifdef _WIN32 +//LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +1 VERSIONINFO + FILEVERSION _RPCVIEW_VERSION_MAJOR_,_RPCVIEW_VERSION_MINOR_,_RPCVIEW_VERSION_RELEASE_,0 + PRODUCTVERSION _RPCVIEW_VERSION_MAJOR_,_RPCVIEW_VERSION_MINOR_,_RPCVIEW_VERSION_RELEASE_,0 + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "RpcView" + VALUE "FileDescription", "MS RPC decompilation module" + VALUE "InternalName", "RpcView" + VALUE "LegalCopyright", "Copyright © 2012-2017 RpcView Team" + VALUE "LegalTrademarks", "Copyright (C) 2012-2017 RpcView Team" + VALUE "OriginalFilename", "RpcDecompiler.dll" + VALUE "ProductName", "RpcDecompiler" + VALUE "ProductVersion", _RPCVIEW_PRODUCT_VERSION_ + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.\0" +END + + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Français (France) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/RpcDecompiler/internalComplexTypesArrays.cpp b/RpcDecompiler/internalComplexTypesArrays.cpp new file mode 100644 index 0000000..73f2507 --- /dev/null +++ b/RpcDecompiler/internalComplexTypesArrays.cpp @@ -0,0 +1,1113 @@ +#include "..\RpcCommon\RpcView.h" +#include "internalRpcDecompTypeDefs.h" +#include "internalComplexTypesArrays.h" +#include "internalTypeTools.h" +#include "internalComplexTypesPointers.h" +#include "internalRpcDecompiler.h" +#include "InternalComplexTypesMisc.h" + +#include + + +BOOL __fastcall processFixedSizeArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + ArrayDescrHeader_U ArrayToDecode; + UINT ArrayMemorySize = 0; + INT16 OffsetToEmbeddedElement = 0; + + INT fixedArraySizes[30]; + UINT fixedArraySizesIndex = 0; + UINT i = 0; + + // Variables related to embedded element (if any) + StructMemberLayout_U ElementMemberLayoutToDecode; + RVA_T pElementDescr = 0; + + SimpleStructHeader_t embeddedStruct; + + BYTE elementToDecode; + SMFixedSizedArrayHeader_t SMArray; + LGFixedSizedArrayHeader_t LGArray; + + switch(fcType) + { + case FC_SMFARRAY: + RPC_GET_PROCESS_DATA( + pType, + &ArrayToDecode, + sizeof(SMFixedSizedArrayHeader_t) + ); + ArrayMemorySize = ArrayToDecode.smFixedSizedArrayHdr.totalSize; + pType += sizeof(SMFixedSizedArrayHeader_t); + break; + case FC_LGFARRAY: + RPC_GET_PROCESS_DATA( + pType, + &ArrayToDecode, + sizeof(LGFixedSizedArrayHeader_t) + ); + ArrayMemorySize = ArrayToDecode.lgFixedSizedArrayHdr.totalSize; + pType += sizeof(LGFixedSizedArrayHeader_t); + break; + default: + bResult = FALSE; + goto End; + } + + + //TODO Check for Pointer_layout presence + // -->Write code here<-- + //END TODO + + RPC_GET_PROCESS_DATA( + pType, + &ElementMemberLayoutToDecode, + sizeof(StructMemberLayout_U) + ); + + fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize; + pElementDescr = pType; + if( ElementMemberLayoutToDecode.baseTypeMemberLayout == FC_EMBEDDED_COMPLEX ) + { + // We need the offset of the embedded structure to actually know what is inside the struct + // Offset is positive if the struct is declared after the array we're analyzing; negative otherwise + OffsetToEmbeddedElement = ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription; + pType += sizeof(StructNonBaseTypeMemberLayout_t); + pElementDescr = pType + OffsetToEmbeddedElement - sizeof(ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription); + + RPC_GET_PROCESS_DATA( + pElementDescr, + &elementToDecode, + sizeof(BYTE) + ); + + + // Processing multi-dimensional array + while((elementToDecode & 0xFF) == FC_SMFARRAY || (elementToDecode & 0xFF) == FC_LGFARRAY){ + if((elementToDecode & 0xFF) == FC_SMFARRAY){ + + RPC_GET_PROCESS_DATA( + pElementDescr, + &SMArray, + sizeof(SMFixedSizedArrayHeader_t) + ); + + ArrayMemorySize = SMArray.totalSize; + pElementDescr += sizeof(SMFixedSizedArrayHeader_t); + + }else{ + if((elementToDecode & 0xFF) == FC_LGFARRAY){ + + RPC_GET_PROCESS_DATA( + pElementDescr, + &LGArray, + sizeof(LGFixedSizedArrayHeader_t) + ); + ArrayMemorySize = LGArray.totalSize; + pElementDescr += sizeof(LGFixedSizedArrayHeader_t); + } + + } + + fixedArraySizes[fixedArraySizesIndex] /= ArrayMemorySize; + fixedArraySizesIndex++; + fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize; + + + RPC_GET_PROCESS_DATA( + pElementDescr, + &ElementMemberLayoutToDecode, + sizeof(StructMemberLayout_U) + ); + if(ElementMemberLayoutToDecode.baseTypeMemberLayout == FC_EMBEDDED_COMPLEX){ + OffsetToEmbeddedElement = ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription; + pElementDescr += sizeof(StructNonBaseTypeMemberLayout_t); + pElementDescr = pElementDescr + OffsetToEmbeddedElement - sizeof(ElementMemberLayoutToDecode.nonBaseTypeMemberLayout.offsetToDescription); + RPC_GET_PROCESS_DATA( + pElementDescr, + &elementToDecode, + sizeof(BYTE) + ); + }else{ + elementToDecode = ElementMemberLayoutToDecode.baseTypeMemberLayout; + } + } // end while + }else{ // ElementMemberLayoutToDecode.baseTypeMemberLayout == FC_EMBEDDED_COMPLEX + + RPC_GET_PROCESS_DATA( + pType, + &elementToDecode, + sizeof(BYTE) + ); + } + + ParamDesc.setRva(pElementDescr); + + if(isSimpleType((FC_TYPE)ElementMemberLayoutToDecode.baseTypeMemberLayout)) + { + bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processFixedSizeArray : error while dumping simpleType"); + return FALSE; + } + fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize / getSimpleTypeMemorySize((FC_TYPE)elementToDecode); + fixedArraySizesIndex++; + } // isSimpleType(ElementMemberLayoutToDecode.baseTypeMemberLayout + else{ + //UINT OffstetInTypeFormatString = 0; + RPC_GET_PROCESS_DATA( + pElementDescr, + &embeddedStruct, + sizeof(SimpleStructHeader_t) + ); + fixedArraySizes[fixedArraySizesIndex] = ArrayMemorySize / embeddedStruct.memory_size; + fixedArraySizesIndex++; + + bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processFixedSizeArray : error while dumping non simple type"); + return FALSE; + } + + + // store array memory size + //ParamDesc.setMemorySize(ArrayMemorySize); + } + + for(i=0; i& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + ProcFormatStringParam_U paramToPrint; + CorrelationDescriptor_U correlationDescriptorToRead; + + ConformanceDescr_T confDesc; + + BYTE elementType; + StructNonBaseTypeMemberLayout_t elementDescription; + + BYTE correlationType; + BYTE correlationOperator; + short correlationOffset; + NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0}; + + std::ostringstream rangeStr; + + UNREFERENCED_PARAMETER(fcType); + +#ifdef DBG_DECOMP + oss << " /* FC_CARRAY */"; +#endif + + RPC_GET_PROCESS_DATA( + pType, + ¶mToPrint, + sizeof(paramToPrint) + ); + + pType += sizeof(ConformantArrayHeader_t); + + // Get correlation descriptor offset in the type format string + RPC_GET_PROCESS_DATA( + pType, + &correlationDescriptorToRead, + sizeof(correlationDescriptorToRead) // + ); + + confDesc.pType = pType; + + if(robustFlagWasSet){ + correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescRobust.offset; + correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags; + + }else{ + correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset; + } + + if(robustFlagWasSet) + { + pType += sizeof(CorrelationDescriptorRobust_t); + } + else + { + pType += sizeof(CorrelationDescriptorNonRobust_t); + } + + + confDesc.confType = size_is; + confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust; + + + bResult = processCorrelationDescriptor(pContext, confDesc, oss,ParamDesc); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantArray : correlation descriptor not correctly decoded"); + return FALSE; + } + + + + // Handle undocumented range attribute on conformance + if(ParamDesc.hasRangeOnConformance() )//&& confDesc.corrDesc.correlation_type != FC_CONSTANT_CONFORMANCE && confDesc.corrDesc.correlation_type != FC_POINTER_CONFORMANCE) + { + bResult = ProcessArrayRange(pContext, pType, ParamDesc, rangeStr); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantArray : range on conformance not correctly decoded"); + return FALSE; + } + oss << rangeStr.str(); + pType += sizeof(Range_t); + } + + + + + RPC_GET_PROCESS_DATA( + pType, + &elementType, + sizeof(BYTE)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to get process data \n"); + return FALSE; + } + + // + // check if a pointer layout is present + // Warning : if a pointer layout is present it's skipped since this information seems to be redundant + // this should be investigated + // + if(elementType == FC_PP) + { + pType += sizeof(BYTE); + + // read until FC_END is found + while(TRUE) + { + RPC_GET_PROCESS_DATA( + pType, + &elementType, + sizeof(BYTE)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to get process data \n"); + return FALSE; + } + + pType ++ ; + + if(elementType == FC_END) + { + break; + } + } + } + + + RPC_GET_PROCESS_DATA( + pType, + &elementType, + sizeof(BYTE)); + + if(elementType == FC_EMBEDDED_COMPLEX){ + RPC_GET_PROCESS_DATA( + pType, + &elementDescription, + sizeof(StructNonBaseTypeMemberLayout_t) + ) + pType += elementDescription.offsetToDescription + sizeof(elementDescription.offsetToDescription); + } + + // ParamDesc.setuOffset((UINT)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString)); + ParamDesc.setRva(pType); + + // Write the type of array + if(rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss) == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to dump type \n"); + return FALSE; + } + + + + // + // proposition : ne pas ajouter de [] si le tableau est préfixé par un pointeur + if(ParamDesc.getuPtrLevel() == 0) + { + oss << "[]"; + } + else + { +#ifdef DBG_DECOMP + oss<<"/*[] CONFORMANT_ARRAY*/"; +#endif + } + + bResult = TRUE; + + return bResult; +} + + +BOOL __fastcall processConformantVaryingArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + CorrelationDescriptor_U correlationDescriptorToRead; + + BYTE elementType = 0; + StructNonBaseTypeMemberLayout_t elementDescription; + + BYTE correlationType; + BYTE correlationOperator; + short correlationOffset; + NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0}; + ConformanceDescr_T confDesc; + + std::ostringstream rangeStr; + + UNREFERENCED_PARAMETER(fcType); + + oss << " /* [DBG] FC_CVARRAY */"; + + pType += sizeof(ConformantVaryingArrayHeader_t); + + // Read the first correlation descriptor + RPC_GET_PROCESS_DATA( + pType, + &correlationDescriptorToRead, + sizeof(correlationDescriptorToRead) // + ); + + if(robustFlagWasSet){ + correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescRobust.offset; + correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags; + + }else{ + correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset; + } + + if(robustFlagWasSet) + { + pType += sizeof(CorrelationDescriptorRobust_t); + } + else + { + pType += sizeof(CorrelationDescriptorNonRobust_t); + } + + confDesc.confType = size_is; + confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust; + + + bResult = processCorrelationDescriptor(pContext, confDesc, oss,ParamDesc); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantVaryingArray : first correlation descriptor not correctly decoded"); + return FALSE; + } + + if(ParamDesc.hasRangeOnConformance() )//&& confDesc.corrDesc.correlation_type != FC_CONSTANT_CONFORMANCE && confDesc.corrDesc.correlation_type != FC_POINTER_CONFORMANCE) + { + bResult = ProcessArrayRange(pContext, pType, ParamDesc, rangeStr); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantArray : range on conformance not correctly decoded"); + return FALSE; + } + + oss << rangeStr.str(); + pType += sizeof(Range_t); + } + + // Read the second correlation descriptor + RPC_GET_PROCESS_DATA( + pType, + &correlationDescriptorToRead, + sizeof(correlationDescriptorToRead) // + ); + + if(robustFlagWasSet){ + correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescRobust.offset; + correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags; + }else{ + correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset; + } + + if(robustFlagWasSet) + { + pType += sizeof(CorrelationDescriptorRobust_t); + } + else + { + pType += sizeof(CorrelationDescriptorNonRobust_t); + } + + confDesc.confType = length_is; // todo : cas du first_is + confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust; + + + bResult = processCorrelationDescriptor(pContext, confDesc, oss,ParamDesc); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantVaryingArray : second correlation descriptor not correctly decoded"); + return FALSE; + } + + if(ParamDesc.hasRangeOnConformance()) + { + pType += sizeof(Range_t); + } + + + + // + // check if a pointer layout is present + // Warning : if a pointer layout is present it's skipped since this information seems to be redundant + // this should be investigated + // + + RPC_GET_PROCESS_DATA( + pType, + &elementType, + sizeof(BYTE) // + ); + + if(elementType == FC_PP) + { + + pType += sizeof(BYTE); + + // read until FC_END is found + while(TRUE) + { + RPC_GET_PROCESS_DATA( + pType, + &elementType, + sizeof(BYTE)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processConformantArray : unable to get process data \n"); + return FALSE; + } + + pType ++ ; + + if(elementType == FC_END) + { + break; + } + + + } + + } + + + RPC_GET_PROCESS_DATA( + pType, + &elementType, + sizeof(BYTE)); + + + if(elementType == FC_EMBEDDED_COMPLEX){ + RPC_GET_PROCESS_DATA( + pType, + &elementDescription, + sizeof(StructNonBaseTypeMemberLayout_t) + ) + pType += elementDescription.offsetToDescription + sizeof(elementDescription.offsetToDescription); + } + + ///ParamDesc.setuOffset((UINT)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString)); + ParamDesc.setRva(pType); + + + bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss); // Write the type of array + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processConformantVaryingArray : dump type failed"); + return FALSE; + } + + // + // proposition : ne pas ajouter de [] si le tableau est préfixé par un pointeur + if(ParamDesc.getuPtrLevel() == 0) + { + oss << "[]"; + } + else + { + oss<<"/*[] CONFORMANT_ARRAY*/"; + } + + bResult = TRUE; + + return bResult; + +} + + +BOOL __fastcall processVaryingArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + CorrelationDescriptor_U correlationDescriptorToRead; + + UINT argNbr = 0; + INT size = 0; + + ArrayDescrHeader_U ArrayToDecode; + UINT ArraySize; + + BYTE correlationType; + BYTE correlationOperator; + short correlationOffset; + NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0}; + + BYTE value; + + UNREFERENCED_PARAMETER(fcType); + + RPC_GET_PROCESS_DATA( + pType, + &value, + sizeof(BYTE) // + ); + + switch(value){ + case FC_LGVARRAY: + RPC_GET_PROCESS_DATA( + pType, + &ArrayToDecode, + sizeof(LGVaryingArrayHeader_t) + ); + ArraySize = ArrayToDecode.lgVaryingArrayHdr.numberOfElements; + pType += sizeof(LGVaryingArrayHeader_t); + break; + case FC_SMVARRAY: + RPC_GET_PROCESS_DATA( + pType, + &ArrayToDecode, + sizeof(SMVaryingArrayHeader_t) + ); + ArraySize = ArrayToDecode.smVaryingArrayHdr.numberOfElements; + pType += sizeof(SMVaryingArrayHeader_t); + break; + default: + RPC_DEBUG_FN((UCHAR*)"Error in PrintParamVaryingArray : bad array type"); + goto End; + } + + // Read the variance correlation descriptor + RPC_GET_PROCESS_DATA( + pType, + &correlationDescriptorToRead, + sizeof(correlationDescriptorToRead) // + ); + + if(robustFlagWasSet){ + correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescRobust.offset; + correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags; + + }else{ + correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset; + } + + pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance()); + + if(is64B) argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_64B; + else argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_32B; + + // Only FC_CONSTANT_CONFORMANCE handled as of now. + switch(correlationType & 0xF0){ + case FC_CONSTANT_CONFORMANCE: + size = ((correlationOperator << 16) | correlationOffset) & 0xFFFFFF; + break; + default: + break; + } + switch(correlationOperator){ + case FC_CALLBACK: // Callback called to evaluate expression given to last_is(). Not handled yet + oss<<"[/*TODO first_is and/or last_is() */]"; + break; + case FC_DEREFERENCE: + oss<<"[length_is( * arg_"<pRpcDecompilerInfo->pTypeFormatString)); + ParamDesc.setRva(pType); + + bResult = rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss); // Write the type of array + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processVaryingArray : rpcDumpType failed"); + return FALSE; + } + + oss<<"["<& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + CorrelationDescriptor_U correlationDescriptorToRead; + + ComplexArrayHeader_t complexArray; + UINT64 arrayDescrOffset = pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString; + UINT argNbr = 0; + INT size = 0; + + BYTE correlationType; + BYTE correlationOperator; + short correlationOffset; + NDR_CORRELATION_FLAGS correlationFlags = {0,0,0,0,0}; + + StructNonBaseTypeMemberLayout_t elementDescription; + UINT8 elementToDecode; + + UINT32 arraySize[30]; + UINT32 arraySizeIndex = 0; + + UINT8 varDescrHandled[15]; + UINT16 callbacksCalled[15]; + UINT32 i = 0; + UINT32 j = 0; + + BOOL isLastEmbeddedArray = FALSE; + BOOL lengthIs = FALSE; + BOOL lastIs = FALSE; + BOOL firstArray = TRUE; + + std::stringstream lastIsStdString; + lastIsStdString << "[last_is("; + + std::stringstream lengthIsStdStr; + lengthIsStdStr << "[length_is("; + + std::ostringstream rangeStr; + + ConformanceDescr_T confDesc; + + UNREFERENCED_PARAMETER(fcType); + + memset(varDescrHandled, 0, sizeof(varDescrHandled)); + memset(callbacksCalled, -1, sizeof(callbacksCalled)); + + + + oss << " /* [DBG] FC_BOGUS_ARRAY */ "; + + + //// + + //RPC_GET_PROCESS_DATA( + // pType, + // dbgBuf, + // DBG_BUF_SIZE + // ); + + //oss<< std::endl << "DUMP : "; + //for(int i=0; i + + oss<<"[size_is("; + while(!isLastEmbeddedArray) + { + RPC_GET_PROCESS_DATA( + pType, + &complexArray, + sizeof(ComplexArrayHeader_t) // + ); + pType += sizeof(ComplexArrayHeader_t); + + if(complexArray.numberOfElements == 0){ + RVA_T pRangeDesc = pType; + // Read the conformance correlation descriptor ( size_is, max_is ) + RPC_GET_PROCESS_DATA( + pType, + &correlationDescriptorToRead, + sizeof(correlationDescriptorToRead) + ); + + if(robustFlagWasSet){ + correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescRobust.offset; + correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags; + }else{ + correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset; + } + + if(robustFlagWasSet) + { + pRangeDesc += sizeof(CorrelationDescriptorRobust_t); + } + else + { + pRangeDesc += sizeof(CorrelationDescriptorNonRobust_t); + } + + confDesc.confType = size_is; + confDesc.corrDesc = correlationDescriptorToRead.corrDescNonRobust; + + // decode target of ConformanceDescriptor + bResult = processCorrelationDescriptorNaked(pContext, confDesc, oss,ParamDesc); + if(bResult == FALSE) + { + RPC_ERROR_FN("processCorrelationDescriptorNaked failed\n"); + return FALSE; + } + if(ParamDesc.hasRangeOnConformance() && firstArray)// && confDesc.corrDesc.correlation_type != FC_CONSTANT_CONFORMANCE && confDesc.corrDesc.correlation_type != FC_POINTER_CONFORMANCE) + { + bResult = ProcessArrayRange(pContext, pRangeDesc, ParamDesc, rangeStr); + if(bResult == FALSE) + { + RPC_ERROR_FN("ProcessArrayRange failed\n"); + return FALSE; + } + firstArray = FALSE; + } + + arraySize[arraySizeIndex++] = 0; + + }else{ // complexArray.numberOfElements == 0 + arraySize[arraySizeIndex++] = complexArray.numberOfElements; + } + + pType += 2 * getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance()); // Forget about 2nd correlation descriptor, will be handled later + + + RPC_GET_PROCESS_DATA( + pType, + &elementDescription, + sizeof(StructNonBaseTypeMemberLayout_t) + ) + if(elementDescription.memberType == FC_EMBEDDED_COMPLEX) + { + + pType = pType + sizeof(StructNonBaseTypeMemberLayout_t) + elementDescription.offsetToDescription - sizeof(elementDescription.offsetToDescription); + RPC_GET_PROCESS_DATA( + pType, + &elementToDecode, + sizeof(UINT8) + ); + + if(elementToDecode != FC_BOGUS_ARRAY) + { + oss<<")]"; + isLastEmbeddedArray = TRUE; + }else{ + oss<<","; + } + }else{ // elementDescription.memberType == FC_EMBEDDED_COMPLEX + oss<<")]"; + isLastEmbeddedArray = TRUE; + } + } // while(!isLastEmbeddedArray) + + // Add the range if any + oss << rangeStr.str(); + + pType = (RVA_T)(arrayDescrOffset + pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString); + isLastEmbeddedArray = FALSE; + + /**************************************************** + * + * + * Variance descriptor + * + * + ****************************************************/ + while(!isLastEmbeddedArray){ + RPC_GET_PROCESS_DATA( + pType, + &complexArray, + sizeof(ComplexArrayHeader_t) + ); + pType += sizeof(ComplexArrayHeader_t); + + // Jump over conformance descriptor + pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance()); + + // Read variance descriptor + RPC_GET_PROCESS_DATA( + pType, + &correlationDescriptorToRead, + sizeof(correlationDescriptorToRead) + ); + + if(robustFlagWasSet){ + correlationType = correlationDescriptorToRead.corrDescRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescRobust.offset; + correlationFlags = correlationDescriptorToRead.corrDescRobust.robust_flags; + }else{ + correlationType = correlationDescriptorToRead.corrDescNonRobust.correlation_type; + correlationOperator = correlationDescriptorToRead.corrDescNonRobust.correlation_operator; + correlationOffset = correlationDescriptorToRead.corrDescNonRobust.offset; + } + pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance()); + + + if(correlationType != 0xFF) + { // If variance descriptor is not invalid + + if(is64B) argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_64B; + else argNbr = correlationOffset / VIRTUAL_STACK_OFFSET_GRANULARITY_32B; + + // Only FC_CONSTANT_CONFORMANCE handled yet. + switch(correlationType & 0xF0){ + + case FC_CONSTANT_CONFORMANCE: + size = ((correlationOperator << 16) | correlationOffset) & 0xFFFFFF; + lastIsStdString< + // proposition : ne pas ajouter de [] si le tableau est préfixé par un pointeur + if(ParamDesc.getuPtrLevel() == 0) + { + for(i=0; i +#include +#include "internalRpcDecompTypeDefs.h" + + + +BOOL __fastcall processFixedSizeArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss); + +BOOL __fastcall processConformantArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss); + +BOOL __fastcall processConformantVaryingArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss); + +BOOL __fastcall processVaryingArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss); + +BOOL __fastcall processComplexArray( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss); + +UINT __fastcall getArrayMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType); + + + + +#endif//_INTERNAL_COMPLEX_TYPES_ARRAYS_H_ \ No newline at end of file diff --git a/RpcDecompiler/internalComplexTypesPointers.cpp b/RpcDecompiler/internalComplexTypesPointers.cpp new file mode 100644 index 0000000..c279e79 --- /dev/null +++ b/RpcDecompiler/internalComplexTypesPointers.cpp @@ -0,0 +1,326 @@ +#include "..\RpcCommon\RpcView.h" +#include "internalComplexTypesPointers.h" +#include "internalRpcDecompiler.h" +#include "internalRpcDecompTypeDefs.h" +#include "internalComplexTypesArrays.h" +#include "InternalComplexTypesMisc.h" +#include "internalRpcUtils.h" + +#include + + +BOOL __fastcall processStandardPointer( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BYTE bRead; + BOOL bResult; + RVA_T pComplexType = NULL; + CommonPtrSimple_t simplePtr; + CommonPtrComplex_t complexPtr; + + // set attributes relative to pointer + if(ParamDesc.getuPtrLevel() == 0) // pointer attributes seems to be applied only on first pointer level + { + if(fcType == FC_UP) + { + oss<<"[unique]"; + } + + + if(fcType == FC_RP) + { + oss<<"[ref]"; + } + + if(fcType == FC_FP) + { + oss<<"[ptr]"; + } + + if(fcType == FC_OP) + { + oss<<"/*FC_OP*/"; + } + } + + // increment pointer attribute + ParamDesc.incPtrLevel(); + + + + + // read FC_POINTER_ATTRIBUTE + RPC_GET_PROCESS_DATA((pType+1),&bRead,sizeof(bRead)); + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processStandardPointer : unable to read process data\n"); + return FALSE; + } + + ; + + if(bRead & FC_SIMPLE_POINTER) // A pointer to a simple type or nonsized conformant string + { + + // read simple ptr + RPC_GET_PROCESS_DATA(pType, &simplePtr, sizeof(simplePtr)); + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processStandardPointer : unable to read process data\n"); + return FALSE; + } + + + // special case where it's a conformant non sized string + if((FC_TYPE)simplePtr.simple_type == FC_C_CSTRING) + { + oss << "[string] char"; + displayPtrLevel(ParamDesc.getuPtrLevel(), oss); + oss<< " " << ParamDesc.getStrTypeName(); + } + else if((FC_TYPE)simplePtr.simple_type == FC_C_WSTRING) + { + oss << "[string] wchar_t"; + displayPtrLevel(ParamDesc.getuPtrLevel(), oss); + oss<< " " << ParamDesc.getStrTypeName(); + } + else // simple type + { + + + bResult = processSimpleType( + pContext, + (FC_TYPE)simplePtr.simple_type, + ParamDesc, + oss); + + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processStandardPointer : unable to parsse simple type\n"); + return FALSE; + } + } + } + else // complex pointer + { + + + RPC_GET_PROCESS_DATA(pType, &complexPtr, sizeof(complexPtr)); + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processStandardPointer : unable to read process data\n"); + return FALSE; + } + + // compute type Offset : + pComplexType = pType + sizeof(complexPtr.pointerType) + sizeof(complexPtr.pointer_attributes) + complexPtr.offset_to_complex_description; + //ParamDesc.setuOffset((UINT)(pComplexType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString)); //TODO : .... + ParamDesc.setRva(pComplexType); + + // DEBUG + ParamDesc.setArrayIsAttributedPointer(); + + // END DEBUG + + bResult = rpcDumpType( + pContext, + ParamDesc, + listAdditionalTypes, + oss); + + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processStandardPointer : unable to dump complex type\n"); + return FALSE; + } + + + } + + // set Param size in memory + // (set done after RpcDump type to override MemorySize of pointeed type) + //ParamDesc.setMemorySize(POINTER_SIZE); + + return TRUE; +} + + +BOOL __fastcall processInterfacePointer( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::ostringstream& oss) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult; + BYTE bRead; + GUID ifGuid; + + + + + + //read firstByte + RPC_GET_PROCESS_DATA(++pType,&bRead,sizeof(bRead)); + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processInterfacePointer : unable to read process data\n"); + return FALSE; + } + + + + if(bRead == FC_CONSTANT_IID) + { + pType++; + + + // read ifGuid.Data1; + RPC_GET_PROCESS_DATA(pType, &ifGuid, sizeof(ifGuid)); + + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processInterfacePointer : unable to read process data\n"); + return FALSE; + } + pType += sizeof(ifGuid); + + + + oss<<"interface("; + oss< interface pointer with idd_is() + { + // TODO + oss<<"[iid_is(TODO)] FC_IP "; + } + + oss<& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = TRUE; + short shortOffset; + ByteCountHeader_T byteCountHeader; + ConformanceDescr_T confDescr; + + + + // increment pointer count + ParamDesc.incPtrLevel(); + + RPC_GET_PROCESS_DATA(pType,&byteCountHeader,sizeof(byteCountHeader)); + + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processByteCountPointer : unable to read process data\n"); + return FALSE; + } + + pType += sizeof(byteCountHeader); + + // conformance part parsing + // byte_count is an acf attributes, so we'll comment it + + oss << "/* ACF attributes : "; + confDescr.pType = pType; + confDescr.confType = byte_count; + + RPC_GET_PROCESS_DATA(confDescr.pType, &confDescr.corrDesc, sizeof(confDescr.corrDesc)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processByteCountPointer : unable to read process data\n"); + return FALSE; + } + + processCorrelationDescriptor(pContext, confDescr, oss, ParamDesc); + oss << "*/ "; + + // skip conformance part + pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance()); + + + + // check if it's simple type or complex type + if(byteCountHeader.simpleTypeOrPad == FC_PAD) + { + + + // COMPLEX_TYPE + // read offset to complex type + RPC_GET_PROCESS_DATA(pType,&shortOffset,sizeof(shortOffset)); + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processByteCountPointer : unable to read process data\n"); + return FALSE; + } + + + pType += shortOffset; + //ParamDesc.setuOffset((UINT)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString)); + ParamDesc.setRva(pType); + + //dump COMPLEX TYPE + bResult = rpcDumpType( + pContext, + ParamDesc, + listAdditionalTypes, + oss); + + if(!bResult) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processByteCountPointer : unable to dump embeded type"); + return FALSE; + } + + } + else + { + // SIMPLE_TYPE + if(!processSimpleType(pContext, (FC_TYPE) byteCountHeader.simpleTypeOrPad, ParamDesc, oss)) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processByteCountPointer : unable to dump simple type"); + return FALSE; + } + } + + + // set Param size in memory + // (set done after RpcDump type to override MemorySize of pointeed type) + //ParamDesc.setMemorySize(POINTER_SIZE); + + return TRUE; +} + diff --git a/RpcDecompiler/internalComplexTypesPointers.h b/RpcDecompiler/internalComplexTypesPointers.h new file mode 100644 index 0000000..cc738ec --- /dev/null +++ b/RpcDecompiler/internalComplexTypesPointers.h @@ -0,0 +1,45 @@ +#ifndef _INTERNAL_COMPLEX_TYPES_POINTERS_H_ +#define _INTERNAL_COMPLEX_TYPES_POINTERS_H_ + +#include +#include +#include "internalRpcDecompTypeDefs.h" + + + + +#define POINTER_SIZE_32_BITS 4 +#define POINTER_SIZE_64_BITS 8 +#define POINTER_SIZE (is64B?POINTER_SIZE_64_BITS:POINTER_SIZE_32_BITS) + + +//--------------------------------------------------------------------------- +BOOL __fastcall processStandardPointer( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processInterfacePointer( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall processByteCountPointer( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + + + +#endif//_INTERNAL_COMPLEX_TYPES_POINTERS_H_ \ No newline at end of file diff --git a/RpcDecompiler/internalComplexTypesStrings.cpp b/RpcDecompiler/internalComplexTypesStrings.cpp new file mode 100644 index 0000000..4684e80 --- /dev/null +++ b/RpcDecompiler/internalComplexTypesStrings.cpp @@ -0,0 +1,168 @@ +#include "..\RpcCommon\RpcView.h" +#include "internalRpcDecompiler.h" +#include "internalRpcDecompTypeDefs.h" +#include "internalComplexTypesStrings.h" +#include "InternalComplexTypesMisc.h" +#include "internalComplexTypesPointers.h" +#include "internalRpcUtils.h" + + +BOOL __fastcall processConformantString( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::ostringstream& oss) +{ + + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BYTE bFC_STRING_SIZED; + ConformantSizedStr_t conformantSizedStr; + ConformanceDescr_T confDesc; + + oss<<"[string]"; + + + // set Param size in memory + //ParamDesc.setMemorySize(POINTER_SIZE); + + + // check if string contains FC_STRING_SIZED (conformance descriptor) + RPC_GET_PROCESS_DATA(pType+1,&bFC_STRING_SIZED,sizeof(bFC_STRING_SIZED)); + if(!bResult) + { + return FALSE; + } + + if(bFC_STRING_SIZED == FC_STRING_SIZED) + { + // read conformance sized string + RPC_GET_PROCESS_DATA( + pType, + &conformantSizedStr, + SIZE_OF_CONFORMANT_SIZED_STR); + if(!bResult) + { + return FALSE; + } + + pType += FIELD_OFFSET(ConformantSizedStr_t, conformance_description); + + // build conformance descriptor + confDesc.confType = size_is; + confDesc.corrDesc = conformantSizedStr.conformance_description.corrDescNonRobust; + confDesc.pType = pType ; + + // print correlation desc + processCorrelationDescriptor(pContext, confDesc, oss, ParamDesc); + + if(robustFlagWasSet) + { + pType += sizeof(CorrelationDescriptorRobust_t); + } + else + { + pType += sizeof(CorrelationDescriptorNonRobust_t); + } + + if(ParamDesc.hasRangeOnConformance()) + { + ProcessArrayRange(pContext, pType, ParamDesc, oss); + pType += sizeof(Range_t); + } + + } + + + if(fcType == FC_C_CSTRING) + { + oss<<" char"; + } + else // FC_C_WSTRING + { + oss<<" wchar_t"; + } + + displayPtrLevel(ParamDesc.getuPtrLevel(), oss); + oss << " "; + oss< +#include "internalRpcDecompTypeDefs.h" + + +//-------------------------------------------------------------------------- +BOOL __fastcall processConformantString( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::ostringstream& oss); + + +//-------------------------------------------------------------------------- +BOOL __fastcall processNonConformantString( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::ostringstream& oss); + + +//-------------------------------------------------------------------------- +BOOL __fastcall processStructureString( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::ostringstream& oss); + + + +#endif//_INTERNAL_COMPLEX_TYPES_STRINGS_H_ \ No newline at end of file diff --git a/RpcDecompiler/internalComplexTypesStructs.cpp b/RpcDecompiler/internalComplexTypesStructs.cpp new file mode 100644 index 0000000..6789c27 --- /dev/null +++ b/RpcDecompiler/internalComplexTypesStructs.cpp @@ -0,0 +1,1083 @@ +#include +#include +#include + +#include "..\RpcCommon\RpcView.h" +#include "internalRpcDecompTypeDefs.h" +#include "internalComplexTypesStructs.h" +#include "internalTypeTools.h" +#include "internalRpcDecompiler.h" +#include "internalRpcUtils.h" +#include "internalComplexTypesPointers.h" + + +BOOL __fastcall getStructureMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszStructureMemorySize) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BOOL bResult = FALSE; + SimpleStructHeader_t structHeader; // header common to all kind of structures + + // read structure header in order to store it's memory size + RPC_GET_PROCESS_DATA( + pType, + &structHeader, + sizeof(SimpleStructHeader_t) + ); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processStructure : unable to get process data"); + return FALSE; + } + + *pszStructureMemorySize = structHeader.memory_size; + + + return TRUE; +} + + +BOOL __fastcall processStructure( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + SimpleStructHeader_t structHeader; // header common to all kind of structures + + UNREFERENCED_PARAMETER(fcType); + + // read structure header in order to store it's memory size + RPC_GET_PROCESS_DATA( + pType, + &structHeader, + sizeof(SimpleStructHeader_t) + ); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] processStructure : unable to get process data"); + return FALSE; + } + + //ParamDesc.setMemorySize(structHeader.memory_size); + + // declare structure param + oss<<"struct Struct_"<< std::dec <pRpcDecompilerInfo->pTypeFormatString)<<"_t"; + displayPtrLevel(ParamDesc.getuPtrLevel(), oss); + oss<<" "<& vectMembersOffset) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BYTE bRead; + UINT uOffsetInMemberList = 0; + + while(1) + { + + RPC_GET_PROCESS_DATA( + pMemberLayout, + &bRead, + sizeof(bRead)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_BOGUS_STRUCT : unable to get process data"); + return FALSE; + } + + + if(isSimpleType((FC_TYPE)bRead)) // is this a simple type + { + // save member offset + vectMembersOffset.push_back(uOffsetInMemberList); + // increment offset counter + uOffsetInMemberList += getSimpleTypeMemorySize((FC_TYPE)bRead); + + pMemberLayout += sizeof(bRead); + } + else if((FC_TYPE)bRead == FC_EMBEDDED_COMPLEX) // is this an embedded complex + { + StructNonBaseTypeMemberLayout_t structMemberLayout; + //ParamDesc paramDesc; + RVA_T pComplexType; + size_t szComplexSize = 0; + //std::list listUseless; + //std::ostringstream ossUseless; + + + RPC_GET_PROCESS_DATA(pMemberLayout, &structMemberLayout, sizeof(StructNonBaseTypeMemberLayout_t)); + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] buildStructureOffsetMemberVector : unable to get process data"); + return FALSE; + } + + //// dump type in order to get its size + pComplexType = pMemberLayout + FIELD_OFFSET(StructNonBaseTypeMemberLayout_t, offsetToDescription) + structMemberLayout.offsetToDescription; + + ////paramDesc.setuOffset((UINT)(pComplexType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString)); + //paramDesc.setpType(pComplexType); + //paramDesc.inheritProperties(structureDesc); + + //if (rpcDumpType(pContext, paramDesc, listUseless, ossUseless) == FALSE) + //{ + // RPC_DEBUG_FN((UCHAR*)"[ERROR] defineType_FC_BOGUS_STRUCT : unable to dump type"); + // return FALSE; + //} + + if(getTypeMemorySize(pContext, pComplexType, &szComplexSize, structureDesc.getHasRangeOnConformance()) == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] buildStructureOffsetMemberVector : unable to get memory type size"); + return FALSE; + } + + + // save member offset + vectMembersOffset.push_back(uOffsetInMemberList); + // increment offset counter + uOffsetInMemberList += (UINT)szComplexSize; + + + pMemberLayout += sizeof(StructNonBaseTypeMemberLayout_t); + } + else if((FC_TYPE)bRead == FC_POINTER) // is this a pointer + { + // save member offset + vectMembersOffset.push_back(uOffsetInMemberList); + // increment offset counter + uOffsetInMemberList += POINTER_SIZE; + + pMemberLayout += sizeof(bRead); + } + else if((FC_TYPE)bRead >= FC_STRUCTPAD1 && (FC_TYPE)bRead <= FC_STRUCTPAD7) // is this PAD + { + // increment offset counter + uOffsetInMemberList += bRead - (FC_STRUCTPAD1 - 1); + + pMemberLayout += sizeof(bRead); + } + else if((FC_TYPE)bRead == FC_PAD || (FC_TYPE)bRead == FC_END) // is this the end ? + { + + // store last offset off the structure (useful when we have a conformant array) + vectMembersOffset.push_back(uOffsetInMemberList); + // and exit + break; + } + else + { + RPC_DEBUG_FN((UCHAR*)"/* [ERROR] unknow member layout : 0x%x", bRead ); + return FALSE; + } + + } + + return TRUE; +} + + +BOOL __fastcall dumpEveryStructMember( + _In_ VOID* pContext, + _In_ RVA_T pMemberLayout, + _In_opt_ RVA_T pPointerLayout, + _In_ const TypeToDefine& structureDesc, + _In_ const std::vector& vectMembersOffset, + _Inout_ std::list& listAdditionalTypes, + _Inout_ std::ostringstream& oss, + _In_opt_ const std::map* pMapPointerLayout = NULL) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BYTE bRead; + UINT uStructMemberCounter = 0; + UINT uPointerCounter = 0; + + while(TRUE) + { + + RPC_GET_PROCESS_DATA( + pMemberLayout, + &bRead, + sizeof(bRead)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] dumpEveryStructMember : unable to get process data"); + return FALSE; + } + + + + + if((FC_TYPE)bRead == FC_END) // is this the end + { + break; + } + else if( ((FC_TYPE)bRead >= FC_STRUCTPAD1 && (FC_TYPE)bRead <= FC_STRUCTPAD7) || (FC_TYPE)bRead == FC_PAD) // is this PAD + { + // increment offset counter + + pMemberLayout += sizeof(bRead); + } + else if(bRead != FC_EMBEDDED_COMPLEX && + pMapPointerLayout != NULL && + pMapPointerLayout->find(vectMembersOffset[uStructMemberCounter]) != pMapPointerLayout->end()) // check if there's an entry in mapPointerLayout for current structure member + { + auto it = pMapPointerLayout->find(vectMembersOffset[uStructMemberCounter]); + std::ostringstream ossTmp; + + + + oss<<"\t\t"; + + //set struct member name + ossTmp << "\tStructMember"<second); + + if (rpcDumpType(pContext, paramDesc, listAdditionalTypes, oss) == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] dumpEveryStructMember : unable to dump mapPointerLayout associated type"); + oss << "/* [ERROR] dumpEveryStructMember : unable to dump mapPointerLayout associated type */" << std::endl; + return FALSE; + } + + // End of member printing + oss<<";\n"; + + uStructMemberCounter++; + + + + pMemberLayout += sizeof(bRead); // type read should be a simple type (FC_LONG) + + } + else if(isSimpleType((FC_TYPE)bRead)) // is this a simple type + { + std::stringstream ossTmp; + ParamDesc paramDesc; + + oss<<"\t\t"; + + //set struct member name + ossTmp << "\tStructMember" << uStructMemberCounter; + paramDesc.setParamName(ossTmp.str()); + paramDesc.setuStructMemberNum(uStructMemberCounter); + // inherit its properties from structure + paramDesc.inheritProperties(structureDesc); + + + //simple type to print + processSimpleType(pContext, (FC_TYPE)bRead, paramDesc, oss); + + // End of member printing + oss<<";\n"; + uStructMemberCounter ++; + + pMemberLayout += sizeof(bRead); + } + else if((FC_TYPE)bRead == FC_EMBEDDED_COMPLEX) // is this an embedded complex + { + std::ostringstream ossTmp; + StructNonBaseTypeMemberLayout_t structMemberLayout; + RVA_T pComplexType; + + oss<<"\t\t"; + + //set struct member name + ossTmp << "\tStructMember"<pRpcDecompilerInfo->pTypeFormatString)); + paramDesc.setRva(pComplexType); + + if (rpcDumpType(pContext, paramDesc, listAdditionalTypes, oss) == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] dumpEveryStructMember : unable to dump type"); + oss << "/* [ERROR] dumpEveryStructMember : unable to dump FC_EMBEDDED_COMPLEX type */" << std::endl; + return FALSE; + } + + // End of member printing + oss<<";\n"; + + uStructMemberCounter++; + + + pMemberLayout += sizeof(StructNonBaseTypeMemberLayout_t); + } + else if((FC_TYPE)bRead == FC_POINTER) // is this a pointer + { + std::ostringstream ossTmp; + RVA_T pPointer; + + // check if pPointerLayout has been provide + if(pPointerLayout == NULL) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] dumpEveryStructMember, a pointer need to be decoded but an empty pPointerLayout has been provided\n"); + oss << "[ERROR] dumpEveryStructMember, a pointer need to be decoded but an empty pPointerLayout has been provided\n"; + return FALSE; + } + + oss<<"\t\t"; + + //set struct member name + ossTmp << "\tStructMember"<pRpcDecompilerInfo->pTypeFormatString)); + paramDesc.setRva(pPointer); + + bResult = rpcDumpType(pContext, paramDesc, listAdditionalTypes, oss); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] dumpEveryStructMember : unable to dump FC_POINTER type"); + oss << "/* [ERROR] dumpEveryStructMember : unable to dump FC_POINTER type */" << std::endl; + return FALSE; + } + // End of member printing + oss<<";\n"; + + // increment pointer counter + uPointerCounter++; + uStructMemberCounter++; + + + pMemberLayout += sizeof(bRead); + } + else + { + RPC_DEBUG_FN((UCHAR*)"/* [ERROR] unknow member layout : 0x%x", bRead ); + oss << "/* [ERROR] unknow member layout : 0x" << std::hex <<(int) bRead << std::dec << "*/" << std::endl; + return FALSE; + } + + } + + return TRUE; +} + + + +BOOL __fastcall parseNoRepeat( + _In_ VOID* pContext, + _In_ RVA_T pPointerInstanceLayout, + _Out_ std::map& mapPointerLayout, + _Out_ size_t* pSzPointerInstanceLayout) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + SingleInstancePtrToSimpleType_t singleInstancePtr; + RVA_T pPtrDesc; + + RPC_GET_PROCESS_DATA(pPointerInstanceLayout, &singleInstancePtr, sizeof(singleInstancePtr)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] parseNoRepeat : unable to get process data"); + return FALSE; + } + + pPtrDesc = pPointerInstanceLayout + OFFSET_SINGLE_INSTANCE_TO_PTR_DESC; + mapPointerLayout.insert( std::pair(singleInstancePtr.pointerInstance.offsetToPtrInBuffer, pPtrDesc)); + + // set szPointerInstanceLayout size + *pSzPointerInstanceLayout = sizeof(singleInstancePtr); + + return TRUE; +} + +BOOL __fastcall parseVariableRepeat( + _In_ VOID* pContext, + _In_ RVA_T pPointerInstanceLayout, + _Inout_ std::map& mapPointerLayout, + _Out_ size_t* pSzPointerInstanceLayout) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + VariableRepeatPtr_t variableRepeatPtr; + PointerInstance_t pointerInstanceRead; + RVA_T pPointerInstance = NULL; + + RPC_GET_PROCESS_DATA(pPointerInstanceLayout, &variableRepeatPtr, sizeof(variableRepeatPtr)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] parseNoRepeat : unable to get process data"); + return FALSE; + } + + + pPointerInstance = pPointerInstanceLayout + sizeof(VariableRepeatPtr_t); + + for(int i=0; i( pointerInstanceRead.offsetToPtrInBuffer, + pPointerInstance + FIELD_OFFSET(PointerInstance_t, pointerDescription))); + + pPointerInstance += sizeof(pointerInstanceRead); + } + + + // set szPointerInstanceLayout size + *pSzPointerInstanceLayout = (pPointerInstance - pPointerInstanceLayout); + + return TRUE; +} + +BOOL __fastcall parseFixedRepeat() +{ + return FALSE; +} + + +BOOL __fastcall parsePointerLayout( + _In_ VOID* pContext, + _In_ const RVA_T pPointerLayout, + _Inout_ std::map& mapPointerLayout, + _Out_ size_t* pSzPointerLayout, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + PointerLayoutHeader_t pointerLayoutHeader; + RVA_T pStream = pPointerLayout; + BYTE bFcType; + + + *pSzPointerLayout = 0; + //oss << std::endl << "\t/*DBG DUMP : "; + //int i = 0; + //while(true) + //{ + // BYTE bRead; + + // RPC_GET_PROCESS_DATA((pStream+i), &bRead, sizeof(bRead)); + + // oss << std::hex << " 0x"<<(int)bRead; + + // if(i++ == 128) + // { + // break; + // } + //} + //oss << " */"; + // read header + RPC_GET_PROCESS_DATA(pStream, &pointerLayoutHeader, sizeof(pointerLayoutHeader)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] parsePointerLayout : unable to get process data"); + return FALSE; + } + + if(pointerLayoutHeader.pointerType != FC_PP) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] parsePointerLayout : not a pointer layout"); + oss << " // [ERROR] parsePointerLayout : not a pointer layout" << std::endl; + return FALSE; + } + + pStream += sizeof(pointerLayoutHeader); + + + + // read pointer description + RPC_GET_PROCESS_DATA(pStream, &bFcType, sizeof(bFcType)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] parsePointerLayout : unable to get process data"); + return FALSE; + } + + // FC_END means it's the end of pointers description + while((FC_TYPE)bFcType != FC_END) + { + + size_t szPointerInstanceLayout = 0; + + if(bFcType == FC_NO_REPEAT) + { + if( parseNoRepeat(pContext, pStream, mapPointerLayout, &szPointerInstanceLayout) == FALSE) + { + oss << " // [ERROR] parsePointerLayout : error in parseNoRepeat "; + return FALSE; + } + + pStream += (RVA_T)szPointerInstanceLayout; + } + else if(bFcType == FC_VARIABLE_REPEAT) + { + if( parseVariableRepeat(pContext, pStream, mapPointerLayout, &szPointerInstanceLayout) == FALSE) + { + oss << " // [ERROR] parsePointerLayout : error in parseVariableRepeat "; + return FALSE; + } + + pStream += (RVA_T)szPointerInstanceLayout; + } + else if(bFcType == FC_FIXED_OFFSET) + { + oss << " // [ERROR] parsePointerLayout : error, parseFixedOffset not implemented"; + return FALSE; + } + else + { + oss << " // [ERROR] parsePointerLayout : unknown pointer layout type : (0x" << std::hex << bFcType << ")"; + return FALSE; + } + + RPC_GET_PROCESS_DATA(pStream, &bFcType, sizeof(bFcType)); + + if(FALSE == bResult) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] parsePointerLayout : unable to get process data"); + return FALSE; + } + + }//while((FC_TYPE)bFcType != FC_END) + + // compute pointerLayout size + *pSzPointerLayout = (size_t) ((pStream + 1) - pPointerLayout); + + return TRUE; +} + + +BOOL __fastcall defineTypeSimpleStruct( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const TypeToDefine& structureDesc, + _Inout_ std::list& listAdditionalType, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + SimpleStructHeader_t SimpleStructHeader; + RVA_T pMemberLayout = NULL; + std::map mapPointerLayout; + UINT uStructId = (UINT32)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString); + + + + #ifdef DBG_DECOMP + oss << std::endl << "\t/*FC_STRUCT || FC_PSTRUCT */" ; + #endif + + oss < + //oss << " /* DBG : mapPointerLayout " << std::endl; + + //for(auto iter=mapPointerLayout.begin(); iter != mapPointerLayout.end(); iter++) + //{ + // oss << "offset : 0x" << std::hex <<(int)iter->first << ", "; + // oss << " pointer desc : " << std::hex << (LONGLONG) iter->second; + // oss << std::endl; + //} + + //oss << " */" << std::endl; + // + + + pMemberLayout = pPointerLayout + (RVA_T)szPointerLayout; + } + else // structure is a simple structure without pointer + { + pMemberLayout = pType + sizeof(SimpleStructHeader); + } + + + // building of a vector associating every member + // to its offset + std::vector vectMembersOffset; + if(buildStructureOffsetMemberVector(pContext, pMemberLayout, structureDesc, vectMembersOffset) == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineTypeSimpleStruct : unable to build structure member offset"); + return FALSE; + } + + + // then let's dump every struct member + bResult = dumpEveryStructMember( + pContext, + pMemberLayout, + NULL, // no pointer layout + structureDesc, + vectMembersOffset, + listAdditionalType, + oss, + &mapPointerLayout); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineTypeSimpleStruct : unable to dumpEveryStructMember"); + return FALSE; + + } + + + //close the structure declaration + oss<<"\t}Struct_"<& listAdditionalType, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + ConfStructHeader_t confStructHeader; + std::map mapPointerLayout; + RVA_T pMemberLayout; + RVA_T pArrayDescription; + UINT uStructId = (UINT32)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString); + UINT uStructMemberCount; + + + #ifdef DBG_DECOMP + oss << std::endl << "\t/*FC_CSTRUCT*/" ; + #endif + oss<<"\n\ttypedef struct Struct_"<< std::dec << uStructId<<"_t\n\t{\n"; + + + RPC_GET_PROCESS_DATA( + pType, + &confStructHeader, + sizeof(confStructHeader) + ); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_CSTRUCT : unable to get process data"); + return FALSE; + } + + + + // compute pArrayDescription + pArrayDescription = pType + FIELD_OFFSET(ConfStructHeader_t, offsetToArrayDescription) + confStructHeader.offsetToArrayDescription; + //+ sizeof(confStructHeader.structType) + //+ sizeof(confStructHeader.alignment) + //+ sizeof(confStructHeader.memory_size) + //+ confStructHeader.offsetToArrayDescription; + + + + // check if it's a structure with pointers + if(confStructHeader.structType == FC_CPSTRUCT) + { + RVA_T pPointerLayout = pType + sizeof(confStructHeader); + size_t szPointerLayout = 0; + + bResult = parsePointerLayout(pContext, pPointerLayout, mapPointerLayout, &szPointerLayout,oss); + + if(bResult == FALSE) + { + oss << "[ERROR] an error has occured in parsePointerLayout\n"; + return FALSE; + } + + + + pMemberLayout = pPointerLayout + (RVA_T)szPointerLayout; + } + else // structure is a simple structure without pointer + { + pMemberLayout = pType + sizeof(confStructHeader); + } + + + + // first let's build a vect list associating every member + // to its offset + std::vector vectMembersOffset; + if(buildStructureOffsetMemberVector(pContext, pMemberLayout, structureDesc, vectMembersOffset) == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_CSTRUCT : unable to build structure member offset"); + return FALSE; + } + + + // then let's dump every struct member + bResult = dumpEveryStructMember( + pContext, + pMemberLayout, + NULL, + structureDesc, + vectMembersOffset, + listAdditionalType, + oss); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_CSTRUCT : unable to dumpEveryStructMember"); + return FALSE; + + } + + // dump last struct member (conformant string or array) + { + uStructMemberCount = (UINT) vectMembersOffset.size() - 1; // last struct member count is equal to the size of vectMemberOffset + std::stringstream ss; + ss << "StructMember" << uStructMemberCount ; + + ParamDesc lastStructMember(ss.str(), uStructMemberCount, vectMembersOffset); // TODO rassembler le inherit dans le constructeur + lastStructMember.inheritProperties(structureDesc); + lastStructMember.setRva(pArrayDescription); + + oss<<"\t"; + + bResult = rpcDumpType( + pContext, + lastStructMember, + listAdditionalType, + oss); + + oss<<";" << std::endl << "\t" ; + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_CSTRUCT : unable to Dump last member"); + return FALSE; + } + } + + //close the structure declaration + oss<<"\t}Struct_"<& listAdditionalType, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + ComplexStructHeader_t complexStructHeader; + + + RVA_T pMemberLayout; + RVA_T pPointerLayout; + RVA_T pConformantArrayDescription = NULL; + UINT uStructId = (UINT32)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString); + UINT uStructMemberCount; + + + #ifdef DBG_DECOMP + oss << std::endl << "\t/*FC_BOGUS_STRUCT*/" ; + #endif + oss<<"\n\ttypedef struct Struct_"<< std::dec << uStructId<<"_t\n\t{\n"; + + + RPC_GET_PROCESS_DATA( + pType, + &complexStructHeader, + sizeof(ComplexStructHeader_t) + ); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_BOGUS_STRUCT : unable to get process data"); + return FALSE; + } + + + + // compute PointerLayout + pPointerLayout = pType + + sizeof(complexStructHeader.structType) + + sizeof(complexStructHeader.alignment) + + sizeof(complexStructHeader.memory_size) + + sizeof(complexStructHeader.offsetToArrayDescription) + + complexStructHeader.offsetToPointerLayout; + + // compute pArrayDescription if needed + if(complexStructHeader.offsetToArrayDescription != 0) + { + pConformantArrayDescription = pType + + sizeof(complexStructHeader.structType) + + sizeof(complexStructHeader.alignment) + + sizeof(complexStructHeader.memory_size) + + complexStructHeader.offsetToArrayDescription; + } + + + pMemberLayout = pType + sizeof(ComplexStructHeader_t); + + // first let's build a vect list associating every member + // to its offset + std::vector vectMembersOffset; + if(buildStructureOffsetMemberVector(pContext, pMemberLayout, structureDesc, vectMembersOffset) == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_BOGUS_STRUCT : unable to build structure member offset"); + return FALSE; + } + + + // then let's dump every struct member + bResult = dumpEveryStructMember( + pContext, + pMemberLayout, + pPointerLayout, + structureDesc, + vectMembersOffset, + listAdditionalType, + oss); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_BOGUS_STRUCT : unable to dumpEveryStructMember"); + return FALSE; + + } + + // if needed let's dump conformant_array_description + if(pConformantArrayDescription != NULL) + { + + uStructMemberCount = (UINT) vectMembersOffset.size() - 1; // last struct member count is equal to the size of vectMemberOffset + std::stringstream ss; + ss << "StructMember" << uStructMemberCount ; + + ParamDesc lastStructMember(ss.str(), uStructMemberCount, vectMembersOffset); + lastStructMember.inheritProperties(structureDesc); + lastStructMember.setRva(pConformantArrayDescription); + lastStructMember.setArrayIsAttributedPointer(); + + oss<<"\t"; + + bResult = rpcDumpType( + pContext, + lastStructMember, + listAdditionalType, + oss); + + oss<<";" << std::endl << "\t" ; + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_BOGUS_STRUCT : unable to Dump last member"); + return FALSE; + } + } + + //close the structure declaration + oss<<"\t}Struct_"< + memory_size<2> + reserved<4> + enum_offset<2> + copy_size<2> + mem_copy_incr<2> + union_description_offset<2> + member_layout<> + FC_END + + +*/ + + +//BOOL __fastcall defineTypeHardStruct( +// _In_ VOID* pContext, +// _In_ PBYTE pType, +// _Out_ std::list& listProcTypes, +// _Out_ std::ostringstream& oss) +//{ +// BOOL bResult = FALSE; +// RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; +// +// HardStructHeader_t hardStructHeader; +// +// +// PBYTE pMemberLayout; +// PBYTE pEnum; +// PBYTE pUnion; +// +// UINT uStructId = (UINT32)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString); +// +// oss< vectMembersOffset; +// if(buildStructureOffsetMemberVector(pContext, pMemberLayout, vectMembersOffset) == FALSE) +// { +// RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_HARD_STRUCT : unable to build structure member offset"); +// return FALSE; +// } +// +// +// // then let's dump every struct member +// bResult = dumpEveryStructMember( +// pContext, +// pMemberLayout, +// NULL, +// vectMembersOffset, +// listProcTypes, +// oss); +// +// if(bResult == FALSE) +// { +// RPC_DEBUG_FN((UCHAR*) "[ERROR] defineType_FC_HARD_STRUCT : unable to dumpEveryStructMember"); +// return FALSE; +// +// } +// +// +// // and finaly dump last member : enum or union +// +// //close the structure declaration +// oss<<"\t}Struct_"< +#include + +#define POINTER_LAYOUT_ENTRY_SIZE 4 + + +//--------------------------------------------------------------------------- +BOOL __fastcall getStructureMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszStructureMemorySize); + +//--------------------------------------------------------------------------- +BOOL __fastcall processStructure( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall defineTypeSimpleStruct( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const TypeToDefine& structureDesc, + _Inout_ std::list& listAdditionalType, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall defineTypeConformantStructure( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const TypeToDefine& structureDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//--------------------------------------------------------------------------- +BOOL __fastcall defineTypeComplexStruct( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const TypeToDefine& structureDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//BOOL __fastcall defineTypeHardStruct( +// _In_ VOID* pContext, +// _In_ PBYTE pType, +// _In_ const TypeToDefine& structureDesc, +// _Out_ std::list& listProcTypes, +// _Out_ std::ostringstream& oss); + + + + +#endif//_INTERNAL_COMPLEX_TYPES_STRUCTS_H_ \ No newline at end of file diff --git a/RpcDecompiler/internalComplexTypesUnions.cpp b/RpcDecompiler/internalComplexTypesUnions.cpp new file mode 100644 index 0000000..9646385 --- /dev/null +++ b/RpcDecompiler/internalComplexTypesUnions.cpp @@ -0,0 +1,619 @@ +#include +#include "..\RpcCommon\RpcView.h" +#include "internalRpcDecompTypeDefs.h" +#include "internalComplexTypesUnions.h" +#include "InternalComplexTypesMisc.h" +#include "internalRpcDecompiler.h" +#include "internalTypeTools.h" +#include "internalRpcUtils.h" + + +BOOL __fastcall processNonEncapsulatedUnion( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + UNREFERENCED_PARAMETER(fcType); + //NonEncapUnionHeader_t nonEncapUnionHeaderToPrint; + nonEncapUnion_offsetToSizeAndArmDescription_t offsetToSizeAndArmDescription; + UINT16 uMemorySize; + + ConformanceDescr_T confDesc; + UINT32 unionOffsetValueToContructTypeName = 0; + + RVA_T pTypeStart; + + + + // save pUnionheader to parse it later + pTypeStart = pType; + + + // let's skip union header + + pType += sizeof(NonEncapUnionHeader_t); + + // we'll have to read a switch_is correlation descr + confDesc.pType = pType; + confDesc.confType = switch_is; + + RPC_GET_PROCESS_DATA( + confDesc.pType, + &(confDesc.corrDesc), + sizeof(confDesc.corrDesc)); + + pType += getCorrelationDescriptorSize(robustFlagWasSet, ParamDesc.hasRangeOnConformance()); + + + RPC_GET_PROCESS_DATA( + pType, + &offsetToSizeAndArmDescription, + sizeof(nonEncapUnion_offsetToSizeAndArmDescription_t) + ); + + + + ParamDesc.addConformanceDescr(confDesc); + processCorrelationDescriptor(pContext, confDesc, oss, ParamDesc); + + //Calculate the absolute offset where offsetToSizeAndArmDescription points + unionOffsetValueToContructTypeName = (UINT32)((pType + offsetToSizeAndArmDescription) - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString); + + + + + TypeToDefine unionDesc((pType + offsetToSizeAndArmDescription) , ParamDesc); + //unionDesc.setuOffset(unionOffsetValueToContructTypeName); + unionDesc.setpNonEncapsulatedUnionHeader(pTypeStart); + + listProcTypes.push_back(unionDesc); + + // read union memory size + RPC_GET_PROCESS_DATA( + pType + offsetToSizeAndArmDescription, + &uMemorySize, + sizeof(uMemorySize) + ); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processNonEncapsulatedUnion : unable to dump complex type"); + return FALSE; + } + + //ParamDesc.setMemorySize(uMemorySize); + + oss<<"union union_"<< std::dec <& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + //TypeToDefine unionDesc; + + EncapUnion_t encapUnion; + + UNREFERENCED_PARAMETER(fcType); + + // get memory size + RPC_GET_PROCESS_DATA( + pType, + &encapUnion, + sizeof(encapUnion)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processEncapsulatedUnion : unable to dump complex type"); + return FALSE; + } + + // save memory size + //ParamDesc.setMemorySize(encapUnion.sizeAndArmDescr.memorySize + ((encapUnion.switchType & ENCAP_UNION_SWITCH_MEMORY_INCREMENT_MASK) >> 0x4)); + + + // store the type in listProcTypes in order to define it later + + // unionDesc.m_uOffset = ParamDesc.m_uOffset; + // unionDesc.m_fcType = fcType; + TypeToDefine unionDesc(pType, ParamDesc); + + listProcTypes.push_back(unionDesc); + + oss<<"union_"<< std::dec <pRpcDecompilerInfo->pTypeFormatString)<<" "; + displayPtrLevel(ParamDesc.getuPtrLevel(), oss); + oss<<" "<> 0x4); + + + + return TRUE; +} + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall printEachUnionMember( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const TypeToDefine& unionDesc, + _In_ UINT16 unionMemberCount, + _In_ BOOL bIsEncapsulatedUnion, + _Inout_ std::list& listAdditionalsType, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + ArmXCase_t unionMemberToPrint; + DefaultArmDescr_t defaultArmToPrint = 0; + + + //Print each member of the union + the default member + //bResult = PrintEachUnionMember(/* in */ pRpcDecompilerCtxt, /* in */ TypeOffset, /* in */ unionEncapsulatedDescr, /* in */ unionMemberCount, _Out_ oss); + //if(bResult == FALSE) goto End; + for(int i = 0; i < unionMemberCount; i++) + { + ParamDesc memberDesc; + std::ostringstream ossMemberName; + + + // each member inherits it properties from the union + memberDesc.inheritProperties(unionDesc); + + + //lire la description du membre courant de l'union + RPC_GET_PROCESS_DATA( + pType, + &unionMemberToPrint, + sizeof(ArmXCase_t)); + + // set memberDesc info + ossMemberName << "unionMember_" << unionMemberToPrint.armCaseValue; + memberDesc.setParamName(ossMemberName.str()); + + pType += ARM_X_CASE_SIZE; + + if(bIsEncapsulatedUnion) + { + oss<<"\t\tcase ("<= MIN_UNION_SIMPLE_TYPE_ENCODE) && + ( ((UINT16) unionMemberToPrint.offsetToArmDescription) <= MAX_UNION_SIMPLE_TYPE_ENCODE) + ) + {//member is a simple type + + bResult = processSimpleType( + pContext, + (FC_TYPE) (unionMemberToPrint.offsetToArmDescription & FC_MAGIC_UNION_GET_SIMPLE_TYPE), + memberDesc, + oss); + + if (bResult == FALSE) goto End; + + + + } + else //member is a complex type + { + RVA_T pComplexType; + + //member description is localized at the relative offset unionMemberToPrint.offsetToArmDescription + //Calculate the absolute offset where unionMemberToPrint.offsetToArmDescription points + pComplexType = (pType //(fin du offsetToSizeAndArmDescription courant) + - sizeof(unionMemberToPrint.offsetToArmDescription) //base de l'offset à calculer + + unionMemberToPrint.offsetToArmDescription); //ajout de la valeur relative de l'offset contenue dans unionMemberToPrint.offsetToArmDescription + + + //memberDesc.setuOffset((UINT)(pComplexType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString)); + memberDesc.setRva(pComplexType); + + //rpcDumpType + bResult = rpcDumpType( + pContext, + memberDesc, + listAdditionalsType, + oss); + + + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[printEachUnionMember] : unable to dump complex type"); + goto End; + } + } + + oss << ";" << std::endl; + + + } + + // process default + RPC_GET_PROCESS_DATA( + pType, + &defaultArmToPrint, + sizeof(DefaultArmDescr_t)); + + + switch(defaultArmToPrint) + { + + + + case NO_DEFAULT_ARM_DESCRIPTION: + oss<<"\t/* no default member to print for this Union.\n\tAn exception will be raised if the switch_is value does not match any of the cases values */\n"; + RPC_DEBUG_FN((UCHAR*)"\nPrintTypeUnionNonEncapsulated : no default member to print for this Union"); + bResult = TRUE; + break; + + case EMPTY_DEFAULT_ARM_DESCRIPTION: + if(bIsEncapsulatedUnion) + { + oss<<"\t\tdefault:\n\t\t;"<= MIN_UNION_SIMPLE_TYPE_ENCODE) && + ( ((UINT16) defaultArmToPrint) <= MAX_UNION_SIMPLE_TYPE_ENCODE) + ) + { + ParamDesc defaultMemberDesc; + defaultMemberDesc.setParamName("defaultMember"); + + + + //default = simple type + bResult = processSimpleType( + pContext, + (FC_TYPE) (defaultArmToPrint & FC_MAGIC_UNION_GET_SIMPLE_TYPE), + defaultMemberDesc, + oss); + + if (bResult == FALSE) goto End; + } + else //default = complex type + { + ParamDesc defaultMemberDesc; + + //member description is localized at the relative offset defaultArmToPrint + //Calculate the absolute offset where defaultArmToPrint points + pType = (pType //base de l'offset à calculer + + (INT16) defaultArmToPrint); //ajout de la valeur relative de l'offset contenue dans defaultArmToPrint + + defaultMemberDesc.setParamName("defaultMember"); + //defaultMemberDesc.setuOffset((UINT)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString)); + defaultMemberDesc.setRva(pType); + + + //rpcDumpType + bResult = rpcDumpType( + pContext, + defaultMemberDesc, + listAdditionalsType, + oss); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"\n!!! source = %s ligne = %d - PrintParamOfFieldType returned bResult = %d", __FILE__, __LINE__, bResult); + goto End; + } + } + + oss << ";"<& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + RVA_T pType = unionDesc.getpNonEncapuslatedUnionHeader(); + FC_TYPE switchType; + UnionArmSelector_t unionArmSeltorToPrint; + UINT16 unionMemberCount = 0; + NonEncapUnionHeader_t nonEncapUnionHeader; + //short offsetToSizeAndArmDescr; + + #ifdef DBG_DECOMP + + oss << std::endl; + oss << "\t /* FC_NON_ENCAPSULATED_UNION , offset : NO_MORE "; //<< (int)unionStrDesc.getuOffset(); + oss << ", pType : 0x" << std::hex << (int)unionDesc.getpType() << std::dec << " */"; + #endif + + + + // read nonEncapUnionHeader + RPC_GET_PROCESS_DATA( + pType, + &nonEncapUnionHeader, + sizeof(nonEncapUnionHeader) + ); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[defineTypeNonEncapsulatedUnion] ERROR : unable to get process data"); + return FALSE; + } + + // display switch type + switchType = (FC_TYPE) nonEncapUnionHeader.switchType; + + + //// skip switch_is_description (already processed by processNonEncapsulatedUnion function) + //pType += sizeof(nonEncapUnionHeader); + //if(robustFlagWasSet) + //{ + // pType += sizeof(CorrelationDescriptorRobust_t); + //} + //else + //{ + // pType += sizeof(CorrelationDescriptorRobust_t); + //} + + //// get offset to size_and_arm description + //RPC_GET_PROCESS_DATA( + // pType, + // &offsetToSizeAndArmDescr, + // sizeof(offsetToSizeAndArmDescr) + //); + // + + + //pType += offsetToSizeAndArmDescr; + + + + //pType = pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString + unionStrDesc.getuOffset() + sizeof(INT16); + + pType = unionDesc.getRva(); + pType += sizeof(INT16); // skip memory size + + + //Determine the number of member of the union + RPC_GET_PROCESS_DATA( + pType, + &unionArmSeltorToPrint, + sizeof(UnionArmSelector_t) + ); + pType += sizeof(UnionArmSelector_t); + + unionMemberCount = unionArmSeltorToPrint & UNION_ARM_SELTOR_NB_UNION_MEMBER_MASK; + + + //start to print the union + oss<pRpcDecompilerInfo->pTypeFormatString) <pRpcDecompilerInfo->pTypeFormatString) <<";"<& listAdditionalTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + EncapUnion_t encapUnionToPrint; + UnionArmSelector_t unionArmSeltorToPrint; + + UINT16 unionMemberCount = 0; + UINT32 unionOffsetValueToContructTypeName = (UINT32)(pType - pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString); + ParamDesc memberDesc; + + RPC_GET_PROCESS_DATA( + pType, + &encapUnionToPrint, + sizeof(EncapUnion_t) + ); + + if(encapUnionToPrint.unionType != FC_ENCAPSULATED_UNION) + { + RPC_DEBUG_FN((UCHAR*)"\nPrintTypeUnionEncapsulated ERROR : unionType != FC_ENCAPSULATED_UNION"); + bResult = FALSE; + goto End; + } + pType += sizeof(EncapUnion_t); + + //Determine the number of member of the union + RPC_GET_PROCESS_DATA( + pType, + &unionArmSeltorToPrint, + sizeof(UnionArmSelector_t) + ); + pType += sizeof(UnionArmSelector_t); + + unionMemberCount = unionArmSeltorToPrint & UNION_ARM_SELTOR_NB_UNION_MEMBER_MASK; + + //start to print the union + oss<<"\n\ttypedef union union_"<< std::dec << unionOffsetValueToContructTypeName<<" switch ("; + + bResult = printSimpleType(pRpcDecompilerCtxt, (FC_TYPE)(encapUnionToPrint.switchType & ENCAP_UNION_SWITCH_TYPE_TYPE_MASK) , /* in/out */ oss); + oss<<" discrim) U"< +#include "internalRpcDecompTypeDefs.h" + + +//-------------------------------------------------------------------------- +BOOL __fastcall processNonEncapsulatedUnion( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//-------------------------------------------------------------------------- +BOOL __fastcall getNonEncapsulatedUnionMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize, + _In_ BOOL bHasRangeOnConformance); + + +//-------------------------------------------------------------------------- +BOOL __fastcall processEncapsulatedUnion( + _In_ VOID* pContext, + _In_ const RVA_T pType, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& ParamDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//-------------------------------------------------------------------------- +BOOL __fastcall getEncapsulatedUnionMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize); + + +//-------------------------------------------------------------------------- +BOOL __fastcall defineTypeNonEncapsulatedUnion( + _In_ VOID* pContext, + _In_ const TypeToDefine& unionDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + +//-------------------------------------------------------------------------- +BOOL __fastcall defineTypeEncapsulatedUnion( + _In_ VOID* pContext, + _In_ RVA_T pType, + _In_ const TypeToDefine& unionDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + + + +#endif//_INTERNAL_COMPLEX_TYPES_UNIONS_H_ \ No newline at end of file diff --git a/RpcDecompiler/internalRpcDecompTypeDefs.h b/RpcDecompiler/internalRpcDecompTypeDefs.h new file mode 100644 index 0000000..8f0d58b --- /dev/null +++ b/RpcDecompiler/internalRpcDecompTypeDefs.h @@ -0,0 +1,2010 @@ +#ifndef _INTERNAL_RPC_DECOMP_TYPE_DEFS_H_ +#define _INTERNAL_RPC_DECOMP_TYPE_DEFS_H_ + + +#include +#include +#include + + +#include "..\RpcCommon\RpcView.h" +#include "RpcDecompiler.h" + +extern boolean robustFlagWasSet; +extern BOOL is64B; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// Private types declaration +//////////////////////////////////////////////////////////////////////////////// +typedef struct _RpcDecompilerCtxt_T{ + RpcViewHelper_T* pRpcViewHelper; + RpcDecompilerInfo_T* pRpcDecompilerInfo; + RpcModuleInfo_T* pRpcModuleInfo; + //... +}RpcDecompilerCtxt_T; + +#ifdef _DEBUG +#define DEBUG_BREAK() __debugbreak() +#define DEBUG_EXIT(x) ExitProcess(x) +#else +#define DEBUG_BREAK() +#define DEBUG_EXIT(x) +#endif + +#define DEFAULT_IF_NAME "DefaultIfName" +#define RPC_DECOMPILER_INVALID_TYPE_SIZE ((UINT)-1) +#define RPC_DECOMPILER_INVALID_PARAM_SIZE ((UINT)-1) +//#define RPC_DEBUG_FN pRpcDecompilerCtxt->pRpcViewHelper->RpcDebug +#define RPC_ERROR_FN(x) printf("[%s] error %s",__FUNCTION__,x); +#define RPC_DEBUG_FN(...) printf((const char*)__VA_ARGS__) +#define RPC_PRINT_FN pRpcDecompilerCtxt->pRpcViewHelper->RpcPrint +#define RPC_ALLOC_FN pRpcDecompilerCtxt->pRpcViewHelper->RpcAlloc +#define RPC_FREE_FN pRpcDecompilerCtxt->pRpcViewHelper->RpcFree +#define RPC_GET_PROCESS_DATA( pAddress, pBuffer, BufferLength) \ +{ \ + /*BOOL bResult;*/ \ + \ + bResult = pRpcDecompilerCtxt->pRpcViewHelper->RpcGetProcessData(pRpcDecompilerCtxt->pRpcModuleInfo, pAddress, pBuffer, BufferLength); \ + if(bResult == FALSE) \ +{ \ + RPC_DEBUG_FN((UCHAR*)"\n!!! source = %s ligne = %d - ERROR RpcGetProcessData", __FILE__, __LINE__); \ + *((UCHAR*)NULL)=0; \ +} \ +} +#define RPC_GET_PROCESS_DATA2( pAddress, pBuffer, BufferLength) pRpcDecompilerCtxt->pRpcViewHelper->RpcGetProcessData(pRpcDecompilerCtxt->pRpcModuleInfo, pAddress, pBuffer, BufferLength) \ + +#define ERROR_ZERO_TYPEOFFSET_MSG "\nERROR: TypeOffset == 0 whereas Type is not simple Type\n" + + +#define NB_DIGIT_MAX_INT_32BITS_BASE_10 11 //2^32 = 4294967296 ==> 10 caractères ou word +//2^31 = 2147483648 + signe ==> 11 caractères ou word +#define BASE_10 10 + +#define EMPTY_PARAM_ATTR 0x0000 + +#define VIRTUAL_STACK_OFFSET_GRANULARITY_32B 4 +#define VIRTUAL_STACK_OFFSET_GRANULARITY_64B 8 +#define VIRTUAL_STACK_OFFSET_GRANULARITY (is64B?VIRTUAL_STACK_OFFSET_GRANULARITY_64B:VIRTUAL_STACK_OFFSET_GRANULARITY_32B) + + + +//////////////////////////////////////////////////////////////////////////////// +// Codes retour de fonctions +//////////////////////////////////////////////////////////////////////////////// +typedef enum RpcDecompilerErrorCodes_E +{ + RPC_DECOMP_SUCCESS = 0, + RPC_DECOMP_ERROR = 1, + RPC_DECOMP_NULL_PTR = 2, + RPC_DECOMP_NEED_MORE_SOURCE_BYTE = 3 +}RpcDecompilerErrorCodes_E; + +//////////////////////////////////////////////////////////////////////////////// +// _MIDL_PROC_FORMAT_STRING types +//////////////////////////////////////////////////////////////////////////////// + +// types de headers possibles +typedef enum HeaderID_E +{ + oi, // voir typedef struct Oi_Header_t + oif, // voir typedef struct Oif_Header_t + win2kext, // voir typedef struct Win2kExt_Header_t + + undefHeaderType +}HeaderID_E; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// HANDLE types +//------------------------------------------------------------------------------ +// handle_type values +//#define FC_BIND_CONTEXT 0x30 +//#define FC_BIND_GENERIC 0x31 +//#define FC_BIND_PRIMITIVE 0x32 +//#define FC_AUTO_HANDLE 0x33 +//#define FC_CALLBACK_HANDLE 0x34 +#define FC_EXPLICIT_HANDLE 0x00 + +#pragma pack(push, 1) // Align all structure on 1 byte + +typedef struct ExplicitHandlePrimitive_t +{ + unsigned char flag; + unsigned short offset; +}ExplicitHandlePrimitive_t; + +typedef struct ExplicitHandleGeneric_t +{ + unsigned char flagAndSize; + unsigned short offset; + unsigned char binding_routine_pair_index; + unsigned char pad; +}ExplicitHandleGeneric_t; + +typedef struct ExplicitHandleContext_t +{ + unsigned char flags; + unsigned short offset; + unsigned char context_rundown_routine_index; + unsigned char param_num; +}ExplicitHandleContext_t; + +typedef union ExplicitHandle_U +{ + ExplicitHandlePrimitive_t explicitHandlePrimitive; + ExplicitHandleGeneric_t explicitHandleGeneric; + ExplicitHandleContext_t explicitHandleContext; +}ExplicitHandle_U; + +#define EXPLICIT_HANDLE_MIN_SIZE 4 // EXPLICIT_HANDLE_PRIMITIVE_SIZE +#define EXPLICIT_HANDLE_PRIMITIVE_SIZE 4 // sizeof(ExplicitHandle_t.htype) + sizeof(ExplicitHandlePrimitive_t) +#define EXPLICIT_HANDLE_GENERIC_SIZE 6 // sizeof(ExplicitHandle_t.htype) + sizeof(ExplicitHandleGeneric_t) +#define EXPLICIT_HANDLE_CONTEXT_SIZE 6 // sizeof(ExplicitHandle_t.htype) + sizeof(ExplicitHandleContext_t) +typedef struct ExplicitHandle_t +{ + unsigned char htype; // voir handle_type values + ExplicitHandle_U hContent; +}ExplicitHandle_t; + + + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// OI header types +//------------------------------------------------------------------------------ +//oi_flags values +#define Oi_FULL_PTR_USED 0x01 //Uses the full pointer package +#define Oi_RPCSS_ALLOC_USED 0x02 //Uses the RpcSs memory package +#define Oi_OBJECT_PROC 0x04 //A procedure in an object interface +#define Oi_HAS_RPCFLAGS 0x08 //The procedure has Rpc flags +#define Oi_star10 0x10 //Overloaded +#define Oi_star20 0x20 //Overloaded +#define Oi_USE_NEW_INIT_ROUTINES 0x40 //Uses Windows NT3.5 Beta2+ init routines +#define Oi_Unused 0x80 //Unused + +//oi_flags values : the following flags are overloaded +#define ENCODE_IS_USED 0x10 //Used only in pickling +#define DECODE_IS_USED 0x20 //Used only in pickling +#define Oi_IGNORE_OBJECT_EXCEPTION_HANDLING 0x10 //Not used any more (old OLE) +#define Oi_HAS_COMM_OR_FAULT 0x20 //In raw RPC only, [comm _, fault_status] +#define Oi_OBJ_USE_V2_INTERPRETER 0x20 //In DCOM only, use -Oif interpreter + + + + + + +typedef struct Oi_Header_1stPart_t +{ + unsigned char handle_type; // voir handle_type values + unsigned char oi_flags; // voir oi_flags values +}Oi_Header_1stPart_t; + + +typedef struct Oi_Header_RpcFlags_t +{ + unsigned char rpc_flags[4]; +}Oi_Header_RpcFlags_t; + +typedef struct Oi_Header_3rdPart_t +{ + unsigned short procNum; // provides the procedure's procedure number + unsigned short stack_size; /* provides the total size of all parameters on the stack, + including any this pointer and/or return value */ +}Oi_Header_3rdPart_t; + +#define OI_EXT_HEADER_BASE_SIZE 6 +#define OI_EXT_HEADER_OIFLAGS_SIZE 4 // si oi_flags contient flag Oi_HAS_RPCFLAGS +typedef struct Oi_Header_t +{ + unsigned char handle_type; // voir handle_type values + unsigned char oi_flags; // voir oi_flags values + Oi_Header_RpcFlags_t * pRpcFlags; // != NULL si oi_flags contient Oi_HAS_RPCFLAGS sinon NULL + unsigned short procNum; // provides the procedure's procedure number + unsigned short stack_size; /* provides the total size of all parameters on the stack, + including any this pointer and/or return value */ + ExplicitHandle_t * explicitHandleDescr; /* NULL si handle_type != FC_EXPLICIT_HANDLE */ +}Oi_Header_t; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// OIF header types +//------------------------------------------------------------------------------ +//interpreter_opt_flag values +typedef struct INTERPRETER_OPT_FLAGS +{ + unsigned char ServerMustSize : 1; // 0x01 set if the server needs to perform a buffer sizing pass + unsigned char ClientMustSize : 1; // 0x02 set if the client needs to perform a buffer sizing pass + unsigned char HasReturn : 1; // 0x04 set if the procedure has a return value + unsigned char HasPipes : 1; // 0x08 set if the pipe package needs to be used to support a pipe argument + unsigned char Unused : 1; + unsigned char HasAsyncUuid : 1; // 0x20 set if the procedure is a, asynchronous DCOM procedure + unsigned char HasExtensions : 1; // 0x40 indicates that Windows 2000 and later extensions are used, voir Win2kExt_Header_t + unsigned char HasAsyncHandle : 1; /* 0x80 indicates an asynchronous RPC procedure + The HasAsyncHandle bit has been initially used for a different DCOM implementation + of async support, and hence could not be used for the current style async support + in DCOM. The HasAsyncUuid bit currently indicates this. */ +} INTERPRETER_OPT_FLAGS, *PINTERPRETER_OPT_FLAGS; + +#define OIF_EXT_HEADER_SIZE 6 +typedef struct Oif_Header_t +{ + // Oi_Header_t oiHeader; // Voir Oi_Header_t + unsigned short constant_client_buffer_size;/* Provides the size of the marshaling buffer that could have + been precomputed by the compiler. This may be only a partial size, + as the CLIENT_MUST_SIZE flag triggers the sizing. */ + unsigned short constant_server_buffer_size;/* Provides the size of the marshaling buffer that could have + been precomputed by the compiler. This may be only a partial size, + as the SERVER_MUST_SIZE flag triggers the sizing. */ + INTERPRETER_OPT_FLAGS interpreter_opt_flag; // Voir interpreter_opt_flag values + unsigned char number_of_param; // Nombre de paramètres décrits de la procédure, return compris +}Oif_Header_t; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// WIN2KEXT header types +//------------------------------------------------------------------------------ +//interpreter_opt_flag2 values +typedef struct INTERPRETER_OPT_FLAGS2 +{ + unsigned char HasNewCorrDesc : 1; /* 0x01 The HasNewCorrDesc member indicates whether new correlation descriptors + are used in the format strings generated by the compiler. The new correlation + descriptor is related to the denial-of-attack functionality. The ClientCorrCheck + and ServerCorrCheck members are set when the routine needs the correlation check + on the indicated side. */ + unsigned char ClientCorrCheck : 1; /* 0x02 The ClientCorrCheck member is a cache size hint on the client side and + ServerCorrCheck is a hint on the server side. When the size comes out as zero, + a default size should be used. */ + unsigned char ServerCorrCheck : 1; /* 0x04 The ClientCorrCheck member is a cache size hint on the client side and + ServerCorrCheck is a hint on the server side. When the size comes out as zero, + a default size should be used. */ + unsigned char HasNotify : 1; /* 0x08 The HasNotify and HasNotify2 flags indicate that the routine uses the notify + feature as defined by the [notify] and [notify_flag] attributes, respectively. */ + unsigned char HasNotify2 : 1; /* 0x10 The HasNotify and HasNotify2 flags indicate that the routine uses the notify + feature as defined by the [notify] and [notify_flag] attributes, respectively. */ + unsigned char HasComplexReturn : 1; /* 0x20 Undocumented flag. Unknown purpose */ + unsigned char HasRangeOnConf : 1; /* 0x40 Undocumented flag. If set, check for range information within NDR structures (array...) */ + unsigned char HasBigByValueParam : 1; /* 0x80 Undocumented flag. Purpose unknown so far. */ + +} INTERPRETER_OPT_FLAGS2, *PINTERPRETER_OPT_FLAGS2; + +typedef UINT16 FloatDoubleMask_t; /* The FloatDoubleMask element addresses the issue of a floating point argument for 64-bit Windows. + This field is generated only for 64-bit stubs. The mask is needed for the assembly routines that + download/upload registers from/to the virtual stack to handle floating-point arguments and registers + properly. The mask consist of 2 bits per argument, or rather per floating-point register. + The coding is as follows: The least significant bits correspond to the first FP register, the next 2 + bits correspond to the second register, and so on. */ + +#define WIN2K_EXT_HEADER_32B_SIZE sizeof(Win2kExt_Header_t) - sizeof(FloatDoubleMask_t) +#define WIN2K_EXT_HEADER_64B_SIZE sizeof(Win2kExt_Header_t) /* TODO : verifier avec test car valeur 12 extraite de la doc MSDN mais doute sur valeur + car somme taille des champs = 10 pas 12... */ +typedef struct Win2kExt_Header_t +{ + // Oif_Header_t oifHeader; // Voir Oif_Header_t + unsigned char extension_version; /* Provides the size of the Win2kExt section in bytes. Doing so + make it possible for the current NDR engine to step over the extension + section correctly even if the section were to come from a mater compiler + version with more fields than the current engine understands. + */ + INTERPRETER_OPT_FLAGS2 interpreter_opt_flag2; // Voir interpreter_opt_flag2 values + unsigned short clientCorrHint; /* The ClientCorrCheck member is a cache size hint on the client side and + ServerCorrCheck is a hint on the server side. When the size comes out as zero, + a default size should be used. */ + unsigned short serverCorrHint; + unsigned short notifyIndex; // TODO ? : The NotifyIndex element is an index to a notify routine, if one is used. + FloatDoubleMask_t floatDoubleMask; /* Si extension_version == WIN2K_EXT_HEADER_32B_SIZE floatDoubleMask est non présent, + sinon si extension_version == WIN2K_EXT_HEADER_64B_SIZE floatDoubleMask est présent */ +}Win2kExt_Header_t; + + + +// +// Oi Header +typedef struct _OI_HEADER_BEGINNING_T +{ + BYTE bHandle_type; + BYTE bOi_flags; +}OI_HEADER_BEGINNING_T; + +typedef struct _OI_HEADER_END_T +{ + WORD wProc_num; + WORD wStack_size; + // [explicit_handle_description<>] +}OI_HEADER_END_T; + +typedef struct _OI_HEADER_T +{ + OI_HEADER_BEGINNING_T beginning; + DWORD dwRpc_flags; + OI_HEADER_END_T end; +}OI_HEADER_T; + +// Oif fields +typedef struct _OIF_HEADER_T +{ + WORD wConstant_client_buffer_size; + WORD wConstant_server_buffer_size; + BYTE bINTERPRETER_OPT_FLAGS; + BYTE bNumber_of_params; +}OIF_HEADER_T; + +// +// Procedure header +typedef struct _PROC_HEADER_T +{ + OI_HEADER_T oiHeader; + ExplicitHandle_t explicitHandle; + OIF_HEADER_T oifheader; + Win2kExt_Header_t win2KextHeader; +}PROC_HEADER_T; + + + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// UNION HEADER type (OI / OIF / WIN2KEXT) +//------------------------------------------------------------------------------ +typedef union ProcFormatStringHeader_U +{ + Oi_Header_t oiHeader; + Oif_Header_t oifHeader; + Win2kExt_Header_t win2kHeader; +}ProcFormatStringHeader_U; + +typedef struct ProcFormatStringHeader_t +{ + HeaderID_E headerTypeID; // Voir HeaderID_E + unsigned int headerEffectiveSize; /* OI_EXT_HEADER_BASE_SIZE si headerTypeID == oi + ou OI_EXT_HEADER_OIFLAGS_SIZE si headerTypeID == oi et Oi_Header_t.oi_flags contient Oi_HAS_RPCFLAGS + + + OIF_EXT_HEADER_SIZE si headerTypeID == oif ou headerTypeID == win2kext + + Win2kExt_Header_t.extension_version si headerTypeID == win2kext */ + + ProcFormatStringHeader_U headerContent; /* Voir Oi_Header_t si HeaderID_E == oi + Voir Oif_Header_t si HeaderID_E == oif + Voir Win2kExt_Header_t si HeaderID_E == win2kext */ +}ProcFormatStringHeader_t; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// PARAM types +//------------------------------------------------------------------------------ +// types de param descriptor possibles +typedef enum ParamID_E +{ + paramDescrOi, // voir typedef struct ParamDescriptor_oi_t, Possible uniquement en environnement 32bits + paramDescrOif, // voir typedef struct ParamDescriptor_oif_t +}ParamID_E; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// OI PARAM descriptor types - The -Oi mode is not supported on 64-bit platforms +//------------------------------------------------------------------------------ +typedef struct OiParamComplexType_t +{ + unsigned char stack_size; /* The stack_size<1> is the size of the parameter on the stack, expressed + as the number of integers the parameter occupies on the stack. */ + unsigned short type_offset; /* The type_offset<2> field is the offset in the type format string table, + indicating the type descriptor for the argument. */ + +}OiParamComplexType_t; + +typedef unsigned char OiParamSimpleType_t; + +typedef union OiParamType_U +{ + OiParamSimpleType_t simple_type; + OiParamComplexType_t complex_type; +}OiParamType_U; + +// param_direction values +//#define FC_IN_PARAM_BASETYPE 0x4e +//#define FC_RETURN_PARAM_BASETYPE 0x53 +//#define FC_IN_PARAM 0x4d +//#define FC_IN_OUT_PARAM 0x50 +//#define FC_OUT_PARAM 0x51 +//#define FC_RETURN_PARAM 0x52 //A procedure return value +//#define FC_IN_PARAM_NO_FREE_INST 0x4f //An in xmit/rep as a parameter for which no freeing is made. + +typedef struct ParamDescriptor_oi_t // The -Oi mode is not supported on 64-bit platforms +{ + unsigned short param_direction; // Voir param_direction values + OiParamType_U paramType; /* Si param_direction == FC_IN_PARAM_BASETYPE ou FC_RETURN_PARAM_BASETYPE + Alors paramType est de type OiParamSimpleType_t + Sinon paramType est de type OiParamComplexType_t */ +}ParamDescriptor_oi_t; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// OIF PARAM descriptor types +//------------------------------------------------------------------------------ +//OIF paramAttributes values +typedef struct PARAM_ATTRIBUTES +{ + unsigned short MustSize : 1; // 0x0001 set only if the parameter must be sized + unsigned short MustFree : 1; // 0x0002 set if the server must call the parameter's NdrFree* routine + unsigned short IsPipe : 1; // 0x0004 + unsigned short IsIn : 1; // 0x0008 + unsigned short IsOut : 1; // 0x0010 + unsigned short IsReturn : 1; // 0x0020 + unsigned short IsBasetype : 1; /* 0x0040 set for simple types that are being marshaled by the main –Oif + interpreter loop. In particular, a simple type with a range + attribute on it is not flagged as a base type in order to force + the range routine marshaling through dispatching using an FC_RANGE + token. + */ + unsigned short IsByValue : 1; /* 0x0080 set for compound types being sent by value, but is not set for simple + types, regardless of whether the argument is a pointer. The compound + types for which it is set are structures, unions, transmit_as, + represent_as, wire_marshal and SAFEARRAY. In general, the bit was + introduced for the benefit of the main interpreter loop in the –Oicf + interpreter, to ensure the nonsimple arguments (refe rred to as compound + type arguments) are properly dereferenced. This bit was never used in + previous versions of the interpreter. + */ + unsigned short IsSimpleRef : 1; /* 0x0100 set for a parameter that is a reference pointer to anything + other than another pointer, and which has no allocate attributes. + For such a type, the parameter description's type_offset<> field, + except for a reference pointer to a base type, provides the offset + to the referent's type; the reference pointer is simply skipped. + */ + unsigned short IsDontCallFreeInst : 1; // 0x0200 set for certain represent_as parameters whose free instance routines should not be called. + unsigned short SaveForAsyncFinish : 1; // 0x0400 + unsigned short IsPartialIgnore : 1; /* 0x0800 Undocumented flag. Unknown purpose */ + unsigned short IsForceAllocate : 1; /* 0x1000 Undocumented flag. Unknown purpose */ + unsigned short ServerAllocSize : 3; /* 0xe000 bits are nonzero if the parameter is [ out], [ in], or [ in,out] + pointer to pointer, or pointer to enum16, and will be initialized + on the server interpreter's stack, rather than using a call to + I_RpcAllocate. If nonzero, this value is multiplied by 8 to get + the number of bytes for the parameter. Note that doing so means at + least 8 bytes are always allocated for a pointer. */ + +} PARAM_ATTRIBUTES, *PPARAM_ATTRIBUTES; + + +typedef struct ParamDescrOifBaseType_t +{ + unsigned char type_format_char; /* For base types, the argument type is given directly by the format character + corresponding to the type. */ + unsigned char unused; +}ParamDescrOifBaseType_t; + +typedef unsigned short ParamDescrOifOtherType_t; + +typedef union OifParamType_U +{ + ParamDescrOifBaseType_t base_type_format_char; // Voir ParamDescrOifBaseType_t + ParamDescrOifOtherType_t other_type_offset; /* For other types, the type_offset<2> field gives the offset in + the type format string table where the type descriptor for the + argument is located. */ +}OifParamType_U; + +typedef struct ParamDescriptor_oif_t +{ + PARAM_ATTRIBUTES paramAttributes; // Voir paramAttributes values + unsigned short stack_offset; /* Indicates the offset on the virtual argument stack, in bytes. + Pour Base types voir ParamDescrOifBaseType_t + Pour Other types voir OifParamType_U.other_type_offset + */ + OifParamType_U paramType; /* Si paramAttributes contient le flag IsBaseType + Alors paramType est de type ParamDescrOifBaseType_t + Sinon de type ParamDescrOifOtherType_t */ +}ParamDescriptor_oif_t; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// UNION PARAM type (OI / OIF format) +//----------------------------------------------------------------------------- +typedef union ProcFormatStringParam_U +{ + ParamDescriptor_oi_t oi_Format; + ParamDescriptor_oif_t oif_Format; +}ProcFormatStringParam_U; + +#define OI_PARAM_BASETYPE_SIZE 2 +#define OI_PARAM_OTHERTYPE_SIZE 4 +#define OIF_PARAM_SIZE 6 +typedef struct ProcFormatStringParam_t +{ + ParamID_E paramDescrType; // Voir ParamID_E + unsigned int fieldEffectiveSize; /* Si paramDescrType == paramDescrOi et + paramContent.oiFormat.param_direction == FC_IN_PARAM_BASETYPE ou + paramContent.oiFormat.param_direction == FC_RETURN_PARAM_BASETYPE + Alors fieldEffectiveSize = OI_PARAM_BASETYPE_SIZE + Sinon Si paramDescrType == paramDescrOi + Alors fieldEffectiveSize = OI_PARAM_OTHERTYPE_SIZE + + Si paramDescrType == paramDescrOi + Alors fieldEffectiveSize = OIF_PARAM_SIZE */ + ProcFormatStringParam_U paramContent; /* Voir ParamDescriptor_oi_t si paramDescrType == paramDescrOi + Voir ParamDescriptor_oif_t si paramDescrType == paramDescrOif */ + struct ProcFormatStringParam_t * nextParam; +}ProcFormatStringParam_t; + +//------------------------------------------------------------------------------ +// _MIDL_PROC_FORMAT_STRING types : +// MIDL_PROC_FORMAT_STRING +//----------------------------------------------------------------------------- +typedef struct Fabrique_MIDL_PROC_FORMAT_STRING +{ + short pad; + unsigned int cumulatedEffectiveSize; + ProcFormatStringHeader_t header; + ProcFormatStringParam_t * param; +}Fabrique_MIDL_PROC_FORMAT_STRING; + + + +////////////////////////////////////////////////////////////////////////////////// +//// _MIDL_TYPE_FORMAT_STRING types +////////////////////////////////////////////////////////////////////////////////// +enum FC_TYPE +{ + FC_ZERO = 0x0, + FC_BYTE = 0x1, + FC_CHAR = 0x2, + FC_SMALL = 0x3, + FC_USMALL = 0x4, + FC_WCHAR = 0x5, + FC_SHORT = 0x6, + FC_USHORT = 0x7, + FC_LONG = 0x8, + FC_ULONG = 0x9, + FC_FLOAT = 0xA, + FC_HYPER = 0xB, + FC_DOUBLE = 0xC, + FC_ENUM16 = 0xD, + FC_ENUM32 = 0xE, + FC_IGNORE = 0xF, + FC_ERROR_STATUS_T = 0x10, + FC_RP = 0x11, + FC_UP = 0x12, + FC_OP = 0x13, + FC_FP = 0x14, + FC_STRUCT = 0x15, + FC_PSTRUCT = 0x16, + FC_CSTRUCT = 0x17, + FC_CPSTRUCT = 0x18, + FC_CVSTRUCT = 0x19, + FC_BOGUS_STRUCT = 0x1A, + FC_CARRAY = 0x1B, + FC_CVARRAY = 0x1C, + FC_SMFARRAY = 0x1D, + FC_LGFARRAY = 0x1E, + FC_SMVARRAY = 0x1F, + FC_LGVARRAY = 0x20, + FC_BOGUS_ARRAY = 0x21, + FC_C_CSTRING = 0x22, + FC_C_BSTRING = 0x23, + FC_C_SSTRING = 0x24, + FC_C_WSTRING = 0x25, + FC_CSTRING = 0x26, + FC_BSTRING = 0x27, + FC_SSTRING = 0x28, + FC_WSTRING = 0x29, + FC_ENCAPSULATED_UNION = 0x2A, + FC_NON_ENCAPSULATED_UNION = 0x2B, + FC_BYTE_COUNT_POINTER = 0x2C, + FC_TRANSMIT_AS = 0x2D, + FC_REPRESENT_AS = 0x2E, + FC_IP = 0x2F, + FC_BIND_CONTEXT = 0x30, + FC_BIND_GENERIC = 0x31, + FC_BIND_PRIMITIVE = 0x32, + FC_AUTO_HANDLE = 0x33, + FC_CALLBACK_HANDLE = 0x34, + FC_UNUSED1 = 0x35, + FC_POINTER = 0x36, + FC_ALIGNM2 = 0x37, + FC_ALIGNM4 = 0x38, + FC_ALIGNM8 = 0x39, + FC_UNUSED2 = 0x3A, + FC_UNUSED3 = 0x3B, + FC_UNUSED4 = 0x3C, + FC_STRUCTPAD1 = 0x3D, + FC_STRUCTPAD2 = 0x3E, + FC_STRUCTPAD3 = 0x3F, + FC_STRUCTPAD4 = 0x40, + FC_STRUCTPAD5 = 0x41, + FC_STRUCTPAD6 = 0x42, + FC_STRUCTPAD7 = 0x43, + FC_STRING_SIZED = 0x44, + FC_UNUSED5 = 0x45, + FC_NO_REPEAT = 0x46, + FC_FIXED_REPEAT = 0x47, + FC_VARIABLE_REPEAT = 0x48, + FC_FIXED_OFFSET = 0x49, + FC_VARIABLE_OFFSET = 0x4A, + FC_PP = 0x4B, + FC_EMBEDDED_COMPLEX = 0x4C, + FC_IN_PARAM = 0x4D, + FC_IN_PARAM_BASETYPE = 0x4E, + FC_IN_PARAM_NO_FREE_INST = 0x4F, + FC_IN_OUT_PARAM = 0x50, + FC_OUT_PARAM = 0x51, + FC_RETURN_PARAM = 0x52, + FC_RETURN_PARAM_BASETYPE = 0x53, + FC_DEREFERENCE = 0x54, + FC_DIV_2 = 0x55, + FC_MULT_2 = 0x56, + FC_ADD_1 = 0x57, + FC_SUB_1 = 0x58, + FC_CALLBACK = 0x59, + FC_CONSTANT_IID = 0x5A, + FC_END = 0x5B, + FC_PAD = 0x5C, + FC_EXPR = 0x5D, + FC_SPLIT_DEREFERENCE = 0x74, + FC_SPLIT_DIV_2 = 0x75, + FC_SPLIT_MULT_2 = 0x76, + FC_SPLIT_ADD_1 = 0x77, + FC_SPLIT_SUB_1 = 0x78, + FC_SPLIT_CALLBACK = 0x79, + FC_HARD_STRUCT = 0xB1, + FC_TRANSMIT_AS_PTR = 0xB2, + FC_REPRESENT_AS_PTR = 0xB3, + FC_USER_MARSHAL = 0xB4, + FC_PIPE = 0xB5, + FC_BLKHOLE = 0xB6, + FC_RANGE = 0xB7, + FC_INT3264 = 0xB8, + FC_UINT3264 = 0xB9, + FC_END_OF_UNIVERSE = 0xBA, +}; + + + + + + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// correlation descriptors +//------------------------------------------------------------------------------ +/* A correlation descriptor is a format string that describes an expression based +on one argument related to another argument. A correlation descriptor is needed +for handling semantics related to attributes like [ size_is()], [ length_is()], +[ switch_is()] and [ iid_is()]. Correlation descriptors are used with arrays, +sized pointers, unions, and interface pointers. The eventual expression value can +be a size, a length, a union discriminant, or a pointer to an IID, respectively. +In terms of format strings, correlation descriptors are used with arrays, unions, +and interface pointers. A sized pointer is described in format strings as a +pointer to an array. + +Correlation descriptors have been designed to support only very limited expressions. +For complicated situations, the compiler generates an expression evaluation routine +to be called by the engine when needed. +*/ + +// correlation types +#define FC_NORMAL_CONFORMANCE 0x00 /* A normal case of conformance, such as that +described in a field of a structure. */ +#define FC_POINTER_CONFORMANCE 0x10 /* For attributed pointers ( size_is(), length_is()) +which are fields in a structure. This affects the +way the base memory pointer is set. */ +#define FC_TOP_LEVEL_CONFORMANCE 0x20 /* For top-level conformance described by another parameter. */ +#define FC_CONSTANT_CONFORMANCE 0x40 /* For a constant value. The compiler precalculates the value +from a constant expression supplied by the user. When this +is the case, the subsequent 3 bytes in the conformance +description contain the lower 3 bytes of a long describing +the conformance size. No further computation is required. */ +#define FC_TOP_LEVEL_MULTID_CONFORMANCE 0x80 /* For top-level conformance of a multidimensional array described +by another parameter. +Note Multidimensional sized arrays and pointers trigger a +switch to –Oicf. */ +#define CORR_TYPE_4_LOWER_NIBBLE_MASK 0x0F +#define CORR_TYPE_4_UPPER_NIBBLE_MASK 0xF0 + +typedef struct _NDR_CORRELATION_FLAGS +{ + unsigned short Early : 1; /* indicates early versus late correlation. An early correlation is when the expression + argument precedes the described argument, for example a size argument is before a sized + pointer argument. A late correlation is when the expression argument comes after the related + argument. The engine performs validation of early correlation values right away, the late + correlation values are stored for checking after unmarshaling is done. */ + unsigned short Split : 1; /* indicates an async split among [in] and [out] arguments. For example, a size argument may be + [in] while the sized pointer may be [out]. In the DCOM async context, these arguments happen + to be on different stacks, so the engine must be aware of this. */ + unsigned short IsIidIs : 1; /* indicates an iid_is() correlation. The NdrComputeConformance routine is tricked to obtain a + pointer to IID as an expression value, but the validation routine cannot compare such values + (they would be pointers) and so the flag indicates that actual IIDs need to be compared. */ + unsigned short DontCheck : 1; + unsigned short Ranged : 1; /* Undocumented flag. Something about range on conformance */ + unsigned short Unused : 11; +} NDR_CORRELATION_FLAGS; + +// correlation_operator values +//#define FC_DEREFERENCE 0x54 // The FC_DEREFERENCE constant is used for correlation being a pointee, like for [size_is(*pL)]. +//#define FC_DIV_2 0x55 // Arithmetic operators just use the indicated constant. +//#define FC_MULT_2 0x56 // Arithmetic operators just use the indicated constant. +//#define FC_ADD_1 0x57 // Arithmetic operators just use the indicated constant. +//#define FC_SUB_1 0x58 // Arithmetic operators just use the indicated constant. +//#define FC_CALLBACK 0x59 // The FC_CALLBACK constant indicates that an expression evaluation routine needs to be called. +//#define FC_EXPR 0x5D + + + + +typedef struct CorrelationDescriptorNonRobust_t +{ + unsigned char correlation_type; /* Voir correlation types pour les 4 bits de poids fort + FC_LONG | FC_ULONG | FC_SHORT | FC_USHORT | FC_SMALL + | FC_USMALL | FC_HYPER pour les 4 bits de poids faible */ + /* Note 64-bit expressions are not supported. FC_HYPER is used only for iid_is() on 64-bit platforms to extract the pointer value for IID*. */ + /* The compiler sets the type nibble to zero for the following cases: constant expression mentioned above and when evaluation expression routine + needs to be called, for example, when FC_CONSTANT_CONFORMANCE and FC_CALLBACK are used. */ + + unsigned char correlation_operator; // voir correlation_operator values + INT16 offset; + /* The offset<2> field is typically a relative memory offset to the expression argument variable. It can also be an expression evaluation–routine + index. As mentioned previously in this document, for constant expressions it is a part of actual, final expression value. + + The interpretation of the offset<2> field as memory offset depends on the complexity of the expression, the location of the expression variable, + and in the case of an array, whether the array is actually an attributed pointer. + + If the array is an attributed pointer and the conformance variable is a field in a structure, the offset field contains the offset from the beginning + of the structure to the conformance-describing field. If the array is not an attributed pointer and the conformance variable is a field in a structure, + the offset field contains the offset from the end of the nonconformant part of the structure to the conformance-describing field. Typically, the + conformant array is at the end of the structure. + + For top-level conformance, the offset field contains the offset from the stub's first parameter's location on the stack to the parameter that describes + the conformance. This is not used in –Os mode. There are other exceptions to the interpretation of the offset field; such exceptions are described in + the description of those types. + + When offset<2> is used with FC_CALLBACK, it contains an index in the expression evaluation routine table generated by the compiler. The stub message + is passed to the evaluation routine, which then computes the conformance value and assigns it to the MaxCount field of the stub message. + */ +}CorrelationDescriptorNonRobust_t; + +typedef struct CorrelationDescriptorRobust_t +{ + unsigned char correlation_type; /* Voir correlation types pour les 4 bits de poids fort + FC_LONG | FC_ULONG | FC_SHORT | FC_USHORT | FC_SMALL + | FC_USMALL | FC_HYPER pour les 4 bits de poids faible */ + /* Note 64-bit expressions are not supported. FC_HYPER is used only for iid_is() on 64-bit platforms to extract the pointer value for IID*. */ + /* The compiler sets the type nibble to zero for the following cases: constant expression mentioned above and when evaluation expression routine + needs to be called, for example, when FC_CONSTANT_CONFORMANCE and FC_CALLBACK are used. */ + + unsigned char correlation_operator; // voir correlation_operator values + INT16 offset; + /* The offset<2> field is typically a relative memory offset to the expression argument variable. It can also be an expression evaluation–routine + index. As mentioned previously in this document, for constant expressions it is a part of actual, final expression value. + + The interpretation of the offset<2> field as memory offset depends on the complexity of the expression, the location of the expression variable, + and in the case of an array, whether the array is actually an attributed pointer. + + If the array is an attributed pointer and the conformance variable is a field in a structure, the offset field contains the offset from the beginning + of the structure to the conformance-describing field. If the array is not an attributed pointer and the conformance variable is a field in a structure, + the offset field contains the offset from the end of the nonconformant part of the structure to the conformance-describing field. Typically, the + conformant array is at the end of the structure. + + For top-level conformance, the offset field contains the offset from the stub's first parameter's location on the stack to the parameter that describes + the conformance. This is not used in –Os mode. There are other exceptions to the interpretation of the offset field; such exceptions are described in + the description of those types. + + When offset<2> is used with FC_CALLBACK, it contains an index in the expression evaluation routine table generated by the compiler. The stub message + is passed to the evaluation routine, which then computes the conformance value and assigns it to the MaxCount field of the stub message. + */ + NDR_CORRELATION_FLAGS robust_flags; +}CorrelationDescriptorRobust_t; + + +#define ROBUST_DELTA (sizeof(CorrelationDescriptorRobust_t) - sizeof(CorrelationDescriptorNonRobust_t)) + +typedef union CorrelationDescriptor_U +{ + CorrelationDescriptorNonRobust_t corrDescNonRobust; + CorrelationDescriptorRobust_t corrDescRobust; +}CorrelationDescriptor_U; + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types pointeurs +//------------------------------------------------------------------------------ + +// pointer_attributes values +enum FC_POINTER_ATTRIBUTE +{ + FC_ALLOCATE_ALL_NODES=0x1, // The pointer is a part of an allocate(all_nodes) allocation scheme. + FC_DONT_FREE=0x2, // An allocate(dont_free) pointer + FC_ALLOCED_ON_STACK=0x4, // A pointer whose referent is allocated on the stub's stack. + FC_SIMPLE_POINTER=0x8, /* A pointer to a simple type or nonsized conformant string. This + //flag being set indicates layout of the pointer description as the + //simple pointer layout described above, otherwise the descriptor + //format with the offset is indicated. */ + FC_POINTER_DEREF=0x10, // A pointer that must be dereferenced before handling the pointer's referent. + /* Pointers that have size_is(), max_is(), length_is(), last_is(), and/or first_is() applied to them have + format string descriptions identical to a pointer to an array of the appropriate type (for example, a + conformant array if size_is() is applied, a conformant varying array if size_is() and length_is are applied). + */ + FC_MAYBENULL_SIZEIS=0x20 // Undocumented flag. +}; + + +typedef struct CommonPtrSimple_t +{ + unsigned char pointerType; // Voir pointer_type values : FC_RP ou FC_UP ou FC_FP ou FC_OP + unsigned char pointer_attributes; // Voir pointer_attributes values + unsigned char simple_type; // Voir simple_types values + unsigned char pad; // FC_PAD +}CommonPtrSimple_t; +#define SIZE_COMMON_PTR_SIMPLE sizeof(CommonPtrSimple_t) + +typedef struct CommonPtrComplex_t +{ + unsigned char pointerType; // Voir pointer_type values : FC_RP ou FC_UP ou FC_FP ou FC_OP + unsigned char pointer_attributes; // Voir pointer_attributes values + INT16 offset_to_complex_description; // Offset vers la description du type dans MIDL_TYPE_FORMAT_STRING +}CommonPtrComplex_t; + + +typedef struct InterfacePtrConstantIID_t +{ + unsigned char pointerType; // Voir pointer_type values : FC_IP + unsigned char fc_constant_IID_code; // FC_CONSTANT_IID + GUID iid; /* The iid<16> part is the actual IID for the interface pointer. The iid + is written to the format string in a format identical to the GUID data + structure: long, short, short, char [8]. */ +}InterfacePtrConstantIID_t; + +typedef struct InterfacePtrNonConstantIID_t +{ + unsigned char pointerType; // Voir pointer_type values : FC_IP + unsigned char pad; // FC_PAD + CorrelationDescriptor_U iid_description; /* CorrelationDescriptorRobust_t si /robust + Sinon CorrelationDescriptorNonRobust_t */ +}InterfacePtrNonConstantIID_t; + + +typedef struct ByteCountHeader_T +{ + unsigned char pointerType; // FC_BYTE_COUNT_POINTER + unsigned char simpleTypeOrPad; // simple type or FC_PAD +}ByteCountHeader_T; + +typedef struct ByteCountPtrSimple_t +{ + ByteCountHeader_T byteCountHeader; + CorrelationDescriptor_U byte_count_description; /* CorrelationDescriptorRobust_t si /robust + Sinon CorrelationDescriptorNonRobust_t */ +}ByteCountPtrSimple_t; + +typedef struct ByteCountPtrComplex_t +{ + ByteCountHeader_T byteCountHeader; + CorrelationDescriptor_U byte_count_description; /* CorrelationDescriptorRobust_t si /robust + Sinon CorrelationDescriptorNonRobust_t */ + unsigned char * pointee_description; //TODO : taille de ce parametre ? +}ByteCountPtrComplex_t; + +typedef union PointerTypeContent_U +{ + CommonPtrSimple_t commonPtrSimple; + CommonPtrComplex_t commonPtrComplex; + InterfacePtrConstantIID_t interfPtrConstantIID; + InterfacePtrNonConstantIID_t interfPtrNonConstantIID; + ByteCountPtrSimple_t byteCountPtrSimple; + ByteCountPtrComplex_t byteCountPtrComplex; +}PointerTypeContent_U; + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types pointer layout +//------------------------------------------------------------------------------ +// Pointer layout describes pointers of a structure or an array. + + +/* A pointer layout has a variable size and is composed of +- a PointerLayoutHeader_t +- one or several pointer instance layout which can be 3 different structures with different size : +- SingleInstancePtrToSimpleType_t wich contains one PointerInstance_t +- FixedRepeatPtr_t + one or several additional PointerInstance_t +- VariableRepeatPtr_t + one or several additional PointerInstance_t +- a PointerLayoutEnd_t +*/ +#define POINTER_LAYOUT_MIN_SIZE (sizeof(PointerLayoutHeader_t) + sizeof(SingleInstancePtrToSimpleType_t) + sizeof(PointerLayoutEnd_t)) +typedef struct PointerLayoutHeader_t +{ + UINT8 pointerType; // FC_PP + UINT8 pad; // FC_PAD +}PointerLayoutHeader_t; + +// one or several pointer instance layout, see SingleInstancePtrToSimpleType_t, FixedRepeatPtrHeader_t and VariableRepeatPtrHeader_t below + +typedef UINT8 PointerLayoutEnd_t; // FC_END + + +// a pointer instance layout contains at least one PointerInstance_t +typedef union PointerDescription_U +{ + CommonPtrSimple_t commonPtrSimple; + CommonPtrComplex_t commonPtrComplex; +}PointerDescription_U; + +typedef struct PointerInstance_t +{ + INT16 offsetToPtrInMemory; /* The signed offset to the pointer's location in memory. For a pointer residing + in a structure, this offset is a negative offset from the end of the structure + (the end of the nonconformant portion of conformant structures); for arrays, + the offset is from the beginning of the array. + */ + INT16 offsetToPtrInBuffer; /* The signed offset to the pointer's location in the buffer. For a pointer residing + in a structure, this offset is a negative offset from the end of the structure + (the end of the nonconformant portion of conformant structures): for arrays, the + offset is from the beginning of the array. + */ + PointerDescription_U pointerDescription; /* d'après la doc MSDN partie Pointer Layout, + pointerDescription est de taille 4 ce qui correspond à la taille des types + commonPtrSimple et commonPtrComplex. + TODO : valider cette hypothèse au cours des tests + */ +}PointerInstance_t; + + +typedef struct SingleInstancePtrToSimpleType_t +{ + UINT8 repeatType; // FC_NO_REPEAT + UINT8 pad; // FC_PAD + PointerInstance_t pointerInstance; // voir PointerInstance_t +}SingleInstancePtrToSimpleType_t; + + +#define OFFSET_SINGLE_INSTANCE_TO_PTR_DESC FIELD_OFFSET(SingleInstancePtrToSimpleType_t , pointerInstance) + FIELD_OFFSET(PointerInstance_t,pointerDescription) + + +//For fixed repeat and variable repeat pointer instances there is a set of offset and pointer descriptions for each pointer in the repeat instance. +typedef struct FixedRepeatPtr_t +{ + UINT8 repeatType; // FC_FIXED_REPEAT + UINT8 pad; // FC_PAD + UINT16 iterations; // Total number of pointers that have the same layout<> described. + UINT16 increment; // Increment between successive pointers during a REPEAT. + INT16 offsetToArray; /* Offset from an enclosing structure to the embedded array whose + pointers are being handled. For top-level arrays, this field will always be zero. */ + UINT16 numberOfPointers; // Number of different pointers in a repeat instance. + //PointerInstance_t pointerInstance; /* Several pointerInstance can follow according to iterations, increment and numberOfPointers. + // PointerInstance_t pointerInstance; See PointerInstance_t */ +}FixedRepeatPtr_t; + +//For fixed repeat and variable repeat pointer instances there is a set of offset and pointer descriptions for each pointer in the repeat instance. +typedef struct VariableRepeatPtr_t +{ + UINT8 repeatType0; // FC_VARIABLE_REPEAT + UINT8 repeatType1; // FC_FIXED_OFFSET or FC_VARIABLE_OFFSET + UINT16 increment; // Increment between successive pointers during a REPEAT. + INT16 offsetToArray; /* Offset from an enclosing structure to the embedded array whose + pointers are being handled. For top-level arrays, this field will always be zero. */ + UINT16 numberOfPointers; // Number of different pointers in a repeat instance. + //PointerInstance_t pointerInstance; /* Several pointerInstance can follow according to iterations, increment and numberOfPointers. + // PointerInstance_t pointerInstance; See PointerInstance_t */ +}VariableRepeatPtr_t; + + +typedef union PointerInstanceLayout_U +{ + SingleInstancePtrToSimpleType_t singleInstPtrToSimpleType; // See ptrLayoutSingleInstancePtrToSimpleTypeDescr + FixedRepeatPtr_t fixedRepeatPtr; // See ptrLayoutFixedRepeatPtrDescr + VariableRepeatPtr_t variableReapeatPtr; // See ptrLayoutVariableRepeatPtrDescr +}PointerInstanceLayout_U; + + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types arrays +//------------------------------------------------------------------------------ +// array types values +//#define FC_CARRAY 0x1b // TODO a confirmer - conformant array +//#define FC_CVARRAY 0x1c // TODO a confirmer - conformant varying array +//#define FC_SMFARRAY 0x1d // TODO a confirmer - small (<64K) fixed array +//#define FC_LGFARRAY 0x1e // TODO a confirmer - large (>= 64K) fixed array +//#define FC_SMVARRAY 0x1f // TODO a confirmer - small (<64K) varying array +//#define FC_LGVARRAY 0x20 // TODO a confirmer - large (>= 64K) varying array +//#define FC_BOGUS_ARRAY 0x21 // TODO a confirmer - complex array + + +/* An array descriptor has a variable size and is composed of +- an ArrayDescrHeader_U according to the type of array (See SMFixedSizedArrayHeader_t, LGFixedSizedArrayHeader_t, +ConformantArrayHeader_t, ConformantVaryingArrayHeader_t, SMVaryingArrayHeader_t, LGVaryingArrayHeader_t, ComplexArrayHeader_t) +- an optional pointer layout (See PointerInstanceLayout_U) +- an ArrayDescrEnd_t +*/ + + + +/* A fixed-sized array format string is generated for arrays that have a known size, +and therefore may be block-copied to the marshaling buffer. */ +typedef struct SMFixedSizedArrayHeader_t +{ + UINT8 arrayDescrType; // FC_SMFARRAY + UINT8 alignment; + UINT16 totalSize; /* Total size of the array in memory, in bytes. This is the same as wire size after alignment. + The total size is calculated for categories for which the padding issue does not exist and + the size is actual array size. */ +}SMFixedSizedArrayHeader_t; + +/* A fixed-sized array format string is generated for arrays that have a known size, +and therefore may be block-copied to the marshaling buffer. */ +#define LGFIXED_ARRAY_HEADER_SIZE 6 +typedef struct LGFixedSizedArrayHeader_t +{ + UINT8 arrayDescrType; // FC_LGFARRAY + UINT8 alignment; + UINT32 totalSize; /* Total size of the array in memory, in bytes. This is the same as wire size after alignment. + The total size is calculated for categories for which the padding issue does not exist and + the size is actual array size. */ +}LGFixedSizedArrayHeader_t; + +// The conformance_description<> is a correlation descriptor and has 4 or 6 bytes depending on whether /robust is used. +#define CONFORMANT_ARRAY_HEADER_SIZE_NONROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT16) + sizeof(CorrelationDescriptorNonRobust_t)) +#define CONFORMANT_ARRAY_HEADER_SIZE_ROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT16) + sizeof(CorrelationDescriptorRobust_t)) +typedef struct ConformantArrayHeader_t +{ + UINT8 arrayDescrType; // FC_CARRAY + UINT8 alignment; + UINT16 elementSize; // Element size in memory of a single element of the array, including padding (this may happen for complex arrays only). + //CorrelationDescriptor_U conformanceDescription; // See CorrelationDescriptor_U +}ConformantArrayHeader_t; + +// The conformance_description<> is a correlation descriptor and has 4 or 6 bytes depending on whether /robust is used. +#define CONFORMANT_VAR_ARRAY_HEADER_SIZE_NONROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT16) + sizeof(CorrelationDescriptorNonRobust_t) + sizeof(CorrelationDescriptorNonRobust_t)) +#define CONFORMANT_VAR_ARRAY_HEADER_SIZE_ROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT16) + sizeof(CorrelationDescriptorRobust_t) + sizeof(CorrelationDescriptorRobust_t)) +typedef struct ConformantVaryingArrayHeader_t +{ + UINT8 arrayDescrType; // FC_CVARRAY + UINT8 alignment; + UINT16 elementSize; // Element size in memory of a single element of the array, including padding (this may happen for complex arrays only) + // CorrelationDescriptor_U conformanceDescription; // See CorrelationDescriptor_U + // CorrelationDescriptor_U varianceDescription; // See CorrelationDescriptor_U +}ConformantVaryingArrayHeader_t; + +// The conformance_description<> is a correlation descriptor and has 4 or 6 bytes depending on whether /robust is used. +#define CONFORMANT_SMVAR_ARRAY_HEADER_SIZE_NONROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT16) + sizeof(UINT16) + sizeof(CorrelationDescriptorNonRobust_t)) +#define CONFORMANT_SMVAR_ARRAY_HEADER_SIZE_ROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT16) + sizeof(UINT16) + sizeof(CorrelationDescriptorRobust_t)) +typedef struct SMVaryingArrayHeader_t +{ + UINT8 arrayDescrType; // FC_SMVARRAY + UINT8 alignment; + UINT16 totalSize; /* Total size of the array in memory, in bytes. This is the same as wire size after alignment. + The total size is calculated for categories for which the padding issue does not exist and + the size is actual array size. */ + UINT16 numberOfElements; + UINT16 elementSize; // Element size in memory of a single element of the array, including padding (this may happen for complex arrays only) + // CorrelationDescriptor_U varianceDescription; // See CorrelationDescriptor_U + /* For varying arrays embedded inside of a structure, the offset<2> field of the variance_description<> is a relative offset from the varying array's position in the + structure to the variance describing field. The offset is typically relative to the beginning of the structure. */ +}SMVaryingArrayHeader_t; + +// The conformance_description<> is a correlation descriptor and has 4 or 6 bytes depending on whether /robust is used. +#define CONFORMANT_LGVAR_ARRAY_HEADER_SIZE_NONROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT32) + sizeof(UINT32) + sizeof(UINT16) + sizeof(CorrelationDescriptorNonRobust_t)) +#define CONFORMANT_LGVAR_ARRAY_HEADER_SIZE_ROBUST (sizeof(UINT8) + sizeof(UINT8) + sizeof(UINT32) + sizeof(UINT32) + sizeof(UINT16) + sizeof(CorrelationDescriptorRobust_t)) +typedef struct LGVaryingArrayHeader_t +{ + UINT8 arrayDescrType; // FC_LGVARRAY + UINT8 alignment; + UINT32 totalSize; /* Total size of the array in memory, in bytes. This is the same as wire size after alignment. + The total size is calculated for categories for which the padding issue does not exist and + the size is actual array size. */ + UINT32 numberOfElements; + UINT16 elementSize; // Element size in memory of a single element of the array, including padding (this may happen for complex arrays only) + // CorrelationDescriptor_U varianceDescription; // See CorrelationDescriptor_U + /* For varying arrays embedded inside of a structure, the offset<2> field of the variance_description<> is a relative offset from the varying array's position in the + structure to the variance describing field. The offset is typically relative to the beginning of the structure. */ +}LGVaryingArrayHeader_t; + + + + +/* A complex array is any array with an element that prevents it from being block-copied, and as such, additional action needs to be taken. These elements make an array complex: + +simple types: ENUM16, __INT3264 (on 64-bit platforms only), an integral with [ range] +reference and interface pointers (all pointers on 64-bit platforms) +unions +complex structures (see the Complex Structure Description topic for a full list of reasons for a structure to be complex) +elements defined with [ transmit_as], [ user_marshal] +All multidimensional arrays with at least one conformant and/or varying dimension are complex regardless of the underlying element type. +*/ +typedef struct ComplexArrayHeader_t +{ + UINT8 arrayDescrType; // FC_BOGUS_ARRAY + UINT8 alignment; + UINT16 numberOfElements; // The number_of_elements<2> field is zero if the array is conformant. + // CorrelationDescriptor_U conformanceDescription; // See CorrelationDescriptor_U + // CorrelationDescriptor_U varianceDescription; // See CorrelationDescriptor_U + /* If the array has conformance and/or variance then the conformance_description<> and/or variance_description<> field(s) + have valid descriptions, otherwise the first 4 bytes of the correlation descriptor are set to 0xFFFFFFFF. The flags, when present, are set to zero. */ +}ComplexArrayHeader_t; + +#define ARRAY_DESCR_HEADER_MIN_SIZE sizeof(SMFixedSizedArrayHeader_t) +typedef union ArrayDescrHeader_U +{ + SMFixedSizedArrayHeader_t smFixedSizedArrayHdr; // See arraySMFixedSizedDescr + LGFixedSizedArrayHeader_t lgFixedSizedArrayHdr; // See arrayLGFixedSizedDescr + ConformantArrayHeader_t conformantArrayHdr; // See arrayConformantDescr + ConformantVaryingArrayHeader_t conformantVaryingArrayHdr; // See arrayConformantVaryingDescr + SMVaryingArrayHeader_t smVaryingArrayHdr; // See arraySMVaryingDescr + LGVaryingArrayHeader_t lgVaryingArrayHdr; // See arrayLGVaryingDescr + ComplexArrayHeader_t complexArray; // See arrayComplexDescr +}ArrayDescrHeader_U; + + +typedef struct ArrayDescrEnd_t +{ + unsigned char * elementDescription; // TODO : taille de ce parametre ? + UINT8 end; // FC_END +}ArrayDescrEnd_t; + + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types string +//------------------------------------------------------------------------------ + + +typedef struct NonConformantStr_t +{ + UINT8 stringType; // FC_CSTRING | FC_WSTRING + UINT8 pad; // FC_PAD + UINT16 string_size; +}NonConformantStr_t; //An example of nonconformant string is a [string] on a fixed-size array. + + +// a conformant string describes common strings, like a [string] char * argument. +/* Si stringType = FC_C_CSTRING | FC_C_WSTRING et StringTypeContent_U.confSizedStr.fc_string_sized_code != FC_STRING_SIZED */ +typedef struct ConformantStr_t +{ + UINT8 stringType; // FC_C_CSTRING | FC_C_WSTRING + UINT8 pad; // FC_PAD +}ConformantStr_t; + +// a sized conformant string +#define SIZE_OF_CONFORMANT_SIZED_STR (robustFlagWasSet)?sizeof(ConformantSizedStr_t):(sizeof(ConformantSizedStr_t)-ROBUST_DELTA) + +typedef struct ConformantSizedStr_t +{ + UINT8 stringType; // FC_C_CSTRING | FC_C_WSTRING + UINT8 fc_string_sized_code; //FC_STRING_SIZED + CorrelationDescriptor_U conformance_description; /* CorrelationDescriptorRobust_t si /robust + Sinon CorrelationDescriptorNonRobust_t */ +}ConformantSizedStr_t; + + + +typedef struct NonConfStructStr_t +{ + UINT8 stringType; // FC_SSTRING + UINT8 element_size; + UINT16 number_of_elements; +}NonConfStructStr_t; //nonconformant string-able structure + + + +//Conformant string-able structure: +/* Si stringType = FC_C_SSTRING et StringTypeContent_U.confSizedStructStr.fc_string_sized_code != FC_STRING_SIZED */ +typedef struct ConfStructStr_t +{ + UINT8 stringType; // FC_C_SSTRING + UINT8 element_size; +}ConfStructStr_t; + +//Conformant sized string-able structure. +typedef struct ConfSizedStructStr_t +{ + UINT8 stringType; // FC_C_SSTRING + UINT8 element_size; + UINT8 fc_string_sized_code; // FC_STRING_SIZED + UINT8 pad; // FC_PAD + CorrelationDescriptor_U conformance_description; /* CorrelationDescriptorRobust_t si /robust + Sinon CorrelationDescriptorNonRobust_t */ +}ConfSizedStructStr_t; + + +typedef union StringTypeContent_U +{ + ConformantStr_t confStr; // Voir strConfStrDescr + ConformantSizedStr_t confSizedStr; // Voir strConfSizedStrDescr + NonConformantStr_t nonConfStr; // Voir strNonConfStrDescr + NonConfStructStr_t nonConfStructStr; // Voir strNonConfStructStrDescr + ConfStructStr_t confStructStr; // Voir strConfStructStrDescr + ConfSizedStructStr_t confSizedStructStr; // Voir strConfSizedStructStrDescr +}StringTypeContent_U; + + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types structures +//------------------------------------------------------------------------------ +// struct types values +//#define FC_STRUCT 0x15 // TODO a confirmer - simple structure +//#define FC_PSTRUCT 0x16 // TODO a confirmer - simple structure avec pointeur +//#define FC_CSTRUCT 0x17 // TODO a confirmer - conformant structure +//#define FC_CPSTRUCT 0x18 // TODO a confirmer - conformant structure avec pointeur +//#define FC_CVSTRUCT 0x19 // TODO a confirmer - conformant varying structure +//#define FC_BOGUS_STRUCT 0x1a + +/* A structure descriptor has a variable size and is composed of +- a StructDescrHeader_U according to the type of struct (See SimpleStructHeader_t, SimpleWithPtrsStructHeader_t, +ConfStructHeader_t, ConfWithPtrsStructHeader_t, ConfVaryingStructHeader_t, HardStructHeader_t, ComplexStructHeader_t) +- a pointer layout only for SimpleWithPtrsStructHeader_t, ConfWithPtrsStructHeader_t, ConfVaryingStructHeader_t (optional) +and ComplexStructHeader_t (optional) See "types pointer layout" described above : variable size. +- a member layout which has variable length (See StructMemberLayout_U) +- a StructDescrEnd_t +*/ + +/* A simple structure contains only base types, fixed arrays, and other simple structures. The main feature of the simple +structure is that it can be block-copied as a whole. */ +typedef struct SimpleStructHeader +{ + UINT8 structType; // FC_STRUCT + UINT8 alignment; /* The necessary alignment of the buffer before unmarshaling the structure. + Valid values are 0, 1, 3, and 7 (the actual alignment minus 1). */ + UINT16 memory_size; /* Size of the structure in memory in bytes; for conformant structures this + size does not include the array's size. */ +}SimpleStructHeader_t; + +/* A simple structure with pointers contains only base types, pointers, fixed arrays, simple structures, and other simple +structures with pointers. Because the layout<> will only have to be visited when doing an endianess conversion, it is placed +at the end of the description. */ +typedef struct SimpleWithPtrsStructHeader_t +{ + UINT8 structType; // FC_PSTRUCT + UINT8 alignment; /* The necessary alignment of the buffer before unmarshaling the structure. + Valid values are 0, 1, 3, and 7 (the actual alignment minus 1). */ + UINT16 memory_size; /* Size of the structure in memory in bytes; for conformant structures this + size does not include the array's size. */ + // type_pointer_layout pointer_layout; // See "types pointer layout" described above : variable size. + // StructMemberLayout_U member_layout; // See StructMemberLayout_U : variable size. + // StructDescrEnd_t end; // FC_END +}SimpleWithPtrsStructHeader_t; + +/* A conformant structure contains only base types, fixed arrays, and simple structures, and must contain either a conformant +string or a conformant array. This array could actually be contained in another conformant structure or conformant structure +with pointers which is embedded in this structure. */ +typedef struct ConfStructHeader_t +{ + UINT8 structType; // FC_CSTRUCT + UINT8 alignment; /* The necessary alignment of the buffer before unmarshaling the structure. + Valid values are 0, 1, 3, and 7 (the actual alignment minus 1). */ + UINT16 memory_size; /* Size of the structure in memory in bytes; for conformant structures this + size does not include the array's size. */ + INT16 offsetToArrayDescription; /* Offset from the current format string pointer to the description of the + conformant array contained in a structure. */ + // StructMemberLayout_U member_layout; // See StructMemberLayout_U : variable size. + // StructDescrEnd_t end; // FC_END +}ConfStructHeader_t; + +/* A conformant structure with pointers contains only base types, pointers, fixed arrays, simple structures, and simple +structures with pointers; a conformant structure must contain a conformant array. This array could actually be contained +in another conformant structure or conformant structure with pointers that is embedded in this structure. */ +typedef struct ConfWithPtrsStructHeader_t +{ + UINT8 structType; // FC_CSTRUCT + UINT8 alignment; /* The necessary alignment of the buffer before unmarshaling the structure. + Valid values are 0, 1, 3, and 7 (the actual alignment minus 1). */ + UINT16 memory_size; /* Size of the structure in memory in bytes; for conformant structures this + size does not include the array's size. */ + INT16 offsetToArrayDescription; /* Offset from the current format string pointer to the description of the + conformant array contained in a structure. */ + // type_pointer_layout pointer_layout; // See "types pointer layout" described above : variable size. + // StructMemberLayout_U member_layout; // See StructMemberLayout_U : variable size. + // StructDescrEnd_t end; // FC_END +}ConfWithPtrsStructHeader_t; + +/* A conformant varying structure contains only simple types, pointers, fixed arrays, simple structures, and simple structures +with pointers; a conformant varying structure must contain either a conformant string or a conformant-varying array. +The conformant string or array can actually be contained in another conformant structure or conformant structure with pointers +that is embedded in this structure. */ +typedef struct ConfVaryingStructHeader_t +{ + UINT8 structType; // FC_CVSTRUCT + UINT8 alignment; /* The necessary alignment of the buffer before unmarshaling the structure. + Valid values are 0, 1, 3, and 7 (the actual alignment minus 1). */ + UINT16 memory_size; /* Size of the structure in memory in bytes; for conformant structures this + size does not include the array's size. */ + INT16 offsetToArrayDescription; /* Offset from the current format string pointer to the description of the + conformant array contained in a structure. */ + // type_pointer_layout pointer_layout; // See "types pointer layout" described above : variable size. OPTIONAL + // StructMemberLayout_U member_layout; // See StructMemberLayout_U : variable size. + // StructDescrEnd_t end; // FC_END +}ConfVaryingStructHeader_t; + +/* The hard structure was a concept aimed at eliminating steep penalties related to processing complex structures. It is derived +from an observation that a complex structure typically has only one or two conditions that prevent block-copying, and therefore +spoil its performance compared to a simple structure. The culprits are usually unions or enumeration fields. + +A hard structure is a structure that has an enum16, end-padding in memory, or a union as the last member. These three elements +prevent the structure from falling into one of the previous structure categories, which enjoy small interpretation overhead and +maximum optimization potential, but do not force it into the very costly complex structure category. + +The enum16 must not cause the memory and wire sizes of the structure to differ. The structure cannot have any conformant array, +nor any pointers (unless part of the union); the only other members allowed are base types, fixed arrays, and simple structures. */ +typedef struct HardStructHeader_t +{ + UINT8 structType; // FC_HARD_STRUCTURE + UINT8 alignment; /* The necessary alignment of the buffer before unmarshaling the structure. + Valid values are 0, 1, 3, and 7 (the actual alignment minus 1). */ + UINT16 memory_size; /* Size of the structure in memory in bytes; for conformant structures this + size does not include the array's size. */ + UINT32 reserved; + INT16 enumOffset; /* The enum_offset<2> field provides the offset from the beginning of the + structure in memory to an enum16 if it contains one; otherwise the + enum_offset<2> field is –1. */ + UINT16 copySize; /* The copy_size<2> field provides the total number of bytes in the structure, + which may be block-copied into/from the buffer. This total does not include + any trailing union nor any end-padding in memory. This value is also the amount + the buffer pointer should be incremented following the copy. */ + UINT16 memCopyIncr; /* The mem_copy_incr<2> field is the number of bytes the memory pointer should be + incremented following the block-copy before handling any trailing union. Incrementing + by this amount (not by copy_size<2> bytes) yields a proper memory pointer to any + trailing union. */ + INT16 unionDescriptionOffset; + + + + // StructMemberLayout_U member_layout; // See StructMemberLayout_U : variable size. + // StructDescrEnd_t end; // FC_END +}HardStructHeader_t; + +#define NULL_OFFSET 0x00 +typedef struct ComplexStructHeader_t +{ + UINT8 structType; // FC_BOGUS_STRUCT + UINT8 alignment; /* The necessary alignment of the buffer before unmarshaling the structure. + Valid values are 0, 1, 3, and 7 (the actual alignment minus 1). */ + UINT16 memory_size; /* Size of the structure in memory in bytes; for conformant structures this + size does not include the array's size. */ + INT16 offsetToArrayDescription; /* If the structure contains a conformant array, the offset_to_conformant_array_description<2> + field provides the offset to the conformant array's description, otherwise it is zero. */ + INT16 offsetToPointerLayout; /* If the structure has pointers, the offset_to_pointer_layout<2> field provides the offset + past the structure's layout to the pointer layout, otherwise this field is zero. */ + // StructMemberLayout_U member_layout; // See StructMemberLayout_U : variable size. + // StructDescrEnd_t end; // FC_END + // type_pointer_layout pointer_layout; // See "types pointer layout" described above : variable size. OPTIONAL + /* The pointer_layout<> field of a complex structure is handled somewhat differently than for other + structures. The pointer_layout<> field of a complex structure only contains descriptions of actual + pointer fields in the structure itself. Any pointers contained within any embedded arrays, unions, + or structures are not described in the complex structure's pointer_layout<> field. + + Note This is in contrast to other structures, which duplicate the description of any pointers + contained in embedded arrays or structures in their own pointer _layout<> field as well. + + The format of a complex structure's pointer layout is also radically different. Because it only + contains descriptions of actual pointer members and because a complex structure is marshaled and + unmarshaled one field at a time, the pointer_layout<> field simply contains the pointer description + of all pointer members. There is no beginning FC_PP, and none of the usual pointer_layout<> information. */ +}ComplexStructHeader_t; + +#define STRUCT_DESCR_HEADER_MIN_SIZE sizeof(SimpleStructHeader_t) +typedef union StructDescrHeader_U +{ + SimpleStructHeader_t simpleStruct; // Voir structSimpleDescr + SimpleWithPtrsStructHeader_t simpleWithPtrsStruct; // Voir structSimpleWithPtrsDescr + ConfStructHeader_t confStruct; // Voir structConformantDescr + ConfWithPtrsStructHeader_t confWithPtrsStruct; // Voir structConformantWithPtrsDescr + ConfVaryingStructHeader_t confVaryingStruct; // Voir structConformantVaryingDescr + HardStructHeader_t hardStruct; // Voir structHardDescr + ComplexStructHeader_t complexStruct; // Voir structComplexDescr +}StructDescrHeader_U; + +/* Then a struct descriptor contains a member layout which has a variable size : +A structure's layout description contains one or more of the following format characters: +- Any of the base type characters, like FC_CHAR, and so on +- Alignment directives. There are three format characters specifying alignment of the memory pointer: FC_ALIGNM2, +FC_ALIGNM4, and FC_ALIGNM8. Note There are also buffer alignment tokens, FC_ALIGNB2 through FC_ALIGNM8; these are not used. +- Memory padding. These occur only at the end of a structure's description and denote the number of bytes of padding in +memory before the conformant array in the structure: FC_STRUCTPADn, where n is the number of bytes of padding. +- Any embedded nonbase type (note, however, that a conformant array never occurs in the structure layout). This has a 4-byte description: */ + +typedef UINT8 StructBaseTypeMemberLayout_t; // base type like FC_CHAR and so on, or structure alignement values, or structure memory padding + +// structure alignement values +//#define FC_ALIGNM2 0x37 +//#define FC_ALIGNM4 0x38 +//#define FC_ALIGNM8 0x39 + +// structure memory padding +//#define FC_STRUCTPAD1 0x3d +//#define FC_STRUCTPAD2 0x3e +//#define FC_STRUCTPAD3 0x3f +//#define FC_STRUCTPAD4 0x40 +//#define FC_STRUCTPAD5 0x41 +//#define FC_STRUCTPAD6 0x42 +//#define FC_STRUCTPAD7 0x43 + +//#define FC_EMBEDDED_COMPLEX 0x4c + +typedef struct StructNonBaseTypeMemberLayout_t +{ + UINT8 memberType; // FC_EMBEDDED_COMPLEX + UINT8 memoryPad; // memory_pad<1> is a padding needed in memory before the complex field. + INT16 offsetToDescription; /* offset_to_description<2> is a relative type offset to the embedded type. + where the offset is not guaranteed to be 2-byte aligned. */ +}StructNonBaseTypeMemberLayout_t; + + +typedef union StructMemberLayout_U +{ + StructBaseTypeMemberLayout_t baseTypeMemberLayout; // See StructBaseTypeMemberLayout_t + StructNonBaseTypeMemberLayout_t nonBaseTypeMemberLayout; // See StructNonBaseTypeMemberLayout_t +}StructMemberLayout_U; + + +/* There may also be an FC_PAD before the terminating FC_END if needed to ensure that the format string will be aligned at a 2-byte boundary following the FC_END. */ +typedef UINT8 StructDescrEnd_t; // FC_END + +//Following type created in order to manipulate common header members of differents structures types descriptors +typedef struct AllStructDescrCommonHeader_MemberType_Align_MemorySize_t +{ + UINT8 structType; + UINT8 alignment; + UINT16 memory_size; +}AllStructDescrCommonHeader_MemberType_Align_MemorySize_t; + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types union +//------------------------------------------------------------------------------ + +// UnionArmSelector_t : Both encapsulated and nonencapsulated unions share a common union_arm_selector<> format: +/* An UnionArmSelector_t is composed of +- a UnionArm_t +- one to several ArmXCase_t +- one DefaultArmDescr_t +*/ +#define UNION_ARM_SELTOR_ALIGN_MASK 0xF000 +#define UNION_ARM_SELTOR_NB_UNION_MEMBER_MASK 0x0FFF +typedef UINT16 UnionArmSelector_t; /* The union_arms<2> field consists of two parts. If the union is a MIDL 1.0 style union, + the upper 4 bits contain the alignment of the union arm (alignment of greatest aligned arm). + Otherwise the upper 4 bits are zero. The lower 12 bits contain the number of arms in the union. + In other words: + alignment arm_counter */ + +#define ARM_X_CASE_SIZE (sizeof(UINT32) + sizeof(INT16)) +typedef struct ArmXCase_t +{ + UINT32 armCaseValue; + INT16 offsetToArmDescription; /* The offset_to_arm_description<2> fields contain a relative signed offset to the arm's type + description. However, the field is overloaded with optimization for simple types. For these, + the upper byte of this offset field is FC_MAGIC_UNION_BYTE (0x80) and the lower byte of the short + is the actual format character type of the arm. As such, there are two ranges for the offset values: + "80 xx" means that xx is a type format string; and everything else within range (80 FF .. 7f FF) + means an actual offset. This makes offsets from range <80 00 .. 80 FF > unavailable as offsets. + The compiler checks that as of MIDL version 5.1.164. */ +}ArmXCase_t; + +typedef UINT16 DefaultArmDescr_t; /* The default_arm_description<2> field indicates the type of union arm for the default arm, if any. + If there is no default arm specified for the union then the default_arm_description<2> field is 0xFFFF + and an exception is raised if the switch_is value does not match any of the arm case values. If the + default arm is specified but empty, then the default_arm_description<2> field is zero. Otherwise the + default_arm_description<2> field has the same semantics as the offset_to_arm_description<2> fields. */ +/* The following is a summary: +0 - empty default +FFFF - no default +80xx - simple type +other - relative offset */ + +// union types values +//#define FC_ENCAPSULATED_UNION 0x2a +//#define FC_NON_ENCAPSULATED_UNION 0x2b + +#define FC_MAGIC_UNION_BYTE 0x8000 +#define MIN_UNION_SIMPLE_TYPE_ENCODE 0x8000 +#define MAX_UNION_SIMPLE_TYPE_ENCODE 0x80FF +#define FC_MAGIC_UNION_GET_SIMPLE_TYPE 0x00FF +#define NO_DEFAULT_ARM_DESCRIPTION 0xFFFF +#define EMPTY_DEFAULT_ARM_DESCRIPTION 0x0000 + +typedef struct SizeAndArmDescription_t +{ + UINT16 memorySize; /* The memory_size<2> field is the size of the union only, and is identical to + nonencapsulated unions. To obtain the total size of the structure that contains the union, + add memory_size<2> to memory increment to step over, that is to the upper nibble of the + switch_type<1> field, then align by the alignment corresponding to the increment. */ + // UnionArmSelector_t union_arm_selector // See UnionArmSelector_t (composed of UnionArm_t, ArmXCase_t, DefaultArmDescr_t) : Variable size and content +}SizeAndArmDescription_t; + +/* An encapsulated union comes from a special union syntax in IDL. Effectively, an encapsulated union is a +bundle structure with a discriminant field at the beginning of the structure and the union as the only other member. */ +#define ENCAP_UNION_SWITCH_TYPE_TYPE_MASK 0x0F +#define ENCAP_UNION_SWITCH_MEMORY_INCREMENT_MASK 0xF0 +typedef struct EncapUnion_t +{ + UINT8 unionType; // FC_ENCAPSULATED_UNION + UINT8 switchType; /* An encapsulated union's switch_type<1> field has two parts. The lower nibble + provides the actual switch type, and the upper nibble provides the memory increment + to step over that is an amount that the memory pointer must be incremented to skip + past the switch_is field, which includes any padding between the switch_is() field + of the stub-constructed structure and the actual union field. */ + SizeAndArmDescription_t sizeAndArmDescr; // See sizeAndArmDescription_t +}EncapUnion_t; + +/* A nonencapsulated union is a typical situation where a union is one argument or field and the switch is another argument or field, respectively. */ +#define NON_ENCAP_UNION_NON_ROBUST_HEADER_SIZE (sizeof(NonEncapUnionHeader_t) + sizeof(CorrelationDescriptorNonRobust_t) + sizeof(nonEncapUnion_offsetToSizeAndArmDescription_t)) +#define NON_ENCAP_UNION_ROBUST_HEADER_SIZE (sizeof(NonEncapUnionHeader_t) + sizeof(CorrelationDescriptorRobust_t) + sizeof(nonEncapUnion_offsetToSizeAndArmDescription_t)) + +#define NON_ENCAP_UNION_OFFSET_TO_SIZE_AND_ARM_JUST_FOLLOW_UNION_DESCR 0x02 +typedef INT16 nonEncapUnion_offsetToSizeAndArmDescription_t; + +typedef struct NonEncapUnionHeader_t +{ + UINT8 unionType; // FC_NON_ENCAPSULATED_UNION + UINT8 switchType; // The switch_type<1> field is a format character for the discriminant. + /* CorrelationDescriptor_U switchIsDescription; /* The switch_is_descriptor<> field is a correlation descriptor and has 4 or 6 bytes + depending on whether /robust is used. However, for the switch_is_description<>, if + the union is embedded in a structure, the offset field of the switch_is_description<> + is the offset to the switch_is field from the union's position in the structure + (not from the beginning of the structure). */ + /* nonEncapUnion_offsetToSizeAndArmDescription_t offsetToSizeAndArmDescription; /* The offset_to_size_and_arm_description<2> field gives the offset to the union's size + and arm description, which is identical to that for encapsulated unions and is shared + by all nonencapsulated unions of the same type. See sizeAndArmDescription_t. */ + +}NonEncapUnionHeader_t; + + + +/*typedef union UnionDescr_U +{ +EncapUnion_t encapUnion; // See unionEncapsulatedDescr +NonEncapUnion_t nonEncapUnion; // See unionNonEncapsulatedDescr +}UnionDescr_U;*/ + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// type Range +//------------------------------------------------------------------------------ +typedef struct Range_t +{ + unsigned char range_type; // FC_RANGE + unsigned char flags_type; + long lowValue; + long highValue; +}Range_t; + + +#pragma pack(pop) + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types Transmit_as and Represent_as +//------------------------------------------------------------------------------ +// TODO + +typedef struct TransmitRepresentAs_t +{ + unsigned char type; + unsigned char flag; + short quintuple_index; + unsigned short presented_type_memory_size; + unsigned short transmitted_type_buffer_size; + short transmitted_type_offset; +}TransmitRepresentAs_t; + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types User-marshal +//------------------------------------------------------------------------------ +typedef struct _UserMarshal_t +{ + unsigned char userMarshalType; // FC_USER_MARSHAL + unsigned char flags; + unsigned short quadruple_index; + unsigned short user_type_memory_size; + unsigned short transmitted_type_buffer_size; + short offset_to_the_transmitted_type; +}UserMarshal_t; + + +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// types Pipe +//------------------------------------------------------------------------------ +typedef struct _Pipe_t +{ + unsigned char pipeType; // FC_USER_MARSHAL + unsigned char unknowChar; + short offsetToType; + unsigned short size0; + unsigned short size1; +}Pipe_t; + + +// TODO : delete following types +/* +//------------------------------------------------------------------------------ +// _MIDL_TYPE_FORMAT_STRING types : +// type end +//----------------------------------------------------------------------------- +typedef unsigned char EndTypeContent_t; + +typedef struct EndDescriptor_t +{ +unsigned int fieldEffectiveSize; // 1 octet +EndTypeContent_t end; // FC_NULL +}EndDescriptor_t; + + + +typedef union TypeFormat_U +{ +StringDescriptor_t stringDescriptor; +PointerDescriptor_t pointerDescriptor; +EndDescriptor_t endDescriptor; +}TypeFormat_U; + +typedef struct TypeFormat_t +{ +FieldTypeID_E TypeDescrID; +TypeFormat_U descriptor; +struct TypeFormat_t * nextType; +} TypeFormat_t; + +typedef TypeFormat_t * PtrTypeFormat_t; + +#define FIRST_PAD_VALUE 0x0000 +typedef unsigned short typeFormat1stPad_t;*/ + +#define START_VALUE 0x0000 +typedef unsigned short typeFormatStart_t; + + +/*typedef struct Fabrique_MIDL_TYPE_FORMAT_STRING +{ +unsigned int cumulatedEffectiveSize; +unsigned short pad; +unsigned short start; //TODO : confirmer le role de ce champ +TypeFormat_t * firstType; +}Fabrique_MIDL_TYPE_FORMAT_STRING;*/ + + + + +#define FC_NULL 0x00 //TODO : a confirmer + + +// TODO : a confirmer - transmit as / represent as values +//#define FC_TRANSMIT_AS 0x2d +//#define FC_REPRESENT_AS 0x2e + +// TODO : voir utilité +//#define FC_POINTER 0x36 +// +// +//#define FC_STRING_SIZED 0x44 + +//#define FC_END 0x5b +//#define FC_PAD 0x5c + +//#define FC_USER_MARSHAL 0xb4 +//#define FC_RANGE 0xb7 + +// user marshal flags +#define USER_MARSHAL_UNIQUE 0x80 +#define USER_MARSHAL_REF 0x40 +#define USER_MARSHAL_POINTER 0xc0 +#define USER_MARSHAL_IID 0x20 + +// context handle flags +#define NDR_CONTEXT_HANDLE_CANNOT_BE_NULL 0x01 +#define NDR_CONTEXT_HANDLE_SERIALIZE 0x02 +#define NDR_CONTEXT_HANDLE_NO_SERIALIZE 0x04 +#define NDR_STRICT_CONTEXT_HANDLE 0x08 + +/* AddElement(Container_T* pContainer, void* pElement, UINT Id); */ + + + + + + + +// NEW TYPE + +class ParamDesc; + +typedef struct _INLINED_PARAM_BASE_T +{ + BYTE bFcTypeParamProperties; + BYTE bFcType; +}INLINED_PARAM_BASE_T; + +typedef struct _INLINED_PARAM_COMPLEX_T +{ + BYTE bFcTypeParamProperties; + BYTE stackSize; + USHORT offset; +}INLINED_PARAM_COMPLEX_T; + +typedef union inlinedParam +{ + INLINED_PARAM_BASE_T baseParam; + INLINED_PARAM_COMPLEX_T complexParam; +}inlinedParam; + +// class used to describe an idl function +class IdlFunctionDesc +{ +private: + std::string m_strFunctionName; + UINT32 m_uNbParam; + BOOL m_bHasRangeOnConformance; + BOOL m_bHasReturn; + std::list m_listParam; + +public: + IdlFunctionDesc(); + IdlFunctionDesc(std::string strFunctionName); + + UINT32 getNbParam() const; + std::string getFunctionName() const {return m_strFunctionName;} + VOID setNbParam(UINT32 uNbParam); + VOID setHasReturn(BOOL hasReturn); + VOID addParamToList(ParamDesc parameter); + std::list& getParamList(); + + BOOL hasRangeOnConformance() const; + BOOL hasReturn() const; + + VOID parseWin32ExtHeader(Win2kExt_Header_t* pWin32kExtHeader); +}; + + +enum FC_CONFORMANCE_TYPE_T +{ + switch_is, + size_is, + length_is, + byte_count, +}; + +typedef struct ConformanceDescr_T_ +{ + RVA_T pType; + FC_CONFORMANCE_TYPE_T confType; + CorrelationDescriptorNonRobust_t corrDesc; // non robust, we'll see if robust part is needed +}ConformanceDescr_T; + +// structure used to store information about structMebmer +typedef struct StructureMember_T_ +{ + FC_TYPE fcType; + UINT uSize; +}StructureMember_T; + + +// Enum used to define FC_EXPR calculus for size_is/length_is as extracted by Brandon Falk from Windows 8 pdb +// brandonfa.lk/win8/win8_devrel_head_x86/combase.h + +enum EXPR_TOKEN +{ + FC_EXPR_START = 0, + FC_EXPR_ILLEGAL = 0, + FC_EXPR_CONST32 = 1, + FC_EXPR_CONST64 = 2, + FC_EXPR_VAR = 3, + FC_EXPR_OPER = 4, + FC_EXPR_NOOP = 5, + FC_EXPR_END = 6 +}; + +enum OP_TOKEN +{ + OP_UNARY_PLUS = 1, + OP_UNARY_MINUS = 2, + OP_UNARY_NOT = 3, + OP_UNARY_COMPLEMENT = 4, + OP_UNARY_INDIRECTION = 5, + OP_UNARY_CAST = 6, + OP_UNARY_AND = 7, + // Gap of unknown values + + OP_PLUS = 0xE, + OP_MINUS = 0xF, + OP_STAR = 0x10, + OP_SLASH = 0x11, + OP_MOD = 0x12, + OP_LEFT_SHIFT = 0x13, + OP_RIGHT_SHIFT = 0x14, + OP_LESS = 0x15, + OP_LESS_EQUAL = 0x16, + OP_GREATER_EQUAL = 0x17, + OP_GREATER = 0x18, + OP_EQUAL = 0x19, + OP_NOT_EQUAL = 0x1A, + OP_AND = 0x1B, + OP_OR = 0x1C, + OP_XOR = 0x1D, + OP_LOGICAL_AND = 0x1E, + OP_LOGICAL_OR = 0x1F, + OP_EXPRESSION = 0x20 + +}; + +enum OP_OPERATOR_TYPE +{ + OP_UNARY, + OP_BINARY, + OP_TERNARY +}; + +typedef struct _EXPR_OPERATOR +{ + UINT8 ExprType; + UINT8 Operator; + UINT8 CastType; + UINT8 Reserved; +} EXPR_OPERATOR; + +typedef struct _EXPR_CONST32 +{ + UINT8 ExprType; + UINT8 Reserved; + UINT16 Reserved1; + UINT32 ConstValue; +} EXPR_CONST32; + +typedef struct _EXPR_CONST64 +{ + UINT8 ExprType; + UINT8 Reserved; + UINT16 Reserved1; + INT64 ConstValue; +} EXPR_CONST64; + +typedef struct __EXPR_VAR +{ + UINT8 ExprType; + UINT8 VarType; + INT16 Offset; +// UINT32 Offset; +} EXPR_VAR; + +typedef struct _EXPR_NOOP +{ + UINT8 ExprType; + UINT8 Size; + UINT16 Reserved; +} EXPR_NOOP; + +class TypeToDefine; + +// class used to store idl param description +class ParamDesc +{ +private: + BOOL m_bString; // param is [string] + BOOL m_bIn; // param is [in] + BOOL m_bUnique; // param is [unique] + BOOL m_bOut; // param is [out] + BOOL m_bReturn; // param is return + UINT m_uPtrLevel; // pointer level of the type (ie : number of '*') + BOOL m_hasRangeOnConformance; + BOOL m_arrayIsAttributedPointer; // Needed for correlation descriptor offset field + FC_TYPE m_fcType; + RVA_T m_rva; // rva in type /proc format string + std::string m_strTypeName; // param Name + //UINT m_uOffset; // param offset in type format string + std::list m_listConfDescr; + UINT m_uStructMemberNum; // when param is in a structure definition, indicate struct member number + UINT m_uMemorySize; // size of the param in memory + std::vector m_vectMembersOffset; // this field is only used when the param is a struct member + // it's a vector containing member offset of other struct member (used for conformance) + +public: + + // constructors + ParamDesc(); + ParamDesc(std::string strTypeName); + ParamDesc(std::string strTypeName, UINT uStructMemberNum, std::vector vectMemberOffset); + //ParamDesc(const TypeToDefine& UnionStructDesc); + + + + + // getter + UINT getuPtrLevel() const {return m_uPtrLevel;} + /*UINT getMemorySize() const {return m_uMemorySize;}*/ + BOOL hasRangeOnConformance() const {return m_hasRangeOnConformance;} + BOOL isReturn() const {return m_bReturn;} + BOOL isIn() const {return m_bIn;} + BOOL isOut() const {return m_bOut;} + FC_TYPE getFcType() const {return m_fcType;} + RVA_T getRva() const {return m_rva;} + std::string getStrTypeName() const {return m_strTypeName;} + //UINT getuOffset() const {return m_uOffset;} + UINT getuStructMemberNum() const {return m_uStructMemberNum;} + BOOL getArrayIsAttributedPointer() const {return m_arrayIsAttributedPointer;} + std::vector& getVectMembersOffset() {return m_vectMembersOffset;} + + + //setter + void setString() {m_bString = TRUE;} + void setUnique() {m_bUnique = TRUE;} + void setHasRangeOnConformance() {m_hasRangeOnConformance = TRUE;} + void setFcType(_In_ FC_TYPE fcType) {m_fcType = fcType;} + void setRva(_In_ RVA_T rva) {m_rva = rva;} + void setParamName(_In_ std::string strParamName) {m_strTypeName = strParamName;} + //void setuOffset(UINT uOffset) {m_uOffset = uOffset;} + void setuStructMemberNum(_In_ UINT uStructMemberNum) {m_uStructMemberNum = uStructMemberNum;} + /*void setMemorySize(_In_ UINT uMemorySize) {m_uMemorySize = uMemorySize;}*/ + void incPtrLevel() {m_uPtrLevel++;} + void setArrayIsAttributedPointer() {m_arrayIsAttributedPointer = TRUE;} + void setIsIn() {m_bIn = TRUE;} + void setIsOut() {m_bOut = TRUE;} + void setIsReturn() {m_bReturn = TRUE;} + + + LONG getRelativeOffsetFromFmtString(_In_ RVA_T pFormatString) const; + void fillWithParamAttr(_In_ PARAM_ATTRIBUTES paramAttr); + void inheritProperties(_In_ const TypeToDefine& parentTypeDesc); + void gestDescr(_Inout_ std::string& strDesc); + + void addStructureMember(_In_ StructureMember_T strucMember); + void addConformanceDescr(_In_ ConformanceDescr_T conformanceDescr); + + + + +}; + + + + +// class used to store Union or Structure that will be processed lately +class TypeToDefine +{ +private : + RVA_T m_rva; + FC_TYPE m_fcType; + UINT m_uOffset; + BOOL m_bHasRangeOnConf; + RVA_T m_pNonEncapsulatedUnionHeader; // only used with FC_NON_ENCAPSULATED_UNION + + +public: + + //TypeToDefine(); + TypeToDefine(const RVA_T pType, const ParamDesc& paramDesc); + + //getter + RVA_T getRva() const {return m_rva;} + //PBYTE getpType() const {return m_pType;} + FC_TYPE getFcType() const {return m_fcType;} + //UINT getuOffset() const {return m_uOffset;} + BOOL getHasRangeOnConformance() const {return m_bHasRangeOnConf;} + RVA_T getpNonEncapuslatedUnionHeader() const {return m_pNonEncapsulatedUnionHeader;} + + + //setter + void setRva(RVA_T rva) {m_rva = rva;} + //void setpType(PBYTE pType) {m_pType = pType;} + ///void setuOffset(UINT uOffset) {m_uOffset = uOffset;} + void setpNonEncapsulatedUnionHeader(RVA_T pNonEncap) {m_pNonEncapsulatedUnionHeader = pNonEncap;} + + // operator + bool operator<( const TypeToDefine& right); + bool operator== ( const TypeToDefine& right); +}; + + +//////////////////////////////////////////////////////////////////////////////// +// NDR_VERSION definitions +//////////////////////////////////////////////////////////////////////////////// +#define NDR_VERSION_5_2 0x50002 +#define NDR_VERSION_5_4 0x50004 +#define NDR_VERSION_6_0 0x60000 +#define NDR_VERSION_6_1 0x60001 +#define NDR_VERSION_6_2 0x60002 + +#endif//_INTERNAL_RPC_DECOMP_TYPE_DEFS_H_ \ No newline at end of file diff --git a/RpcDecompiler/internalRpcDecompTypeDefsNew.h b/RpcDecompiler/internalRpcDecompTypeDefsNew.h new file mode 100644 index 0000000..1fc207e --- /dev/null +++ b/RpcDecompiler/internalRpcDecompTypeDefsNew.h @@ -0,0 +1,10 @@ +#ifndef _INTERNAL_RPC_DECOMP_TYPE_DEFS_H_NEW_ +#define _INTERNAL_RPC_DECOMP_TYPE_DEFS_H_NEW_ + +#include "internalRpcDecompTypeDefs.h" + + + + + +#endif diff --git a/RpcDecompiler/internalRpcDecompiler.cpp b/RpcDecompiler/internalRpcDecompiler.cpp new file mode 100644 index 0000000..de1189e --- /dev/null +++ b/RpcDecompiler/internalRpcDecompiler.cpp @@ -0,0 +1,1352 @@ +#include "internalRpcDecompTypeDefs.h" +#include "internalRpcDecompiler.h" +#include "internalRpcUtils.h" +#include "internalComplexTypesStrings.h" +#include "internalComplexTypesArrays.h" +#include "internalComplexTypesPointers.h" +#include "InternalComplexTypesMisc.h" +#include "internalComplexTypesUnions.h" +#include "internalComplexTypesStructs.h" +#include +#include +#include + +#include "internalTypeTools.h" + + + + +///\warning Global variable is64B to set according to the real RPC binary information to decompile. The code design is to be adapted. +BOOL is64B; + +//#ifdef _AMD64_ +//boolean is64B = TRUE; +//#else +//boolean is64B = FALSE; +//#endif + +///\warning Global variable robustFlagWasSet to set according to the real RPC binary information to decompile. The code design is to be adapted. +/// robustFlagWasSet to set according to the real environment (/robust used or not, see following line) +/// robustFlagWasSet could be set to the w2kHeaderToDecode.interpreter_opt_flag2.HasNewCorrDesc value read from a procedure descriptor. +boolean robustFlagWasSet; + + + + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall getAllTypesSortedInAList( + _In_ VOID* pContext, + _In_ std::list & listTypesToDefine, + _Inout_ std::list& listAllTypesSorted, + _Inout_ std::ostringstream& oss) +{ + + + BOOL bResult; + + listTypesToDefine.sort(); + listTypesToDefine.unique(); + + while(!listTypesToDefine.empty()) + { + // list used to store addition type that might be embeded in current type + std::list listAdditionalType; + + TypeToDefine TypeToDefineToDefine = listTypesToDefine.front(); + + // remove first element from list + listTypesToDefine.pop_front(); + + // print it + bResult = printType( + pContext, + TypeToDefineToDefine, + listAdditionalType, + oss); + + // if we're unable to Print type we abort + if(bResult == FALSE) + { + return FALSE; + } + + listAllTypesSorted.push_back(TypeToDefineToDefine); + + // merge listTypesToDefine and ListAdditionalTypes + if(!listAdditionalType.empty()) + { + //listTypesToDefine.merge(listAdditionalType); + listTypesToDefine.splice(listTypesToDefine.end(), listAdditionalType); + } + + // remove from listTypesToDefine elements that already are in + for(auto iter = listAllTypesSorted.begin(); iter != listAllTypesSorted.end(); iter++) + { + listTypesToDefine.remove(*iter); + } + + + listTypesToDefine.sort(); + listTypesToDefine.unique(); + + } + + listAllTypesSorted.unique(); + listAllTypesSorted.sort(); + + + return TRUE; +} + + +// --------------------------------------------------------------------------------------------- +BOOL __fastcall dumpTypeList( + _In_ VOID* pContext, + _In_ std::list & listTypesToDefine, + _Inout_ std::ostringstream& oss) +{ + + std::list listAdditionalType; + BOOL bResult; + + listTypesToDefine.sort(); + listTypesToDefine.unique(); + + + for(auto iter=listTypesToDefine.begin(); iter!=listTypesToDefine.end(); iter++) + { + bResult = printType( + pContext, + *iter, + listAdditionalType, + oss); + + if(bResult == FALSE) + { + oss << std::endl << "[ERROR] dumpTypeList : unable to print type\n" << std::endl; + return FALSE; + } + } + + return TRUE; +} + + +// --------------------------------------------------------------------------------------------- +BOOL __fastcall RpcDecompilerPrintAllTypesInList + ( + _In_ VOID* pContext, + _In_ std::list & listProcTypes, + _Out_ std::ostringstream& oss + ) +{ + std::list listAllTypesSorted; + std::ostringstream ossUseless; + + + /*oss<<"/*"<uOffset<<" "; + } + oss<<""<& listProcType, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + Oi_Header_1stPart_t oiHeader1stPartToDecode; + Oi_Header_RpcFlags_t * oiHeaderRpcFlagsToDecode = NULL; + Oi_Header_3rdPart_t oiHeader3rdPartToDecode; + ExplicitHandle_t * oiHeaderExplicitHandleToDecode = NULL; + Oif_Header_t oifHeaderToDecode; + Win2kExt_Header_t w2kHeaderToDecode; + + UINT currentOffset = formatStringOffset; + UINT numParam = 0; + BOOL isReturnParam = FALSE; + BOOL returnTypeHasBeenPrinted = FALSE; + + UINT paramSizeInBytes = 0; + + memset(&oiHeader1stPartToDecode, 0, sizeof(Oi_Header_1stPart_t)); + memset(&oiHeader3rdPartToDecode, 0, sizeof(Oi_Header_3rdPart_t)); + memset(&oifHeaderToDecode, 0, sizeof(Oif_Header_t)); + memset(&w2kHeaderToDecode, 0, sizeof(Win2kExt_Header_t)); + + //following checks already done by the caller function + /* if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString == NULL) goto End;*/ + + RPC_DEBUG_FN((UCHAR*)"\n\n*************** RpcDecompilerDecodeAndPrintPrototypeReturnType ******************"); + + /********************************************************************** + * Decode the Oi Header + ***********************************************************************/ + //Decode the Oi header 1st part + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + &oiHeader1stPartToDecode, + sizeof(Oi_Header_1stPart_t) + ); + currentOffset += sizeof(Oi_Header_1stPart_t); + + RPC_DEBUG_FN((UCHAR*)"\n\n"); + RPC_DEBUG_FN((UCHAR*)"\noiHeader1stPartToDecode.handle_type = 0x%x", oiHeader1stPartToDecode.handle_type); + RPC_DEBUG_FN((UCHAR*)"\noiHeader1stPartToDecode.oi_flags = 0x%x", oiHeader1stPartToDecode.oi_flags); + + //Decode the Oi header Rpc Flags + if(oiHeader1stPartToDecode.oi_flags & Oi_HAS_RPCFLAGS) + { + oiHeaderRpcFlagsToDecode = (Oi_Header_RpcFlags_t *) RPC_ALLOC_FN(sizeof(Oi_Header_RpcFlags_t)); + if(oiHeaderRpcFlagsToDecode == NULL) + { + RPC_DEBUG_FN((UCHAR*)"\n!!! source = %s line = %d - RpcAlloc returned NULL pointer", __FILE__, __LINE__); + goto End; + } + + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + oiHeaderRpcFlagsToDecode, + sizeof(Oi_Header_RpcFlags_t) + ); + + currentOffset += sizeof(Oi_Header_RpcFlags_t); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderRpcFlagsToDecode->rpc_flags = 0x%x", oiHeaderRpcFlagsToDecode->rpc_flags); + } + + + + //Decode the Oi header 3rd part + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + &oiHeader3rdPartToDecode, + sizeof(Oi_Header_3rdPart_t) + ); + currentOffset += sizeof(Oi_Header_3rdPart_t); + + RPC_DEBUG_FN((UCHAR*)"\noiHeader3rdPartToDecode.procNum = 0x%x", oiHeader3rdPartToDecode.procNum); + RPC_DEBUG_FN((UCHAR*)"\noiHeader3rdPartToDecode.stack_size = 0x%x", oiHeader3rdPartToDecode.stack_size); + + + //Decode the Oi header explicit handle + //TODO : creer une fonction qui fait cela, cad GetExplicitHandleSize + if(oiHeader1stPartToDecode.handle_type == FC_EXPLICIT_HANDLE) + { + oiHeaderExplicitHandleToDecode = (ExplicitHandle_t *) RPC_ALLOC_FN(sizeof(ExplicitHandle_t)); + if(oiHeaderExplicitHandleToDecode == NULL) + { + RPC_DEBUG_FN((UCHAR*)"!!! source = %s line = %d - RpcAlloc returned NULL pointer", __FILE__, __LINE__); + goto End; + } + + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + oiHeaderExplicitHandleToDecode, + EXPLICIT_HANDLE_MIN_SIZE + ); + + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->htype = 0x%x", oiHeaderExplicitHandleToDecode->htype); + + switch(oiHeaderExplicitHandleToDecode->htype) + { + case FC_BIND_PRIMITIVE: +#if EXPLICIT_HANDLE_MIN_SIZE != EXPLICIT_HANDLE_PRIMITIVE_SIZE +#error check the value of EXPLICIT_HANDLE_MIN_SIZE, EXPLICIT_HANDLE_PRIMITIVE_SIZE and the code +#endif + currentOffset += EXPLICIT_HANDLE_PRIMITIVE_SIZE; + + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandlePrimitive.flag = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandlePrimitive.flag); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandlePrimitive.offset = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandlePrimitive.offset); + + break; + + case FC_BIND_GENERIC: + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + oiHeaderExplicitHandleToDecode, + EXPLICIT_HANDLE_GENERIC_SIZE + ); + currentOffset += EXPLICIT_HANDLE_GENERIC_SIZE; + + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.flagAndSize = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.flagAndSize); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.offset = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.offset); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.binding_routine_pair_index = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.binding_routine_pair_index); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.pad = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleGeneric.pad); + + break; + + case FC_BIND_CONTEXT: + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + oiHeaderExplicitHandleToDecode, + EXPLICIT_HANDLE_CONTEXT_SIZE + ); + currentOffset += EXPLICIT_HANDLE_CONTEXT_SIZE; + + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.flags = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.flags); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.offset = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.offset); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.context_rundown_routine_index = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.context_rundown_routine_index); + RPC_DEBUG_FN((UCHAR*)"\noiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.param_num = 0x%x", oiHeaderExplicitHandleToDecode->hContent.explicitHandleContext.param_num); + + break; + + default: + RPC_DEBUG_FN((UCHAR*)"\n!!! source = %s line = %d - ERREUR : oiHeaderExplicitHandleToDecode->htype undefined value. value = 0x%x", __FILE__, __LINE__, oiHeaderExplicitHandleToDecode->htype); + bResult = FALSE; + goto End; + break; + + } // switch(oiHeaderExplicitHandleToDecode->htype) + + }// if(oiHeader1stPartToDecode.handle_type == FC_EXPLICIT_HANDLE) + + + /********************************************************************** + * Decode the Oif Header (necessary for 64bits) + ***********************************************************************/ + + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + &oifHeaderToDecode, + OIF_EXT_HEADER_SIZE + ); + currentOffset += OIF_EXT_HEADER_SIZE; + + RPC_DEBUG_FN((UCHAR*)"\noifHeaderToDecode.constant_client_buffer_size = 0x%x", oifHeaderToDecode.constant_client_buffer_size); + RPC_DEBUG_FN((UCHAR*)"\noifHeaderToDecode.constant_server_buffer_size = 0x%x", oifHeaderToDecode.constant_server_buffer_size); + RPC_DEBUG_FN((UCHAR*)"\noifHeaderToDecode.interpreter_opt_flag = 0x%x", oifHeaderToDecode.interpreter_opt_flag); + RPC_DEBUG_FN((UCHAR*)"\noifHeaderToDecode.number_of_param = 0x%x", oifHeaderToDecode.number_of_param); + + +#ifdef DBG_DECOMP + oss << "/* is Async bit set : "; + + if(oifHeaderToDecode.interpreter_opt_flag.HasAsyncUuid) + { + oss << " TRUE */"; + } + else + { + oss << " FALSE */"; + } +#endif + + /********************************************************************** + * Decode the Win2kExt Header + ***********************************************************************/ + // TODO : need to identify which precise condition trigger the apparition of a win2KExt header + if(pRpcDecompilerCtxt->pRpcDecompilerInfo->NDRVersion != 0x20000) + { + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + &(w2kHeaderToDecode.extension_version), + sizeof(w2kHeaderToDecode.extension_version) + ); + + switch (w2kHeaderToDecode.extension_version) + { + case WIN2K_EXT_HEADER_32B_SIZE: + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + &w2kHeaderToDecode, + WIN2K_EXT_HEADER_32B_SIZE + ); + + currentOffset += WIN2K_EXT_HEADER_32B_SIZE; + + break; + case WIN2K_EXT_HEADER_64B_SIZE: + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + currentOffset), + &w2kHeaderToDecode, + WIN2K_EXT_HEADER_64B_SIZE + ); + + currentOffset += WIN2K_EXT_HEADER_64B_SIZE; + + break; + default: + RPC_DEBUG_FN((UCHAR*)"\n!!! source = %s line = %d - ERREUR : w2kHeaderToDecode.extension_version undefined value. value = 0x%x", __FILE__, __LINE__, w2kHeaderToDecode.extension_version); + bResult = FALSE; + goto End; + } + // parse Win32Ext Header + IdlFunctionDesc.parseWin32ExtHeader(&w2kHeaderToDecode); + + RPC_DEBUG_FN((UCHAR*)"\nw2kHeaderToDecode.extension_version = 0x%x", w2kHeaderToDecode.extension_version); + RPC_DEBUG_FN((UCHAR*)"\nw2kHeaderToDecode.interpreter_opt_flag2 = 0x%x", w2kHeaderToDecode.interpreter_opt_flag2); + RPC_DEBUG_FN((UCHAR*)"\nw2kHeaderToDecode.clientCorrHint = 0x%x", w2kHeaderToDecode.clientCorrHint); + RPC_DEBUG_FN((UCHAR*)"\nw2kHeaderToDecode.serverCorrHint = 0x%x", w2kHeaderToDecode.serverCorrHint); + RPC_DEBUG_FN((UCHAR*)"\nw2kHeaderToDecode.notifyIndex = 0x%x", w2kHeaderToDecode.notifyIndex); + + if(w2kHeaderToDecode.extension_version == WIN2K_EXT_HEADER_64B_SIZE) + { + RPC_DEBUG_FN((UCHAR*)"\nw2kHeaderToDecode.floatDoubleMask = 0x%x", w2kHeaderToDecode.floatDoubleMask); + } + + + }//endif + + + + + //TODO + // Print the handle type information to take into account + switch(oiHeader1stPartToDecode.handle_type) + { + case FC_BIND_CONTEXT: + break; + case FC_BIND_PRIMITIVE: + + oss << "\n/*********************************************************"; + oss << "\n * Add the following line in header of the the ACF file:"; + //oss << "\n *\timplicit_handle (handle_t "< 0) + { + //Find and print the return parameter type. Note: as soon as a return type is printed, the loop ends + numParam = 1; + while( (! returnTypeHasBeenPrinted) && (numParam <= oifHeaderToDecode.number_of_param) ) + { + RPC_DEBUG_FN((UCHAR*)"\nRpcDecompilerDecodeAndPrintPrototypeReturnType: numParam = 0x%x on total to analyse = 0x%x", numParam, oifHeaderToDecode.number_of_param); + bResult = RpcDecompilerGetReturnParamInfo(/* in */ pRpcDecompilerCtxt, /* in */ currentOffset, /* in */ paramDescrOif, /* out */ &isReturnParam); + if (bResult == FALSE) goto End; + + if(isReturnParam) + { + //Return param is found, to be printed + //RPC_PRINT_FN((UCHAR*)"\t"); + oss << "\t"; + + bResult = RpcDecompilerPrintParam( + pRpcDecompilerCtxt, + /* in */ currentOffset, + /* in */ paramDescrOif, + /* out */ ¶mSizeInBytes, + /* in */ IdlFunctionDesc, + /* in/out */ listProcType, + /* in, out */oss); + + + if (bResult == FALSE || paramSizeInBytes == RPC_DECOMPILER_INVALID_PARAM_SIZE) goto End; + returnTypeHasBeenPrinted = TRUE; + } + + currentOffset += OIF_PARAM_SIZE; + numParam++; + } + + if(! returnTypeHasBeenPrinted) + { + //No parameter to be printed whereas the procedure is supposed to return something... + RPC_DEBUG_FN((UCHAR*)"\n!!! RpcDecompilerDecodeAndPrintPrototypeReturnType: file = %s, line = %d, no return param found whereas oifHeaderToDecode.interpreter_opt_flag.HasReturn", + __FILE__, __LINE__); + goto End; + } + }// (*nbParamToPrint > 0) + }//( oifHeaderToDecode.interpreter_opt_flag.HasReturn ) + else + { + //RPC_PRINT_FN((UCHAR*)"\tvoid"); + oss <<"\tvoid "; + + RPC_DEBUG_FN((UCHAR*)"\tvoid "); + }// !( oifHeaderToDecode.interpreter_opt_flag.HasReturn ) + +End: + *sizeOfProcDescr = currentOffset - formatStringOffset; + if(oiHeaderRpcFlagsToDecode != NULL) RPC_FREE_FN(oiHeaderRpcFlagsToDecode); + if(oiHeaderExplicitHandleToDecode != NULL) RPC_FREE_FN(oiHeaderExplicitHandleToDecode); + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcDecompilerPrintPrototypeName( + _In_ VOID* pContext, + _In_ UINT ProcIndex, + _Inout_ std::ostringstream& oss) +{ + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + //following checks already done by the caller function + /* if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + + if (pRpcDecompilerCtxt->pRpcDecompilerInfo == NULL) goto End;*/ + if(pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable == NULL) + { + return FALSE; + } + + RPC_DEBUG_FN((UCHAR*)"\n\n************************** RpcDecompilerPrintPrototypeName ************************"); + + + if(pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[ProcIndex] == NULL) + { + + //oss << "_Function_0x" << std::hex << (long)(pFunction - pModuleBase) << "("; + oss << " _Function_" << std::dec << ProcIndex << "("; + + } + else + { + size_t sz = wcslen(pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[ProcIndex]) + 1; + size_t szConverted = 0; + + char* pTmp = (char*)pRpcDecompilerCtxt->pRpcViewHelper->RpcAlloc(sz); + + if(pTmp != NULL) + { + ZeroMemory(pTmp, sz); + wcstombs_s(&szConverted, pTmp, sz, pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[ProcIndex], sz); + + oss << pTmp << "("; + + pRpcDecompilerCtxt->pRpcViewHelper->RpcFree(pTmp); + } + + //oss << narrow(std::wstring(pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[ProcIndex])) << "("; + + + }// if(pRpcDecompilerCtxt->pRpcDecompilerInfo->ppProcNameTable[ProcIndex] == NULL) + + + return TRUE; +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcDecompilerGetReturnParamInfo( + _In_ VOID* pContext, + _In_ UINT paramOffset, + _In_ ParamID_E paramDescrFormat, + _Out_ BOOL * isReturnParam) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + //UINT formatStringOffset = 0; + ProcFormatStringParam_U paramToAnalyze; + + + //following checks already done by the caller function + /* if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + + if(pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString == NULL) goto End; */ + + RPC_DEBUG_FN((UCHAR*)"\n\n******************* RpcDecompilerGetReturnParamInfo *****************"); + + switch(paramDescrFormat) + { + case paramDescrOi: + //TODO + //paramSizeInBytes = OI_PARAM_BASETYPE_SIZE; + //paramSizeInBytes = OI_PARAM_OTHERTYPE_SIZE; + RPC_DEBUG_FN((UCHAR*)"\n!!! source = %s ligne = %d - RpcDecompilerGetReturnParamInfo : paramDescrOi not handled", __FILE__, __LINE__); + goto End; + break; + + case paramDescrOif: + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + paramOffset), + ¶mToAnalyze, + sizeof(paramToAnalyze) + ); + + RPC_DEBUG_FN((UCHAR*)"\nRpcDecompilerGetReturnParamInfo: paramToPrint.oif_Format.paramAttributes = 0x%x", paramToAnalyze.oif_Format.paramAttributes); + + *isReturnParam = paramToAnalyze.oif_Format.paramAttributes.IsReturn; + break; + default: + RPC_DEBUG_FN((UCHAR*)"\n!!! RpcDecompilerGetReturnParamInfo : ERROR, paramDescrFormat not recognized"); + bResult = FALSE; + goto End; + break; + } + +End: + return bResult; +} + + +// ----------------------------------------------------------------------------------------------- +DWORD __fastcall getSimpleTypeMemorySize(_In_ FC_TYPE fcType) +{ + switch(fcType) + { + + case FC_BYTE: + case FC_CHAR: + case FC_SMALL: + case FC_USMALL: + return 1; + + case FC_WCHAR: + case FC_SHORT: + case FC_USHORT: + return 2; + + case FC_LONG: + case FC_ULONG: + case FC_ENUM16: + case FC_ENUM32: + case FC_ERROR_STATUS_T: + return 4; + + case FC_FLOAT: + case FC_HYPER: + case FC_DOUBLE: + case FC_INT3264: + case FC_UINT3264: + return 8; + + case FC_ZERO: + return 0; + + case FC_IGNORE: + return POINTER_SIZE; + + default: + return (DWORD)-1; + + } +} + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall processSimpleType( + _In_ VOID* pContext, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& paramDesc, + _Inout_ std::ostringstream& oss) +{ + if (printSimpleType(pContext, fcType, oss) == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] processSimpleType : unknow type\n"); + return FALSE; + } + + // get simple type size + //paramDesc.setMemorySize(getSimpleTypeMemorySize(fcType)); + + displayPtrLevel(paramDesc.getuPtrLevel(), oss); + + oss<& listProcTypes, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = TRUE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BYTE bFC_TYPE; + + + RPC_GET_PROCESS_DATA( + paramDesc.getRva(), + &bFC_TYPE, + sizeof(bFC_TYPE)); + + if(bResult == FALSE) + { + RPC_ERROR_FN("RpcGetProcessData failed\n"); + return FALSE; + } + + paramDesc.setFcType((FC_TYPE)bFC_TYPE); + + switch(paramDesc.getFcType()) + { + //------------------------------------ + // Simple type + //------------------------------------ + case FC_BYTE: + case FC_CHAR: + case FC_SMALL: + case FC_WCHAR: + case FC_SHORT: + case FC_USHORT: + case FC_LONG: + case FC_ULONG: + case FC_FLOAT: + case FC_HYPER: + case FC_DOUBLE: + case FC_ENUM16: + case FC_ENUM32: + case FC_ERROR_STATUS_T: + case FC_IGNORE: + case FC_INT3264: + case FC_UINT3264: + //processSimpleType(pContext, + bResult = processSimpleType(pContext, (FC_TYPE)bFC_TYPE, paramDesc, oss); + if (bResult==FALSE) RPC_ERROR_FN("processSimpleType failed\n"); + break; + + + + //------------------------------------ + // Arrays + //------------------------------------ + case FC_CARRAY: + bResult = processConformantArray(pContext,paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processConformantArray failed\n"); + break; + case FC_CVARRAY: + bResult = processConformantVaryingArray(pContext,paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processConformantVaryingArray failed\n"); + break; + case FC_SMFARRAY: + case FC_LGFARRAY: + bResult = processFixedSizeArray(pContext,paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processFixedSizeArray failed\n"); + break; + case FC_SMVARRAY: + case FC_LGVARRAY: + bResult = processVaryingArray(pContext,paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processVaryingArray failed\n"); + break; + case FC_BOGUS_ARRAY: + bResult = processComplexArray(pContext,paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processComplexArray failed\n"); + break; + //------------------------------------ + // Structures + //------------------------------------ + case FC_STRUCT: + case FC_PSTRUCT: + case FC_CSTRUCT: + case FC_CPSTRUCT: + case FC_CVSTRUCT: + case FC_BOGUS_STRUCT: + case FC_HARD_STRUCT: + bResult = processStructure(pContext, paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processStructure failed\n"); + break; + //------------------------------------ + // Unions + //------------------------------------ + case FC_ENCAPSULATED_UNION: + + bResult = processEncapsulatedUnion( + pContext, + paramDesc.getRva(), + (FC_TYPE)bFC_TYPE, + paramDesc, + listProcTypes, + oss); + if (bResult == FALSE) RPC_ERROR_FN("processEncapsulatedUnion failed\n"); + break; + + case FC_NON_ENCAPSULATED_UNION: + + bResult = processNonEncapsulatedUnion( + pContext, + paramDesc.getRva(), + (FC_TYPE)bFC_TYPE, + paramDesc, + listProcTypes, + oss); + if (bResult == FALSE) RPC_ERROR_FN("processNonEncapsulatedUnion failed\n"); + break; + + + + + //------------------------------------ + // Pointers + //------------------------------------ + case FC_RP: + case FC_UP: + case FC_FP: + case FC_OP: + bResult = processStandardPointer( + pContext, + paramDesc.getRva(), + (FC_TYPE)bFC_TYPE, + paramDesc, + listProcTypes, + oss); + if (bResult == FALSE) RPC_ERROR_FN("processStandardPointer failed\n"); + break; + + case FC_IP: + bResult = processInterfacePointer( + pContext, + paramDesc.getRva(), + paramDesc, + oss); + if (bResult == FALSE) RPC_ERROR_FN("processInterfacePointer failed\n"); + break; + + case FC_BYTE_COUNT_POINTER: + bResult = processByteCountPointer( + pContext, + paramDesc.getRva(), + paramDesc, + listProcTypes, + oss + ); + if (bResult == FALSE) RPC_ERROR_FN("processByteCountPointer failed\n"); + break; + + //------------------------------------ + // Strings + //------------------------------------ + case FC_C_CSTRING: + case FC_C_WSTRING: + bResult = processConformantString(pContext, paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, oss); + if (bResult == FALSE) RPC_ERROR_FN("processConformantString failed\n"); + break; + + case FC_WSTRING: + case FC_CSTRING: + bResult = processNonConformantString(pContext, paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, oss); + if (bResult == FALSE) RPC_ERROR_FN("processNonConformantString failed\n"); + break; + + case FC_SSTRING: + case FC_C_SSTRING: + bResult = processStructureString(pContext, paramDesc.getRva(), (FC_TYPE)bFC_TYPE, paramDesc, oss); + if (bResult == FALSE) RPC_ERROR_FN("processStructureString failed\n"); + break; + + //------------------------------------ + // Misc ... + //------------------------------------ + case FC_BIND_CONTEXT: + bResult = processBindContext(pContext,paramDesc.getRva(), paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processBindContext failed\n"); + break; + + case FC_BLKHOLE: + bResult = process_FC_BLKHOLE(pContext, paramDesc.getRva(), paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("process_FC_BLKHOLE failed\n"); + break; + + case FC_RANGE: + bResult = processRange(pContext, paramDesc.getRva(), paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processRange failed\n"); + break; + + case FC_USER_MARSHAL: + bResult = processUserMarshal(pContext, paramDesc.getRva(), paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processUserMarshal failed\n"); + break; + + case FC_TRANSMIT_AS: + case FC_REPRESENT_AS: + bResult = processTransmitRepresentAs(pContext, paramDesc.getRva(), paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processTransmitRepresentAs failed\n"); + break; + + case FC_PIPE: + bResult = processPipe(pContext, paramDesc.getRva(), paramDesc, listProcTypes, oss); + if (bResult == FALSE) RPC_ERROR_FN("processPipe failed\n"); + break; + + case FC_ZERO: + + oss << "/* FC_ZERO */"; + bResult = TRUE; + break; + default: + RPC_ERROR_FN("Invalid type\n"); + oss << "[ERROR] dump type : unknown type (0x" << std::hex << (int)bFC_TYPE << ")" << std::endl; + + return FALSE; + } + + + return bResult; +} + + +//----------------------------------------------------------------------------- +BOOL __fastcall getTypeMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize, + _In_ BOOL bHasRangeOnConformance) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + BYTE bFC_TYPE; + + *pszMemorySize = 0; + + RPC_GET_PROCESS_DATA( + pType, + &bFC_TYPE, + sizeof(bFC_TYPE)); + + if(bResult == FALSE) + { + RPC_DEBUG_FN((UCHAR*)"[ERROR] getTypeMemorySize : Unable to get process data\n"); + return FALSE; + } + + + switch(bFC_TYPE) + { + //------------------------------------ + // Simple type + //------------------------------------ + case FC_BYTE: + case FC_CHAR: + case FC_SMALL: + case FC_WCHAR: + case FC_SHORT: + case FC_USHORT: + case FC_LONG: + case FC_ULONG: + case FC_FLOAT: + case FC_HYPER: + case FC_DOUBLE: + case FC_ENUM16: + case FC_ENUM32: + case FC_ERROR_STATUS_T: + case FC_IGNORE: + case FC_INT3264: + case FC_UINT3264: + //processSimpleType(pContext, + (*pszMemorySize) = getSimpleTypeMemorySize((FC_TYPE)bFC_TYPE); + bResult = TRUE; + break; + + + + //------------------------------------ + // Arrays + //------------------------------------ + case FC_CARRAY: + case FC_CVARRAY: + case FC_SMFARRAY: + case FC_LGFARRAY: + case FC_SMVARRAY: + case FC_LGVARRAY: + case FC_BOGUS_ARRAY: + *pszMemorySize = getArrayMemorySize(pContext, pType); + break; + + + //------------------------------------ + // Structures + //------------------------------------ + case FC_STRUCT: + case FC_PSTRUCT: + case FC_CSTRUCT: + case FC_CPSTRUCT: + case FC_CVSTRUCT: + case FC_BOGUS_STRUCT: + case FC_HARD_STRUCT: + bResult = getStructureMemorySize(pContext, pType, pszMemorySize); + + break; + + //------------------------------------ + // Unions + //------------------------------------ + case FC_ENCAPSULATED_UNION: + bResult = getEncapsulatedUnionMemorySize(pContext, pType, pszMemorySize); + break; + + case FC_NON_ENCAPSULATED_UNION: + bResult = getNonEncapsulatedUnionMemorySize(pContext, pType, pszMemorySize, bHasRangeOnConformance); + break; + + + + + //------------------------------------ + // Pointers / Strings / BIND_CONTEXT + //------------------------------------ + case FC_RP: + case FC_UP: + case FC_FP: + case FC_OP: + case FC_IP: + case FC_BYTE_COUNT_POINTER: + case FC_C_CSTRING: + case FC_C_WSTRING: + case FC_WSTRING: + case FC_CSTRING: + case FC_BIND_CONTEXT: + *pszMemorySize = POINTER_SIZE; + bResult = TRUE; + break; + + + + //------------------------------------ + // Misc ... + //------------------------------------ + case FC_BLKHOLE: + bResult = getFC_BLKHOLEMemorySize(pContext, pType, pszMemorySize, bHasRangeOnConformance); + break; + + case FC_RANGE: + bResult = getRangeMemorySize(pContext, pType, pszMemorySize); + break; + + case FC_USER_MARSHAL: + bResult = getUserMarshallMemorySize(pContext, pType, pszMemorySize); + break; + + case FC_TRANSMIT_AS: + case FC_REPRESENT_AS: + bResult = getTransmitAsRepresentAsMemorySize(pContext, pType, pszMemorySize); + break; + + case FC_PIPE: + bResult = getPipeMemorySize(pContext, pType, pszMemorySize, bHasRangeOnConformance); + break; + + case FC_ZERO: + *pszMemorySize = 0; + bResult = TRUE; + break; + + default: + bResult = FALSE; + RPC_DEBUG_FN("[ERROR] getTypeMemorySize : unable to get memory size for type : 0x%x \n", bFC_TYPE); + + return FALSE; + } + + //// + //if(bResult == TRUE) + //{ + // RPC_PRINT_FN((UCHAR*)"getTypeMemorySize type : %x, size : %x \n", bFC_TYPE, *pszMemorySize); + // + //} + //else + //{ + // RPC_PRINT_FN((UCHAR*)"getTypeMemorySize failed \n"); + //} + //// + + return bResult; +} + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall RpcDecompilerPrintParam( + _In_ VOID* pContext, + _In_ UINT paramOffset, + _In_ ParamID_E paramDescrFormat, + _Out_ UINT * paramSizeInBytes, + _In_ const IdlFunctionDesc& IdlFunctionDesc, + _Inout_ std::list& listProcType, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + //UINT formatStringOffset = 0; + ProcFormatStringParam_U paramToPrint; + + UINT32 argNbr = 0; + + ParamDesc ParamDesc; + + //following checks already done by the caller function + /* if (pRpcDecompilerCtxt == NULL) goto End; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) goto End; + + if(pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString == NULL) goto End; */ + + + switch(paramDescrFormat) + { + case paramDescrOi: + //TODO + //paramSizeInBytes = OI_PARAM_BASETYPE_SIZE; + //paramSizeInBytes = OI_PARAM_OTHERTYPE_SIZE; + goto End; + break; + + + case paramDescrOif: + *paramSizeInBytes = OIF_PARAM_SIZE; + + RPC_GET_PROCESS_DATA( + (pRpcDecompilerCtxt->pRpcDecompilerInfo->pProcFormatString + paramOffset), + ¶mToPrint, + sizeof(paramToPrint) + ); + + RPC_DEBUG_FN((UCHAR*)"\nparamToPrint.oif_Format.paramAttributes = 0x%x", paramToPrint.oif_Format.paramAttributes); + RPC_DEBUG_FN((UCHAR*)"\nparamToPrint.oif_Format.stack_offset = 0x%x", paramToPrint.oif_Format.stack_offset); + + //*isReturnParam = paramToPrint.oif_Format.paramAttributes.IsReturn; + + + if(is64B) argNbr = paramToPrint.oif_Format.stack_offset / VIRTUAL_STACK_OFFSET_GRANULARITY_64B; + else argNbr = paramToPrint.oif_Format.stack_offset / VIRTUAL_STACK_OFFSET_GRANULARITY_32B; + + + // add param IdlFunctionDesc properties + if(IdlFunctionDesc.hasRangeOnConformance()) + { + ParamDesc.setHasRangeOnConformance(); + } + + // fill param desc with ParamAttr + ParamDesc.fillWithParamAttr(paramToPrint.oif_Format.paramAttributes); + + if( (!paramToPrint.oif_Format.paramAttributes.IsReturn) /*&& + (typeFieldType != ptrCommonSimpleDescr) && + (typeFieldType != ptrCommonComplexDescr) && + (typeFieldType != ptrInterfaceConstantIID) && + (typeFieldType != ptrInterfaceNonConstantIIDDescr) && + (typeFieldType != ptrByteCountSimpleDescr) && + (typeFieldType != ptrByteCountComplexDescr)*/ + // ) { RPC_PRINT_FN((UCHAR*)"_%d", paramOffset); RPC_DEBUG_FN((UCHAR*)"_%d", paramOffset);} + ) + { + std::ostringstream ossTmp; + ossTmp << "arg_" << argNbr; + + ParamDesc.setParamName(ossTmp.str()); + + RPC_DEBUG_FN((UCHAR*)" arg_%d", argNbr); + + oss << std::endl << "\t\t"; + + if(paramToPrint.oif_Format.paramAttributes.IsIn && paramToPrint.oif_Format.paramAttributes.IsOut) + { + oss << "[in, out]"; + RPC_DEBUG_FN((UCHAR*)"[in, out]"); + } + else if (paramToPrint.oif_Format.paramAttributes.IsIn) + { + oss<<"[in]"; + RPC_DEBUG_FN((UCHAR*)"[in]"); + } + else // paramAttributes.IsOut + { + oss<<"[out]"; + RPC_DEBUG_FN((UCHAR*)"[out]"); + } + } + + if(paramToPrint.oif_Format.paramAttributes.IsBasetype) + { + bResult = processSimpleType( + pContext, + (FC_TYPE)paramToPrint.oif_Format.paramType.base_type_format_char.type_format_char, + ParamDesc, + oss); + + if(FALSE == bResult) + { + displayErrorMessage(oss, " unable to processSimpleType "); + goto End; + } + + + } //if(paramToPrint.oif_Format.paramAttributes.IsBasetype) + else + { + //ParamDesc.setuOffset(paramToPrint.oif_Format.paramType.other_type_offset); // param offset in type format string + ParamDesc.setRva(pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString + paramToPrint.oif_Format.paramType.other_type_offset); + + bResult = rpcDumpType( + pContext, + ParamDesc, + listProcType, + oss); + + if(bResult == FALSE) + { + displayErrorMessage(oss, " unable to dump type"); + //RPC_DEBUG_FN((UCHAR*)"\n!!! source = %s ligne = %d - PrintParamOfFieldType returned bResult = %d", __FILE__, __LINE__, bResult); + goto End; + } + }// !(paramToPrint.oif_Format.paramAttributes.IsBasetype) + + + + bResult = TRUE; + break; + + + default: + RPC_DEBUG_FN((UCHAR*)"\n!!! RpcDecompilerPrintParam : ERROR, paramDescrFormat not recognized"); + bResult = FALSE; + goto End; + break; + } + +End: + return (bResult); +} + diff --git a/RpcDecompiler/internalRpcDecompiler.h b/RpcDecompiler/internalRpcDecompiler.h new file mode 100644 index 0000000..48f4ee9 --- /dev/null +++ b/RpcDecompiler/internalRpcDecompiler.h @@ -0,0 +1,104 @@ +#ifndef _INTERNAL_RPC_DECOMPILER_H_ +#define _INTERNAL_RPC_DECOMPILER_H_ + +#include + +#include "internalRpcDecompTypeDefs.h" + + +//#define DBG_DECOMP + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall getAllTypesSortedInAList( + _In_ VOID* pContext, + _In_ std::list & listTypesToDefine, + _Inout_ std::list& listAllTypesSorted, + _Inout_ std::ostringstream& oss); + + +// --------------------------------------------------------------------------------------------- +BOOL __fastcall dumpTypeList( + _In_ VOID* pContext, + _In_ std::list & listTypesToDefine, + _Inout_ std::ostringstream& oss); + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall RpcDecompilerPrintAllTypesInList( + _In_ VOID* pContext, + _In_ std::list & listProcTypes, + _Out_ std::ostringstream& oss); + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall RpcDecompilerDecodeAndPrintPrototypeReturnType( + _In_ VOID* pContext, + _In_ UINT ProcIndex, + _Out_ UINT * paramOffset, + _Out_ UINT * sizeOfProcDescr, + _Inout_ IdlFunctionDesc& IdlFunctionDesc, + _Inout_ std::list& listProcType, + _Inout_ std::ostringstream& oss); + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcDecompilerPrintPrototypeName( + _In_ VOID* pContext, + _In_ UINT ProcIndex, + _Inout_ std::ostringstream& oss); + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcDecompilerGetReturnParamInfo( + _In_ VOID* pContext, + _In_ UINT paramOffset, + _In_ ParamID_E paramDescrFormat, + _Out_ BOOL * isReturnParam); + + +// ------------------------------------------------------------------------------------------------ +DWORD __fastcall getSimpleTypeMemorySize(_In_ FC_TYPE fcType); + + +// ------------------------------------------------------------------------------------------------ +BOOL __fastcall processSimpleType( + _In_ VOID* pContext, + _In_ FC_TYPE fcType, + _Inout_ ParamDesc& paramDesc, + _Inout_ std::ostringstream& oss); + + +//----------------------------------------------------------------------------- +BOOL __fastcall printSimpleType( + _In_ VOID* pContext, + _In_ FC_TYPE fcType, + _Inout_ std::ostringstream& oss); + + +//------------------------------------------------------------------------------ +BOOL __fastcall rpcDumpType( + _In_ VOID* pContext, + _In_ ParamDesc& paramDesc, + _Inout_ std::list& listProcTypes, + _Inout_ std::ostringstream& oss); + +//----------------------------------------------------------------------------- +BOOL __fastcall getTypeMemorySize( + _In_ VOID* pContext, + _In_ RVA_T pType, + _Out_ size_t* pszMemorySize, + _In_ BOOL bHasRangeOnConformance); + + +// ---------------------------------------------------------------------------------------------- +BOOL __fastcall RpcDecompilerPrintParam( + _In_ VOID* pContext, + _In_ UINT paramOffset, + _In_ ParamID_E paramDescrFormat, + _Out_ UINT * paramSizeInBytes, + _In_ const IdlFunctionDesc& IdlFunctionDesc, + _Inout_ std::list& listProcType, + _Inout_ std::ostringstream& oss); + +#endif//_INTERNAL_RPC_DECOMPILER_H_ \ No newline at end of file diff --git a/RpcDecompiler/internalRpcUtils.h b/RpcDecompiler/internalRpcUtils.h new file mode 100644 index 0000000..6ff82de --- /dev/null +++ b/RpcDecompiler/internalRpcUtils.h @@ -0,0 +1,30 @@ +#ifndef _RPC_UTILS_ +#define _RPC_UTILS_ + +#include +#include +#include +#include +#include "RpcDecompiler.h" + + +//--------------------------------------------------------------------------- +BOOL __fastcall isStandardCharacter(_In_ const WCHAR wc); + + +//-------------------------------------------------------------------------- +std::string narrow( + _In_ const std::wstring& ws); + + +//------------------------------------------------------------------------- +VOID displayPtrLevel( + _In_ const UINT uPtrLevel, + _Inout_ std::ostringstream& oss); + +//-------------------------------------------------------------------------- +VOID displayErrorMessage( + _Inout_ std::ostringstream& oss, + _In_ PCHAR message); + +#endif \ No newline at end of file diff --git a/RpcDecompiler/internalTypeTools.cpp b/RpcDecompiler/internalTypeTools.cpp new file mode 100644 index 0000000..48b0826 --- /dev/null +++ b/RpcDecompiler/internalTypeTools.cpp @@ -0,0 +1,180 @@ +#include "..\RpcCommon\RpcView.h" +#include "internalRpcDecompTypeDefs.h" +#include "internalTypeTools.h" +#include "internalComplexTypesArrays.h" +#include "internalComplexTypesPointers.h" +#include "internalComplexTypesStrings.h" +#include "internalComplexTypesStructs.h" +#include "internalComplexTypesUnions.h" +#include "internalRpcUtils.h" + +#define DEFAULT_ENUM "\n\ + /* \n\ + // this is the default enum referenced by all functions and structures using an enum \n\ + typedef enum enum32_toDefine_t\n\ + {\n\ + value_0 = 0,\n\ + value_1 = 1,\n\ + //...\n\ + }enum32_toDefine_t;\n\ + */\n" + +//------------------------------------------------------------------------------ +void __fastcall printDefaultEnum( + _Inout_ std::ostringstream& oss) +{ + + oss <& listAdditionalType, + _Inout_ std::ostringstream& oss) +{ + BOOL bResult = FALSE; + RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext; + + RVA_T pType; + + if (pRpcDecompilerCtxt == NULL) return FALSE; + if (pRpcDecompilerCtxt->pRpcViewHelper == NULL) return FALSE; + + if(pRpcDecompilerCtxt->pRpcDecompilerInfo->pTypeFormatString == NULL) return FALSE; + + RPC_DEBUG_FN((UCHAR*)"\n\n******************** printType *********************"); + + + + pType = typeToDefine.getRva(); + + //RPC_GET_PROCESS_DATA( + // pType, + // &elementType, + // sizeof(BYTE) + // ); + + #ifdef DBG_DECOMP + oss << std::endl << "/* pType : 0x"< +#include + + +//---------------------------------------------------------------------------- +BOOL __fastcall isSimpleType( + _In_ FC_TYPE type); + + +//----------------------------------------------------------------------------- +BOOL __fastcall printType( + _In_ VOID* pContext, + _In_ TypeToDefine& typeToDefine, + _Inout_ std::list& listAdditionalType, + _Inout_ std::ostringstream& oss); + + + + +//------------------------------------------------------------------------------ +void __fastcall printDefaultEnum( + _Inout_ std::ostringstream& oss); + + +#endif//_INTERNAL_TYPE_TOOLS_H_ \ No newline at end of file diff --git a/RpcView/CMakeLists.txt b/RpcView/CMakeLists.txt new file mode 100644 index 0000000..3fc17cf --- /dev/null +++ b/RpcView/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required (VERSION 3.0.2) + +message("[RpcView]") + +project(RpcView) + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) + +# Find the QtWidgets library +# set CMAKE_PREFIX_PATH=c:\Qt\4.8.6 +find_package(Qt4 REQUIRED QtGui QtCore) + +add_executable( + RpcView + + "${PROJECT_BINARY_DIR}/../RpcViewVersion.h" + DecompilationWidget.cpp + EndpointsWidget.cpp + FilterWidget.cpp + IdlHighlighter.cpp + InterfaceInfoWidget.cpp + InterfacesWidget.cpp + MainWindow.cpp + ../RpcCommon/Misc.c + ../RpcCommon/ntdll.c + Pdb.c + ProceduresWidget.cpp + ProcessInfoWidget.cpp + ProcessWidget.cpp + + ConfigurationVisitor.cpp + EndpointSelectedVisitor.cpp + InitViewsVisitor.cpp + InterfaceSelectedVisitor.cpp + ProcessSelectedVisitor.cpp + RefreshVisitor.cpp + + RpcCoreManager.c + RpcView.cpp + RpcViewResource.rc + ) + +if(${CMAKE_GENERATOR} MATCHES "Win64") + message(STATUS "Target is 64 bits") + target_link_libraries(RpcView ../../../Qt/lib/x64/QtGui ../../../Qt/lib/x64/QtCore) + target_link_libraries(RpcView Qt4::QtGui Qt4::QtCore) +else(${CMAKE_GENERATOR} MATCHES "Win64") + message(STATUS "Target is 32 bits") + target_link_libraries(RpcView ../../../Qt/lib/x86/QtGui ../../../Qt/lib/x86/QtCore) + target_link_libraries(RpcView Qt4::QtGui Qt4::QtCore) +endif(${CMAKE_GENERATOR} MATCHES "Win64") \ No newline at end of file diff --git a/RpcView/ConfigurationVisitor.cpp b/RpcView/ConfigurationVisitor.cpp new file mode 100644 index 0000000..8ff4e96 --- /dev/null +++ b/RpcView/ConfigurationVisitor.cpp @@ -0,0 +1,144 @@ +#include "ConfigurationVisitor.h" +#include "EndpointsWidget.h" +#include "InterfacesWidget.h" +#include "InterfaceInfoWidget.h" +#include "ProcessWidget.h" +#include "ProcessInfoWidget.h" +#include "ProceduresWidget.h" + +//------------------------------------------------------------------------------ +ConfigurationVisitor_C::ConfigurationVisitor_C(ConfigurationType_T ConfigurationType, QSettings* pSettings) +{ + this->pSettings = pSettings; + this->ConfigurationType = ConfigurationType; +} + + +//------------------------------------------------------------------------------ +void ConfigurationVisitor_C::Visit(EndpointsWidget_C* pEndpointsWidget) +{ + switch (ConfigurationType) + { + case Load: + pEndpointsWidget->LoadConfiguration(this->pSettings); + break; + //-- + case Save: + pEndpointsWidget->SaveConfiguration(this->pSettings); + break; + //-- + case UpdateColumns: + pEndpointsWidget->UpdateColumnsVisibility(); + break; + // + default: + break; + } +} + + +//------------------------------------------------------------------------------ +void ConfigurationVisitor_C::Visit(InterfacesWidget_C* pInterfacesWidget) +{ + switch (ConfigurationType) + { + case Load: + pInterfacesWidget->LoadConfiguration(this->pSettings); + break; + //-- + case Save: + pInterfacesWidget->SaveConfiguration(this->pSettings); + break; + //-- + case UpdateColumns: + pInterfacesWidget->UpdateColumnsVisibility(); + break; + //-- + case AddressRVA: + pInterfacesWidget->SetAddressRepresentation(AddressRepresentation_RVA); + break; + //-- + case AddressAbsolute: + pInterfacesWidget->SetAddressRepresentation(AddressRepresentation_Absolute); + break; + //-- + default: + break; + } +} + +//------------------------------------------------------------------------------ +void ConfigurationVisitor_C::Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget) +{ + switch (ConfigurationType) + { + case AddressRVA: + pInterfaceInfoWidget->SetAddressRepresentation(AddressRepresentation_RVA); + break; + //-- + case AddressAbsolute: + pInterfaceInfoWidget->SetAddressRepresentation(AddressRepresentation_Absolute); + break; + //-- + default: + break; + } +} + +//------------------------------------------------------------------------------ +void ConfigurationVisitor_C::Visit(ProcessInfoWidget_C* pProcessInfoWidget) +{ + //nothing to do here +} + +//------------------------------------------------------------------------------ +void ConfigurationVisitor_C::Visit(ProceduresWidget_C* pProceduresWidget) +{ + switch (ConfigurationType) + { + case Load: + pProceduresWidget->LoadConfiguration(this->pSettings); + break; + //-- + case Save: + pProceduresWidget->SaveConfiguration(this->pSettings); + break; + //-- + case UpdateColumns: + pProceduresWidget->UpdateColumnsVisibility(); + break; + //-- + case AddressRVA: + pProceduresWidget->SetAddressRepresentation(AddressRepresentation_RVA); + break; + //-- + case AddressAbsolute: + pProceduresWidget->SetAddressRepresentation(AddressRepresentation_Absolute); + break; + //-- + default: + break; + } +} + +//------------------------------------------------------------------------------ +void ConfigurationVisitor_C::Visit(ProcessWidget_C* pProcessWidget) +{ + switch (ConfigurationType) + { + case Load: + pProcessWidget->LoadConfiguration(this->pSettings); + break; + //-- + case Save: + pProcessWidget->SaveConfiguration(this->pSettings); + break; + //-- + case UpdateColumns: + pProcessWidget->UpdateColumnsVisibility(); + break; + // + default: + break; + } +} \ No newline at end of file diff --git a/RpcView/ConfigurationVisitor.h b/RpcView/ConfigurationVisitor.h new file mode 100644 index 0000000..57d26d2 --- /dev/null +++ b/RpcView/ConfigurationVisitor.h @@ -0,0 +1,36 @@ +#ifndef _CONFIGURATION_VISITOR_H_ +#define _CONFIGURATION_VISITOR_H_ + +#include "../Qt/Qt.h" +#include "ViewVisitor.h" +#include "ProcessEntry.h" +#include "..\RpcCore\RpcCore.h" + + +//------------------------------------------------------------------------------ +class ConfigurationVisitor_C : public ViewVisitor_C +{ +public: + typedef enum { + Load, + Save, + UpdateColumns, + AddressAbsolute, + AddressRVA + }ConfigurationType_T; + + ConfigurationVisitor_C(ConfigurationType_T, QSettings*); + + virtual void Visit(EndpointsWidget_C* pEndpointsWidget); + virtual void Visit(InterfacesWidget_C* pInterfacesWidget); + virtual void Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget); + virtual void Visit(ProcessInfoWidget_C* pProcessInfoWidget); + virtual void Visit(ProceduresWidget_C* pProceduresWidget); + virtual void Visit(ProcessWidget_C* pProcessWidget); + +private: + QSettings* pSettings; + ConfigurationType_T ConfigurationType; +}; + +#endif //_CONFIGURATION_VISITOR_H_ \ No newline at end of file diff --git a/RpcView/DecompilationWidget.cpp b/RpcView/DecompilationWidget.cpp new file mode 100644 index 0000000..7a79ba3 --- /dev/null +++ b/RpcView/DecompilationWidget.cpp @@ -0,0 +1,37 @@ +#include "DecompilationWidget.h" + +#define TAB_AS_CHARS 4 + +static const char WidgetName[] = "Decompilation"; + + +//------------------------------------------------------------------------------ +void DecompilationWidget_C::InsertText(const char* Txt) +{ + /* + pTextEdit->moveCursor(QTextCursor::End); + pTextEdit->append( QString::fromAscii(Txt) ); + pTextEdit->ensureCursorVisible(); + */ + pTextEdit->setText( QString::fromAscii(Txt) ); + pTextEdit->ensureCursorVisible(); +} + +//------------------------------------------------------------------------------ +DecompilationWidget_C::DecompilationWidget_C(QWidget *parent) : QDockWidget(WidgetName) +{ + QFont font; + + setObjectName(WidgetName); + + font.setFamily("Courier"); + font.setFixedPitch(true); + + pTextEdit = new QTextEdit(this); + pTextEdit->setLineWrapMode(QTextEdit::NoWrap); + pTextEdit->setFont(font); + pTextEdit->setTabStopWidth(font.pointSize()*TAB_AS_CHARS); + + pIdlHighlighter = new IdlHighlighter_C(pTextEdit->document()); + setWidget(pTextEdit); +} \ No newline at end of file diff --git a/RpcView/DecompilationWidget.h b/RpcView/DecompilationWidget.h new file mode 100644 index 0000000..2c8d866 --- /dev/null +++ b/RpcView/DecompilationWidget.h @@ -0,0 +1,20 @@ +#ifndef _DECOMPILATION_WIDGET_H_ +#define _DECOMPILATION_WIDGET_H_ + +#include "../Qt/Qt.h" +#include "IdlHighlighter.h" + +class DecompilationWidget_C : public QDockWidget + { + Q_OBJECT + + public: + DecompilationWidget_C(QWidget* pParent); + void InsertText(const char* Txt); + + private: + IdlHighlighter_C* pIdlHighlighter; + QTextEdit* pTextEdit; + }; + +#endif //_DECOMPILATION_WIDGET_H_ \ No newline at end of file diff --git a/RpcView/EndpointSelectedVisitor.cpp b/RpcView/EndpointSelectedVisitor.cpp new file mode 100644 index 0000000..b3734a9 --- /dev/null +++ b/RpcView/EndpointSelectedVisitor.cpp @@ -0,0 +1,102 @@ +#include "EndpointSelectedVisitor.h" +#include "EndpointsWidget.h" +#include "InterfacesWidget.h" +#include "InterfaceInfoWidget.h" +#include "ProcessWidget.h" +#include "ProcessInfoWidget.h" +#include "ProceduresWidget.h" +#include "../RpcCommon/Misc.h" + + +typedef struct _EnumCtxt_T{ + ProcessInfoWidget_C* pProcessInfoWidget; +}EnumCtxt_T; + + +//------------------------------------------------------------------------------ +EndpointSelectedVisitor_C::EndpointSelectedVisitor_C(quint32 Pid,RpcCore_T* pRpcCore,void* pRpcCoreCtxt) +{ + this->Pid = Pid; + this->pRpcCore = pRpcCore; + this->pRpcCoreCtxt = pRpcCoreCtxt; +} + + +//------------------------------------------------------------------------------ +void EndpointSelectedVisitor_C::Visit(EndpointsWidget_C* pEndpointsWidget) +{ + //nothing to do here +} + + +//------------------------------------------------------------------------------ +void EndpointSelectedVisitor_C::Visit(InterfacesWidget_C* pInterfacesWidget) +{ + // + // Apply process filter + // + pInterfacesWidget->ApplyProcessFilter(Pid); + pInterfacesWidget->resizeColumnsToContents(); +} + +//------------------------------------------------------------------------------ +void EndpointSelectedVisitor_C::Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget) +{ + // + // if the Pid of the selected endpoint is different from the current + // interface one we ave to reset the InterfaceInfoWidget + // + if (this->Pid != pInterfaceInfoWidget->GetPid()) + { + pInterfaceInfoWidget->Reset(); + } +} + + +//------------------------------------------------------------------------------ +static BOOL __fastcall EnumProcessAuth(DWORD Pid, RpcAuthInfo_T* pRpcAuthInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + UNREFERENCED_PARAMETER(Pid); + UNREFERENCED_PARAMETER(pbContinue); + + pEnumCtxt->pProcessInfoWidget->AddAuthInfo(pRpcAuthInfo); + return (TRUE); +} + + +//------------------------------------------------------------------------------ +void EndpointSelectedVisitor_C::Visit(ProcessInfoWidget_C* pProcessInfoWidget) +{ + RpcProcessInfo_T* pRpcProcessInfo; + EnumCtxt_T EnumCtxt; + + EnumCtxt.pProcessInfoWidget = pProcessInfoWidget; + pProcessInfoWidget->reset(); + + pRpcProcessInfo = pRpcCore->RpcCoreGetProcessInfoFn( pRpcCoreCtxt, Pid, 0, RPC_PROCESS_INFO_ALL ); + if (pRpcProcessInfo != NULL) + { + pProcessInfoWidget->UpdateProcessInfo(pRpcProcessInfo); + pRpcCore->RpcCoreFreeProcessInfoFn( pRpcCoreCtxt, pRpcProcessInfo ); + pRpcCore->RpcCoreEnumProcessAuthInfoFn( pRpcCoreCtxt, Pid, (RpcCoreEnumProcessAuthInfoCallbackFn_T)EnumProcessAuth,&EnumCtxt); + } +} + +//------------------------------------------------------------------------------ +void EndpointSelectedVisitor_C::Visit(ProceduresWidget_C* pProceduresWidget) +{ + // + // if the Pid of the selected endpoint is different from the current + // procedure one we ave to reset the ProcedureWidget + // + if (this->Pid != pProceduresWidget->GetPid()) + { + pProceduresWidget->reset(this->Pid); + } +} + +//------------------------------------------------------------------------------ +void EndpointSelectedVisitor_C::Visit(ProcessWidget_C* pProcessWidget) +{ + pProcessWidget->SelectProcess(Pid); +} \ No newline at end of file diff --git a/RpcView/EndpointSelectedVisitor.h b/RpcView/EndpointSelectedVisitor.h new file mode 100644 index 0000000..af970e2 --- /dev/null +++ b/RpcView/EndpointSelectedVisitor.h @@ -0,0 +1,25 @@ +#ifndef _ENDPOINT_SELECTED_VISITOR_H_ +#define _ENDPOINT_SELECTED_VISITOR_H_ + +#include "..\Qt\Qt.h" +#include "ViewVisitor.h" +#include "..\RpcCore\RpcCore.h" + +//------------------------------------------------------------------------------ +class EndpointSelectedVisitor_C : public ViewVisitor_C +{ +private: + RpcCore_T* pRpcCore; + void* pRpcCoreCtxt; + quint32 Pid; +public: + EndpointSelectedVisitor_C(quint32 Pid,RpcCore_T* pRpcCore,void* pRpcCoreCtxt); + virtual void Visit(EndpointsWidget_C* pEndpointsWidget); + virtual void Visit(InterfacesWidget_C* pInterfacesWidget); + virtual void Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget); + virtual void Visit(ProcessInfoWidget_C* pProcessInfoWidget); + virtual void Visit(ProceduresWidget_C* pProceduresWidget); + virtual void Visit(ProcessWidget_C* pProcessWidget); +}; + +#endif \ No newline at end of file diff --git a/RpcView/EndpointsWidget.cpp b/RpcView/EndpointsWidget.cpp new file mode 100644 index 0000000..6d00217 --- /dev/null +++ b/RpcView/EndpointsWidget.cpp @@ -0,0 +1,265 @@ +#include "EndpointsWidget.h" +#include "..\RpcCommon\RpcCommon.h" + + +static const char WidgetName[] = "Endpoints"; + + +//------------------------------------------------------------------------------ +QString EndpointsWidget_C::GetEndpointsWidgetColumnName(Column_T Column) +{ + switch(Column) + { + case Column_Pid : return (QString("Pid")); + case Column_Protocol: return (QString("Protocol")); + case Column_Name : return (QString("Name")); + default : return (QString("Unknown")); + } +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::EndpointSelected(const QModelIndex& Index) +{ + quint32 Pid; + + Pid = pProxyModel->data(pProxyModel->index(Index.row(), Column_Pid)).toUInt(); + // + // Emit the EndpointSelected signal so that the MainWindow sends + // the appropriate visitor + // + emit EndpointSelected(Pid); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::ApplyProcessFilter(quint32 Pid) +{ + if (Pid == INVALID_PID_VALUE) + { + pProxyModel->setFilterRegExp( QRegExp(".*") ); + } + else + { + pProxyModel->setFilterRegExp( QString("^%1$").arg(Pid) ); + if (pProxyModel->rowCount() == 0) pProxyModel->setFilterRegExp( QRegExp(".*") ); + } + pFilterWidget->Reset(); +} + + +//------------------------------------------------------------------------------ +ULONG EndpointsWidget_C::GetEndpoints() +{ + return (ULONG)pProxyModel->rowCount(); +} + + +//------------------------------------------------------------------------------ +ULONG EndpointsWidget_C::GetTotalEndpoints() +{ + return (ULONG)pModel->rowCount(); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::SnapEndpoint() +{ + PrivateItemList = pModel->findItems(".*", Qt::MatchRegExp, Column_Name); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::RemoveUnregisteredEndpoints() +{ + for (auto Iter=PrivateItemList.begin();Iter!=PrivateItemList.end();Iter++) + { + if (*Iter!=NULL) pModel->removeRow( (*Iter)->row()); + } +} + + +//------------------------------------------------------------------------------ +bool EndpointsWidget_C::IsEndpointsPresent(quint32 Pid, WCHAR* pName,WCHAR* pProtocole) +{ + QList ItemList; + bool bResult = false; + + ItemList = pModel->findItems(QString::fromUtf16((const ushort*)pName), Qt::MatchFixedString, Column_Name); + 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_Protocol)).toString() == QString::fromUtf16((const ushort*)pProtocole)) + { + PrivateItemList.removeOne(*Iter); + + bResult = true; + goto End; + } + } + } +End: + return (bResult); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::SaveConfiguration(QSettings* pSettings) +{ + pSettings->setValue("Endpoints/geometry",pEndpoints->header()->saveState()); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::LoadConfiguration(QSettings* pSettings) +{ + pEndpoints->header()->restoreState( pSettings->value("Endpoints/geometry").toByteArray() ); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::resizeColumnsToContents() +{ + int Index; + + for (Index = 0; Index < Column_Last; Index++) + { + pEndpoints->resizeColumnToContents(Index); + } +} + + +//------------------------------------------------------------------------------ +bool EndpointsWidget_C::AddEndpoint(quint32 Pid, RpcEndpointInfo_T* pRpcEndpointInfo) +{ + int Index; + + Index = pModel->rowCount(); + pModel->setRowCount(Index+1); + pModel->setData(pModel->index(Index, EndpointsWidget_C::Column_Pid), Pid); + pModel->setData(pModel->index(Index, EndpointsWidget_C::Column_Protocol), QString::fromUtf16((const ushort*)pRpcEndpointInfo->pProtocole)); + pModel->setData(pModel->index(Index, EndpointsWidget_C::Column_Name), QString::fromUtf16((const ushort*)pRpcEndpointInfo->pName)); + return (true); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::AcceptVisitor(ViewVisitor_C* pVisitor) +{ + pVisitor->Visit(this); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::UpdateUserFilter() +{ + if (pFilterWidget->GetText()!="") ApplyUserFilter( pFilterWidget->GetText() ); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::ApplyUserFilter(const QString & FilterText) +{ + QRegExp FilterRegExp; + + FilterRegExp.setPattern( FilterText ); + FilterRegExp.setCaseSensitivity( Qt::CaseInsensitive ); + + pProxyModel->setFilterKeyColumn(-1); //filter all columns: UGLY Qt + pProxyModel->setFilterRegExp( FilterRegExp ); +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::CreateColumnsSelectionWidget() +{ + pColumnsSelectionWidget = new QGroupBox(WidgetName,this); + QVBoxLayout* pLayout = new QVBoxLayout(pColumnsSelectionWidget); + + for (int i = 0; i < Column_Last; i++) + { + CheckBoxArray[i] = new QCheckBox(GetEndpointsWidgetColumnName((Column_T)i),this); + pLayout->addWidget(CheckBoxArray[i]); + } + pColumnsSelectionWidget->setLayout(pLayout); +} + + +//------------------------------------------------------------------------------ +QWidget* EndpointsWidget_C::GetColumnsSelectionWidget() +{ + for (int i = 0; i < Column_Last; i++) + { + CheckBoxArray[i]->setChecked(!pEndpoints->header()->isSectionHidden(i)); + } + return pColumnsSelectionWidget; +} + + +//------------------------------------------------------------------------------ +void EndpointsWidget_C::UpdateColumnsVisibility() +{ + for (int i = 0; i < Column_Last; i++) + { + pEndpoints->header()->setSectionHidden(i, !CheckBoxArray[i]->isChecked()); + } +} + + +//------------------------------------------------------------------------------ +EndpointsWidget_C::EndpointsWidget_C(QWidget* pParent):QDockWidget(WidgetName) +{ + QGridLayout* pGridLayout; + QGroupBox* pGroupBox; + + setObjectName(WidgetName); + + pGroupBox = new QGroupBox(this); + pGridLayout = new QGridLayout; + + pProxyModel = new QSortFilterProxyModel(this); + pProxyModel->setDynamicSortFilter(true); + pProxyModel->setFilterKeyColumn(Column_Pid); + pProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + + pModel = new QStandardItemModel(0, Column_Last, this); + + for (uint i = 0; isetHeaderData(i, Qt::Horizontal, GetEndpointsWidgetColumnName( (EndpointsWidget_C::Column_T)i ) ); + } + + pEndpoints = new QTreeView; + pEndpoints->setEditTriggers(QAbstractItemView::NoEditTriggers); + pEndpoints->setSelectionBehavior(QAbstractItemView::SelectRows); + pEndpoints->setSelectionMode(QAbstractItemView::SingleSelection); + pEndpoints->setRootIsDecorated(false); + pEndpoints->setSortingEnabled(true); + pEndpoints->setAlternatingRowColors(true); + pEndpoints->setAnimated(true); + pEndpoints->setModel(pProxyModel); + pEndpoints->sortByColumn(Column_Protocol, Qt::AscendingOrder); + pEndpoints->header()->installEventFilter(pParent); + + pProxyModel->setSourceModel(pModel); + + connect( pEndpoints, SIGNAL(pressed(const QModelIndex&)), this, SLOT(EndpointSelected(const QModelIndex&))); + connect( pEndpoints, SIGNAL(activated(const QModelIndex&)), this, SLOT(EndpointSelected(const QModelIndex&))); + connect( this, SIGNAL(EndpointSelected(quint32)), pParent, SLOT(EndpointSelected(quint32)) ); + // + // Add user filtering (CTL+F) support + // + pFilterWidget = new FilterWidget_C(this); + + pGridLayout->addWidget(pEndpoints,0,0); + pGridLayout->addWidget(pFilterWidget,1,0); + pGroupBox->setLayout(pGridLayout); + setWidget(pGroupBox); + // + // Create the Widget for column selection + // + CreateColumnsSelectionWidget(); +} \ No newline at end of file diff --git a/RpcView/EndpointsWidget.h b/RpcView/EndpointsWidget.h new file mode 100644 index 0000000..629fd4c --- /dev/null +++ b/RpcView/EndpointsWidget.h @@ -0,0 +1,63 @@ +#ifndef _ENDPOINTS_WIDGET_H_ +#define _ENDPOINTS_WIDGET_H_ + +#include "..\Qt\Qt.h" +#include "..\RpcCore\RpcCore.h" +#include "FilterWidget.h" +#include "View.h" + +//----------------------------------------------------------------------------- +class EndpointsWidget_C : public QDockWidget, public View_I +{ + Q_OBJECT + +public: + EndpointsWidget_C(QWidget* pParent); + + virtual void AcceptVisitor(ViewVisitor_C* pVisitor); + void ApplyProcessFilter(quint32 Pid); + ULONG GetEndpoints(); + ULONG GetTotalEndpoints(); + bool IsEndpointsPresent(quint32 Pid, WCHAR* pName,WCHAR* pProtocol); + void RemoveUnregisteredEndpoints(); + void SnapEndpoint(); + void resizeColumnsToContents(); + bool AddEndpoint(quint32 Pid, RpcEndpointInfo_T* pRpcEndpointInfo); + void UpdateUserFilter(); + void SaveConfiguration(QSettings*); + void LoadConfiguration(QSettings*); + QWidget* GetColumnsSelectionWidget(); + void UpdateColumnsVisibility(); + void CreateColumnsSelectionWidget(); + +public slots: + void ApplyUserFilter(const QString &); + +private slots: + void EndpointSelected(const QModelIndex&); + +signals: + void EndpointSelected(quint32 Pid); + +private: + + typedef enum{ + Column_Pid, + Column_Protocol, + Column_Name, + Column_Last + }Column_T; + + FilterWidget_C* pFilterWidget; + QTreeView* pEndpoints; + QSortFilterProxyModel* pProxyModel; + QStandardItemModel* pModel; + QList PrivateItemList; + //-- + QGroupBox* pColumnsSelectionWidget; + QCheckBox* CheckBoxArray[Column_Last]; + + QString GetEndpointsWidgetColumnName(Column_T Column); +}; + +#endif// _ENDPOINTS_WIDGET_H_ diff --git a/RpcView/EulaDialog.h b/RpcView/EulaDialog.h new file mode 100644 index 0000000..17d3b44 --- /dev/null +++ b/RpcView/EulaDialog.h @@ -0,0 +1,21 @@ +#ifndef _EULA_DIALOG_H_ +#define _EULA_DIALOG_H_ + +#include "..\Qt\Qt.h" + +//------------------------------------------------------------------------------ +class EulaDialog_C : public QDialog +{ + Q_OBJECT + +public: + EulaDialog_C(); + +private: + QGridLayout* pGridLayout; + QTextEdit* pTextEdit; + QPushButton* pAccept; + QPushButton* pDecline; +}; + +#endif// _EULA_DIALOG_H_ \ No newline at end of file diff --git a/RpcView/FilterWidget.cpp b/RpcView/FilterWidget.cpp new file mode 100644 index 0000000..afcd3c9 --- /dev/null +++ b/RpcView/FilterWidget.cpp @@ -0,0 +1,63 @@ +#include "FilterWidget.h" +#include "RpcViewResource.h" + + +//------------------------------------------------------------------------------ +void FilterWidget_C::Show() +{ + this->show(); + pUserFilter->setFocus(); +} + + +//------------------------------------------------------------------------------ +void FilterWidget_C::Reset() +{ + pUserFilter->clear(); + this->hide(); +} + + +//------------------------------------------------------------------------------ +const QString FilterWidget_C::GetText() +{ + return ( pUserFilter->text() ); +} + + +//------------------------------------------------------------------------------ +void FilterWidget_C::Hide() +{ + this->hide(); +} + + +//------------------------------------------------------------------------------ +FilterWidget_C::FilterWidget_C(QWidget* pParent) +{ + QAction* pFindAction = new QAction(this); + QAction* pEchapAction = new QAction(this); + QLabel* pFilterLabel = new QLabel("Filter: ",this); + + pFindAction->setShortcut(QKeySequence::Find); + pFindAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); + pParent->addAction( pFindAction ); + + pEchapAction->setShortcut(QKeySequence(tr("Esc"))); + pEchapAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); + pParent->addAction( pEchapAction ); + + connect( pFindAction, SIGNAL(triggered(bool)), this, SLOT(Show())); + connect( pEchapAction, SIGNAL(triggered(bool)), this, SLOT(Hide())); + + QGridLayout* pFilterLayout = new QGridLayout(this); + + pUserFilter = new QLineEdit(this); + pMatchingItems = new QLabel(this); + pFilterLayout->addWidget(pFilterLabel, 0, 0); + pFilterLayout->addWidget(pUserFilter,0,1); + this->setLayout(pFilterLayout); + this->Reset(); + + connect( pUserFilter, SIGNAL(textEdited(const QString &)), pParent, SLOT(ApplyUserFilter(const QString &)) ); +} \ No newline at end of file diff --git a/RpcView/FilterWidget.h b/RpcView/FilterWidget.h new file mode 100644 index 0000000..3c1a958 --- /dev/null +++ b/RpcView/FilterWidget.h @@ -0,0 +1,26 @@ +#ifndef _FILTER_WIDGET_H_ +#define _FILTER_WIDGET_H_ + +#include "..\Qt\Qt.h" + +//----------------------------------------------------------------------------- +class FilterWidget_C : public QWidget +{ + Q_OBJECT + +public: + FilterWidget_C(QWidget* pParent); + void Reset(); + const QString GetText(); + +private slots: + void Hide(); + void Show(); + +private: + QLineEdit* pUserFilter; + QLabel* pMatchingItems; +}; + + +#endif //_FILTER_WIDGET_H_ \ No newline at end of file diff --git a/RpcView/IdlHighlighter.cpp b/RpcView/IdlHighlighter.cpp new file mode 100644 index 0000000..6dc5b85 --- /dev/null +++ b/RpcView/IdlHighlighter.cpp @@ -0,0 +1,96 @@ +#include "IdlHighlighter.h" + +// +// REMARK: This code comes from Qt example. +// It should be updated to really comply with the IDL syntax +// + +//------------------------------------------------------------------------------ +IdlHighlighter_C::IdlHighlighter_C(QTextDocument *parent) : QSyntaxHighlighter(parent) +{ + HighlightingRule rule; + + keywordFormat.setForeground(Qt::darkBlue); + keywordFormat.setFontWeight(QFont::Bold); + QStringList keywordPatterns; + keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b" + << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b" + << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b" + << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b" + << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b" + << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b" + << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b" + << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b" + << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b" + << "\\bvoid\\b" << "\\bvolatile\\b"; + foreach (const QString &pattern, keywordPatterns) + { + rule.pattern = QRegExp(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + classFormat.setFontWeight(QFont::Bold); + classFormat.setForeground(Qt::darkMagenta); + rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); + rule.format = classFormat; + highlightingRules.append(rule); + + singleLineCommentFormat.setForeground(Qt::red); + rule.pattern = QRegExp("//[^\n]*"); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); + + multiLineCommentFormat.setForeground(Qt::red); + + quotationFormat.setForeground(Qt::darkGreen); + rule.pattern = QRegExp("\".*\""); + rule.format = quotationFormat; + highlightingRules.append(rule); + + functionFormat.setFontItalic(true); + functionFormat.setForeground(Qt::blue); + rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); + rule.format = functionFormat; + highlightingRules.append(rule); + + commentStartExpression = QRegExp("/\\*"); + commentEndExpression = QRegExp("\\*/"); +} + + +//------------------------------------------------------------------------------ + void IdlHighlighter_C::highlightBlock(const QString &text) + { + foreach (const HighlightingRule &rule, highlightingRules) + { + QRegExp expression(rule.pattern); + int index = expression.indexIn(text); + while (index >= 0) { + int length = expression.matchedLength(); + setFormat(index, length, rule.format); + index = expression.indexIn(text, index + length); + } + } + setCurrentBlockState(0); + + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = commentStartExpression.indexIn(text); + + while (startIndex >= 0) + { + int endIndex = commentEndExpression.indexIn(text, startIndex); + int commentLength; + if (endIndex == -1) + { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } else + { + commentLength = endIndex - startIndex + commentEndExpression.matchedLength(); + } + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); + } + } \ No newline at end of file diff --git a/RpcView/IdlHighlighter.h b/RpcView/IdlHighlighter.h new file mode 100644 index 0000000..94791b9 --- /dev/null +++ b/RpcView/IdlHighlighter.h @@ -0,0 +1,35 @@ +#ifndef _IDL_HIGHLIGHTER_H_ +#define _IDL_HIGHLIGHTER_H_ + +#include "../Qt/Qt.h" + + class IdlHighlighter_C : public QSyntaxHighlighter + { + Q_OBJECT + + public: + IdlHighlighter_C(QTextDocument *parent = 0); + + protected: + void highlightBlock(const QString &text); + + private: + struct HighlightingRule + { + QRegExp pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QRegExp commentStartExpression; + QRegExp commentEndExpression; + + QTextCharFormat keywordFormat; + QTextCharFormat classFormat; + QTextCharFormat singleLineCommentFormat; + QTextCharFormat multiLineCommentFormat; + QTextCharFormat quotationFormat; + QTextCharFormat functionFormat; + }; + +#endif //_IDL_HIGHLIGHTER_H_ \ No newline at end of file diff --git a/RpcView/InitViewsVisitor.cpp b/RpcView/InitViewsVisitor.cpp new file mode 100644 index 0000000..80b47d6 --- /dev/null +++ b/RpcView/InitViewsVisitor.cpp @@ -0,0 +1,181 @@ +#include "InitViewsVisitor.h" +#include "EndpointsWidget.h" +#include "InterfacesWidget.h" +#include "InterfaceInfoWidget.h" +#include "ProcessWidget.h" +#include "ProcessInfoWidget.h" +#include "ProceduresWidget.h" +#include "../RpcCommon/Misc.h" + + +typedef struct _EnumCtxt_T{ + InitViewsVisitor_C* pInitViewsVisitor; + EndpointsWidget_C* pEndpointsWidget; + InterfacesWidget_C* pInterfacesWidget; +}EnumCtxt_T; + + +//------------------------------------------------------------------------------ +static BOOL WINAPI EnumProc(DWORD Pid, DWORD Ppid, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + ProcessEntry_C* pProcessEntry = new ProcessEntry_C(Ppid,Pid); + + pEnumCtxt->pInitViewsVisitor->ProcessVector.push_back(pProcessEntry); + return (TRUE); +} + + +//------------------------------------------------------------------------------ +InitViewsVisitor_C::InitViewsVisitor_C(RpcCore_T* pRpcCore,void** ppRpcCoreCtxt) +{ + EnumCtxt_T EnumCtxt; + + this->pRpcCore= pRpcCore; + + this->NbOfInterfaces = 0; + this->pRpcCoreCtxt = pRpcCore->RpcCoreInitFn(); + if (this->pRpcCoreCtxt==NULL) goto End; + *ppRpcCoreCtxt = this->pRpcCoreCtxt; + + EnumCtxt.pInitViewsVisitor = this; + EnumProcess( (EnumProcessCallbackFn_T)&EnumProc, &EnumCtxt ); +End: + ; +} + + +//------------------------------------------------------------------------------ +InitViewsVisitor_C::~InitViewsVisitor_C() +{ + for (UINT32 i = 0; i < ProcessVector.size(); i++) + { + delete ProcessVector[i]; + } + ProcessVector.clear(); +} + + +//------------------------------------------------------------------------------ +static BOOL __fastcall EnumEndpoints(DWORD Pid, RpcEndpointInfo_T* pRpcEndpointInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + UNREFERENCED_PARAMETER(pbContinue); + + pEnumCtxt->pEndpointsWidget->AddEndpoint(Pid, pRpcEndpointInfo ); + return (TRUE); +} + + +//------------------------------------------------------------------------------ +void InitViewsVisitor_C::Visit(EndpointsWidget_C* pEndpointsWidget) +{ + EnumCtxt_T EnumCtxt; + std::vector::iterator Iter; + + EnumCtxt.pInitViewsVisitor = this; + EnumCtxt.pEndpointsWidget = pEndpointsWidget; + + for (Iter=ProcessVector.begin();Iter!=ProcessVector.end();Iter++) + { + if (*Iter!=NULL) + { + pRpcCore->RpcCoreEnumProcessEndpointsFn( + pRpcCoreCtxt, + (*Iter)->Pid, + (RpcCoreEnumProcessEndpointsCallbackFn_T) &EnumEndpoints, + &EnumCtxt); + } + } + NbOfEndpoints = pEndpointsWidget->GetEndpoints(); +} + + +//------------------------------------------------------------------------------ +static BOOL __fastcall EnumInterfaces(RpcInterfaceInfo_T* pRpcInterfaceInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + UNREFERENCED_PARAMETER(pbContinue); + + pEnumCtxt->pInterfacesWidget->AddInterfaces(pRpcInterfaceInfo); + return (TRUE); +} + + +//------------------------------------------------------------------------------ +void InitViewsVisitor_C::Visit(InterfacesWidget_C* pInterfacesWidget) +{ + EnumCtxt_T EnumCtxt; + std::vector::iterator Iter; + + EnumCtxt.pInitViewsVisitor = this; + EnumCtxt.pInterfacesWidget = pInterfacesWidget; + for (Iter=ProcessVector.begin();Iter!=ProcessVector.end();Iter++) + { + if (*Iter!=NULL) + { + pRpcCore->RpcCoreEnumProcessInterfacesFn( + pRpcCoreCtxt, + (*Iter)->Pid, + (RpcCoreEnumProcessInterfacesCallbackFn_T) &EnumInterfaces, + &EnumCtxt, + RPC_INTERFACE_INFO_ALL); + } + } +} + + +//------------------------------------------------------------------------------ +void InitViewsVisitor_C::Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget) +{ + //nothing to do here +} + + +//------------------------------------------------------------------------------ +void InitViewsVisitor_C::Visit(ProcessInfoWidget_C* pProcessInfoWidget) +{ + //nothing to do here +} + + +//------------------------------------------------------------------------------ +void InitViewsVisitor_C::Visit(ProceduresWidget_C* pProceduresWidget) +{ + //nothing to do here +} + + +//------------------------------------------------------------------------------ +void InitViewsVisitor_C::Visit(ProcessWidget_C* pProcessWidget) +{ + std::vector::iterator Iter; + RpcProcessInfo_T* pRpcProcessInfo = NULL; + + for (Iter=ProcessVector.begin();Iter!=ProcessVector.end();Iter++) + { + if (*Iter!=NULL) + { + pRpcProcessInfo = pRpcCore->RpcCoreGetProcessInfoFn(pRpcCoreCtxt,(*Iter)->Pid,(*Iter)->Ppid,RPC_PROCESS_INFO_ALL); + if (pRpcProcessInfo!=NULL) + { + pProcessWidget->AddProcess(pRpcProcessInfo); + this->NbOfInterfaces+=pRpcProcessInfo->InterfacesCount; + pRpcCore->RpcCoreFreeProcessInfoFn(pRpcCoreCtxt,pRpcProcessInfo); + } + } + } + pProcessWidget->resizeColumnsToContents(); + NbOfProcesses=pProcessWidget->GetProcesses(); +} + + +//------------------------------------------------------------------------------ +ULONG InitViewsVisitor_C::GetEndpoints() +{ + return (this->NbOfEndpoints); +} + + +//------------------------------------------------------------------------------ +ULONG InitViewsVisitor_C::GetInterfaces() +{ + return (this->NbOfInterfaces); +} \ No newline at end of file diff --git a/RpcView/InitViewsVisitor.h b/RpcView/InitViewsVisitor.h new file mode 100644 index 0000000..8114d63 --- /dev/null +++ b/RpcView/InitViewsVisitor.h @@ -0,0 +1,36 @@ +#ifndef _INIT_VIEWS_VISITOR_H_ +#define _INIT_VIEWS_VISITOR_H_ + +#include "ViewVisitor.h" +#include "..\RpcCore\RpcCore.h" +#include "ProcessEntry.h" +#include + + +//------------------------------------------------------------------------------ +class InitViewsVisitor_C : public ViewVisitor_C +{ +private: + RpcCore_T* pRpcCore; + VOID* pRpcCoreCtxt; + ULONG NbOfEndpoints; + ULONG NbOfProcesses; + ULONG NbOfInterfaces; + +public: + ULONG GetEndpoints(); + ULONG GetInterfaces(); +public: + std::vector ProcessVector; + + InitViewsVisitor_C(RpcCore_T* pRpcCore,void** ppRpcCoreCtxt); + ~InitViewsVisitor_C(); + virtual void Visit(EndpointsWidget_C* pEndpointsWidget); + virtual void Visit(InterfacesWidget_C* pInterfacesWidget); + virtual void Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget); + virtual void Visit(ProcessInfoWidget_C* pProcessInfoWidget); + virtual void Visit(ProceduresWidget_C* pProceduresWidget); + virtual void Visit(ProcessWidget_C* pProcessWidget); +}; + +#endif \ No newline at end of file diff --git a/RpcView/InterfaceInfoWidget.cpp b/RpcView/InterfaceInfoWidget.cpp new file mode 100644 index 0000000..63d2392 --- /dev/null +++ b/RpcView/InterfaceInfoWidget.cpp @@ -0,0 +1,309 @@ +#include "InterfaceInfoWidget.h" +#include "..\RpcCommon\RpcCommon.h" + +//------------------------------------------------------------------------------ +extern QString GetInterfaceFlagsString(quint32 Flags); + +static const char WidgetName[] = "Interface Properties"; + +//------------------------------------------------------------------------------ +QString GetInterfaceNdrFlagsString(quint32 Flags) +{ + QString FlagsString; + + if (Flags & RPCFLG_HAS_MULTI_SYNTAXES) FlagsString.append("RPCFLG_HAS_MULTI_SYNTAXES\n"); + if (Flags & RPCFLG_HAS_CALLBACK) FlagsString.append("RPCFLG_HAS_CALLBACK\n"); + if (Flags & RPC_INTERFACE_HAS_PIPES) FlagsString.append("RPC_INTERFACE_HAS_PIPES\n"); + return (FlagsString); +} + + +//------------------------------------------------------------------------------ +void InterfaceInfoWidget_C::Reset() +{ + pTabWidget->setTabEnabled(pTabWidget->indexOf(pMainWidget),false); + pTabWidget->setTabEnabled(pTabWidget->indexOf(pRpcWidget),false); + pTabWidget->setTabEnabled(pTabWidget->indexOf(pNdrWidget),false); +} + + +//------------------------------------------------------------------------------ +UINT InterfaceInfoWidget_C::GetPid() +{ + return (this->Pid); +} + + +//------------------------------------------------------------------------------ +void InterfaceInfoWidget_C::UpdateInterfaceInfo(RpcInterfaceInfo_T* pRpcInterfaceInfo, WCHAR* pIfCallbackName) +{ + WCHAR* pUuidString = NULL; + WCHAR* pTransfertSyntaxString = NULL; + bool bEnable; + + if (pRpcInterfaceInfo==NULL) goto End; + this->Pid = pRpcInterfaceInfo->Pid; + + if ( UuidToStringW(&pRpcInterfaceInfo->If.Uuid,(RPC_WSTR*)&pUuidString)!=RPC_S_OK ) goto End; + if ( UuidToStringW(&pRpcInterfaceInfo->TransfertSyntax.SyntaxGUID,(RPC_WSTR*)&pTransfertSyntaxString)!=RPC_S_OK ) goto End; + + pTabWidget->setTabEnabled(pTabWidget->indexOf(pMainWidget),true); + pUuid->setText( QString::fromUtf16((const ushort*)pUuidString) ); + // + // Only Rpc interfaces have versions + // + if (pRpcInterfaceInfo->IfType==IfType_RPC) + { + pVersion->setText( QString("%1.%2").arg(pRpcInterfaceInfo->If.VersMajor).arg(pRpcInterfaceInfo->If.VersMinor) ); + } + else + { + pVersion->clear(); + } + pName->setText( QString::fromUtf16((const ushort*)pRpcInterfaceInfo->Name) ); + + if (pRpcInterfaceInfo->IfType!=IfType_RPC) + { + pTabWidget->setTabEnabled(pTabWidget->indexOf(pRpcWidget),false); + } + else + { + pTabWidget->setTabEnabled(pTabWidget->indexOf(pRpcWidget),true); + } + + if ( (pIfCallbackName==NULL) || (*pIfCallbackName==0) ) bEnable=false; + else bEnable=true; + pCallbackName->setEnabled(bEnable); + pCallbackName->setText( QString::fromUtf16((const ushort*)pIfCallbackName) ); + + if (pRpcInterfaceInfo->TypeOfStub==TypeOfStub_TypeLib) + { + pTabWidget->setTabEnabled(pTabWidget->indexOf(pNdrWidget),false); + } + else + { + pTabWidget->setTabEnabled(pTabWidget->indexOf(pNdrWidget),true); + } + + if (pRpcInterfaceInfo->NumberOfProcedures==INVALID_PROC_COUNT) pProcCount->setText( "Unknown" ); + else pProcCount->setText( QString("%1").arg(pRpcInterfaceInfo->NumberOfProcedures) ); + + switch(pRpcInterfaceInfo->TypeOfStub) + { + case TypeOfStub_Interpreted:pStub->setText("Interpreted"); break; + case TypeOfStub_Inlined: pStub->setText("Inlined"); break; + case TypeOfStub_TypeLib: pStub->setText("TypeLib"); break; + case TypeOfStub_Hybrid: pStub->setText("Hybrid"); break; + default: pStub->setText("Unknown"); break; + } + + if (pRpcInterfaceInfo->Location[0]==0) bEnable=false; + else bEnable=true; + pLocation->setEnabled(bEnable); + pLocation->setText( QString::fromUtf16((const ushort*)pRpcInterfaceInfo->Location) ); + pLocation->setCursorPosition(0); + + Base = (quintptr)pRpcInterfaceInfo->pLocationBase; + IfCallback = (quintptr)pRpcInterfaceInfo->IfCallbackFn; + TypeFormatString = (quintptr)pRpcInterfaceInfo->pTypeFormatString; + ProcFormatString = (quintptr)pRpcInterfaceInfo->pProcFormatString; + ExpressionEvaluation = (quintptr)pRpcInterfaceInfo->apfnExprEval; + + pBase->setText(QString("0x%1").arg(Base, HEX_SIZE_OF_PTR, 16, QLatin1Char('0'))); + SetAddressRepresentation(this->AddressRepresentation); + // + // Even if Location state is actually a mask, we consider it as 2 separte values + // + if (pRpcInterfaceInfo->LocationState == MEM_FREE) pState->setText("MEM_FREE"); + else if (pRpcInterfaceInfo->LocationState == MEM_COMMIT) pState->setText("MEM_COMMIT"); + + if (pRpcInterfaceInfo->Annotation[0]==0) bEnable=false; + else bEnable=true; + + pAnnotation->setEnabled(bEnable); + pAnnotation->setText( QString::fromLatin1((const char*)pRpcInterfaceInfo->Annotation) ); + pAnnotation->setCursorPosition(0); + + if (!pRpcInterfaceInfo->bIsRegistered) + { + pEpMapper->setEnabled(false); + pEpMapper->setText( "" ); + } + else + { + pEpMapper->setEnabled(true); + pEpMapper->setText( "Registered" ); + } + + pTransfertSyntax->setText( QString::fromUtf16((const ushort*)pTransfertSyntaxString).append(" V%1.%2").arg(pRpcInterfaceInfo->TransfertSyntax.SyntaxVersion.MajorVersion).arg(pRpcInterfaceInfo->TransfertSyntax.SyntaxVersion.MinorVersion) ); + pNdrVersion->setText( QString("0x%1").arg(pRpcInterfaceInfo->NdrInfo.Version,0,16) ); + pMidlVersion->setText( QString("0x%1").arg(pRpcInterfaceInfo->NdrInfo.MIDLVersion,0,16) ); + pNdrFlags->setText( GetInterfaceNdrFlagsString(pRpcInterfaceInfo->NdrInfo.mFlags) ); + + if (pRpcInterfaceInfo->Flags==0) bEnable=false; + else bEnable=true; + + pFlags->setEnabled(bEnable); + pFlags->setText( GetInterfaceFlagsString(pRpcInterfaceInfo->Flags) ); + + if (pRpcInterfaceInfo->Description[0]==0) bEnable=false; + else bEnable=true; + + pDescription->setEnabled(bEnable); + pDescription->setText( QString::fromUtf16((const ushort*)pRpcInterfaceInfo->Description) ); +End: + if (pUuidString!=NULL) RpcStringFreeW((RPC_WSTR*)&pUuidString); + if (pTransfertSyntaxString!=NULL) RpcStringFreeW((RPC_WSTR*)&pTransfertSyntaxString); + return; +} + +//------------------------------------------------------------------------------ +void InterfaceInfoWidget_C::SetAddressRepresentation(AddressRepresentation_T AddressRepresentation) +{ + this->AddressRepresentation = AddressRepresentation; + + pCallbackAddress->setText(""); + pTypeFormatString->setText(""); + pProcFormatString->setText(""); + pExpressionEvaluation->setText(""); + switch (AddressRepresentation) + { + case AddressRepresentation_RVA: + if ((IfCallback != 0) && (IfCallback!=INVALID_IF_CALLBACK_ADDRESS)) pCallbackAddress->setText(QString("+0x%1").arg(IfCallback - Base, 8, 16, QLatin1Char('0'))); + if (TypeFormatString != 0) pTypeFormatString->setText(QString("+0x%1").arg(TypeFormatString - Base, 8, 16, QLatin1Char('0'))); + if (ProcFormatString != 0) pProcFormatString->setText(QString("+0x%1").arg(ProcFormatString - Base, 8, 16, QLatin1Char('0'))); + if (ExpressionEvaluation != 0) pExpressionEvaluation->setText(QString("+0x%1").arg(ExpressionEvaluation - Base, 8, 16, QLatin1Char('0'))); + break; + //-- + case AddressRepresentation_Absolute: + if ((IfCallback != 0) && (IfCallback != INVALID_IF_CALLBACK_ADDRESS))pCallbackAddress->setText(QString("0x%1").arg(IfCallback, HEX_SIZE_OF_PTR, 16, QLatin1Char('0'))); + if (TypeFormatString != 0) pTypeFormatString->setText(QString("0x%1").arg(TypeFormatString, HEX_SIZE_OF_PTR, 16, QLatin1Char('0'))); + if (ProcFormatString != 0) pProcFormatString->setText(QString("0x%1").arg(ProcFormatString, HEX_SIZE_OF_PTR, 16, QLatin1Char('0'))); + if (ExpressionEvaluation != 0) pExpressionEvaluation->setText(QString("0x%1").arg(ExpressionEvaluation, HEX_SIZE_OF_PTR, 16, QLatin1Char('0'))); + break; + //-- + default: + break; + } +} + + +//------------------------------------------------------------------------------ +void InterfaceInfoWidget_C::AcceptVisitor(ViewVisitor_C* pVisitor) +{ + pVisitor->Visit(this); +} + + +//------------------------------------------------------------------------------ +InterfaceInfoWidget_C::InterfaceInfoWidget_C(QWidget* pParent):QDockWidget(WidgetName) +{ + this->Pid = 0; + + setObjectName(WidgetName); + + pTabWidget = new QTabWidget(this); + pTabWidget->setMovable(true); + setWidget(pTabWidget); + // + // Creates the main properties tab + // + pMainWidget = new QWidget(this); + QFormLayout* pMainLayout = new QFormLayout; + + pUuid = new QLineEdit(this); + pVersion = new QLabel(this); + pName = new QLineEdit(this); + pLocation = new QLineEdit(this); + pBase = new QLabel(this); + pState = new QLabel(this); + pStub = new QLabel(this); + pProcCount = new QLabel("0",this); + pDescription = new QTextEdit(this); + + pUuid->setReadOnly(true); + pName->setReadOnly(true); + pLocation->setEnabled(false); + pLocation->setReadOnly(true); + pDescription->setReadOnly(true); + pDescription->setMinimumHeight(20); + + pMainLayout->addRow("Uuid:", pUuid); + pMainLayout->addRow("Version:", pVersion); + pMainLayout->addRow("Name:", pName); + pMainLayout->addRow("Location:", pLocation); + pMainLayout->addRow("Base:", pBase); + pMainLayout->addRow("State:", pState); + pMainLayout->addRow("Stub:", pStub); + pMainLayout->addRow("Procedures:", pProcCount); + pMainLayout->addRow("Description:", pDescription); + + pMainWidget->setLayout(pMainLayout); + pTabWidget->addTab(pMainWidget,"Main"); + // + // Creates the RPC tab + // + pRpcWidget = new QWidget(this); + QFormLayout* pRpcLayout = new QFormLayout; + + pCallbackName = new QLineEdit(this); + pCallbackAddress= new QLineEdit(this); + pEpMapper = new QLabel(this); + pFlags = new QTextEdit(this); + pAnnotation = new QLineEdit(this); + + pFlags->setReadOnly(true); + pFlags->setMinimumHeight(20); + pCallbackName->setReadOnly(true); + pCallbackAddress->setReadOnly(true); + pAnnotation->setEnabled(false); + pAnnotation->setReadOnly(true); + + pRpcLayout->addRow("Callback Name:", pCallbackName); + pRpcLayout->addRow("Callback Addr:", pCallbackAddress); + pRpcLayout->addRow("EpMapper:", pEpMapper); + pRpcLayout->addRow("Annotation:", pAnnotation); + pRpcLayout->addRow("Flags:", pFlags); + + pRpcWidget->setLayout(pRpcLayout); + pTabWidget->addTab(pRpcWidget,"RPC"); + // + // Creates the NDR tab + // + pNdrWidget = new QWidget(this); + QFormLayout* pNdrLayout = new QFormLayout; + + pTransfertSyntax = new QLineEdit(this); + pNdrVersion = new QLabel("0",this); + pMidlVersion = new QLabel("0",this); + pNdrFlags = new QTextEdit(this); + pTypeFormatString = new QLineEdit(this); + pProcFormatString = new QLineEdit(this); + pExpressionEvaluation = new QLineEdit(this); + + pTransfertSyntax->setReadOnly(true); + pNdrFlags->setReadOnly(true); + pNdrFlags->setMinimumHeight(20); + pTypeFormatString->setReadOnly(true); + pProcFormatString->setReadOnly(true); + pExpressionEvaluation->setReadOnly(true); + + pNdrLayout->addRow("Syntax:", pTransfertSyntax); + pNdrLayout->addRow("NDR Version:", pNdrVersion); + pNdrLayout->addRow("MIDL Version:", pMidlVersion); + pNdrLayout->addRow("NDR Flags:", pNdrFlags); + pNdrLayout->addRow("TypeFormatString:", pTypeFormatString); + pNdrLayout->addRow("ProcFormatString:", pProcFormatString); + pNdrLayout->addRow("ExpressionEvaluation:", pExpressionEvaluation); + + pNdrWidget->setLayout(pNdrLayout); + pTabWidget->addTab(pNdrWidget, "NDR"); + // + // By default: all tabs are disable + // + pTabWidget->setTabEnabled(pTabWidget->indexOf(pMainWidget),false); + pTabWidget->setTabEnabled(pTabWidget->indexOf(pRpcWidget),false); + pTabWidget->setTabEnabled(pTabWidget->indexOf(pNdrWidget),false); + // + this->AddressRepresentation = AddressRepresentation_Absolute; +} \ No newline at end of file diff --git a/RpcView/InterfaceInfoWidget.h b/RpcView/InterfaceInfoWidget.h new file mode 100644 index 0000000..3ccf33e --- /dev/null +++ b/RpcView/InterfaceInfoWidget.h @@ -0,0 +1,61 @@ +#ifndef _INTERFACE_INFO_WIDGET_H_ +#define _INTERFACE_INFO_WIDGET_H_ + +#include "..\Qt\Qt.h" +#include "..\RpcCore\RpcCore.h" +#include "..\RpcCommon\RpcCommon.h" +#include "View.h" + +//------------------------------------------------------------------------------ +class InterfaceInfoWidget_C : public QDockWidget, public View_I +{ + Q_OBJECT + +public: + InterfaceInfoWidget_C(QWidget* pParent); + virtual void AcceptVisitor(ViewVisitor_C* pVisitor); + + UINT GetPid(); + void Reset(); + void UpdateInterfaceInfo(RpcInterfaceInfo_T* pRpcInterfaceInfo, WCHAR* pCallbackName); + void SetAddressRepresentation(AddressRepresentation_T AddressRepresentation); +private: + UINT Pid; + AddressRepresentation_T AddressRepresentation; + quintptr Base; + quintptr IfCallback; + quintptr TypeFormatString; + quintptr ProcFormatString; + quintptr ExpressionEvaluation; + //Global + QTabWidget* pTabWidget; + //Main + QWidget* pMainWidget; + QLineEdit* pUuid; + QLabel* pVersion; + QLineEdit* pName; + QLineEdit* pLocation; + QLabel* pBase; + QLabel* pState; + QLabel* pStub; + QLabel* pProcCount; + QTextEdit* pDescription; + //RPC + QWidget* pRpcWidget; + QLineEdit* pCallbackName; + QLineEdit* pCallbackAddress; + QLabel* pEpMapper; + QLineEdit* pAnnotation; + QTextEdit* pFlags; + //NDR + QWidget* pNdrWidget; + QLineEdit* pTransfertSyntax; + QLabel* pNdrVersion; + QLabel* pMidlVersion; + QTextEdit* pNdrFlags; + QLineEdit* pTypeFormatString; + QLineEdit* pProcFormatString; + QLineEdit* pExpressionEvaluation; +}; + +#endif// _INTERFACE_INFO_WIDGET_H_ diff --git a/RpcView/InterfaceSelectedVisitor.cpp b/RpcView/InterfaceSelectedVisitor.cpp new file mode 100644 index 0000000..04b945e --- /dev/null +++ b/RpcView/InterfaceSelectedVisitor.cpp @@ -0,0 +1,185 @@ +#include "InterfaceSelectedVisitor.h" +#include "EndpointsWidget.h" +#include "InterfacesWidget.h" +#include "InterfaceInfoWidget.h" +#include "ProcessWidget.h" +#include "ProcessInfoWidget.h" +#include "ProceduresWidget.h" +#include "../RpcCommon/Misc.h" +#include "Pdb.h" +#include + +//------------------------------------------------------------------------------ +InterfaceSelectedVisitor_C::InterfaceSelectedVisitor_C(quint32 Pid, RPC_IF_ID* pIf,RpcCore_T* pRpcCore,void* pRpcCoreCtxt) +{ + this->Pid = Pid; + this->pIf = pIf; + this->pRpcCore = pRpcCore; + this->pRpcCoreCtxt = pRpcCoreCtxt; + + this->pRpcInterfaceInfo = pRpcCore->RpcCoreGetInterfaceInfoFn( pRpcCoreCtxt, Pid, pIf, RPC_INTERFACE_INFO_ALL ); +} + + +//------------------------------------------------------------------------------ +InterfaceSelectedVisitor_C::~InterfaceSelectedVisitor_C() +{ + if (pRpcInterfaceInfo != NULL) + { + pRpcCore->RpcCoreFreeInterfaceInfoFn(pRpcCoreCtxt, pRpcInterfaceInfo); + } +} + + +//------------------------------------------------------------------------------ +void InterfaceSelectedVisitor_C::Visit(EndpointsWidget_C* pEndpointsWidget) +{ + pEndpointsWidget->ApplyProcessFilter(this->Pid); + pEndpointsWidget->resizeColumnsToContents(); +} + + +//------------------------------------------------------------------------------ +void InterfaceSelectedVisitor_C::Visit(InterfacesWidget_C* pInterfacesWidget) +{ + //nothing todo +} + +//------------------------------------------------------------------------------ +void InterfaceSelectedVisitor_C::Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget) +{ + HANDLE hProcess = NULL; + WCHAR SymbolName[RPC_MAX_LENGTH]; + void* hPdb; + + if (pRpcInterfaceInfo==NULL) goto End; + // + // Get the callback name + // + SymbolName[0]=0; + if (pRpcInterfaceInfo->pLocationBase!=NULL) + { + hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,Pid); + if (hProcess==NULL) goto End; + + hPdb = PdbInit(hProcess, pRpcInterfaceInfo->pLocationBase, pRpcInterfaceInfo->LocationSize); + if (hPdb!=NULL) + { + PdbGetSymbolName(hPdb,pRpcInterfaceInfo->IfCallbackFn, SymbolName, sizeof(SymbolName)); + PdbUninit(hPdb); + } + } + // + // Update the view + // + pInterfaceInfoWidget->UpdateInterfaceInfo( pRpcInterfaceInfo, SymbolName ); +End: + if (hProcess!=NULL) CloseHandle(hProcess); + return; +} + + +typedef struct _EnumCtxt_T{ + ProcessInfoWidget_C* pProcessInfoWidget; +}EnumCtxt_T; + + +//------------------------------------------------------------------------------ +static BOOL __fastcall EnumProcessAuth(DWORD Pid, RpcAuthInfo_T* pRpcAuthInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + UNREFERENCED_PARAMETER(Pid); + UNREFERENCED_PARAMETER(pbContinue); + + pEnumCtxt->pProcessInfoWidget->AddAuthInfo(pRpcAuthInfo); + return (TRUE); +} + + +//------------------------------------------------------------------------------ +void InterfaceSelectedVisitor_C::Visit(ProcessInfoWidget_C* pProcessInfoWidget) +{ + RpcProcessInfo_T* pRpcProcessInfo; + EnumCtxt_T EnumCtxt; + + EnumCtxt.pProcessInfoWidget = pProcessInfoWidget; + pProcessInfoWidget->reset(); + pRpcProcessInfo = pRpcCore->RpcCoreGetProcessInfoFn( pRpcCoreCtxt, Pid, 0, RPC_PROCESS_INFO_ALL ); + if (pRpcProcessInfo!=NULL) + { + pProcessInfoWidget->UpdateProcessInfo(pRpcProcessInfo); + pRpcCore->RpcCoreFreeProcessInfoFn( pRpcCoreCtxt, pRpcProcessInfo ); + pRpcCore->RpcCoreEnumProcessAuthInfoFn( pRpcCoreCtxt, Pid, (RpcCoreEnumProcessAuthInfoCallbackFn_T)EnumProcessAuth,&EnumCtxt); + } +} + +//------------------------------------------------------------------------------ +void InterfaceSelectedVisitor_C::Visit(ProceduresWidget_C* pProceduresWidget) +{ + HANDLE hProcess = NULL; + WCHAR SymbolName[RPC_MAX_LENGTH]; + ULONG ProcIdx; + VOID* ProcFormat = NULL; + LPCWSTR pProcName = NULL; + VOID* hPdb = NULL; + UCHAR* ProcAddress = NULL; + + if (pRpcInterfaceInfo==NULL) goto End; + pProceduresWidget->reset(pRpcInterfaceInfo->Pid); + + switch(pRpcInterfaceInfo->IfType) + { + // + // Get proc names from pdb files if present + // + case IfType_RPC: + if (pRpcInterfaceInfo->pLocationBase==NULL) goto End; + + hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,Pid); + if (hProcess==NULL) goto End; + + hPdb = PdbInit(hProcess, pRpcInterfaceInfo->pLocationBase, pRpcInterfaceInfo->LocationSize); + for(ProcIdx=0;ProcIdxNumberOfProcedures;ProcIdx++) + { + if (pRpcInterfaceInfo->ppProcAddressTable!=NULL) + { + SymbolName[0]=0; + if (hPdb!=NULL) + { + PdbGetSymbolName(hPdb, (UCHAR*)pRpcInterfaceInfo->pLocationBase + pRpcInterfaceInfo->ppProcAddressTable[ProcIdx], SymbolName, sizeof(SymbolName)); + } + if ( (pRpcInterfaceInfo->pFormatStringOffsetTable==NULL)|| + (pRpcInterfaceInfo->pProcFormatString==NULL)) + { + ProcFormat=NULL; + } + else + { + ProcFormat=pRpcInterfaceInfo->pProcFormatString + pRpcInterfaceInfo->pFormatStringOffsetTable[ProcIdx]; + } + pProceduresWidget->AddProcedure( + ProcIdx, + SymbolName, + pRpcInterfaceInfo->pLocationBase, + pRpcInterfaceInfo->ppProcAddressTable[ProcIdx], + ProcFormat + ); + } + } + PdbUninit(hPdb); + + break; + + default: + break; + } + pProceduresWidget->resizeColumnsToContents(); +End: + if (hProcess!=NULL) CloseHandle(hProcess); + return; +} + +//------------------------------------------------------------------------------ +void InterfaceSelectedVisitor_C::Visit(ProcessWidget_C* pProcessWidget) +{ + pProcessWidget->SelectProcess(Pid); +} \ No newline at end of file diff --git a/RpcView/InterfaceSelectedVisitor.h b/RpcView/InterfaceSelectedVisitor.h new file mode 100644 index 0000000..0092576 --- /dev/null +++ b/RpcView/InterfaceSelectedVisitor.h @@ -0,0 +1,28 @@ +#ifndef _INTERFACE_SELECTED_VISITOR_H_ +#define _INTERFACE_SELECTED_VISITOR_H_ + +#include "../Qt/Qt.h" +#include "ViewVisitor.h" +#include "..\RpcCore\RpcCore.h" + +//------------------------------------------------------------------------------ +class InterfaceSelectedVisitor_C : public ViewVisitor_C +{ +private: + quint32 Pid; + RPC_IF_ID* pIf; + RpcCore_T* pRpcCore; + VOID* pRpcCoreCtxt; + RpcInterfaceInfo_T* pRpcInterfaceInfo; +public: + InterfaceSelectedVisitor_C(quint32 Pid, RPC_IF_ID* pIf,RpcCore_T* pRpcCore,void* pRpcCoreCtxt); + ~InterfaceSelectedVisitor_C(); + virtual void Visit(EndpointsWidget_C* pEndpointsWidget); + virtual void Visit(InterfacesWidget_C* pInterfacesWidget); + virtual void Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget); + virtual void Visit(ProcessInfoWidget_C* pProcessInfoWidget); + virtual void Visit(ProceduresWidget_C* pProceduresWidget); + virtual void Visit(ProcessWidget_C* pProcessWidget); +}; + +#endif \ No newline at end of file diff --git a/RpcView/InterfacesWidget.cpp b/RpcView/InterfacesWidget.cpp new file mode 100644 index 0000000..c084c3f --- /dev/null +++ b/RpcView/InterfacesWidget.cpp @@ -0,0 +1,489 @@ +#include +#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; + RPC_IF_ID RpcIfId; + UCHAR* pUuidStringA; + + QString& PidString = pProxyModel->data( pProxyModel->index(Index.row(), Column_Pid) ).toString(); + pUuidStringA = (UCHAR*)pProxyModel->data( pProxyModel->index(Index.row(), Column_Uuid) ).toString().toLatin1().data(); + QString& VersionString = pProxyModel->data( pProxyModel->index(Index.row(), Column_Version) ).toString(); + VersionStringList = VersionString.split(".", QString::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 ItemList; + UCHAR* pUuidString = NULL; + bool bResult = false; + + if ( UuidToStringA(&pIfId->Uuid,&pUuidString)!=RPC_S_OK ) goto End; + + ItemList = pModel->findItems(QString::fromAscii((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;isetData(pModel->index(Index,i), QBrush(Color), Qt::BackgroundRole); + } +} + + +//------------------------------------------------------------------------------ +bool InterfacesWidget_C::AddInterfaces(RpcInterfaceInfo_T* pRpcInterfaceInfo) +{ + int Index; + QString PidString; + WCHAR* pUuidString = NULL; + WCHAR* pTransfertSyntaxString = 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::fromAscii("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 AddressRepresentation) +{ + switch (AddressRepresentation) + { + 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;isetHeaderData(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; +} \ No newline at end of file diff --git a/RpcView/InterfacesWidget.h b/RpcView/InterfacesWidget.h new file mode 100644 index 0000000..617d650 --- /dev/null +++ b/RpcView/InterfacesWidget.h @@ -0,0 +1,86 @@ +#ifndef _INTERFACES_WIDGET_H_ +#define _INTERFACES_WIDGET_H_ + +#include "..\Qt\Qt.h" +#include "..\RpcCore\RpcCore.h" +#include "FilterWidget.h" +#include "View.h" +#include "..\RpcCommon\RpcCommon.h" + + +//------------------------------------------------------------------------------ +class InterfacesWidget_C : public QDockWidget, public View_I +{ + Q_OBJECT + +public: + + typedef enum{ + Column_Pid, + Column_Uuid, + Column_Version, + Column_IfType, + Column_NumberOfProcedures, + Column_HasMarshallingInfo, + Column_IfCallbackFn, + Column_Name, + Column_Base, + Column_Location, + Column_Flags, + Column_Description, + Column_IsRegistered, + Column_Annotation, + Column_TransfertSyntax, + Column_Last //Must be the last one + }Column_T; + + InterfacesWidget_C(QWidget* pParent); + virtual void AcceptVisitor(ViewVisitor_C* pVisitor); + ULONG GetInterfaces(); + ULONG GetTotalInterfaces(); + bool IsInterfacePresent(quint32 Pid, RPC_IF_ID* pIfIp); + void RemoveUnregisteredInterfaces(); + void SnapInterfaces(); + void SaveConfiguration(QSettings*); + void LoadConfiguration(QSettings*); + void UpdateUserFilter(); + QWidget* GetColumnsSelectionWidget(); + void UpdateColumnsVisibility(); + void CreateColumnsSelectionWidget(); + + void ApplyProcessFilter(quint32 Pid); + void resizeColumnsToContents(); + bool AddInterfaces(RpcInterfaceInfo_T* pRpcInterfaceInfo); + void SetAddressRepresentation(AddressRepresentation_T AddressRepresentation); + +public slots: + void ApplyUserFilter(const QString &); + +private slots: + void InterfaceSelected(const QModelIndex& Index); + void SetRowColor(int Index,const QColor& Color); + void ShowUserFilter(); + void HideUserFilter(); + +signals: + void InterfaceSelected(quint32 Pid, RPC_IF_ID* pIf); + void SigDecompileInterface(quint32 Pid, RPC_IF_ID* pIf); + +private: + FilterWidget_C* pFilterWidget; + QTreeView* pInterfaces; + QSortFilterProxyModel* pProxyModel; + QStandardItemModel* pModel; + QLineEdit* pUserFilter; + QLabel* pMatchingItems; + QList PrivateItemList; + QGroupBox* pColumnsSelectionWidget; + QCheckBox* ColumnsCheckBoxArray[Column_Last]; + QWidget* pColorSelectionWidget; + QSignalMapper* SignalMapper; + AddressRepresentation_T AddressRepresentation; + + QString GetColumName(Column_T Column); +}; + +#endif// _INTERFACES_WIDGET_H_ diff --git a/RpcView/Main.ico b/RpcView/Main.ico new file mode 100644 index 0000000..78c955a Binary files /dev/null and b/RpcView/Main.ico differ diff --git a/RpcView/MainWindow.cpp b/RpcView/MainWindow.cpp new file mode 100644 index 0000000..52e00ce --- /dev/null +++ b/RpcView/MainWindow.cpp @@ -0,0 +1,803 @@ +#include "MainWindow.h" +#include "RpcViewResource.h" +#include "../RpcCommon/Misc.h" +#include +#include +#include +#include +#include + +#include "ConfigurationVisitor.h" +#include "ProcessSelectedVisitor.h" +#include "EndpointSelectedVisitor.h" +#include "InterfaceSelectedVisitor.h" +#include "InitViewsVisitor.h" +#include "RefreshVisitor.h" + +#define FAST_REFRESH_SPEED 500 +#define NORMAL_REFRESH_SPEED 1000 +#define BELOW_NORMAL_REFRESH_SPEED 2000 +#define SLOW_REFRESH_SPEED 5000 +#define VERY_SLOW_REFRESH_SPEED 10000 +#define SHELL_EXECUTE_SUCCESS ((HINSTANCE)42) // According to the doc, welcome the 16-bit compatibilty + + +extern ULONG NTAPI DecompilerExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers); +extern HMODULE NTAPI LoadDecompilerEngine(RpcDecompilerHelper_T** ppRpcDecompilerHelper); +extern void NTAPI InitDecompilerInfo(_In_ RpcInterfaceInfo_T* pRpcInterfaceInfo, _Out_ RpcDecompilerInfo_T* pRpcDecompilerInfo); +extern void NTAPI UninitDecompilerInfo(RpcDecompilerInfo_T* pRpcDecompilerInfo); + +static const char WidgetName[] = "RpcView"; + +//------------------------------------------------------------------------------ +void MainWindow_C::InterfaceSelected(quint32 Pid, RPC_IF_ID* pIf) +{ + CHAR SymbolPath; + + if (GetEnvironmentVariableA("RpcViewSymbolPath",&SymbolPath,sizeof(SymbolPath))==0) + { + StatusBar.showMessage("Symbol path not configured."); + } + + InterfaceSelectedVisitor_C InterfaceSelectedVisitor( + Pid, + pIf, + pRpcCore, + pRpcCoreCtxt + ); + + this->SendVisitor(InterfaceSelectedVisitor); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::EndpointSelected(quint32 Pid) +{ + EndpointSelectedVisitor_C EndpointSelectedVisitor( + Pid, + pRpcCore, + pRpcCoreCtxt + ); + this->SendVisitor(EndpointSelectedVisitor); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::ProcessSelected(quint32 Pid) +{ + ProcessSelectedVisitor_C ProcessSelectedVisitor( + Pid, + pRpcCore, + pRpcCoreCtxt + ); + this->SendVisitor(ProcessSelectedVisitor); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::InitColumnsDialog() +{ + ColumnsDialog = new QDialog(this); + ColumnsVLayout = new QVBoxLayout(ColumnsDialog); + ColumnsHLayout = new QHBoxLayout(); + ColumnsVLayout1 = new QVBoxLayout(); + ColumnsButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + + pProcessColumns = pProcessWidget->GetColumnsSelectionWidget(); + pEndpointsColumns = pEndpointsWidget->GetColumnsSelectionWidget(); + pInterfacesColumns = pInterfacesWidget->GetColumnsSelectionWidget(); + pProceduresColumns = pProceduresWidget->GetColumnsSelectionWidget(); + + ColumnsHLayout->addWidget(pProcessColumns); + ColumnsVLayout1->addWidget(pEndpointsColumns); + ColumnsVLayout1->addWidget(pProceduresColumns); + ColumnsHLayout->addLayout(ColumnsVLayout1); + ColumnsHLayout->addWidget(pInterfacesColumns); + + ColumnsVLayout->addLayout(ColumnsHLayout); + ColumnsVLayout->addWidget(ColumnsButtonBox); + + connect(ColumnsButtonBox, SIGNAL(rejected()), ColumnsDialog, SLOT(reject())); + connect(ColumnsButtonBox, SIGNAL(accepted()), ColumnsDialog, SLOT(accept())); + connect(ColumnsDialog, SIGNAL(accepted()), this, SLOT(UpdateColumns())); + + ColumnsDialog->setWindowTitle("Select Columns"); + ColumnsDialog->setLayout(ColumnsVLayout); + ColumnsDialog->setMaximumSize(0, 0); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::ShowColumnsDialog() +{ + pProcessColumns = pProcessWidget->GetColumnsSelectionWidget(); + pEndpointsColumns = pEndpointsWidget->GetColumnsSelectionWidget(); + pInterfacesColumns = pInterfacesWidget->GetColumnsSelectionWidget(); + pProceduresColumns = pProceduresWidget->GetColumnsSelectionWidget(); + + ColumnsDialog->exec(); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::UpdateColumns() +{ + ConfigurationVisitor_C ConfigurationVisitor(ConfigurationVisitor_C::UpdateColumns, NULL); + SendVisitor(ConfigurationVisitor); +} + + +//------------------------------------------------------------------------------ +bool MainWindow_C::eventFilter(QObject* pObject, QEvent* pEvent) +{ + if (pEvent->type() == QEvent::ContextMenu) + { + QPoint& position = QCursor::pos(); + // + // Show the context menu associatd to columns + // + QMenu ColumnsMenu; + + QAction* pActionSelectColumns = ColumnsMenu.addAction("Select Columns..."); + QAction* pActionFitAll = ColumnsMenu.addAction("Size All Columns to fit"); + // + QAction* selectedItem = ColumnsMenu.exec(position); + if (selectedItem == pActionFitAll) + { + delete pActionSelectColumns; + static_cast(pObject)->resizeSections(QHeaderView::ResizeToContents); + + } + else if (selectedItem == pActionSelectColumns) + { + delete pActionFitAll; + ShowColumnsDialog(); + } + if (selectedItem != NULL) delete selectedItem; + } + return QWidget::eventFilter(pObject, pEvent); +} + + +//------------------------------------------------------------------------------ +VOID* __fastcall RpcAlloc(SIZE_T Size) +{ + return OS_ALLOC(Size); +} + + +//------------------------------------------------------------------------------ +VOID __fastcall RpcFree(VOID* pMem) +{ + OS_FREE(pMem); +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcGetProcessData(RpcModuleInfo_T* pRpcModuleInfo, RVA_T Rva, VOID* pBuffer, UINT BufferLength) +{ + BOOL bResult = FALSE; + HANDLE hProcess = NULL; + VOID* pAddress = NULL; + + if (pRpcModuleInfo == NULL) goto End; + pAddress = (VOID*)(pRpcModuleInfo->pModuleBase + Rva); + + hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pRpcModuleInfo->Pid); + if (hProcess == NULL) goto End; + bResult = ReadProcessMemory(hProcess, pAddress, pBuffer, BufferLength, NULL); +End: + if (hProcess != NULL) CloseHandle(hProcess); + return (bResult); +} + + +//------------------------------------------------------------------------------ +VOID __cdecl RpcPrint(void* pContext, const char* pTxt) +{ + DecompilationWidget_C* pDecompilationWidget = (DecompilationWidget_C*)pContext; + pDecompilationWidget->InsertText(pTxt); +#ifdef _DEBUG + printf("%s\n", pTxt); +#endif +} + + +//------------------------------------------------------------------------------ +VOID __cdecl RpcDebug(const char* pFunction, ULONG Line, const char* pFormatString, ...) +{ + va_list Arg; + va_start(Arg, pFormatString); + + _vcprintf(pFormatString, Arg); +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall RpcGetInterfaceName(GUID* pUuid, UCHAR* pName, ULONG NameLength) +{ + HKEY hKey = NULL; + ULONG DataLength; + UCHAR SubKeyName[MAX_PATH]; + RPC_CSTR pUuidString = NULL; + BOOL bResult = FALSE; + + if (UuidToStringA(pUuid, &pUuidString) != RPC_S_OK) goto End; + StringCbPrintfA((STRSAFE_LPSTR)SubKeyName, sizeof(SubKeyName), "Interface\\{%s}", pUuidString); + + if (RegOpenKeyExA(HKEY_CLASSES_ROOT, (LPCSTR)SubKeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) goto End; + DataLength = NameLength; + if (RegQueryValueExA(hKey, NULL, NULL, NULL, pName, &DataLength) != ERROR_SUCCESS) goto End; + + bResult = TRUE; +End: + if (hKey != NULL) RegCloseKey(hKey); + if (pUuidString != NULL) RpcStringFreeA(&pUuidString); + return (bResult); +} + + + +//------------------------------------------------------------------------------ +void MainWindow_C::SlotDecompileInterface(quint32 Pid, RPC_IF_ID* pIf) +{ + RpcDecompilerInfo_T RpcDecompilerInfo; + void* pDecompilerCtxt = NULL; + RpcInterfaceInfo_T* pRpcInterfaceInfo = NULL; + RpcDecompilerHelper_T* pRpcDecompilerHelper = NULL; + HMODULE hDecompiler = NULL; + + ZeroMemory(&RpcDecompilerInfo, sizeof(RpcDecompilerInfo)); + // + // Get the decompiler + // + hDecompiler = LoadDecompilerEngine(&pRpcDecompilerHelper); + if (hDecompiler==NULL) goto End; + // + // Get the Interface info + // + pRpcInterfaceInfo = pRpcCore->RpcCoreGetInterfaceInfoFn( pRpcCoreCtxt, Pid, pIf, RPC_INTERFACE_INFO_ALL ); + if (pRpcInterfaceInfo == NULL) goto End; + InitDecompilerInfo(pRpcInterfaceInfo, &RpcDecompilerInfo); + __try{ + RpcViewHelper_T LocalRpcViewHelper = { + this->pDecompilationWidget, + &RpcAlloc, + &RpcFree, + &RpcGetProcessData, + &RpcPrint, + &RpcDebug, + &RpcGetInterfaceName + }; + pDecompilerCtxt = pRpcDecompilerHelper->RpcDecompilerInitFn(&LocalRpcViewHelper, &RpcDecompilerInfo); + if (pDecompilerCtxt!=NULL) + { + pRpcDecompilerHelper->RpcDecompilerPrintAllProceduresFn( pDecompilerCtxt ); + pRpcDecompilerHelper->RpcDecompilerUninitFn(pDecompilerCtxt); + } + }__except( DecompilerExceptionFilter(GetExceptionInformation()) ) + { + //Failure + goto End; + } +End: + UninitDecompilerInfo(&RpcDecompilerInfo); + if (hDecompiler!=NULL) FreeLibrary(hDecompiler); + if (pRpcInterfaceInfo!=NULL) + { + pRpcCore->RpcCoreFreeInterfaceInfoFn(pRpcCoreCtxt,pRpcInterfaceInfo); + } + return; +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::ViewDetailsForAllProcesses() +{ + HINSTANCE hInstance; + UCHAR FilePath[MAX_PATH]; + + GetModuleFileNameA(NULL,(LPSTR)FilePath,_countof(FilePath)); + hInstance = ShellExecuteA(NULL, "runas", (LPCSTR)FilePath, 0, 0, SW_SHOWNORMAL); + if ( hInstance == SHELL_EXECUTE_SUCCESS) + { + Exit(); + } +} + +//------------------------------------------------------------------------------ +void MainWindow_C::About() +{ + Version_T Version; + QString AboutText; + HMODULE hDecompiler; + RpcDecompilerHelper_T* pRpcDecompilerHelper = NULL; + LocationInfo_T LocationInfo; + + AboutText.append("RpcView"); + + if (!GetLocationInfo(GetCurrentProcess(), GetModuleHandle(NULL), &LocationInfo)) goto End; + Version.As64BitsValue = GetModuleVersion(LocationInfo.Location); + + AboutText.append( QString(" v%4.%3.%2.%1\n\n").arg(Version.As16BitsValues.Part1).arg(Version.As16BitsValues.Part2).arg(Version.As16BitsValues.Part3).arg(Version.As16BitsValues.Part4) ); + /* + Version.As64BitsValue = pRpcCoreNativeHelper->RuntimeVersion; + AboutText.append(" - "); + AboutText.append(pRpcCoreNativeHelper->pDescription); + AboutText.append( QString(" for v%4.%3.%2.%1\n").arg(Version.As16BitsValues.Part1).arg(Version.As16BitsValues.Part2).arg(Version.As16BitsValues.Part3).arg(Version.As16BitsValues.Part4) ); + Version.As64BitsValue = pRpcCoreNativeHelper->RuntimeVersion; +#ifdef _WIN64 + Version.As64BitsValue = pRpcCoreWow64Helper->RuntimeVersion; + AboutText.append(" - "); + AboutText.append(pRpcCoreWow64Helper->pDescription); + AboutText.append( QString(" for v%4.%3.%2.%1\n").arg(Version.As16BitsValues.Part1).arg(Version.As16BitsValues.Part2).arg(Version.As16BitsValues.Part3).arg(Version.As16BitsValues.Part4) ); + Version.As64BitsValue = pRpcCoreWow64Helper->RuntimeVersion; +#endif + */ + hDecompiler = LoadDecompilerEngine(&pRpcDecompilerHelper); + if (hDecompiler==NULL) goto End; + + if (!GetLocationInfo(GetCurrentProcess(), hDecompiler, &LocationInfo)) goto End; + Version.As64BitsValue = GetModuleVersion(LocationInfo.Location); + FreeLibrary(hDecompiler); + + AboutText.append(" - Decompiler engine"); + AboutText.append( QString(" v%4.%3.%2.%1\n").arg(Version.As16BitsValues.Part1).arg(Version.As16BitsValues.Part2).arg(Version.As16BitsValues.Part3).arg(Version.As16BitsValues.Part4) ); + +End: + QMessageBox::about( + this, + "About RpcView", + AboutText + ); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::Help() +{ + QMessageBox::information( + this, + "RpcView Help", + "RpcView presents a complete view of RPC interfaces on a system.\n" + "See http://rpcview.org" + ); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SendVisitor(ViewVisitor_C& Visitor) +{ + // + // todo: a vector of elements (maybe a view factory???) + // + pProcessWidget->AcceptVisitor(&Visitor); + pEndpointsWidget->AcceptVisitor(&Visitor); + pInterfacesWidget->AcceptVisitor(&Visitor); + pProceduresWidget->AcceptVisitor(&Visitor); + + pInterfaceInfoWidget->AcceptVisitor(&Visitor); + pProcessInfoWidget->AcceptVisitor(&Visitor); +} + + +//------------------------------------------------------------------------------ + void MainWindow_C::closeEvent(QCloseEvent *event) + { + Exit(); + } + + + //------------------------------------------------------------------------------ +void MainWindow_C::Exit() +{ + pSettings->setValue("MainWindow/windowState", saveState()); + pSettings->setValue("MainWindow/geometry", saveGeometry()); + pSettings->setValue("RefreshSpeed", this->RefreshSpeedInMs); + pSettings->setValue("AddressRepresentation", this->AddressRepresentation); + + ConfigurationVisitor_C ConfigurationVisitor(ConfigurationVisitor_C::Save, pSettings); + SendVisitor(ConfigurationVisitor); + // + // Uninit the RpcCore + // + pRpcCore->RpcCoreUninitFn(pRpcCoreCtxt); + delete this; +#ifdef _DEBUG + _CrtDumpMemoryLeaks(); +#endif + ExitProcess(EXIT_SUCCESS); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::RefreshViews() +{ + RefreshVisitor_C RefreshVisitor( + pRpcCore, + pRpcCoreCtxt + ); + + SendVisitor(RefreshVisitor); + + pEndpointsCountLabel->setText( QString("Endpoints: %1/%2").arg(RefreshVisitor.GetEndpoints()).arg(RefreshVisitor.GetTotalEndpoints()) ); + pProcessesCountLabel->setText( QString("Processes: %1/%2").arg(RefreshVisitor.GetProcesses()).arg(RefreshVisitor.GetTotalProcesses()) ); + pInterfacesCountLabel->setText( QString("Interfaces: %1/%2").arg(RefreshVisitor.GetInterfaces()).arg(RefreshVisitor.GetTotalInterfaces()) ); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::ConfigureSymbols() +{ + bool bOk; + QString Txt; + QString CurrentSymbolsPath; + QString NewSymbolsPath; + + CurrentSymbolsPath = pSettings->value("SymbolsPath").toString(); + + NewSymbolsPath = QInputDialog::getText( + this, + "Configure Symbols", + "RpcView uses symbols to resolve function names when displaying RPC procedures names.\n\nIf you do not require that information you do not need to configure symbols", + QLineEdit::Normal, + CurrentSymbolsPath, + &bOk + ); + if ( bOk && !NewSymbolsPath.isEmpty() ) + { + pSettings->setValue("SymbolsPath",NewSymbolsPath); + SetEnvironmentVariableA("RpcViewSymbolPath",NewSymbolsPath.toAscii()); + } +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetUpdateSpeedAsFast() +{ + this->RefreshSpeedInMs = FAST_REFRESH_SPEED; + pRefreshTimer->setInterval(this->RefreshSpeedInMs); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetUpdateSpeedAsNormal() +{ + this->RefreshSpeedInMs = NORMAL_REFRESH_SPEED; + pRefreshTimer->setInterval(this->RefreshSpeedInMs); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetUpdateSpeedAsBelowNormal() +{ + this->RefreshSpeedInMs = BELOW_NORMAL_REFRESH_SPEED; + pRefreshTimer->setInterval(this->RefreshSpeedInMs); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetUpdateSpeedAsSlow() +{ + this->RefreshSpeedInMs = SLOW_REFRESH_SPEED; + pRefreshTimer->setInterval(this->RefreshSpeedInMs); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetUpdateSpeedAsVerySlow() +{ + this->RefreshSpeedInMs = VERY_SLOW_REFRESH_SPEED; + pRefreshTimer->setInterval(this->RefreshSpeedInMs); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::InvokeFindShortcut() +{ + QKeyEvent FindEvent(QKeyEvent::KeyPress, Qt::Key_F, Qt::ControlModifier); + QApplication::sendEvent(this, &FindEvent); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::FilterProcesses() +{ + pProcessWidget->setFocus(Qt::ActiveWindowFocusReason); + InvokeFindShortcut(); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::FilterEndpoints() +{ + pEndpointsWidget->setFocus(Qt::ActiveWindowFocusReason); + InvokeFindShortcut(); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::FilterInterfaces() +{ + pInterfacesWidget->setFocus(Qt::ActiveWindowFocusReason); + InvokeFindShortcut(); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetAbsolute() +{ + this->AddressRepresentation = AddressRepresentation_Absolute; + + ConfigurationVisitor_C ConfigurationVisitor(ConfigurationVisitor_C::AddressAbsolute, NULL); + SendVisitor(ConfigurationVisitor); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetRVA() +{ + this->AddressRepresentation = AddressRepresentation_RVA; + + ConfigurationVisitor_C ConfigurationVisitor(ConfigurationVisitor_C::AddressRVA, NULL); + SendVisitor(ConfigurationVisitor); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::SetupMenu() +{ + HICON hUacIcon; + QMenuBar* pMenuBar = new QMenuBar(this); + // + // File + // + QMenu* pMenuFile = pMenuBar->addMenu("&File"); + QAction* pActionAllProcessesDetails = pMenuFile->addAction("Show &Details for All Processes",this,SLOT(ViewDetailsForAllProcesses())); + QAction* pActionFileExit = pMenuFile->addAction("E&xit",this,SLOT(Exit())); + // + // Option + // + QMenu* pMenuOptions = pMenuBar->addMenu("&Options"); + QAction* pActionConfigureSymbols = pMenuOptions->addAction("Configure Sym&bols",this,SLOT(ConfigureSymbols())); + QMenu* pSubMenupdateSpeed = pMenuOptions->addMenu("&Refresh Speed"); + QAction* pActionRefresh = pMenuOptions->addAction("Refresh &Now", this, SLOT(RefreshViews())); + QAction* pActionViewSelectColumns = pMenuOptions->addAction("Select Col&umns", this, SLOT(ShowColumnsDialog())); + QMenu* pSubMenuAddress = pMenuOptions->addMenu("&Address"); + pActionRefresh->setShortcut(Qt::Key_F5); + + pAddressAbsolute = pSubMenuAddress->addAction("Absolute", this, SLOT(SetAbsolute())); + pAddressRva = pSubMenuAddress->addAction("RVA", this, SLOT(SetRVA())); + QActionGroup* pAddressGroup = new QActionGroup(this); + + pAddressGroup->addAction(pAddressAbsolute); + pAddressGroup->addAction(pAddressRva); + + pAddressAbsolute->setCheckable(true); + pAddressRva->setCheckable(true); + + pActionSpeedFast = pSubMenupdateSpeed->addAction(".5 seconds", this, SLOT(SetUpdateSpeedAsFast())); + pActionSpeedNormal = pSubMenupdateSpeed->addAction("1 second", this, SLOT(SetUpdateSpeedAsNormal())); + pActionSpeedBelowNormal = pSubMenupdateSpeed->addAction("2 seconds", this, SLOT(SetUpdateSpeedAsBelowNormal())); + pActionSpeedSlow = pSubMenupdateSpeed->addAction("5 seconds", this, SLOT(SetUpdateSpeedAsSlow())); + pActionSpeedVerySlow = pSubMenupdateSpeed->addAction("10 seconds", this, SLOT(SetUpdateSpeedAsVerySlow())); + + pActionSpeedFast->setCheckable(true); + pActionSpeedNormal->setCheckable(true); + pActionSpeedBelowNormal->setCheckable(true); + pActionSpeedSlow->setCheckable(true); + pActionSpeedVerySlow->setCheckable(true); + + QActionGroup* pSpeedActionGroup = new QActionGroup(this); + + pSpeedActionGroup->addAction(pActionSpeedFast); + pSpeedActionGroup->addAction(pActionSpeedNormal); + pSpeedActionGroup->addAction(pActionSpeedBelowNormal); + pSpeedActionGroup->addAction(pActionSpeedSlow); + pSpeedActionGroup->addAction(pActionSpeedVerySlow); + // + // View + // + QMenu* pMenuView = pMenuBar->addMenu("&View"); + pMenuView->addAction(pInterfacesWidget->toggleViewAction()); + pMenuView->addAction(pEndpointsWidget->toggleViewAction()); + pMenuView->addAction(pProceduresWidget->toggleViewAction()); + pMenuView->addAction(pProcessInfoWidget->toggleViewAction()); + pMenuView->addAction(pInterfaceInfoWidget->toggleViewAction()); + pMenuView->addAction(pDecompilationWidget->toggleViewAction()); + + pInterfacesWidget->toggleViewAction()->setText("&Interfaces"); + pEndpointsWidget->toggleViewAction()->setText("&Endpoints"); + pProceduresWidget->toggleViewAction()->setText("&Procedures"); + pProcessInfoWidget->toggleViewAction()->setText("Proce&ss Properties"); + pInterfaceInfoWidget->toggleViewAction()->setText("Inter&faces Properties"); + pDecompilationWidget->toggleViewAction()->setText("&Decompilation"); + // + // Filter + // + QMenu* pMenuFilter = pMenuBar->addMenu("Fil&ter"); + QAction* pActionFilterProcesses = pMenuFilter->addAction("&Process", this, SLOT(FilterProcesses())); + QAction* pActionFilterEndpoints = pMenuFilter->addAction("&Endpoints", this, SLOT(FilterEndpoints())); + QAction* pActionFilterInterfaces = pMenuFilter->addAction("&Interfaces", this, SLOT(FilterInterfaces())); + // + // Help + // + QMenu* pMenuHelp = pMenuBar->addMenu("&Help"); + QAction* pActionHelp = pMenuHelp->addAction("&Help...", this, SLOT(Help())); + pActionHelp->setShortcut(Qt::Key_F1); + //-- + pMenuHelp->addSeparator(); + //-- + QAction* pActionAbout = pMenuHelp->addAction("&About", this, SLOT(About())); + pActionAboutQt = pMenuHelp->addAction("About &Qt", qApp, SLOT(aboutQt())); + + if (IsUserAnAdmin()) pActionAllProcessesDetails->setEnabled(false); + + hUacIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_UAC_ICON)); + if (hUacIcon!=NULL) + { + pActionAllProcessesDetails->setIcon(QPixmap::fromWinHICON(hUacIcon)); + DestroyIcon(hUacIcon); + } + setMenuBar(pMenuBar); +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::InitMenuRefreshSpeed() +{ + switch(RefreshSpeedInMs) + { + case FAST_REFRESH_SPEED : pActionSpeedFast->setChecked(true); break; + case NORMAL_REFRESH_SPEED : pActionSpeedNormal->setChecked(true); break; + case BELOW_NORMAL_REFRESH_SPEED : pActionSpeedBelowNormal->setChecked(true); break; + case SLOW_REFRESH_SPEED : pActionSpeedSlow->setChecked(true); break; + case VERY_SLOW_REFRESH_SPEED : pActionSpeedVerySlow->setChecked(true); break; + //-- + default: + break; + } +} + + +//------------------------------------------------------------------------------ +void MainWindow_C::InitMenuAddressRepresentation() +{ + switch (AddressRepresentation) + { + case AddressRepresentation_Absolute : pAddressAbsolute->setChecked(true); break; + case AddressRepresentation_RVA : pAddressRva->setChecked(true); break; + //-- + default: + break; + } +} + + +//------------------------------------------------------------------------------ +MainWindow_C::MainWindow_C(RpcCore_T* pRpcCore) +{ + setObjectName(WidgetName); //required to save the window geometry/state + setWindowTitle(WidgetName); + // + // Inits Helpers: RpcCore and RpcDecompiler + // + this->pRpcCore = pRpcCore; + + setDockOptions( + QMainWindow::AllowNestedDocks| + QMainWindow::AllowTabbedDocks| + QMainWindow::AnimatedDocks + ); + // + // Creates all the views + // + pInterfacesWidget = new InterfacesWidget_C(this); + pProceduresWidget = new ProceduresWidget_C(this); + pInterfaceInfoWidget= new InterfaceInfoWidget_C(this); + pProcessWidget = new ProcessWidget_C(this); + pProcessInfoWidget = new ProcessInfoWidget_C(this); + pEndpointsWidget = new EndpointsWidget_C(this); + pDecompilationWidget= new DecompilationWidget_C(this); + // + // Add the Process view as the main one + // + setCentralWidget(pProcessWidget); + // + // All other views are optional DockWidgets: + // + addDockWidget(Qt::RightDockWidgetArea, pProcessInfoWidget); + addDockWidget(Qt::RightDockWidgetArea, pInterfaceInfoWidget); + addDockWidget(Qt::BottomDockWidgetArea, pInterfacesWidget); + addDockWidget(Qt::LeftDockWidgetArea, pEndpointsWidget); + addDockWidget(Qt::BottomDockWidgetArea, pProceduresWidget); + addDockWidget(Qt::LeftDockWidgetArea, pDecompilationWidget); + // + // Create the menu + // + SetupMenu(); + + pProcessesCountLabel = new QLabel("Processes: -",this); + pInterfacesCountLabel = new QLabel("Interfaces: -",this); + pEndpointsCountLabel = new QLabel("Enpoints: -",this); + + StatusBar.showMessage("Ready."); + + StatusBar.addPermanentWidget(pEndpointsCountLabel); + StatusBar.addPermanentWidget(pInterfacesCountLabel); + StatusBar.addPermanentWidget(pProcessesCountLabel); + + setStatusBar(&StatusBar); + + HANDLE hIcon = LoadImageA(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_MAIN_ICON), IMAGE_ICON, 0, 0, 0); + + QFont font("Helvetica", 20, QFont::Bold); +#ifndef _DEBUG + QSplashScreen SplashScreen(QPixmap::fromWinHICON((HICON)hIcon),Qt::WindowStaysOnTopHint); + SplashScreen.showMessage(QString("RpcView"), Qt::AlignCenter, QColor(Qt::lightGray)); + SplashScreen.setFont(font); + SplashScreen.show(); +#endif + // + // Init all the views + // + InitViewsVisitor_C InitViewsVisitor( + pRpcCore, + &pRpcCoreCtxt + ); + SendVisitor(InitViewsVisitor); + // + // Restore saved settings + // + pSettings = new QSettings(RPC_VIEW_ORGANIZATION_NAME, RPC_VIEW_APPLICATION_NAME,this); + + QVariant RefreshSpeedValue; + + RefreshSpeedValue = pSettings->value("RefreshSpeed"); + if (RefreshSpeedValue.isNull()) + { + this->RefreshSpeedInMs = NORMAL_REFRESH_SPEED; + } + else + { + this->RefreshSpeedInMs = RefreshSpeedValue.toUInt(); + } + InitMenuRefreshSpeed(); + + QVariant AddressRepresentationValue; + + AddressRepresentationValue = pSettings->value("AddressRepresentation"); + if (AddressRepresentationValue.isNull()) + { + this->AddressRepresentation = AddressRepresentation_Absolute; + } + else + { + this->AddressRepresentation = (AddressRepresentation_T)AddressRepresentationValue.toUInt(); + } + InitMenuAddressRepresentation(); + show(); + + restoreGeometry( pSettings->value("MainWindow/geometry").toByteArray() ); + restoreState( pSettings->value("MainWindow/windowState").toByteArray() ); + ConfigurationVisitor_C ConfigurationVisitor(ConfigurationVisitor_C::Load,pSettings); + SendVisitor(ConfigurationVisitor); + if (AddressRepresentation == AddressRepresentation_RVA) + { + ConfigurationVisitor_C ConfigurationVisitor(ConfigurationVisitor_C::AddressRVA, pSettings); + SendVisitor(ConfigurationVisitor); + } + + SetEnvironmentVariableA( "RpcViewSymbolPath",pSettings->value("SymbolsPath").toByteArray() ); + + pInterfacesCountLabel->setText( QString("Interfaces: %1").arg(InitViewsVisitor.GetInterfaces()) ); + pEndpointsCountLabel->setText( QString("Endpoints: %1").arg(InitViewsVisitor.GetEndpoints()) ); + // + // Start auto refresh + // + pRefreshTimer = new QTimer(this); + connect(pRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViews())); + pRefreshTimer->start(this->RefreshSpeedInMs); + + InitColumnsDialog(); +} \ No newline at end of file diff --git a/RpcView/MainWindow.h b/RpcView/MainWindow.h new file mode 100644 index 0000000..ae051f3 --- /dev/null +++ b/RpcView/MainWindow.h @@ -0,0 +1,119 @@ +#ifndef _MAIN_WINDOW_H_ +#define _MAIN_WINDOW_H_ + +#include "..\Qt\Qt.h" + +#include "..\RpcCommon\RpcView.h" +#include "ProcessWidget.h" +#include "ProcessInfoWidget.h" +#include "EndpointsWidget.h" +#include "InterfacesWidget.h" +#include "InterfaceInfoWidget.h" +#include "ProceduresWidget.h" +#include "DecompilationWidget.h" +#include "..\RpcCore\RpcCore.h" +#include "..\RpcDecompiler\RpcDecompiler.h" +#include "ViewVisitor.h" + +#define RPC_VIEW_ORGANIZATION_NAME "RpcView Team" +#define RPC_VIEW_APPLICATION_NAME "RpcView" + + +//------------------------------------------------------------------------------ +class MainWindow_C : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow_C(RpcCore_T* pRpcCore); + +public slots: + void ConfigureSymbols(); + void ProcessSelected(quint32 Pid); + void EndpointSelected(quint32 Pid); + void InterfaceSelected(quint32 Pid, RPC_IF_ID* pIf); + void SlotDecompileInterface(quint32, RPC_IF_ID*); + void SetAbsolute(); + void SetRVA(); + void Exit(); + +protected: + void closeEvent(QCloseEvent *event); + +private slots: + void About(); + void Help(); + void RefreshViews(); + void ViewDetailsForAllProcesses(); + //-- + void SetUpdateSpeedAsFast(); + void SetUpdateSpeedAsNormal(); + void SetUpdateSpeedAsBelowNormal(); + void SetUpdateSpeedAsSlow(); + void SetUpdateSpeedAsVerySlow(); + void ShowColumnsDialog(); + void UpdateColumns(); + //-- + void FilterProcesses(); + void FilterEndpoints(); + void FilterInterfaces(); + +private: + void* pRpcCoreCtxt; + RpcCore_T* pRpcCore; + AddressRepresentation_T AddressRepresentation; + + QStatusBar StatusBar; + ProcessWidget_C* pProcessWidget; + ProcessInfoWidget_C* pProcessInfoWidget; + ProceduresWidget_C* pProceduresWidget; + EndpointsWidget_C* pEndpointsWidget; + InterfacesWidget_C* pInterfacesWidget; + InterfaceInfoWidget_C* pInterfaceInfoWidget; + DecompilationWidget_C* pDecompilationWidget; + + QLabel* pProcessesCountLabel; + QLabel* pInterfacesCountLabel; + QLabel* pEndpointsCountLabel; + + QAction* pActionViewInterfaces; + QAction* pActionViewEndpoints; + QAction* pActionViewProcedures; + QAction* pActionViewInterfaceInfo; + QAction* pActionViewProcessInfo; + QAction* pActionAboutQt; + QAction* pActionSpeedFast; + QAction* pActionSpeedNormal; + QAction* pActionSpeedBelowNormal; + QAction* pActionSpeedSlow; + QAction* pActionSpeedVerySlow; + QAction* pAddressAbsolute; + QAction* pAddressRva; + + QSettings* pSettings; + QTimer* pRefreshTimer ; + //-- + uint RefreshSpeedInMs; + //-- + // Columns Dialog + QDialog* ColumnsDialog; + QVBoxLayout* ColumnsVLayout; + QHBoxLayout* ColumnsHLayout; + QVBoxLayout* ColumnsVLayout1; + QDialogButtonBox* ColumnsButtonBox; + QWidget* pProcessColumns; + QWidget* pEndpointsColumns; + QWidget* pInterfacesColumns; + QWidget* pProceduresColumns; + + + void SendVisitor(ViewVisitor_C& pVisitor); + void InitMenuRefreshSpeed(); + void InitMenuAddressRepresentation(); + void InitColumnsDialog(); + void SetupMenu(); + void InvokeFindShortcut(); + bool eventFilter(QObject* pObject, QEvent* pEvent); +}; + +#endif// _PROCESS_LOGGER_WINDOW_H_ diff --git a/RpcView/Pdb.c b/RpcView/Pdb.c new file mode 100644 index 0000000..ca54615 --- /dev/null +++ b/RpcView/Pdb.c @@ -0,0 +1,194 @@ +#include "Pdb.h" +#include +#include +#include + +#define _CRTDBG_MAP_ALLOC +#include +#include + +#define RSDS_SIGNATURE 'SDSR' +#define PDB_MAX_SYMBOL_SIZE 1000 + +//Only for PDB2.0 format! +struct CV_INFO_PDB20{ + DWORD CvSignature; + DWORD Offset; + DWORD Signature; + DWORD Age; + BYTE PdbFileName[MAX_PATH]; +}; + +//Only for PDB7.0 format! +typedef struct _CV_INFO_PDB70{ + DWORD CvSignature; + GUID Signature; + DWORD Age; + BYTE PdbFileName[MAX_PATH]; +} CV_INFO_PDB70; + + +typedef struct _PdbCtxt_T{ + HANDLE hProcess; + void* pModuleBase; + ULONG ModuleSize; +}PdbCtxt_T; + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetModulePdbInfo(HANDLE hProcess, VOID* pModuleBase, CV_INFO_PDB70* pPdb70Info) +{ + UCHAR* pBase = (UCHAR*)pModuleBase; + IMAGE_DOS_HEADER ImageDosHeader; + IMAGE_NT_HEADERS ImageNtHeaders; + IMAGE_DEBUG_DIRECTORY ImageDebugDirectory; + BOOL bResult = FALSE; +#ifdef _WIN64 + BOOL bWow64; + IMAGE_NT_HEADERS32 ImageNtHeaders32; + + if (hProcess==NULL) hProcess = GetCurrentProcess(); + + if (!IsWow64Process(hProcess, &bWow64)) goto End; + if (bWow64==TRUE) + { + if (!ReadProcessMemory(hProcess, pModuleBase, &ImageDosHeader, sizeof(ImageDosHeader), NULL)) goto End; + if (!ReadProcessMemory(hProcess, pBase + ImageDosHeader.e_lfanew, &ImageNtHeaders32, sizeof(ImageNtHeaders32), NULL)) goto End; + if (!ReadProcessMemory(hProcess, pBase + ImageNtHeaders32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress, &ImageDebugDirectory, sizeof(ImageDebugDirectory), NULL)) goto End; + if (!ReadProcessMemory(hProcess, pBase + ImageDebugDirectory.AddressOfRawData, pPdb70Info, sizeof(*pPdb70Info), NULL)) goto End; + } + else +#endif + { + if (!ReadProcessMemory(hProcess, pModuleBase, &ImageDosHeader, sizeof(ImageDosHeader), NULL)) goto End; + if (!ReadProcessMemory(hProcess, pBase + ImageDosHeader.e_lfanew, &ImageNtHeaders, sizeof(ImageNtHeaders), NULL)) goto End; + if (!ReadProcessMemory(hProcess, pBase + ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress, &ImageDebugDirectory, sizeof(ImageDebugDirectory), NULL)) goto End; + if (!ReadProcessMemory(hProcess, pBase + ImageDebugDirectory.AddressOfRawData, pPdb70Info, sizeof(*pPdb70Info), NULL)) goto End; + } + if (pPdb70Info->CvSignature != RSDS_SIGNATURE ) + { + _cprintf("Invalid CvSignature"); + goto End; + } + bResult = TRUE; +End: + return (bResult); +} + + +//------------------------------------------------------------------------------ +BOOL WINAPI GetPdbFilePath(HANDLE hProcess, VOID* pModuleBase, UCHAR* pPdbPath, UINT PdbPathSize) +{ + CV_INFO_PDB70 Pdb70Info; + CHAR SymbolPath[MAX_PATH]; + BOOL bResult = FALSE; + + if (!GetModulePdbInfo(hProcess, pModuleBase, &Pdb70Info)) goto End; + /* + if (!SymFindFileInPath(hProcess, "c:\\symbols\\", Pdb70Info.PdbFileName, &Pdb70Info.Signature, Pdb70Info.Age, 0, SSRVOPT_GUIDPTR, pPdbPath, NULL, NULL)) + { + printf("SymFindFileInPath failed %u\n", GetLastError()); + goto End; + } + */ + if (strchr((char*)Pdb70Info.PdbFileName, '\\') != NULL) + { + StringCbPrintfA((STRSAFE_LPSTR)pPdbPath, PdbPathSize, "%hs", Pdb70Info.PdbFileName); + } + else + { + if (GetEnvironmentVariableA("RpcViewSymbolPath", SymbolPath, sizeof(SymbolPath)) == 0) goto End; + StringCbPrintfA((STRSAFE_LPSTR)pPdbPath, PdbPathSize, "%s\\%s\\%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%X\\%s", + SymbolPath, + Pdb70Info.PdbFileName, + Pdb70Info.Signature.Data1, + Pdb70Info.Signature.Data2, + Pdb70Info.Signature.Data3, + Pdb70Info.Signature.Data4[0], + Pdb70Info.Signature.Data4[1], + Pdb70Info.Signature.Data4[2], + Pdb70Info.Signature.Data4[3], + Pdb70Info.Signature.Data4[4], + Pdb70Info.Signature.Data4[5], + Pdb70Info.Signature.Data4[6], + Pdb70Info.Signature.Data4[7], + Pdb70Info.Age, + Pdb70Info.PdbFileName + ); + } + //printf("pdb path: %s\n",pPdbPath); + bResult = TRUE; +End: + return (bResult); +} + + +//------------------------------------------------------------------------------ +__checkReturn void* WINAPI PdbInit(__in HANDLE hProcess, __in VOID* pModuleBase, __in UINT ModuleSize) +{ + UCHAR PdbPath[MAX_PATH]; + PdbCtxt_T* pPdbCtxt = NULL; + + if (!SymInitialize(hProcess, NULL, FALSE)) goto End; + if (!GetPdbFilePath(hProcess, pModuleBase, PdbPath, sizeof(PdbPath))) goto End; + if (!SymLoadModule64(hProcess, NULL, (STRSAFE_LPCSTR)PdbPath, NULL,(DWORD64) pModuleBase, ModuleSize)) + { + printf("SymLoadModule64 failed\n"); + SymCleanup(hProcess); + goto End; + } + // + // All is ok, so we can allocate and init the PDB private context + // + pPdbCtxt = (PdbCtxt_T*)malloc(sizeof(PdbCtxt_T)); + if (pPdbCtxt!=NULL) + { + ZeroMemory(pPdbCtxt, sizeof(PdbCtxt_T)); + + pPdbCtxt->hProcess = hProcess; + pPdbCtxt->ModuleSize = ModuleSize; + pPdbCtxt->pModuleBase = pModuleBase; + } +End: + return (pPdbCtxt); +} + + +//------------------------------------------------------------------------------ +__checkReturn BOOL WINAPI PdbGetSymbolName(__in void* hCtxt, __in VOID* pSymbol, __out WCHAR* pName, __in UINT NameLength) +{ + BOOL bResult = FALSE; + IMAGEHLP_SYMBOL64* pSymbolInfo = NULL; + DWORD64 dwDisp = 0; + PdbCtxt_T* pPdbCtxt = (PdbCtxt_T*)hCtxt; + + if (pPdbCtxt==NULL) goto End; + + pSymbolInfo=(IMAGEHLP_SYMBOL64*)malloc( PDB_MAX_SYMBOL_SIZE ); + if (pSymbolInfo==NULL) goto End; + ZeroMemory(pSymbolInfo, PDB_MAX_SYMBOL_SIZE); + + pSymbolInfo->MaxNameLength = NameLength; + pSymbolInfo->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + + bResult = SymGetSymFromAddr64( pPdbCtxt->hProcess, (DWORD64)pSymbol, &dwDisp, pSymbolInfo); + if (!bResult) goto End; + if (dwDisp!=0) goto End; + StringCbPrintfW(pName,NameLength,L"%S",pSymbolInfo->Name); +End: + if (pSymbolInfo!=NULL) free(pSymbolInfo); + return (bResult); +} + + +//------------------------------------------------------------------------------ +void WINAPI PdbUninit(__in void* hCtxt) +{ + PdbCtxt_T* pPdbCtxt = (PdbCtxt_T*)hCtxt; + + if (pPdbCtxt==NULL) goto End; + SymUnloadModule64(pPdbCtxt->hProcess,(DWORD64)pPdbCtxt->pModuleBase); + free(pPdbCtxt); +End: + return; +} \ No newline at end of file diff --git a/RpcView/Pdb.h b/RpcView/Pdb.h new file mode 100644 index 0000000..da5ad54 --- /dev/null +++ b/RpcView/Pdb.h @@ -0,0 +1,10 @@ +#ifndef _PDB_H_ +#define _PDB_H_ + +#include + +EXTERN_C __checkReturn void* WINAPI PdbInit(__in HANDLE hProcess, __in VOID* pModuleBase, __in UINT ModuleSize); +EXTERN_C __checkReturn BOOL WINAPI PdbGetSymbolName(__in void* pPdbCtxt, __in VOID* pSymbol, __out WCHAR* pName, __in UINT NameLength); +EXTERN_C void WINAPI PdbUninit(__in void* pPdbCtxt); + +#endif // _PDB_H_ \ No newline at end of file diff --git a/RpcView/ProceduresWidget.cpp b/RpcView/ProceduresWidget.cpp new file mode 100644 index 0000000..c2b4d03 --- /dev/null +++ b/RpcView/ProceduresWidget.cpp @@ -0,0 +1,226 @@ +#include "ProceduresWidget.h" +#include "..\..\RpcCommon\RpcCommon.h" + +static const char WidgetName[] = "Procedures"; +static const char ConfigPath[] = "Procedures/geometry"; + + +//------------------------------------------------------------------------------ +QString GetProceduresWidgetColumName(ProceduresWigetColumn_T ProceduresWigetColumn) +{ + switch(ProceduresWigetColumn) + { + case ProceduresWigetColumn_Index : return (QString("Index")); + case ProceduresWigetColumn_Name : return (QString("Name")); + case ProceduresWigetColumn_Address : return (QString("Address")); + case ProceduresWigetColumn_FormatString : return (QString("Format")); + default: return (QString("Unknown")); + } +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::reset(ULONG Pid) +{ + this->Pid = Pid; + pProcedures->clear(); +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::resizeColumnsToContents() +{ + int Index; + + for( Index=0; Index < ProceduresWigetColumn_Last; Index++) + { + pProcedures->resizeColumnToContents(Index); + } +} + + +//------------------------------------------------------------------------------ +bool ProceduresWidget_C::AddProcedure(quint32 ProcIdx, WCHAR* pSymbolName, VOID* pBase, ULONG Rva, VOID* pProcFormatString) +{ + QTreeWidgetItem* pProcedure; + + pCurrentIntefaceBase = pBase; + pProcedure = new QTreeWidgetItem; + + pProcedure->setData(ProceduresWigetColumn_Index, Qt::DisplayRole, ProcIdx ); + pProcedure->setData(ProceduresWigetColumn_Name, Qt::DisplayRole, QString::fromUtf16((const ushort*)pSymbolName)); + pProcedure->setData(ProceduresWigetColumn_Address, Qt::UserRole, (quintptr)pBase + (quint32)Rva); + + if (pProcFormatString == NULL) + { + pProcedure->setData(ProceduresWigetColumn_FormatString, Qt::DisplayRole, ""); + } + else + { + pProcedure->setData(ProceduresWigetColumn_FormatString, Qt::UserRole, (quintptr)pProcFormatString); + } + + switch (AddressRepresentation) + { + case AddressRepresentation_Absolute: + pProcedure->setData(ProceduresWigetColumn_Address, Qt::DisplayRole, QString("0x%1").arg((quintptr)pBase + Rva, 16, 16, QLatin1Char('0'))); + pProcedure->setData(ProceduresWigetColumn_FormatString, Qt::DisplayRole, QString("0x%1").arg((quintptr)pProcFormatString, 16, 16, QLatin1Char('0'))); + break; + //-- + case AddressRepresentation_RVA: + pProcedure->setData(ProceduresWigetColumn_Address, Qt::DisplayRole, QString("+0x%1").arg((quintptr)Rva, 8, 16, QLatin1Char('0'))); + pProcedure->setData(ProceduresWigetColumn_FormatString, Qt::DisplayRole, QString("+0x%1").arg((quintptr)pProcFormatString - (quintptr)pBase, 8, 16, QLatin1Char('0'))); + break; + //-- + default: + break; + } + + pProcedures->addTopLevelItem(pProcedure); + return (true); +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::SetAddressRepresentation(AddressRepresentation_T AddressRepresentation) +{ + QTreeWidgetItem* pProcedure; + quintptr AbsoluteAddr; + + this->AddressRepresentation = AddressRepresentation; + + switch (AddressRepresentation) + { + case AddressRepresentation_RVA: + for (int i = 0; i < pProcedures->topLevelItemCount(); i++) + { + pProcedure = pProcedures->topLevelItem(i); + AbsoluteAddr = pProcedure->data(ProceduresWigetColumn_Address, Qt::UserRole).toULongLong(); + pProcedure->setData(ProceduresWigetColumn_Address, Qt::DisplayRole, QString("+0x%1").arg(AbsoluteAddr - (quintptr)pCurrentIntefaceBase, 8, 16, QLatin1Char('0'))); + AbsoluteAddr = pProcedure->data(ProceduresWigetColumn_FormatString, Qt::UserRole).toULongLong(); + pProcedure->setData(ProceduresWigetColumn_FormatString, Qt::DisplayRole, QString("+0x%1").arg(AbsoluteAddr - (quintptr)pCurrentIntefaceBase, 8, 16, QLatin1Char('0'))); + } + break; + //-- + case AddressRepresentation_Absolute: + for (int i = 0; i < pProcedures->topLevelItemCount(); i++) + { + pProcedure = pProcedures->topLevelItem(i); + AbsoluteAddr = pProcedure->data(ProceduresWigetColumn_Address, Qt::UserRole).toULongLong(); + pProcedure->setData(ProceduresWigetColumn_Address, Qt::DisplayRole, QString("0x%1").arg(AbsoluteAddr, HEX_SIZE_OF_PTR, 16, QLatin1Char('0'))); + AbsoluteAddr = pProcedure->data(ProceduresWigetColumn_FormatString, Qt::UserRole).toULongLong(); + pProcedure->setData(ProceduresWigetColumn_FormatString, Qt::DisplayRole, QString("0x%1").arg(AbsoluteAddr, HEX_SIZE_OF_PTR, 16, QLatin1Char('0'))); + } + break; + //-- + default: + break; + } +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::AcceptVisitor(ViewVisitor_C* pVisitor) +{ + pVisitor->Visit(this); +} + + +//------------------------------------------------------------------------------ +UINT ProceduresWidget_C::GetPid() +{ + return (this->Pid); +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::SaveConfiguration(QSettings* pSettings) +{ + pSettings->setValue(ConfigPath, pProcedures->header()->saveState()); +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::LoadConfiguration(QSettings* pSettings) +{ + pProcedures->header()->restoreState(pSettings->value(ConfigPath).toByteArray()); +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::CreateColumnsSelectionWidget() +{ + pColumnsSelectionWidget = new QGroupBox(WidgetName,this); + QVBoxLayout* pLayout = new QVBoxLayout(pColumnsSelectionWidget); + + for (int i = 0; i < ProceduresWigetColumn_Last; i++) + { + CheckBoxArray[i] = new QCheckBox(GetProceduresWidgetColumName((ProceduresWigetColumn_T)i), pColumnsSelectionWidget); + pLayout->addWidget(CheckBoxArray[i]); + } + pLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + pColumnsSelectionWidget->setLayout(pLayout); +} + + +//------------------------------------------------------------------------------ +QWidget* ProceduresWidget_C::GetColumnsSelectionWidget() +{ + for (int i = 0; i < ProceduresWigetColumn_Last; i++) + { + CheckBoxArray[i]->setChecked(!pProcedures->header()->isSectionHidden(i)); + } + return pColumnsSelectionWidget; +} + + +//------------------------------------------------------------------------------ +void ProceduresWidget_C::UpdateColumnsVisibility() +{ + for (int i = 0; i < ProceduresWigetColumn_Last; i++) + { + pProcedures->header()->setSectionHidden(i, !CheckBoxArray[i]->isChecked()); + } +} + + +//------------------------------------------------------------------------------ +ProceduresWidget_C::ProceduresWidget_C(QWidget* pParent):QDockWidget(WidgetName) +{ + UINT Idx; + QGridLayout* pGridLayout; + QGroupBox* pGroupBox; + + this->Pid = 0; + + setObjectName(WidgetName); + + pProcedures = new QTreeWidget(this); + pGridLayout = new QGridLayout(); + pGroupBox = new QGroupBox(); + + QTreeWidgetItem* pHeaderItem = pProcedures->headerItem(); + for (Idx = 0; Idx < ProceduresWigetColumn_Last; Idx++) + { + pHeaderItem->setText( Idx, GetProceduresWidgetColumName((ProceduresWigetColumn_T)Idx) ); + } + + pProcedures->setColumnCount(ProceduresWigetColumn_Last); + pProcedures->setSortingEnabled(true); + pProcedures->sortByColumn(-1); + pProcedures->setAnimated(true); + pProcedures->expandAll(); + pProcedures->setAlternatingRowColors(true); + pProcedures->setRootIsDecorated(false); + pProcedures->setMouseTracking(true); + pProcedures->header()->installEventFilter(pParent); + + pGridLayout->addWidget(pProcedures,0,0); + pGroupBox->setLayout(pGridLayout); + setWidget(pGroupBox); + AddressRepresentation = AddressRepresentation_Absolute; + // + // Create the Widget for column selection + // + CreateColumnsSelectionWidget(); +} \ No newline at end of file diff --git a/RpcView/ProceduresWidget.h b/RpcView/ProceduresWidget.h new file mode 100644 index 0000000..a5f0b21 --- /dev/null +++ b/RpcView/ProceduresWidget.h @@ -0,0 +1,48 @@ +#ifndef _PROCEDURES_WIDGET_H_ +#define _PROCEDURES_WIDGET_H_ + +#include "..\Qt\Qt.h" +#include "..\RpcCore\RpcCore.h" +#include "View.h" +#include "..\..\RpcCommon\\RpcCommon.h" + +typedef enum _ProceduresWigetColumn_T{ + ProceduresWigetColumn_Index, + ProceduresWigetColumn_Name, + ProceduresWigetColumn_Address, + ProceduresWigetColumn_FormatString, + //... + ProceduresWigetColumn_Last +}ProceduresWigetColumn_T; + +//------------------------------------------------------------------------------ +class ProceduresWidget_C : public QDockWidget, public View_I +{ + Q_OBJECT + +public: + ProceduresWidget_C(QWidget* pParent); + virtual void AcceptVisitor(ViewVisitor_C* pVisitor); + + void resizeColumnsToContents(); + void reset(ULONG Pid); + UINT GetPid(); + QWidget* GetColumnsSelectionWidget(); + void UpdateColumnsVisibility(); + void SaveConfiguration(QSettings*); + void LoadConfiguration(QSettings*); + void SetAddressRepresentation(AddressRepresentation_T AddressRepresentation); +public slots: + bool AddProcedure(quint32 ProcIdx, WCHAR* pSymbolName, VOID* pBase, ULONG Rva, VOID* pProcFormatString); + +private: + UINT Pid; + QTreeWidget* pProcedures; + QGroupBox* pColumnsSelectionWidget; + QCheckBox* CheckBoxArray[ProceduresWigetColumn_Last]; + void* pCurrentIntefaceBase; + AddressRepresentation_T AddressRepresentation; + void CreateColumnsSelectionWidget(); +}; + +#endif// _PROCEDURES_WIDGET_H_ diff --git a/RpcView/ProcessEntry.h b/RpcView/ProcessEntry.h new file mode 100644 index 0000000..6e87ca5 --- /dev/null +++ b/RpcView/ProcessEntry.h @@ -0,0 +1,19 @@ +#ifndef _PROCESS_ENTRY_H_ +#define _PROCESS_ENTRY_H_ + +#include + +//------------------------------------------------------------------------------ +class ProcessEntry_C +{ +public: + ProcessEntry_C(ULONG Ppid, ULONG Pid) + { + this->Ppid=Ppid; + this->Pid = Pid; + } + ULONG Ppid; + ULONG Pid; +}; + +#endif //_PROCESS_ENTRY_H_ \ No newline at end of file diff --git a/RpcView/ProcessInfoWidget.cpp b/RpcView/ProcessInfoWidget.cpp new file mode 100644 index 0000000..c202bd1 --- /dev/null +++ b/RpcView/ProcessInfoWidget.cpp @@ -0,0 +1,279 @@ +#include "ProcessInfoWidget.h" +#include "../RpcCore/RpcCore.h" +#include "../RpcCommon/Misc.h" + +static const char WidgetName[] = "Processes Properties"; + +typedef enum _AuthInfoColumn_T{ + AuthInfoColumn_AuthSvc, + AuthInfoColumn_Name, + AuthInfoColumn_Comment, + AuthInfoColumn_PrincipalName, + //... + AuthInfoColumn_Last +}AuthInfoColumn_T; + + +typedef enum _ProcessInfoTab_T{ + ProcessInfoTab_Image, + ProcessInfoTab_RPC, + ProcessInfoTab_SSP +}ProcessInfoTab_T; + + +//------------------------------------------------------------------------------ +QString GetProcessInfoTabName(ProcessInfoTab_T ProcessInfoTab) +{ + switch(ProcessInfoTab) + { + case ProcessInfoTab_Image : return QString("Image"); + case ProcessInfoTab_RPC : return QString("RPC"); + case ProcessInfoTab_SSP : return QString("SSP"); + default:return QString("Unknown"); + } +} + + +//------------------------------------------------------------------------------ +QString GetAuthInfoColumnName(AuthInfoColumn_T AuthInfoColumn) +{ + switch(AuthInfoColumn) + { + case AuthInfoColumn_AuthSvc: return QString("Id"); + case AuthInfoColumn_Name: return QString("Name"); + case AuthInfoColumn_Comment: return QString("Comment"); + case AuthInfoColumn_PrincipalName: return QString("PrincName"); + default:return QString("Unknown"); + } +} + + +//------------------------------------------------------------------------------ +bool ProcessInfoWidget_C::AddAuthInfo(RpcAuthInfo_T* pRpcAuthInfo) +{ + int Index; + + Index = pModel->rowCount(); + pModel->setRowCount(Index+1); + pModel->setData(pModel->index(Index, AuthInfoColumn_AuthSvc), (quint32)pRpcAuthInfo->AuthSvc ); + pModel->setData(pModel->index(Index, AuthInfoColumn_Name), QString::fromUtf16((const ushort*)pRpcAuthInfo->Name)); + pModel->setData(pModel->index(Index, AuthInfoColumn_Comment), QString::fromUtf16((const ushort*)pRpcAuthInfo->Comment)); + pModel->setData(pModel->index(Index, AuthInfoColumn_PrincipalName), QString::fromUtf16((const ushort*)pRpcAuthInfo->PrincipalName)); + return (true); +} + + +//------------------------------------------------------------------------------ +void ProcessInfoWidget_C::reset() +{ + pModel->setRowCount(0); +} + +//------------------------------------------------------------------------------ +void ProcessInfoWidget_C::resizeColumnsToContents() +{ + int Index; + + for( Index=0; Index < AuthInfoColumn_Last; Index++) + { + pAuthTreeView->resizeColumnToContents(Index); + } +} + + +//------------------------------------------------------------------------------ +ULONG ProcessInfoWidget_C::GetPid() +{ + return (this->Pid); +} + + +//------------------------------------------------------------------------------ +void ProcessInfoWidget_C::UpdateProcessInfo(RpcProcessInfo_T* pRpcProcessInfo) +{ + Version_T Version; + bool bEnable; + + if (pRpcProcessInfo==NULL) return; + + this->Pid = pRpcProcessInfo->Pid; + + pTabWidget->setTabEnabled(pTabWidget->indexOf(pImageWidget),true); + pTabWidget->setTabEnabled(pTabWidget->indexOf(pRpcWidget),pRpcProcessInfo->bIsServer); + + if (pRpcProcessInfo->SspCount != 0) pTabWidget->setTabEnabled(pTabWidget->indexOf(pAuthTreeView),true); + else pTabWidget->setTabEnabled(pTabWidget->indexOf(pAuthTreeView),false); + + Version.As64BitsValue = pRpcProcessInfo->Version; + + if ( pRpcProcessInfo->Path[0] == 0) bEnable=false; + else bEnable=true; + pPath->setEnabled(bEnable); + pPath->setText( QString::fromUtf16((const ushort*)pRpcProcessInfo->Path) ); + pPath->setToolTip( pPath->text() ); + pPath->setCursorPosition(0); + + if ( pRpcProcessInfo->CmdLine[0] == 0) bEnable=false; + else bEnable=true; + pCmdLine->setEnabled(bEnable); + pCmdLine->setText( QString::fromUtf16((const ushort*)pRpcProcessInfo->CmdLine) ); + pCmdLine->setToolTip( pCmdLine->text() ); + pCmdLine->setCursorPosition(0); + + if (pRpcProcessInfo->hIcon!=NULL) + { + pIconLabel->setPixmap( QPixmap::fromWinHICON( pRpcProcessInfo->hIcon ) ); + pIconLabel->show(); + DestroyIcon( pRpcProcessInfo->hIcon ); + } + else + { + pIconLabel->hide(); + } + + if ( pRpcProcessInfo->User[0] == 0) bEnable=false; + else bEnable=true; + pUser->setEnabled(bEnable); + pUser->setText( QString::fromUtf16((const ushort*)pRpcProcessInfo->User) ); + pCmdLine->setCursorPosition(0); + + pInterfaces->setText( QString("%1").arg(pRpcProcessInfo->InterfacesCount) ); + pEndpoints->setText( QString("%1").arg(pRpcProcessInfo->EndpointsCount) ); + if (pRpcProcessInfo->MaxCalls==RPC_C_LISTEN_MAX_CALLS_DEFAULT) pMaxCall->setText( "Default" ); + else pMaxCall->setText( QString("%1").arg(pRpcProcessInfo->MaxCalls) ); + /* + if (pRpcProcessInfo->bIsListening) pState->setText( "Listening" ); + else pState->setText( "Stopped" ); + */ + pName->setText( QString::fromUtf16((const ushort*)pRpcProcessInfo->Description) ); + if (pRpcProcessInfo->Desktop[0] == NULL) bEnable=false; + else bEnable=true; + pDesktop->setEnabled(bEnable); + pDesktop->setText( QString::fromUtf16((const ushort*)pRpcProcessInfo->Desktop) ); + pDesktop->setCursorPosition(0); + + pInCalls->setText( QString("%1").arg(pRpcProcessInfo->InCalls) ); + pOutCalls->setText( QString("%1").arg(pRpcProcessInfo->OutCalls) ); + pInPackets->setText( QString("%1").arg(pRpcProcessInfo->InPackets) ); + pOutPackets->setText( QString("%1").arg(pRpcProcessInfo->OutPackets) ); + + if (Version.As64BitsValue==0) pVersion->setText("Unknown"); + else pVersion->setText( QString("%4.%3.%2.%1").arg(Version.As16BitsValues.Part1).arg(Version.As16BitsValues.Part2).arg(Version.As16BitsValues.Part3).arg(Version.As16BitsValues.Part4) ); +#ifdef _WIN64 + if (pRpcProcessInfo->bIsWow64) pImage->setText( QString("32-bits") ); + else pImage->setText( QString("64-bits") ); +#else + pImage->setText( QString("32-bits") ); +#endif +} + + +//------------------------------------------------------------------------------ +void ProcessInfoWidget_C::AcceptVisitor(ViewVisitor_C* pVisitor) +{ + pVisitor->Visit(this); +} + + +//------------------------------------------------------------------------------ +ProcessInfoWidget_C::ProcessInfoWidget_C(QWidget* pParent):QDockWidget(WidgetName) +{ + setObjectName(WidgetName); + + pTabWidget = new QTabWidget(this); + pTabWidget->setMovable(true); + setWidget(pTabWidget); + // + // Creates the Image properties tab + // + QFormLayout* pImageLayout = new QFormLayout; + pImageWidget = new QWidget(this); + pIconLabel = new QLabel(this); + pVersion = new QLabel(this); + pName = new QLineEdit(this); + pUser = new QLineEdit(this); + pCmdLine = new QLineEdit(this); + pPath = new QLineEdit(this); + pDesktop = new QLineEdit(this); + pImage = new QLabel(this); + + pName->setFrame(false); + pName->setReadOnly(true); + pImageLayout->addRow(pIconLabel, pName); + pImageLayout->addRow("Version:", pVersion); + pImageLayout->addRow("Path:", pPath); + pPath->setReadOnly(true); + pPath->setEnabled(false); + pImageLayout->addRow("CmdLine:", pCmdLine); + pCmdLine->setReadOnly(true); + pCmdLine->setEnabled(false); + pImageLayout->addRow("User:", pUser); + pUser->setReadOnly(true); + pUser->setEnabled(false); + pImageLayout->addRow("Desktop:", pDesktop); + pDesktop->setReadOnly(true); + pDesktop->setEnabled(false); + pImageLayout->addRow("Image:", pImage); + + pImageWidget->setLayout(pImageLayout); + pTabWidget->insertTab(ProcessInfoTab_Image,pImageWidget,GetProcessInfoTabName(ProcessInfoTab_Image)); + // + // Creates the RPC properties tab + // + pRpcWidget = new QWidget(this); + QFormLayout* pRpcLayout = new QFormLayout; + //pState = new QLabel(this); + pMaxCall = new QLabel(this); + pEndpoints = new QLabel(this); + pInterfaces = new QLabel(this); + pInCalls = new QLabel(this); + pOutCalls = new QLabel(this); + pInPackets = new QLabel(this); + pOutPackets = new QLabel(this); + + pRpcLayout->addRow("Interfaces:", pInterfaces); + pRpcLayout->addRow("Endpoints:", pEndpoints); + //pRpcLayout->addRow("State:", pState); + pRpcLayout->addRow("MaxCalls:", pMaxCall); + + pRpcLayout->addRow("In Calls:", pInCalls); + pRpcLayout->addRow("Out Calls:", pOutCalls); + pRpcLayout->addRow("In Packets:", pInPackets); + pRpcLayout->addRow("Out Packets:", pOutPackets); + + pRpcWidget->setLayout(pRpcLayout); + pTabWidget->insertTab(ProcessInfoTab_RPC,pRpcWidget,GetProcessInfoTabName(ProcessInfoTab_RPC)); + // + // Creates the Security package properties tab + // + pProxyModel = new QSortFilterProxyModel; + pProxyModel->setDynamicSortFilter(true); + pProxyModel->setFilterKeyColumn(AuthInfoColumn_AuthSvc); + pProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + + pModel = new QStandardItemModel(0, AuthInfoColumn_Last, this); + + for(int i=0;isetHeaderData(i, Qt::Horizontal, GetAuthInfoColumnName( (AuthInfoColumn_T)i ) ); + } + + pAuthTreeView = new QTreeView; + pAuthTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); + pAuthTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); + pAuthTreeView->setSelectionMode(QAbstractItemView::SingleSelection); + pAuthTreeView->setRootIsDecorated(false); + pAuthTreeView->setSortingEnabled(true); + pAuthTreeView->setAnimated(true); + pAuthTreeView->setModel(pProxyModel); + pAuthTreeView->sortByColumn(AuthInfoColumn_AuthSvc, Qt::AscendingOrder); + + pProxyModel->setSourceModel(pModel); + pTabWidget->insertTab(ProcessInfoTab_SSP,pAuthTreeView,GetProcessInfoTabName(ProcessInfoTab_SSP)); + // + // By default: all tabs are disable + // + pTabWidget->setTabEnabled(pTabWidget->indexOf(pImageWidget),false); + pTabWidget->setTabEnabled(pTabWidget->indexOf(pRpcWidget),false); + pTabWidget->setTabEnabled(pTabWidget->indexOf(pAuthTreeView),false); +} \ No newline at end of file diff --git a/RpcView/ProcessInfoWidget.h b/RpcView/ProcessInfoWidget.h new file mode 100644 index 0000000..47d9f7b --- /dev/null +++ b/RpcView/ProcessInfoWidget.h @@ -0,0 +1,78 @@ +#ifndef _PROCESS_INFO_WIDGET_H_ +#define _PROCESS_INFO_WIDGET_H_ + +#include "..\Qt\Qt.h" +#include "..\RpcCore\RpcCore.h" +#include "View.h" + +/* +///GLOBAL/// +- Name +- Path +- CmdLine +- Current Directory +- Image 32/64 bits +- Description +- Icon +- Version +- Signed or not +- Parent +- User +... + +///RPC/// + - Authentication-Service & principal name (PROVIDER_INFO) + - number of interfaces + - number of endpoints + - max call + - is listening + - GetKeyFn and its Arg (see RpcServerRegisterAuthInfo) + ... +*/ + + +//------------------------------------------------------------------------------ +class ProcessInfoWidget_C : public QDockWidget, public View_I +{ + Q_OBJECT + +public: + ProcessInfoWidget_C(QWidget* pParent); + virtual void AcceptVisitor(ViewVisitor_C* pVisitor); + + bool AddAuthInfo(RpcAuthInfo_T* pRpcAuthInfo); + void UpdateProcessInfo(RpcProcessInfo_T* pRpcProcessInfo); + void resizeColumnsToContents(); + void reset(); + ULONG GetPid(); +private: + QLabel* pIconLabel; + QLineEdit* pCmdLine; + QLineEdit* pPath; + QLineEdit* pUser; + QLineEdit* pDesktop; + QLineEdit* pName; + QLabel* pImage; + QLabel* pEndpoints; + QLabel* pInterfaces; + QLabel* pMaxCall; + //QLabel* pState; + QLabel* pVersion; + QSortFilterProxyModel* pProxyModel; + QStandardItemModel* pModel; + + QTabWidget* pTabWidget; + //tabs + QWidget* pImageWidget; + QWidget* pRpcWidget; + QTreeView* pAuthTreeView; + + QLabel* pInCalls; + QLabel* pOutCalls; + QLabel* pInPackets; + QLabel* pOutPackets; + + ULONG Pid; +}; + +#endif// _PROCESS_INFO_WIDGET_H_ diff --git a/RpcView/ProcessSelectedVisitor.cpp b/RpcView/ProcessSelectedVisitor.cpp new file mode 100644 index 0000000..ba65b49 --- /dev/null +++ b/RpcView/ProcessSelectedVisitor.cpp @@ -0,0 +1,117 @@ +#include "ProcessSelectedVisitor.h" +#include "EndpointsWidget.h" +#include "InterfacesWidget.h" +#include "InterfaceInfoWidget.h" +#include "ProcessWidget.h" +#include "ProcessInfoWidget.h" +#include "ProceduresWidget.h" +#include "../RpcCommon/Misc.h" + +typedef struct _EnumCtxt_T{ + ProcessInfoWidget_C* pProcessInfoWidget; +}EnumCtxt_T; + +//------------------------------------------------------------------------------ +ProcessSelectedVisitor_C::ProcessSelectedVisitor_C(quint32 Pid,RpcCore_T* pRpcCore,void* pRpcCoreCtxt) +{ + this->Pid = Pid; + this->pRpcCore = pRpcCore; + this->pRpcCoreCtxt = pRpcCoreCtxt; + + pRpcProcessInfo = pRpcCore->RpcCoreGetProcessInfoFn(pRpcCoreCtxt, Pid, INVALID_PID_VALUE, RPC_PROCESS_INFO_ALL); +} + + +//------------------------------------------------------------------------------ +ProcessSelectedVisitor_C::~ProcessSelectedVisitor_C() +{ + pRpcCore->RpcCoreFreeProcessInfoFn(pRpcCoreCtxt, pRpcProcessInfo); +} + + +//------------------------------------------------------------------------------ +void ProcessSelectedVisitor_C::Visit(EndpointsWidget_C* pEndpointsWidget) +{ + //Apply process filter + pEndpointsWidget->ApplyProcessFilter(Pid); + this->NbOfEndpoints = pEndpointsWidget->GetEndpoints(); +} + + +//------------------------------------------------------------------------------ +void ProcessSelectedVisitor_C::Visit(InterfacesWidget_C* pInterfacesWidget) +{ + //Apply process filter + pInterfacesWidget->ApplyProcessFilter(Pid); + this->NbOfInterfaces = pInterfacesWidget->GetInterfaces(); +} + + +//------------------------------------------------------------------------------ +void ProcessSelectedVisitor_C::Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget) +{ + if (this->Pid!=pInterfaceInfoWidget->GetPid()) + { + pInterfaceInfoWidget->Reset(); + } +} + + +//------------------------------------------------------------------------------ +BOOL __fastcall EnumProcessAuth(DWORD Pid, RpcAuthInfo_T* pRpcAuthInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + UNREFERENCED_PARAMETER(Pid); + UNREFERENCED_PARAMETER(pbContinue); + + pEnumCtxt->pProcessInfoWidget->AddAuthInfo(pRpcAuthInfo); + return (TRUE); +} + + +//------------------------------------------------------------------------------ +void ProcessSelectedVisitor_C::Visit(ProcessInfoWidget_C* pProcessInfoWidget) +{ + EnumCtxt_T EnumCtxt; + + EnumCtxt.pProcessInfoWidget = pProcessInfoWidget; + + pProcessInfoWidget->UpdateProcessInfo( pRpcProcessInfo ); + pProcessInfoWidget->reset(); //for authinfo + pRpcCore->RpcCoreEnumProcessAuthInfoFn(pRpcCoreCtxt, pRpcProcessInfo->Pid,(RpcCoreEnumProcessAuthInfoCallbackFn_T)&EnumProcessAuth,&EnumCtxt); +} + +//------------------------------------------------------------------------------ +void ProcessSelectedVisitor_C::Visit(ProceduresWidget_C* pProceduresWidget) +{ + if (pProceduresWidget->GetPid() != this->Pid ) + { + pProceduresWidget->reset(this->Pid); + } +} + +//------------------------------------------------------------------------------ +void ProcessSelectedVisitor_C::Visit(ProcessWidget_C* pProcessWidget) +{ + this->NbOfProcesses = pProcessWidget->GetProcesses(); +} + + +//------------------------------------------------------------------------------ +ULONG ProcessSelectedVisitor_C::GetEndpoints() +{ + return (this->NbOfEndpoints); +} + + +//------------------------------------------------------------------------------ +ULONG ProcessSelectedVisitor_C::GetInterfaces() +{ + return (this->NbOfInterfaces); +} + + +//------------------------------------------------------------------------------ +ULONG ProcessSelectedVisitor_C::GetProcesses() +{ + return (this->NbOfProcesses); +} diff --git a/RpcView/ProcessSelectedVisitor.h b/RpcView/ProcessSelectedVisitor.h new file mode 100644 index 0000000..af4e191 --- /dev/null +++ b/RpcView/ProcessSelectedVisitor.h @@ -0,0 +1,33 @@ +#ifndef _PROCESS_SELECTED_VISITOR_H_ +#define _PROCESS_SELECTED_VISITOR_H_ + +#include "../Qt/Qt.h" +#include "ViewVisitor.h" +#include "..\RpcCore\RpcCore.h" + +//------------------------------------------------------------------------------ +class ProcessSelectedVisitor_C : public ViewVisitor_C +{ +private: + RpcProcessInfo_T* pRpcProcessInfo; + RpcCore_T* pRpcCore; + void* pRpcCoreCtxt; + ULONG NbOfEndpoints; + ULONG NbOfProcesses; + ULONG NbOfInterfaces; + quint32 Pid; +public: + ProcessSelectedVisitor_C(quint32 Pid,RpcCore_T* pRpcCore,void* pRpcCoreCtxt); + ProcessSelectedVisitor_C::~ProcessSelectedVisitor_C(); + ULONG GetEndpoints(); + ULONG GetInterfaces(); + ULONG GetProcesses(); + virtual void Visit(EndpointsWidget_C* pEndpointsWidget); + virtual void Visit(InterfacesWidget_C* pInterfacesWidget); + virtual void Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget); + virtual void Visit(ProcessInfoWidget_C* pProcessInfoWidget); + virtual void Visit(ProceduresWidget_C* pProceduresWidget); + virtual void Visit(ProcessWidget_C* pProcessWidget); +}; + +#endif \ No newline at end of file diff --git a/RpcView/ProcessWidget.cpp b/RpcView/ProcessWidget.cpp new file mode 100644 index 0000000..272fe73 --- /dev/null +++ b/RpcView/ProcessWidget.cpp @@ -0,0 +1,559 @@ +#include "ProcessWidget.h" + +static const char WidgetName[] = "Processes"; + +//------------------------------------------------------------------------------ +QString ProcessWidget_C::GetColumName(Column_T Column) +{ + switch(Column) + { + case Column_Name : return (QString("Name")); + case Column_Pid : return (QString("Pid")); + case Column_Path : return (QString("Path")); + case Column_Description : return (QString("Description")); + case Column_CmdLine : return (QString("CmdLine")); + case Column_UserName : return (QString("User")); + case Column_Desktop : return (QString("Desktop")); + case Column_IsRpcServer : return (QString("RpcServer")); + //case Column_IsListening : return (QString("Listening")); +#ifdef _WIN64 + case Column_IsWow64 : return (QString("Image")); +#endif + case Column_MaxCalls : return (QString("MaxCalls")); + default: return (QString("Unknown")); + } +} + +//------------------------------------------------------------------------------ +ULONG ProcessWidget_C::GetProcesses() +{ + return ( pProxyModel->rowCount() ); +} + + +//------------------------------------------------------------------------------ +ULONG ProcessWidget_C::GetTotalProcesses() +{ + return ( pModel->rowCount() ); +} + +//------------------------------------------------------------------------------ +void ProcessWidget_C::resizeColumnsToContents() +{ + int Index; + + for( Index=0; Index < Column_Last; Index++) + { + pProcessTree->resizeColumnToContents(Index); + pProcessView->resizeColumnToContents(Index); + } +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::SelectProcess(quint32 Pid) +{ + QList TreeItemList; + QList ViewItemList; + + TreeItemList= pProcessTree->findItems( QString("%1").arg(Pid), Qt::MatchFixedString|Qt::MatchRecursive, Column_Pid); + if (!TreeItemList.isEmpty()) + { + pProcessTree->setCurrentItem( TreeItemList.first() ); + pProcessTree->scrollToItem( TreeItemList.first() ); + } + ViewItemList = pModel->findItems( QString("%1").arg(Pid), Qt::MatchFixedString, Column_Pid); + if (!ViewItemList.isEmpty()) + { + QModelIndex ModelIndex = pProxyModel->mapFromSource( ViewItemList.first()->index() ); + pProcessView->selectionModel()->select( ModelIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + pProcessView->scrollTo( ModelIndex ); + } + pFilterWidget->Reset(); + this->ApplyUserFilter(""); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::SnapProcesses() +{ + PrivateTreeItemList = pProcessTree->findItems(".*", Qt::MatchRegExp|Qt::MatchRecursive, Column_Pid); + PrivateViewItemList = pModel->findItems(".*", Qt::MatchRegExp, Column_Pid); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::RemoveTerminatedProcesses() +{ + QTreeWidgetItem* pParent; + // + // Remove processes from the TreeWidget + // 1. Only child processes + // + for (auto Iter=PrivateTreeItemList.begin();Iter!=PrivateTreeItemList.end();Iter++) + { + if (*Iter!=NULL) + { + pParent = (*Iter)->parent(); + if (pParent != NULL) pParent->removeChild(*Iter); + } + } + // + // 2. Parent processes + // + for (auto Iter = PrivateTreeItemList.begin(); Iter != PrivateTreeItemList.end(); Iter++) + { + if (*Iter != NULL) + { + pParent = (*Iter)->parent(); + if (pParent == NULL) delete *Iter; + } + } + // + // Remove processes from the TreeView + // + for (auto Iter=PrivateViewItemList.begin();Iter!=PrivateViewItemList.end();Iter++) + { + if (*Iter!=NULL) pModel->removeRow( (*Iter)->row()); + } +} + + +//------------------------------------------------------------------------------ +bool ProcessWidget_C::IsProcessPresent(quint32 Pid) +{ + QList TreeItemList; + QList ViewItemList; + bool bProcessPresent = false; + + TreeItemList = pProcessTree->findItems( QString("%1").arg(Pid), Qt::MatchFixedString|Qt::MatchRecursive, Column_Pid); + if (TreeItemList.isEmpty()) goto End; + + PrivateTreeItemList.removeOne(TreeItemList.first()); + + ViewItemList = pModel->findItems( QString("%1").arg(Pid), Qt::MatchFixedString, Column_Pid); + if (ViewItemList.isEmpty()) goto End; + + PrivateViewItemList.removeOne(ViewItemList.first()); + bProcessPresent = true; +End: + return (bProcessPresent); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::ProcessSelected(QTreeWidgetItem* pItem, int Column) +{ + quint32 Pid; + + Pid = pItem->data(Column_Pid,0).toInt(); + emit ProcessSelected(Pid); +} + +//------------------------------------------------------------------------------ +void ProcessWidget_C::ProcessSelected(const QModelIndex& Index) +{ + quint32 Pid; + + Pid = pProxyModel->data( pProxyModel->index(Index.row(), Column_Pid) ).toUInt(); + emit ProcessSelected(Pid); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::SetRowColor(QTreeWidgetItem* pProcess,int Index,const QColor& Color) +{ + for (int i=0;isetBackground(i, QBrush(Color) ); + pModel->setData(pModel->index(Index,i), QBrush(Color), Qt::BackgroundRole); + } +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::UpdateProcess(RpcProcessInfo_T* pRpcProcessInfo) +{ + QList TreeItemList; + QList ViewItemList; + QTreeWidgetItem* pProcess; + int Index; + + if (pRpcProcessInfo->bIsServer) + { + TreeItemList = pProcessTree->findItems( QString("%1").arg(pRpcProcessInfo->Pid), Qt::MatchFixedString|Qt::MatchRecursive, Column_Pid); + if (TreeItemList.isEmpty()) return; + + ViewItemList = pModel->findItems( QString("%1").arg(pRpcProcessInfo->Pid), Qt::MatchFixedString, Column_Pid); + if (ViewItemList.isEmpty()) return; + + pProcess= TreeItemList.first(); + if (pProcess==NULL) return; + + Index = ViewItemList.first()->row(); + + if ( pRpcProcessInfo->MaxCalls == RPC_C_LISTEN_MAX_CALLS_DEFAULT) + { + AddProcessItem( pProcess, Index, Column_MaxCalls, Qt::DisplayRole, QString("Default") ); + } + else + { + AddProcessItem( pProcess, Index, Column_MaxCalls, Qt::DisplayRole, (quint32)pRpcProcessInfo->MaxCalls ); + } + //-- + AddProcessItem( pProcess, Index, Column_IsRpcServer, Qt::DisplayRole, true ); + + switch(pRpcProcessInfo->RpcProcessType) + { + case RpcProcessType_RPC: + SetRowColor(pProcess,Index,QColor(200, 200, 255, 180)); + break; + //-- + case RpcProcessType_DCOM: + SetRowColor(pProcess,Index,QColor(255, 255, 200, 180)); + //SetRowColor(pProcess, Index, QColor(200, 200, 255, 180)); + break; + //-- + case RpcProcessType_HYBRID: + //SetRowColor(pProcess,Index,QColor(255, 200, 200, 180)); + SetRowColor(pProcess, Index, QColor(200, 200, 255, 180)); + break; + //-- + default: + break; + } + } +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::AddProcessItem(QTreeWidgetItem* pProcess,int Index, Column_T Column, Qt::ItemDataRole Role,const QVariant& Value) +{ + pProcess->setData( Column, Role, Value ); + pModel->setData(pModel->index(Index, Column), Value, Role ); +} + + +//------------------------------------------------------------------------------ +bool ProcessWidget_C::AddProcess(RpcProcessInfo_T* pRpcProcessInfo) +{ + QList ParentList; + QTreeWidgetItem* pParent = NULL; + QTreeWidgetItem* pProcess; + int Index; + + Index = pModel->rowCount(); + pModel->setRowCount(Index+1); + + pProcess = new QTreeWidgetItem; + + if ( pRpcProcessInfo->hIcon!=NULL ) + { + AddProcessItem(pProcess,Index,Column_Name, Qt::DecorationRole, QIcon( QPixmap::fromWinHICON( pRpcProcessInfo->hIcon ) ) ); + DestroyIcon( pRpcProcessInfo->hIcon ); + } + + if (pRpcProcessInfo->Pid == 0) + { + AddProcessItem(pProcess,Index,Column_Name, Qt::DisplayRole, QString("[System Idle Process]") ); + AddProcessItem(pProcess,Index,Column_Pid, Qt::DisplayRole, (quint32) pRpcProcessInfo->Pid ); + pProcessTree->addTopLevelItem(pProcess); + return true; + } + AddProcessItem(pProcess,Index,Column_Name, Qt::DisplayRole, QString::fromUtf16((const ushort*)pRpcProcessInfo->Name) ); + + AddProcessItem( + pProcess, + Index, + Column_Name, + Qt::ToolTipRole, + QString("Path:\n").append(QString::fromUtf16((const ushort*)pRpcProcessInfo->Path)).append("\nCmdLine:\n").append(QString::fromUtf16((const ushort*)pRpcProcessInfo->CmdLine)) + ); + + AddProcessItem(pProcess,Index,Column_Pid, Qt::DisplayRole, (quint32) pRpcProcessInfo->Pid ); + AddProcessItem(pProcess,Index,Column_UserName, Qt::DisplayRole, QString::fromUtf16((const ushort*)pRpcProcessInfo->User) ); + AddProcessItem(pProcess,Index,Column_Path, Qt::DisplayRole, QString::fromUtf16((const ushort*)pRpcProcessInfo->Path) ); + AddProcessItem(pProcess,Index,Column_Description, Qt::DisplayRole, QString::fromUtf16((const ushort*)pRpcProcessInfo->Description) ); + AddProcessItem(pProcess,Index,Column_CmdLine, Qt::DisplayRole, QString::fromUtf16((const ushort*)pRpcProcessInfo->CmdLine) ); + AddProcessItem(pProcess,Index,Column_Desktop, Qt::DisplayRole, QString::fromUtf16((const ushort*)pRpcProcessInfo->Desktop) ); +#ifdef _WIN64 + if (pRpcProcessInfo->bIsWow64) AddProcessItem(pProcess,Index,Column_IsWow64, Qt::DisplayRole, QString("32-bit") ); + else AddProcessItem(pProcess,Index,Column_IsWow64, Qt::DisplayRole, QString("64-bit") ); +#endif + + QList ItemList; + + ItemList = pProcessTree->findItems( QString("%1").arg(pRpcProcessInfo->ParentPid), Qt::MatchFixedString|Qt::MatchRecursive, Column_Pid); + if (!ItemList.isEmpty()) + { + pParent = ItemList.first(); + pParent->addChild(pProcess); + pProcessTree->expandItem(pParent); + } + else + { + pProcessTree->addTopLevelItem(pProcess); + } + // + // Add warning: when a non rpc server is selected -> view all endpoints and interfaces of the system + // + if (!pRpcProcessInfo->bIsServer) + { + for(int i=0;isetStatusTip(i,"WARNING: view all the system endpoints and interfaces."); + } + } + UpdateProcess(pRpcProcessInfo); + return (true); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::AcceptVisitor(ViewVisitor_C* pVisitor) +{ + pVisitor->Visit(this); +} + +//------------------------------------------------------------------------------ +void ProcessWidget_C::Reset() +{ + pProcessTree->clear(); + pProcessView->reset(); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::SaveConfiguration(QSettings* pSettings) +{ + pSettings->setValue("Processes/View/geometry",pProcessView->header()->saveState()); + pSettings->setValue("Processes/Tree/geometry",pProcessTree->header()->saveState()); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::LoadConfiguration(QSettings* pSettings) +{ + pProcessView->header()->restoreState( pSettings->value("Processes/View/geometry").toByteArray() ); + pProcessTree->header()->restoreState( pSettings->value("Processes/Tree/geometry").toByteArray() ); + // + // Force Tree sorting by PID + // + pProcessTree->sortByColumn(Column_Pid); + pProcessTree->sortByColumn(-1); +} + +//------------------------------------------------------------------------------ +void ProcessWidget_C::InitProcessTreeWidget(QWidget* pParent) +{ + pProcessTree = new QTreeWidget(this); + + QTreeWidgetItem* pHeaderItem = pProcessTree->headerItem(); + for (quint32 Idx = 0; Idx < Column_Last; Idx++) + { + pHeaderItem->setText( Idx, GetColumName((Column_T)Idx) ); + } + pProcessTree->setColumnCount(Column_Last); + pProcessTree->sortByColumn(Column_Pid); + pProcessTree->sortByColumn(-1); + pProcessTree->setAnimated(true); + pProcessTree->setSortingEnabled(true); + + pProcessTree->expandAll(); + pProcessTree->setRootIsDecorated(false); + pProcessTree->setMouseTracking(true); + + pProcessTree->hideColumn(Column_IsRpcServer); + pProcessTree->hideColumn(Column_Desktop); + + connect( pProcessTree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(ProcessSelected(QTreeWidgetItem*, int))); + connect( pProcessTree, SIGNAL(itemPressed(QTreeWidgetItem*, int)), this, SLOT(ProcessSelected(QTreeWidgetItem*, int))); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::InitProcessTreeView(QWidget* pParent) +{ + pProxyModel = new QSortFilterProxyModel(this); + pProxyModel->setDynamicSortFilter(true); + pProxyModel->setFilterKeyColumn(Column_Pid); + pProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + + pModel = new QStandardItemModel(0, Column_Last, this); + + for(uint i=0;isetHeaderData(i, Qt::Horizontal, GetColumName((Column_T)i) ); + } + + pProcessView = new QTreeView(this); + pProcessView->setEditTriggers(QAbstractItemView::NoEditTriggers); + pProcessView->setSelectionBehavior(QAbstractItemView::SelectRows); + pProcessView->setSelectionMode(QAbstractItemView::SingleSelection); + pProcessView->setRootIsDecorated(false); + pProcessView->setSortingEnabled(true); + pProcessView->setAlternatingRowColors(true); + pProcessView->setAnimated(true); + pProcessView->setModel(pProxyModel); + pProcessView->sortByColumn(Column_Pid, Qt::AscendingOrder); + + pProcessView->hideColumn(Column_IsRpcServer); + pProcessView->hideColumn(Column_Desktop); + + pProxyModel->setSourceModel(pModel); + connect( pProcessView, SIGNAL(pressed(const QModelIndex&)), this, SLOT(ProcessSelected(const QModelIndex&))); + connect( pProcessView, SIGNAL(activated(const QModelIndex&)), this, SLOT(ProcessSelected(const QModelIndex&))); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::UpdateUserFilter() +{ + if (pFilterWidget->GetText()!="") ApplyUserFilter( pFilterWidget->GetText() ); +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::ApplyUserFilter(const QString & FilterText) +{ + QRegExp FilterRegExp; + + FilterRegExp.setPattern( FilterText ); + FilterRegExp.setCaseSensitivity( Qt::CaseInsensitive ); + + pProxyModel->setFilterKeyColumn(-1); //filter all columns: UGLY Qt + pProxyModel->setFilterRegExp( FilterRegExp ); + + if ( pProxyModel->rowCount()==pModel->rowCount() ) + { + // + // In case of view switching, we have to update the selected process in the other view! + // + if ( (pStackedWidget->currentWidget()!=pProcessTree) && + (pProcessTree->header()->sortIndicatorSection()==-1) ) + { + pStackedWidget->setCurrentWidget(pProcessTree); + pProcessTree->header()->restoreState(pProcessView->header()->saveState()); + } + else + { + pProxyModel->setFilterRegExp( QRegExp(".*") ); + } + } + else + { + if (pStackedWidget->currentWidget()!=pProcessView) + { + pStackedWidget->setCurrentWidget(pProcessView); + pProcessView->header()->restoreState(pProcessTree->header()->saveState()); + } + } +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::CreateColumnsSelectionWidget() +{ + pColumnsSelectionWidget = new QGroupBox(WidgetName,this); + QVBoxLayout* pLayout = new QVBoxLayout(pColumnsSelectionWidget); + + for (int i = 0; i < Column_Last; i++) + { + CheckBoxArray[i] = new QCheckBox(GetColumName((Column_T)i), pColumnsSelectionWidget); + pLayout->addWidget(CheckBoxArray[i]); + } + pLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + pColumnsSelectionWidget->setLayout(pLayout); +} + + +//------------------------------------------------------------------------------ +QWidget* ProcessWidget_C::GetColumnsSelectionWidget() +{ + for (int i = 0; i < Column_Last; i++) + { + CheckBoxArray[i]->setChecked(!pProcessTree->header()->isSectionHidden(i)); + } + return pColumnsSelectionWidget; +} + + +//------------------------------------------------------------------------------ +void ProcessWidget_C::UpdateColumnsVisibility() +{ + for (int i = 0; i < Column_Last; i++) + { + pProcessTree->header()->setSectionHidden(i, !CheckBoxArray[i]->isChecked() ); + pProcessView->header()->setSectionHidden(i, !CheckBoxArray[i]->isChecked()); + } +} + + +//------------------------------------------------------------------------------ +// Switch to the view header +void ProcessWidget_C::TreeHeaderClicked(int logicalIndex) +{ + if (pStackedWidget->currentWidget()!=pProcessView) + { + pStackedWidget->setCurrentWidget(pProcessView); + pProcessView->header()->restoreState(pProcessTree->header()->saveState()); + pProcessView->scrollTo(pProcessView->currentIndex()); + } +} + + +//------------------------------------------------------------------------------ +// Switch to the Tree after ascending and descending order +void ProcessWidget_C::ViewHeaderClicked(int logicalIndex) +{ + if (logicalIndex!=Column_Name) return; + + if (pProcessView->header()->sortIndicatorOrder() == Qt::DescendingOrder) return; + + if (pStackedWidget->currentWidget()!=pProcessTree) + { + pFilterWidget->Reset(); + ApplyUserFilter(""); + + pStackedWidget->setCurrentWidget(pProcessTree); + pProcessTree->header()->restoreState(pProcessView->header()->saveState()); + pProcessTree->sortByColumn(Column_Pid); + pProcessTree->sortByColumn(-1); + pProcessTree->scrollToItem(pProcessTree->currentItem()); + } +} + + +//------------------------------------------------------------------------------ +ProcessWidget_C::ProcessWidget_C(QWidget* pParent):QGroupBox(WidgetName) +{ + QGridLayout* pGridLayout; + + setObjectName(WidgetName); + + pStackedWidget = new QStackedWidget(this); + pGridLayout = new QGridLayout(this); + + InitProcessTreeWidget(pParent); + InitProcessTreeView(pParent); + pProcessView->header()->installEventFilter(pParent); + pProcessTree->header()->installEventFilter(pParent); + + pStackedWidget->addWidget(pProcessTree); + pStackedWidget->addWidget(pProcessView); + // + // Add user filtering (CTL+F) support + // + pFilterWidget = new FilterWidget_C(this); + + pGridLayout->addWidget(pStackedWidget,0,0); + pGridLayout->addWidget(pFilterWidget,1,0); + setLayout(pGridLayout); + connect( this, SIGNAL(ProcessSelected(quint32)), pParent, SLOT(ProcessSelected(quint32)) ); + connect( pProcessTree->header(),SIGNAL(sectionClicked(int)), this , SLOT(TreeHeaderClicked(int) )); + connect( pProcessView->header(),SIGNAL(sectionClicked(int)), this , SLOT(ViewHeaderClicked(int) )); + // + // Create the Widget for column selection + // + CreateColumnsSelectionWidget(); +} diff --git a/RpcView/ProcessWidget.h b/RpcView/ProcessWidget.h new file mode 100644 index 0000000..df7b493 --- /dev/null +++ b/RpcView/ProcessWidget.h @@ -0,0 +1,87 @@ +#ifndef _PROCESS_WIDGET_H_ +#define _PROCESS_WIDGET_H_ + +#include "..\Qt\Qt.h" +#include "..\RpcCommon\RpcView.h" +#include "..\RpcCore\RpcCore.h" +#include "View.h" +#include "FilterWidget.h" + + +//------------------------------------------------------------------------------ +class ProcessWidget_C : public QGroupBox, public View_I +{ + Q_OBJECT + +public: + + typedef enum { + Column_Name, + Column_Pid, + Column_Path, + Column_Description, +#ifdef _WIN64 + Column_IsWow64, +#endif + Column_UserName, + Column_CmdLine, + Column_Desktop, + Column_IsRpcServer, + //Column_IsListening, + Column_MaxCalls, + Column_Last, + }Column_T; + + ProcessWidget_C(QWidget* pParent); + virtual void AcceptVisitor(ViewVisitor_C* pVisitor); + void resizeColumnsToContents(); + void SelectProcess(quint32 Pid); + void SnapProcesses(); + void RemoveTerminatedProcesses(); + bool IsProcessPresent(quint32 Pid); + bool AddProcess(RpcProcessInfo_T* pRpcProcessInfo); + void UpdateProcess(RpcProcessInfo_T* pRpcProcessInfo); + void Reset(); + ULONG GetProcesses(); + ULONG GetTotalProcesses(); + void UpdateUserFilter(); + void SaveConfiguration(QSettings*); + void LoadConfiguration(QSettings*); + QWidget* GetColumnsSelectionWidget(); + void UpdateColumnsVisibility(); + +private slots: + void ProcessSelected(QTreeWidgetItem*, int); + void ProcessSelected(const QModelIndex&); + void ApplyUserFilter(const QString &); + +signals: + void ProcessSelected(quint32); + +public slots: + void TreeHeaderClicked(int logicalIndex); + void ViewHeaderClicked(int logicalIndex); + +private: + QGridLayout* pGridLayout; + QStackedWidget* pStackedWidget; + QTreeWidget* pProcessTree; + QTreeView* pProcessView; + QSortFilterProxyModel* pProxyModel; + QStandardItemModel* pModel; + QList PrivateTreeItemList; + QList PrivateViewItemList; + FilterWidget_C* pFilterWidget; + //-- + QGroupBox* pColumnsSelectionWidget; + QCheckBox* CheckBoxArray[Column_Last]; + + void SetRowColor(QTreeWidgetItem* pProcess,int Index,const QColor& Color); + void InitProcessTreeWidget(QWidget* pParent); + void InitProcessTreeView(QWidget* pParent); + void AddProcessItem(QTreeWidgetItem* pProcess,int Index, Column_T Column, Qt::ItemDataRole Role,const QVariant& Value); + void CreateColumnsSelectionWidget(); + QString GetColumName(Column_T ProcessWigetColumn); +}; + +#endif// _PROCESS_WIDGET_H_ diff --git a/RpcView/RefreshVisitor.cpp b/RpcView/RefreshVisitor.cpp new file mode 100644 index 0000000..27279d7 --- /dev/null +++ b/RpcView/RefreshVisitor.cpp @@ -0,0 +1,250 @@ +#include "InterfaceSelectedVisitor.h" +#include "EndpointsWidget.h" +#include "InterfacesWidget.h" +#include "InterfaceInfoWidget.h" +#include "ProcessWidget.h" +#include "ProcessInfoWidget.h" +#include "ProceduresWidget.h" +#include "RefreshVisitor.h" +#include "../RpcCommon/Misc.h" +#include "Pdb.h" +#include + + +typedef struct _EnumCtxt_T{ + RefreshVisitor_C* pRefreshVisitor; + EndpointsWidget_C* pEndpointsWidget; + InterfacesWidget_C* pInterfacesWidget; + RpcCore_T* pRpcCore; + VOID* pRpcCoreCtxt; +}EnumCtxt_T; + + +//------------------------------------------------------------------------------ +static BOOL WINAPI EnumProc(DWORD Pid, DWORD Ppid, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + ProcessEntry_C* pProcessEntry = new ProcessEntry_C(Ppid,Pid); + + pEnumCtxt->pRefreshVisitor->ProcessVector.push_back(pProcessEntry); + return (TRUE); +} + +//------------------------------------------------------------------------------ +RefreshVisitor_C::RefreshVisitor_C(RpcCore_T* pRpcCore,void* pRpcCoreCtxt) +{ + EnumCtxt_T EnumCtxt; + + this->pRpcCore = pRpcCore; + this->pRpcCoreCtxt = pRpcCoreCtxt; + + this->NumberOfEndpoints = 0; + this->NumberOfInterfaces = 0; + + EnumCtxt.pRefreshVisitor = this; + EnumProcess( (EnumProcessCallbackFn_T)&EnumProc, &EnumCtxt ); +} + + +//------------------------------------------------------------------------------ +ULONG RefreshVisitor_C::GetEndpoints() +{ + return (this->NumberOfEndpoints); +} + + +//------------------------------------------------------------------------------ +ULONG RefreshVisitor_C::GetInterfaces() +{ + return (this->NumberOfInterfaces); +} + + +//------------------------------------------------------------------------------ +ULONG RefreshVisitor_C::GetProcesses() +{ + return (this->NumberOfProcesses); +} + +//------------------------------------------------------------------------------ +ULONG RefreshVisitor_C::GetTotalEndpoints() +{ + return (this->TotalEndpoints); +} + +//------------------------------------------------------------------------------ +ULONG RefreshVisitor_C::GetTotalInterfaces() +{ + return (this->TotalInterfaces); +} + +//------------------------------------------------------------------------------ +ULONG RefreshVisitor_C::GetTotalProcesses() +{ + return (this->TotalProcesses); +} + +//------------------------------------------------------------------------------ +RefreshVisitor_C::~RefreshVisitor_C() +{ + for (UINT32 i = 0; i < ProcessVector.size(); i++) + { + delete ProcessVector[i]; + } + ProcessVector.clear(); +} + + +//------------------------------------------------------------------------------ +static BOOL __fastcall EnumEndpoints(DWORD Pid, RpcEndpointInfo_T* pRpcEndpointInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + UNREFERENCED_PARAMETER(pbContinue); + + if (!pEnumCtxt->pEndpointsWidget->IsEndpointsPresent(Pid,pRpcEndpointInfo->pName,pRpcEndpointInfo->pProtocole)) + { + pEnumCtxt->pEndpointsWidget->AddEndpoint(Pid, pRpcEndpointInfo ); + } + return (TRUE); +} + + +//------------------------------------------------------------------------------ +void RefreshVisitor_C::Visit(EndpointsWidget_C* pEndpointsWidget) +{ + EnumCtxt_T EnumCtxt; + std::vector::iterator Iter; + + pEndpointsWidget->SnapEndpoint(); + + EnumCtxt.pRefreshVisitor = this; + EnumCtxt.pEndpointsWidget = pEndpointsWidget; + for (Iter=ProcessVector.begin();Iter!=ProcessVector.end();Iter++) + { + if (*Iter!=NULL) + { + pRpcCore->RpcCoreEnumProcessEndpointsFn( + pRpcCoreCtxt, + (*Iter)->Pid, + (RpcCoreEnumProcessEndpointsCallbackFn_T) &EnumEndpoints, + &EnumCtxt); + } + } + pEndpointsWidget->RemoveUnregisteredEndpoints(); + pEndpointsWidget->UpdateUserFilter(); + this->NumberOfEndpoints = pEndpointsWidget->GetEndpoints(); + this->TotalEndpoints = pEndpointsWidget->GetTotalEndpoints(); +} + + +//------------------------------------------------------------------------------ +static BOOL __fastcall EnumInterfaces(RpcInterfaceInfo_T* pRpcInterfaceInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + UNREFERENCED_PARAMETER(pbContinue); + RpcInterfaceInfo_T* pRpcInterfaceInfoFull = NULL; + + if (!pEnumCtxt->pInterfacesWidget->IsInterfacePresent(pRpcInterfaceInfo->Pid,&pRpcInterfaceInfo->If)) + { + pRpcInterfaceInfoFull = pEnumCtxt->pRpcCore->RpcCoreGetInterfaceInfoFn(pEnumCtxt->pRpcCoreCtxt,pRpcInterfaceInfo->Pid,&pRpcInterfaceInfo->If,RPC_INTERFACE_INFO_ALL); + if (pRpcInterfaceInfoFull!=NULL) + { + pEnumCtxt->pInterfacesWidget->AddInterfaces(pRpcInterfaceInfoFull); + pEnumCtxt->pRpcCore->RpcCoreFreeInterfaceInfoFn(pEnumCtxt->pRpcCoreCtxt,pRpcInterfaceInfoFull); + } + } + return (TRUE); +} + + +//------------------------------------------------------------------------------ +void RefreshVisitor_C::Visit(InterfacesWidget_C* pInterfacesWidget) +{ + EnumCtxt_T EnumCtxt; + std::vector::iterator Iter; + + pInterfacesWidget->SnapInterfaces(); + + EnumCtxt.pRefreshVisitor = this; + EnumCtxt.pInterfacesWidget = pInterfacesWidget; + EnumCtxt.pRpcCoreCtxt = this->pRpcCoreCtxt; + EnumCtxt.pRpcCore = this->pRpcCore; + for (Iter=ProcessVector.begin();Iter!=ProcessVector.end();Iter++) + { + if (*Iter!=NULL) + { + pRpcCore->RpcCoreEnumProcessInterfacesFn( + pRpcCoreCtxt, + (*Iter)->Pid, + (RpcCoreEnumProcessInterfacesCallbackFn_T) &EnumInterfaces, + &EnumCtxt, + RPC_INTERFACE_INFO_DEFAULT); + } + } + pInterfacesWidget->RemoveUnregisteredInterfaces(); + pInterfacesWidget->UpdateUserFilter(); + this->NumberOfInterfaces = pInterfacesWidget->GetInterfaces(); + this->TotalInterfaces = pInterfacesWidget->GetTotalInterfaces(); +} + + +//------------------------------------------------------------------------------ +void RefreshVisitor_C::Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget) +{ + //nothing to do here +} + + +//------------------------------------------------------------------------------ +void RefreshVisitor_C::Visit(ProcessInfoWidget_C* pProcessInfoWidget) +{ + RpcProcessInfo_T* pRpcProcessInfo = NULL; + + pRpcProcessInfo = pRpcCore->RpcCoreGetProcessInfoFn(pRpcCoreCtxt,pProcessInfoWidget->GetPid(),0,RPC_PROCESS_INFO_ALL); + if (pRpcProcessInfo!=NULL) + { + pProcessInfoWidget->UpdateProcessInfo(pRpcProcessInfo); + pRpcCore->RpcCoreFreeProcessInfoFn(pRpcCoreCtxt,pRpcProcessInfo); + } +} + + +//------------------------------------------------------------------------------ +void RefreshVisitor_C::Visit(ProceduresWidget_C* pProceduresWidget) +{ + //nothing to do +} + + +//------------------------------------------------------------------------------ +void RefreshVisitor_C::Visit(ProcessWidget_C* pProcessWidget) +{ + std::vector::iterator Iter; + RpcProcessInfo_T* pRpcProcessInfo = NULL; + BOOL bWow64; + bool bIsProcessPresent; + ULONG ProcessInfoMask; + + pProcessWidget->SnapProcesses(); + + for (Iter=ProcessVector.begin();Iter!=ProcessVector.end();Iter++) + { + if ( (*Iter!=NULL) ) + { + bWow64 = IsProcessWow64((*Iter)->Pid); + bIsProcessPresent = pProcessWidget->IsProcessPresent((*Iter)->Pid); + if (bIsProcessPresent) ProcessInfoMask = 0; + else ProcessInfoMask = RPC_PROCESS_INFO_ALL; + + pRpcProcessInfo = pRpcCore->RpcCoreGetProcessInfoFn(pRpcCoreCtxt,(*Iter)->Pid,(*Iter)->Ppid,ProcessInfoMask); + + if (pRpcProcessInfo!=NULL) + { + if (bIsProcessPresent) pProcessWidget->UpdateProcess(pRpcProcessInfo); + else pProcessWidget->AddProcess(pRpcProcessInfo); + + pRpcCore->RpcCoreFreeProcessInfoFn(pRpcCoreCtxt, pRpcProcessInfo); + } + } + } + pProcessWidget->RemoveTerminatedProcesses(); + this->NumberOfProcesses = pProcessWidget->GetProcesses(); + this->TotalProcesses = pProcessWidget->GetTotalProcesses(); +} \ No newline at end of file diff --git a/RpcView/RefreshVisitor.h b/RpcView/RefreshVisitor.h new file mode 100644 index 0000000..ef83da2 --- /dev/null +++ b/RpcView/RefreshVisitor.h @@ -0,0 +1,49 @@ +#ifndef _REFRESH_VISITOR_H_ +#define _REFRESH_VISITOR_H_ + +#include "../Qt/Qt.h" +#include "ViewVisitor.h" +#include "ProcessEntry.h" +#include "..\RpcCore\RpcCore.h" + +//------------------------------------------------------------------------------ +class RefreshVisitor_C : public ViewVisitor_C +{ +public: + std::vector ProcessVector; + + RefreshVisitor_C(RpcCore_T* pRpcCore,void* pRpcCoreCtxt); + ~RefreshVisitor_C(); + + // FIXE ME + // NumberOfEndpoints as well as NumberOfInterfaces SHOULD be private members + // but we have to change the RpcCore API to avoid enum in order to achieve this goal! + // + ULONG NumberOfEndpoints; + ULONG NumberOfInterfaces; + ULONG NumberOfProcesses; + + ULONG TotalEndpoints; + ULONG TotalInterfaces; + ULONG TotalProcesses; + + ULONG GetEndpoints(); + ULONG GetInterfaces(); + ULONG GetProcesses(); + ULONG GetTotalEndpoints(); + ULONG GetTotalInterfaces(); + ULONG GetTotalProcesses(); + + virtual void Visit(EndpointsWidget_C* pEndpointsWidget); + virtual void Visit(InterfacesWidget_C* pInterfacesWidget); + virtual void Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget); + virtual void Visit(ProcessInfoWidget_C* pProcessInfoWidget); + virtual void Visit(ProceduresWidget_C* pProceduresWidget); + virtual void Visit(ProcessWidget_C* pProcessWidget); + +private: + RpcCore_T* pRpcCore; + void* pRpcCoreCtxt; +}; + +#endif //_REFRESH_VISITOR_H_ \ No newline at end of file diff --git a/RpcView/RpcCoreManager.c b/RpcView/RpcCoreManager.c new file mode 100644 index 0000000..3305ace --- /dev/null +++ b/RpcView/RpcCoreManager.c @@ -0,0 +1,301 @@ +#include <../../RpcCore/RpcCore.h> +#include "..\RpcCommon\Misc.h" +#include "..\RpcCommon\RpcCommon.h" +#include + +typedef struct _RpcCoreManager_T{ + void* pNativeCoreCtxt; + RpcCore_T* pNativeCore; +#ifdef _WIN64 + void* pWow64CoreCtxt; + RpcCore_T* pWow64Core; +#endif +}RpcCoreManager_T; + +// RpcCore +VOID* __fastcall RpcCoreInit(); //returns a private context for the RpcCoreEngine +VOID __fastcall RpcCoreUninit(VOID* pRpcCoreCtxt); +RpcProcessInfo_T* __fastcall RpcCoreGetProcessInfo(void* pRpcCoreCtxt, DWORD Pid, DWORD Ppid, ULONG ProcessInfoMask); +VOID __fastcall RpcCoreFreeProcessInfo(void* pRpcCoreCtxt, RpcProcessInfo_T* pRpcProcessInfo); +RpcInterfaceInfo_T* __fastcall RpcCoreGetInterfaceInfo(void* pRpcCoreCtxt, DWORD Pid, RPC_IF_ID* pIf, ULONG InterfaceInfoMask); +VOID __fastcall RpcCoreFreeInterfaceInfo(void* pRpcCoreCtxt, RpcInterfaceInfo_T* pRpcInterfaceInfo); +BOOL __fastcall RpcCoreEnumProcessInterfaces(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessInterfacesCallbackFn_T RpcCoreEnumProcessInterfacesCallbackFn, void* pCallbackCtxt, ULONG InterfaceInfoMask); +BOOL __fastcall RpcCoreEnumProcessEndpoints(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessEndpointsCallbackFn_T RpcCoreEnumProcessEndpointsCallbackFn, void* pCallbackCtxt); +BOOL __fastcall RpcCoreEnumProcessAuthInfo(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessAuthInfoCallbackFn_T RpcCoreEnumProcessAuthInfoCallbackFn, void* pCallbackCtxt); + + +RpcCore_T gRpcCoreManager = +{ + 0, + //"Generic RpcCore Manager", + FALSE, + &RpcCoreInit, + &RpcCoreUninit, + &RpcCoreGetProcessInfo, + &RpcCoreFreeProcessInfo, + &RpcCoreGetInterfaceInfo, + &RpcCoreFreeInterfaceInfo, + &RpcCoreEnumProcessInterfaces, + &RpcCoreEnumProcessEndpoints, + &RpcCoreEnumProcessAuthInfo, +}; + +//------------------------------------------------------------------------------ +BOOL NTAPI LoadCoreEngine(RpcCore_T** ppRpcCoreHelper, void** ppRpcCoreCtxt, BOOL bWow64Helper) +{ + WIN32_FIND_DATAA Win32FindData; + HMODULE hLib; + // Version_T Version; + HANDLE hFindFile = INVALID_HANDLE_VALUE; + RpcCore_T* pRpcCoreHelper = NULL; + BOOL bResult = FALSE; + + hFindFile = FindFirstFileA("*.dll", &Win32FindData); + if (hFindFile == INVALID_HANDLE_VALUE) goto End; + do + { + hLib = LoadLibraryA(Win32FindData.cFileName); + if (hLib != NULL) + { + pRpcCoreHelper = (RpcCore_T*)GetProcAddress(hLib, RPC_CORE_EXPORT_SYMBOL); + if (pRpcCoreHelper != NULL) + { + *ppRpcCoreCtxt = pRpcCoreHelper->RpcCoreInitFn(); + if (*ppRpcCoreCtxt != NULL) + { + pRpcCoreHelper->RpcCoreUninitFn(*ppRpcCoreCtxt); + if (bWow64Helper == pRpcCoreHelper->bWow64Helper) + { +// Version.As64BitsValue = pRpcCoreHelper->RuntimeVersion; + _cprintf("RpcCore : %s\n", Win32FindData.cFileName); + // _cprintf("Version : %I64X (%u.%u.%u.%u)\n", Version.As64BitsValue, Version.As16BitsValues.Part4, Version.As16BitsValues.Part3, Version.As16BitsValues.Part2, Version.As16BitsValues.Part1); + _cprintf("Helper : 0x%p\n", pRpcCoreHelper); + _cprintf("Wow64 : "); + if (pRpcCoreHelper->bWow64Helper) _cprintf("TRUE\n"); else _cprintf("FALSE\n"); + // _cprintf("Description: %s\n\n", pRpcCoreHelper->pDescription); + *ppRpcCoreHelper = pRpcCoreHelper; + bResult = TRUE; + goto End; + } + } + } + FreeLibrary(hLib); + } + } while (FindNextFileA(hFindFile, &Win32FindData)); +End: + if (hFindFile != INVALID_HANDLE_VALUE) FindClose(hFindFile); + return (bResult); +} + + +//----------------------------------------------------------------------------- +VOID* __fastcall RpcCoreInit() +{ + RpcCoreManager_T* pRpcCoreManager; + + pRpcCoreManager = (RpcCoreManager_T*)OS_ALLOC(sizeof(RpcCoreManager_T)); + + if (!LoadCoreEngine(&pRpcCoreManager->pNativeCore, &pRpcCoreManager->pNativeCoreCtxt, FALSE)) + { + const char Caption[] = "Unsupported runtime version"; +#ifdef _WIN64 + const char Msg[] = "Please send us a mail to contact@rpcview.org with your rpcrt4.dll files (in System32 and SysWOW64 directories)"; +#else + const char Msg[] = "Please send us a mail to contact@rpcview.org with your rpcrt4.dll file (in System32 directory)"; +#endif +#ifdef _DEBUG + _cprintf("** %s **\n%s\n",Caption,Msg); +#else + MessageBoxA(NULL, Msg, Caption, MB_OK); +#endif + ExitProcess(0); + } + pRpcCoreManager->pNativeCoreCtxt = pRpcCoreManager->pNativeCore->RpcCoreInitFn(); +#ifdef _WIN64 + if (!LoadCoreEngine(&pRpcCoreManager->pWow64Core, &pRpcCoreManager->pWow64CoreCtxt, TRUE)) goto Cleanup; + pRpcCoreManager->pWow64CoreCtxt = pRpcCoreManager->pWow64Core->RpcCoreInitFn(); +#endif +End: + return (pRpcCoreManager); +#ifdef _WIN64 +Cleanup: +#endif + OS_FREE(pRpcCoreManager); + pRpcCoreManager = NULL; + goto End; +} + +//----------------------------------------------------------------------------- +VOID __fastcall RpcCoreUninit(VOID* pRpcCoreCtxt) +{ + RpcCoreManager_T* pRpcCoreManager; + + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager == NULL) goto End; + + pRpcCoreManager->pNativeCore->RpcCoreUninitFn(pRpcCoreManager->pNativeCoreCtxt); +#ifdef _WIN64 + pRpcCoreManager->pWow64Core->RpcCoreUninitFn(pRpcCoreManager->pWow64CoreCtxt); +#endif + OS_FREE(pRpcCoreManager); +End: + return; +} + +//----------------------------------------------------------------------------- +RpcProcessInfo_T* __fastcall RpcCoreGetProcessInfo(void* pRpcCoreCtxt, DWORD Pid, DWORD Ppid, ULONG ProcessInfoMask) +{ + RpcCoreManager_T* pRpcCoreManager = NULL; + RpcProcessInfo_T* pRpcProcessInfo = NULL; + + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager == NULL) goto End; + +#ifdef _WIN64 + if (IsProcessWow64(Pid)) + { + pRpcProcessInfo = pRpcCoreManager->pWow64Core->RpcCoreGetProcessInfoFn(pRpcCoreManager->pWow64CoreCtxt, Pid, Ppid, ProcessInfoMask); + } + else +#endif + { + pRpcProcessInfo = pRpcCoreManager->pNativeCore->RpcCoreGetProcessInfoFn(pRpcCoreManager->pNativeCoreCtxt, Pid, Ppid, ProcessInfoMask); + } +End: + return (pRpcProcessInfo); +} + +//----------------------------------------------------------------------------- +VOID __fastcall RpcCoreFreeProcessInfo(void* pRpcCoreCtxt, RpcProcessInfo_T* pRpcProcessInfo) +{ + RpcCoreManager_T* pRpcCoreManager = NULL; + + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager != NULL) + { +#ifdef _WIN64 + if (IsProcessWow64(pRpcProcessInfo->Pid)) + { + pRpcCoreManager->pWow64Core->RpcCoreFreeProcessInfoFn(pRpcCoreManager->pWow64CoreCtxt, pRpcProcessInfo); + } + else +#endif + { + pRpcCoreManager->pNativeCore->RpcCoreFreeProcessInfoFn(pRpcCoreManager->pNativeCoreCtxt, pRpcProcessInfo); + } + } +} + +//----------------------------------------------------------------------------- +RpcInterfaceInfo_T* __fastcall RpcCoreGetInterfaceInfo(void* pRpcCoreCtxt, DWORD Pid, RPC_IF_ID* pIf, ULONG InterfaceInfoMask) +{ + RpcCoreManager_T* pRpcCoreManager = NULL; + RpcInterfaceInfo_T* pRpcInterfaceInfo = NULL; + + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager == NULL) goto End; + +#ifdef _WIN64 + if (IsProcessWow64(Pid)) + { + pRpcInterfaceInfo = pRpcCoreManager->pWow64Core->RpcCoreGetInterfaceInfoFn(pRpcCoreManager->pWow64CoreCtxt, Pid, pIf, InterfaceInfoMask); + } + else +#endif + { + pRpcInterfaceInfo = pRpcCoreManager->pNativeCore->RpcCoreGetInterfaceInfoFn(pRpcCoreManager->pNativeCoreCtxt, Pid, pIf, InterfaceInfoMask); + } +End: + return (pRpcInterfaceInfo); +} + +//----------------------------------------------------------------------------- +VOID __fastcall RpcCoreFreeInterfaceInfo(void* pRpcCoreCtxt, RpcInterfaceInfo_T* pRpcInterfaceInfo) +{ + RpcCoreManager_T* pRpcCoreManager = NULL; + + if (pRpcInterfaceInfo == NULL) return; + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager != NULL) + { +#ifdef _WIN64 + if (IsProcessWow64(pRpcInterfaceInfo->Pid)) + { + pRpcCoreManager->pWow64Core->RpcCoreFreeInterfaceInfoFn(pRpcCoreManager->pWow64CoreCtxt, pRpcInterfaceInfo); + } + else +#endif + { + pRpcCoreManager->pNativeCore->RpcCoreFreeInterfaceInfoFn(pRpcCoreManager->pNativeCoreCtxt, pRpcInterfaceInfo); + } + } +} + +//----------------------------------------------------------------------------- +BOOL __fastcall RpcCoreEnumProcessInterfaces(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessInterfacesCallbackFn_T RpcCoreEnumProcessInterfacesCallbackFn, void* pCallbackCtxt, ULONG InterfaceInfoMask) +{ + RpcCoreManager_T* pRpcCoreManager = NULL; + BOOL bResult = FALSE; + + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager == NULL) goto End; + +#ifdef _WIN64 + if (IsProcessWow64(Pid)) + { + bResult = pRpcCoreManager->pWow64Core->RpcCoreEnumProcessInterfacesFn(pRpcCoreManager->pWow64CoreCtxt, Pid, RpcCoreEnumProcessInterfacesCallbackFn, pCallbackCtxt, InterfaceInfoMask); + } + else +#endif + { + bResult = pRpcCoreManager->pNativeCore->RpcCoreEnumProcessInterfacesFn(pRpcCoreManager->pNativeCoreCtxt, Pid, RpcCoreEnumProcessInterfacesCallbackFn, pCallbackCtxt, InterfaceInfoMask); + } +End: + return (bResult); +} + +//----------------------------------------------------------------------------- +BOOL __fastcall RpcCoreEnumProcessEndpoints(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessEndpointsCallbackFn_T RpcCoreEnumProcessEndpointsCallbackFn, void* pCallbackCtxt) +{ + RpcCoreManager_T* pRpcCoreManager = NULL; + BOOL bResult = FALSE; + + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager == NULL) goto End; + +#ifdef _WIN64 + if (IsProcessWow64(Pid)) + { + bResult = pRpcCoreManager->pWow64Core->RpcCoreEnumProcessEndpointsFn(pRpcCoreManager->pWow64CoreCtxt, Pid, RpcCoreEnumProcessEndpointsCallbackFn, pCallbackCtxt); + } + else +#endif + { + bResult = pRpcCoreManager->pNativeCore->RpcCoreEnumProcessEndpointsFn(pRpcCoreManager->pNativeCoreCtxt, Pid, RpcCoreEnumProcessEndpointsCallbackFn, pCallbackCtxt); + } +End: + return (bResult); +} + +//----------------------------------------------------------------------------- +BOOL __fastcall RpcCoreEnumProcessAuthInfo(void* pRpcCoreCtxt, DWORD Pid, RpcCoreEnumProcessAuthInfoCallbackFn_T RpcCoreEnumProcessAuthInfoCallbackFn, void* pCallbackCtxt) +{ + RpcCoreManager_T* pRpcCoreManager = NULL; + BOOL bResult = FALSE; + + pRpcCoreManager = (RpcCoreManager_T*)pRpcCoreCtxt; + if (pRpcCoreManager == NULL) goto End; + +#ifdef _WIN64 + if (IsProcessWow64(Pid)) + { + bResult = pRpcCoreManager->pWow64Core->RpcCoreEnumProcessAuthInfoFn(pRpcCoreManager->pWow64CoreCtxt, Pid, RpcCoreEnumProcessAuthInfoCallbackFn, pCallbackCtxt); + } + else +#endif + { + bResult = pRpcCoreManager->pNativeCore->RpcCoreEnumProcessAuthInfoFn(pRpcCoreManager->pNativeCoreCtxt, Pid, RpcCoreEnumProcessAuthInfoCallbackFn, pCallbackCtxt); + } +End: + return (bResult); +} diff --git a/RpcView/RpcView.cpp b/RpcView/RpcView.cpp new file mode 100644 index 0000000..baf9ef1 --- /dev/null +++ b/RpcView/RpcView.cpp @@ -0,0 +1,380 @@ +#include "..\Qt\Qt.h" + +#include +#include +#include +#include +#include + +#include "MainWindow.h" +#include "EulaDialog.h" +#include "DecompilationWidget.h" +#include "Pdb.h" +#include "RpcViewResource.h" +#include "..\RpcDecompiler\RpcDecompiler.h" +#include "..\RpcCore\RpcCore.h" +#include "..\RpcCommon\Misc.h" + +#include + +#pragma comment(lib,"Winmm.lib") +#pragma comment(lib,"Imm32.lib") +#pragma comment(lib,"Dbghelp.lib") +#pragma comment(lib,"Rpcrt4.lib") +#pragma comment(lib,"Ws2_32.lib") + +// +// Set the entry point to WinMain in relase configuration +// +#ifndef _DEBUG +#pragma comment(linker, "/SUBSYSTEM:WINDOWS") +#endif + +VOID* __fastcall RpcAlloc(SIZE_T Size); +VOID __fastcall RpcFree(VOID* pMem); +BOOL __fastcall RpcGetProcessData(RpcModuleInfo_T* pRpcModuleInfo, RVA_T rva, VOID* pBuffer, UINT BufferLength); //Size is IN (pPorcNameBuffer size)/OUT (read size) +VOID __cdecl RpcPrint(void* pContext,const char* pTxt); +VOID __cdecl RpcDebug(const char* pFunction, ULONG Line, const char* pFormatString, ...); +BOOL __fastcall RpcGetInterfaceName(GUID* pIfId,UCHAR* pName,ULONG NameLength); + +#ifdef __cplusplus +extern "C" { +#endif + +extern RpcCore_T gRpcCoreManager; + +#ifdef __cplusplus +} +#endif + +//------------------------------------------------------------------------------ +ULONG NTAPI DecompilerExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) +{ + UCHAR ModulePath[RPC_MAX_LENGTH]; + HMODULE hModule; + + ModulePath[0]=0; + _cprintf("Exception catched.\n"); + GetMappedFileNameA(GetCurrentProcess(), pExceptionPointers->ExceptionRecord->ExceptionAddress, (LPSTR)ModulePath, sizeof(ModulePath)); + _cprintf("Code : 0x%X\n", pExceptionPointers->ExceptionRecord->ExceptionCode); + _cprintf("Module : %s\n", ModulePath); + GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress, &hModule); + _cprintf("Address: 0x%p (0x%p + 0x%X)\n", pExceptionPointers->ExceptionRecord->ExceptionAddress, hModule, (UINT_PTR)pExceptionPointers->ExceptionRecord->ExceptionAddress - (UINT_PTR)hModule ); + return (EXCEPTION_EXECUTE_HANDLER); +} + + +//------------------------------------------------------------------------------ +HMODULE NTAPI LoadDecompilerEngine(RpcDecompilerHelper_T** ppRpcDecompilerHelper) +{ + WIN32_FIND_DATAA Win32FindData; + HMODULE hLib = NULL; + HANDLE hFindFile = INVALID_HANDLE_VALUE; + RpcDecompilerHelper_T* pRpcDecompilerHelper = NULL; + BOOL bResult = FALSE; + + hFindFile = FindFirstFileA("*.dll", &Win32FindData); + if ( hFindFile==INVALID_HANDLE_VALUE ) goto End; + do + { + __try{ + hLib = LoadLibraryA(Win32FindData.cFileName); + } + __except( DecompilerExceptionFilter(GetExceptionInformation()) ) + { + goto End; + } + if (hLib!=NULL) + { + pRpcDecompilerHelper = (RpcDecompilerHelper_T*)GetProcAddress(hLib, RPC_DECOMPILER_EXPORT_SYMBOL); + if (pRpcDecompilerHelper!=NULL) + { + _cprintf("Found RpcDecompilerHelper %p\n", pRpcDecompilerHelper); + *ppRpcDecompilerHelper = pRpcDecompilerHelper; + bResult = TRUE; + goto End; + } + else + { + FreeLibrary(hLib); + hLib=NULL; + } + } + }while( FindNextFileA(hFindFile, &Win32FindData) ); +End: + if ( hFindFile!=INVALID_HANDLE_VALUE ) FindClose(hFindFile); + return (hLib); +} + + +//------------------------------------------------------------------------------ +void NTAPI InitDecompilerInfo(_In_ RpcInterfaceInfo_T* pRpcInterfaceInfo, _Out_ RpcDecompilerInfo_T* pRpcDecompilerInfo) +{ + UINT i; + UINT SymboleLength; + HANDLE hProcess = NULL; + void* hPdb = NULL; + WCHAR SymboleName[RPC_MAX_LENGTH]; + + if (pRpcDecompilerInfo == NULL) goto End; + if (pRpcInterfaceInfo == NULL) goto End; + + pRpcDecompilerInfo->pModuleBase = (UINT64)pRpcInterfaceInfo->pLocationBase; + pRpcDecompilerInfo->pIfId = &pRpcInterfaceInfo->If; + pRpcDecompilerInfo->Pid = pRpcInterfaceInfo->Pid; + StringCbPrintfW(pRpcDecompilerInfo->InterfaceName, sizeof(pRpcDecompilerInfo->InterfaceName), L"%s", pRpcInterfaceInfo->Name); + pRpcDecompilerInfo->pSyntaxId = &pRpcInterfaceInfo->TransfertSyntax; + + pRpcDecompilerInfo->MIDLVersion = pRpcInterfaceInfo->NdrInfo.MIDLVersion; + pRpcDecompilerInfo->NDRFags = pRpcInterfaceInfo->NdrInfo.mFlags; + pRpcDecompilerInfo->NDRVersion = pRpcInterfaceInfo->NdrInfo.Version; + + pRpcDecompilerInfo->NumberOfProcedures = pRpcInterfaceInfo->NumberOfProcedures; + pRpcDecompilerInfo->ppProcAddressTable = pRpcInterfaceInfo->ppProcAddressTable; + pRpcDecompilerInfo->pTypeFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pTypeFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + + pRpcDecompilerInfo->pFormatStringOffsetTable = pRpcInterfaceInfo->pFormatStringOffsetTable; + pRpcDecompilerInfo->pProcFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pProcFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + + pRpcDecompilerInfo->apfnExprEval = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->apfnExprEval - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + pRpcDecompilerInfo->bIsInlined = FALSE; + + pRpcDecompilerInfo->pExprOffset = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pExprOffset - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + pRpcDecompilerInfo->pExprFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pExprFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + // + // Cannot decompile if we cannot get the ppProcAddressTable value!!! + // + if (pRpcDecompilerInfo->ppProcAddressTable == NULL) + { + printf("*** No procedure: %u\n", pRpcDecompilerInfo->NumberOfProcedures); + // ExitProcess(0); + // goto End; + } + + pRpcDecompilerInfo->ppProcNameTable = (WCHAR**)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures*sizeof(UCHAR*)); + if (pRpcDecompilerInfo->ppProcNameTable == NULL) goto End; + + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pRpcInterfaceInfo->Pid); + if (hProcess == NULL) goto End; +#ifdef _WIN64 + pRpcDecompilerInfo->bIs64Bits = !pRpcInterfaceInfo->bWow64Process; +#else + pRpcDecompilerInfo->bIs64Bits = FALSE; +#endif + // + // Creates and initialiaze the pbFunctionInterpreted bool table + // TODO : should be really initialized + // + pRpcDecompilerInfo->pbFunctionInterpreted = (BOOL*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures*sizeof(BOOL)); + if (pRpcDecompilerInfo->pbFunctionInterpreted == NULL) goto End; + // + // Creates and initialiaze the ppProcFormatInlined RVA_T table + // TODO : should be really initialized + // + pRpcDecompilerInfo->ppProcFormatInlined = (RVA_T*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures*sizeof(RVA_T)); + if (pRpcDecompilerInfo->ppProcFormatInlined == NULL) goto End; + // + // Creates and initialiaze the ppDispatchProcAddressTable RVA_T table + // TODO : should be really initialized + // + pRpcDecompilerInfo->ppDispatchProcAddressTable = (RVA_T*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures*sizeof(RVA_T)); + if (pRpcDecompilerInfo->ppDispatchProcAddressTable == NULL) goto End; + + hPdb = PdbInit(hProcess, pRpcInterfaceInfo->pLocationBase, pRpcInterfaceInfo->LocationSize); + if (hPdb == NULL) goto End; + for (i = 0; iNumberOfProcedures; i++) + { + SymboleName[0] = 0; + if (PdbGetSymbolName(hPdb, (UCHAR*)pRpcInterfaceInfo->pLocationBase + pRpcDecompilerInfo->ppProcAddressTable[i], SymboleName, sizeof(SymboleName))) + { + SymboleLength = ((UINT)wcslen(SymboleName) + 1)*sizeof(WCHAR); + pRpcDecompilerInfo->ppProcNameTable[i] = (WCHAR*)OS_ALLOC(SymboleLength); + memcpy(pRpcDecompilerInfo->ppProcNameTable[i], SymboleName, SymboleLength); + } + } + PdbUninit(hPdb); +End: + if (hProcess != NULL) CloseHandle(hProcess); + return; +} + + +//------------------------------------------------------------------------------ +void NTAPI UninitDecompilerInfo(RpcDecompilerInfo_T* pRpcDecompilerInfo) +{ + UINT i; + + if (pRpcDecompilerInfo->ppProcNameTable != NULL) + { + for (i = 0; iNumberOfProcedures; i++) + { + if (pRpcDecompilerInfo->ppProcNameTable[i] != NULL) OS_FREE(pRpcDecompilerInfo->ppProcNameTable[i]); + } + OS_FREE(pRpcDecompilerInfo->ppProcNameTable); + } + if (pRpcDecompilerInfo->pbFunctionInterpreted != NULL) OS_FREE(pRpcDecompilerInfo->pbFunctionInterpreted); + if (pRpcDecompilerInfo->ppProcFormatInlined != NULL) OS_FREE(pRpcDecompilerInfo->ppProcFormatInlined); + if (pRpcDecompilerInfo->ppDispatchProcAddressTable != NULL) OS_FREE(pRpcDecompilerInfo->ppDispatchProcAddressTable); +} + + +#ifdef _DEBUG + +typedef struct _EnumCtxt_T{ + void* pRpcCoreCtxt; + RpcCore_T* pRpcCore; + RpcDecompilerHelper_T* pRpcDecompilerHelper; +}EnumCtxt_T; + + +//------------------------------------------------------------------------------ +VOID __cdecl RpcDbgPrint(void* pContext, const char* pTxt) +{ + printf("%s\n", pTxt); +} + + +//------------------------------------------------------------------------------ +static BOOL __fastcall EnumInterfaces(RpcInterfaceInfo_T* pRpcInterfaceInfo, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + RpcDecompilerInfo_T RpcDecompilerInfo; + void* pDecompilerCtxt; + + UNREFERENCED_PARAMETER(pbContinue); + + ZeroMemory(&RpcDecompilerInfo, sizeof(RpcDecompilerInfo_T)); + if (pRpcInterfaceInfo->IfType != IfType_RPC) goto End; + InitDecompilerInfo(pRpcInterfaceInfo, &RpcDecompilerInfo); + __try{ + RpcViewHelper_T LocalRpcViewHelper = { + NULL, + &RpcAlloc, + &RpcFree, + &RpcGetProcessData, + &RpcDbgPrint, + &RpcDebug, + &RpcGetInterfaceName + }; + pDecompilerCtxt = pEnumCtxt->pRpcDecompilerHelper->RpcDecompilerInitFn(&LocalRpcViewHelper, &RpcDecompilerInfo); + if (pDecompilerCtxt!=NULL) + { + pEnumCtxt->pRpcDecompilerHelper->RpcDecompilerPrintAllProceduresFn( pDecompilerCtxt ); + pEnumCtxt->pRpcDecompilerHelper->RpcDecompilerUninitFn(pDecompilerCtxt); + } + }__except( DecompilerExceptionFilter(GetExceptionInformation()) ) + { + //Failure + goto End; + } + +End: + UninitDecompilerInfo(&RpcDecompilerInfo); + return (TRUE); +} + + +//------------------------------------------------------------------------------ +static BOOL WINAPI EnumProc(DWORD Pid, DWORD Ppid, EnumCtxt_T* pEnumCtxt, BOOL* pbContinue) +{ + RpcProcessInfo_T* pRpcProcessInfo; + + UNREFERENCED_PARAMETER(pbContinue); + + pRpcProcessInfo=pEnumCtxt->pRpcCore->RpcCoreGetProcessInfoFn(pEnumCtxt->pRpcCoreCtxt, Pid, Ppid,RPC_PROCESS_INFO_ALL); + if (pRpcProcessInfo==NULL) goto End; + pEnumCtxt->pRpcCore->RpcCoreFreeProcessInfoFn(pEnumCtxt->pRpcCoreCtxt, pRpcProcessInfo); + pEnumCtxt->pRpcCore->RpcCoreEnumProcessInterfacesFn(pEnumCtxt->pRpcCoreCtxt, Pid, (RpcCoreEnumProcessInterfacesCallbackFn_T)&EnumInterfaces, pEnumCtxt, RPC_INTERFACE_INFO_ALL); +End: + return (TRUE); +} + + +//------------------------------------------------------------------------------ +int DecompileAllInterfaces(RpcCore_T* pRpcCore) +{ + EnumCtxt_T EnumCtxt; + RpcDecompilerHelper_T* pRpcDecompilerHelper; + HMODULE hDecompiler = NULL; + + hDecompiler=LoadDecompilerEngine(&pRpcDecompilerHelper); + if (hDecompiler==NULL) goto End; + + EnumCtxt.pRpcDecompilerHelper = pRpcDecompilerHelper; + EnumCtxt.pRpcCore = pRpcCore; + EnumCtxt.pRpcCoreCtxt = pRpcCore->RpcCoreInitFn(); + if (EnumCtxt.pRpcCoreCtxt==NULL) goto End; + + _cprintf("Start scanning...\n"); + EnumProcess( (EnumProcessCallbackFn_T)&EnumProc, &EnumCtxt ); + _cprintf("Done\n"); +End: + if (EnumCtxt.pRpcCoreCtxt != NULL) pRpcCore->RpcCoreUninitFn(EnumCtxt.pRpcCoreCtxt); + if (hDecompiler!=NULL) FreeLibrary(hDecompiler); + return (0); +} + +#endif + + +//------------------------------------------------------------------------------ +#ifdef _DEBUG + int main(int argc, char* argv[]) +#else + int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) +#endif +{ + MainWindow_C* pMainWindow = NULL; + HICON hMainIcon; + UCHAR CurrentDirectory[MAX_PATH]; + UCHAR* pSeparator; + +#ifdef _DEBUG + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); +#else + int argc = 1; + char* pCmdLineA = NULL; + char** argv = &pCmdLineA; + + pCmdLineA = GetCommandLineA(); +#endif + QApplication app(argc, argv); + QSettings Settings(RPC_VIEW_ORGANIZATION_NAME, RPC_VIEW_APPLICATION_NAME); + // + // Set the current directory according to the given EXE path + // + StringCbPrintfA((STRSAFE_LPSTR)CurrentDirectory,sizeof(CurrentDirectory),"%s",argv[0]); + pSeparator = (UCHAR*)strrchr((const char*)CurrentDirectory,'\\'); + if (pSeparator!=NULL) + { + *pSeparator = 0; + _cprintf("%s\n",CurrentDirectory); + SetCurrentDirectoryA((LPCSTR)CurrentDirectory); + } +#ifdef _DEBUG + if (argc>1) + { + if (!_stricmp(argv[1],"/DA")) + { + DecompileAllInterfaces(&gRpcCoreManager); + } + else + { + _cprintf("Usage %s: [/DA]\n",argv[0]); + _cprintf(" /DA : decompile all interfaces\n"); + } + _CrtDumpMemoryLeaks(); + return 0; + } +#endif + + pMainWindow = new MainWindow_C(&gRpcCoreManager); + + hMainIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_MAIN_ICON)); + if (hMainIcon!=NULL) + { + pMainWindow->setWindowIcon(QPixmap::fromWinHICON(hMainIcon)); + DestroyIcon(hMainIcon); + } + return app.exec(); +} \ No newline at end of file diff --git a/RpcView/RpcViewResource.h b/RpcView/RpcViewResource.h new file mode 100644 index 0000000..9b13a85 --- /dev/null +++ b/RpcView/RpcViewResource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by resource.rc +// +#define ID_MAIN_ICON 1001 +#define ID_UAC_ICON 1002 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/RpcView/RpcViewResource.rc b/RpcView/RpcViewResource.rc new file mode 100644 index 0000000..31c1db1 --- /dev/null +++ b/RpcView/RpcViewResource.rc @@ -0,0 +1,102 @@ +// Microsoft Visual C++ generated resource script. +// +#include "RpcViewResource.h" +#include + +#define APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Français (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +#ifdef _WIN32 +//LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +1 VERSIONINFO + FILEVERSION _RPCVIEW_VERSION_MAJOR_,_RPCVIEW_VERSION_MINOR_,_RPCVIEW_VERSION_RELEASE_,0 + PRODUCTVERSION _RPCVIEW_VERSION_MAJOR_,_RPCVIEW_VERSION_MINOR_,_RPCVIEW_VERSION_RELEASE_,0 + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "RpcView" + VALUE "FileDescription", "RpcView" + VALUE "InternalName", "RpcView" + VALUE "LegalCopyright", "Copyright © 2012-2017 RpcView Team" + VALUE "LegalTrademarks", "Copyright (C) 2012-2017 RpcView Team" + VALUE "OriginalFilename", "RpcView.exe" + VALUE "ProductName", "RpcView" + VALUE "ProductVersion", _RPCVIEW_PRODUCT_VERSION_ + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +ID_MAIN_ICON ICON "Main.ico" +ID_UAC_ICON ICON "Uac.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.\0" +END + + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Français (France) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/RpcView/RpcViewVersion.h.in b/RpcView/RpcViewVersion.h.in new file mode 100644 index 0000000..55a13df --- /dev/null +++ b/RpcView/RpcViewVersion.h.in @@ -0,0 +1,9 @@ +#ifndef _RPCVIEW_VERSION_H_ +#define _RPCVIEW_VERSION_H_ + +#define _RPCVIEW_VERSION_MAJOR_ @RPCVIEW_VERSION_MAJOR@ +#define _RPCVIEW_VERSION_MINOR_ @RPCVIEW_VERSION_MINOR@ +#define _RPCVIEW_VERSION_RELEASE_ @RPCVIEW_VERSION_RELEASE@ +#define _RPCVIEW_PRODUCT_VERSION_ "@RPCVIEW_VERSION_MAJOR@.@RPCVIEW_VERSION_MINOR@.@RPCVIEW_VERSION_RELEASE@.0" + +#endif \ No newline at end of file diff --git a/RpcView/Uac.ico b/RpcView/Uac.ico new file mode 100644 index 0000000..25d695e Binary files /dev/null and b/RpcView/Uac.ico differ diff --git a/RpcView/View.h b/RpcView/View.h new file mode 100644 index 0000000..a95fb9c --- /dev/null +++ b/RpcView/View.h @@ -0,0 +1,16 @@ +#ifndef _VIEW_H_ +#define _VIEW_H_ + +#include "..\Qt\Qt.h" +#include "ViewVisitor.h" + +// +// View Interface +// +class View_I +{ +public: + virtual void AcceptVisitor(ViewVisitor_C* pVisitor)=0; +}; + +#endif // _VIEW_H_ \ No newline at end of file diff --git a/RpcView/ViewFactory.h b/RpcView/ViewFactory.h new file mode 100644 index 0000000..879781b --- /dev/null +++ b/RpcView/ViewFactory.h @@ -0,0 +1,16 @@ +#ifndef _VIEW_FACTORY_H_ +#define _VIEW_FACTORY_H_ + +#include "View.h" + +using namespace std; + +class ViewFactory_C +{ +public: + ViewFactory_C(); + void CreateViews(&vector); + ViewVisitor_C* CreateVisitor(ViewAction_T ViewAction); +}; + +#endif //_VIEW_FACTORY_H_ \ No newline at end of file diff --git a/RpcView/ViewVisitor.h b/RpcView/ViewVisitor.h new file mode 100644 index 0000000..16ea154 --- /dev/null +++ b/RpcView/ViewVisitor.h @@ -0,0 +1,22 @@ +#ifndef _VIEW_VISITOR_H_ +#define _VIEW_VISITOR_H_ + +class EndpointsWidget_C; +class InterfacesWidget_C; +class InterfaceInfoWidget_C; +class ProcessInfoWidget_C; +class ProceduresWidget_C; +class ProcessWidget_C; + +class ViewVisitor_C +{ +public: + virtual void Visit(EndpointsWidget_C* pEndpointsWidget) = 0; + virtual void Visit(InterfacesWidget_C* pInterfacesWidget) = 0; + virtual void Visit(InterfaceInfoWidget_C* pInterfaceInfoWidget) = 0; + virtual void Visit(ProcessInfoWidget_C* pProcessInfoWidget) = 0; + virtual void Visit(ProceduresWidget_C* pProceduresWidget) = 0; + virtual void Visit(ProcessWidget_C* pProcessWidget) = 0; +}; + +#endif \ No newline at end of file