add plugins-extra

This commit is contained in:
AirDog46 2025-05-13 19:49:49 +03:00
parent c5fab8aa94
commit 3575d86c17
531 changed files with 70258 additions and 1 deletions

1
.gitignore vendored
View File

@ -105,7 +105,6 @@ Desktop.ini
build/Installer/*.exe
ProcessHacker/include/phapprev.h
ProcessHacker/sdk/phapppub.h
plugins-extra/
sdk/
KProcessHacker/*.log

View File

@ -0,0 +1,122 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0c0904b0"
BEGIN
VALUE "CompanyName", "dmex"
VALUE "FileDescription", "Atom Table Plugin for Process Hacker"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "dmex.AtomTablePlugin"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "AtomTablePlugin.dll"
VALUE "ProductName", "Atom Table plugin for Process Hacker"
VALUE "ProductVersion", "1.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ATOMDIALOG DIALOGEX 0, 0, 325, 180
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Global Atom Table"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Close",IDOK,269,160,50,14
CONTROL "",IDC_ATOMLIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,5,312,152
PUSHBUTTON "Refresh",IDRETRY,7,160,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ATOMDIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 318
TOPMARGIN, 5
BOTTOMMARGIN, 174
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{12390643-F40D-411F-A2E8-BF85F90223DF}</ProjectGuid>
<RootNamespace>AtomTablePlugin</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>AtomTablePlugin</ProjectName>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="AtomTablePlugin.rc" />
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{802108be-ae96-47c3-8d93-884ed6dd096a}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{3e65ffb8-3f3e-40d7-b3ca-d55cae8edb16}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{b98dd849-bbfe-4b41-8c48-f65680da5c00}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="AtomTablePlugin.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,2 @@
1.0
* Initial release

View File

@ -0,0 +1,455 @@
/*
* Process Hacker Extra Plugins -
* NT Atom Table Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#define CINTERFACE
#define COBJMACROS
#include <phdk.h>
#include <phappresource.h>
#include "resource.h"
#define ATOM_TABLE_MENUITEM 1000
#define PLUGIN_NAME L"dmex.AtomTablePlugin"
#define SETTING_NAME_WINDOW_POSITION (PLUGIN_NAME L".WindowPosition")
#define SETTING_NAME_WINDOW_SIZE (PLUGIN_NAME L".WindowSize")
#define SETTING_NAME_LISTVIEW_COLUMNS (PLUGIN_NAME L".ListViewColumns")
static PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
static PH_CALLBACK_REGISTRATION MainMenuInitializingCallbackRegistration;
static PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration;
static HWND ListViewWndHandle;
static PH_LAYOUT_MANAGER LayoutManager;
static PPH_PLUGIN PluginInstance;
NTSTATUS PhEnumAtomTable(
_Out_ PATOM_TABLE_INFORMATION* AtomTable
)
{
NTSTATUS status;
PVOID buffer;
ULONG bufferSize = 0x1000;
buffer = PhAllocate(bufferSize);
memset(buffer, 0, bufferSize);
status = NtQueryInformationAtom(
RTL_ATOM_INVALID_ATOM,
AtomTableInformation,
buffer,
bufferSize,
&bufferSize // Not used...
);
if (!NT_SUCCESS(status))
{
PhFree(buffer);
return status;
}
*AtomTable = buffer;
return status;
}
NTSTATUS PhQueryAtomTableEntry(
_In_ RTL_ATOM Atom,
_Out_ PATOM_BASIC_INFORMATION* AtomInfo
)
{
NTSTATUS status;
PVOID buffer;
ULONG bufferSize = 0x1000;
buffer = PhAllocate(bufferSize);
memset(buffer, 0, bufferSize);
status = NtQueryInformationAtom(
Atom,
AtomBasicInformation,
buffer,
bufferSize,
&bufferSize // Not used...
);
if (!NT_SUCCESS(status))
{
PhFree(buffer);
return status;
}
*AtomInfo = buffer;
return status;
}
VOID LoadAtomTable(VOID)
{
PATOM_TABLE_INFORMATION atomTable = NULL;
if (!NT_SUCCESS(PhEnumAtomTable(&atomTable)))
return;
ExtendedListView_SetRedraw(ListViewWndHandle, FALSE);
ListView_DeleteAllItems(ListViewWndHandle);
for (ULONG i = 0; i < atomTable->NumberOfAtoms; i++)
{
PATOM_BASIC_INFORMATION atomInfo = NULL;
if (!NT_SUCCESS(PhQueryAtomTableEntry(atomTable->Atoms[i], &atomInfo)))
{
PhAddListViewItem(ListViewWndHandle, MAXINT, PhaFormatString(L"(Error) #%lu", i)->Buffer, NULL);
continue;
}
if ((atomInfo->Flags & RTL_ATOM_PINNED) == RTL_ATOM_PINNED)
{
INT index = PhAddListViewItem(
ListViewWndHandle,
MAXINT,
PhaFormatString(L"%s (Pinned)", atomInfo->Name)->Buffer,
NULL
);
PhSetListViewSubItem(
ListViewWndHandle,
index,
1,
PhaFormatString(L"%u", atomInfo->UsageCount)->Buffer
);
}
else
{
INT index = PhAddListViewItem(
ListViewWndHandle,
MAXINT,
atomInfo->Name,
NULL
);
PhSetListViewSubItem(
ListViewWndHandle,
index,
1,
PhaFormatString(L"%u", atomInfo->UsageCount)->Buffer
);
}
PhFree(atomInfo);
}
ExtendedListView_SetRedraw(ListViewWndHandle, TRUE);
PhFree(atomTable);
}
PPH_STRING PhGetSelectedListViewItemText(
_In_ HWND hWnd
)
{
INT index = PhFindListViewItemByFlags(
hWnd,
-1,
LVNI_SELECTED
);
if (index != -1)
{
WCHAR textBuffer[MAX_PATH] = L"";
LVITEM item;
item.mask = LVIF_TEXT;
item.iItem = index;
item.iSubItem = 0;
item.pszText = textBuffer;
item.cchTextMax = MAX_PATH;
if (ListView_GetItem(hWnd, &item))
return PhCreateString(textBuffer);
}
return NULL;
}
VOID ShowStatusMenu(
_In_ HWND hwndDlg
)
{
PPH_STRING cacheEntryName;
cacheEntryName = PhGetSelectedListViewItemText(ListViewWndHandle);
if (cacheEntryName)
{
POINT cursorPos;
PPH_EMENU menu;
PPH_EMENU_ITEM selectedItem;
GetCursorPos(&cursorPos);
menu = PhCreateEMenu();
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 1, L"Remove", NULL, NULL), -1);
selectedItem = PhShowEMenu(
menu,
ListViewWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
cursorPos.x,
cursorPos.y
);
if (selectedItem && selectedItem->Id != -1)
{
switch (selectedItem->Id)
{
case 1:
{
INT lvItemIndex = PhFindListViewItemByFlags(
ListViewWndHandle,
-1,
LVNI_SELECTED
);
if (lvItemIndex != -1)
{
if (!PhGetIntegerSetting(L"EnableWarnings") || PhShowConfirmMessage(
hwndDlg,
L"remove",
cacheEntryName->Buffer,
NULL,
FALSE
))
{
PATOM_TABLE_INFORMATION atomTable = NULL;
if (!NT_SUCCESS(PhEnumAtomTable(&atomTable)))
return;
for (ULONG i = 0; i < atomTable->NumberOfAtoms; i++)
{
PATOM_BASIC_INFORMATION atomInfo = NULL;
if (!NT_SUCCESS(PhQueryAtomTableEntry(atomTable->Atoms[i], &atomInfo)))
continue;
if (!PhEqualStringZ(atomInfo->Name, cacheEntryName->Buffer, TRUE))
continue;
do
{
if (!NT_SUCCESS(NtDeleteAtom(atomTable->Atoms[i])))
{
break;
}
PhFree(atomInfo);
atomInfo = NULL;
if (!NT_SUCCESS(PhQueryAtomTableEntry(atomTable->Atoms[i], &atomInfo)))
break;
} while (atomInfo->UsageCount >= 1);
ListView_DeleteItem(ListViewWndHandle, lvItemIndex);
if (atomInfo)
{
PhFree(atomInfo);
}
}
PhFree(atomTable);
}
}
}
break;
}
}
PhDestroyEMenu(menu);
PhDereferenceObject(cacheEntryName);
}
}
INT_PTR CALLBACK MainWindowDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PhCenterWindow(hwndDlg, PhMainWndHandle);
ListViewWndHandle = GetDlgItem(hwndDlg, IDC_ATOMLIST);
PhInitializeLayoutManager(&LayoutManager, hwndDlg);
PhAddLayoutItem(&LayoutManager, ListViewWndHandle, NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDRETRY), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
PhRegisterDialog(hwndDlg);
PhLoadWindowPlacementFromSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
PhSetListViewStyle(ListViewWndHandle, FALSE, TRUE);
PhSetControlTheme(ListViewWndHandle, L"explorer");
PhAddListViewColumn(ListViewWndHandle, 0, 0, 0, LVCFMT_LEFT, 370, L"Atom Name");
PhAddListViewColumn(ListViewWndHandle, 1, 1, 1, LVCFMT_LEFT, 70, L"Ref Count");
PhSetExtendedListView(ListViewWndHandle);
PhLoadListViewColumnsFromSetting(SETTING_NAME_LISTVIEW_COLUMNS, ListViewWndHandle);
LoadAtomTable();
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&LayoutManager);
break;
case WM_DESTROY:
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
PhSaveListViewColumnsToSetting(SETTING_NAME_LISTVIEW_COLUMNS, ListViewWndHandle);
PhDeleteLayoutManager(&LayoutManager);
PhUnregisterDialog(hwndDlg);
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
EndDialog(hwndDlg, IDOK);
break;
case IDRETRY:
LoadAtomTable();
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR hdr = (LPNMHDR)lParam;
switch (hdr->code)
{
case NM_RCLICK:
{
if (hdr->hwndFrom == ListViewWndHandle)
ShowStatusMenu(hwndDlg);
}
break;
}
}
break;
}
return FALSE;
}
VOID NTAPI MainMenuInitializingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
PPH_EMENU_ITEM systemMenu;
if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_TOOLS)
return;
if (!(systemMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"System", 0)))
{
PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, PH_EMENU_SEPARATOR, 0, L"", NULL), -1);
PhInsertEMenuItem(menuInfo->Menu, systemMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"System", NULL), -1);
}
PhInsertEMenuItem(systemMenu, PhPluginCreateEMenuItem(PluginInstance, 0, ATOM_TABLE_MENUITEM, L"Atom Table", NULL), -1);
}
VOID NTAPI MenuItemCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_ITEM menuItem = (PPH_PLUGIN_MENU_ITEM)Parameter;
switch (menuItem->Id)
{
case ATOM_TABLE_MENUITEM:
{
DialogBox(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_ATOMDIALOG),
NULL,
MainWindowDlgProc
);
}
break;
}
}
LOGICAL DllMain(
_In_ HINSTANCE Instance,
_In_ ULONG Reason,
_Reserved_ PVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
{
PPH_PLUGIN_INFORMATION info;
PH_SETTING_CREATE settings[] =
{
{ IntegerPairSettingType, SETTING_NAME_WINDOW_POSITION, L"350,350" },
{ ScalableIntegerPairSettingType, SETTING_NAME_WINDOW_SIZE, L"@96|510,380" },
{ StringSettingType, SETTING_NAME_LISTVIEW_COLUMNS, L"" }
};
PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
if (!PluginInstance)
return FALSE;
info->Author = L"dmex";
info->DisplayName = L"Global Atom Table";
info->Description = L"Plugin for viewing the Global Atom Table via the Tools menu.";
info->HasOptions = FALSE;
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackMainMenuInitializing),
MainMenuInitializingCallback,
NULL,
&MainMenuInitializingCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
MenuItemCallback,
NULL,
&PluginMenuItemCallbackRegistration
);
PhAddSettings(settings, ARRAYSIZE(settings));
}
break;
}
return TRUE;
}

View File

@ -0,0 +1,17 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by AtomTablePlugin.rc
//
#define IDD_ATOMDIALOG 101
#define IDC_ATOMLIST 1001
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40006
#define _APS_NEXT_CONTROL_VALUE 1002
#define _APS_NEXT_SYMED_VALUE 103
#endif
#endif

View File

@ -0,0 +1,100 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,0,0
PRODUCTVERSION 1,1,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0c0904b0"
BEGIN
VALUE "CompanyName", "wj32"
VALUE "FileDescription", "Average CPU plugin for Process Hacker"
VALUE "FileVersion", "1.1"
VALUE "InternalName", "wj32.AvgCpuPlugin"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "AvgCpuPlugin.dll"
VALUE "ProductName", "Average CPU plugin for Process Hacker"
VALUE "ProductVersion", "1.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1200
END
END
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}</ProjectGuid>
<RootNamespace>AvgCpuPlugin</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>AvgCpuPlugin</ProjectName>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="AvgCpuPlugin.rc" />
</ItemGroup>
<ItemGroup>
<Text Include="CHANGELOG.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="AvgCpuPlugin.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Text Include="CHANGELOG.txt" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,5 @@
1.1
* Fixed calculation bug
1.0
* Initial release

View File

@ -0,0 +1,315 @@
/*
* Process Hacker Extra Plugins -
* Average CPU Plugin
*
* Copyright (C) 2011 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include <phdk.h>
#include "resource.h"
#define COLUMN_ID_AVGCPU10 1
#define COLUMN_ID_AVGCPU60 2
#define HISTORY_SIZE 60
typedef struct _PROCESS_EXTENSION
{
LIST_ENTRY ListEntry;
PPH_PROCESS_ITEM ProcessItem;
FLOAT CpuHistory[HISTORY_SIZE];
ULONG CpuHistoryCount;
ULONG CpuHistoryPosition;
FLOAT Avg10CpuUsage;
FLOAT Avg60CpuUsage;
WCHAR Avg10CpuUsageText[PH_INT32_STR_LEN_1];
WCHAR Avg60CpuUsageText[PH_INT32_STR_LEN_1];
} PROCESS_EXTENSION, *PPROCESS_EXTENSION;
PPH_PLUGIN PluginInstance;
PH_CALLBACK_REGISTRATION TreeNewMessageCallbackRegistration;
PH_CALLBACK_REGISTRATION ProcessTreeNewInitializingCallbackRegistration;
PH_CALLBACK_REGISTRATION ProcessAddedCallbackRegistration;
PH_CALLBACK_REGISTRATION ProcessRemovedCallbackRegistration;
PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration;
LIST_ENTRY ProcessListHead = { &ProcessListHead, &ProcessListHead };
VOID TreeNewMessageCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_TREENEW_MESSAGE message = Parameter;
switch (message->Message)
{
case TreeNewGetCellText:
{
PPH_TREENEW_GET_CELL_TEXT getCellText = message->Parameter1;
PPH_PROCESS_NODE node;
PPROCESS_EXTENSION extension;
node = (PPH_PROCESS_NODE)getCellText->Node;
extension = PhPluginGetObjectExtension(PluginInstance, node->ProcessItem, EmProcessItemType);
switch (message->SubId)
{
case COLUMN_ID_AVGCPU10:
case COLUMN_ID_AVGCPU60:
{
FLOAT cpuUsage;
PWCHAR buffer;
if (message->SubId == COLUMN_ID_AVGCPU10)
{
cpuUsage = extension->Avg10CpuUsage * 100;
buffer = extension->Avg10CpuUsageText;
}
else
{
cpuUsage = extension->Avg60CpuUsage * 100;
buffer = extension->Avg60CpuUsageText;
}
if (cpuUsage >= 0.01)
{
PH_FORMAT format;
SIZE_T returnLength;
PhInitFormatF(&format, cpuUsage, 2);
if (PhFormatToBuffer(&format, 1, buffer, PH_INT32_STR_LEN_1 * sizeof(WCHAR), &returnLength))
{
getCellText->Text.Buffer = buffer;
getCellText->Text.Length = (USHORT)(returnLength - sizeof(WCHAR)); // minus null terminator
}
}
else if (cpuUsage != 0 && PhGetIntegerSetting(L"ShowCpuBelow001"))
{
PhInitializeStringRef(&getCellText->Text, L"< 0.01");
}
}
break;
}
}
break;
}
}
LONG NTAPI AvgCpuSortFunction(
_In_ PVOID Node1,
_In_ PVOID Node2,
_In_ ULONG SubId,
_In_ PVOID Context
)
{
PPH_PROCESS_NODE node1 = Node1;
PPH_PROCESS_NODE node2 = Node2;
PPROCESS_EXTENSION extension1 = PhPluginGetObjectExtension(PluginInstance, node1->ProcessItem, EmProcessItemType);
PPROCESS_EXTENSION extension2 = PhPluginGetObjectExtension(PluginInstance, node2->ProcessItem, EmProcessItemType);
switch (SubId)
{
case COLUMN_ID_AVGCPU10:
return singlecmp(extension1->Avg10CpuUsage, extension2->Avg10CpuUsage);
case COLUMN_ID_AVGCPU60:
return singlecmp(extension1->Avg60CpuUsage, extension2->Avg60CpuUsage);
}
return 0;
}
VOID ProcessTreeNewInitializingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_TREENEW_INFORMATION info = Parameter;
PH_TREENEW_COLUMN column;
memset(&column, 0, sizeof(PH_TREENEW_COLUMN));
column.SortDescending = TRUE;
column.Text = L"CPU Average (10)";
column.Width = 45;
column.Alignment = PH_ALIGN_RIGHT;
column.TextFlags = DT_RIGHT;
PhPluginAddTreeNewColumn(PluginInstance, info->CmData, &column, COLUMN_ID_AVGCPU10, NULL, AvgCpuSortFunction);
column.Text = L"CPU Average (60)";
PhPluginAddTreeNewColumn(PluginInstance, info->CmData, &column, COLUMN_ID_AVGCPU60, NULL, AvgCpuSortFunction);
}
VOID ProcessItemCreateCallback(
_In_ PVOID Object,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Extension
)
{
PPH_PROCESS_ITEM processItem = Object;
PPROCESS_EXTENSION extension = Extension;
memset(extension, 0, sizeof(PROCESS_EXTENSION));
extension->ProcessItem = processItem;
}
VOID ProcessAddedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PROCESS_ITEM processItem = Parameter;
PPROCESS_EXTENSION extension = PhPluginGetObjectExtension(PluginInstance, processItem, EmProcessItemType);
InsertTailList(&ProcessListHead, &extension->ListEntry);
}
VOID ProcessRemovedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PROCESS_ITEM processItem = Parameter;
PPROCESS_EXTENSION extension = PhPluginGetObjectExtension(PluginInstance, processItem, EmProcessItemType);
RemoveEntryList(&extension->ListEntry);
}
VOID ProcessesUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
static ULONG runCount = 0;
if (runCount != 0)
{
PLIST_ENTRY listEntry;
listEntry = ProcessListHead.Flink;
while (listEntry != &ProcessListHead)
{
PPROCESS_EXTENSION extension = CONTAINING_RECORD(listEntry, PROCESS_EXTENSION, ListEntry);
PPH_PROCESS_ITEM processItem = extension->ProcessItem;
FLOAT sum;
ULONG i;
ULONG total;
ULONG count;
if (extension->CpuHistoryPosition != 0)
extension->CpuHistoryPosition--;
else
extension->CpuHistoryPosition = HISTORY_SIZE - 1;
extension->CpuHistory[extension->CpuHistoryPosition] = processItem->CpuUsage;
if (extension->CpuHistoryCount < HISTORY_SIZE)
extension->CpuHistoryCount++;
// Calculate the 10 interval average.
sum = 0;
i = extension->CpuHistoryPosition;
total = 10;
if (total > extension->CpuHistoryCount)
total = extension->CpuHistoryCount;
count = total;
do
{
sum += extension->CpuHistory[i];
i++;
if (i == HISTORY_SIZE)
i = 0;
} while (--count != 0);
extension->Avg10CpuUsage = sum / total;
// Calculate the 60 interval average.
if (extension->CpuHistoryCount > 10)
{
total = 50;
if (total > extension->CpuHistoryCount - 10)
total = extension->CpuHistoryCount - 10;
count = total;
do
{
sum += extension->CpuHistory[i];
i++;
if (i == HISTORY_SIZE)
i = 0;
} while (--count != 0);
extension->Avg60CpuUsage = sum / (total + 10);
}
else
{
// Not enough samples.
extension->Avg60CpuUsage = extension->Avg10CpuUsage;
}
listEntry = listEntry->Flink;
}
}
runCount++;
}
LOGICAL DllMain(
_In_ HINSTANCE Instance,
_In_ ULONG Reason,
_Reserved_ PVOID Reserved
)
{
if (Reason == DLL_PROCESS_ATTACH)
{
PPH_PLUGIN_INFORMATION info;
PluginInstance = PhRegisterPlugin(L"wj32.AvgCpuPlugin", Instance, &info);
if (!PluginInstance)
return FALSE;
info->DisplayName = L"Average CPU";
info->Description = L"Adds a column to display average CPU times.";
info->Author = L"wj32";
PhRegisterCallback(PhGetPluginCallback(PluginInstance, PluginCallbackTreeNewMessage),
TreeNewMessageCallback, NULL, &TreeNewMessageCallbackRegistration);
PhRegisterCallback(PhGetGeneralCallback(GeneralCallbackProcessTreeNewInitializing),
ProcessTreeNewInitializingCallback, NULL, &ProcessTreeNewInitializingCallbackRegistration);
PhRegisterCallback(&PhProcessAddedEvent, ProcessAddedHandler, NULL, &ProcessAddedCallbackRegistration);
PhRegisterCallback(&PhProcessRemovedEvent, ProcessRemovedHandler, NULL, &ProcessRemovedCallbackRegistration);
PhRegisterCallback(&PhProcessesUpdatedEvent, ProcessesUpdatedHandler, NULL, &ProcessesUpdatedCallbackRegistration);
PhPluginSetObjectExtension(PluginInstance, EmProcessItemType, sizeof(PROCESS_EXTENSION),
ProcessItemCreateCallback, NULL);
}
return TRUE;
}

View File

@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by AvgCpuPlugin.rc
//
// 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 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,2 @@
1.0
* Initial release

View File

@ -0,0 +1,141 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0c0904b0"
BEGIN
VALUE "CompanyName", "dmex"
VALUE "FileDescription", "DbgView plugin for Process Hacker"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "dmex.DbgView"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "DbgViewPlugin.dll"
VALUE "ProductName", "DbgView plugin for Process Hacker"
VALUE "ProductVersion", "1.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DBGVIEW_DIALOG DIALOGEX 0, 0, 343, 181
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Debug View"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Close",IDCLOSE,286,160,50,14
CONTROL "",IDC_DEBUGLISTVIEW,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,5,329,152
PUSHBUTTON "Options",IDC_OPTIONS,7,160,50,14
CONTROL "Auto-scroll",IDC_AUTOSCROLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,61,164,50,10
CONTROL "Always on Top",IDC_ALWAYSONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,219,164,63,10
END
IDD_MESSAGE_DIALOG DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Message"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Close",IDCLOSE,252,155,50,14
EDITTEXT IDC_MESSAGE,7,7,295,145,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL,WS_EX_CLIENTEDGE
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DBGVIEW_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 336
TOPMARGIN, 5
BOTTOMMARGIN, 174
END
IDD_MESSAGE_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 169
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{AAD42A11-92A7-4918-A76A-862528185199}</ProjectGuid>
<RootNamespace>DbgViewPlugin</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>DbgViewPlugin</ProjectName>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="filter.c" />
<ClCompile Include="log.c" />
<ClCompile Include="main.c" />
<ClCompile Include="dialog.c" />
<ClCompile Include="message.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DbgViewPlugin.rc" />
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{f52999d5-d374-492f-b42c-0baf337ae22b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{b028ae70-b630-49a5-95b3-d9196126eb9a}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{d760553d-e87a-480a-9cbd-4e69599125b8}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="log.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="filter.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dialog.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="message.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DbgViewPlugin.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,694 @@
/*
* Process Hacker Extra Plugins -
* Debug View Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
static HANDLE DbgDialogThreadHandle = NULL;
static HWND DbgDialogHandle = NULL;
static PH_EVENT InitializedEvent = PH_EVENT_INIT;
VOID NTAPI DbgLoggedEventCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_DBGEVENTS_CONTEXT context = (PPH_DBGEVENTS_CONTEXT)Context;
if (context->DialogHandle)
{
PostMessage(context->DialogHandle, WM_DEBUG_LOG_UPDATED, 0, 0);
}
}
VOID DbgUpdateLogList(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
)
{
Context->ListViewCount = Context->LogMessageList->Count;
ListView_SetItemCountEx(Context->ListViewHandle, Context->ListViewCount, LVSICF_NOSCROLL);
if (Context->ListViewCount >= 2 && Button_GetCheck(Context->AutoScrollHandle) == BST_CHECKED)
{
if (ListView_IsItemVisible(Context->ListViewHandle, Context->ListViewCount - 2))
{
ListView_EnsureVisible(Context->ListViewHandle, Context->ListViewCount - 1, FALSE);
}
}
}
PPH_STRING DbgGetStringForSelectedLogEntries(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ BOOLEAN All
)
{
PH_STRING_BUILDER stringBuilder;
ULONG i;
if (Context->ListViewCount == 0)
return PhReferenceEmptyString();
PhInitializeStringBuilder(&stringBuilder, 0x100);
i = Context->ListViewCount - 1;
while (TRUE)
{
PDEBUG_LOG_ENTRY entry;
SYSTEMTIME systemTime;
PPH_STRING temp;
if (!All)
{
if (!(ListView_GetItemState(Context->ListViewHandle, i, LVIS_SELECTED) & LVIS_SELECTED))
{
goto ContinueLoop;
}
}
entry = Context->LogMessageList->Items[i];
if (!entry)
goto ContinueLoop;
PhLargeIntegerToLocalSystemTime(&systemTime, &entry->Time);
temp = PhFormatDateTime(&systemTime);
PhAppendStringBuilder(&stringBuilder, &temp->sr);
PhDereferenceObject(temp);
PhAppendStringBuilder2(&stringBuilder, L": ");
temp = PhFormatString(
L"%s (%lu): %s",
entry->ProcessName->Buffer, // entry->FilePath->Buffer;
HandleToUlong(entry->ProcessId),
entry->Message->Buffer
);
PhAppendStringBuilder(&stringBuilder, &temp->sr);
PhDereferenceObject(temp);
PhAppendStringBuilder2(&stringBuilder, L"\r\n");
ContinueLoop:
if (i == 0)
break;
i--;
}
return PhFinalStringBuilderString(&stringBuilder);
}
VOID ShowListViewMenu(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
)
{
INT index;
PDEBUG_LOG_ENTRY entry;
index = PhFindListViewItemByFlags(Context->ListViewHandle, -1, LVNI_SELECTED);
if (index == -1)
return;
entry = Context->LogMessageList->Items[index];
if (entry)
{
POINT cursorPos;
PPH_EMENU menu;
PPH_EMENU_ITEM selectedItem;
GetCursorPos(&cursorPos);
menu = PhCreateEMenu();
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 1, L"View Message", NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 2, L"Go to Owning &Process", NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, selectedItem = PhCreateEMenuItem(0, 0, L"E&xclude Process", NULL, NULL), -1);
PhInsertEMenuItem(selectedItem, PhCreateEMenuItem(0, 3, L"By PID", NULL, NULL), -1);
PhInsertEMenuItem(selectedItem, PhCreateEMenuItem(0, 4, L"By Name", NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 5, L"&Copy", NULL, NULL), -1);
selectedItem = PhShowEMenu(
menu,
Context->ListViewHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
cursorPos.x,
cursorPos.y
);
if (selectedItem && selectedItem->Id != -1)
{
switch (selectedItem->Id)
{
case 1:
{
DialogBoxParam(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_MESSAGE_DIALOG),
Context->DialogHandle,
DbgPropDlgProc,
(LPARAM)entry
);
}
break;
case 2:
{
PPH_PROCESS_NODE processNode;
if (processNode = PhFindProcessNode(entry->ProcessId))
{
ProcessHacker_ToggleVisible(PhMainWndHandle, TRUE);
ProcessHacker_SelectTabPage(PhMainWndHandle, 0);
ProcessHacker_SelectProcessNode(PhMainWndHandle, processNode);
}
}
break;
case 3:
{
AddFilterType(Context, FilterByPid, entry->ProcessId, entry->ProcessName);
DbgUpdateLogList(Context);
}
break;
case 4:
{
AddFilterType(Context, FilterByName, entry->ProcessId, entry->ProcessName);
DbgUpdateLogList(Context);
}
break;
case 5:
{
PPH_STRING string;
string = DbgGetStringForSelectedLogEntries(Context, FALSE);
PhSetClipboardString(Context->DialogHandle, &string->sr);
PhDereferenceObject(string);
SetFocus(Context->ListViewHandle);
}
break;
}
}
PhDestroyEMenu(menu);
}
}
VOID ShowDropdownMenu(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
)
{
RECT rect;
PPH_EMENU menu = NULL;
PPH_EMENU_ITEM selectedItem = NULL;
PPH_EMENU_ITEM resetMenuItem = NULL;
PPH_EMENU_ITEM captureMenuItem = NULL;
PPH_EMENU_ITEM captureGlobalMenuItem = NULL;
GetWindowRect(Context->OptionsHandle, &rect);
menu = PhCreateEMenu();
PhInsertEMenuItem(menu, captureMenuItem = PhCreateEMenuItem(0, ID_CAPTURE_WIN32, L"Capture Win32", NULL, NULL), -1);
PhInsertEMenuItem(menu, captureGlobalMenuItem = PhCreateEMenuItem(0, ID_CAPTURE_WIN32_GLOBAL, L"Capture Global Win32", NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, resetMenuItem = PhCreateEMenuItem(PH_EMENU_DISABLED, ID_RESET_FILTERS, L"Reset Filters", NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, ID_CLEAR_EVENTS, L"Clear", NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, ID_SAVE_EVENTS, L"Save", NULL, NULL), -1);
if (Context->ExcludeList->Count > 0)
{
resetMenuItem->Text = PhaFormatString(L"Reset Filters [%lu]", Context->ExcludeList->Count)->Buffer;
resetMenuItem->Flags &= ~PH_EMENU_DISABLED;
}
if (Context->CaptureLocalEnabled)
{
captureMenuItem->Flags |= PH_EMENU_CHECKED;
}
if (Context->CaptureGlobalEnabled)
{
captureGlobalMenuItem->Flags |= PH_EMENU_CHECKED;
}
selectedItem = PhShowEMenu(
menu,
Context->DialogHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
rect.left,
rect.bottom
);
if (selectedItem && selectedItem->Id != -1)
{
switch (selectedItem->Id)
{
case ID_CAPTURE_WIN32:
{
if (!Context->CaptureLocalEnabled)
DbgEventsCreate(Context, FALSE);
else
DbgEventsCleanup(Context, FALSE);
}
break;
case ID_CAPTURE_WIN32_GLOBAL:
{
if (!PhGetOwnTokenAttributes().Elevated)
{
PhShowInformation(Context->DialogHandle, L"This option requires elevation.");
break;
}
if (!Context->CaptureGlobalEnabled)
DbgEventsCreate(Context, TRUE);
else
DbgEventsCleanup(Context, TRUE);
}
break;
case ID_RESET_FILTERS:
{
ResetFilters(Context);
}
break;
case ID_CLEAR_EVENTS:
{
DbgClearLogEntries(Context);
DbgUpdateLogList(Context);
}
break;
case ID_SAVE_EVENTS:
{
static PH_FILETYPE_FILTER filters[] =
{
{ L"Text files (*.txt)", L"*.txt" },
{ L"All files (*.*)", L"*.*" }
};
PVOID fileDialog = PhCreateSaveFileDialog();
PhSetFileDialogFilter(fileDialog, filters, ARRAYSIZE(filters));
PhSetFileDialogFileName(fileDialog, L"DbgView.txt");
if (PhShowFileDialog(Context->DialogHandle, fileDialog))
{
NTSTATUS status;
PPH_STRING fileName;
PPH_FILE_STREAM fileStream;
PPH_STRING string;
fileName = PhGetFileDialogFileName(fileDialog);
PhAutoDereferenceObject(fileName);
if (NT_SUCCESS(status = PhCreateFileStream(
&fileStream,
fileName->Buffer,
FILE_GENERIC_WRITE,
FILE_SHARE_READ,
FILE_OVERWRITE_IF,
0
)))
{
PhWritePhTextHeader(fileStream);
string = DbgGetStringForSelectedLogEntries(Context, TRUE);
PhWriteStringAsUtf8FileStreamEx(fileStream, string->Buffer, string->Length);
PhDereferenceObject(string);
PhDereferenceObject(fileStream);
}
if (!NT_SUCCESS(status))
PhShowStatus(PhMainWndHandle, L"Unable to create the file", status, 0);
}
PhFreeFileDialog(fileDialog);
}
break;
}
}
PhDestroyEMenu(menu);
}
INT_PTR CALLBACK DbgViewDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PPH_DBGEVENTS_CONTEXT context;
if (uMsg == WM_INITDIALOG)
{
context = (PPH_DBGEVENTS_CONTEXT)PhAllocate(sizeof(PH_DBGEVENTS_CONTEXT));
memset(context, 0, sizeof(PH_DBGEVENTS_CONTEXT));
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PPH_DBGEVENTS_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_NCDESTROY)
{
RemoveProp(hwndDlg, L"Context");
PhFree(context);
}
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
PhCenterWindow(hwndDlg, PhMainWndHandle);
context->DialogHandle = hwndDlg;
context->ListViewHandle = GetDlgItem(hwndDlg, IDC_DEBUGLISTVIEW);
context->AutoScrollHandle = GetDlgItem(hwndDlg, IDC_AUTOSCROLL);
context->OptionsHandle = GetDlgItem(hwndDlg, IDC_OPTIONS);
context->LogMessageList = PhCreateList(1);
context->ExcludeList = PhCreateList(1);
PhRegisterDialog(hwndDlg);
PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE);
PhSetControlTheme(context->ListViewHandle, L"explorer");
PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 140, L"Process");
PhAddListViewColumn(context->ListViewHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Timestamp");
PhAddListViewColumn(context->ListViewHandle, 2, 2, 2, LVCFMT_LEFT, 220, L"Message");
//PhSetExtendedListView(context->ListViewHandle);
if (context->ListViewImageList = ImageList_Create(19, 19, ILC_COLOR32 | ILC_MASK, 0, 40))
{
HICON defaultIcon = PhGetFileShellIcon(NULL, L".exe", TRUE);
ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL);
ImageList_AddIcon(context->ListViewImageList, defaultIcon);
DestroyIcon(defaultIcon);
}
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&context->LayoutManager, context->OptionsHandle, NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, context->AutoScrollHandle, NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ALWAYSONTOP), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDCLOSE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
PhLoadWindowPlacementFromSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
PhLoadListViewColumnsFromSetting(SETTING_NAME_COLUMNS, context->ListViewHandle);
if (PhGetIntegerSetting(SETTING_NAME_ALWAYSONTOP))
{
context->AlwaysOnTop = TRUE;
SetFocus(hwndDlg);
SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
Button_SetCheck(GetDlgItem(hwndDlg, IDC_ALWAYSONTOP), BST_CHECKED);
}
if (PhGetIntegerSetting(SETTING_NAME_AUTOSCROLL))
{
context->AutoScroll = TRUE;
Button_SetCheck(context->AutoScrollHandle, BST_CHECKED);
}
DbgCreateSecurityAttributes(context);
DbgUpdateLogList(context);
PhRegisterCallback(&DbgLoggedCallback, DbgLoggedEventCallback, context, &context->DebugLoggedRegistration);
}
return TRUE;
case WM_DESTROY:
{
DbgEventsCleanup(context, FALSE);
DbgEventsCleanup(context, TRUE);
DbgCleanupSecurityAttributes(context);
if (context->ListViewImageList)
ImageList_Destroy(context->ListViewImageList);
if (context->ExcludeList)
{
ResetFilters(context);
PhDereferenceObject(context->ExcludeList);
}
if (context->LogMessageList)
{
DbgClearLogEntries(context);
PhDereferenceObject(context->LogMessageList);
}
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
PhSaveListViewColumnsToSetting(SETTING_NAME_COLUMNS, context->ListViewHandle);
PhDeleteLayoutManager(&context->LayoutManager);
PhUnregisterCallback(&DbgLoggedCallback, &context->DebugLoggedRegistration);
PhUnregisterDialog(hwndDlg);
PostQuitMessage(0);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
break;
case WM_SHOWDIALOG:
{
if (IsMinimized(hwndDlg))
ShowWindow(hwndDlg, SW_RESTORE);
else
ShowWindow(hwndDlg, SW_SHOW);
SetForegroundWindow(hwndDlg);
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_OPTIONS:
ShowDropdownMenu(context);
break;
case IDCLOSE:
case IDCANCEL:
DestroyWindow(hwndDlg);
break;
case IDC_AUTOSCROLL:
{
context->AutoScroll = !context->AutoScroll;
PhSetIntegerSetting(SETTING_NAME_AUTOSCROLL, context->AutoScroll);
Button_SetCheck(context->AutoScrollHandle, context->AutoScroll ? BST_CHECKED : BST_UNCHECKED);
}
break;
case IDC_ALWAYSONTOP:
{
context->AlwaysOnTop = !context->AlwaysOnTop;
SetWindowPos(hwndDlg, context->AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
PhSetIntegerSetting(SETTING_NAME_ALWAYSONTOP, context->AlwaysOnTop);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR hdr = (LPNMHDR)lParam;
switch (hdr->code)
{
case NM_RCLICK:
{
if (hdr->hwndFrom == context->ListViewHandle)
{
ShowListViewMenu(context);
}
}
break;
case NM_DBLCLK:
{
PDEBUG_LOG_ENTRY entry;
INT index;
index = PhFindListViewItemByFlags(context->ListViewHandle, -1, LVNI_SELECTED);
if (index == -1)
break;
entry = context->LogMessageList->Items[index];
DialogBoxParam(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_MESSAGE_DIALOG),
hwndDlg,
DbgPropDlgProc,
(LPARAM)entry
);
}
break;
case LVN_GETDISPINFO:
{
NMLVDISPINFO* dispInfo = (NMLVDISPINFO*)hdr;
PDEBUG_LOG_ENTRY entry;
entry = context->LogMessageList->Items[dispInfo->item.iItem];
if (dispInfo->item.mask & LVIF_IMAGE)
{
dispInfo->item.iImage = entry->ImageIndex;
}
if (dispInfo->item.iSubItem == 0)
{
if (dispInfo->item.mask & LVIF_TEXT)
{
wcsncpy_s(
dispInfo->item.pszText,
dispInfo->item.cchTextMax,
entry->ProcessName->Buffer,
_TRUNCATE
);
}
}
else if (dispInfo->item.iSubItem == 1)
{
if (dispInfo->item.mask & LVIF_TEXT)
{
SYSTEMTIME systemTime;
PPH_STRING dateTime;
PPH_STRING dateString;
PhLargeIntegerToLocalSystemTime(&systemTime, &entry->Time);
dateTime = PhFormatTime(&systemTime, L"hh:mm:ss");
dateString = PhFormatString(
L"%s.%u",
dateTime->Buffer,
systemTime.wMilliseconds
);
wcsncpy_s(
dispInfo->item.pszText,
dispInfo->item.cchTextMax,
dateString->Buffer,
_TRUNCATE
);
PhDereferenceObject(dateString);
PhDereferenceObject(dateTime);
}
}
else if (dispInfo->item.iSubItem == 2)
{
if (dispInfo->item.mask & LVIF_TEXT)
{
wcsncpy_s(
dispInfo->item.pszText,
dispInfo->item.cchTextMax,
entry->Message->Buffer,
_TRUNCATE
);
}
}
}
break;
}
}
break;
case WM_DEBUG_LOG_UPDATED:
DbgUpdateLogList(context);
break;
}
return FALSE;
}
NTSTATUS DbgViewDialogThread(
_In_ PVOID Parameter
)
{
BOOL result;
MSG message;
PH_AUTO_POOL autoPool;
PhInitializeAutoPool(&autoPool);
DbgDialogHandle = CreateDialog(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_DBGVIEW_DIALOG),
NULL,
DbgViewDlgProc
);
PhSetEvent(&InitializedEvent);
while (result = GetMessage(&message, NULL, 0, 0))
{
if (result == -1)
break;
if (!IsDialogMessage(DbgDialogHandle, &message))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
PhDrainAutoPool(&autoPool);
}
PhDeleteAutoPool(&autoPool);
PhResetEvent(&InitializedEvent);
if (DbgDialogThreadHandle)
{
NtClose(DbgDialogThreadHandle);
DbgDialogThreadHandle = NULL;
}
return STATUS_SUCCESS;
}
VOID ShowDebugEventsDialog(
VOID
)
{
if (!DbgDialogThreadHandle)
{
if (!(DbgDialogThreadHandle = PhCreateThread(0, DbgViewDialogThread, NULL)))
{
PhShowStatus(PhMainWndHandle, L"Unable to create the window.", 0, GetLastError());
return;
}
PhWaitForEvent(&InitializedEvent, NULL);
}
PostMessage(DbgDialogHandle, WM_SHOWDIALOG, 0, 0);
}

View File

@ -0,0 +1,81 @@
/*
* Process Hacker Extra Plugins -
* Debug View Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
VOID AddFilterType(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ FILTER_BY_TYPE Type,
_In_ HANDLE ProcessID,
_In_ PPH_STRING ProcessName
)
{
PDBG_FILTER_TYPE newFilterEntry;
newFilterEntry = PhAllocate(sizeof(DBG_FILTER_TYPE));
newFilterEntry->Type = Type;
newFilterEntry->ProcessId = ProcessID;
newFilterEntry->ProcessName = ProcessName;
PhAddItemList(Context->ExcludeList, newFilterEntry);
// Remove any existing entries...
for (ULONG i = 0; i < Context->LogMessageList->Count; i++)
{
PDEBUG_LOG_ENTRY listEntry = Context->LogMessageList->Items[i];
if (Type == FilterByName)
{
if (PhEqualString(listEntry->ProcessName, newFilterEntry->ProcessName, TRUE))
{
PhRemoveItemList(Context->LogMessageList, i);
i--;
}
}
else if (Type == FilterByPid)
{
if (listEntry->ProcessId == ProcessID)
{
PhRemoveItemList(Context->LogMessageList, i);
i--;
}
}
}
}
VOID ResetFilters(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
)
{
for (ULONG i = 0; i < Context->ExcludeList->Count; i++)
{
PDBG_FILTER_TYPE filterEntry = Context->ExcludeList->Items[i];
if (filterEntry->ProcessName)
PhDereferenceObject(filterEntry->ProcessName);
PhFree(filterEntry);
PhRemoveItemList(Context->ExcludeList, i);
i--;
}
}

View File

@ -0,0 +1,495 @@
/*
* Process Hacker Extra Plugins -
* Debug View Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
PH_CALLBACK_DECLARE(DbgLoggedCallback);
VOID DbgFreeLogEntry(
_Inout_ PDEBUG_LOG_ENTRY Entry
)
{
PhClearReference(&Entry->FilePath);
PhClearReference(&Entry->ProcessName);
PhClearReference(&Entry->Message);
PhFree(Entry);
}
VOID DbgAddLogEntry(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ PDEBUG_LOG_ENTRY Entry
)
{
if (Context->LogMessageList->Count > PhGetIntegerSetting(SETTING_NAME_MAX_ENTRIES))
{
DbgFreeLogEntry(Context->LogMessageList->Items[0]);
PhRemoveItemList(Context->LogMessageList, 0);
}
PhAddItemList(Context->LogMessageList, Entry);
PhInvokeCallback(&DbgLoggedCallback, Entry);
}
VOID DbgClearLogEntries(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
)
{
for (ULONG i = 0; i < Context->LogMessageList->Count; i++)
{
if (Context->LogMessageList->Items[i])
{
DbgFreeLogEntry(Context->LogMessageList->Items[i]);
}
}
PhClearList(Context->LogMessageList);
}
VOID DbgShowErrorMessage(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ PWSTR Type
)
{
ULONG errorCode = GetLastError();
PPH_STRING errorMessage = PhGetWin32Message(errorCode);
if (errorMessage)
{
PhShowError(Context->DialogHandle, PhaFormatString(L"%s: [%u] %s", Type, errorCode, errorMessage->Buffer)->Buffer);
PhDereferenceObject(errorMessage);
}
}
VOID DbgFormatObjectName(
_In_ BOOLEAN LocalName,
_In_ PWSTR OriginalName,
_Out_ PUNICODE_STRING ObjectName
)
{
SIZE_T length;
SIZE_T originalNameLength;
// Sessions other than session 0 require SeCreateGlobalPrivilege.
if (LocalName && NtCurrentPeb()->SessionId != 0)
{
WCHAR buffer[256] = L"";
memcpy(buffer, L"\\Sessions\\", 10 * sizeof(WCHAR));
_ultow(NtCurrentPeb()->SessionId, buffer + 10, 10);
length = PhCountStringZ(buffer);
originalNameLength = PhCountStringZ(OriginalName);
memcpy(buffer + length, OriginalName, (originalNameLength + 1) * sizeof(WCHAR));
length += originalNameLength;
ObjectName->Buffer = buffer;
ObjectName->MaximumLength = (ObjectName->Length = (USHORT)(length * sizeof(WCHAR))) + sizeof(WCHAR);
}
else
{
RtlInitUnicodeString(ObjectName, OriginalName);
}
}
VOID DbgProcessLogMessageEntry(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ BOOLEAN GlobalEvents
)
{
NTSTATUS status;
PDBWIN_PAGE_BUFFER debugMessageBuffer;
PDEBUG_LOG_ENTRY entry = NULL;
HANDLE processHandle = NULL;
PPH_STRING fileName = NULL;
HICON icon = NULL;
debugMessageBuffer = GlobalEvents ? Context->GlobalDebugBuffer : Context->LocalDebugBuffer;
entry = PhAllocate(sizeof(DEBUG_LOG_ENTRY));
memset(entry, 0, sizeof(DEBUG_LOG_ENTRY));
PhQuerySystemTime(&entry->Time);
entry->ProcessId = UlongToHandle(debugMessageBuffer->ProcessId);
entry->Message = PhConvertMultiByteToUtf16(debugMessageBuffer->Buffer);
if (WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID)
{
status = PhGetProcessImageFileNameByProcessId(entry->ProcessId, &fileName);
}
else
{
if (NT_SUCCESS(status = PhOpenProcess(&processHandle, ProcessQueryAccess, entry->ProcessId)))
{
status = PhGetProcessImageFileName(processHandle, &fileName);
NtClose(processHandle);
}
}
if (!NT_SUCCESS(status))
fileName = PhGetKernelFileName();
PhMoveReference(&fileName, PhGetFileName(fileName));
icon = PhGetFileShellIcon(PhGetString(fileName), L".exe", TRUE);
if (icon)
{
entry->ImageIndex = ImageList_AddIcon(Context->ListViewImageList, icon);
DestroyIcon(icon);
}
entry->FilePath = fileName;
entry->ProcessName = PhGetBaseName(fileName);
// Drop event if it matches a filter
for (ULONG i = 0; i < Context->ExcludeList->Count; i++)
{
PDBG_FILTER_TYPE filterEntry = Context->ExcludeList->Items[i];
if (filterEntry->Type == FilterByName)
{
if (PhEqualString(filterEntry->ProcessName, entry->ProcessName, TRUE))
{
DbgFreeLogEntry(entry);
return;
}
}
else if (filterEntry->Type == FilterByPid)
{
if (filterEntry->ProcessId == entry->ProcessId)
{
DbgFreeLogEntry(entry);
return;
}
}
}
DbgAddLogEntry(Context, entry);
}
NTSTATUS DbgEventsLocalThread(
_In_ PVOID Parameter
)
{
LARGE_INTEGER timeout;
NTSTATUS status;
PPH_DBGEVENTS_CONTEXT context = (PPH_DBGEVENTS_CONTEXT)Parameter;
while (TRUE)
{
NtSetEvent(context->LocalBufferReadyEvent, NULL);
status = NtWaitForSingleObject(
context->LocalDataReadyEvent,
FALSE,
PhTimeoutFromMilliseconds(&timeout, 100)
);
if (status == STATUS_TIMEOUT)
continue;
if (status != STATUS_SUCCESS)
break;
// The process calling OutputDebugString is blocked here...
// This gives us some time to extract information without the process exiting.
DbgProcessLogMessageEntry(context, FALSE);
}
return STATUS_SUCCESS;
}
NTSTATUS DbgEventsGlobalThread(
_In_ PVOID Parameter
)
{
LARGE_INTEGER timeout;
NTSTATUS status;
PPH_DBGEVENTS_CONTEXT context = (PPH_DBGEVENTS_CONTEXT)Parameter;
while (TRUE)
{
NtSetEvent(context->GlobalBufferReadyEvent, NULL);
status = NtWaitForSingleObject(
context->GlobalDataReadyEvent,
FALSE,
PhTimeoutFromMilliseconds(&timeout, 100)
);
if (status == STATUS_TIMEOUT)
continue;
if (status != STATUS_SUCCESS)
break;
// The process calling OutputDebugString is blocked here...
// This gives us some time to extract information without the process exiting.
DbgProcessLogMessageEntry(context, TRUE);
}
return STATUS_SUCCESS;
}
BOOLEAN DbgCreateSecurityAttributes(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
)
{
Context->SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
Context->SecurityAttributes.bInheritHandle = TRUE;
if (ConvertStringSecurityDescriptorToSecurityDescriptor(
L"D:(A;;GRGWGX;;;WD)(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRGWGX;;;AN)(A;;GRGWGX;;;RC)(A;;GRGWGX;;;S-1-15-2-1)S:(ML;;NW;;;LW)",
SDDL_REVISION,
&Context->SecurityAttributes.lpSecurityDescriptor,
NULL
))
{
return TRUE;
}
return FALSE;
}
BOOLEAN DbgCleanupSecurityAttributes(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
)
{
if (Context->SecurityAttributes.lpSecurityDescriptor)
{
LocalFree(Context->SecurityAttributes.lpSecurityDescriptor);
Context->SecurityAttributes.lpSecurityDescriptor = NULL;
return TRUE;
}
return FALSE;
}
BOOLEAN DbgEventsCreate(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ BOOLEAN GlobalEvents
)
{
if (GlobalEvents)
{
SIZE_T viewSize;
LARGE_INTEGER maximumSize;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING objectName;
HANDLE threadHandle = NULL;
maximumSize.QuadPart = PAGE_SIZE;
viewSize = sizeof(DBWIN_PAGE_BUFFER);
if (!(Context->GlobalBufferReadyEvent = CreateEvent(&Context->SecurityAttributes, FALSE, FALSE, L"Global\\" DBWIN_BUFFER_READY)))
{
DbgShowErrorMessage(Context, L"DBWIN_BUFFER_READY");
return FALSE;
}
if (!(Context->GlobalDataReadyEvent = CreateEvent(&Context->SecurityAttributes, FALSE, FALSE, L"Global\\" DBWIN_DATA_READY)))
{
DbgShowErrorMessage(Context, L"DBWIN_DATA_READY");
return FALSE;
}
DbgFormatObjectName(FALSE, DBWIN_BUFFER_SECTION_NAME, &objectName);
InitializeObjectAttributes(
&objectAttributes,
&objectName,
OBJ_CASE_INSENSITIVE,
NULL,
Context->SecurityAttributes.lpSecurityDescriptor
);
if (!NT_SUCCESS(NtCreateSection(
&Context->GlobalDataBufferHandle,
STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
&objectAttributes,
&maximumSize,
PAGE_READWRITE,
SEC_COMMIT,
NULL
)))
{
DbgShowErrorMessage(Context, L"NtCreateSection");
return FALSE;
}
if (!NT_SUCCESS(NtMapViewOfSection(
Context->GlobalDataBufferHandle,
NtCurrentProcess(),
&Context->GlobalDebugBuffer,
0,
0,
NULL,
&viewSize,
ViewShare,
0,
PAGE_READONLY
)))
{
DbgShowErrorMessage(Context, L"NtMapViewOfSection");
return FALSE;
}
Context->CaptureGlobalEnabled = TRUE;
if (threadHandle = PhCreateThread(0, DbgEventsGlobalThread, Context))
{
NtClose(threadHandle);
}
}
else
{
SIZE_T viewSize;
LARGE_INTEGER maximumSize;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING objectName;
HANDLE threadHandle = NULL;
maximumSize.QuadPart = PAGE_SIZE;
viewSize = sizeof(DBWIN_PAGE_BUFFER);
if (!(Context->LocalBufferReadyEvent = CreateEvent(&Context->SecurityAttributes, FALSE, FALSE, L"Local\\" DBWIN_BUFFER_READY)))
{
DbgShowErrorMessage(Context, L"DBWIN_BUFFER_READY");
return FALSE;
}
if (!(Context->LocalDataReadyEvent = CreateEvent(&Context->SecurityAttributes, FALSE, FALSE, L"Local\\" DBWIN_DATA_READY)))
{
DbgShowErrorMessage(Context, L"DBWIN_DATA_READY");
return FALSE;
}
DbgFormatObjectName(TRUE, DBWIN_BUFFER_SECTION_NAME, &objectName);
InitializeObjectAttributes(
&objectAttributes,
&objectName,
OBJ_CASE_INSENSITIVE,
NULL,
Context->SecurityAttributes.lpSecurityDescriptor
);
if (!NT_SUCCESS(NtCreateSection(
&Context->LocalDataBufferHandle,
STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
&objectAttributes,
&maximumSize,
PAGE_READWRITE,
SEC_COMMIT,
NULL
)))
{
DbgShowErrorMessage(Context, L"NtCreateSection");
return FALSE;
}
if (!NT_SUCCESS(NtMapViewOfSection(
Context->LocalDataBufferHandle,
NtCurrentProcess(),
&Context->LocalDebugBuffer,
0,
0,
NULL,
&viewSize,
ViewShare,
0,
PAGE_READONLY
)))
{
DbgShowErrorMessage(Context, L"NtMapViewOfSection");
return FALSE;
}
Context->CaptureLocalEnabled = TRUE;
if (threadHandle = PhCreateThread(0, DbgEventsLocalThread, Context))
{
NtClose(threadHandle);
}
}
return TRUE;
}
VOID DbgEventsCleanup(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ BOOLEAN CleanupGlobal
)
{
if (CleanupGlobal)
{
Context->CaptureGlobalEnabled = FALSE;
if (Context->GlobalDebugBuffer)
{
NtUnmapViewOfSection(NtCurrentProcess(), Context->GlobalDebugBuffer);
Context->GlobalDebugBuffer = NULL;
}
if (Context->GlobalDataBufferHandle)
{
NtClose(Context->GlobalDataBufferHandle);
Context->GlobalDataBufferHandle = NULL;
}
if (Context->GlobalBufferReadyEvent)
{
NtClose(Context->GlobalBufferReadyEvent);
Context->GlobalBufferReadyEvent = NULL;
}
if (Context->GlobalDataReadyEvent)
{
NtClose(Context->GlobalDataReadyEvent);
Context->GlobalDataReadyEvent = NULL;
}
}
else
{
Context->CaptureLocalEnabled = FALSE;
if (Context->LocalDebugBuffer)
{
NtUnmapViewOfSection(NtCurrentProcess(), Context->LocalDebugBuffer);
Context->LocalDebugBuffer = NULL;
}
if (Context->LocalDataBufferHandle)
{
NtClose(Context->LocalDataBufferHandle);
Context->LocalDataBufferHandle = NULL;
}
if (Context->LocalBufferReadyEvent)
{
NtClose(Context->LocalBufferReadyEvent);
Context->LocalBufferReadyEvent = NULL;
}
if (Context->LocalDataReadyEvent)
{
NtClose(Context->LocalDataReadyEvent);
Context->LocalDataReadyEvent = NULL;
}
}
}

View File

@ -0,0 +1,115 @@
/*
* Process Hacker Extra Plugins -
* Debug View Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
PPH_PLUGIN PluginInstance;
static PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
static PH_CALLBACK_REGISTRATION MainMenuInitializingCallbackRegistration;
VOID NTAPI MainMenuInitializingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
PPH_EMENU_ITEM systemMenu;
PPH_EMENU_ITEM bootMenuItem;
if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_TOOLS)
return;
if (!(systemMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"System", 0)))
{
PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, PH_EMENU_SEPARATOR, 0, L"", NULL), -1);
PhInsertEMenuItem(menuInfo->Menu, systemMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"System", NULL), -1);
}
PhInsertEMenuItem(systemMenu, bootMenuItem = PhPluginCreateEMenuItem(PluginInstance, 0, DBGVIEW_MENUITEM, L"Debug View", NULL), -1);
}
VOID NTAPI MenuItemCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_ITEM menuItem = (PPH_PLUGIN_MENU_ITEM)Parameter;
switch (menuItem->Id)
{
case DBGVIEW_MENUITEM:
ShowDebugEventsDialog();
break;
}
}
LOGICAL DllMain(
_In_ HINSTANCE Instance,
_In_ ULONG Reason,
_Reserved_ PVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
{
PPH_PLUGIN_INFORMATION info;
PH_SETTING_CREATE settings[] =
{
{ IntegerPairSettingType, SETTING_NAME_WINDOW_POSITION, L"350,350" },
{ ScalableIntegerPairSettingType, SETTING_NAME_WINDOW_SIZE, L"@96|510,380" },
{ StringSettingType, SETTING_NAME_COLUMNS, L"" },
{ IntegerSettingType, SETTING_NAME_ALWAYSONTOP, L"0" },
{ IntegerSettingType, SETTING_NAME_AUTOSCROLL, L"1" },
{ IntegerSettingType, SETTING_NAME_MAX_ENTRIES, L"2048" }
};
PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
if (!PluginInstance)
return FALSE;
info->DisplayName = L"Debug View";
info->Author = L"dmex";
info->Description = L"Plugin for viewing Win32 debug output via the Tools menu.";
info->HasOptions = FALSE;
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackMainMenuInitializing),
MainMenuInitializingCallback,
NULL,
&MainMenuInitializingCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
MenuItemCallback,
NULL,
&PluginMenuItemCallbackRegistration
);
PhAddSettings(settings, ARRAYSIZE(settings));
}
break;
}
return TRUE;
}

View File

@ -0,0 +1,178 @@
/*
* Process Hacker Extra Plugins -
* Debug View Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBG_H_
#define _DBG_H_
#define PLUGIN_NAME L"dmex.DbgView"
#define SETTING_NAME_WINDOW_POSITION (PLUGIN_NAME L".WindowPosition")
#define SETTING_NAME_WINDOW_SIZE (PLUGIN_NAME L".WindowSize")
#define SETTING_NAME_COLUMNS (PLUGIN_NAME L".WindowColumns")
#define SETTING_NAME_ALWAYSONTOP (PLUGIN_NAME L".AlwaysOnTop")
#define SETTING_NAME_AUTOSCROLL (PLUGIN_NAME L".AutoScroll")
#define SETTING_NAME_MAX_ENTRIES (PLUGIN_NAME L".MaxEntries")
#define DBGVIEW_MENUITEM 1000
#define WM_SHOWDIALOG (WM_APP + 100)
#define WM_DEBUG_LOG_UPDATED (WM_APP + 101)
#define CINTERFACE
#define COBJMACROS
#include <phdk.h>
#include <phappresource.h>
#include <windowsx.h>
#include <Sddl.h>
#include "resource.h"
#define DBWIN_BUFFER_READY L"DBWIN_BUFFER_READY"
#define DBWIN_DATA_READY L"DBWIN_DATA_READY"
#define DBWIN_BUFFER L"DBWIN_BUFFER"
#define DBWIN_BUFFER_READY_OBJECT_NAME L"\\BaseNamedObjects\\DBWIN_BUFFER_READY"
#define DBWIN_DATA_READY_OBJECT_NAME L"\\BaseNamedObjects\\DBWIN_DATA_READY"
#define DBWIN_BUFFER_SECTION_NAME L"\\BaseNamedObjects\\DBWIN_BUFFER"
// The Win32 OutputDebugString buffer.
typedef struct _DBWIN_PAGE_BUFFER
{
ULONG ProcessId; /** The ID of the process. */
CHAR Buffer[PAGE_SIZE - sizeof(ULONG)]; /** The buffer containing the debug message. */
} DBWIN_PAGE_BUFFER, *PDBWIN_PAGE_BUFFER;
extern PPH_PLUGIN PluginInstance;
extern PH_CALLBACK DbgLoggedCallback;
typedef enum _FILTER_BY_TYPE
{
FilterByUnknown,
FilterByPid,
FilterByName
} FILTER_BY_TYPE;
typedef struct _DBG_FILTER_TYPE
{
FILTER_BY_TYPE Type;
HANDLE ProcessId;
PPH_STRING ProcessName;
} DBG_FILTER_TYPE, *PDBG_FILTER_TYPE;
typedef enum _COMMAND_ID
{
ID_CAPTURE_WIN32 = 1,
ID_CAPTURE_WIN32_GLOBAL,
ID_RESET_FILTERS,
ID_CLEAR_EVENTS,
ID_SAVE_EVENTS,
} COMMAND_ID;
typedef struct _PH_DBGEVENTS_CONTEXT
{
BOOLEAN AlwaysOnTop;
BOOLEAN AutoScroll;
BOOLEAN CaptureLocalEnabled;
BOOLEAN CaptureGlobalEnabled;
ULONG ListViewCount;
HWND DialogHandle;
HWND ListViewHandle;
HWND AutoScrollHandle;
HWND OptionsHandle;
HIMAGELIST ListViewImageList;
PH_LAYOUT_MANAGER LayoutManager;
PH_CALLBACK_REGISTRATION DebugLoggedRegistration;
SECURITY_ATTRIBUTES SecurityAttributes;
PPH_LIST ExcludeList;
PPH_LIST LogMessageList;
HANDLE LocalBufferReadyEvent;
HANDLE LocalDataReadyEvent;
HANDLE LocalDataBufferHandle;
PDBWIN_PAGE_BUFFER LocalDebugBuffer;
HANDLE GlobalBufferReadyEvent;
HANDLE GlobalDataReadyEvent;
HANDLE GlobalDataBufferHandle;
PDBWIN_PAGE_BUFFER GlobalDebugBuffer;
} PH_DBGEVENTS_CONTEXT, *PPH_DBGEVENTS_CONTEXT;
typedef struct _DEBUG_LOG_ENTRY
{
INT ImageIndex;
LARGE_INTEGER Time;
HANDLE ProcessId;
PPH_STRING Message;
PPH_STRING ProcessName;
PPH_STRING FilePath;
} DEBUG_LOG_ENTRY, *PDEBUG_LOG_ENTRY;
INT_PTR CALLBACK DbgPropDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID ShowDebugEventsDialog(
VOID
);
// log.c
VOID DbgClearLogEntries(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
);
BOOLEAN DbgCreateSecurityAttributes(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
);
BOOLEAN DbgCleanupSecurityAttributes(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
);
BOOLEAN DbgEventsCreate(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ BOOLEAN GlobalEvents
);
VOID DbgEventsCleanup(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ BOOLEAN CleanupGlobal
);
// Filter.c
VOID AddFilterType(
_Inout_ PPH_DBGEVENTS_CONTEXT Context,
_In_ FILTER_BY_TYPE Type,
_In_ HANDLE ProcessID,
_In_ PPH_STRING ProcessName
);
VOID ResetFilters(
_Inout_ PPH_DBGEVENTS_CONTEXT Context
);
#endif

View File

@ -0,0 +1,87 @@
/*
* Process Hacker Extra Plugins -
* Debug View Plugin
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
static PH_LAYOUT_MANAGER LayoutManager;
INT_PTR CALLBACK DbgPropDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PDEBUG_LOG_ENTRY entry = (PDEBUG_LOG_ENTRY)lParam;
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
PhInitializeLayoutManager(&LayoutManager, hwndDlg);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDCLOSE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
Edit_SetText(GetDlgItem(hwndDlg, IDC_MESSAGE), entry->Message->Buffer);
//SendMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), WM_SETFONT, (WPARAM)PhApplicationFont, FALSE);
}
return TRUE;
case WM_DESTROY:
PhDeleteLayoutManager(&LayoutManager);
break;
case WM_SIZE:
PhLayoutManagerLayout(&LayoutManager);
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDCLOSE:
EndDialog(hwndDlg, IDOK);
break;
}
}
break;
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
{
HDC hDC = (HDC)wParam;
HWND hwndChild = (HWND)lParam;
// Check for our static label and change the color.
if (GetDlgCtrlID(hwndChild) == IDC_MESSAGE)
{
SetBkMode(hDC, TRANSPARENT);
// set window background color.
return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
}
}
break;
}
return FALSE;
}

View File

@ -0,0 +1,22 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by DbgViewPlugin.rc
//
#define IDD_DBGVIEW_DIALOG 101
#define IDD_MESSAGE_DIALOG 103
#define IDC_DEBUGLISTVIEW 1001
#define IDC_MESSAGE 1002
#define IDC_OPTIONS 1003
#define IDC_AUTOSCROLL 1004
#define IDC_ALWAYSONTOP 1005
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40006
#define _APS_NEXT_CONTROL_VALUE 1006
#define _APS_NEXT_SYMED_VALUE 105
#endif
#endif

View File

@ -0,0 +1,4 @@
1.0
* Initial release

View File

@ -0,0 +1,123 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DNSVIEW DIALOGEX 0, 0, 325, 181
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "DNS Resolver Cache"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Close",IDOK,269,160,50,14
CONTROL "",IDC_DNSLIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,5,312,152
PUSHBUTTON "Refresh",IDC_DNS_REFRESH,7,160,50,14
PUSHBUTTON "Flush",IDC_DNS_CLEAR,62,160,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DNSVIEW, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 318
TOPMARGIN, 5
BOTTOMMARGIN, 174
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0c0904b0"
BEGIN
VALUE "CompanyName", "dmex"
VALUE "FileDescription", "DnsCachePlugin plugin for Process Hacker"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "dmex.DnsCachePlugin"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "DnsCachePlugin.dll"
VALUE "ProductName", "DnsCachePlugin plugin for Process Hacker"
VALUE "ProductVersion", "1.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1200
END
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{34E39D39-7148-45BF-9B36-DEF53E534A11}</ProjectGuid>
<RootNamespace>DnsCachePlugin</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>DnsCachePlugin</ProjectName>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<AdditionalDependencies>dnsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>dnsapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
<AdditionalDependencies>dnsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>dnsapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<AdditionalDependencies>dnsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>dnsapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<AdditionalDependencies>dnsapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>dnsapi.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DnsCachePlugin.rc" />
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{f52999d5-d374-492f-b42c-0baf337ae22b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{b028ae70-b630-49a5-95b3-d9196126eb9a}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{d760553d-e87a-480a-9cbd-4e69599125b8}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DnsCachePlugin.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,434 @@
/*
* Process Hacker Extra Plugins -
* DNS Cache Plugin
*
* Copyright (C) 2014 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
static HINSTANCE DnsApiHandle = NULL;
static _DnsGetCacheDataTable DnsGetCacheDataTable_I = NULL;
static _DnsFlushResolverCache DnsFlushResolverCache_I = NULL;
static _DnsFlushResolverCacheEntry DnsFlushResolverCacheEntry_I = NULL;
static HWND ListViewWndHandle;
static PH_LAYOUT_MANAGER LayoutManager;
static PPH_PLUGIN PluginInstance;
static PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
static PH_CALLBACK_REGISTRATION MainMenuInitializingCallbackRegistration;
static PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration;
VOID EnumDnsCacheTable(
_In_ HWND hwndDlg
)
{
PDNS_CACHE_ENTRY dnsCacheDataTable = NULL;
__try
{
if (!DnsGetCacheDataTable_I(&dnsCacheDataTable))
__leave;
while (dnsCacheDataTable)
{
PDNS_RECORD dnsQueryResultPtr = NULL;
DNS_STATUS dnsStatus = DnsQuery(
dnsCacheDataTable->Name,
dnsCacheDataTable->Type,
DNS_QUERY_NO_WIRE_QUERY | 32768, // Undocumented flags
NULL,
&dnsQueryResultPtr,
NULL
);
if (dnsStatus == ERROR_SUCCESS)
{
PDNS_RECORD dnsRecordPtr = dnsQueryResultPtr;
while (dnsRecordPtr)
{
INT itemIndex = MAXINT;
ULONG ipAddrStringLength = INET6_ADDRSTRLEN;
TCHAR ipAddrString[INET6_ADDRSTRLEN] = L"";
itemIndex = PhAddListViewItem(hwndDlg, MAXINT,
PhaFormatString(L"%s", dnsCacheDataTable->Name)->Buffer,
NULL
);
if (dnsRecordPtr->wType == DNS_TYPE_A)
{
IN_ADDR ipv4Address = { 0 };
ipv4Address.s_addr = dnsRecordPtr->Data.A.IpAddress;
RtlIpv4AddressToString(&ipv4Address, ipAddrString);
PhSetListViewSubItem(hwndDlg, itemIndex, 1, PhaFormatString(L"A")->Buffer);
PhSetListViewSubItem(hwndDlg, itemIndex, 2, PhaFormatString(L"%s", ipAddrString)->Buffer);
}
else if (dnsRecordPtr->wType == DNS_TYPE_AAAA)
{
IN6_ADDR ipv6Address = { 0 };
memcpy_s(
ipv6Address.s6_addr,
sizeof(ipv6Address.s6_addr),
dnsRecordPtr->Data.AAAA.Ip6Address.IP6Byte,
sizeof(dnsRecordPtr->Data.AAAA.Ip6Address.IP6Byte)
);
RtlIpv6AddressToString(&ipv6Address, ipAddrString);
PhSetListViewSubItem(hwndDlg, itemIndex, 1, PhaFormatString(L"AAAA")->Buffer);
PhSetListViewSubItem(hwndDlg, itemIndex, 2, PhaFormatString(L"%s", ipAddrString)->Buffer);
}
else if (dnsRecordPtr->wType == DNS_TYPE_PTR)
{
PhSetListViewSubItem(hwndDlg, itemIndex, 1, PhaFormatString(L"PTR")->Buffer);
PhSetListViewSubItem(hwndDlg, itemIndex, 2, PhaFormatString(L"%s", dnsRecordPtr->Data.PTR.pNameHost)->Buffer);
}
else if (dnsRecordPtr->wType == DNS_TYPE_CNAME)
{
PhSetListViewSubItem(hwndDlg, itemIndex, 1, PhaFormatString(L"CNAME")->Buffer);
PhSetListViewSubItem(hwndDlg, itemIndex, 2, PhaFormatString(L"%s", dnsRecordPtr->Data.CNAME.pNameHost)->Buffer);
}
else
{
PhSetListViewSubItem(hwndDlg, itemIndex, 1, PhaFormatString(L"UNKNOWN")->Buffer);
PhSetListViewSubItem(hwndDlg, itemIndex, 2, PhaFormatString(L"")->Buffer);
}
PhSetListViewSubItem(hwndDlg, itemIndex, 3, PhaFormatString(L"%lu", dnsRecordPtr->dwTtl)->Buffer);
dnsRecordPtr = dnsRecordPtr->pNext;
}
DnsRecordListFree(dnsQueryResultPtr, DnsFreeRecordList);
}
dnsCacheDataTable = dnsCacheDataTable->Next;
}
}
__finally
{
if (dnsCacheDataTable)
{
DnsRecordListFree(dnsCacheDataTable, DnsFreeRecordList);
}
}
}
PPH_STRING PhGetSelectedListViewItemText(
_In_ HWND hWnd
)
{
INT index = PhFindListViewItemByFlags(
hWnd,
-1,
LVNI_SELECTED
);
if (index != -1)
{
WCHAR textBuffer[MAX_PATH] = L"";
LVITEM item;
item.mask = LVIF_TEXT;
item.iItem = index;
item.iSubItem = 0;
item.pszText = textBuffer;
item.cchTextMax = ARRAYSIZE(textBuffer);
if (ListView_GetItem(hWnd, &item))
return PhCreateString(textBuffer);
}
return NULL;
}
VOID ShowStatusMenu(
_In_ HWND hwndDlg
)
{
PPH_STRING cacheEntryName;
cacheEntryName = PhGetSelectedListViewItemText(ListViewWndHandle);
if (cacheEntryName)
{
POINT cursorPos;
PPH_EMENU menu;
PPH_EMENU_ITEM selectedItem;
GetCursorPos(&cursorPos);
menu = PhCreateEMenu();
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, 1, L"Remove", NULL, NULL), -1);
selectedItem = PhShowEMenu(
menu,
PhMainWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
cursorPos.x,
cursorPos.y
);
if (selectedItem && selectedItem->Id != -1)
{
switch (selectedItem->Id)
{
case 1:
{
INT lvItemIndex = PhFindListViewItemByFlags(
ListViewWndHandle,
-1,
LVNI_SELECTED
);
if (lvItemIndex != -1)
{
if (!PhGetIntegerSetting(L"EnableWarnings") || PhShowConfirmMessage(
hwndDlg,
L"remove",
cacheEntryName->Buffer,
NULL,
FALSE
))
{
if (DnsFlushResolverCacheEntry_I(cacheEntryName->Buffer))
{
ListView_DeleteAllItems(ListViewWndHandle);
EnumDnsCacheTable(ListViewWndHandle);
}
}
}
}
break;
}
}
PhDestroyEMenu(menu);
PhDereferenceObject(cacheEntryName);
}
}
INT_PTR CALLBACK DnsCacheDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PhCenterWindow(hwndDlg, PhMainWndHandle);
ListViewWndHandle = GetDlgItem(hwndDlg, IDC_DNSLIST);
PhRegisterDialog(hwndDlg);
PhSetListViewStyle(ListViewWndHandle, FALSE, TRUE);
PhSetControlTheme(ListViewWndHandle, L"explorer");
PhAddListViewColumn(ListViewWndHandle, 0, 0, 0, LVCFMT_LEFT, 280, L"Host Name");
PhAddListViewColumn(ListViewWndHandle, 1, 1, 1, LVCFMT_LEFT, 70, L"Type");
PhAddListViewColumn(ListViewWndHandle, 2, 2, 2, LVCFMT_LEFT, 100, L"IP Address");
PhAddListViewColumn(ListViewWndHandle, 3, 3, 3, LVCFMT_LEFT, 50, L"TTL");
PhSetExtendedListView(ListViewWndHandle);
PhInitializeLayoutManager(&LayoutManager, hwndDlg);
PhAddLayoutItem(&LayoutManager, ListViewWndHandle, NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_DNS_REFRESH), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_DNS_CLEAR), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
PhLoadWindowPlacementFromSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
PhLoadListViewColumnsFromSetting(SETTING_NAME_COLUMNS, ListViewWndHandle);
if (DnsApiHandle = LoadLibrary(L"dnsapi.dll"))
{
DnsGetCacheDataTable_I = PhGetProcedureAddress(DnsApiHandle, "DnsGetCacheDataTable", 0);
DnsFlushResolverCache_I = PhGetProcedureAddress(DnsApiHandle, "DnsFlushResolverCache", 0);
DnsFlushResolverCacheEntry_I = PhGetProcedureAddress(DnsApiHandle, "DnsFlushResolverCacheEntry_W", 0);
}
EnumDnsCacheTable(ListViewWndHandle);
}
break;
case WM_DESTROY:
{
if (DnsApiHandle)
{
FreeLibrary(DnsApiHandle);
DnsApiHandle = NULL;
}
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
PhSaveListViewColumnsToSetting(SETTING_NAME_COLUMNS, ListViewWndHandle);
PhDeleteLayoutManager(&LayoutManager);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&LayoutManager);
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_DNS_CLEAR:
{
if (!PhGetIntegerSetting(L"EnableWarnings") || PhShowConfirmMessage(
hwndDlg,
L"Flush",
L"the dns cache",
NULL,
FALSE
))
{
if (DnsFlushResolverCache_I)
DnsFlushResolverCache_I();
ListView_DeleteAllItems(ListViewWndHandle);
EnumDnsCacheTable(ListViewWndHandle);
}
}
break;
case IDC_DNS_REFRESH:
ListView_DeleteAllItems(ListViewWndHandle);
EnumDnsCacheTable(ListViewWndHandle);
break;
case IDCANCEL:
case IDOK:
EndDialog(hwndDlg, IDOK);
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR hdr = (LPNMHDR)lParam;
switch (hdr->code)
{
case NM_RCLICK:
{
if (hdr->hwndFrom == ListViewWndHandle)
ShowStatusMenu(hwndDlg);
}
break;
}
}
break;
}
return FALSE;
}
VOID NTAPI MainMenuInitializingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
PPH_EMENU_ITEM systemMenu;
PPH_EMENU_ITEM bootMenuItem;
if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_TOOLS)
return;
if (!(systemMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"System", 0)))
{
PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, PH_EMENU_SEPARATOR, 0, L"", NULL), -1);
PhInsertEMenuItem(menuInfo->Menu, systemMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"System", NULL), -1);
}
PhInsertEMenuItem(systemMenu, bootMenuItem = PhPluginCreateEMenuItem(PluginInstance, 0, DNSCACHE_MENUITEM, L"DNS Cache Table", NULL), -1);
}
VOID NTAPI MenuItemCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_ITEM menuItem = (PPH_PLUGIN_MENU_ITEM)Parameter;
switch (menuItem->Id)
{
case DNSCACHE_MENUITEM:
{
DialogBox(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_DNSVIEW),
NULL,
DnsCacheDlgProc
);
}
break;
}
}
LOGICAL DllMain(
_In_ HINSTANCE Instance,
_In_ ULONG Reason,
_Reserved_ PVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
{
PPH_PLUGIN_INFORMATION info;
PH_SETTING_CREATE settings[] =
{
{ IntegerPairSettingType, SETTING_NAME_WINDOW_POSITION, L"350,350" },
{ ScalableIntegerPairSettingType, SETTING_NAME_WINDOW_SIZE, L"@96|510,380" },
{ StringSettingType, SETTING_NAME_COLUMNS, L"" }
};
PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
if (!PluginInstance)
return FALSE;
info->DisplayName = L"DNS Cache Viewer";
info->Author = L"dmex";
info->Description = L"Plugin for viewing the DNS Resolver Cache via the Tools menu.";
info->HasOptions = FALSE;
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackMainMenuInitializing),
MainMenuInitializingCallback,
NULL,
&MainMenuInitializingCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
MenuItemCallback,
NULL,
&PluginMenuItemCallbackRegistration
);
PhAddSettings(settings, ARRAYSIZE(settings));
}
break;
}
return TRUE;
}

View File

@ -0,0 +1,75 @@
/*
* Process Hacker Extra Plugins -
* DNS Cache Plugin
*
* Copyright (C) 2014 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DNS_H_
#define _DNS_H_
#define PLUGIN_NAME L"dmex.DnsCachePlugin"
#define SETTING_NAME_WINDOW_POSITION (PLUGIN_NAME L".WindowPosition")
#define SETTING_NAME_WINDOW_SIZE (PLUGIN_NAME L".WindowSize")
#define SETTING_NAME_COLUMNS (PLUGIN_NAME L".WindowColumns")
#define DNSCACHE_MENUITEM 1000
#define INET_ADDRSTRLEN 22
#define INET6_ADDRSTRLEN 65
#define CINTERFACE
#define COBJMACROS
#include <phdk.h>
#include <phappresource.h>
#include "resource.h"
#include <windns.h>
#include <Winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#pragma comment(lib, "Ws2_32.lib")
extern PPH_PLUGIN PluginInstance;
VOID ShowDnsCacheDialog(
VOID
);
typedef struct _DNS_CACHE_ENTRY
{
struct _DNS_CACHE_ENTRY* Next; // Pointer to next entry
PCWSTR Name; // DNS Record Name
USHORT Type; // DNS Record Type
USHORT DataLength; // Not referenced
ULONG Flags; // DNS Record Flags
} DNS_CACHE_ENTRY, *PDNS_CACHE_ENTRY;
typedef DNS_STATUS (WINAPI* _DnsGetCacheDataTable)(
_Inout_ PDNS_CACHE_ENTRY* DnsCacheEntry
);
typedef BOOL (WINAPI* _DnsFlushResolverCache)(
VOID
);
typedef BOOL (WINAPI* _DnsFlushResolverCacheEntry)(
_In_ PCWSTR Name
);
#endif

View File

@ -0,0 +1,19 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by DnsCachePlugin.rc
//
#define IDD_DNSVIEW 101
#define IDC_DNSLIST 1021
#define IDC_DNS_REFRESH 4355
#define IDC_DNS_CLEAR 4356
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 112
#define _APS_NEXT_COMMAND_VALUE 40006
#define _APS_NEXT_CONTROL_VALUE 1023
#define _APS_NEXT_SYMED_VALUE 108
#endif
#endif

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- General -->
<PropertyGroup>
<OutDir>$(SolutionDir)..\bin\$(Configuration)$(PlatformArchitecture)\plugins\</OutDir>
<IntDir>$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
<CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseDebugLibraries Condition="'$(Configuration)'=='Debug'">true</UseDebugLibraries>
<UseDebugLibraries Condition="'$(Configuration)'=='Release'">false</UseDebugLibraries>
<LinkIncremental Condition="'$(Configuration)'=='Debug'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)'=='Release'">false</LinkIncremental>
<WholeProgramOptimization Condition="'$(Configuration)'=='Debug'">false</WholeProgramOptimization>
<WholeProgramOptimization Condition="'$(Configuration)'=='Release'">true</WholeProgramOptimization>
</PropertyGroup>
<!-- Debugging -->
<PropertyGroup>
<LocalDebuggerCommand>$(SolutionDir)..\bin\$(Configuration)$(PlatformArchitecture)\ProcessHacker.exe</LocalDebuggerCommand>
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\bin\$(Configuration)$(PlatformArchitecture)\</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<!-- Global -->
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>../../sdk/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<CallingConvention>StdCall</CallingConvention>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<StringPooling>true</StringPooling>
</ClCompile>
<Link>
<AdditionalDependencies>ProcessHacker.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<MinimumRequiredVersion>6.01</MinimumRequiredVersion>
<SubSystem>Windows</SubSystem>
</Link>
<BuildLog>
<Path>$(IntDir)$(MSBuildProjectName).log</Path>
</BuildLog>
</ItemDefinitionGroup>
<!-- Debug Builds -->
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<FunctionLevelLinking>false</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
</ClCompile>
</ItemDefinitionGroup>
<!-- Release Builds -->
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization> <!-- <Optimization>Full</Optimization> -->
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Link>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<SetChecksum>true</SetChecksum>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<!-- Win32 Builds -->
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<ClCompile>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>../../sdk/lib/i386;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<!-- x64 Builds -->
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
<Link>
<AdditionalLibraryDirectories>../../sdk/lib/amd64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<!-- Debug|Win32 Builds -->
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<!-- Debug|x64 Builds -->
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<!-- Release|Win32 Builds -->
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<!-- Release|x64 Builds -->
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>

View File

@ -0,0 +1,247 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 14.0.25123.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D7078584-1144-4143-8DE8-D6741F6FD685}"
ProjectSection(SolutionItems) = preProject
ExtraPlugins.props = ExtraPlugins.props
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HexPidPlugin", "HexPidPlugin\HexPidPlugin.vcxproj", "{50691784-4EB0-4B5E-B428-BD37E52F8D2E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AvgCpuPlugin", "AvgCpuPlugin\AvgCpuPlugin.vcxproj", "{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetCriticalPlugin", "SetCriticalPlugin\SetCriticalPlugin.vcxproj", "{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ROTViewerPlugin", "ROTViewerPlugin\ROTViewerPlugin.vcxproj", "{4C581739-03D9-4E73-B453-0536DFB34C91}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DnsCachePlugin", "DnsCachePlugin\DnsCachePlugin.vcxproj", "{34E39D39-7148-45BF-9B36-DEF53E534A11}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AtomTablePlugin", "AtomTablePlugin\AtomTablePlugin.vcxproj", "{12390643-F40D-411F-A2E8-BF85F90223DF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WaitChainPlugin", "WaitChainPlugin\WaitChainPlugin.vcxproj", "{D6EA1C23-4CBC-4CD5-931C-38C984722510}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PerfMonPlugin", "PerfMonPlugin\PerfMonPlugin.vcxproj", "{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NvGpuPlugin", "NvGpuPlugin\NvGpuPlugin.vcxproj", "{B509BF8F-6007-4173-B05E-5037B958C12F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DbgViewPlugin", "DbgViewPlugin\DbgViewPlugin.vcxproj", "{AAD42A11-92A7-4918-A76A-862528185199}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetExtrasPlugin", "NetExtrasPlugin\NetExtrasPlugin.vcxproj", "{B2F55139-7984-498F-98CB-AC25A3E08CCC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TaskbarExtPlugin", "TaskbarExtPlugin\TaskbarExtPlugin.vcxproj", "{58E266DF-088C-470D-9EC8-403B40042373}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SecurityExplorer", "SecurityExplorerPlugin\SecurityExplorer.vcxproj", "{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ServiceBackupRestorePlugin", "ServiceBackupRestorePlugin\ServiceBackupRestorePlugin.vcxproj", "{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FirewallMonitorPlugin", "FirewallMonitorPlugin\FirewallMonitorPlugin.vcxproj", "{44A7C3BA-BAD5-40F3-AB70-442D44539053}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ForceShutdownPlugin", "ForceShutdownPlugin\ForceShutdownPlugin.vcxproj", "{4417E8FC-5FA6-4631-B792-1872561E7DC2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TrustedInstallerPlugin", "TrustedInstallerPlugin\TrustedInstallerPlugin.vcxproj", "{652D6556-B8E3-4173-B321-60F623E127E8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminatorPlugin", "TerminatorPlugin\TerminatorPlugin.vcxproj", "{93D93301-3638-4CFA-8F1B-547528023087}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FirmwarePlugin", "FirmwarePlugin\FirmwarePlugin.vcxproj", "{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PoolMonPlugin", "PoolMonPlugin\PoolMonPlugin.vcxproj", "{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ObjectManagerPlugin", "ObjectManagerPlugin\ObjectManagerPlugin.vcxproj", "{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExtraPlugins", "ExtraPlugins\ExtraPlugins.vcxproj", "{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Debug|Win32.ActiveCfg = Debug|Win32
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Debug|Win32.Build.0 = Debug|Win32
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Debug|x64.ActiveCfg = Debug|x64
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Debug|x64.Build.0 = Debug|x64
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Release|Win32.ActiveCfg = Release|Win32
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Release|Win32.Build.0 = Release|Win32
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Release|x64.ActiveCfg = Release|x64
{50691784-4EB0-4B5E-B428-BD37E52F8D2E}.Release|x64.Build.0 = Release|x64
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Debug|Win32.ActiveCfg = Debug|Win32
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Debug|Win32.Build.0 = Debug|Win32
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Debug|x64.ActiveCfg = Debug|x64
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Debug|x64.Build.0 = Debug|x64
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Release|Win32.ActiveCfg = Release|Win32
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Release|Win32.Build.0 = Release|Win32
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Release|x64.ActiveCfg = Release|x64
{A68DC3E8-5E2E-4883-A2A4-81F921458A9C}.Release|x64.Build.0 = Release|x64
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Debug|Win32.ActiveCfg = Debug|Win32
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Debug|Win32.Build.0 = Debug|Win32
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Debug|x64.ActiveCfg = Debug|x64
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Debug|x64.Build.0 = Debug|x64
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Release|Win32.ActiveCfg = Release|Win32
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Release|Win32.Build.0 = Release|Win32
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Release|x64.ActiveCfg = Release|x64
{AF008176-46A6-4EFB-8061-D1EF9B9CEC29}.Release|x64.Build.0 = Release|x64
{4C581739-03D9-4E73-B453-0536DFB34C91}.Debug|Win32.ActiveCfg = Debug|Win32
{4C581739-03D9-4E73-B453-0536DFB34C91}.Debug|Win32.Build.0 = Debug|Win32
{4C581739-03D9-4E73-B453-0536DFB34C91}.Debug|x64.ActiveCfg = Debug|x64
{4C581739-03D9-4E73-B453-0536DFB34C91}.Debug|x64.Build.0 = Debug|x64
{4C581739-03D9-4E73-B453-0536DFB34C91}.Release|Win32.ActiveCfg = Release|Win32
{4C581739-03D9-4E73-B453-0536DFB34C91}.Release|Win32.Build.0 = Release|Win32
{4C581739-03D9-4E73-B453-0536DFB34C91}.Release|x64.ActiveCfg = Release|x64
{4C581739-03D9-4E73-B453-0536DFB34C91}.Release|x64.Build.0 = Release|x64
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Debug|Win32.ActiveCfg = Debug|Win32
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Debug|Win32.Build.0 = Debug|Win32
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Debug|x64.ActiveCfg = Debug|x64
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Debug|x64.Build.0 = Debug|x64
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Release|Win32.ActiveCfg = Release|Win32
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Release|Win32.Build.0 = Release|Win32
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Release|x64.ActiveCfg = Release|x64
{34E39D39-7148-45BF-9B36-DEF53E534A11}.Release|x64.Build.0 = Release|x64
{12390643-F40D-411F-A2E8-BF85F90223DF}.Debug|Win32.ActiveCfg = Debug|Win32
{12390643-F40D-411F-A2E8-BF85F90223DF}.Debug|Win32.Build.0 = Debug|Win32
{12390643-F40D-411F-A2E8-BF85F90223DF}.Debug|Win32.Deploy.0 = Debug|Win32
{12390643-F40D-411F-A2E8-BF85F90223DF}.Debug|x64.ActiveCfg = Debug|x64
{12390643-F40D-411F-A2E8-BF85F90223DF}.Debug|x64.Build.0 = Debug|x64
{12390643-F40D-411F-A2E8-BF85F90223DF}.Debug|x64.Deploy.0 = Debug|x64
{12390643-F40D-411F-A2E8-BF85F90223DF}.Release|Win32.ActiveCfg = Release|Win32
{12390643-F40D-411F-A2E8-BF85F90223DF}.Release|Win32.Build.0 = Release|Win32
{12390643-F40D-411F-A2E8-BF85F90223DF}.Release|Win32.Deploy.0 = Release|Win32
{12390643-F40D-411F-A2E8-BF85F90223DF}.Release|x64.ActiveCfg = Release|x64
{12390643-F40D-411F-A2E8-BF85F90223DF}.Release|x64.Build.0 = Release|x64
{12390643-F40D-411F-A2E8-BF85F90223DF}.Release|x64.Deploy.0 = Release|x64
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Debug|Win32.ActiveCfg = Debug|Win32
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Debug|Win32.Build.0 = Debug|Win32
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Debug|x64.ActiveCfg = Debug|x64
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Debug|x64.Build.0 = Debug|x64
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Release|Win32.ActiveCfg = Release|Win32
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Release|Win32.Build.0 = Release|Win32
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Release|x64.ActiveCfg = Release|x64
{D6EA1C23-4CBC-4CD5-931C-38C984722510}.Release|x64.Build.0 = Release|x64
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Debug|Win32.ActiveCfg = Debug|Win32
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Debug|Win32.Build.0 = Debug|Win32
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Debug|x64.ActiveCfg = Debug|x64
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Debug|x64.Build.0 = Debug|x64
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Release|Win32.ActiveCfg = Release|Win32
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Release|Win32.Build.0 = Release|Win32
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Release|x64.ActiveCfg = Release|x64
{E373C568-D6C5-4E0E-94ED-A759EDE16A9E}.Release|x64.Build.0 = Release|x64
{B509BF8F-6007-4173-B05E-5037B958C12F}.Debug|Win32.ActiveCfg = Debug|Win32
{B509BF8F-6007-4173-B05E-5037B958C12F}.Debug|Win32.Build.0 = Debug|Win32
{B509BF8F-6007-4173-B05E-5037B958C12F}.Debug|x64.ActiveCfg = Debug|x64
{B509BF8F-6007-4173-B05E-5037B958C12F}.Debug|x64.Build.0 = Debug|x64
{B509BF8F-6007-4173-B05E-5037B958C12F}.Release|Win32.ActiveCfg = Release|Win32
{B509BF8F-6007-4173-B05E-5037B958C12F}.Release|Win32.Build.0 = Release|Win32
{B509BF8F-6007-4173-B05E-5037B958C12F}.Release|x64.ActiveCfg = Release|x64
{B509BF8F-6007-4173-B05E-5037B958C12F}.Release|x64.Build.0 = Release|x64
{AAD42A11-92A7-4918-A76A-862528185199}.Debug|Win32.ActiveCfg = Debug|Win32
{AAD42A11-92A7-4918-A76A-862528185199}.Debug|Win32.Build.0 = Debug|Win32
{AAD42A11-92A7-4918-A76A-862528185199}.Debug|x64.ActiveCfg = Debug|x64
{AAD42A11-92A7-4918-A76A-862528185199}.Debug|x64.Build.0 = Debug|x64
{AAD42A11-92A7-4918-A76A-862528185199}.Release|Win32.ActiveCfg = Release|Win32
{AAD42A11-92A7-4918-A76A-862528185199}.Release|Win32.Build.0 = Release|Win32
{AAD42A11-92A7-4918-A76A-862528185199}.Release|x64.ActiveCfg = Release|x64
{AAD42A11-92A7-4918-A76A-862528185199}.Release|x64.Build.0 = Release|x64
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Debug|Win32.ActiveCfg = Debug|Win32
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Debug|Win32.Build.0 = Debug|Win32
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Debug|x64.ActiveCfg = Debug|x64
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Debug|x64.Build.0 = Debug|x64
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Release|Win32.ActiveCfg = Release|Win32
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Release|Win32.Build.0 = Release|Win32
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Release|x64.ActiveCfg = Release|x64
{B2F55139-7984-498F-98CB-AC25A3E08CCC}.Release|x64.Build.0 = Release|x64
{58E266DF-088C-470D-9EC8-403B40042373}.Debug|Win32.ActiveCfg = Debug|Win32
{58E266DF-088C-470D-9EC8-403B40042373}.Debug|Win32.Build.0 = Debug|Win32
{58E266DF-088C-470D-9EC8-403B40042373}.Debug|x64.ActiveCfg = Debug|x64
{58E266DF-088C-470D-9EC8-403B40042373}.Debug|x64.Build.0 = Debug|x64
{58E266DF-088C-470D-9EC8-403B40042373}.Release|Win32.ActiveCfg = Release|Win32
{58E266DF-088C-470D-9EC8-403B40042373}.Release|Win32.Build.0 = Release|Win32
{58E266DF-088C-470D-9EC8-403B40042373}.Release|x64.ActiveCfg = Release|x64
{58E266DF-088C-470D-9EC8-403B40042373}.Release|x64.Build.0 = Release|x64
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Debug|Win32.ActiveCfg = Debug|Win32
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Debug|Win32.Build.0 = Debug|Win32
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Debug|x64.ActiveCfg = Debug|x64
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Debug|x64.Build.0 = Debug|x64
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Release|Win32.ActiveCfg = Release|Win32
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Release|Win32.Build.0 = Release|Win32
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Release|x64.ActiveCfg = Release|x64
{0DCBC570-B4E3-482A-9872-8BB5678F5E5C}.Release|x64.Build.0 = Release|x64
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Debug|Win32.ActiveCfg = Debug|Win32
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Debug|Win32.Build.0 = Debug|Win32
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Debug|x64.ActiveCfg = Debug|x64
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Debug|x64.Build.0 = Debug|x64
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Release|Win32.ActiveCfg = Release|Win32
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Release|Win32.Build.0 = Release|Win32
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Release|x64.ActiveCfg = Release|x64
{D08A2B6C-822F-46C8-A7AC-A2EE609237D6}.Release|x64.Build.0 = Release|x64
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Debug|Win32.ActiveCfg = Debug|Win32
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Debug|Win32.Build.0 = Debug|Win32
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Debug|x64.ActiveCfg = Debug|x64
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Debug|x64.Build.0 = Debug|x64
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Release|Win32.ActiveCfg = Release|Win32
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Release|Win32.Build.0 = Release|Win32
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Release|x64.ActiveCfg = Release|x64
{44A7C3BA-BAD5-40F3-AB70-442D44539053}.Release|x64.Build.0 = Release|x64
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Debug|Win32.ActiveCfg = Debug|Win32
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Debug|Win32.Build.0 = Debug|Win32
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Debug|x64.ActiveCfg = Debug|x64
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Debug|x64.Build.0 = Debug|x64
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Release|Win32.ActiveCfg = Release|Win32
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Release|Win32.Build.0 = Release|Win32
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Release|x64.ActiveCfg = Release|x64
{4417E8FC-5FA6-4631-B792-1872561E7DC2}.Release|x64.Build.0 = Release|x64
{652D6556-B8E3-4173-B321-60F623E127E8}.Debug|Win32.ActiveCfg = Debug|Win32
{652D6556-B8E3-4173-B321-60F623E127E8}.Debug|Win32.Build.0 = Debug|Win32
{652D6556-B8E3-4173-B321-60F623E127E8}.Debug|x64.ActiveCfg = Debug|x64
{652D6556-B8E3-4173-B321-60F623E127E8}.Debug|x64.Build.0 = Debug|x64
{652D6556-B8E3-4173-B321-60F623E127E8}.Release|Win32.ActiveCfg = Release|Win32
{652D6556-B8E3-4173-B321-60F623E127E8}.Release|Win32.Build.0 = Release|Win32
{652D6556-B8E3-4173-B321-60F623E127E8}.Release|x64.ActiveCfg = Release|x64
{652D6556-B8E3-4173-B321-60F623E127E8}.Release|x64.Build.0 = Release|x64
{93D93301-3638-4CFA-8F1B-547528023087}.Debug|Win32.ActiveCfg = Debug|Win32
{93D93301-3638-4CFA-8F1B-547528023087}.Debug|Win32.Build.0 = Debug|Win32
{93D93301-3638-4CFA-8F1B-547528023087}.Debug|x64.ActiveCfg = Debug|x64
{93D93301-3638-4CFA-8F1B-547528023087}.Debug|x64.Build.0 = Debug|x64
{93D93301-3638-4CFA-8F1B-547528023087}.Release|Win32.ActiveCfg = Release|Win32
{93D93301-3638-4CFA-8F1B-547528023087}.Release|Win32.Build.0 = Release|Win32
{93D93301-3638-4CFA-8F1B-547528023087}.Release|x64.ActiveCfg = Release|x64
{93D93301-3638-4CFA-8F1B-547528023087}.Release|x64.Build.0 = Release|x64
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Debug|Win32.ActiveCfg = Debug|Win32
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Debug|Win32.Build.0 = Debug|Win32
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Debug|x64.ActiveCfg = Debug|x64
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Debug|x64.Build.0 = Debug|x64
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Release|Win32.ActiveCfg = Release|Win32
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Release|Win32.Build.0 = Release|Win32
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Release|x64.ActiveCfg = Release|x64
{21B34EB4-4C56-4449-A2C0-BC50B4480D7C}.Release|x64.Build.0 = Release|x64
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Debug|Win32.ActiveCfg = Debug|Win32
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Debug|Win32.Build.0 = Debug|Win32
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Debug|x64.ActiveCfg = Debug|x64
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Debug|x64.Build.0 = Debug|x64
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Release|Win32.ActiveCfg = Release|Win32
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Release|Win32.Build.0 = Release|Win32
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Release|x64.ActiveCfg = Release|x64
{34E1194C-61AE-4FAF-A5F9-540DD6DF4872}.Release|x64.Build.0 = Release|x64
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Debug|Win32.ActiveCfg = Debug|Win32
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Debug|Win32.Build.0 = Debug|Win32
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Debug|x64.ActiveCfg = Debug|x64
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Debug|x64.Build.0 = Debug|x64
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Release|Win32.ActiveCfg = Release|Win32
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Release|Win32.Build.0 = Release|Win32
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Release|x64.ActiveCfg = Release|x64
{DADA7017-0A25-4E97-BC21-D7FE3DE2EBF3}.Release|x64.Build.0 = Release|x64
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Debug|Win32.ActiveCfg = Debug|Win32
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Debug|Win32.Build.0 = Debug|Win32
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Debug|x64.ActiveCfg = Debug|x64
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Debug|x64.Build.0 = Debug|x64
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Release|Win32.ActiveCfg = Release|Win32
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Release|Win32.Build.0 = Release|Win32
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Release|x64.ActiveCfg = Release|x64
{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,4 @@
1.0
* Initial release

View File

@ -0,0 +1,184 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000904b0"
BEGIN
VALUE "CompanyName", "dmex"
VALUE "FileDescription", "Extra plugins for Process Hacker"
VALUE "FileVersion", "1.0.0.0"
VALUE "InternalName", "dmex.ExtraPlugins"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "ExtraPlugins.dll"
VALUE "ProductName", "Extra plugins for Process Hacker"
VALUE "ProductVersion", "1.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x9, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_PLUGINS_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 2
RIGHTMARGIN, 637
TOPMARGIN, 2
BOTTOMMARGIN, 309
END
IDD_DISABLED_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 2
RIGHTMARGIN, 307
TOPMARGIN, 2
BOTTOMMARGIN, 176
HORZGUIDE, 2
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_PLUGINS_DIALOG AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_DISABLED_DIALOG AFX_DIALOG_LAYOUT
BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_PLUGINS_DIALOG DIALOGEX 0, 0, 639, 313
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Plugin Manager"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Installed",IDC_INSTALLED,2,2,65,14,NOT WS_TABSTOP
PUSHBUTTON "Browse",IDC_BROWSE,73,2,64,14,NOT WS_TABSTOP
PUSHBUTTON "Updates (0)",IDC_UPDATES,143,2,65,14,NOT WS_TABSTOP
EDITTEXT IDC_SEARCHBOX,483,2,153,14,ES_AUTOHSCROLL,WS_EX_CLIENTEDGE
CONTROL "",IDC_PLUGINTREE,"PhTreeNew",WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP | 0xa,2,18,635,275,WS_EX_CLIENTEDGE
PUSHBUTTON "Close",IDOK,587,295,50,14
PUSHBUTTON "Disabled Plugins (0)",IDC_DISABLED,2,295,75,14,NOT WS_TABSTOP
PUSHBUTTON "Clean up",IDC_CLEANUP,81,295,75,14,NOT WS_VISIBLE
END
IDD_DISABLED_DIALOG DIALOGEX 0, 0, 309, 178
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Disabled Plugins"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "OK",IDOK,257,162,50,14
CONTROL "",IDC_LIST_DISABLED,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,2,15,305,145
LTEXT "Changes may require a restart to take effect.",IDC_INSTRUCTION,3,3,154,8
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_SEARCH_ACTIVE_BMP BITMAP "resources\\active_search.bmp"
IDB_SEARCH_INACTIVE_BMP BITMAP "resources\\inactive_search.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// PNG
//
IDB_SEARCH_ACTIVE PNG "resources\\active_search.png"
IDB_SEARCH_INACTIVE PNG "resources\\inactive_search.png"
IDB_SETTINGS_PNG PNG "resources\\cog_edit_modern.png"
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{96549A3E-D1BD-470E-A5B3-A64803C4DEF5}</ProjectGuid>
<RootNamespace>ExtraPlugins</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>ExtraPlugins</ProjectName>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<AdditionalDependencies>windowscodecs.lib;bcrypt.lib;winhttp.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>windowscodecs.dll;bcrypt.dll;winhttp.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
<AdditionalDependencies>windowscodecs.lib;bcrypt.lib;winhttp.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>windowscodecs.dll;bcrypt.dll;winhttp.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<AdditionalDependencies>windowscodecs.lib;bcrypt.lib;winhttp.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>windowscodecs.dll;bcrypt.dll;winhttp.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<AdditionalDependencies>windowscodecs.lib;bcrypt.lib;winhttp.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>windowscodecs.dll;bcrypt.dll;winhttp.dll;uxtheme.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="CHANGELOG.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="cloud.c" />
<ClCompile Include="dialog.c" />
<ClCompile Include="disabled.c" />
<ClCompile Include="json-c\arraylist.c" />
<ClCompile Include="json-c\debug.c" />
<ClCompile Include="json-c\json_c_version.c" />
<ClCompile Include="json-c\json_object.c" />
<ClCompile Include="json-c\json_object_iterator.c" />
<ClCompile Include="json-c\json_tokener.c" />
<ClCompile Include="json-c\json_util.c" />
<ClCompile Include="json-c\libjson.c" />
<ClCompile Include="json-c\linkhash.c" />
<ClCompile Include="json-c\printbuf.c" />
<ClCompile Include="json-c\random_seed.c" />
<ClCompile Include="main.c" />
<ClCompile Include="miniz\miniz.c" />
<ClCompile Include="plugin.c" />
<ClCompile Include="searchbox.c" />
<ClCompile Include="setup\page4.c" />
<ClCompile Include="setup\page1.c" />
<ClCompile Include="setup\page2.c" />
<ClCompile Include="setup\page3.c" />
<ClCompile Include="setup\page5.c" />
<ClCompile Include="setup\updater.c" />
<ClCompile Include="setup\verify.c" />
<ClCompile Include="setup\uninstall.c" />
<ClCompile Include="wndtree.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="json-c\arraylist.h" />
<ClInclude Include="json-c\bits.h" />
<ClInclude Include="json-c\config.h" />
<ClInclude Include="json-c\debug.h" />
<ClInclude Include="json-c\json.h" />
<ClInclude Include="json-c\json_config.h" />
<ClInclude Include="json-c\json_c_version.h" />
<ClInclude Include="json-c\json_inttypes.h" />
<ClInclude Include="json-c\json_object.h" />
<ClInclude Include="json-c\json_object_iterator.h" />
<ClInclude Include="json-c\json_object_private.h" />
<ClInclude Include="json-c\json_tokener.h" />
<ClInclude Include="json-c\json_util.h" />
<ClInclude Include="json-c\linkhash.h" />
<ClInclude Include="json-c\math_compat.h" />
<ClInclude Include="json-c\printbuf.h" />
<ClInclude Include="json-c\random_seed.h" />
<ClInclude Include="main.h" />
<ClInclude Include="miniz\miniz.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ExtraPlugins.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="resources\active_search.bmp" />
<Image Include="resources\active_search.png" />
<Image Include="resources\cog_edit_modern.png" />
<Image Include="resources\inactive_search.bmp" />
<Image Include="resources\inactive_search.png" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -0,0 +1,200 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{802108be-ae96-47c3-8d93-884ed6dd096a}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{3e65ffb8-3f3e-40d7-b3ca-d55cae8edb16}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{b98dd849-bbfe-4b41-8c48-f65680da5c00}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\json-c">
<UniqueIdentifier>{d13aeaca-3136-44f8-8525-ac088e4170ad}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\json-c">
<UniqueIdentifier>{297fc08d-cce6-41c6-8e77-63411ddd185b}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\zip">
<UniqueIdentifier>{59006979-4faf-455c-b58c-3f81e8ff9272}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\zip">
<UniqueIdentifier>{2ff6c860-c958-4bcc-8147-4093cad157e5}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files\Images">
<UniqueIdentifier>{77191a45-2eba-438a-8ad2-853e25615850}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\pages">
<UniqueIdentifier>{50861cd8-df66-4551-a743-f08b54011d1e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wndtree.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="cloud.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="json-c\arraylist.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\json_c_version.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\json_object.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\json_object_iterator.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\json_tokener.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\json_util.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\linkhash.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\random_seed.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\debug.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\libjson.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="json-c\printbuf.c">
<Filter>Source Files\json-c</Filter>
</ClCompile>
<ClCompile Include="miniz\miniz.c">
<Filter>Source Files\zip</Filter>
</ClCompile>
<ClCompile Include="setup\verify.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="setup\page1.c">
<Filter>Source Files\pages</Filter>
</ClCompile>
<ClCompile Include="setup\page2.c">
<Filter>Source Files\pages</Filter>
</ClCompile>
<ClCompile Include="setup\page3.c">
<Filter>Source Files\pages</Filter>
</ClCompile>
<ClCompile Include="setup\page4.c">
<Filter>Source Files\pages</Filter>
</ClCompile>
<ClCompile Include="setup\page5.c">
<Filter>Source Files\pages</Filter>
</ClCompile>
<ClCompile Include="setup\updater.c">
<Filter>Source Files\pages</Filter>
</ClCompile>
<ClCompile Include="dialog.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="disabled.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="plugin.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="searchbox.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="setup\uninstall.c">
<Filter>Source Files\pages</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="json-c\json_config.h">
<Filter>Source Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json.h">
<Filter>Source Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\arraylist.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json_c_version.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json_inttypes.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json_object.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json_object_iterator.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json_object_private.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json_tokener.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\json_util.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\linkhash.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\math_compat.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\printbuf.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\random_seed.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\bits.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\config.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="json-c\debug.h">
<Filter>Header Files\json-c</Filter>
</ClInclude>
<ClInclude Include="miniz\miniz.h">
<Filter>Header Files\zip</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ExtraPlugins.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="resources\inactive_search.bmp">
<Filter>Resource Files\Images</Filter>
</Image>
<Image Include="resources\inactive_search.png">
<Filter>Resource Files\Images</Filter>
</Image>
<Image Include="resources\active_search.png">
<Filter>Resource Files\Images</Filter>
</Image>
<Image Include="resources\active_search.bmp">
<Filter>Resource Files\Images</Filter>
</Image>
<Image Include="resources\cog_edit_modern.png" />
</ItemGroup>
<ItemGroup>
<Text Include="CHANGELOG.txt" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,594 @@
/*
* Process Hacker Extra Plugins -
* Plugin Manager
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include "miniz\miniz.h"
ULONGLONG ParseVersionString(
_In_ PPH_STRING Version
)
{
PH_STRINGREF remainingPart, majorPart, minorPart, revisionPart, reservedPart;
ULONG64 majorInteger = 0, minorInteger = 0, revisionInteger = 0, reservedInteger = 0;
PhInitializeStringRef(&remainingPart, PhGetString(Version));
PhSplitStringRefAtChar(&remainingPart, '.', &majorPart, &remainingPart);
PhSplitStringRefAtChar(&remainingPart, '.', &minorPart, &remainingPart);
PhSplitStringRefAtChar(&remainingPart, '.', &revisionPart, &remainingPart);
PhSplitStringRefAtChar(&remainingPart, '.', &reservedPart, &remainingPart);
PhStringToInteger64(&majorPart, 10, &majorInteger);
PhStringToInteger64(&minorPart, 10, &minorInteger);
PhStringToInteger64(&revisionPart, 10, &revisionInteger);
PhStringToInteger64(&reservedPart, 10, &reservedInteger);
return MAKE_VERSION_ULONGLONG(majorInteger, minorInteger, reservedInteger, revisionInteger);
}
json_object_ptr json_get_object(
_In_ json_object_ptr Object,
_In_ PCSTR Key
)
{
json_object_ptr returnObj;
if (json_object_object_get_ex(Object, Key, &returnObj))
{
return returnObj;
}
return NULL;
}
static BOOLEAN ReadRequestString(
_In_ HINTERNET Handle,
_Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
_Out_ ULONG *DataLength
)
{
BYTE buffer[PAGE_SIZE];
PSTR data;
ULONG allocatedLength;
ULONG dataLength;
ULONG returnLength;
allocatedLength = sizeof(buffer);
data = (PSTR)PhAllocate(allocatedLength);
dataLength = 0;
// Zero the buffer
memset(buffer, 0, PAGE_SIZE);
memset(data, 0, allocatedLength);
while (WinHttpReadData(Handle, buffer, PAGE_SIZE, &returnLength))
{
if (returnLength == 0)
break;
if (allocatedLength < dataLength + returnLength)
{
allocatedLength *= 2;
data = (PSTR)PhReAllocate(data, allocatedLength);
}
// Copy the returned buffer into our pointer
memcpy(data + dataLength, buffer, returnLength);
// Zero the returned buffer for the next loop
//memset(buffer, 0, returnLength);
dataLength += returnLength;
}
if (allocatedLength < dataLength + 1)
{
allocatedLength++;
data = (PSTR)PhReAllocate(data, allocatedLength);
}
// Ensure that the buffer is null-terminated.
data[dataLength] = 0;
*DataLength = dataLength;
*Data = data;
return TRUE;
}
VOID EnumerateLoadedPlugins(
_In_ PWCT_CONTEXT Context
)
{
PPH_AVL_LINKS root;
PPH_AVL_LINKS links;
root = PluginInstance->Links.Parent;
while (root)
{
if (!root->Parent)
break;
root = root->Parent;
}
for (
links = PhMinimumElementAvlTree((PPH_AVL_TREE)root);
links;
links = PhSuccessorElementAvlTree(links)
)
{
HANDLE handle;
IO_STATUS_BLOCK isb;
FILE_BASIC_INFORMATION basic;
PPHAPP_PLUGIN pluginInstance;
PH_STRINGREF pluginBaseName;
pluginInstance = CONTAINING_RECORD(links, PHAPP_PLUGIN, Links);
PhInitializeStringRefLongHint(&pluginBaseName, PhGetPluginBaseName(pluginInstance));
if (PhIsPluginDisabled(&pluginBaseName))
{
continue;
}
memset(&basic, 0, sizeof(FILE_BASIC_INFORMATION));
if (NT_SUCCESS(PhCreateFileWin32(
&handle,
PhGetString(pluginInstance->FileName),
FILE_GENERIC_READ,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
)))
{
NtQueryInformationFile(
handle,
&isb,
&basic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation
);
NtClose(handle);
}
ULONG versionSize;
PVOID versionInfo;
PUSHORT languageInfo;
UINT language;
UINT bufferSize = 0;
PWSTR buffer = NULL;
PPH_STRING internalName = NULL;
PPH_STRING version = NULL;
versionSize = GetFileVersionInfoSize(PhGetString(pluginInstance->FileName), NULL);
versionInfo = PhAllocate(versionSize);
memset(versionInfo, 0, versionSize);
if (GetFileVersionInfo(PhGetString(pluginInstance->FileName), 0, versionSize, versionInfo))
{
if (VerQueryValue(versionInfo, L"\\", &buffer, &bufferSize))
{
VS_FIXEDFILEINFO* info = (VS_FIXEDFILEINFO*)buffer;
if (info->dwSignature == 0xfeef04bd)
{
version = PhFormatString(
L"%lu.%lu.%lu.%lu",
(info->dwFileVersionMS >> 16) & 0xffff,
(info->dwFileVersionMS >> 0) & 0xffff,
(info->dwFileVersionLS >> 16) & 0xffff,
(info->dwFileVersionLS >> 0) & 0xffff
);
}
}
if (VerQueryValue(versionInfo, L"\\VarFileInfo\\Translation", &languageInfo, &language))
{
PPH_STRING internalNameString = PhFormatString(
L"\\StringFileInfo\\%04x%04x\\InternalName",
languageInfo[0],
languageInfo[1]
);
if (VerQueryValue(versionInfo, PhGetStringOrEmpty(internalNameString), &buffer, &bufferSize))
{
internalName = PhCreateStringEx(buffer, bufferSize * sizeof(WCHAR));
}
PhDereferenceObject(internalNameString);
}
}
PPLUGIN_NODE entry = PhCreateAlloc(sizeof(PLUGIN_NODE));
memset(entry, 0, sizeof(PLUGIN_NODE));
entry->State = PLUGIN_STATE_LOCAL;
entry->PluginInstance = pluginInstance;
entry->InternalName = internalName;
entry->Version = PhSubstring(version, 0, version->Length / sizeof(WCHAR) - 4);
entry->Name = PhCreateString(pluginInstance->Information.DisplayName);
entry->Author = PhCreateString(pluginInstance->Information.Author);
entry->Description = PhCreateString(pluginInstance->Information.Description);
entry->FilePath = PhCreateString2(&pluginInstance->FileName->sr);
entry->FileName = PhGetBaseName(entry->FilePath);
SYSTEMTIME utcTime, localTime;
PhLargeIntegerToSystemTime(&utcTime, &basic.LastWriteTime);
SystemTimeToTzSpecificLocalTime(NULL, &utcTime, &localTime);
entry->UpdatedTime = PhFormatDateTime(&localTime);
PhLargeIntegerToSystemTime(&utcTime, &basic.CreationTime);
SystemTimeToTzSpecificLocalTime(NULL, &utcTime, &localTime);
entry->AddedTime = PhFormatDateTime(&localTime);
entry->PluginOptions = pluginInstance->Information.HasOptions;
PostMessage(Context->DialogHandle, ID_UPDATE_ADD, 0, (LPARAM)entry);
}
}
NTSTATUS QueryPluginsCallbackThread(
_In_ PVOID Parameter
)
{
HINTERNET httpSessionHandle = NULL;
HINTERNET httpConnectionHandle = NULL;
HINTERNET httpRequestHandle = NULL;
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig = { 0 };
ULONG xmlStringBufferLength = 0;
PSTR xmlStringBuffer = NULL;
json_object_ptr rootJsonObject;
PWCT_CONTEXT context = Parameter;
WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig);
if (!(httpSessionHandle = WinHttpOpen(
L"ExtraPlugins_1.0",
proxyConfig.lpszProxy ? WINHTTP_ACCESS_TYPE_NAMED_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
proxyConfig.lpszProxy,
proxyConfig.lpszProxyBypass,
0
)))
{
goto CleanupExit;
}
if (!(httpConnectionHandle = WinHttpConnect(
httpSessionHandle,
L"wj32.org",
INTERNET_DEFAULT_HTTP_PORT,
0
)))
{
goto CleanupExit;
}
if (!(httpRequestHandle = WinHttpOpenRequest(
httpConnectionHandle,
NULL,
L"/processhacker/plugins/list.php",
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH
)))
{
goto CleanupExit;
}
if (!WinHttpSendRequest(
httpRequestHandle,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
0
))
{
goto CleanupExit;
}
if (!WinHttpReceiveResponse(httpRequestHandle, NULL))
goto CleanupExit;
if (!ReadRequestString(httpRequestHandle, &xmlStringBuffer, &xmlStringBufferLength))
goto CleanupExit;
if (!(rootJsonObject = json_tokener_parse(xmlStringBuffer)))
goto CleanupExit;
for (INT i = 0; i < json_object_array_length(rootJsonObject); i++)
{
json_object_ptr jvalue;
PPLUGIN_NODE entry;
SYSTEMTIME time = { 0 };
SYSTEMTIME localTime = { 0 };
PH_STRINGREF pluginBaseName;
PPH_STRING pluginDllPath;
entry = PhCreateAlloc(sizeof(PLUGIN_NODE));
memset(entry, 0, sizeof(PLUGIN_NODE));
jvalue = json_object_array_get_idx(rootJsonObject, i);
entry->Id = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_id")));
entry->Visible = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_visible")));
entry->InternalName = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_internal_name")));
entry->Name = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_name")));
entry->Version = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_version")));
entry->Author = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_author")));
entry->Description = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_description")));
entry->IconUrl = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_icon")));
entry->Requirements = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_requirements")));
entry->FeedbackUrl = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_feedback")));
entry->Screenshots = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_screenshots")));
entry->AddedTime = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_datetime_added")));
entry->UpdatedTime = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_datetime_updated")));
entry->Download_count = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_download_count")));
entry->Download_link_32 = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_download_link_32")));
entry->Download_link_64 = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_download_link_64")));
entry->SHA2_32 = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_hash_32")));
entry->SHA2_64 = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_hash_64")));
entry->HASH_32 = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_signed_32")));
entry->HASH_64 = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_signed_64")));
entry->FileName = PhConvertUtf8ToUtf16(json_object_get_string(json_get_object(jvalue, "plugin_filename")));
swscanf(
PhGetString(entry->UpdatedTime),
L"%hu-%hu-%hu %hu:%hu:%hu",
&time.wYear,
&time.wMonth,
&time.wDay,
&time.wHour,
&time.wMinute,
&time.wSecond
);
if (SystemTimeToTzSpecificLocalTime(NULL, &time, &localTime))
{
entry->UpdatedTime = PhFormatDateTime(&localTime);
}
pluginDllPath = PhConcatStrings(3, PhGetString(PhGetApplicationDirectory()), L"Plugins\\", PhGetString(entry->FileName));
PhInitializeStringRefLongHint(&pluginBaseName, PhGetString(entry->FileName));
if (PhIsPluginDisabled(&pluginBaseName))
goto CleanupExit;
if (RtlDoesFileExists_U(PhGetString(pluginDllPath)))
{
ULONG versionSize;
PVOID versionInfo;
PUSHORT languageInfo;
UINT language;
UINT bufferSize = 0;
PWSTR buffer = NULL;
PPH_STRING internalName = NULL;
PPH_STRING version = NULL;
entry->FilePath = PhCreateString2(&pluginDllPath->sr);//entry->PluginInstance->FileName->sr);
versionSize = GetFileVersionInfoSize(PhGetString(entry->FilePath), NULL);
versionInfo = PhAllocate(versionSize);
memset(versionInfo, 0, versionSize);
if (GetFileVersionInfo(PhGetString(entry->FilePath), 0, versionSize, versionInfo))
{
if (VerQueryValue(versionInfo, L"\\", &buffer, &bufferSize))
{
VS_FIXEDFILEINFO* info = (VS_FIXEDFILEINFO*)buffer;
if (info->dwSignature == 0xfeef04bd)
{
version = PhFormatString(
L"%lu.%lu.%lu.%lu",
(info->dwFileVersionMS >> 16) & 0xffff,
(info->dwFileVersionMS >> 0) & 0xffff,
(info->dwFileVersionLS >> 16) & 0xffff,
(info->dwFileVersionLS >> 0) & 0xffff
);
}
}
if (VerQueryValue(versionInfo, L"\\VarFileInfo\\Translation", &languageInfo, &language))
{
PPH_STRING internalNameString = PhFormatString(
L"\\StringFileInfo\\%04x%04x\\InternalName",
languageInfo[0],
languageInfo[1]
);
if (VerQueryValue(versionInfo, PhGetStringOrEmpty(internalNameString), &buffer, &bufferSize))
{
internalName = PhCreateStringEx(buffer, bufferSize * sizeof(WCHAR));
}
PhDereferenceObject(internalNameString);
}
}
PhFree(versionInfo);
if (entry->PluginInstance = (PPHAPP_PLUGIN)PhFindPlugin(PhGetString(entry->InternalName)))
{
ULONGLONG currentVersion = ParseVersionString(version);
ULONGLONG latestVersion = ParseVersionString(entry->Version);
entry->PluginOptions = entry->PluginInstance->Information.HasOptions;
if (currentVersion < latestVersion)
{
// User is running an older version
entry->State = PLUGIN_STATE_UPDATE;
PostMessage(context->DialogHandle, ID_UPDATE_ADD, 0, (LPARAM)entry);
}
}
else
{
// Plugin waiting to load?
entry->State = PLUGIN_STATE_RESTART;
PostMessage(context->DialogHandle, ID_UPDATE_ADD, 0, (LPARAM)entry);
}
}
else
{
// New plugin available for download
entry->State = PLUGIN_STATE_REMOTE;
PostMessage(context->DialogHandle, ID_UPDATE_ADD, 0, (LPARAM)entry);
}
}
CleanupExit:
if (httpRequestHandle)
WinHttpCloseHandle(httpRequestHandle);
if (httpConnectionHandle)
WinHttpCloseHandle(httpConnectionHandle);
if (httpSessionHandle)
WinHttpCloseHandle(httpSessionHandle);
if (xmlStringBuffer)
PhFree(xmlStringBuffer);
PostMessage(context->DialogHandle, ID_UPDATE_COUNT, 0, 0);
return STATUS_SUCCESS;
}
NTSTATUS SetupExtractBuild(
_In_ PVOID Parameter
)
{
static PH_STRINGREF pluginsDirectory = PH_STRINGREF_INIT(L"plugins\\");
mz_uint64 totalLength = 0;
mz_uint64 total_size = 0;
mz_uint64 downloadedBytes = 0;
PPH_STRING totalSizeStr = NULL;
mz_bool status = MZ_FALSE;
mz_zip_archive zip_archive;
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)Parameter;
memset(&zip_archive, 0, sizeof(zip_archive));
// TODO: Move existing folder items.
if (!(status = mz_zip_reader_init_file(&zip_archive, PhGetStringOrEmpty(context->SetupFilePath), 0)))
{
goto error;
}
for (mz_uint i = 0; i < mz_zip_reader_get_num_files(&zip_archive); i++)
{
mz_zip_archive_file_stat file_stat;
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat))
{
//mz_zip_reader_end(&zip_archive);
break;
}
total_size += file_stat.m_uncomp_size;
}
totalSizeStr = PhFormatSize(total_size, -1);
for (ULONG i = 0; i < mz_zip_reader_get_num_files(&zip_archive); i++)
{
mz_zip_archive_file_stat stat;
if (!mz_zip_reader_file_stat(&zip_archive, i, &stat))
{
continue;
}
if (mz_zip_reader_is_file_a_directory(&zip_archive, i))
{
PPH_STRING directory;
PPH_STRING fileName;
PPH_STRING fullSetupPath;
PPH_STRING extractPath;
ULONG indexOfFileName = -1;
fileName = PhConvertUtf8ToUtf16(stat.m_filename);
directory = PhGetApplicationDirectory();
extractPath = PhConcatStringRef3(&directory->sr, &pluginsDirectory, &fileName->sr);
fullSetupPath = PhGetFullPath(PhGetStringOrEmpty(extractPath), &indexOfFileName);
SHCreateDirectoryEx(NULL, PhGetStringOrEmpty(fullSetupPath), NULL);
}
else
{
PPH_STRING directory;
PPH_STRING fileName;
PPH_STRING fullSetupPath;
PPH_STRING extractPath;
PPH_STRING directoryPath;
//PPH_STRING baseNameString;
PPH_STRING fileNameString;
ULONG indexOfFileName = -1;
fileName = PhConvertUtf8ToUtf16(stat.m_filename);
directory = PhGetApplicationDirectory();
extractPath = PhConcatStringRef3(&directory->sr, &pluginsDirectory, &fileName->sr);
fullSetupPath = PhGetFullPath(PhGetStringOrEmpty(extractPath), &indexOfFileName);
//baseNameString = PhGetBaseName(fullSetupPath);
//fullSetupPath = PhGetFullPath(PhGetStringOrEmpty(fileName), &indexOfFileName);
fileNameString = PhConcatStrings(2, fullSetupPath->Buffer, L".bak");
if (indexOfFileName != -1)
{
if (directoryPath = PhSubstring(fullSetupPath, 0, indexOfFileName))
{
SHCreateDirectoryEx(NULL, PhGetStringOrEmpty(directoryPath), NULL);
PhDereferenceObject(directoryPath);
}
}
if (RtlDoesFileExists_U(PhGetStringOrEmpty(fullSetupPath)))
{
MoveFileEx(PhGetString(fullSetupPath), PhGetString(fileNameString), MOVEFILE_REPLACE_EXISTING);
}
if (!mz_zip_reader_extract_to_file(&zip_archive, i, PhGetString(fullSetupPath), 0))
{
goto error;
}
PhDereferenceObject(fullSetupPath);
PhDereferenceObject(extractPath);
}
}
mz_zip_reader_end(&zip_archive);
return STATUS_SUCCESS;
error:
mz_zip_reader_end(&zip_archive);
return STATUS_FAIL_CHECK;
}

View File

@ -0,0 +1,752 @@
/*
* Process Hacker Extra Plugins -
* Plugin Manager
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
BOOLEAN WordMatchStringRef(
_In_ PWCT_CONTEXT Context,
_In_ PPH_STRINGREF Text
)
{
PH_STRINGREF part;
PH_STRINGREF remainingPart;
remainingPart = Context->SearchboxText->sr;
while (remainingPart.Length)
{
PhSplitStringRefAtChar(&remainingPart, '|', &part, &remainingPart);
if (part.Length)
{
if (PhFindStringInStringRef(Text, &part, TRUE) != -1)
return TRUE;
}
}
return FALSE;
}
BOOLEAN WordMatchStringZ(
_In_ PWCT_CONTEXT Context,
_In_ PWSTR Text
)
{
PH_STRINGREF text;
PhInitializeStringRef(&text, Text);
return WordMatchStringRef(Context, &text);
}
VOID UpdateTreeView(
_In_ PWCT_CONTEXT Context
)
{
//PhSwapReference(&Context->TreeText, PhCreateString(L"Loading Plugins..."));
//TreeNew_SetEmptyText(Context->TreeNewHandle, &Context->TreeText->sr, 0);
PhApplyTreeNewFilters(Context->TreeFilter);
TreeNew_AutoSizeColumn(Context->TreeNewHandle, TREE_COLUMN_ITEM_NAME, TN_AUTOSIZE_REMAINING_SPACE);
}
VOID UpdateMenuView(_In_ PWCT_CONTEXT Context, UINT Id)
{
HWND active = Context->PluginMenuActive;
Context->PluginMenuActiveId = Id;
Context->PluginMenuActive = GetDlgItem(Context->DialogHandle, Id);
RedrawWindow(active, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE | RDW_FRAME);
}
LRESULT DrawButton(
_In_ PWCT_CONTEXT Context,
_In_ LPARAM lParam
)
{
LPNMTVCUSTOMDRAW drawInfo = (LPNMTVCUSTOMDRAW)lParam;
BOOLEAN isGrayed = (drawInfo->nmcd.uItemState & CDIS_GRAYED) == CDIS_GRAYED;
BOOLEAN isChecked = (drawInfo->nmcd.uItemState & CDIS_CHECKED) == CDIS_CHECKED;
BOOLEAN isDisabled = (drawInfo->nmcd.uItemState & CDIS_DISABLED) == CDIS_DISABLED;
BOOLEAN isSelected = (drawInfo->nmcd.uItemState & CDIS_SELECTED) == CDIS_SELECTED;
BOOLEAN isHighlighted = (drawInfo->nmcd.uItemState & CDIS_HOT) == CDIS_HOT;
BOOLEAN isFocused = (drawInfo->nmcd.uItemState & CDIS_FOCUS) == CDIS_FOCUS;
if (drawInfo->nmcd.dwDrawStage == CDDS_PREPAINT)
{
HPEN PenActive = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
HPEN PenNormal = CreatePen(PS_SOLID, 1, RGB(0, 0xff, 0));
HBRUSH BrushNormal = GetSysColorBrush(COLOR_3DFACE);
HBRUSH BrushSelected = CreateSolidBrush(RGB(0xff, 0xff, 0xff));
HBRUSH BrushPushed = CreateSolidBrush(RGB(153, 209, 255));
PPH_STRING windowText = PH_AUTO(PhGetWindowText(drawInfo->nmcd.hdr.hwndFrom));
SetBkMode(drawInfo->nmcd.hdc, TRANSPARENT);
if (isHighlighted || Context->PluginMenuActiveId == drawInfo->nmcd.hdr.idFrom)
{
FillRect(drawInfo->nmcd.hdc, &drawInfo->nmcd.rc, BrushNormal);
SelectObject(drawInfo->nmcd.hdc, PenActive);
SelectObject(drawInfo->nmcd.hdc, Context->BoldFontHandle);
}
else if (isSelected)
{
FillRect(drawInfo->nmcd.hdc, &drawInfo->nmcd.rc, BrushPushed);
SelectObject(drawInfo->nmcd.hdc, PenActive);
SelectObject(drawInfo->nmcd.hdc, Context->BoldFontHandle);
}
else
{
FillRect(drawInfo->nmcd.hdc, &drawInfo->nmcd.rc, BrushNormal);
}
DrawText(
drawInfo->nmcd.hdc,
windowText->Buffer,
(ULONG)windowText->Length / 2,
&drawInfo->nmcd.rc,
DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE
);
MoveToEx(drawInfo->nmcd.hdc, drawInfo->nmcd.rc.left, drawInfo->nmcd.rc.bottom, 0);
LineTo(drawInfo->nmcd.hdc, drawInfo->nmcd.rc.right, drawInfo->nmcd.rc.bottom);
DeletePen(PenNormal);
DeletePen(PenActive);
DeleteBrush(BrushNormal);
DeleteBrush(BrushSelected);
DeleteBrush(BrushPushed);
return CDRF_SKIPDEFAULT;
}
return CDRF_DODEFAULT;
}
BOOLEAN ProcessTreeFilterCallback(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
)
{
PWCT_CONTEXT context = Context;
PPLUGIN_NODE node = (PPLUGIN_NODE)Node;
// Hide plugins from different tabs
if (node->State != context->Type)
return FALSE;
// Hide uninstalled plugins from the local tab
//if (node->Type == PLUGIN_VIEW_LOCAL && node->State == PLUGIN_STATE_UNINSTALLED)
// return FALSE;
//// Hide installed plugins from the remote tab
//if (node->Type == PLUGIN_VIEW_REMOTE && node->State == PLUGIN_STATE_INSTALLED)
// return FALSE;
if (PhIsNullOrEmptyString(context->SearchboxText))
return TRUE;
if (!PhIsNullOrEmptyString(node->InternalName))
{
if (WordMatchStringRef(context, &node->InternalName->sr))
return TRUE;
}
if (!PhIsNullOrEmptyString(node->Id))
{
if (WordMatchStringRef(context, &node->Id->sr))
return TRUE;
}
if (!PhIsNullOrEmptyString(node->Name))
{
if (WordMatchStringRef(context, &node->Name->sr))
return TRUE;
}
if (!PhIsNullOrEmptyString(node->Version))
{
if (WordMatchStringRef(context, &node->Version->sr))
return TRUE;
}
if (!PhIsNullOrEmptyString(node->Author))
{
if (WordMatchStringRef(context, &node->Author->sr))
return TRUE;
}
if (!PhIsNullOrEmptyString(node->Description))
{
if (WordMatchStringRef(context, &node->Description->sr))
return TRUE;
}
return FALSE;
}
INT_PTR CALLBACK CloudPluginsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PWCT_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PWCT_CONTEXT)PhAllocate(sizeof(WCT_CONTEXT));
memset(context, 0, sizeof(WCT_CONTEXT));
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PWCT_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
{
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
PhDeleteLayoutManager(&context->LayoutManager);
PhUnregisterDialog(hwndDlg);
RemoveProp(hwndDlg, L"Context");
PhFree(context);
PostQuitMessage(0);
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
LOGFONT logFont;
context->DialogHandle = hwndDlg;
context->PluginMenuActiveId = IDC_INSTALLED;
context->PluginMenuActive = GetDlgItem(hwndDlg, IDC_INSTALLED);
context->TreeNewHandle = GetDlgItem(hwndDlg, IDC_PLUGINTREE);
context->SearchHandle = GetDlgItem(hwndDlg, IDC_SEARCHBOX);
context->SearchboxText = PhReferenceEmptyString();
CreateSearchControl(hwndDlg, context->SearchHandle, ID_SEARCH_CLEAR);
if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &logFont, 0))
{
context->NormalFontHandle = CreateFont(
-PhMultiplyDivideSigned(-14, PhGlobalDpi, 72),
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
DEFAULT_PITCH,
logFont.lfFaceName
);
context->BoldFontHandle = CreateFont(
-PhMultiplyDivideSigned(-16, PhGlobalDpi, 72),
0,
0,
0,
FW_BOLD,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
DEFAULT_PITCH,
logFont.lfFaceName
);
}
PhCenterWindow(hwndDlg, PhMainWndHandle);
WtcInitializeWindowTree(hwndDlg, context->TreeNewHandle, &context->TreeContext);
PhAddTreeNewFilter(context->TreeFilter = WtcGetTreeListFilterSupport(), (PPH_TN_FILTER_FUNCTION)ProcessTreeFilterCallback, context);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, context->TreeNewHandle, NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&context->LayoutManager, context->SearchHandle, NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_CLEANUP), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_DISABLED), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
PhLoadWindowPlacementFromSetting(SETTING_NAME_WINDOW_POSITION, SETTING_NAME_WINDOW_SIZE, hwndDlg);
EnumerateLoadedPlugins(context);
SetWindowText(GetDlgItem(hwndDlg, IDC_DISABLED), PhGetString(PhaFormatString(L"Disabled Plugins (%lu)", PhDisabledPluginsCount())));
PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), QueryPluginsCallbackThread, context);
UpdateTreeView(context);
SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_INSTALLED), TRUE);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
TreeNew_AutoSizeColumn(context->TreeNewHandle, TREE_COLUMN_ITEM_NAME, TN_AUTOSIZE_REMAINING_SPACE);
break;
case WM_COMMAND:
{
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case EN_CHANGE:
{
PPH_STRING newSearchboxText;
newSearchboxText = PH_AUTO(PhGetWindowText(context->SearchHandle));
if (!PhEqualString(context->SearchboxText, newSearchboxText, FALSE))
{
// Cache the current search text for our callback.
PhSwapReference(&context->SearchboxText, newSearchboxText);
if (!PhIsNullOrEmptyString(context->SearchboxText))
{
// Expand the nodes to ensure that they will be visible to the user.
}
PhApplyTreeNewFilters(context->TreeFilter);
}
}
break;
}
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case ID_SEARCH_CLEAR:
{
if (context->SearchHandle)
{
SetFocus(context->SearchHandle);
Static_SetText(context->SearchHandle, L"");
UpdateTreeView(context);
}
}
break;
case IDC_INSTALLED:
{
context->Type = PLUGIN_STATE_LOCAL;
UpdateMenuView(context, IDC_INSTALLED);
UpdateTreeView(context);
}
break;
case IDC_BROWSE:
{
context->Type = PLUGIN_STATE_REMOTE;
UpdateMenuView(context, IDC_BROWSE);
UpdateTreeView(context);
}
break;
case IDC_UPDATES:
{
context->Type = PLUGIN_STATE_UPDATE;
UpdateMenuView(context, IDC_UPDATES);
UpdateTreeView(context);
}
break;
case WM_ACTION:
{
PPLUGIN_NODE selectedNode;
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
{
if (selectedNode->State == PLUGIN_STATE_LOCAL)
{
if (selectedNode->PluginInstance && selectedNode->PluginInstance->Information.HasOptions)
{
PhInvokeCallback(PhGetPluginCallback((PPH_PLUGIN)selectedNode->PluginInstance, PluginCallbackShowOptions), hwndDlg);
}
}
else if (selectedNode->State == PLUGIN_STATE_REMOTE)
{
if (StartInitialCheck(hwndDlg, selectedNode, PLUGIN_ACTION_INSTALL))
{
}
}
else if (selectedNode->State == PLUGIN_STATE_UPDATE)
{
if (StartInitialCheck(hwndDlg, selectedNode, PLUGIN_ACTION_INSTALL))
{
}
}
}
}
break;
case ID_WCTSHOWCONTEXTMENU:
{
POINT cursorPos;
PPH_EMENU menu;
PPH_EMENU_ITEM selectedItem;
PPLUGIN_NODE selectedNode;
GetCursorPos(&cursorPos);
if (!(selectedNode = WeGetSelectedWindowNode(&context->TreeContext)))
break;
menu = PhCreateEMenu();
if (selectedNode->State == PLUGIN_STATE_LOCAL)
{
HICON shieldIcon;
shieldIcon = PhLoadIcon(NULL, IDI_SHIELD, PH_LOAD_ICON_SIZE_SMALL | PH_LOAD_ICON_STRICT, 0, 0);
selectedItem = PhCreateEMenuItem(0, ID_MENU_UNINSTALL, L"Uninstall", NULL, NULL);
if (shieldIcon)
{
selectedItem->Bitmap = PhIconToBitmap(
shieldIcon,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON)
);
DestroyIcon(shieldIcon);
}
PhInsertEMenuItem(menu, selectedItem, -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, ID_MENU_DISABLE, L"Disable", NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, ID_MENU_PROPERTIES, L"Options", NULL, NULL), -1);
if (!selectedNode->PluginInstance || !selectedNode->PluginInstance->Information.HasOptions)
{
PhSetFlagsEMenuItem(menu, ID_MENU_PROPERTIES, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
if (!PhGetOwnTokenAttributes().Elevated)
{
PhSetFlagsEMenuItem(menu, ID_MENU_UNINSTALL, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
}
else
{
HICON shieldIcon;
shieldIcon = PhLoadIcon(NULL, IDI_SHIELD, PH_LOAD_ICON_SIZE_SMALL | PH_LOAD_ICON_STRICT, 0, 0);
selectedItem = PhCreateEMenuItem(0, ID_MENU_INSTALL, PhaFormatString(L"Install %s plugin", PhGetStringOrEmpty(selectedNode->Name))->Buffer, NULL, NULL);
if (shieldIcon)
{
selectedItem->Bitmap = PhIconToBitmap(
shieldIcon,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON)
);
DestroyIcon(shieldIcon);
}
PhInsertEMenuItem(menu, selectedItem, -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(PH_EMENU_SEPARATOR, 0, NULL, NULL, NULL), -1);
PhInsertEMenuItem(menu, PhCreateEMenuItem(0, ID_MENU_DISABLE, L"Disable", NULL, NULL), -1);
if (!PhGetOwnTokenAttributes().Elevated)
{
PhSetFlagsEMenuItem(menu, ID_MENU_INSTALL, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
}
}
selectedItem = PhShowEMenu(
menu,
hwndDlg,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
cursorPos.x,
cursorPos.y
);
if (selectedItem && selectedItem->Id != -1)
{
switch (selectedItem->Id)
{
case ID_MENU_INSTALL:
{
if (!PhGetOwnTokenAttributes().Elevated)
{
//SHELLEXECUTEINFO info = { sizeof(SHELLEXECUTEINFO) };
//info.lpFile = L"ProcessHacker.exe";
//info.lpParameters = L"-plugin dmex.ExtraPlugins:INSTALL -plugin dmex.ExtraPlugins:hex64value";
//info.lpVerb = L"runas";
//info.nShow = SW_SHOW;
//info.hwnd = hwndDlg;
//if (!ShellExecuteEx(&info))
//{
//}
}
else
{
PPLUGIN_NODE selectedNode;
PPLUGIN_NODE existingNode;
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
{
if (selectedNode->State == PLUGIN_STATE_LOCAL)
{
if (existingNode = FindTreeNode(
&context->TreeContext,
PLUGIN_STATE_REMOTE,
selectedNode->InternalName
))
{
if (StartInitialCheck(hwndDlg, existingNode, PLUGIN_ACTION_INSTALL))
{
}
}
UpdateTreeView(context);
}
else
{
if (StartInitialCheck(hwndDlg, selectedNode, PLUGIN_ACTION_INSTALL))
{
}
if (existingNode = FindTreeNode(
&context->TreeContext,
PLUGIN_STATE_REMOTE,
selectedNode->InternalName
))
{
selectedNode->State = PLUGIN_STATE_RESTART;
}
UpdateTreeView(context);
}
}
}
}
break;
case ID_MENU_UNINSTALL:
{
if (!PhGetOwnTokenAttributes().Elevated)
{
//SHELLEXECUTEINFO info = { sizeof(SHELLEXECUTEINFO) };
//info.lpFile = L"ProcessHacker.exe";
//info.lpParameters = L"-plugin dmex.ExtraPlugins:UNINSTALL -plugin dmex.ExtraPlugins:hex64value";
//info.lpVerb = L"runas";
//info.nShow = SW_SHOW;
//info.hwnd = hwndDlg;
//
//if (!ShellExecuteEx(&info))
//{
//
//}
}
else
{
PPLUGIN_NODE selectedNode;
PPLUGIN_NODE existingNode;
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
{
if (StartInitialCheck(hwndDlg, selectedNode, PLUGIN_ACTION_UNINSTALL))
{
if (existingNode = FindTreeNode(
&context->TreeContext,
PLUGIN_STATE_LOCAL,
selectedNode->InternalName
))
{
existingNode->State = PLUGIN_STATE_RESTART;
}
}
UpdateTreeView(context);
}
}
}
break;
case ID_MENU_DISABLE:
{
PPH_STRING baseName;
baseName = PhGetBaseName(selectedNode->FileName);
PhSetPluginDisabled(&baseName->sr, TRUE);
selectedNode->State = PLUGIN_STATE_RESTART;
UpdateTreeView(context);
SetWindowText(GetDlgItem(hwndDlg, IDC_DISABLED),
PhGetString(PhaFormatString(L"Disabled Plugins (%lu)", PhDisabledPluginsCount()))
);
}
break;
case ID_MENU_PROPERTIES:
{
if (selectedNode->PluginInstance)
{
PhInvokeCallback(PhGetPluginCallback((PPH_PLUGIN)selectedNode->PluginInstance, PluginCallbackShowOptions), hwndDlg);
}
}
break;
}
}
}
break;
case IDCANCEL:
case IDOK:
{
//ShowUpdateDialog(hwndDlg, PLUGIN_ACTION_RESTART);
DestroyWindow(hwndDlg);
}
break;
case IDC_DISABLED:
{
ShowDisabledPluginsDialog(hwndDlg);
SetWindowText(GetDlgItem(hwndDlg, IDC_DISABLED),
PhGetString(PhaFormatString(L"Disabled Plugins (%lu)", PhDisabledPluginsCount()))
);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
switch (header->code)
{
case NM_CUSTOMDRAW:
{
if (header->idFrom == IDC_INSTALLED || header->idFrom == IDC_BROWSE || header->idFrom == IDC_UPDATES)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, DrawButton(context, lParam));
return TRUE;
}
}
break;
}
}
break;
case ID_UPDATE_ADD:
{
PPLUGIN_NODE entry = (PPLUGIN_NODE)lParam;
CloudAddChildWindowNode(&context->TreeContext, entry);
UpdateTreeView(context);
}
break;
case ID_UPDATE_COUNT:
{
ULONG count = 0;
for (ULONG i = 0; i < context->TreeContext.NodeList->Count; i++)
{
PPLUGIN_NODE windowNode = context->TreeContext.NodeList->Items[i];
if (windowNode->State == PLUGIN_STATE_UPDATE)
{
count++;
}
}
SetWindowText(GetDlgItem(hwndDlg, IDC_UPDATES), PhGetString(PhaFormatString(L"Updates (%lu)", count)));
}
break;
}
return FALSE;
}
NTSTATUS CloudDialogThread(
_In_ PVOID Parameter
)
{
BOOL result;
MSG message;
HWND cloudDialogHandle;
PH_AUTO_POOL autoPool;
PhInitializeAutoPool(&autoPool);
cloudDialogHandle = CreateDialog(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_PLUGINS_DIALOG),
NULL,
CloudPluginsDlgProc
);
if (IsIconic(cloudDialogHandle))
ShowWindow(cloudDialogHandle, SW_RESTORE);
else
ShowWindow(cloudDialogHandle, SW_SHOW);
SetForegroundWindow(cloudDialogHandle);
while (result = GetMessage(&message, NULL, 0, 0))
{
if (result == -1)
break;
if (!IsDialogMessage(cloudDialogHandle, &message))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
PhDrainAutoPool(&autoPool);
}
PhDeleteAutoPool(&autoPool);
return STATUS_SUCCESS;
}
VOID ShowPluginManagerDialog(
VOID
)
{
HANDLE threadHandle;
if (threadHandle = PhCreateThread(0, CloudDialogThread, NULL))
{
NtClose(threadHandle);
}
}

View File

@ -0,0 +1,184 @@
/*
* Process Hacker Extra Plugins -
* Plugin Manager
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
VOID PhAddDisabledPlugins(
_In_ PPLUGIN_DISABLED_CONTEXT Context
)
{
PPH_STRING disabled;
PH_STRINGREF remainingPart;
PH_STRINGREF part;
PPH_STRING displayText;
INT lvItemIndex;
disabled = PhGetStringSetting(L"DisabledPlugins");
remainingPart = disabled->sr;
while (remainingPart.Length)
{
PhSplitStringRefAtChar(&remainingPart, '|', &part, &remainingPart);
if (part.Length)
{
displayText = PhCreateString2(&part);
PhAcquireQueuedLockExclusive(&Context->ListLock);
lvItemIndex = PhAddListViewItem(Context->ListViewHandle, MAXINT, PhGetString(displayText), displayText);
PhReleaseQueuedLockExclusive(&Context->ListLock);
ListView_SetItemState(Context->ListViewHandle, lvItemIndex, ITEM_CHECKED, LVIS_STATEIMAGEMASK);
}
}
PhDereferenceObject(disabled);
}
INT_PTR CALLBACK DisabledPluginsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PPLUGIN_DISABLED_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PPLUGIN_DISABLED_CONTEXT)PhAllocate(sizeof(PLUGIN_DISABLED_CONTEXT));
memset(context, 0, sizeof(PLUGIN_DISABLED_CONTEXT));
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PPLUGIN_DISABLED_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
{
PhDeleteLayoutManager(&context->LayoutManager);
PhUnregisterDialog(hwndDlg);
RemoveProp(hwndDlg, L"Context");
PhFree(context);
}
}
if (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
context->DialogHandle = hwndDlg;
context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST_DISABLED);
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE);
ListView_SetExtendedListViewStyleEx(context->ListViewHandle,
LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER,
LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
PhSetControlTheme(context->ListViewHandle, L"explorer");
PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 400, L"Property");
PhSetExtendedListView(context->ListViewHandle);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
PhAddDisabledPlugins(context);
SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDOK), TRUE);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
break;
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDCANCEL:
case IDOK:
{
EndDialog(hwndDlg, IDOK);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
if (header->code == LVN_ITEMCHANGED)
{
LPNM_LISTVIEW listView = (LPNM_LISTVIEW)lParam;
if (!PhTryAcquireReleaseQueuedLockExclusive(&context->ListLock))
break;
if (listView->uChanged & LVIF_STATE)
{
switch (listView->uNewState & LVIS_STATEIMAGEMASK)
{
case 0x2000: // checked
{
PPH_STRING param = (PPH_STRING)listView->lParam;
PhSetPluginDisabled(&param->sr, TRUE);
//context->OptionsChanged = TRUE;
}
break;
case 0x1000: // unchecked
{
PPH_STRING param = (PPH_STRING)listView->lParam;
PhSetPluginDisabled(&param->sr, FALSE);
//context->OptionsChanged = TRUE;
}
break;
}
}
}
}
break;
}
return FALSE;
}
VOID ShowDisabledPluginsDialog(
_In_ HWND Parent
)
{
DialogBox(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_DIALOG1),
Parent,
DisabledPluginsDlgProc
);
}

View File

@ -0,0 +1,5 @@
Michael Clark <michael@metaparadigm.com>
Jehiah Czebotar <jehiah@gmail.com>
Eric Haszlakiewicz <hawicz+json-c@gmail.com>
C. Watford (christopher.watford@gmail.com)

View File

@ -0,0 +1,42 @@
Copyright (c) 2009-2012 Eric Haszlakiewicz
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
----------------------------------------------------------------
Copyright (c) 2004, 2005 Metaparadigm Pte Ltd
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,214 @@
0.12
* Address security issues:
* CVE-2013-6371: hash collision denial of service
* CVE-2013-6370: buffer overflow if size_t is larger than int
* Avoid potential overflow in json_object_get_double
* Eliminate the mc_abort() function and MC_ABORT macro.
* Make the json_tokener_errors array local. It has been deprecated for
a while, and json_tokener_error_desc() should be used instead.
* change the floating point output format to %.17g so values with
more than 6 digits show up in the output.
* Remove the old libjson.so name compatibility support. The library is
only created as libjson-c.so now and headers are only installed
into the ${prefix}/json-c directory.
* When supported by the linker, add the -Bsymbolic-functions flag.
* Various changes to fix the build on MSVC.
* Make strict mode more strict:
* number must not start with 0
* no single-quote strings
* no comments
* trailing char not allowed
* only allow lowercase literals
* Added a json_object_new_double_s() convenience function to allow
an exact string representation of a double to be specified when
creating the object and use it in json_tokener_parse_ex() so
a re-serialized object more exactly matches the input.
* Add support NaN and Infinity
0.11
* IMPORTANT: the name of the library has changed to libjson-c.so and
the header files are now in include/json-c.
The pkgconfig name has also changed from json to json-c.
You should change your build to use appropriate -I and -l options.
A compatibility shim is in place so builds using the old name will
continue to work, but that will be removed in the next release.
* Maximum recursion depth is now a runtime option.
json_tokener_new() is provided for compatibility.
json_tokener_new_ex(depth)
* Include json_object_iterator.h in the installed headers.
* Add support for building on Android.
* Rewrite json_object_object_add to replace just the value if the key already exists so keys remain valid.
* Make it safe to delete keys while iterating with the json_object_object_foreach macro.
* Add a json_set_serializer() function to allow the string output of a json_object to be customized.
* Make float parsing locale independent.
* Add a json_tokener_set_flags() function and a JSON_TOKENER_STRICT flag.
* Enable -Werror when building.
* speed improvements to parsing 64-bit integers on systems with working sscanf
* Add a json_object_object_length function.
* Fix a bug (buffer overrun) when expanding arrays to more than 64 entries.
0.10
* Add a json_object_to_json_string_ext() function to allow output to be
formatted in a more human readable form.
* Add json_object_object_get_ex(), a NULL-safe get object method, to be able
to distinguish between a key not present and the value being NULL.
* Add an alternative iterator implementation, see json_object_iterator.h
* Make json_object_iter public to enable external use of the
json_object_object_foreachC macro.
* Add a printbuf_memset() function to provide an effecient way to set and
append things like whitespace indentation.
* Adjust json_object_is_type and json_object_get_type so they return
json_type_null for NULL objects and handle NULL passed to
json_objct_object_get().
* Rename boolean type to json_bool.
* Fix various compile issues for Visual Studio and MinGW.
* Allow json_tokener_parse_ex() to be re-used to parse multiple object.
Also, fix some parsing issues with capitalized hexadecimal numbers and
number in E notation.
* Add json_tokener_get_error() and json_tokener_error_desc() to better
encapsulate the process of retrieving errors while parsing.
* Various improvements to the documentation of many functions.
* Add new json_object_array_sort() function.
* Fix a bug in json_object_get_int(), which would incorrectly return 0
when called on a string type object.
Eric Haszlakiewicz
* Add a json_type_to_name() function.
Eric Haszlakiewicz
* Add a json_tokener_parse_verbose() function.
Jehiah Czebotar
* Improve support for null bytes within JSON strings.
Jehiah Czebotar
* Fix file descriptor leak if memory allocation fails in json_util
Zachary Blair, zack_blair at hotmail dot com
* Add int64 support. Two new functions json_object_net_int64 and
json_object_get_int64. Binary compatibility preserved.
Eric Haszlakiewicz, EHASZLA at transunion com
Rui Miguel Silva Seabra, rms at 1407 dot org
* Fix subtle bug in linkhash where lookup could hang after all slots
were filled then successively freed.
Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com
* Make json_object_from_file take const char *filename
Spotted by Vikram Raj V, vsagar at attinteractive dot com
* Add handling of surrogate pairs (json_tokener.c, test4.c, Makefile.am)
Brent Miller, bdmiller at yahoo dash inc dot com
* Correction to comment describing printbuf_memappend in printbuf.h
Brent Miller, bdmiller at yahoo dash inc dot com
0.9
* Add README.html README-WIN32.html config.h.win32 to Makefile.am
Michael Clark, <michael@metaparadigm.com>
* Add const qualifier to the json_tokener_parse functions
Eric Haszlakiewicz, EHASZLA at transunion dot com
* Rename min and max so we can never clash with C or C++ std library
Ian Atha, thatha at yahoo dash inc dot com
* Fix any noticeable spelling or grammar errors.
* Make sure every va_start has a va_end.
* Check all pointers for validity.
Erik Hovland, erik at hovland dot org
* Fix json_object_get_boolean to return false for empty string
Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com
* optimizations to json_tokener_parse_ex(), printbuf_memappend()
Brent Miller, bdmiller at yahoo dash inc dot com
* Disable REFCOUNT_DEBUG by default in json_object.c
* Don't use this as a variable, so we can compile with a C++ compiler
* Add casts from void* to type of assignment when using malloc
* Add #ifdef __cplusplus guards to all of the headers
* Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table
Michael Clark, <michael@metaparadigm.com>
* Null pointer dereference fix. Fix json_object_get_boolean strlen test
to not return TRUE for zero length string. Remove redundant includes.
Erik Hovland, erik at hovland dot org
* Fixed warning reported by adding -Wstrict-prototypes
-Wold-style-definition to the compilatin flags.
Dotan Barak, dotanba at gmail dot com
* Add const correctness to public interfaces
Gerard Krol, g dot c dot krol at student dot tudelft dot nl
0.8
* Add va_end for every va_start
Dotan Barak, dotanba at gmail dot com
* Add macros to enable compiling out debug code
Geoffrey Young, geoff at modperlcookbook dot org
* Fix bug with use of capital E in numbers with exponents
Mateusz Loskot, mateusz at loskot dot net
* Add stddef.h include
* Patch allows for json-c compile with -Werror and not fail due to
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
Geoffrey Young, geoff at modperlcookbook dot org
0.7
* Add escaping of backslash to json output
* Add escaping of foward slash on tokenizing and output
* Changes to internal tokenizer from using recursion to
using a depth state structure to allow incremental parsing
0.6
* Fix bug in escaping of control characters
Johan Björklund, johbjo09 at kth dot se
* Remove include "config.h" from headers (should only
be included from .c files)
Michael Clark <michael@metaparadigm.com>
0.5
* Make headers C++ compatible by change *this to *obj
* Add ifdef C++ extern "C" to headers
* Use simpler definition of min and max in bits.h
Larry Lansing, llansing at fuzzynerd dot com
* Remove automake 1.6 requirement
* Move autogen commands into autogen.sh. Update README
* Remove error pointer special case for Windows
* Change license from LGPL to MIT
Michael Clark <michael@metaparadigm.com>
0.4
* Fix additional error case in object parsing
* Add back sign reversal in nested object parse as error pointer
value is negative, while error value is positive.
Michael Clark <michael@metaparadigm.com>
0.3
* fix pointer arithmetic bug for error pointer check in is_error() macro
* fix type passed to printbuf_memappend in json_tokener
* update autotools bootstrap instructions in README
Michael Clark <michael@metaparadigm.com>
0.2
* printbuf.c - C. Watford (christopher.watford@gmail.com)
Added a Win32/Win64 compliant implementation of vasprintf
* debug.c - C. Watford (christopher.watford@gmail.com)
Removed usage of vsyslog on Win32/Win64 systems, needs to be handled
by a configure script
* json_object.c - C. Watford (christopher.watford@gmail.com)
Added scope operator to wrap usage of json_object_object_foreach, this
needs to be rethought to be more ANSI C friendly
* json_object.h - C. Watford (christopher.watford@gmail.com)
Added Microsoft C friendly version of json_object_object_foreach
* json_tokener.c - C. Watford (christopher.watford@gmail.com)
Added a Win32/Win64 compliant implementation of strndup
* json_util.c - C. Watford (christopher.watford@gmail.com)
Added cast and mask to suffice size_t v. unsigned int conversion
correctness
* json_tokener.c - sign reversal issue on error info for nested object parse
spotted by Johan Björklund (johbjo09 at kth.se)
* json_object.c - escape " in json_escape_str
* Change to automake and libtool to build shared and static library
Michael Clark <michael@metaparadigm.com>
0.1
* initial release

View File

@ -0,0 +1,101 @@
/*
* $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif /* STDC_HEADERS */
#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD)
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include "bits.h"
#include "arraylist.h"
struct array_list*
array_list_new(array_list_free_fn *free_fn)
{
struct array_list *arr;
arr = (struct array_list*)calloc(1, sizeof(struct array_list));
if(!arr) return NULL;
arr->size = ARRAY_LIST_DEFAULT_SIZE;
arr->length = 0;
arr->free_fn = free_fn;
if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) {
free(arr);
return NULL;
}
return arr;
}
extern void
array_list_free(struct array_list *arr)
{
int i;
for(i = 0; i < arr->length; i++)
if(arr->array[i]) arr->free_fn(arr->array[i]);
free(arr->array);
free(arr);
}
void*
array_list_get_idx(struct array_list *arr, int i)
{
if(i >= arr->length) return NULL;
return arr->array[i];
}
static int array_list_expand_internal(struct array_list *arr, int max)
{
void *t;
int new_size;
if(max < arr->size) return 0;
new_size = json_max(arr->size << 1, max);
if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
arr->array = (void**)t;
(void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
arr->size = new_size;
return 0;
}
int
array_list_put_idx(struct array_list *arr, int idx, void *data)
{
if(array_list_expand_internal(arr, idx+1)) return -1;
if(arr->array[idx]) arr->free_fn(arr->array[idx]);
arr->array[idx] = data;
if(arr->length <= idx) arr->length = idx + 1;
return 0;
}
int
array_list_add(struct array_list *arr, void *data)
{
return array_list_put_idx(arr, arr->length, data);
}
void
array_list_sort(struct array_list *arr, int(__cdecl* sort_fn)(const void *, const void *))
{
qsort(arr->array, arr->length, sizeof(arr->array[0]),
(int (__cdecl*)(const void *, const void *))sort_fn);
}
int
array_list_length(struct array_list *arr)
{
return arr->length;
}

View File

@ -0,0 +1,56 @@
/*
* $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _arraylist_h_
#define _arraylist_h_
#ifdef __cplusplus
extern "C" {
#endif
#define ARRAY_LIST_DEFAULT_SIZE 32
typedef void (array_list_free_fn) (void *data);
struct array_list
{
void **array;
int length;
int size;
array_list_free_fn *free_fn;
};
extern struct array_list*
array_list_new(array_list_free_fn *free_fn);
extern void
array_list_free(struct array_list *al);
extern void*
array_list_get_idx(struct array_list *al, int i);
extern int
array_list_put_idx(struct array_list *al, int i, void *data);
extern int
array_list_add(struct array_list *al, void *data);
extern int
array_list_length(struct array_list *al);
extern void
array_list_sort(struct array_list *arr, int(__cdecl* compar)(const void *, const void *));
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,28 @@
/*
* $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _bits_h_
#define _bits_h_
#ifndef json_min
#define json_min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef json_max
#define json_max(a,b) ((a) > (b) ? (a) : (b))
#endif
#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
#define error_ptr(error) ((void*)error)
#define error_description(error) (json_tokener_errors[error])
#define is_error(ptr) (ptr == NULL)
#endif

View File

@ -0,0 +1,89 @@
#define PACKAGE_STRING "JSON C Library 0.12-20140410"
#define PACKAGE_BUGREPORT "json-c@googlegroups.com"
#define PACKAGE_NAME "JSON C Library"
#define PACKAGE_TARNAME "json-c"
#define PACKAGE_VERSION "0.12-20140410"
#define HAVE_SETLOCALE 1
#define HAVE_LOCALE_H 1
#define HAVE_DECL_NAN 1
#define HAVE_DECL_INFINITY 1
//#define HAVE_DECL__ISNAN 1
//#define HAVE_DECL__FINITE 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `open' function. */
#define HAVE_OPEN 1
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#define HAVE_REALLOC 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRNDUP 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to 1 if you have the `vsyslog' function. */
#undef HAVE_VSYSLOG
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1

View File

@ -0,0 +1,174 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Enable RDRANR Hardware RNG Hash Seed */
#undef ENABLE_RDRAND
/* Define if .gnu.warning accepts long strings. */
#undef HAS_GNU_WARNING_LONG
/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
don't. */
#undef HAVE_DECL_INFINITY
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#undef HAVE_DECL_ISINF
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#undef HAVE_DECL_ISNAN
/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
#undef HAVE_DECL_NAN
/* Define to 1 if you have the declaration of `_finite', and to 0 if you
don't. */
#undef HAVE_DECL__FINITE
/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
*/
#undef HAVE_DECL__ISNAN
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `open' function. */
#undef HAVE_OPEN
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#undef HAVE_REALLOC
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to 1 if you have the `vsyslog' function. */
#undef HAVE_VSYSLOG
/* Public define for json_inttypes.h */
#undef JSON_C_HAVE_INTTYPES_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to rpl_realloc if the replacement function should be used. */
#undef realloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View File

@ -0,0 +1,83 @@
/*
* $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#if HAVE_SYSLOG_H
# include <syslog.h>
#endif /* HAVE_SYSLOG_H */
#if HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#include "debug.h"
static int _syslog = 0;
static int _debug = 0;
void mc_set_debug(int debug) { _debug = debug; }
int mc_get_debug(void) { return _debug; }
extern void mc_set_syslog(int syslog)
{
_syslog = syslog;
}
void mc_debug(const char *msg, ...)
{
va_list ap;
if(_debug) {
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_DEBUG, msg, ap);
} else
#endif
vprintf(msg, ap);
va_end(ap);
}
}
void mc_error(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_ERR, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}
void mc_info(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_INFO, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}

View File

@ -0,0 +1,71 @@
/*
* $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void mc_set_debug(int debug);
extern int mc_get_debug(void);
extern void mc_set_syslog(int syslog);
extern void mc_debug(const char *msg, ...);
extern void mc_error(const char *msg, ...);
extern void mc_info(const char *msg, ...);
#ifndef __STRING
#define __STRING(x) #x
#endif
#ifndef PARSER_BROKEN_FIXED
#define JASSERT(cond) do {} while(0)
#else
#define JASSERT(cond) do { \
if (!(cond)) { \
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
*(int *)0 = 1;\
abort(); \
}\
} while(0)
#endif
#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
#ifdef MC_MAINTAINER_MODE
#define MC_SET_DEBUG(x) mc_set_debug(x)
#define MC_GET_DEBUG() mc_get_debug()
#define MC_SET_SYSLOG(x) mc_set_syslog(x)
#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
#else
#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
#define MC_GET_DEBUG() (0)
#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,34 @@
/*
* $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_h_
#define _json_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "bits.h"
#include "debug.h"
#include "linkhash.h"
#include "arraylist.h"
#include "json_util.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_object_iterator.h"
#include "json_c_version.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2012 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
#include "config.h"
#include "json_c_version.h"
const char *json_c_version(void)
{
return JSON_C_VERSION;
}
int json_c_version_num(void)
{
return JSON_C_VERSION_NUM;
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2012 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
#ifndef _json_c_version_h_
#define _json_c_version_h_
#define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 12
#define JSON_C_MICRO_VERSION 0
#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
(JSON_C_MINOR_VERSION << 8) | \
JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.12"
const char *json_c_version(void); /* Returns JSON_C_VERSION */
int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
#endif

View File

@ -0,0 +1,3 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define JSON_C_HAVE_INTTYPES_H 1

View File

@ -0,0 +1,28 @@
#ifndef _json_inttypes_h_
#define _json_inttypes_h_
#include "json_config.h"
#if defined(_MSC_VER) && _MSC_VER <= 1700
/* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */
typedef __int32 int32_t;
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX ((int32_t)_I32_MAX)
typedef __int64 int64_t;
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX ((int64_t)_I64_MAX)
#define PRId64 "I64d"
#define SCNd64 "I64d"
#else
#ifdef JSON_C_HAVE_INTTYPES_H
#include <inttypes.h>
#endif
/* inttypes.h includes stdint.h */
#endif
#endif

View File

@ -0,0 +1,860 @@
/*
* $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include "debug.h"
#include "printbuf.h"
#include "linkhash.h"
#include "arraylist.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_object_private.h"
#include "json_util.h"
#include "math_compat.h"
#if !defined(HAVE_STRDUP) && defined(_MSC_VER)
/* MSC has the version as _strdup */
# define strdup _strdup
#elif !defined(HAVE_STRDUP)
# error You do not have strdup on your system.
#endif /* HAVE_STRDUP */
#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
/* MSC has the version as _snprintf */
# define snprintf _snprintf
#elif !defined(HAVE_SNPRINTF)
# error You do not have snprintf on your system.
#endif /* HAVE_SNPRINTF */
// Don't define this. It's not thread-safe.
/* #define REFCOUNT_DEBUG 1 */
const char *json_number_chars = "0123456789.+-eE";
const char *json_hex_chars = "0123456789abcdefABCDEF";
static void json_object_generic_delete(struct json_object* jso);
static struct json_object* json_object_new(enum json_type o_type);
static json_object_to_json_string_fn json_object_object_to_json_string;
static json_object_to_json_string_fn json_object_boolean_to_json_string;
static json_object_to_json_string_fn json_object_int_to_json_string;
static json_object_to_json_string_fn json_object_double_to_json_string;
static json_object_to_json_string_fn json_object_string_to_json_string;
static json_object_to_json_string_fn json_object_array_to_json_string;
/* ref count debugging */
#ifdef REFCOUNT_DEBUG
static struct lh_table *json_object_table;
static void json_object_init(void) __attribute__ ((constructor));
static void json_object_init(void) {
MC_DEBUG("json_object_init: creating object table\n");
json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
}
static void json_object_fini(void) __attribute__ ((destructor));
static void json_object_fini(void) {
struct lh_entry *ent;
if(MC_GET_DEBUG()) {
if (json_object_table->count) {
MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
json_object_table->count);
lh_foreach(json_object_table, ent) {
struct json_object* obj = (struct json_object*)ent->v;
MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj);
}
}
}
MC_DEBUG("json_object_fini: freeing object table\n");
lh_table_free(json_object_table);
}
#endif /* REFCOUNT_DEBUG */
/* string escaping */
static int json_escape_str(struct printbuf *pb, char *str, size_t len)
{
int pos = 0, start_offset = 0;
unsigned char c;
while (len--) {
c = str[pos];
switch(c) {
case '\b':
case '\n':
case '\r':
case '\t':
case '\f':
case '"':
case '\\':
case '/':
if(pos - start_offset > 0)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
if(c == '\b') printbuf_memappend(pb, "\\b", 2);
else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
else if(c == '\f') printbuf_memappend(pb, "\\f", 2);
else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
else if(c == '/') printbuf_memappend(pb, "\\/", 2);
start_offset = ++pos;
break;
default:
if(c < ' ') {
if(pos - start_offset > 0)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
sprintbuf(pb, "\\u00%c%c",
json_hex_chars[c >> 4],
json_hex_chars[c & 0xf]);
start_offset = ++pos;
} else pos++;
}
}
if(pos - start_offset > 0)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
return 0;
}
/* reference counting */
extern struct json_object* json_object_get(struct json_object *jso)
{
if(jso) {
jso->_ref_count++;
}
return jso;
}
int json_object_put(struct json_object *jso)
{
if(jso)
{
jso->_ref_count--;
if(!jso->_ref_count)
{
if (jso->_user_delete)
jso->_user_delete(jso, jso->_userdata);
jso->_delete(jso);
return 1;
}
}
return 0;
}
/* generic object construction and destruction parts */
static void json_object_generic_delete(struct json_object* jso)
{
#ifdef REFCOUNT_DEBUG
MC_DEBUG("json_object_delete_%s: %p\n",
json_type_to_name(jso->o_type), jso);
lh_table_delete(json_object_table, jso);
#endif /* REFCOUNT_DEBUG */
printbuf_free(jso->_pb);
free(jso);
}
static struct json_object* json_object_new(enum json_type o_type)
{
struct json_object *jso;
jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
if(!jso) return NULL;
jso->o_type = o_type;
jso->_ref_count = 1;
jso->_delete = &json_object_generic_delete;
#ifdef REFCOUNT_DEBUG
lh_table_insert(json_object_table, jso, jso);
MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso);
#endif /* REFCOUNT_DEBUG */
return jso;
}
/* type checking functions */
int json_object_is_type(struct json_object *jso, enum json_type type)
{
if (!jso)
return (type == json_type_null);
return (jso->o_type == type);
}
enum json_type json_object_get_type(struct json_object *jso)
{
if (!jso)
return json_type_null;
return jso->o_type;
}
/* set a custom conversion to string */
void json_object_set_serializer(json_object *jso,
json_object_to_json_string_fn to_string_func,
void *userdata,
json_object_delete_fn *user_delete)
{
// First, clean up any previously existing user info
if (jso->_user_delete)
{
jso->_user_delete(jso, jso->_userdata);
}
jso->_userdata = NULL;
jso->_user_delete = NULL;
if (to_string_func == NULL)
{
// Reset to the standard serialization function
switch(jso->o_type)
{
case json_type_null:
jso->_to_json_string = NULL;
break;
case json_type_boolean:
jso->_to_json_string = &json_object_boolean_to_json_string;
break;
case json_type_double:
jso->_to_json_string = &json_object_double_to_json_string;
break;
case json_type_int:
jso->_to_json_string = &json_object_int_to_json_string;
break;
case json_type_object:
jso->_to_json_string = &json_object_object_to_json_string;
break;
case json_type_array:
jso->_to_json_string = &json_object_array_to_json_string;
break;
case json_type_string:
jso->_to_json_string = &json_object_string_to_json_string;
break;
}
return;
}
jso->_to_json_string = to_string_func;
jso->_userdata = userdata;
jso->_user_delete = user_delete;
}
/* extended conversion to string */
char* json_object_to_json_string_ext(struct json_object *jso, int flags)
{
if (!jso)
return "null";
if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
return NULL;
printbuf_reset(jso->_pb);
if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
return NULL;
return jso->_pb->buf;
}
/* backwards-compatible conversion to string */
char* json_object_to_json_string(struct json_object *jso)
{
return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
}
static void indent(struct printbuf *pb, int level, int flags)
{
if (flags & JSON_C_TO_STRING_PRETTY)
{
printbuf_memset(pb, -1, ' ', level * 2);
}
}
/* json_object_object */
static int json_object_object_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
int had_children = 0;
struct json_object_iter iter;
sprintbuf(pb, "{" /*}*/);
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
json_object_object_foreachC(jso, iter)
{
if (had_children)
{
sprintbuf(pb, ",");
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
}
had_children = 1;
if (flags & JSON_C_TO_STRING_SPACED)
sprintbuf(pb, " ");
indent(pb, level+1, flags);
sprintbuf(pb, "\"");
json_escape_str(pb, iter.key, strlen(iter.key));
if (flags & JSON_C_TO_STRING_SPACED)
sprintbuf(pb, "\": ");
else
sprintbuf(pb, "\":");
if(iter.val == NULL)
sprintbuf(pb, "null");
else
iter.val->_to_json_string(iter.val, pb, level+1,flags);
}
if (flags & JSON_C_TO_STRING_PRETTY)
{
if (had_children)
sprintbuf(pb, "\n");
indent(pb,level,flags);
}
if (flags & JSON_C_TO_STRING_SPACED)
return sprintbuf(pb, /*{*/ " }");
else
return sprintbuf(pb, /*{*/ "}");
}
static void json_object_lh_entry_free(struct lh_entry *ent)
{
free(ent->k);
json_object_put((struct json_object*)ent->v);
}
static void json_object_object_delete(struct json_object* jso)
{
lh_table_free(jso->o.c_object);
json_object_generic_delete(jso);
}
struct json_object* json_object_new_object(void)
{
struct json_object* jso = json_object_new(json_type_object);
if (!jso)
{
return NULL;
}
jso->_delete = &json_object_object_delete;
jso->_to_json_string = &json_object_object_to_json_string;
jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES, NULL, &json_object_lh_entry_free);
return jso;
}
struct lh_table* json_object_get_object(struct json_object *jso)
{
if(!jso) return NULL;
switch(jso->o_type) {
case json_type_object:
return jso->o.c_object;
default:
return NULL;
}
}
void json_object_object_add(struct json_object* jso, const char *key,
struct json_object *val)
{
// We lookup the entry and replace the value, rather than just deleting
// and re-adding it, so the existing key remains valid.
json_object *existing_value = NULL;
struct lh_entry *existing_entry;
existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key);
if (!existing_entry)
{
lh_table_insert(jso->o.c_object, strdup(key), val);
return;
}
existing_value = (void *)existing_entry->v;
if (existing_value)
json_object_put(existing_value);
existing_entry->v = val;
}
int json_object_object_length(struct json_object *jso)
{
return lh_table_length(jso->o.c_object);
}
struct json_object* json_object_object_get(struct json_object* jso, const char *key)
{
struct json_object *result = NULL;
json_object_object_get_ex(jso, key, &result);
return result;
}
json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value)
{
if (value != NULL)
*value = NULL;
if (NULL == jso)
return FALSE;
switch(jso->o_type)
{
case json_type_object:
return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value);
default:
if (value != NULL)
*value = NULL;
return FALSE;
}
}
void json_object_object_del(struct json_object* jso, const char *key)
{
lh_table_delete(jso->o.c_object, key);
}
/* json_object_boolean */
static int json_object_boolean_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
if(jso->o.c_boolean) return sprintbuf(pb, "true");
else return sprintbuf(pb, "false");
}
struct json_object* json_object_new_boolean(json_bool b)
{
struct json_object *jso = json_object_new(json_type_boolean);
if(!jso) return NULL;
jso->_to_json_string = &json_object_boolean_to_json_string;
jso->o.c_boolean = b;
return jso;
}
json_bool json_object_get_boolean(struct json_object *jso)
{
if(!jso) return FALSE;
switch(jso->o_type) {
case json_type_boolean:
return jso->o.c_boolean;
case json_type_int:
return (jso->o.c_int64 != 0);
case json_type_double:
return (jso->o.c_double != 0);
case json_type_string:
return (jso->o.c_string.len != 0);
default:
return FALSE;
}
}
/* json_object_int */
static int json_object_int_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
}
struct json_object* json_object_new_int(int32_t i)
{
struct json_object *jso = json_object_new(json_type_int);
if(!jso) return NULL;
jso->_to_json_string = &json_object_int_to_json_string;
jso->o.c_int64 = i;
return jso;
}
int32_t json_object_get_int(struct json_object *jso)
{
int64_t cint64;
enum json_type o_type;
if(!jso) return 0;
o_type = jso->o_type;
cint64 = jso->o.c_int64;
if (o_type == json_type_string)
{
/*
* Parse strings into 64-bit numbers, then use the
* 64-to-32-bit number handling below.
*/
if (json_parse_int64(jso->o.c_string.str, &cint64) != 0)
return 0; /* whoops, it didn't work. */
o_type = json_type_int;
}
switch(o_type) {
case json_type_int:
/* Make sure we return the correct values for out of range numbers. */
if (cint64 <= INT32_MIN)
return INT32_MIN;
else if (cint64 >= INT32_MAX)
return INT32_MAX;
else
return (int32_t)cint64;
case json_type_double:
return (int32_t)jso->o.c_double;
case json_type_boolean:
return jso->o.c_boolean;
default:
return 0;
}
}
struct json_object* json_object_new_int64(int64_t i)
{
struct json_object *jso = json_object_new(json_type_int);
if(!jso) return NULL;
jso->_to_json_string = &json_object_int_to_json_string;
jso->o.c_int64 = i;
return jso;
}
int64_t json_object_get_int64(struct json_object *jso)
{
int64_t cint;
if(!jso) return 0;
switch(jso->o_type) {
case json_type_int:
return jso->o.c_int64;
case json_type_double:
return (int64_t)jso->o.c_double;
case json_type_boolean:
return jso->o.c_boolean;
case json_type_string:
if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint;
default:
return 0;
}
}
/* json_object_double */
static int json_object_double_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
char buf[128], *p, *q;
size_t size;
/* Although JSON RFC does not support
NaN or Infinity as numeric values
ECMA 262 section 9.8.1 defines
how to handle these cases as strings */
if(isnan(jso->o.c_double))
size = _snprintf_s(buf, sizeof(buf), _TRUNCATE, "NaN");
else if(isinf(jso->o.c_double))
if(jso->o.c_double > 0)
size = _snprintf_s(buf, sizeof(buf), _TRUNCATE, "Infinity");
else
size = _snprintf_s(buf, sizeof(buf), _TRUNCATE, "-Infinity");
else
size = _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%.17g", jso->o.c_double);
p = strchr(buf, ',');
if (p) {
*p = '.';
} else {
p = strchr(buf, '.');
}
if (p && (flags & JSON_C_TO_STRING_NOZERO)) {
/* last useful digit, always keep 1 zero */
p++;
for (q=p ; *q ; q++) {
if (*q!='0') p=q;
}
/* drop trailing zeroes */
*(++p) = 0;
size = p-buf;
}
printbuf_memappend(pb, buf, size);
return (int)size;
}
struct json_object* json_object_new_double(double d)
{
struct json_object *jso = json_object_new(json_type_double);
if (!jso)
return NULL;
jso->_to_json_string = &json_object_double_to_json_string;
jso->o.c_double = d;
return jso;
}
struct json_object* json_object_new_double_s(double d, const char *ds)
{
struct json_object *jso = json_object_new_double(d);
if (!jso)
return NULL;
json_object_set_serializer(jso, json_object_userdata_to_json_string, strdup(ds), json_object_free_userdata);
return jso;
}
int json_object_userdata_to_json_string(struct json_object *jso, struct printbuf *pb, int level, int flags)
{
size_t userdata_len = strlen(jso->_userdata);
printbuf_memappend(pb, jso->_userdata, userdata_len);
return (int)userdata_len;
}
void json_object_free_userdata(struct json_object *jso, void *userdata)
{
free(userdata);
}
double json_object_get_double(struct json_object *jso)
{
double cdouble;
char *errPtr = NULL;
if(!jso) return 0.0;
switch(jso->o_type) {
case json_type_double:
return jso->o.c_double;
case json_type_int:
return (double)jso->o.c_int64;
case json_type_boolean:
return jso->o.c_boolean;
case json_type_string:
errno = 0;
cdouble = strtod(jso->o.c_string.str,&errPtr);
/* if conversion stopped at the first character, return 0.0 */
if (errPtr == jso->o.c_string.str)
return 0.0;
/*
* Check that the conversion terminated on something sensible
*
* For example, { "pay" : 123AB } would parse as 123.
*/
if (*errPtr != '\0')
return 0.0;
/*
* If strtod encounters a string which would exceed the
* capacity of a double, it returns +/- HUGE_VAL and sets
* errno to ERANGE. But +/- HUGE_VAL is also a valid result
* from a conversion, so we need to check errno.
*
* Underflow also sets errno to ERANGE, but it returns 0 in
* that case, which is what we will return anyway.
*
* See CERT guideline ERR30-C
*/
if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) &&
(ERANGE == errno))
cdouble = 0.0;
return cdouble;
default:
return 0.0;
}
}
/* json_object_string */
static int json_object_string_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
sprintbuf(pb, "\"");
json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len);
sprintbuf(pb, "\"");
return 0;
}
static void json_object_string_delete(struct json_object* jso)
{
free(jso->o.c_string.str);
json_object_generic_delete(jso);
}
struct json_object* json_object_new_string(const char *s)
{
struct json_object *jso = json_object_new(json_type_string);
if(!jso) return NULL;
jso->_delete = &json_object_string_delete;
jso->_to_json_string = &json_object_string_to_json_string;
jso->o.c_string.str = strdup(s);
jso->o.c_string.len = (int)strlen(s);
return jso;
}
struct json_object* json_object_new_string_len(const char *s, size_t len)
{
struct json_object *jso = json_object_new(json_type_string);
if(!jso) return NULL;
jso->_delete = &json_object_string_delete;
jso->_to_json_string = &json_object_string_to_json_string;
jso->o.c_string.str = (char*)malloc(len + 1);
memcpy(jso->o.c_string.str, (void *)s, len);
jso->o.c_string.str[len] = '\0';
jso->o.c_string.len = len;
return jso;
}
char* json_object_get_string(struct json_object *jso)
{
if (!jso)
return NULL;
switch (jso->o_type)
{
case json_type_string:
return jso->o.c_string.str;
default:
return json_object_to_json_string(jso);
}
}
int json_object_get_string_len(struct json_object *jso) {
if(!jso) return 0;
switch(jso->o_type) {
case json_type_string:
return (int)jso->o.c_string.len;
default:
return 0;
}
}
/* json_object_array */
static int json_object_array_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
int had_children = 0;
int ii;
sprintbuf(pb, "[");
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
for(ii=0; ii < json_object_array_length(jso); ii++)
{
struct json_object *val;
if (had_children)
{
sprintbuf(pb, ",");
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
}
had_children = 1;
if (flags & JSON_C_TO_STRING_SPACED)
sprintbuf(pb, " ");
indent(pb, level + 1, flags);
val = json_object_array_get_idx(jso, ii);
if(val == NULL)
sprintbuf(pb, "null");
else
val->_to_json_string(val, pb, level+1, flags);
}
if (flags & JSON_C_TO_STRING_PRETTY)
{
if (had_children)
sprintbuf(pb, "\n");
indent(pb,level,flags);
}
if (flags & JSON_C_TO_STRING_SPACED)
return sprintbuf(pb, " ]");
else
return sprintbuf(pb, "]");
}
static void json_object_array_entry_free(void *data)
{
json_object_put((struct json_object*)data);
}
static void json_object_array_delete(struct json_object* jso)
{
array_list_free(jso->o.c_array);
json_object_generic_delete(jso);
}
struct json_object* json_object_new_array(void)
{
struct json_object *jso = json_object_new(json_type_array);
if(!jso) return NULL;
jso->_delete = &json_object_array_delete;
jso->_to_json_string = &json_object_array_to_json_string;
jso->o.c_array = array_list_new(&json_object_array_entry_free);
return jso;
}
struct array_list* json_object_get_array(struct json_object *jso)
{
if(!jso) return NULL;
switch(jso->o_type) {
case json_type_array:
return jso->o.c_array;
default:
return NULL;
}
}
void json_object_array_sort(struct json_object *jso, int(__cdecl* sort_fn)(const void *, const void *))
{
array_list_sort(jso->o.c_array, sort_fn);
}
int json_object_array_length(struct json_object *jso)
{
return array_list_length(jso->o.c_array);
}
int json_object_array_add(struct json_object *jso,struct json_object *val)
{
return array_list_add(jso->o.c_array, val);
}
int json_object_array_put_idx(struct json_object *jso, int idx,
struct json_object *val)
{
return array_list_put_idx(jso->o.c_array, idx, val);
}
struct json_object* json_object_array_get_idx(struct json_object *jso,
int idx)
{
return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
}

View File

@ -0,0 +1,611 @@
/*
* $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_object_h_
#define _json_object_h_
#ifdef __GNUC__
#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func
#else
#define THIS_FUNCTION_IS_DEPRECATED(func) func
#endif
#include "json_inttypes.h"
#ifdef __cplusplus
extern "C" {
#endif
#define JSON_OBJECT_DEF_HASH_ENTRIES 16
/**
* A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes the output
* to have no extra whitespace or formatting applied.
*/
#define JSON_C_TO_STRING_PLAIN 0
/**
* A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes the output to have
* minimal whitespace inserted to make things slightly more readable.
*/
#define JSON_C_TO_STRING_SPACED (1<<0)
/**
* A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes
* the output to be formatted.
*
* See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/
* for an example of the format.
*/
#define JSON_C_TO_STRING_PRETTY (1<<1)
/**
* A flag to drop trailing zero for float values
*/
#define JSON_C_TO_STRING_NOZERO (1<<2)
#undef FALSE
#define FALSE ((json_bool)0)
#undef TRUE
#define TRUE ((json_bool)1)
extern const char *json_number_chars;
extern const char *json_hex_chars;
/* CAW: added for ANSI C iteration correctness */
struct json_object_iter
{
char *key;
struct json_object *val;
struct lh_entry *entry;
};
/* forward structure definitions */
typedef int json_bool;
typedef struct printbuf printbuf;
typedef struct lh_table lh_table;
typedef struct array_list array_list;
typedef struct json_object json_object, *json_object_ptr;
typedef struct json_object_iter json_object_iter;
typedef struct json_tokener json_tokener;
/**
* Type of custom user delete functions. See json_object_set_serializer.
*/
typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata);
/**
* Type of a custom serialization function. See json_object_set_serializer.
*/
typedef int (json_object_to_json_string_fn)(struct json_object *jso,
struct printbuf *pb,
int level,
int flags);
/* supported object types */
typedef enum json_type {
/* If you change this, be sure to update json_type_to_name() too */
json_type_null,
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string,
} json_type;
/* reference counting functions */
/**
* Increment the reference count of json_object, thereby grabbing shared
* ownership of obj.
*
* @param obj the json_object instance
*/
extern struct json_object* json_object_get(struct json_object *obj);
/**
* Decrement the reference count of json_object and free if it reaches zero.
* You must have ownership of obj prior to doing this or you will cause an
* imbalance in the reference count.
*
* @param obj the json_object instance
* @returns 1 if the object was freed.
*/
int json_object_put(struct json_object *obj);
/**
* Check if the json_object is of a given type
* @param obj the json_object instance
* @param type one of:
json_type_null (i.e. obj == NULL),
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string,
*/
extern int json_object_is_type(struct json_object *obj, enum json_type type);
/**
* Get the type of the json_object. See also json_type_to_name() to turn this
* into a string suitable, for instance, for logging.
*
* @param obj the json_object instance
* @returns type being one of:
json_type_null (i.e. obj == NULL),
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string,
*/
extern enum json_type json_object_get_type(struct json_object *obj);
/** Stringify object to json format.
* Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED)
* @param obj the json_object instance
* @returns a string in JSON format
*/
extern char* json_object_to_json_string(struct json_object *obj);
/** Stringify object to json format
* @param obj the json_object instance
* @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
* @returns a string in JSON format
*/
extern char* json_object_to_json_string_ext(struct json_object *obj, int flags);
/**
* Set a custom serialization function to be used when this particular object
* is converted to a string by json_object_to_json_string.
*
* If a custom serializer is already set on this object, any existing
* user_delete function is called before the new one is set.
*
* If to_string_func is NULL, the other parameters are ignored
* and the default behaviour is reset.
*
* The userdata parameter is optional and may be passed as NULL. If provided,
* it is passed to to_string_func as-is. This parameter may be NULL even
* if user_delete is non-NULL.
*
* The user_delete parameter is optional and may be passed as NULL, even if
* the userdata parameter is non-NULL. It will be called just before the
* json_object is deleted, after it's reference count goes to zero
* (see json_object_put()).
* If this is not provided, it is up to the caller to free the userdata at
* an appropriate time. (i.e. after the json_object is deleted)
*
* @param jso the object to customize
* @param to_string_func the custom serialization function
* @param userdata an optional opaque cookie
* @param user_delete an optional function from freeing userdata
*/
extern void json_object_set_serializer(json_object *jso,
json_object_to_json_string_fn to_string_func,
void *userdata,
json_object_delete_fn *user_delete);
/**
* Simply call free on the userdata pointer.
* Can be used with json_object_set_serializer().
*
* @param jso unused
* @param userdata the pointer that is passed to free().
*/
json_object_delete_fn json_object_free_userdata;
/**
* Copy the jso->_userdata string over to pb as-is.
* Can be used with json_object_set_serializer().
*
* @param jso The object whose _userdata is used.
* @param pb The destination buffer.
* @param level Ignored.
* @param flags Ignored.
*/
json_object_to_json_string_fn json_object_userdata_to_json_string;
/* object type methods */
/** Create a new empty object with a reference count of 1. The caller of
* this object initially has sole ownership. Remember, when using
* json_object_object_add or json_object_array_put_idx, ownership will
* transfer to the object/array. Call json_object_get if you want to maintain
* shared ownership or also add this object as a child of multiple objects or
* arrays. Any ownerships you acquired but did not transfer must be released
* through json_object_put.
*
* @returns a json_object of type json_type_object
*/
extern struct json_object* json_object_new_object(void);
/** Get the hashtable of a json_object of type json_type_object
* @param obj the json_object instance
* @returns a linkhash
*/
extern struct lh_table* json_object_get_object(struct json_object *obj);
/** Get the size of an object in terms of the number of fields it has.
* @param obj the json_object whose length to return
*/
extern int json_object_object_length(struct json_object* obj);
/** Add an object field to a json_object of type json_type_object
*
* The reference count will *not* be incremented. This is to make adding
* fields to objects in code more compact. If you want to retain a reference
* to an added object, independent of the lifetime of obj, you must wrap the
* passed object with json_object_get.
*
* Upon calling this, the ownership of val transfers to obj. Thus you must
* make sure that you do in fact have ownership over this object. For instance,
* json_object_new_object will give you ownership until you transfer it,
* whereas json_object_object_get does not.
*
* @param obj the json_object instance
* @param key the object field name (a private copy will be duplicated)
* @param val a json_object or NULL member to associate with the given field
*/
extern void json_object_object_add(struct json_object* obj, const char *key,
struct json_object *val);
/** Get the json_object associate with a given object field
*
* *No* reference counts will be changed. There is no need to manually adjust
* reference counts through the json_object_put/json_object_get methods unless
* you need to have the child (value) reference maintain a different lifetime
* than the owning parent (obj). Ownership of the returned value is retained
* by obj (do not do json_object_put unless you have done a json_object_get).
* If you delete the value from obj (json_object_object_del) and wish to access
* the returned reference afterwards, make sure you have first gotten shared
* ownership through json_object_get (& don't forget to do a json_object_put
* or transfer ownership to prevent a memory leak).
*
* @param obj the json_object instance
* @param key the object field name
* @returns the json_object associated with the given field name
* @deprecated Please use json_object_object_get_ex
*/
THIS_FUNCTION_IS_DEPRECATED(extern struct json_object* json_object_object_get(struct json_object* obj,
const char *key));
/** Get the json_object associated with a given object field.
*
* This returns true if the key is found, false in all other cases (including
* if obj isn't a json_type_object).
*
* *No* reference counts will be changed. There is no need to manually adjust
* reference counts through the json_object_put/json_object_get methods unless
* you need to have the child (value) reference maintain a different lifetime
* than the owning parent (obj). Ownership of value is retained by obj.
*
* @param obj the json_object instance
* @param key the object field name
* @param value a pointer where to store a reference to the json_object
* associated with the given field name.
*
* It is safe to pass a NULL value.
* @returns whether or not the key exists
*/
extern json_bool json_object_object_get_ex(struct json_object* obj,
const char *key,
struct json_object **value);
/** Delete the given json_object field
*
* The reference count will be decremented for the deleted object. If there
* are no more owners of the value represented by this key, then the value is
* freed. Otherwise, the reference to the value will remain in memory.
*
* @param obj the json_object instance
* @param key the object field name
*/
extern void json_object_object_del(struct json_object* obj, const char *key);
/**
* Iterate through all keys and values of an object.
*
* Adding keys to the object while iterating is NOT allowed.
*
* Deleting an existing key, or replacing an existing key with a
* new value IS allowed.
*
* @param obj the json_object instance
* @param key the local name for the char* key variable defined in the body
* @param val the local name for the json_object* object variable defined in
* the body
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L
# define json_object_object_foreach(obj,key,val) \
char *key; \
struct json_object *val __attribute__((__unused__)); \
for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \
({ if(entry ## key) { \
key = (char*)entry ## key->k; \
val = (struct json_object*)entry ## key->v; \
entry_next ## key = entry ## key->next; \
} ; entry ## key; }); \
entry ## key = entry_next ## key )
#else /* ANSI C or MSC */
# define json_object_object_foreach(obj,key,val) \
char *key;\
struct json_object *val; \
struct lh_entry *entry ## key; \
struct lh_entry *entry_next ## key = NULL; \
for(entry ## key = json_object_get_object(obj)->head; \
(entry ## key ? ( \
key = (char*)entry ## key->k, \
val = (struct json_object*)entry ## key->v, \
entry_next ## key = entry ## key->next, \
entry ## key) : 0); \
entry ## key = entry_next ## key)
#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */
/** Iterate through all keys and values of an object (ANSI C Safe)
* @param obj the json_object instance
* @param iter the object iterator
*/
#define json_object_object_foreachC(obj,iter) \
for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next)
/* Array type methods */
/** Create a new empty json_object of type json_type_array
* @returns a json_object of type json_type_array
*/
extern struct json_object* json_object_new_array(void);
/** Get the arraylist of a json_object of type json_type_array
* @param obj the json_object instance
* @returns an arraylist
*/
extern struct array_list* json_object_get_array(struct json_object *obj);
/** Get the length of a json_object of type json_type_array
* @param obj the json_object instance
* @returns an int
*/
extern int json_object_array_length(struct json_object *obj);
/** Sorts the elements of jso of type json_type_array
*
* Pointers to the json_object pointers will be passed as the two arguments
* to @sort_fn
*
* @param obj the json_object instance
* @param sort_fn a sorting function
*/
extern void json_object_array_sort(struct json_object *jso, int(__cdecl* sort_fn)(const void *, const void *));
/** Add an element to the end of a json_object of type json_type_array
*
* The reference count will *not* be incremented. This is to make adding
* fields to objects in code more compact. If you want to retain a reference
* to an added object you must wrap the passed object with json_object_get
*
* @param obj the json_object instance
* @param val the json_object to be added
*/
extern int json_object_array_add(struct json_object *obj,
struct json_object *val);
/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
*
* The reference count will *not* be incremented. This is to make adding
* fields to objects in code more compact. If you want to retain a reference
* to an added object you must wrap the passed object with json_object_get
*
* The reference count of a replaced object will be decremented.
*
* The array size will be automatically be expanded to the size of the
* index if the index is larger than the current size.
*
* @param obj the json_object instance
* @param idx the index to insert the element at
* @param val the json_object to be added
*/
extern int json_object_array_put_idx(struct json_object *obj, int idx,
struct json_object *val);
/** Get the element at specificed index of the array (a json_object of type json_type_array)
* @param obj the json_object instance
* @param idx the index to get the element at
* @returns the json_object at the specified index (or NULL)
*/
extern struct json_object* json_object_array_get_idx(struct json_object *obj,
int idx);
/* json_bool type methods */
/** Create a new empty json_object of type json_type_boolean
* @param b a json_bool TRUE or FALSE (0 or 1)
* @returns a json_object of type json_type_boolean
*/
extern struct json_object* json_object_new_boolean(json_bool b);
/** Get the json_bool value of a json_object
*
* The type is coerced to a json_bool if the passed object is not a json_bool.
* integer and double objects will return FALSE if there value is zero
* or TRUE otherwise. If the passed object is a string it will return
* TRUE if it has a non zero length. If any other object type is passed
* TRUE will be returned if the object is not NULL.
*
* @param obj the json_object instance
* @returns a json_bool
*/
extern json_bool json_object_get_boolean(struct json_object *obj);
/* int type methods */
/** Create a new empty json_object of type json_type_int
* Note that values are stored as 64-bit values internally.
* To ensure the full range is maintained, use json_object_new_int64 instead.
* @param i the integer
* @returns a json_object of type json_type_int
*/
extern struct json_object* json_object_new_int(int32_t i);
/** Create a new empty json_object of type json_type_int
* @param i the integer
* @returns a json_object of type json_type_int
*/
extern struct json_object* json_object_new_int64(int64_t i);
/** Get the int value of a json_object
*
* The type is coerced to a int if the passed object is not a int.
* double objects will return their integer conversion. Strings will be
* parsed as an integer. If no conversion exists then 0 is returned
* and errno is set to EINVAL. null is equivalent to 0 (no error values set)
*
* Note that integers are stored internally as 64-bit values.
* If the value of too big or too small to fit into 32-bit, INT32_MAX or
* INT32_MIN are returned, respectively.
*
* @param obj the json_object instance
* @returns an int
*/
extern int32_t json_object_get_int(struct json_object *obj);
/** Get the int value of a json_object
*
* The type is coerced to a int64 if the passed object is not a int64.
* double objects will return their int64 conversion. Strings will be
* parsed as an int64. If no conversion exists then 0 is returned.
*
* NOTE: Set errno to 0 directly before a call to this function to determine
* whether or not conversion was successful (it does not clear the value for
* you).
*
* @param obj the json_object instance
* @returns an int64
*/
extern int64_t json_object_get_int64(struct json_object *obj);
/* double type methods */
/** Create a new empty json_object of type json_type_double
* @param d the double
* @returns a json_object of type json_type_double
*/
extern struct json_object* json_object_new_double(double d);
/**
* Create a new json_object of type json_type_double, using
* the exact serialized representation of the value.
*
* This allows for numbers that would otherwise get displayed
* inefficiently (e.g. 12.3 => "12.300000000000001") to be
* serialized with the more convenient form.
*
* Note: this is used by json_tokener_parse_ex() to allow for
* an exact re-serialization of a parsed object.
*
* An equivalent sequence of calls is:
* @code
* jso = json_object_new_double(d);
* json_object_set_serializer(d, json_object_userdata_to_json_string,
* strdup(ds), json_object_free_userdata)
* @endcode
*
* @param d the numeric value of the double.
* @param ds the string representation of the double. This will be copied.
*/
extern struct json_object* json_object_new_double_s(double d, const char *ds);
/** Get the double floating point value of a json_object
*
* The type is coerced to a double if the passed object is not a double.
* integer objects will return their double conversion. Strings will be
* parsed as a double. If no conversion exists then 0.0 is returned and
* errno is set to EINVAL. null is equivalent to 0 (no error values set)
*
* If the value is too big to fit in a double, then the value is set to
* the closest infinity with errno set to ERANGE. If strings cannot be
* converted to their double value, then EINVAL is set & NaN is returned.
*
* Arrays of length 0 are interpreted as 0 (with no error flags set).
* Arrays of length 1 are effectively cast to the equivalent object and
* converted using the above rules. All other arrays set the error to
* EINVAL & return NaN.
*
* NOTE: Set errno to 0 directly before a call to this function to
* determine whether or not conversion was successful (it does not clear
* the value for you).
*
* @param obj the json_object instance
* @returns a double floating point number
*/
extern double json_object_get_double(struct json_object *obj);
/* string type methods */
/** Create a new empty json_object of type json_type_string
*
* A copy of the string is made and the memory is managed by the json_object
*
* @param s the string
* @returns a json_object of type json_type_string
*/
extern struct json_object* json_object_new_string(const char *s);
extern struct json_object* json_object_new_string_len(const char *s, size_t len);
/** Get the string value of a json_object
*
* If the passed object is not of type json_type_string then the JSON
* representation of the object is returned.
*
* The returned string memory is managed by the json_object and will
* be freed when the reference count of the json_object drops to zero.
*
* @param obj the json_object instance
* @returns a string
*/
extern char* json_object_get_string(struct json_object *obj);
/** Get the string length of a json_object
*
* If the passed object is not of type json_type_string then zero
* will be returned.
*
* @param obj the json_object instance
* @returns int
*/
extern int json_object_get_string_len(struct json_object *obj);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,168 @@
/**
*******************************************************************************
* @file json_object_iterator.c
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief json-c forces clients to use its private data
* structures for JSON Object iteration. This API
* implementation corrects that by abstracting the
* private json-c details.
*
*******************************************************************************
*/
#include <stddef.h>
#include "json.h"
#include "json_object_private.h"
#include "json_object_iterator.h"
/**
* How It Works
*
* For each JSON Object, json-c maintains a linked list of zero
* or more lh_entry (link-hash entry) structures inside the
* Object's link-hash table (lh_table).
*
* Each lh_entry structure on the JSON Object's linked list
* represents a single name/value pair. The "next" field of the
* last lh_entry in the list is set to NULL, which terminates
* the list.
*
* We represent a valid iterator that refers to an actual
* name/value pair via a pointer to the pair's lh_entry
* structure set as the iterator's opaque_ field.
*
* We follow json-c's current pair list representation by
* representing a valid "end" iterator (one that refers past the
* last pair) with a NULL value in the iterator's opaque_ field.
*
* A JSON Object without any pairs in it will have the "head"
* field of its lh_table structure set to NULL. For such an
* object, json_object_iter_begin will return an iterator with
* the opaque_ field set to NULL, which is equivalent to the
* "end" iterator.
*
* When iterating, we simply update the iterator's opaque_ field
* to point to the next lh_entry structure in the linked list.
* opaque_ will become NULL once we iterate past the last pair
* in the list, which makes the iterator equivalent to the "end"
* iterator.
*/
/// Our current representation of the "end" iterator;
///
/// @note May not always be NULL
static const void* kObjectEndIterValue = NULL;
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj)
{
struct json_object_iterator iter;
struct lh_table* pTable;
/// @note json_object_get_object will return NULL if passed NULL
/// or a non-json_type_object instance
pTable = json_object_get_object(obj);
JASSERT(NULL != pTable);
/// @note For a pair-less Object, head is NULL, which matches our
/// definition of the "end" iterator
iter.opaque_ = pTable->head;
return iter;
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj)
{
struct json_object_iterator iter;
JASSERT(NULL != obj);
JASSERT(json_object_is_type(obj, json_type_object));
iter.opaque_ = kObjectEndIterValue;
return iter;
}
/**
* ****************************************************************************
*/
void
json_object_iter_next(struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next;
}
/**
* ****************************************************************************
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (const char*)(((struct lh_entry *)iter->opaque_)->k);
}
/**
* ****************************************************************************
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v);
}
/**
* ****************************************************************************
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2)
{
JASSERT(NULL != iter1);
JASSERT(NULL != iter2);
return (iter1->opaque_ == iter2->opaque_);
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_init_default(void)
{
struct json_object_iterator iter;
/**
* @note Make this a negative, invalid value, such that
* accidental access to it would likely be trapped by the
* hardware as an invalid address.
*/
iter.opaque_ = NULL;
return iter;
}

View File

@ -0,0 +1,239 @@
/**
*******************************************************************************
* @file json_object_iterator.h
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief json-c forces clients to use its private data
* structures for JSON Object iteration. This API
* corrects that by abstracting the private json-c
* details.
*
* API attributes: <br>
* * Thread-safe: NO<br>
* * Reentrant: NO
*
*******************************************************************************
*/
#ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Forward declaration for the opaque iterator information.
*/
struct json_object_iter_info_;
/**
* The opaque iterator that references a name/value pair within
* a JSON Object instance or the "end" iterator value.
*/
struct json_object_iterator {
const void* opaque_;
};
/**
* forward declaration of json-c's JSON value instance structure
*/
struct json_object;
/**
* Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a
* default state (e.g., initialization list in a class'
* constructor).
*
* @code
* struct json_object_iterator iter = json_object_iter_init_default();
* MyClass() : iter_(json_object_iter_init_default())
* @endcode
*
* @note The initialized value doesn't reference any specific
* pair, is considered an invalid iterator, and MUST NOT
* be passed to any json-c API that expects a valid
* iterator.
*
* @note User and internal code MUST NOT make any assumptions
* about and dependencies on the value of the "default"
* iterator value.
*
* @return json_object_iterator
*/
struct json_object_iterator
json_object_iter_init_default(void);
/** Retrieves an iterator to the first pair of the JSON Object.
*
* @warning Any modification of the underlying pair invalidates all
* iterators to that pair.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator If the JSON Object has at
* least one pair, on return, the iterator refers
* to the first pair. If the JSON Object doesn't
* have any pairs, the returned iterator is
* equivalent to the "end" iterator for the same
* JSON Object instance.
*
* @code
* struct json_object_iterator it;
* struct json_object_iterator itEnd;
* struct json_object* obj;
*
* obj = json_tokener_parse("{'first':'george', 'age':100}");
* it = json_object_iter_begin(obj);
* itEnd = json_object_iter_end(obj);
*
* while (!json_object_iter_equal(&it, &itEnd)) {
* printf("%s\n",
* json_object_iter_peek_name(&it));
* json_object_iter_next(&it);
* }
*
* @endcode
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj);
/** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance.
*
* @warning Do NOT write code that assumes that the "end"
* iterator value is NULL, even if it is so in a
* particular instance of the implementation.
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The "end" iterator and the
* equality test method, on the other hand, permit us to
* cleanly abstract pretty much any reasonable underlying
* representation without burdening the iterator
* structure with unnecessary data.
*
* @note For performance reasons, memorize the "end" iterator prior
* to any loop.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator On return, the iterator refers
* to the "end" of the Object instance's pairs
* (i.e., NOT the last pair, but "beyond the last
* pair" value)
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj);
/** Returns an iterator to the next pair, if any
*
* @warning Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param iter [IN/OUT] Pointer to iterator that references a
* name/value pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or "end"
* iterator is passed. Upon return will contain the
* reference to the next pair if there is one; if there
* are no more pairs, will contain the "end" iterator
* value, which may be compared against the return value
* of json_object_iter_end() for the same JSON Object
* instance.
*/
void
json_object_iter_next(struct json_object_iterator* iter);
/** Returns a const pointer to the name of the pair referenced
* by the given iterator.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if an invalid or
* "end" iterator is passed.
*
* @return const char* Pointer to the name of the referenced
* name/value pair. The name memory belongs to the
* name/value pair, will be freed when the pair is
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);
/** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering
* the instance's reference count.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if invalid or
* "end" iterator is passed.
*
* @return struct json_object* Pointer to the json-c value
* instance of the referenced name/value pair; the
* value's reference count is not changed by this
* function: if you plan to hold on to this json-c node,
* take a look at json_object_get() and
* json_object_put(). IMPORTANT: json-c API represents
* the JSON Null value as a NULL json_object instance
* pointer.
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);
/** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the
* corresponding "end" iterator (that was derived from the same
* JSON Object instance).
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The equality test method, on
* the other hand, permits us to cleanly abstract pretty
* much any reasonable underlying representation.
*
* @param iter1 Pointer to first valid, non-NULL iterator
* @param iter2 POinter to second valid, non-NULL iterator
*
* @warning if a NULL iterator pointer or an uninitialized
* or invalid iterator, or iterators derived from
* different JSON Object instances are passed, bad things
* will happen!
*
* @return json_bool non-zero if iterators are equal (i.e., both
* reference the same name/value pair or are both at
* "end"); zero if they are not equal.
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);
#ifdef __cplusplus
}
#endif
#endif /* JSON_OBJECT_ITERATOR_H */

View File

@ -0,0 +1,47 @@
/*
* $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_object_private_h_
#define _json_object_private_h_
#ifdef __cplusplus
extern "C" {
#endif
typedef void (json_object_private_delete_fn)(struct json_object *o);
struct json_object
{
enum json_type o_type;
json_object_private_delete_fn *_delete;
json_object_to_json_string_fn *_to_json_string;
int _ref_count;
struct printbuf *_pb;
union data {
json_bool c_boolean;
double c_double;
int64_t c_int64;
struct lh_table *c_object;
struct array_list *c_array;
struct {
char *str;
size_t len;
} c_string;
} o;
json_object_delete_fn *_user_delete;
void *_userdata;
};
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,888 @@
/*
* $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include "bits.h"
#include "debug.h"
#include "printbuf.h"
#include "arraylist.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_util.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif /* HAVE_LOCALE_H */
#if !HAVE_STRDUP && defined(_MSC_VER)
/* MSC has the version as _strdup */
# define strdup _strdup
#elif !HAVE_STRDUP
# error You do not have strdup on your system.
#endif /* HAVE_STRDUP */
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
/* MSC has the version as _strnicmp */
# define strncasecmp _strnicmp
#elif !HAVE_STRNCASECMP
# error You do not have strncasecmp on your system.
#endif /* HAVE_STRNCASECMP */
/* Use C99 NAN by default; if not available, nan("") should work too. */
#ifndef NAN
#define NAN nan("")
#endif /* !NAN */
static const char json_null_str[] = "null";
static const int json_null_str_len = sizeof(json_null_str) - 1;
static const char json_inf_str[] = "Infinity";
static const int json_inf_str_len = sizeof(json_inf_str) - 1;
static const char json_nan_str[] = "NaN";
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
static const char json_true_str[] = "true";
static const int json_true_str_len = sizeof(json_true_str) - 1;
static const char json_false_str[] = "false";
static const int json_false_str_len = sizeof(json_false_str) - 1;
static const char* json_tokener_errors[] = {
"success",
"continue",
"nesting too deep",
"unexpected end of data",
"unexpected character",
"null expected",
"boolean expected",
"number expected",
"array value separator ',' expected",
"quoted object property name expected",
"object property name separator ':' expected",
"object value separator ',' expected",
"invalid string sequence",
"expected comment",
"buffer size overflow"
};
const char *json_tokener_error_desc(enum json_tokener_error jerr)
{
int jerr_int = (int)jerr;
if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
return json_tokener_errors[jerr];
}
enum json_tokener_error json_tokener_get_error(json_tokener *tok)
{
return tok->err;
}
/* Stuff for decoding unicode sequences */
#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
struct json_tokener* json_tokener_new_ex(int depth)
{
struct json_tokener *tok;
tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
if (!tok) return NULL;
tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
if (!tok->stack) {
free(tok);
return NULL;
}
tok->pb = printbuf_new();
tok->max_depth = depth;
json_tokener_reset(tok);
return tok;
}
struct json_tokener* json_tokener_new(void)
{
return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
}
void json_tokener_free(struct json_tokener *tok)
{
json_tokener_reset(tok);
if (tok->pb) printbuf_free(tok->pb);
if (tok->stack) free(tok->stack);
free(tok);
}
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
{
tok->stack[depth].state = json_tokener_state_eatws;
tok->stack[depth].saved_state = json_tokener_state_start;
json_object_put(tok->stack[depth].current);
tok->stack[depth].current = NULL;
free(tok->stack[depth].obj_field_name);
tok->stack[depth].obj_field_name = NULL;
}
void json_tokener_reset(struct json_tokener *tok)
{
int i;
if (!tok)
return;
for(i = tok->depth; i >= 0; i--)
json_tokener_reset_level(tok, i);
tok->depth = 0;
tok->err = json_tokener_success;
}
struct json_object* json_tokener_parse(const char *str)
{
enum json_tokener_error jerr_ignored;
struct json_object* obj;
obj = json_tokener_parse_verbose(str, &jerr_ignored);
return obj;
}
struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
{
struct json_tokener* tok;
struct json_object* obj;
tok = json_tokener_new();
if (!tok)
return NULL;
obj = json_tokener_parse_ex(tok, str, -1);
*error = tok->err;
if(tok->err != json_tokener_success) {
if (obj != NULL)
json_object_put(obj);
obj = NULL;
}
json_tokener_free(tok);
return obj;
}
#define state tok->stack[tok->depth].state
#define saved_state tok->stack[tok->depth].saved_state
#define current tok->stack[tok->depth].current
#define obj_field_name tok->stack[tok->depth].obj_field_name
/* Optimization:
* json_tokener_parse_ex() consumed a lot of CPU in its main loop,
* iterating character-by character. A large performance boost is
* achieved by using tighter loops to locally handle units such as
* comments and strings. Loops that handle an entire token within
* their scope also gather entire strings and pass them to
* printbuf_memappend() in a single call, rather than calling
* printbuf_memappend() one char at a time.
*
* PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
* common to both the main loop and the tighter loops.
*/
/* PEEK_CHAR(dest, tok) macro:
* Peeks at the current char and stores it in dest.
* Returns 1 on success, sets tok->err and returns 0 if no more chars.
* Implicit inputs: str, len vars
*/
#define PEEK_CHAR(dest, tok) \
(((tok)->char_offset == len) ? \
(((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
(((tok)->err = json_tokener_success), 0) \
: \
(((tok)->err = json_tokener_continue), 0) \
) : \
(((dest) = *str), 1) \
)
/* ADVANCE_CHAR() macro:
* Incrementes str & tok->char_offset.
* For convenience of existing conditionals, returns the old value of c (0 on eof)
* Implicit inputs: c var
*/
#define ADVANCE_CHAR(str, tok) \
( ++(str), ((tok)->char_offset)++, c)
/* End optimization macro defs */
struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len)
{
struct json_object *obj = NULL;
char c = '\1';
#ifdef HAVE_SETLOCALE
char *oldlocale=NULL, *tmplocale;
tmplocale = setlocale(LC_NUMERIC, NULL);
if (tmplocale) oldlocale = strdup(tmplocale);
setlocale(LC_NUMERIC, "C");
#endif
tok->char_offset = 0;
tok->err = json_tokener_success;
/* this interface is presently not 64-bit clean due to the int len argument
and the internal printbuf interface that takes 32-bit int len arguments
so the function limits the maximum string size to INT32_MAX (2GB).
If the function is called with len == -1 then strlen is called to check
the string length is less than INT32_MAX (2GB) */
if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
tok->err = json_tokener_error_size;
return NULL;
}
while (PEEK_CHAR(c, tok)) {
redo_char:
switch(state) {
case json_tokener_state_eatws:
/* Advance until we change state */
while (isspace((int)c)) {
if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
goto out;
}
if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
printbuf_reset(tok->pb);
printbuf_memappend_fast(tok->pb, &c, 1);
state = json_tokener_state_comment_start;
} else {
state = saved_state;
goto redo_char;
}
break;
case json_tokener_state_start:
switch(c) {
case '{':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_object_field_start;
current = json_object_new_object();
break;
case '[':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_array;
current = json_object_new_array();
break;
case 'I':
case 'i':
state = json_tokener_state_inf;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case 'N':
case 'n':
state = json_tokener_state_null; // or NaN
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case '\'':
if (tok->flags & JSON_TOKENER_STRICT) {
/* in STRICT mode only double-quote are allowed */
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
case '"':
state = json_tokener_state_string;
printbuf_reset(tok->pb);
tok->quote_char = c;
break;
case 'T':
case 't':
case 'F':
case 'f':
state = json_tokener_state_boolean;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
#if defined(__GNUC__)
case '0' ... '9':
#else
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
#endif
case '-':
state = json_tokener_state_number;
printbuf_reset(tok->pb);
tok->is_double = 0;
goto redo_char;
default:
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
break;
case json_tokener_state_finish:
if(tok->depth == 0) goto out;
obj = json_object_get(current);
json_tokener_reset_level(tok, tok->depth);
tok->depth--;
goto redo_char;
case json_tokener_state_inf: /* aka starts with 'i' */
{
int size;
int size_inf;
int is_negative = 0;
printbuf_memappend_fast(tok->pb, &c, 1);
size = json_min(tok->st_pos+1, json_null_str_len);
size_inf = json_min(tok->st_pos+1, json_inf_str_len);
char *infbuf = tok->pb->buf;
if (*infbuf == '-')
{
infbuf++;
is_negative = 1;
}
if ((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_inf_str, infbuf, size_inf) == 0) ||
(strncmp(json_inf_str, infbuf, size_inf) == 0)
)
{
if (tok->st_pos == json_inf_str_len)
{
current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_null: /* aka starts with 'n' */
{
int size;
int size_nan;
printbuf_memappend_fast(tok->pb, &c, 1);
size = json_min(tok->st_pos+1, json_null_str_len);
size_nan = json_min(tok->st_pos+1, json_nan_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_null_str, tok->pb->buf, size) == 0)
|| (strncmp(json_null_str, tok->pb->buf, size) == 0)
) {
if (tok->st_pos == json_null_str_len) {
current = NULL;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
}
else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
(strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
)
{
if (tok->st_pos == json_nan_str_len)
{
current = json_object_new_double(NAN);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_null;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_comment_start:
if(c == '*') {
state = json_tokener_state_comment;
} else if(c == '/') {
state = json_tokener_state_comment_eol;
} else {
tok->err = json_tokener_error_parse_comment;
goto out;
}
printbuf_memappend_fast(tok->pb, &c, 1);
break;
case json_tokener_state_comment:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '*') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
state = json_tokener_state_comment_end;
}
break;
case json_tokener_state_comment_eol:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '\n') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
}
break;
case json_tokener_state_comment_end:
printbuf_memappend_fast(tok->pb, &c, 1);
if(c == '/') {
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
} else {
state = json_tokener_state_comment;
}
break;
case json_tokener_state_string:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_string;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_string_escape:
switch(c) {
case '"':
case '\\':
case '/':
printbuf_memappend_fast(tok->pb, &c, 1);
state = saved_state;
break;
case 'b':
case 'n':
case 'r':
case 't':
case 'f':
if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
state = saved_state;
break;
case 'u':
tok->ucs_char = 0;
tok->st_pos = 0;
state = json_tokener_state_escape_unicode;
break;
default:
tok->err = json_tokener_error_parse_string;
goto out;
}
break;
case json_tokener_state_escape_unicode:
{
unsigned int got_hi_surrogate = 0;
/* Handle a 4-byte sequence, or two sequences if a surrogate pair */
while(1) {
if(strchr(json_hex_chars, c)) {
tok->ucs_char += ((unsigned int)hexdigit(c) << ((3-tok->st_pos++)*4));
if(tok->st_pos == 4) {
unsigned char unescaped_utf[4];
if (got_hi_surrogate) {
if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Recalculate the ucs_char, then fall thru to process normally */
tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
} else {
/* Hi surrogate was not followed by a low surrogate */
/* Replace the hi and process the rest normally */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
got_hi_surrogate = 0;
}
if (tok->ucs_char < 0x80) {
unescaped_utf[0] = tok->ucs_char;
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
} else if (tok->ucs_char < 0x800) {
unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
} else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
/* Got a high surrogate. Remember it and look for the
* the beginning of another sequence, which should be the
* low surrogate.
*/
got_hi_surrogate = tok->ucs_char;
/* Not at end, and the next two chars should be "\u" */
if ((tok->char_offset+1 != len) &&
(tok->char_offset+2 != len) &&
(str[1] == '\\') &&
(str[2] == 'u'))
{
/* Advance through the 16 bit surrogate, and move on to the
* next sequence. The next step is to process the following
* characters.
*/
if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
/* Advance to the first char of the next sequence and
* continue processing with the next sequence.
*/
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
goto out;
}
tok->ucs_char = 0;
tok->st_pos = 0;
continue; /* other json_tokener_state_escape_unicode */
} else {
/* Got a high surrogate without another sequence following
* it. Put a replacement char in for the hi surrogate
* and pretend we finished.
*/
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
} else if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Got a low surrogate not preceded by a high */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
} else if (tok->ucs_char < 0x10000) {
unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
} else if (tok->ucs_char < 0x110000) {
unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
} else {
/* Don't know what we got--insert the replacement char */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
state = saved_state;
break;
}
} else {
tok->err = json_tokener_error_parse_string;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
if (got_hi_surrogate) /* Clean up any pending chars */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
goto out;
}
}
}
break;
case json_tokener_state_boolean:
{
int size1, size2;
printbuf_memappend_fast(tok->pb, &c, 1);
size1 = json_min(tok->st_pos+1, json_true_str_len);
size2 = json_min(tok->st_pos+1, json_false_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
|| (strncmp(json_true_str, tok->pb->buf, size1) == 0)
) {
if(tok->st_pos == json_true_str_len) {
current = json_object_new_boolean(1);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
|| (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
if(tok->st_pos == json_false_str_len) {
current = json_object_new_boolean(0);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_boolean;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_number:
{
/* Advance until we change state */
const char *case_start = str;
int case_len=0;
while(c && strchr(json_number_chars, c)) {
++case_len;
if(c == '.' || c == 'e' || c == 'E')
tok->is_double = 1;
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, case_len);
goto out;
}
}
if (case_len>0)
printbuf_memappend_fast(tok->pb, case_start, case_len);
// Check for -Infinity
if (tok->pb->buf[0] == '-' && case_len == 1 &&
(c == 'i' || c == 'I'))
{
state = json_tokener_state_inf;
goto redo_char;
}
}
{
int64_t num64;
double numd;
if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
if (num64 && tok->pb->buf[0]=='0' && (tok->flags & JSON_TOKENER_STRICT)) {
/* in strict mode, number must not start with 0 */
tok->err = json_tokener_error_parse_number;
goto out;
}
current = json_object_new_int64(num64);
}
else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
{
current = json_object_new_double_s(numd, tok->pb->buf);
} else {
tok->err = json_tokener_error_parse_number;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
break;
case json_tokener_state_array_after_sep:
case json_tokener_state_array:
if(c == ']') {
if (state == json_tokener_state_array_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else {
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_array_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
}
break;
case json_tokener_state_array_add:
json_object_array_add(current, obj);
saved_state = json_tokener_state_array_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_array_sep:
if(c == ']') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_array_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_array;
goto out;
}
break;
case json_tokener_state_object_field_start:
case json_tokener_state_object_field_start_after_sep:
if(c == '}') {
if (state == json_tokener_state_object_field_start_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if (c == '"' || c == '\'') {
tok->quote_char = c;
printbuf_reset(tok->pb);
state = json_tokener_state_object_field;
} else {
tok->err = json_tokener_error_parse_object_key_name;
goto out;
}
break;
case json_tokener_state_object_field:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
obj_field_name = strdup(tok->pb->buf);
saved_state = json_tokener_state_object_field_end;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_object_field;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_object_field_end:
if(c == ':') {
saved_state = json_tokener_state_object_value;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_key_sep;
goto out;
}
break;
case json_tokener_state_object_value:
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_object_value_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
case json_tokener_state_object_value_add:
json_object_object_add(current, obj_field_name, obj);
free(obj_field_name);
obj_field_name = NULL;
saved_state = json_tokener_state_object_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_object_sep:
if(c == '}') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_object_field_start_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_value_sep;
goto out;
}
break;
}
if (!ADVANCE_CHAR(str, tok))
goto out;
} /* while(POP_CHAR) */
out:
if (c &&
(state == json_tokener_state_finish) &&
(tok->depth == 0) &&
(tok->flags & JSON_TOKENER_STRICT)) {
/* unexpected char after JSON data */
tok->err = json_tokener_error_parse_unexpected;
}
if (!c) { /* We hit an eof char (0) */
if(state != json_tokener_state_finish &&
saved_state != json_tokener_state_finish)
tok->err = json_tokener_error_parse_eof;
}
#ifdef HAVE_SETLOCALE
setlocale(LC_NUMERIC, oldlocale);
if (oldlocale) free(oldlocale);
#endif
if (tok->err == json_tokener_success)
{
json_object *ret = json_object_get(current);
int ii;
/* Partially reset, so we parse additional objects on subsequent calls. */
for(ii = tok->depth; ii >= 0; ii--)
json_tokener_reset_level(tok, ii);
return ret;
}
MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
json_tokener_errors[tok->err], tok->char_offset);
return NULL;
}
void json_tokener_set_flags(struct json_tokener *tok, int flags)
{
tok->flags = flags;
}

View File

@ -0,0 +1,208 @@
/*
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_tokener_h_
#define _json_tokener_h_
#include <stddef.h>
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
enum json_tokener_error {
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_size
};
enum json_tokener_state {
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
};
struct json_tokener_srec
{
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
};
#define JSON_TOKENER_DEFAULT_DEPTH 32
struct json_tokener
{
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos, char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
};
/**
* Be strict when parsing JSON input. Use caution with
* this flag as what is considered valid may become more
* restrictive from one release to the next, causing your
* code to fail on previously working input.
*
* This flag is not set by default.
*
* @see json_tokener_set_flags()
*/
#define JSON_TOKENER_STRICT 0x01
/**
* Given an error previously returned by json_tokener_get_error(),
* return a human readable description of the error.
*
* @return a generic error message is returned if an invalid error value is provided.
*/
const char *json_tokener_error_desc(enum json_tokener_error jerr);
/**
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
* or json_tokener_success if there is no error.
*
* When parsing a JSON string in pieces, if the tokener is in the middle
* of parsing this will return json_tokener_continue.
*
* See also json_tokener_error_desc().
*/
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
extern struct json_tokener* json_tokener_new(void);
extern struct json_tokener* json_tokener_new_ex(int depth);
extern void json_tokener_free(struct json_tokener *tok);
extern void json_tokener_reset(struct json_tokener *tok);
extern struct json_object* json_tokener_parse(const char *str);
extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
/**
* Set flags that control how parsing will be done.
*/
extern void json_tokener_set_flags(struct json_tokener *tok, int flags);
/**
* Parse a string and return a non-NULL json_object if a valid JSON value
* is found. The string does not need to be a JSON object or array;
* it can also be a string, number or boolean value.
*
* A partial JSON string can be parsed. If the parsing is incomplete,
* NULL will be returned and json_tokener_get_error() will be return
* json_tokener_continue.
* json_tokener_parse_ex() can then be called with additional bytes in str
* to continue the parsing.
*
* If json_tokener_parse_ex() returns NULL and the error anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
* halted. Then tok object must not be re-used until json_tokener_reset() is
* called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned. Also, json_tokener_get_error() will return json_tokener_success.
* Be sure to check the type with json_object_is_type() or
* json_object_get_type() before using the object.
*
* @b XXX this shouldn't use internal fields:
* Trailing characters after the parsed value do not automatically cause an
* error. It is up to the caller to decide whether to treat this as an
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
* Extra characters can be detected by comparing the tok->char_offset against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
* responsible for calling json_tokener_parse_ex with an appropriate str
* parameter starting with the extra characters.
*
* This interface is presently not 64-bit clean due to the int len argument
* so the function limits the maximum string size to INT32_MAX (2GB).
* If the function is called with len == -1 then strlen is called to check
* the string length is less than INT32_MAX (2GB)
*
* Example:
* @code
json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
{
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
}
if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
// Handle extra characters after parsed object as desired.
// e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.
@endcode
*
* @param tok a json_tokener previously allocated with json_tokener_new()
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str
*/
extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,301 @@
/*
* $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#undef realloc
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif /* HAVE_SYS_STAT_H */
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <io.h>
#endif /* defined(_WIN32) */
#if !defined(HAVE_OPEN) && defined(_WIN32)
# define open _open
#endif
#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
/* MSC has the version as _snprintf */
# define snprintf _snprintf
#elif !defined(HAVE_SNPRINTF)
# error You do not have snprintf on your system.
#endif /* HAVE_SNPRINTF */
#include "bits.h"
#include "debug.h"
#include "printbuf.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_util.h"
static int sscanf_is_broken = 0;
static int sscanf_is_broken_testdone = 0;
static void sscanf_is_broken_test(void);
struct json_object* json_object_from_file(const char *filename)
{
//struct printbuf *pb;
//struct json_object *obj;
//char buf[JSON_FILE_BUF_SIZE];
//int fd, ret;
//if((fd = open(filename, O_RDONLY)) < 0) {
// MC_ERROR("json_object_from_file: error opening file %s: %s\n",
// filename, strerror(errno));
// return NULL;
//}
//if(!(pb = printbuf_new())) {
// close(fd);
// MC_ERROR("json_object_from_file: printbuf_new failed\n");
// return NULL;
//}
//while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
// printbuf_memappend(pb, buf, ret);
//}
//close(fd);
//if(ret < 0) {
// MC_ERROR("json_object_from_file: error reading file %s: %s\n",
// filename, strerror(errno));
// printbuf_free(pb);
// return NULL;
//}
//obj = json_tokener_parse(pb->buf);
//printbuf_free(pb);
return NULL;//obj;
}
/* extended "format and write to file" function */
int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags)
{
//const char *json_str;
//int fd, ret;
//unsigned int wpos, wsize;
//if(!obj) {
// MC_ERROR("json_object_to_file: object is null\n");
// return -1;
//}
//if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
// MC_ERROR("json_object_to_file: error opening file %s: %s\n",
// filename, strerror(errno));
// return -1;
//}
//if(!(json_str = json_object_to_json_string_ext(obj,flags))) {
// close(fd);
// return -1;
//}
//wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
//wpos = 0;
//while(wpos < wsize) {
// if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
// close(fd);
// MC_ERROR("json_object_to_file: error writing file %s: %s\n",
// filename, strerror(errno));
// return -1;
// }
// /* because of the above check for ret < 0, we can safely cast and add */
// wpos += (unsigned int)ret;
//}
//close(fd);
return 0;
}
// backwards compatible "format and write to file" function
int json_object_to_file(const char *filename, struct json_object *obj)
{
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
}
int json_parse_double(const char *buf, double *retval)
{
return (sscanf_s(buf, "%lf", retval)==1 ? 0 : 1);
}
/*
* Not all implementations of sscanf actually work properly.
* Check whether the one we're currently using does, and if
* it's broken, enable the workaround code.
*/
static void sscanf_is_broken_test()
{
int64_t num64;
int ret_errno, is_int64_min, ret_errno2, is_int64_max;
sscanf_s(" -01234567890123456789012345", "%" SCNd64, &num64);
ret_errno = errno;
is_int64_min = (num64 == INT64_MIN);
sscanf_s(" 01234567890123456789012345", "%" SCNd64, &num64);
ret_errno2 = errno;
is_int64_max = (num64 == INT64_MAX);
if (ret_errno != ERANGE || !is_int64_min ||
ret_errno2 != ERANGE || !is_int64_max)
{
MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n");
sscanf_is_broken = 1;
}
}
int json_parse_int64(const char *buf, int64_t *retval)
{
int64_t num64;
const char *buf_sig_digits;
int orig_has_neg;
int saved_errno;
if (!sscanf_is_broken_testdone)
{
sscanf_is_broken_test();
sscanf_is_broken_testdone = 1;
}
// Skip leading spaces
while (isspace((int)*buf) && *buf)
buf++;
errno = 0; // sscanf won't always set errno, so initialize
if (sscanf_s(buf, "%" SCNd64, &num64) != 1)
{
MC_DEBUG("Failed to parse, sscanf != 1\n");
return 1;
}
saved_errno = errno;
buf_sig_digits = buf;
orig_has_neg = 0;
if (*buf_sig_digits == '-')
{
buf_sig_digits++;
orig_has_neg = 1;
}
// Not all sscanf implementations actually work
if (sscanf_is_broken && saved_errno != ERANGE)
{
char buf_cmp[100];
char *buf_cmp_start = buf_cmp;
int recheck_has_neg = 0;
int buf_cmp_len;
// Skip leading zeros, but keep at least one digit
while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
buf_sig_digits++;
if (num64 == 0) // assume all sscanf impl's will parse -0 to 0
orig_has_neg = 0; // "-0" is the same as just plain "0"
_snprintf_s(buf_cmp_start, sizeof(buf_cmp), _TRUNCATE, "%" PRId64, num64);
if (*buf_cmp_start == '-')
{
recheck_has_neg = 1;
buf_cmp_start++;
}
// No need to skip leading spaces or zeros here.
buf_cmp_len = (int)strlen(buf_cmp_start);
/**
* If the sign is different, or
* some of the digits are different, or
* there is another digit present in the original string
* then we have NOT successfully parsed the value.
*/
if (orig_has_neg != recheck_has_neg ||
strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 ||
((int)strlen(buf_sig_digits) != buf_cmp_len &&
isdigit((int)buf_sig_digits[buf_cmp_len])
)
)
{
saved_errno = ERANGE;
}
}
// Not all sscanf impl's set the value properly when out of range.
// Always do this, even for properly functioning implementations,
// since it shouldn't slow things down much.
if (saved_errno == ERANGE)
{
if (orig_has_neg)
num64 = INT64_MIN;
else
num64 = INT64_MAX;
}
*retval = num64;
return 0;
}
#ifndef HAVE_REALLOC
void* rpl_realloc(void* p, size_t n)
{
if (n == 0)
n = 1;
if (p == 0)
return malloc(n);
return realloc(p, n);
}
#endif
#define NELEM(a) (sizeof(a) / sizeof(a[0]))
static const char* json_type_name[] = {
/* If you change this, be sure to update the enum json_type definition too */
"null",
"boolean",
"double",
"int",
"object",
"array",
"string",
};
const char *json_type_to_name(enum json_type o_type)
{
int o_type_int = (int)o_type;
if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
{
MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
return NULL;
}
return json_type_name[o_type];
}

View File

@ -0,0 +1,41 @@
/*
* $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_util_h_
#define _json_util_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
#define JSON_FILE_BUF_SIZE 4096
/* utility functions */
extern struct json_object* json_object_from_file(const char *filename);
extern int json_object_to_file(const char *filename, struct json_object *obj);
extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags);
extern int json_parse_int64(const char *buf, int64_t *retval);
extern int json_parse_double(const char *buf, double *retval);
/**
* Return a string describing the type of the object.
* e.g. "int", or "object", etc...
*/
extern const char *json_type_to_name(enum json_type o_type);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,26 @@
/* dummy source file for compatibility purposes */
#if defined(HAVE_CDEFS_H)
#include <sys/cdefs.h>
#endif
#ifndef __warn_references
#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG)
#define __warn_references(sym,msg) \
__asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text");
#else
#define __warn_references(sym,msg) /* nothing */
#endif
#endif
#include "json_object.h"
__warn_references(json_object_get, "Warning: please link against libjson-c instead of libjson");
/* __asm__(".section .gnu.warning." __STRING(sym) \
" ; .ascii \"" msg "\" ; .text") */

View File

@ -0,0 +1,604 @@
/*
* $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <limits.h>
#include <Windows.h>
#ifdef HAVE_ENDIAN_H
# include <endian.h> /* attempt to define endianness */
#endif
#include "random_seed.h"
#include "linkhash.h"
void lh_abort(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vprintf(msg, ap);
va_end(ap);
exit(1);
}
unsigned long lh_ptr_hash(const void *k)
{
/* CAW: refactored to be 64bit nice */
return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
}
int lh_ptr_equal(const void *k1, const void *k2)
{
return (k1 == k2);
}
/*
* hashlittle from lookup3.c, by Bob Jenkins, May 2006, Public Domain.
* http://burtleburtle.net/bob/c/lookup3.c
* minor modifications to make functions static so no symbols are exported
* minor mofifications to compile with -Werror
*/
/*
-------------------------------------------------------------------------------
lookup3.c, by Bob Jenkins, May 2006, Public Domain.
These are functions for producing 32-bit hashes for hash table lookup.
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
are externally useful functions. Routines to test the hash are included
if SELF_TEST is defined. You can use this free for any purpose. It's in
the public domain. It has no warranty.
You probably want to use hashlittle(). hashlittle() and hashbig()
hash byte arrays. hashlittle() is is faster than hashbig() on
little-endian machines. Intel and AMD are little-endian machines.
On second thought, you probably want hashlittle2(), which is identical to
hashlittle() except it returns two 32-bit hashes for the price of one.
You could implement hashbig2() if you wanted but I haven't bothered here.
If you want to find a hash of, say, exactly 7 integers, do
a = i1; b = i2; c = i3;
mix(a,b,c);
a += i4; b += i5; c += i6;
mix(a,b,c);
a += i7;
final(a,b,c);
then use c as the hash value. If you have a variable length array of
4-byte integers to hash, use hashword(). If you have a byte array (like
a character string), use hashlittle(). If you have several byte arrays, or
a mix of things, see the comments above hashlittle().
Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
then mix those integers. This is fast (you can do a lot more thorough
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
-------------------------------------------------------------------------------
*/
/*
* My best guess at if you are big-endian or little-endian. This may
* need adjustment.
*/
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
__BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
# define HASH_LITTLE_ENDIAN 1
# define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
__BYTE_ORDER == __BIG_ENDIAN) || \
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 1
#else
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 0
#endif
#define hashsize(n) ((uint32_t)1<<(n))
#define hashmask(n) (hashsize(n)-1)
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
/*
-------------------------------------------------------------------------------
mix -- mix 3 32-bit values reversibly.
This is reversible, so any information in (a,b,c) before mix() is
still in (a,b,c) after mix().
If four pairs of (a,b,c) inputs are run through mix(), or through
mix() in reverse, there are at least 32 bits of the output that
are sometimes the same for one pair and different for another pair.
This was tested for:
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
satisfy this are
4 6 8 16 19 4
9 15 3 18 27 15
14 9 3 7 17 3
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
for "differ" defined as + with a one-bit base and a two-bit delta. I
used http://burtleburtle.net/bob/hash/avalanche.html to choose
the operations, constants, and arrangements of the variables.
This does not achieve avalanche. There are input bits of (a,b,c)
that fail to affect some output bits of (a,b,c), especially of a. The
most thoroughly mixed value is c, but it doesn't really even achieve
avalanche in c.
This allows some parallelism. Read-after-writes are good at doubling
the number of bits affected, so the goal of mixing pulls in the opposite
direction as the goal of parallelism. I did what I could. Rotates
seem to cost as much as shifts on every machine I could lay my hands
on, and rotates are much kinder to the top and bottom bits, so I used
rotates.
-------------------------------------------------------------------------------
*/
#define mix(a,b,c) \
{ \
a -= c; a ^= rot(c, 4); c += b; \
b -= a; b ^= rot(a, 6); a += c; \
c -= b; c ^= rot(b, 8); b += a; \
a -= c; a ^= rot(c,16); c += b; \
b -= a; b ^= rot(a,19); a += c; \
c -= b; c ^= rot(b, 4); b += a; \
}
/*
-------------------------------------------------------------------------------
final -- final mixing of 3 32-bit values (a,b,c) into c
Pairs of (a,b,c) values differing in only a few bits will usually
produce values of c that look totally different. This was tested for
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
These constants passed:
14 11 25 16 4 14 24
12 14 25 16 4 14 24
and these came close:
4 8 15 26 3 22 24
10 8 15 26 3 22 24
11 8 15 26 3 22 24
-------------------------------------------------------------------------------
*/
#define final(a,b,c) \
{ \
c ^= b; c -= rot(b,14); \
a ^= c; a -= rot(c,11); \
b ^= a; b -= rot(a,25); \
c ^= b; c -= rot(b,16); \
a ^= c; a -= rot(c,4); \
b ^= a; b -= rot(a,14); \
c ^= b; c -= rot(b,24); \
}
/*
-------------------------------------------------------------------------------
hashlittle() -- hash a variable-length key into a 32-bit value
k : the key (the unaligned variable-length array of bytes)
length : the length of the key, counting by bytes
initval : can be any 4-byte value
Returns a 32-bit value. Every bit of the key affects every bit of
the return value. Two keys differing by one or two bits will have
totally different hash values.
The best hash table sizes are powers of 2. There is no need to do
mod a prime (mod is sooo slow!). If you need less than 32 bits,
use a bitmask. For example, if you need only 10 bits, do
h = (h & hashmask(10));
In which case, the hash table should have hashsize(10) elements.
If you are hashing n strings (uint8_t **)k, do it like this:
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
code any way you wish, private, educational, or commercial. It's free.
Use for hash table lookup, or anything where one collision in 2^^32 is
acceptable. Do NOT use for cryptographic purposes.
-------------------------------------------------------------------------------
*/
static uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
{
uint32_t a,b,c; /* internal state */
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
/* Set up the internal state */
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (length > 12)
{
a += k[0];
b += k[1];
c += k[2];
mix(a,b,c);
length -= 12;
k += 3;
}
/*----------------------------- handle the last (probably partial) block */
/*
* "k[2]&0xffffff" actually reads beyond the end of the string, but
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
case 6 : b+=k[1]&0xffff; a+=k[0]; break;
case 5 : b+=k[1]&0xff; a+=k[0]; break;
case 4 : a+=k[0]; break;
case 3 : a+=k[0]&0xffffff; break;
case 2 : a+=k[0]&0xffff; break;
case 1 : a+=k[0]&0xff; break;
case 0 : return c; /* zero length strings require no mixing */
}
#else /* make valgrind happy */
const uint8_t *k8 = (const uint8_t *)k;
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]; break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
case 1 : a+=k8[0]; break;
case 0 : return c;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
const uint8_t *k8;
/*--------------- all but last block: aligned reads and different mixing */
while (length > 12)
{
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
mix(a,b,c);
length -= 12;
k += 6;
}
/*----------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
switch(length)
{
case 12: c+=k[4]+(((uint32_t)k[5])<<16);
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=k[4];
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=k[2];
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=k[0];
break;
case 1 : a+=k8[0];
break;
case 0 : return c; /* zero length requires no mixing */
}
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
while (length > 12)
{
a += k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
mix(a,b,c);
length -= 12;
k += 12;
}
/*-------------------------------- last block: affect all 32 bits of (c) */
switch(length) /* all the case statements fall through */
{
case 12: c+=((uint32_t)k[11])<<24;
case 11: c+=((uint32_t)k[10])<<16;
case 10: c+=((uint32_t)k[9])<<8;
case 9 : c+=k[8];
case 8 : b+=((uint32_t)k[7])<<24;
case 7 : b+=((uint32_t)k[6])<<16;
case 6 : b+=((uint32_t)k[5])<<8;
case 5 : b+=k[4];
case 4 : a+=((uint32_t)k[3])<<24;
case 3 : a+=((uint32_t)k[2])<<16;
case 2 : a+=((uint32_t)k[1])<<8;
case 1 : a+=k[0];
break;
case 0 : return c;
}
}
final(a,b,c);
return c;
}
unsigned long lh_char_hash(const void *k)
{
static volatile int random_seed = -1;
if (random_seed == -1) {
int seed;
/* we can't use -1 as it is the unitialized sentinel */
while ((seed = json_c_get_random_seed()) == -1);
#if defined __GNUC__
__sync_val_compare_and_swap(&random_seed, -1, seed);
#elif defined _MSC_VER
InterlockedCompareExchange(&random_seed, seed, -1);
#else
#warning "racy random seed initializtion if used by multiple threads"
random_seed = seed; /* potentially racy */
#endif
}
return hashlittle((const char*)k, strlen((const char*)k), random_seed);
}
int lh_char_equal(const void *k1, const void *k2)
{
return (strcmp((const char*)k1, (const char*)k2) == 0);
}
struct lh_table* lh_table_new(int size, const char *name,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn)
{
int i;
struct lh_table *t;
t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
if(!t) lh_abort("lh_table_new: calloc failed\n");
t->count = 0;
t->size = size;
t->name = name;
t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
if(!t->table) lh_abort("lh_table_new: calloc failed\n");
t->free_fn = free_fn;
t->hash_fn = hash_fn;
t->equal_fn = equal_fn;
for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
return t;
}
struct lh_table* lh_kchar_table_new(int size, const char *name,
lh_entry_free_fn *free_fn)
{
return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
}
struct lh_table* lh_kptr_table_new(int size, const char *name,
lh_entry_free_fn *free_fn)
{
return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
}
void lh_table_resize(struct lh_table *t, int new_size)
{
struct lh_table *new_t;
struct lh_entry *ent;
new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
ent = t->head;
while(ent) {
lh_table_insert(new_t, ent->k, ent->v);
ent = ent->next;
}
free(t->table);
t->table = new_t->table;
t->size = new_size;
t->head = new_t->head;
t->tail = new_t->tail;
t->resizes++;
free(new_t);
}
void lh_table_free(struct lh_table *t)
{
struct lh_entry *c;
for(c = t->head; c != NULL; c = c->next) {
if(t->free_fn) {
t->free_fn(c);
}
}
free(t->table);
free(t);
}
int lh_table_insert(struct lh_table *t, void *k, const void *v)
{
unsigned long h, n;
t->inserts++;
if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2);
h = t->hash_fn(k);
n = h % t->size;
while( 1 ) {
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
t->collisions++;
if ((int)++n == t->size) n = 0;
}
t->table[n].k = k;
t->table[n].v = v;
t->count++;
if(t->head == NULL) {
t->head = t->tail = &t->table[n];
t->table[n].next = t->table[n].prev = NULL;
} else {
t->tail->next = &t->table[n];
t->table[n].prev = t->tail;
t->table[n].next = NULL;
t->tail = &t->table[n];
}
return 0;
}
struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
{
unsigned long h = t->hash_fn(k);
unsigned long n = h % t->size;
int count = 0;
t->lookups++;
while( count < t->size ) {
if(t->table[n].k == LH_EMPTY) return NULL;
if(t->table[n].k != LH_FREED &&
t->equal_fn(t->table[n].k, k)) return &t->table[n];
if ((int)++n == t->size) n = 0;
count++;
}
return NULL;
}
const void* lh_table_lookup(struct lh_table *t, const void *k)
{
void *result;
lh_table_lookup_ex(t, k, &result);
return result;
}
json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if (e != NULL) {
if (v != NULL) *v = (void *)e->v;
return TRUE; /* key found */
}
if (v != NULL) *v = NULL;
return FALSE; /* key not found */
}
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
{
ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
if(n < 0) { return -2; }
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
t->count--;
if(t->free_fn) t->free_fn(e);
t->table[n].v = NULL;
t->table[n].k = LH_FREED;
if(t->tail == &t->table[n] && t->head == &t->table[n]) {
t->head = t->tail = NULL;
} else if (t->head == &t->table[n]) {
t->head->next->prev = NULL;
t->head = t->head->next;
} else if (t->tail == &t->table[n]) {
t->tail->prev->next = NULL;
t->tail = t->tail->prev;
} else {
t->table[n].prev->next = t->table[n].next;
t->table[n].next->prev = t->table[n].prev;
}
t->table[n].next = t->table[n].prev = NULL;
return 0;
}
int lh_table_delete(struct lh_table *t, const void *k)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if(!e) return -1;
return lh_table_delete_entry(t, e);
}
int lh_table_length(struct lh_table *t)
{
return t->count;
}

View File

@ -0,0 +1,292 @@
/*
* $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _linkhash_h_
#define _linkhash_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* golden prime used in hash functions
*/
#define LH_PRIME 0x9e370001UL
/**
* The fraction of filled hash buckets until an insert will cause the table
* to be resized.
* This can range from just above 0 up to 1.0.
*/
#define LH_LOAD_FACTOR 0.66
/**
* sentinel pointer value for empty slots
*/
#define LH_EMPTY (void*)-1
/**
* sentinel pointer value for freed slots
*/
#define LH_FREED (void*)-2
struct lh_entry;
/**
* callback function prototypes
*/
typedef void (lh_entry_free_fn) (struct lh_entry *e);
/**
* callback function prototypes
*/
typedef unsigned long (lh_hash_fn) (const void *k);
/**
* callback function prototypes
*/
typedef int (lh_equal_fn) (const void *k1, const void *k2);
/**
* An entry in the hash table
*/
struct lh_entry {
/**
* The key.
*/
void *k;
/**
* The value.
*/
const void *v;
/**
* The next entry
*/
struct lh_entry *next;
/**
* The previous entry.
*/
struct lh_entry *prev;
};
/**
* The hash table structure.
*/
struct lh_table {
/**
* Size of our hash.
*/
int size;
/**
* Numbers of entries.
*/
int count;
/**
* Number of collisions.
*/
int collisions;
/**
* Number of resizes.
*/
int resizes;
/**
* Number of lookups.
*/
int lookups;
/**
* Number of inserts.
*/
int inserts;
/**
* Number of deletes.
*/
int deletes;
/**
* Name of the hash table.
*/
const char *name;
/**
* The first entry.
*/
struct lh_entry *head;
/**
* The last entry.
*/
struct lh_entry *tail;
struct lh_entry *table;
/**
* A pointer onto the function responsible for freeing an entry.
*/
lh_entry_free_fn *free_fn;
lh_hash_fn *hash_fn;
lh_equal_fn *equal_fn;
};
/**
* Pre-defined hash and equality functions
*/
extern unsigned long lh_ptr_hash(const void *k);
extern int lh_ptr_equal(const void *k1, const void *k2);
extern unsigned long lh_char_hash(const void *k);
extern int lh_char_equal(const void *k1, const void *k2);
/**
* Convenience list iterator.
*/
#define lh_foreach(table, entry) \
for(entry = table->head; entry; entry = entry->next)
/**
* lh_foreach_safe allows calling of deletion routine while iterating.
*/
#define lh_foreach_safe(table, entry, tmp) \
for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
/**
* Create a new linkhash table.
* @param size initial table size. The table is automatically resized
* although this incurs a performance penalty.
* @param name the table name.
* @param free_fn callback function used to free memory for entries
* when lh_table_free or lh_table_delete is called.
* If NULL is provided, then memory for keys and values
* must be freed by the caller.
* @param hash_fn function used to hash keys. 2 standard ones are defined:
* lh_ptr_hash and lh_char_hash for hashing pointer values
* and C strings respectively.
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
* lh_ptr_hash and lh_char_hash for comparing pointer values
* and C strings respectively.
* @return a pointer onto the linkhash table.
*/
extern struct lh_table* lh_table_new(int size, const char *name,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);
/**
* Convenience function to create a new linkhash
* table with char keys.
* @param size initial table size.
* @param name table name.
* @param free_fn callback function used to free memory for entries.
* @return a pointer onto the linkhash table.
*/
extern struct lh_table* lh_kchar_table_new(int size, const char *name,
lh_entry_free_fn *free_fn);
/**
* Convenience function to create a new linkhash
* table with ptr keys.
* @param size initial table size.
* @param name table name.
* @param free_fn callback function used to free memory for entries.
* @return a pointer onto the linkhash table.
*/
extern struct lh_table* lh_kptr_table_new(int size, const char *name,
lh_entry_free_fn *free_fn);
/**
* Free a linkhash table.
* If a callback free function is provided then it is called for all
* entries in the table.
* @param t table to free.
*/
extern void lh_table_free(struct lh_table *t);
/**
* Insert a record into the table.
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
*/
extern int lh_table_insert(struct lh_table *t, void *k, const void *v);
/**
* Lookup a record into the table.
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
/**
* Lookup a record into the table
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the found value or NULL if it does not exist.
* @deprecated Use lh_table_lookup_ex instead.
*/
THIS_FUNCTION_IS_DEPRECATED(extern const void* lh_table_lookup(struct lh_table *t, const void *k));
/**
* Lookup a record in the table
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
* @return whether or not the key was found
*/
extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
/**
* Delete a record from the table.
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param e a pointer to the entry to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
/**
* Delete a record from the table.
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param k a pointer to the key to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete(struct lh_table *t, const void *k);
extern int lh_table_length(struct lh_table *t);
void lh_abort(const char *msg, ...);
void lh_table_resize(struct lh_table *t, int new_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,28 @@
#ifndef __math_compat_h
#define __math_compat_h
/* Define isnan and isinf on Windows/MSVC */
#ifndef HAVE_DECL_ISNAN
# ifdef HAVE_DECL__ISNAN
#include <float.h>
#define isnan(x) _isnan(x)
# endif
#endif
#ifndef HAVE_DECL_ISINF
# ifdef HAVE_DECL__FINITE
#include <float.h>
#define isinf(x) (!_finite(x))
# endif
#endif
#ifndef HAVE_DECL_NAN
#error This platform does not have nan()
#endif
#ifndef HAVE_DECL_INFINITY
#error This platform does not have INFINITY
#endif
#endif

View File

@ -0,0 +1,194 @@
/*
* $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDARG_H
# include <stdarg.h>
#else /* !HAVE_STDARG_H */
# error Not enough var arg support!
#endif /* HAVE_STDARG_H */
#include "bits.h"
#include "debug.h"
#include "printbuf.h"
static int printbuf_extend(struct printbuf *p, size_t min_size);
struct printbuf* printbuf_new(void)
{
struct printbuf *p;
p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
if(!p) return NULL;
p->size = 32;
p->bpos = 0;
if(!(p->buf = (char*)malloc(p->size))) {
free(p);
return NULL;
}
return p;
}
/**
* Extend the buffer p so it has a size of at least min_size.
*
* If the current size is large enough, nothing is changed.
*
* Note: this does not check the available space! The caller
* is responsible for performing those calculations.
*/
static int printbuf_extend(struct printbuf *p, size_t min_size)
{
char *t;
size_t new_size;
if (p->size >= min_size)
return 0;
new_size = json_max(p->size * 2, min_size + 8);
#ifdef PRINTBUF_DEBUG
MC_DEBUG("printbuf_memappend: realloc "
"bpos=%d min_size=%d old_size=%d new_size=%d\n",
p->bpos, min_size, p->size, new_size);
#endif /* PRINTBUF_DEBUG */
if(!(t = (char*)realloc(p->buf, new_size)))
return -1;
p->size = new_size;
p->buf = t;
return 0;
}
size_t printbuf_memappend(struct printbuf *p, const char *buf, size_t size)
{
if (p->size <= p->bpos + size + 1) {
if (printbuf_extend(p, p->bpos + size + 1) < 0)
return -1;
}
memcpy(p->buf + p->bpos, buf, size);
p->bpos += size;
p->buf[p->bpos]= '\0';
return size;
}
int printbuf_memset(struct printbuf *pb, size_t offset, int charvalue, size_t len)
{
size_t size_needed;
if (offset == -1)
offset = pb->bpos;
size_needed = offset + len;
if (pb->size < size_needed)
{
if (printbuf_extend(pb, size_needed) < 0)
return -1;
}
memset(pb->buf + offset, charvalue, len);
if (pb->bpos < size_needed)
pb->bpos = size_needed;
return 0;
}
#if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER)
# define vsnprintf _vsnprintf
#elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */
# error Need vsnprintf!
#endif /* !HAVE_VSNPRINTF && defined(_WIN32) */
#if !defined(HAVE_VASPRINTF)
/* CAW: compliant version of vasprintf */
static int vasprintf(char **buf, const char *fmt, va_list ap)
{
#ifndef _WIN32
static char _T_emptybuffer = '\0';
#endif /* !defined(_WIN32) */
int chars;
char *b;
if(!buf) { return -1; }
#ifdef _WIN32
chars = _vscprintf(fmt, ap)+1;
#else /* !defined(_WIN32) */
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
our buffer like on some 64bit sun systems.... but hey, its time to move on */
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
#endif /* defined(_WIN32) */
b = (char*)malloc(sizeof(char) * chars);
if(!b) { return -1; }
if ((chars = vsprintf_s(b, sizeof(char), fmt, ap)) < 0)
{
free(b);
}
else
{
*buf = b;
}
return chars;
}
#endif /* !HAVE_VASPRINTF */
int sprintbuf(struct printbuf *p, const char *msg, ...)
{
va_list ap;
char *t;
int size;
char buf[128];
/* user stack buffer first */
va_start(ap, msg);
size = _vsnprintf_s(buf, sizeof(buf), _TRUNCATE, msg, ap);
va_end(ap);
/* if string is greater than stack buffer, then use dynamic string
with vasprintf. Note: some implementation of vsnprintf return -1
if output is truncated whereas some return the number of bytes that
would have been written - this code handles both cases. */
if(size == -1 || size > 127) {
va_start(ap, msg);
if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; }
va_end(ap);
printbuf_memappend(p, t, size);
free(t);
return size;
} else {
printbuf_memappend(p, buf, size);
return size;
}
}
void printbuf_reset(struct printbuf *p)
{
p->buf[0] = '\0';
p->bpos = 0;
}
void printbuf_free(struct printbuf *p)
{
if(p) {
free(p->buf);
free(p);
}
}

View File

@ -0,0 +1,81 @@
/*
* $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#ifndef _printbuf_h_
#define _printbuf_h_
#ifdef __cplusplus
extern "C" {
#endif
struct printbuf {
char *buf;
size_t bpos;
size_t size;
};
extern struct printbuf*
printbuf_new(void);
/* As an optimization, printbuf_memappend_fast is defined as a macro
* that handles copying data if the buffer is large enough; otherwise
* it invokes printbuf_memappend_real() which performs the heavy
* lifting of realloc()ing the buffer and copying data.
* Your code should not use printbuf_memappend directly--use
* printbuf_memappend_fast instead.
*/
extern size_t printbuf_memappend(struct printbuf *p, const char *buf, size_t size);
__inline void printbuf_memappend_fast(struct printbuf *p, const char *bufptr, size_t bufsize)
{
if ((p->size - p->bpos) > bufsize)
{
memcpy(p->buf + p->bpos, (bufptr), bufsize);
p->bpos += (int)bufsize;
p->buf[p->bpos] = '\0';
}
else
{
printbuf_memappend(p, (bufptr), bufsize);
}
}
#define printbuf_length(p) ((p)->bpos)
/**
* Set len bytes of the buffer to charvalue, starting at offset offset.
* Similar to calling memset(x, charvalue, len);
*
* The memory allocated for the buffer is extended as necessary.
*
* If offset is -1, this starts at the end of the current data in the buffer.
*/
extern int
printbuf_memset(struct printbuf *pb, size_t offset, int charvalue, size_t len);
extern int
sprintbuf(struct printbuf *p, const char *msg, ...);
extern void
printbuf_reset(struct printbuf *p);
extern void
printbuf_free(struct printbuf *p);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,238 @@
/*
* random_seed.c
*
* Copyright (c) 2013 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include <stdio.h>
#include "config.h"
#define DEBUG_SEED(s)
#if defined ENABLE_RDRAND
/* cpuid */
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define HAS_X86_CPUID 1
static void do_cpuid(int regs[], int h)
{
__asm__ __volatile__(
#if defined __x86_64__
"pushq %%rbx;\n"
#else
"pushl %%ebx;\n"
#endif
"cpuid;\n"
#if defined __x86_64__
"popq %%rbx;\n"
#else
"popl %%ebx;\n"
#endif
: "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
: "a"(h));
}
#elif defined _MSC_VER
#define HAS_X86_CPUID 1
#define do_cpuid __cpuid
#endif
/* has_rdrand */
#if HAS_X86_CPUID
static int has_rdrand()
{
// CPUID.01H:ECX.RDRAND[bit 30] == 1
int regs[4];
do_cpuid(regs, 1);
return (regs[2] & (1 << 30)) != 0;
}
#endif
/* get_rdrand_seed - GCC x86 and X64 */
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define HAVE_RDRAND 1
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int _eax;
// rdrand eax
__asm__ __volatile__("1: .byte 0x0F\n"
" .byte 0xC7\n"
" .byte 0xF0\n"
" jnc 1b;\n"
: "=a" (_eax));
return _eax;
}
#endif
#if defined _MSC_VER
#if _MSC_VER >= 1700
#define HAVE_RDRAND 1
/* get_rdrand_seed - Visual Studio 2012 and above */
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int r;
while (_rdrand32_step(&r) == 0);
return r;
}
#elif defined _M_IX86
#define HAVE_RDRAND 1
/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int _eax;
retry:
// rdrand eax
__asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0
__asm jnc retry
__asm mov _eax, eax
return _eax;
}
#endif
#endif
#endif /* defined ENABLE_RDRAND */
/* has_dev_urandom */
#if defined (__APPLE__) || defined(__unix__) || defined(__linux__)
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#define HAVE_DEV_RANDOM 1
static const char *dev_random_file = "/dev/urandom";
static int has_dev_urandom()
{
struct stat buf;
if (stat(dev_random_file, &buf)) {
return 0;
}
return ((buf.st_mode & S_IFCHR) != 0);
}
/* get_dev_random_seed */
static int get_dev_random_seed()
{
DEBUG_SEED("get_dev_random_seed");
int fd = open(dev_random_file, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno));
exit(1);
}
int r;
ssize_t nread = read(fd, &r, sizeof(r));
if (nread != sizeof(r)) {
fprintf(stderr, "error read %s: %s", dev_random_file, strerror(errno));
exit(1);
}
else if (nread != sizeof(r)) {
fprintf(stderr, "error short read %s", dev_random_file);
exit(1);
}
close(fd);
return r;
}
#endif
/* get_cryptgenrandom_seed */
#ifdef _WIN32
#define HAVE_CRYPTGENRANDOM 1
#include <windows.h>
static int get_cryptgenrandom_seed()
{
DEBUG_SEED("get_cryptgenrandom_seed");
HCRYPTPROV hProvider = 0;
int r;
if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
{
fprintf(stderr, "error CryptAcquireContextW");
exit(1);
}
if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r))
{
fprintf(stderr, "error CryptGenRandom");
exit(1);
}
CryptReleaseContext(hProvider, 0);
return r;
}
#endif
/* get_time_seed */
#include <time.h>
static int get_time_seed()
{
DEBUG_SEED("get_time_seed");
return (int)time(NULL) * 433494437;
}
/* json_c_get_random_seed */
int json_c_get_random_seed()
{
#if HAVE_RDRAND
if (has_rdrand()) return get_rdrand_seed();
#endif
#if HAVE_DEV_RANDOM
if (has_dev_urandom()) return get_dev_random_seed();
#endif
#if HAVE_CRYPTGENRANDOM
return get_cryptgenrandom_seed();
#endif
return get_time_seed();
}

View File

@ -0,0 +1,25 @@
/*
* random_seed.h
*
* Copyright (c) 2013 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef seed_h
#define seed_h
#ifdef __cplusplus
extern "C" {
#endif
extern int json_c_get_random_seed();
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,321 @@
/*
* Process Hacker Extra Plugins -
* Plugin Manager
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
PPH_PLUGIN PluginInstance;
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
PH_CALLBACK_REGISTRATION MainMenuInitializingCallbackRegistration;
PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
BOOLEAN LastCleanupExpired(
VOID
)
{
ULONG64 lastUpdateTimeTicks = 0;
LARGE_INTEGER currentUpdateTimeTicks;
PPH_STRING lastUpdateTimeString;
PhQuerySystemTime(&currentUpdateTimeTicks);
lastUpdateTimeString = PhGetStringSetting(SETTING_NAME_LAST_CLEANUP);
PhStringToInteger64(&lastUpdateTimeString->sr, 0, &lastUpdateTimeTicks);
PhDereferenceObject(lastUpdateTimeString);
if (currentUpdateTimeTicks.QuadPart - lastUpdateTimeTicks >= 25 * PH_TICKS_PER_DAY)
{
PPH_STRING currentUpdateTimeString = PhFormatUInt64(currentUpdateTimeTicks.QuadPart, FALSE);
PhSetStringSetting2(SETTING_NAME_LAST_CLEANUP, &currentUpdateTimeString->sr);
PhDereferenceObject(currentUpdateTimeString);
return TRUE;
}
return FALSE;
}
BOOLEAN PluginsCleanupDirectoryCallback(
_In_ PFILE_DIRECTORY_INFORMATION Information,
_In_opt_ PVOID Context
)
{
PH_STRINGREF baseName;
PPH_STRING fileName;
PPH_STRING rootDirectoryPath;
rootDirectoryPath = Context;
baseName.Buffer = Information->FileName;
baseName.Length = Information->FileNameLength;
if (PhEqualStringRef2(&baseName, L".", TRUE) || PhEqualStringRef2(&baseName, L"..", TRUE))
return TRUE;
if (Information->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
HANDLE pluginsDirectoryHandle;
PPH_STRING directoryPath;
PPH_STRING PluginsDirectoryPath;
directoryPath = PhCreateString2(&baseName);
PluginsDirectoryPath = PhConcatStrings(4, rootDirectoryPath->Buffer, L"\\", directoryPath->Buffer, L"\\");
if (NT_SUCCESS(PhCreateFileWin32(
&pluginsDirectoryHandle,
PluginsDirectoryPath->Buffer,
FILE_GENERIC_READ,
0,
FILE_SHARE_READ,
FILE_OPEN,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
)))
{
UNICODE_STRING pattern = RTL_CONSTANT_STRING(L"*");
PhEnumDirectoryFile(pluginsDirectoryHandle, &pattern, PluginsCleanupDirectoryCallback, PluginsDirectoryPath);
NtClose(pluginsDirectoryHandle);
}
}
else if (PhEndsWithStringRef2(&baseName, L".bak", TRUE))
{
NTSTATUS status;
HANDLE fileHandle;
FILE_DISPOSITION_INFORMATION dispositionInfo;
IO_STATUS_BLOCK isb;
fileName = PhCreateStringEx(NULL, rootDirectoryPath->Length + Information->FileNameLength);
memcpy(fileName->Buffer, rootDirectoryPath->Buffer, rootDirectoryPath->Length);
memcpy(&fileName->Buffer[rootDirectoryPath->Length / 2], Information->FileName, Information->FileNameLength);
if (NT_SUCCESS(status = PhCreateFileWin32(
&fileHandle,
fileName->Buffer,
FILE_GENERIC_WRITE | DELETE,
0,
0,
FILE_OVERWRITE_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
)))
{
dispositionInfo.DeleteFile = TRUE;
NtSetInformationFile(
fileHandle,
&isb,
&dispositionInfo,
sizeof(FILE_DISPOSITION_INFORMATION),
FileDispositionInformation
);
NtClose(fileHandle);
}
PhDereferenceObject(fileName);
}
return TRUE;
}
VOID PluginsCleanup(
VOID
)
{
static UNICODE_STRING pluginsPattern = RTL_CONSTANT_STRING(L"*");
HANDLE pluginsDirectoryHandle;
PPH_STRING pluginsDirectory;
PPH_STRING PluginsDirectoryPath;
pluginsDirectory = PhGetStringSetting(L"PluginsDirectory");
if (RtlDetermineDosPathNameType_U(PhGetString(pluginsDirectory)) == RtlPathTypeRelative)
{
PluginsDirectoryPath = PhConcatStrings(
4,
PhGetString(PhGetApplicationDirectory()),
L"\\",
PhGetStringOrEmpty(pluginsDirectory),
L"\\"
);
PhDereferenceObject(pluginsDirectory);
}
else
{
PluginsDirectoryPath = pluginsDirectory;
}
if (NT_SUCCESS(PhCreateFileWin32(
&pluginsDirectoryHandle,
PhGetStringOrEmpty(PluginsDirectoryPath),
FILE_GENERIC_READ,
0,
FILE_SHARE_READ,
FILE_OPEN,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
)))
{
PhEnumDirectoryFile(
pluginsDirectoryHandle,
&pluginsPattern,
PluginsCleanupDirectoryCallback,
PluginsDirectoryPath
);
NtClose(pluginsDirectoryHandle);
}
}
VOID NTAPI LoadCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_LIST pluginArgvList = Parameter;
if (pluginArgvList)
{
for (ULONG i = 0; i < pluginArgvList->Count; i++)
{
PPH_STRING pluginCommandParam = pluginArgvList->Items[i];
if (PhEqualString2(pluginCommandParam, L"INSTALL", TRUE))
{
//PPH_STRING directory;
//PPH_STRING path;
//
//directory = PH_AUTO(PhGetApplicationDirectory());
//path = PhaCreateString(L"\\plugins");
//path = PH_AUTO(PhConcatStringRef2(&directory->sr, &path->sr));
//
//if (MoveFileWithProgress(
// L"new.plugin",
// path->Buffer,
// NULL,
// NULL,
// MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING
// ))
//{
//
//}
NtTerminateProcess(NtCurrentProcess(), EXIT_SUCCESS);
}
else if (PhEqualString2(pluginCommandParam, L"UNINSTALL", TRUE))
{
NtTerminateProcess(NtCurrentProcess(), EXIT_SUCCESS);
}
}
}
else
{
PluginsCleanup();
}
}
VOID NTAPI MainMenuInitializingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
PPH_EMENU_ITEM pluginMenu;
if (menuInfo->u.MainMenu.SubMenuIndex != 0)
return;
if (pluginMenu = PhFindEMenuItem(menuInfo->Menu, PH_EMENU_FIND_DESCEND, NULL, PHAPP_ID_HACKER_PLUGINS))
{
PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, 0, pluginMenu->Id, L"Plugins... (Beta)", NULL), PhIndexOfEMenuItem(menuInfo->Menu, pluginMenu));
PhRemoveEMenuItem(menuInfo->Menu, pluginMenu, 0);
}
}
VOID NTAPI MenuItemCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_ITEM menuItem = Parameter;
switch (menuItem->Id)
{
case PHAPP_ID_HACKER_PLUGINS:
ShowPluginManagerDialog();
break;
}
}
LOGICAL DllMain(
_In_ HINSTANCE Instance,
_In_ ULONG Reason,
_Reserved_ PVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
{
PPH_PLUGIN_INFORMATION info;
PH_SETTING_CREATE settings[] =
{
{ StringSettingType, SETTING_NAME_TREE_LIST_COLUMNS, L"" },
{ StringSettingType, SETTING_NAME_LAST_CLEANUP, L"" },
{ IntegerPairSettingType, SETTING_NAME_WINDOW_POSITION, L"100,100" },
{ ScalableIntegerPairSettingType, SETTING_NAME_WINDOW_SIZE, L"@96|690,540" }
};
PluginInstance = PhRegisterPlugin(SETTING_PREFIX, Instance, &info);
if (!PluginInstance)
return FALSE;
info->DisplayName = L"Extra Plugins Manager";
info->Author = L"dmex";
info->Description = L"Process Hacker plugins from the community.";
info->HasOptions = FALSE;
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
LoadCallback,
NULL,
&PluginLoadCallbackRegistration
);
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackMainMenuInitializing),
MainMenuInitializingCallback,
NULL,
&MainMenuInitializingCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
MenuItemCallback,
NULL,
&PluginMenuItemCallbackRegistration
);
PhAddSettings(settings, ARRAYSIZE(settings));
}
break;
}
return TRUE;
}

View File

@ -0,0 +1,418 @@
/*
* Process Hacker Extra Plugins -
* Plugin Manager
*
* Copyright (C) 2013 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WCT_H_
#define _WCT_H_
#define CINTERFACE
#define COBJMACROS
#include <phdk.h>
#include <phappresource.h>
#include <mxml.h>
#include <verify.h>
#include <workqueue.h>
#include <shlobj.h>
#include <Shellapi.h>
#include <psapi.h>
#include <winhttp.h>
#include <windowsx.h>
#include <uxtheme.h>
#include "resource.h"
#include "json-c/json.h"
#define IDD_WCT_MENUITEM 1000
#define PH_UPDATEISERRORED (WM_APP + 501)
#define PH_UPDATEAVAILABLE (WM_APP + 502)
#define PH_UPDATEISCURRENT (WM_APP + 503)
#define PH_UPDATENEWER (WM_APP + 504)
#define PH_UPDATESUCCESS (WM_APP + 505)
#define PH_UPDATEFAILURE (WM_APP + 506)
#define WM_SHOWDIALOG (WM_APP + 550)
#define WM_ACTION (WM_APP + 1550)
#define ID_WCTSHOWCONTEXTMENU 19584
#define SETTING_PREFIX L"dmex.ExtraPlugins"
#define SETTING_NAME_TREE_LIST_COLUMNS (SETTING_PREFIX L".TreeListColumns")
#define SETTING_NAME_WINDOW_POSITION (SETTING_PREFIX L".WindowPosition")
#define SETTING_NAME_WINDOW_SIZE (SETTING_PREFIX L".WindowSize")
#define SETTING_NAME_LAST_CLEANUP (SETTING_PREFIX L".LastCleanupCheckTime")
#define ID_SEARCH_CLEAR (WM_APP + 8001)
#define ID_UPDATE_ADD (WM_APP + 8002)
#define ID_UPDATE_COUNT (WM_APP + 8003)
#define MAKE_VERSION_ULONGLONG(major, minor, build, revision) \
(((ULONGLONG)(major) << 48) | \
((ULONGLONG)(minor) << 32) | \
((ULONGLONG)(build) << 16) | \
((ULONGLONG)(revision) << 0))
#define ITEM_CHECKED (INDEXTOSTATEIMAGEMASK(2))
#define ITEM_UNCHECKED (INDEXTOSTATEIMAGEMASK(1))
extern PPH_PLUGIN PluginInstance;
typedef enum _TREE_PLUGIN_STATE
{
PLUGIN_STATE_LOCAL,
PLUGIN_STATE_RESTART,
PLUGIN_STATE_REMOTE,
PLUGIN_STATE_UPDATE,
} TREE_PLUGIN_STATE;
typedef enum _WCT_TREE_COLUMN_ITEM_NAME
{
TREE_COLUMN_ITEM_NAME,
TREE_COLUMN_ITEM_AUTHOR,
TREE_COLUMN_ITEM_VERSION,
TREE_COLUMN_ITEM_MAXIMUM
} WCT_TREE_COLUMN_ITEM_NAME;
typedef struct _PHAPP_PLUGIN
{
// Public
PH_AVL_LINKS Links;
PVOID Reserved;
PVOID DllBase;
// end
// Private
PPH_STRING FileName;
ULONG Flags;
PH_STRINGREF Name;
PH_PLUGIN_INFORMATION Information;
PH_CALLBACK Callbacks[PluginCallbackMaximum];
} PHAPP_PLUGIN, *PPHAPP_PLUGIN;
typedef struct _PLUGIN_NODE
{
PH_TREENEW_NODE Node;
HICON Icon;
TREE_PLUGIN_STATE State;
BOOLEAN PluginOptions;
PPHAPP_PLUGIN PluginInstance;
// Local
PPH_STRING FilePath;
PPH_STRING InternalName;
// Remote
PPH_STRING Id;
PPH_STRING Visible;
PPH_STRING Name;
PPH_STRING Version;
PPH_STRING Author;
PPH_STRING Description;
PPH_STRING IconUrl;
PPH_STRING Requirements;
PPH_STRING FeedbackUrl;
PPH_STRING Screenshots;
PPH_STRING AddedTime;
PPH_STRING UpdatedTime;
PPH_STRING Download_count;
PPH_STRING Download_link_32;
PPH_STRING Download_link_64;
PPH_STRING SHA2_32;
PPH_STRING SHA2_64;
PPH_STRING HASH_32;
PPH_STRING HASH_64;
PPH_STRING FileName;
PH_STRINGREF TextCache[TREE_COLUMN_ITEM_MAXIMUM];
} PLUGIN_NODE, *PPLUGIN_NODE;
typedef struct _WCT_TREE_CONTEXT
{
HWND ParentWindowHandle;
HWND TreeNewHandle;
ULONG TreeNewSortColumn;
PH_SORT_ORDER TreeNewSortOrder;
PPH_HASHTABLE NodeHashtable;
PPH_LIST NodeList;
HFONT TitleFontHandle;
HFONT NormalFontHandle;
HFONT BoldFontHandle;
} WCT_TREE_CONTEXT, *PWCT_TREE_CONTEXT;
// dialog.c
VOID ShowPluginManagerDialog(VOID);
// disabled.c
VOID ShowDisabledPluginsDialog(_In_ HWND Parent);
typedef struct _PLUGIN_DISABLED_CONTEXT
{
PH_QUEUED_LOCK ListLock;
HWND DialogHandle;
HWND ListViewHandle;
PH_LAYOUT_MANAGER LayoutManager;
} PLUGIN_DISABLED_CONTEXT, *PPLUGIN_DISABLED_CONTEXT;
ULONG PhDisabledPluginsCount(VOID);
// plugin.c
PWSTR PhGetPluginBaseName(_In_ PPHAPP_PLUGIN Plugin);
BOOLEAN PhIsPluginLoadedByBaseName(_In_ PPH_STRINGREF BaseName);
BOOLEAN PhIsPluginDisabled(_In_ PPH_STRINGREF BaseName);
VOID PhSetPluginDisabled(_In_ PPH_STRINGREF BaseName, _In_ BOOLEAN Disable);
VOID WtcInitializeWindowTree(
_In_ HWND ParentWindowHandle,
_In_ HWND TreeNewHandle,
_Out_ PWCT_TREE_CONTEXT Context
);
VOID WtcDeleteWindowTree(
_In_ PWCT_TREE_CONTEXT Context
);
struct _PH_TN_FILTER_SUPPORT* WtcGetTreeListFilterSupport(
VOID
);
VOID CloudAddChildWindowNode(
_In_ PWCT_TREE_CONTEXT Context,
_In_ PPLUGIN_NODE Entry
);
PPLUGIN_NODE WeAddWindowNode(
_Inout_ PWCT_TREE_CONTEXT Context
);
PPLUGIN_NODE FindTreeNode(
_In_ PWCT_TREE_CONTEXT Context,
_In_ TREE_PLUGIN_STATE Type,
_In_ PPH_STRING InternalName
);
VOID WeRemoveWindowNode(
_In_ PWCT_TREE_CONTEXT Context,
_In_ PPLUGIN_NODE WindowNode
);
VOID WeClearWindowTree(
_In_ PWCT_TREE_CONTEXT Context
);
PPLUGIN_NODE WeGetSelectedWindowNode(
_In_ PWCT_TREE_CONTEXT Context
);
VOID WeGetSelectedWindowNodes(
_In_ PWCT_TREE_CONTEXT Context,
_Out_ PPLUGIN_NODE **Windows,
_Out_ PULONG NumberOfWindows
);
typedef struct _WCT_CONTEXT
{
HWND DialogHandle;
HWND SearchHandle;
HWND TreeNewHandle;
PPH_STRING SearchboxText;
PPH_STRING TreeText;
HFONT NormalFontHandle;
HFONT BoldFontHandle;
TREE_PLUGIN_STATE Type;
HWND PluginMenuActive;
UINT PluginMenuActiveId;
WCT_TREE_CONTEXT TreeContext;
PPH_TN_FILTER_SUPPORT TreeFilter;
PH_LAYOUT_MANAGER LayoutManager;
} WCT_CONTEXT, *PWCT_CONTEXT;
NTSTATUS QueryPluginsCallbackThread(_In_ PVOID Parameter);
VOID EnumerateLoadedPlugins(_In_ PWCT_CONTEXT Context);
typedef enum _PLUGIN_ACTION
{
PLUGIN_ACTION_RESTORE,
PLUGIN_ACTION_INSTALL,
PLUGIN_ACTION_UNINSTALL,
PLUGIN_ACTION_RESTART
} PLUGIN_ACTION;
typedef struct _PH_UPDATER_CONTEXT
{
BOOLEAN FixedWindowStyles;
HWND DialogHandle;
HICON IconSmallHandle;
HICON IconLargeHandle;
PLUGIN_ACTION Action;
PPLUGIN_NODE Node;
PPH_STRING FileDownloadUrl;
PPH_STRING RevVersion;
PPH_STRING Size;
PPH_STRING SetupFilePath;
} PH_UPDATER_CONTEXT, *PPH_UPDATER_CONTEXT;
BOOLEAN ShowUpdateDialog(
_In_ HWND Parent,
_In_ PLUGIN_ACTION Action
);
BOOLEAN StartInitialCheck(
_In_ HWND Parent,
_In_ PPLUGIN_NODE Node,
_In_ PLUGIN_ACTION Action
);
VOID ShowAvailableDialog(_In_ PPH_UPDATER_CONTEXT Context);
VOID ShowCheckForUpdatesDialog(_In_ PPH_UPDATER_CONTEXT Context);
VOID ShowCheckingForUpdatesDialog(_In_ PPH_UPDATER_CONTEXT Context);
VOID TaskDialogLinkClicked(_In_ PPH_UPDATER_CONTEXT Context);
NTSTATUS UpdateDownloadThread(_In_ PVOID Parameter);
// page1.c
VOID ShowCheckForUpdatesDialog(_In_ PPH_UPDATER_CONTEXT Context);
// page2.c
VOID ShowCheckingForUpdatesDialog(_In_ PPH_UPDATER_CONTEXT Context);
// page3.c
VOID ShowAvailableDialog(_In_ PPH_UPDATER_CONTEXT Context);
// page4.c
VOID ShowProgressDialog(_In_ PPH_UPDATER_CONTEXT Context);
VOID ShowLatestVersionDialog(_In_ PPH_UPDATER_CONTEXT Context);
VOID ShowPluginUninstallDialog(_In_ PPH_UPDATER_CONTEXT Context);
VOID ShowUpdateFailedDialog(
_In_ PPH_UPDATER_CONTEXT Context,
_In_ BOOLEAN HashFailed,
_In_ BOOLEAN SignatureFailed
);
// page6.c
VOID ShowInstallRestartDialog(_In_ PPH_UPDATER_CONTEXT Context);
VOID ShowUninstallRestartDialog(_In_ PPH_UPDATER_CONTEXT Context);
NTSTATUS SetupExtractBuild(_In_ PVOID Parameter);
// verify.c
typedef struct _UPDATER_HASH_CONTEXT
{
BCRYPT_ALG_HANDLE SignAlgHandle;
BCRYPT_ALG_HANDLE HashAlgHandle;
BCRYPT_KEY_HANDLE KeyHandle;
BCRYPT_HASH_HANDLE HashHandle;
ULONG HashObjectSize;
ULONG HashSize;
PVOID HashObject;
PVOID Hash;
} UPDATER_HASH_CONTEXT, *PUPDATER_HASH_CONTEXT;
BOOLEAN UpdaterInitializeHash(
_Out_ PUPDATER_HASH_CONTEXT *Context
);
BOOLEAN UpdaterUpdateHash(
_Inout_ PUPDATER_HASH_CONTEXT Context,
_In_reads_bytes_(Length) PVOID Buffer,
_In_ ULONG Length
);
BOOLEAN UpdaterVerifyHash(
_Inout_ PUPDATER_HASH_CONTEXT Context,
_In_ PPH_STRING Sha2Hash
);
BOOLEAN UpdaterVerifySignature(
_Inout_ PUPDATER_HASH_CONTEXT Context,
_In_ PPH_STRING HexSignature
);
VOID UpdaterDestroyHash(
_Inout_ PUPDATER_HASH_CONTEXT Context
);
VOID CreateSearchControl(
_In_ HWND Parent,
_In_ HWND WindowHandle,
_In_ UINT CommandID
);
typedef struct _EDIT_CONTEXT
{
UINT CommandID;
union
{
ULONG Flags;
struct
{
ULONG Hot : 1;
ULONG Pushed : 1;
ULONG Spare : 30;
};
};
LONG CXWidth;
INT CXBorder;
INT ImageWidth;
INT ImageHeight;
HWND WindowHandle;
HFONT WindowFont;
HIMAGELIST ImageList;
HBITMAP BitmapActive;
HBITMAP BitmapInactive;
HBRUSH BrushNormal;
HBRUSH BrushPushed;
HBRUSH BrushHot;
} EDIT_CONTEXT, *PEDIT_CONTEXT;
HBITMAP LoadImageFromResources(
_In_ UINT Width,
_In_ UINT Height,
_In_ PCWSTR Name,
_In_ BOOLEAN RGBAImage
);
LRESULT SysButtonCustomDraw(
_In_ PWCT_CONTEXT Context,
_In_ LPARAM lParam
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,785 @@
#ifndef MINIZ_HEADER_INCLUDED
#define MINIZ_HEADER_INCLUDED
#include <stdlib.h>
// Defines to completely disable specific portions of miniz.c:
// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl.
// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O.
//#define MINIZ_NO_STDIO
// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or
// get/set file times, and the C run-time funcs that get/set times won't be called.
// The current downside is the times written to your archives will be from 1979.
//#define MINIZ_NO_TIME
// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's.
//#define MINIZ_NO_ARCHIVE_APIS
// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's.
//#define MINIZ_NO_ARCHIVE_WRITING_APIS
// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's.
//#define MINIZ_NO_ZLIB_APIS
// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib.
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc
// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user
// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
//#define MINIZ_NO_MALLOC
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
#include <time.h>
#endif
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__)
// MINIZ_X86_OR_X64_CPU is only used to help set the below macros.
#define MINIZ_X86_OR_X64_CPU 1
#endif
#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
#define MINIZ_LITTLE_ENDIAN 1
#endif
#if MINIZ_X86_OR_X64_CPU
// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses.
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
#endif
#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
#define MINIZ_HAS_64BIT_REGISTERS 1
#endif
// ------------------- Types and macros
typedef unsigned char mz_uint8;
typedef signed short mz_int16;
typedef unsigned short mz_uint16;
typedef unsigned int mz_uint32;
typedef unsigned int mz_uint;
typedef long long mz_int64;
typedef unsigned long long mz_uint64;
typedef int mz_bool;
#define MZ_FALSE (0)
#define MZ_TRUE (1)
// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message.
#ifdef _MSC_VER
#define MZ_MACRO_END while (0, 0)
#else
#define MZ_MACRO_END while (0)
#endif
// ------------------- zlib-style API Definitions.
// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits!
typedef unsigned long mz_ulong;
// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap.
void mz_free(void *p);
#define MZ_ADLER32_INIT (1)
// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL.
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
#define MZ_CRC32_INIT (0)
// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL.
mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
// Compression strategies.
enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 };
// Method
#define MZ_DEFLATED 8
#ifndef MINIZ_NO_ZLIB_APIS
// Heap allocation callbacks.
// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long.
typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
typedef void(*mz_free_func)(void *opaque, void *address);
typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
#define MZ_VERSION "9.1.15"
#define MZ_VERNUM 0x91F0
#define MZ_VER_MAJOR 9
#define MZ_VER_MINOR 1
#define MZ_VER_REVISION 15
#define MZ_VER_SUBREVISION 0
// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs).
enum
{
MZ_NO_FLUSH = 0,
MZ_PARTIAL_FLUSH = 1,
MZ_SYNC_FLUSH = 2,
MZ_FULL_FLUSH = 3,
MZ_FINISH = 4,
MZ_BLOCK = 5
};
// Return status codes. MZ_PARAM_ERROR is non-standard.
enum
{
MZ_OK = 0,
MZ_STREAM_END = 1,
MZ_NEED_DICT = 2,
MZ_ERRNO = -1,
MZ_STREAM_ERROR = -2,
MZ_DATA_ERROR = -3,
MZ_MEM_ERROR = -4,
MZ_BUF_ERROR = -5,
MZ_VERSION_ERROR = -6,
MZ_PARAM_ERROR = -10000
};
// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL.
enum
{
MZ_NO_COMPRESSION = 0,
MZ_BEST_SPEED = 1,
MZ_BEST_COMPRESSION = 9,
MZ_UBER_COMPRESSION = 10,
MZ_DEFAULT_LEVEL = 6,
MZ_DEFAULT_COMPRESSION = -1
};
// Window bits
#define MZ_DEFAULT_WINDOW_BITS 15
struct mz_internal_state;
// Compression/decompression stream struct.
typedef struct mz_stream_s
{
const unsigned char *next_in; // pointer to next byte to read
unsigned int avail_in; // number of bytes available at next_in
mz_ulong total_in; // total number of bytes consumed so far
unsigned char *next_out; // pointer to next byte to write
unsigned int avail_out; // number of bytes that can be written to next_out
mz_ulong total_out; // total number of bytes produced so far
char *msg; // error msg (unused)
struct mz_internal_state *state; // internal state, allocated by zalloc/zfree
mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc)
mz_free_func zfree; // optional heap free function (defaults to free)
void *opaque; // heap alloc function user pointer
int data_type; // data_type (unused)
mz_ulong adler; // adler32 of the source or uncompressed data
mz_ulong reserved; // not used
} mz_stream;
typedef mz_stream *mz_streamp;
// Returns the version string of miniz.c.
const char *mz_version(void);
// mz_deflateInit() initializes a compressor with default options:
// Parameters:
// pStream must point to an initialized mz_stream struct.
// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION].
// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio.
// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.)
// Return values:
// MZ_OK on success.
// MZ_STREAM_ERROR if the stream is bogus.
// MZ_PARAM_ERROR if the input parameters are bogus.
// MZ_MEM_ERROR on out of memory.
int mz_deflateInit(mz_streamp pStream, int level);
// mz_deflateInit2() is like mz_deflate(), except with more control:
// Additional parameters:
// method must be MZ_DEFLATED
// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer)
// mem_level must be between [1, 9] (it's checked but ignored by miniz.c)
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2().
int mz_deflateReset(mz_streamp pStream);
// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible.
// Parameters:
// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH.
// Return values:
// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full).
// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore.
// MZ_STREAM_ERROR if the stream is bogus.
// MZ_PARAM_ERROR if one of the parameters is invalid.
// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.)
int mz_deflate(mz_streamp pStream, int flush);
// mz_deflateEnd() deinitializes a compressor:
// Return values:
// MZ_OK on success.
// MZ_STREAM_ERROR if the stream is bogus.
int mz_deflateEnd(mz_streamp pStream);
// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH.
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
// Single-call compression functions mz_compress() and mz_compress2():
// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure.
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress().
mz_ulong mz_compressBound(mz_ulong source_len);
// Initializes a decompressor.
int mz_inflateInit(mz_streamp pStream);
// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer:
// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate).
int mz_inflateInit2(mz_streamp pStream, int window_bits);
// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible.
// Parameters:
// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members.
// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH.
// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster).
// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data.
// Return values:
// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full.
// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified.
// MZ_STREAM_ERROR if the stream is bogus.
// MZ_DATA_ERROR if the deflate stream is invalid.
// MZ_PARAM_ERROR if one of the parameters is invalid.
// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
// with more input data, or with more room in the output buffer (except when using single call decompression, described above).
int mz_inflate(mz_streamp pStream, int flush);
// Deinitializes a decompressor.
int mz_inflateEnd(mz_streamp pStream);
// Single-call decompression.
// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure.
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
// Returns a string description of the specified error code, or NULL if the error code is invalid.
const char *mz_error(int err);
// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports.
// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project.
#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
typedef unsigned char Byte;
typedef unsigned int uInt;
typedef mz_ulong uLong;
typedef Byte Bytef;
typedef uInt uIntf;
typedef char charf;
typedef int intf;
typedef void *voidpf;
typedef uLong uLongf;
typedef void *voidp;
typedef void *const voidpc;
#define Z_NULL 0
#define Z_NO_FLUSH MZ_NO_FLUSH
#define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
#define Z_SYNC_FLUSH MZ_SYNC_FLUSH
#define Z_FULL_FLUSH MZ_FULL_FLUSH
#define Z_FINISH MZ_FINISH
#define Z_BLOCK MZ_BLOCK
#define Z_OK MZ_OK
#define Z_STREAM_END MZ_STREAM_END
#define Z_NEED_DICT MZ_NEED_DICT
#define Z_ERRNO MZ_ERRNO
#define Z_STREAM_ERROR MZ_STREAM_ERROR
#define Z_DATA_ERROR MZ_DATA_ERROR
#define Z_MEM_ERROR MZ_MEM_ERROR
#define Z_BUF_ERROR MZ_BUF_ERROR
#define Z_VERSION_ERROR MZ_VERSION_ERROR
#define Z_PARAM_ERROR MZ_PARAM_ERROR
#define Z_NO_COMPRESSION MZ_NO_COMPRESSION
#define Z_BEST_SPEED MZ_BEST_SPEED
#define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
#define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
#define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
#define Z_FILTERED MZ_FILTERED
#define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
#define Z_RLE MZ_RLE
#define Z_FIXED MZ_FIXED
#define Z_DEFLATED MZ_DEFLATED
#define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
#define alloc_func mz_alloc_func
#define free_func mz_free_func
#define internal_state mz_internal_state
#define z_stream mz_stream
#define deflateInit mz_deflateInit
#define deflateInit2 mz_deflateInit2
#define deflateReset mz_deflateReset
#define deflate mz_deflate
#define deflateEnd mz_deflateEnd
#define deflateBound mz_deflateBound
#define compress mz_compress
#define compress2 mz_compress2
#define compressBound mz_compressBound
#define inflateInit mz_inflateInit
#define inflateInit2 mz_inflateInit2
#define inflate mz_inflate
#define inflateEnd mz_inflateEnd
#define uncompress mz_uncompress
#define crc32 mz_crc32
#define adler32 mz_adler32
#define MAX_WBITS 15
#define MAX_MEM_LEVEL 9
#define zError mz_error
#define ZLIB_VERSION MZ_VERSION
#define ZLIB_VERNUM MZ_VERNUM
#define ZLIB_VER_MAJOR MZ_VER_MAJOR
#define ZLIB_VER_MINOR MZ_VER_MINOR
#define ZLIB_VER_REVISION MZ_VER_REVISION
#define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
#define zlibVersion mz_version
#define zlib_version mz_version()
#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
#endif // MINIZ_NO_ZLIB_APIS
// ------------------- ZIP archive reading/writing
#ifndef MINIZ_NO_ARCHIVE_APIS
enum
{
MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024,
MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260,
MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256
};
typedef struct _mz_zip_archive_file_stat
{
mz_uint32 m_file_index;
mz_uint32 m_central_dir_ofs;
mz_uint16 m_version_made_by;
mz_uint16 m_version_needed;
mz_uint16 m_bit_flag;
mz_uint16 m_method;
#ifndef MINIZ_NO_TIME
time_t m_time;
#endif
mz_uint32 m_crc32;
mz_uint64 m_comp_size;
mz_uint64 m_uncomp_size;
mz_uint16 m_internal_attr;
mz_uint32 m_external_attr;
mz_uint64 m_local_header_ofs;
mz_uint32 m_comment_size;
char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
} mz_zip_archive_file_stat;
typedef size_t(*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
typedef size_t(*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n);
struct mz_zip_internal_state_tag;
typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
typedef enum _mz_zip_mode
{
MZ_ZIP_MODE_INVALID = 0,
MZ_ZIP_MODE_READING = 1,
MZ_ZIP_MODE_WRITING = 2,
MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
} mz_zip_mode;
typedef struct _mz_zip_archive
{
mz_uint64 m_archive_size;
mz_uint64 m_central_directory_file_ofs;
mz_uint m_total_files;
mz_zip_mode m_zip_mode;
mz_uint m_file_offset_alignment;
mz_alloc_func m_pAlloc;
mz_free_func m_pFree;
mz_realloc_func m_pRealloc;
void *m_pAlloc_opaque;
mz_file_read_func m_pRead;
mz_file_write_func m_pWrite;
void *m_pIO_opaque;
mz_zip_internal_state *m_pState;
} mz_zip_archive;
typedef enum _mz_zip_flags
{
MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
} mz_zip_flags;
// ZIP archive reading
// Inits a ZIP archive reader.
// These functions read and validate the archive's central directory.
mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags);
mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags);
#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const wchar_t *pFilename, mz_uint32 flags);
#endif
// Returns the total number of files in the archive.
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
// Returns detailed information about an archive file entry.
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
// Determines if an archive file entry is a directory entry.
mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
// Retrieves the filename of an archive file entry.
// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename.
mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
// Attempts to locates a file in the archive's central directory.
// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH
// Returns -1 if the file cannot be found.
int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
// Extracts a archive file to a memory buffer using no memory allocation.
mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
// Extracts a archive file to a memory buffer.
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
// Extracts a archive file to a dynamically allocated heap buffer.
void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
// Extracts a archive file using a callback function to output the file's data.
mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
#ifndef MINIZ_NO_STDIO
// Extracts a archive file to a disk file and sets its last accessed and modified times.
// This function only extracts files, not archive directory records.
mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const wchar_t *pDst_filename, mz_uint flags);
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const wchar_t *pDst_filename, mz_uint flags);
#endif
// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used.
mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
// ZIP archive writing
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
// Inits a ZIP archive writer.
mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const wchar_t *pFilename, mz_uint64 size_to_reserve_at_beginning);
#endif
// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive.
// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called.
// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it).
// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL.
// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before
// the archive is finalized the file's central directory will be hosed.
mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const wchar_t *pFilename);
// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive.
// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer.
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
#ifndef MINIZ_NO_STDIO
// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive.
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const wchar_t *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
#endif
// Adds a file to an archive by fully cloning the data from another archive.
// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields.
mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index);
// Finalizes the archive by writing the central directory records followed by the end of central directory record.
// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end().
// An archive must be manually finalized by calling this function for it to be valid.
mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize);
// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used.
// Note for the archive to be valid, it must have been finalized before ending.
mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
// Misc. high-level helper functions:
// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive.
// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
mz_bool mz_zip_add_mem_to_archive_file_in_place(const wchar_t *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
// Reads a single file from an archive into a heap block.
// Returns NULL on failure.
void *mz_zip_extract_archive_file_to_heap(const wchar_t *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags);
#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
#endif // #ifndef MINIZ_NO_ARCHIVE_APIS
// ------------------- Low-level Decompression API Definitions
// Decompression flags used by tinfl_decompress().
// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
enum
{
TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
TINFL_FLAG_HAS_MORE_INPUT = 2,
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
TINFL_FLAG_COMPUTE_ADLER32 = 8
};
// High level decompression functions:
// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
// On entry:
// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
// On return:
// Function returns a pointer to the decompressed data, or NULL on failure.
// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
// The caller must call mz_free() on the returned block when it's no longer needed.
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
// Returns 1 on success or 0 on failure.
typedef int(*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
// Max size of LZ dictionary.
#define TINFL_LZ_DICT_SIZE 32768
// Return status.
typedef enum
{
TINFL_STATUS_BAD_PARAM = -3,
TINFL_STATUS_ADLER32_MISMATCH = -2,
TINFL_STATUS_FAILED = -1,
TINFL_STATUS_DONE = 0,
TINFL_STATUS_NEEDS_MORE_INPUT = 1,
TINFL_STATUS_HAS_MORE_OUTPUT = 2
} tinfl_status;
// Initializes the decompressor to its initial state.
#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
#define tinfl_get_adler32(r) (r)->m_check_adler32
// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
// Internal/private bits follow.
enum
{
TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
};
typedef struct
{
mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
} tinfl_huff_table;
#if MINIZ_HAS_64BIT_REGISTERS
#define TINFL_USE_64BIT_BITBUF 1
#endif
#if TINFL_USE_64BIT_BITBUF
typedef mz_uint64 tinfl_bit_buf_t;
#define TINFL_BITBUF_SIZE (64)
#else
typedef mz_uint32 tinfl_bit_buf_t;
#define TINFL_BITBUF_SIZE (32)
#endif
struct tinfl_decompressor_tag
{
mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
tinfl_bit_buf_t m_bit_buf;
size_t m_dist_from_out_buf_start;
tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
};
// ------------------- Low-level Compression API Definitions
// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently).
#define TDEFL_LESS_MEMORY 0
// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search):
// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression).
enum
{
TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF
};
// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data.
// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers).
// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing.
// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory).
// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled.
// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables.
// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks.
// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK).
enum
{
TDEFL_WRITE_ZLIB_HEADER = 0x01000,
TDEFL_COMPUTE_ADLER32 = 0x02000,
TDEFL_GREEDY_PARSING_FLAG = 0x04000,
TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
TDEFL_RLE_MATCHES = 0x10000,
TDEFL_FILTER_MATCHES = 0x20000,
TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
};
// High level compression functions:
// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc().
// On entry:
// pSrc_buf, src_buf_len: Pointer and size of source block to compress.
// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression.
// On return:
// Function returns a pointer to the compressed data, or NULL on failure.
// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data.
// The caller must free() the returned block when it's no longer needed.
void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory.
// Returns 0 on failure.
size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
// Compresses an image to a compressed PNG file in memory.
// On entry:
// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4.
// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory.
// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL
// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps).
// On return:
// Function returns a pointer to the compressed data, or NULL on failure.
// *pLen_out will be set to the size of the PNG image file.
// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
typedef mz_bool(*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally.
mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 };
// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes).
#if TDEFL_LESS_MEMORY
enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
#else
enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS };
#endif
// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions.
typedef enum
{
TDEFL_STATUS_BAD_PARAM = -2,
TDEFL_STATUS_PUT_BUF_FAILED = -1,
TDEFL_STATUS_OKAY = 0,
TDEFL_STATUS_DONE = 1,
} tdefl_status;
// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums
typedef enum
{
TDEFL_NO_FLUSH = 0,
TDEFL_SYNC_FLUSH = 2,
TDEFL_FULL_FLUSH = 3,
TDEFL_FINISH = 4
} tdefl_flush;
// tdefl's compression state structure.
typedef struct
{
tdefl_put_buf_func_ptr m_pPut_buf_func;
void *m_pPut_buf_user;
mz_uint m_flags, m_max_probes[2];
int m_greedy_parsing;
mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer;
mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish;
tdefl_status m_prev_return_status;
const void *m_pIn_buf;
void *m_pOut_buf;
size_t *m_pIn_buf_size, *m_pOut_buf_size;
tdefl_flush m_flush;
const mz_uint8 *m_pSrc;
size_t m_src_buf_left, m_out_buf_ofs;
mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
} tdefl_compressor;
// Initializes the compressor.
// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory.
// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression.
// If pBut_buf_func is NULL the user should always call the tdefl_compress() API.
// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.)
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible.
tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr.
// tdefl_compress_buffer() always consumes the entire input buffer.
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros.
#ifndef MINIZ_NO_ZLIB_APIS
// Create tdefl_compress() flags given zlib-style compression parameters.
// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files)
// window_bits may be -15 (raw deflate) or 15 (zlib)
// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
#endif // #ifndef MINIZ_NO_ZLIB_APIS
#endif // MINIZ_HEADER_INCLUDED

View File

@ -0,0 +1,211 @@
#include "main.h"
ULONG PhDisabledPluginsCount(
VOID
)
{
PPH_STRING disabled;
PH_STRINGREF remainingPart;
PH_STRINGREF part;
ULONG count = 0;
disabled = PhGetStringSetting(L"DisabledPlugins");
remainingPart = disabled->sr;
while (remainingPart.Length)
{
PhSplitStringRefAtChar(&remainingPart, '|', &part, &remainingPart);
if (part.Length)
{
count++;
}
}
PhDereferenceObject(disabled);
return count;
}
// Copied from Process Hacker, plugin.c
PWSTR PhGetPluginBaseName(
_In_ PPHAPP_PLUGIN Plugin
)
{
if (Plugin->FileName)
{
PH_STRINGREF pathNamePart;
PH_STRINGREF baseNamePart;
if (PhSplitStringRefAtLastChar(&Plugin->FileName->sr, '\\', &pathNamePart, &baseNamePart))
return baseNamePart.Buffer;
else
return Plugin->FileName->Buffer;
}
else
{
// Fake disabled plugin.
return Plugin->Name.Buffer;
}
}
BOOLEAN PhIsPluginLoadedByBaseName(
_In_ PPH_STRINGREF BaseName
)
{
PPH_AVL_LINKS root;
PPH_AVL_LINKS links;
root = PluginInstance->Links.Parent;
while (root)
{
if (!root->Parent)
break;
root = root->Parent;
}
for (
links = PhMinimumElementAvlTree((PPH_AVL_TREE)root);
links;
links = PhSuccessorElementAvlTree(links)
)
{
PPHAPP_PLUGIN plugin = CONTAINING_RECORD(links, PHAPP_PLUGIN, Links);
PH_STRINGREF pluginBaseName;
PhInitializeStringRefLongHint(&pluginBaseName, PhGetPluginBaseName(plugin));
if (PhEqualStringRef(&pluginBaseName, BaseName, TRUE))
return TRUE;
}
return FALSE;
}
BOOLEAN PhpLocateDisabledPlugin(
_In_ PPH_STRING List,
_In_ PPH_STRINGREF BaseName,
_Out_opt_ PULONG FoundIndex
)
{
PH_STRINGREF namePart;
PH_STRINGREF remainingPart;
remainingPart = List->sr;
while (remainingPart.Length != 0)
{
PhSplitStringRefAtChar(&remainingPart, '|', &namePart, &remainingPart);
if (PhEqualStringRef(&namePart, BaseName, TRUE))
{
if (FoundIndex)
*FoundIndex = (ULONG)(namePart.Buffer - List->Buffer);
return TRUE;
}
}
return FALSE;
}
BOOLEAN PhIsPluginDisabled(
_In_ PPH_STRINGREF BaseName
)
{
BOOLEAN found;
PPH_STRING disabled;
disabled = PhGetStringSetting(L"DisabledPlugins");
found = PhpLocateDisabledPlugin(disabled, BaseName, NULL);
PhDereferenceObject(disabled);
return found;
}
VOID PhSetPluginDisabled(
_In_ PPH_STRINGREF BaseName,
_In_ BOOLEAN Disable
)
{
BOOLEAN found;
PPH_STRING disabled;
ULONG foundIndex;
PPH_STRING newDisabled;
disabled = PhGetStringSetting(L"DisabledPlugins");
found = PhpLocateDisabledPlugin(disabled, BaseName, &foundIndex);
if (Disable && !found)
{
// We need to add the plugin to the disabled list.
if (disabled->Length != 0)
{
// We have other disabled plugins. Append a pipe character followed by the plugin name.
newDisabled = PhCreateStringEx(NULL, disabled->Length + sizeof(WCHAR) + BaseName->Length);
memcpy(newDisabled->Buffer, disabled->Buffer, disabled->Length);
newDisabled->Buffer[disabled->Length / 2] = '|';
memcpy(&newDisabled->Buffer[disabled->Length / 2 + 1], BaseName->Buffer, BaseName->Length);
PhSetStringSetting2(L"DisabledPlugins", &newDisabled->sr);
PhDereferenceObject(newDisabled);
}
else
{
// This is the first disabled plugin.
PhSetStringSetting2(L"DisabledPlugins", BaseName);
}
}
else if (!Disable && found)
{
ULONG removeCount;
// We need to remove the plugin from the disabled list.
removeCount = (ULONG)BaseName->Length / 2;
if (foundIndex + (ULONG)BaseName->Length / 2 < (ULONG)disabled->Length / 2)
{
// Remove the following pipe character as well.
removeCount++;
}
else if (foundIndex != 0)
{
// Remove the preceding pipe character as well.
foundIndex--;
removeCount++;
}
newDisabled = PhCreateStringEx(NULL, disabled->Length - removeCount * sizeof(WCHAR));
memcpy(newDisabled->Buffer, disabled->Buffer, foundIndex * sizeof(WCHAR));
memcpy(&newDisabled->Buffer[foundIndex], &disabled->Buffer[foundIndex + removeCount],
disabled->Length - removeCount * sizeof(WCHAR) - foundIndex * sizeof(WCHAR));
PhSetStringSetting2(L"DisabledPlugins", &newDisabled->sr);
PhDereferenceObject(newDisabled);
}
PhDereferenceObject(disabled);
}
PPHAPP_PLUGIN PhCreateDisabledPlugin(
_In_ PPH_STRINGREF BaseName
)
{
PPHAPP_PLUGIN plugin;
plugin = PhAllocate(sizeof(PHAPP_PLUGIN));
memset(plugin, 0, sizeof(PHAPP_PLUGIN));
plugin->Name.Length = BaseName->Length;
plugin->Name.Buffer = PhAllocate(BaseName->Length + sizeof(WCHAR));
memcpy(plugin->Name.Buffer, BaseName->Buffer, BaseName->Length);
plugin->Name.Buffer[BaseName->Length / 2] = 0;
return plugin;
}

View File

@ -0,0 +1,38 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ExtraPlugins.rc
//
#define IDD_PLUGINS_DIALOG 102
#define IDB_SEARCH_ACTIVE_BMP 105
#define IDB_SEARCH_ACTIVE 106
#define IDB_SEARCH_INACTIVE_BMP 107
#define IDB_SEARCH_INACTIVE 108
#define IDD_DIALOG1 111
#define IDD_DISABLED_DIALOG 111
#define IDB_SETTINGS 113
#define IDB_SETTINGS_PNG 113
#define IDC_PLUGINTREE 1001
#define IDC_INSTALLED 1036
#define IDC_BROWSE 1037
#define IDC_UPDATES 1038
#define IDC_DISABLED 1039
#define IDC_LIST_DISABLED 1046
#define IDC_CLEANUP 1057
#define ID_MENU_INSTALL 4059
#define ID_MENU_UNINSTALL 40011
#define ID_MENU_DISABLE 40012
#define ID_MENU_PROPERTIES 40013
#define ID_MENU_UNLOAD 40014
#define IDC_INSTRUCTION 40025
#define IDC_SEARCHBOX 40026
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 114
#define _APS_NEXT_COMMAND_VALUE 40028
#define _APS_NEXT_CONTROL_VALUE 1047
#define _APS_NEXT_SYMED_VALUE 104
#endif
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

View File

@ -0,0 +1,666 @@
/*/*
* Process Hacker -
* Subclassed Edit control
*
* Copyright (C) 2012-2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "main.h"
#include <uxtheme.h>
#include <vssym32.h>
#include <Wincodec.h>
VOID NcAreaFreeTheme(
_Inout_ PEDIT_CONTEXT Context
)
{
if (Context->BrushNormal)
DeleteObject(Context->BrushNormal);
if (Context->BrushHot)
DeleteObject(Context->BrushHot);
if (Context->BrushPushed)
DeleteObject(Context->BrushPushed);
}
VOID NcAreaInitializeFont(
_Inout_ PEDIT_CONTEXT Context
)
{
LOGFONT logFont;
if (Context->WindowFont)
DeleteObject(Context->WindowFont);
if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &logFont, 0))
{
Context->WindowFont = CreateFont(
-PhMultiplyDivideSigned(-14, PhGlobalDpi, 72),
0,
0,
0,
FW_MEDIUM,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
DEFAULT_PITCH,
logFont.lfFaceName
);
SendMessage(Context->WindowHandle, WM_SETFONT, (WPARAM)Context->WindowFont, TRUE);
}
}
VOID NcAreaInitializeTheme(
_Inout_ PEDIT_CONTEXT Context
)
{
Context->CXWidth = PhMultiplyDivide(20, PhGlobalDpi, 96);
Context->BrushNormal = GetSysColorBrush(COLOR_WINDOW);
Context->BrushHot = CreateSolidBrush(RGB(205, 232, 255));
Context->BrushPushed = CreateSolidBrush(RGB(153, 209, 255));
if (IsThemeActive())
{
HTHEME themeDataHandle;
if (themeDataHandle = OpenThemeData(Context->WindowHandle, VSCLASS_EDIT))
{
//IsThemePartDefined_I(themeDataHandle, EP_EDITBORDER_NOSCROLL, EPSHV_NORMAL);
if (!SUCCEEDED(GetThemeInt(
themeDataHandle,
EP_EDITBORDER_NOSCROLL,
EPSHV_NORMAL,
TMT_BORDERSIZE,
&Context->CXBorder
)))
{
Context->CXBorder = GetSystemMetrics(SM_CXBORDER) * 2;
}
CloseThemeData(themeDataHandle);
}
else
{
Context->CXBorder = GetSystemMetrics(SM_CXBORDER) * 2;
}
}
else
{
Context->CXBorder = GetSystemMetrics(SM_CXBORDER) * 2;
}
}
VOID NcAreaInitializeImageList(
_Inout_ PEDIT_CONTEXT Context
)
{
HBITMAP bitmapActive;
HBITMAP bitmapInactive;
Context->ImageWidth = GetSystemMetrics(SM_CXSMICON) + 4;
Context->ImageHeight = GetSystemMetrics(SM_CYSMICON) + 4;
Context->ImageList = ImageList_Create(16, 16, ILC_COLOR32, 2, 2);
ImageList_SetImageCount(Context->ImageList, 2);
if (bitmapActive = LoadImageFromResources(Context->ImageWidth, Context->ImageHeight, MAKEINTRESOURCE(IDB_SEARCH_ACTIVE), TRUE))
{
ImageList_Replace(Context->ImageList, 0, bitmapActive, NULL);
DeleteObject(bitmapActive);
}
else
{
PhSetImageListBitmap(Context->ImageList, 0, PluginInstance->DllBase, MAKEINTRESOURCE(IDB_SEARCH_ACTIVE_BMP));
}
if (bitmapInactive = LoadImageFromResources(Context->ImageWidth, Context->ImageHeight, MAKEINTRESOURCE(IDB_SEARCH_INACTIVE), TRUE))
{
ImageList_Replace(Context->ImageList, 1, bitmapInactive, NULL);
DeleteObject(bitmapInactive);
}
else
{
PhSetImageListBitmap(Context->ImageList, 1, PluginInstance->DllBase, MAKEINTRESOURCE(IDB_SEARCH_INACTIVE_BMP));
}
}
VOID NcAreaGetButtonRect(
_Inout_ PEDIT_CONTEXT Context,
_Inout_ PRECT ButtonRect
)
{
ButtonRect->left = (ButtonRect->right - Context->CXWidth) - Context->CXBorder - 1; // offset left border by 1
ButtonRect->bottom -= Context->CXBorder;
ButtonRect->right -= Context->CXBorder;
ButtonRect->top += Context->CXBorder;
}
VOID NcAreaDrawButton(
_Inout_ PEDIT_CONTEXT Context,
_In_ RECT ButtonRect
)
{
HDC hdc;
HDC bufferDc;
HBITMAP bufferBitmap;
HBITMAP oldBufferBitmap;
RECT bufferRect =
{
0, 0,
ButtonRect.right - ButtonRect.left,
ButtonRect.bottom - ButtonRect.top
};
if (!(hdc = GetWindowDC(Context->WindowHandle)))
return;
bufferDc = CreateCompatibleDC(hdc);
bufferBitmap = CreateCompatibleBitmap(hdc, bufferRect.right, bufferRect.bottom);
oldBufferBitmap = SelectObject(bufferDc, bufferBitmap);
if (Context->Pushed)
{
FillRect(bufferDc, &bufferRect, Context->BrushPushed);
//FrameRect(bufferDc, &bufferRect, CreateSolidBrush(RGB(0xff, 0, 0)));
}
else if (Context->Hot)
{
FillRect(bufferDc, &bufferRect, Context->BrushHot);
//FrameRect(bufferDc, &bufferRect, CreateSolidBrush(RGB(38, 160, 218)));
}
else
{
FillRect(bufferDc, &bufferRect, Context->BrushNormal);
}
if (Edit_GetTextLength(Context->WindowHandle) > 0)
{
ImageList_Draw(
Context->ImageList,
0,
bufferDc,
bufferRect.left + ((bufferRect.right - bufferRect.left) - Context->ImageWidth) / 2 + 1, // offset by one
bufferRect.top + ((bufferRect.bottom - bufferRect.top) - Context->ImageHeight) / 2 + 1, // offset by one
ILD_NORMAL | ILD_TRANSPARENT
);
}
else
{
ImageList_Draw(
Context->ImageList,
1,
bufferDc,
bufferRect.left + ((bufferRect.right - bufferRect.left) - (Context->ImageWidth - 2)) / 2, // offset by one
bufferRect.top + ((bufferRect.bottom - bufferRect.top) - (Context->ImageHeight - 2)) / 2 + 1, // offset by one
ILD_NORMAL | ILD_TRANSPARENT
);
}
BitBlt(hdc, ButtonRect.left, ButtonRect.top, ButtonRect.right, ButtonRect.bottom, bufferDc, 0, 0, SRCCOPY);
SelectObject(bufferDc, oldBufferBitmap);
DeleteObject(bufferBitmap);
DeleteDC(bufferDc);
ReleaseDC(Context->WindowHandle, hdc);
}
LRESULT CALLBACK NcAreaWndSubclassProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ UINT_PTR uIdSubclass,
_In_ ULONG_PTR dwRefData
)
{
PEDIT_CONTEXT context;
context = (PEDIT_CONTEXT)GetProp(hWnd, L"SearchBoxContext");
switch (uMsg)
{
case WM_NCDESTROY:
{
NcAreaFreeTheme(context);
if (context->ImageList)
ImageList_Destroy(context->ImageList);
if (context->WindowFont)
DeleteObject(context->WindowFont);
RemoveWindowSubclass(hWnd, NcAreaWndSubclassProc, uIdSubclass);
RemoveProp(hWnd, L"SearchBoxContext");
PhFree(context);
}
break;
case WM_ERASEBKGND:
return 1;
case WM_NCCALCSIZE:
{
LPNCCALCSIZE_PARAMS ncCalcSize = (NCCALCSIZE_PARAMS*)lParam;
// Let Windows handle the non-client defaults.
DefSubclassProc(hWnd, uMsg, wParam, lParam);
// Deflate the client area to accommodate the custom button.
ncCalcSize->rgrc[0].right -= context->CXWidth;
}
return 0;
case WM_NCPAINT:
{
RECT windowRect;
// Let Windows handle the non-client defaults.
DefSubclassProc(hWnd, uMsg, wParam, lParam);
// Get the screen coordinates of the window.
GetWindowRect(hWnd, &windowRect);
// Adjust the coordinates (start from 0,0).
OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
// Get the position of the inserted button.
NcAreaGetButtonRect(context, &windowRect);
// Draw the button.
NcAreaDrawButton(context, windowRect);
}
return 0;
case WM_NCHITTEST:
{
POINT windowPoint;
RECT windowRect;
// Get the screen coordinates of the mouse.
if (!GetCursorPos(&windowPoint))
break;
// Get the screen coordinates of the window.
GetWindowRect(hWnd, &windowRect);
// Get the position of the inserted button.
NcAreaGetButtonRect(context, &windowRect);
// Check that the mouse is within the inserted button.
if (PtInRect(&windowRect, windowPoint))
{
return HTBORDER;
}
}
break;
case WM_NCLBUTTONDOWN:
{
POINT windowPoint;
RECT windowRect;
// Get the screen coordinates of the mouse.
if (!GetCursorPos(&windowPoint))
break;
// Get the screen coordinates of the window.
GetWindowRect(hWnd, &windowRect);
// Get the position of the inserted button.
NcAreaGetButtonRect(context, &windowRect);
// Check that the mouse is within the inserted button.
if (PtInRect(&windowRect, windowPoint))
{
context->Pushed = TRUE;
SetCapture(hWnd);
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
}
}
break;
case WM_LBUTTONUP:
{
POINT windowPoint;
RECT windowRect;
// Get the screen coordinates of the mouse.
if (!GetCursorPos(&windowPoint))
break;
// Get the screen coordinates of the window.
GetWindowRect(hWnd, &windowRect);
// Get the position of the inserted button.
NcAreaGetButtonRect(context, &windowRect);
// Check that the mouse is within the inserted button.
if (PtInRect(&windowRect, windowPoint))
{
// Forward click notification.
SendMessage(GetParent(context->WindowHandle), WM_COMMAND, MAKEWPARAM(context->CommandID, BN_CLICKED), 0);
}
if (GetCapture() == hWnd)
{
context->Pushed = FALSE;
ReleaseCapture();
}
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
}
break;
case WM_CUT:
case WM_CLEAR:
case WM_PASTE:
case WM_UNDO:
case WM_KEYUP:
case WM_SETTEXT:
case WM_KILLFOCUS:
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
break;
case WM_SETTINGCHANGE:
case WM_SYSCOLORCHANGE:
case WM_THEMECHANGED:
{
NcAreaFreeTheme(context);
NcAreaInitializeTheme(context);
NcAreaInitializeFont(context);
// Reset the client area margins.
SendMessage(hWnd, EM_SETMARGINS, EC_LEFTMARGIN, MAKELPARAM(0, 0));
// Refresh the non-client area.
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
// Force the edit control to update its non-client area.
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
}
break;
case WM_NCMOUSEMOVE:
{
POINT windowPoint;
RECT windowRect;
// Get the screen coordinates of the mouse.
if (!GetCursorPos(&windowPoint))
break;
// Get the screen coordinates of the window.
GetWindowRect(hWnd, &windowRect);
// Get the position of the inserted button.
NcAreaGetButtonRect(context, &windowRect);
// Check that the mouse is within the inserted button.
if (PtInRect(&windowRect, windowPoint) && !context->Hot)
{
TRACKMOUSEEVENT trackMouseEvent;
trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
trackMouseEvent.dwFlags = TME_LEAVE | TME_NONCLIENT;
trackMouseEvent.hwndTrack = hWnd;
trackMouseEvent.dwHoverTime = 0;
context->Hot = TRUE;
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
TrackMouseEvent(&trackMouseEvent);
}
}
break;
case WM_NCMOUSELEAVE:
{
if (context->Hot)
{
context->Hot = FALSE;
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
}
}
break;
case WM_MOUSEMOVE:
{
if ((wParam & MK_LBUTTON) && GetCapture() == hWnd)
{
POINT windowPoint;
RECT windowRect;
// Get the screen coordinates of the mouse.
if (!GetCursorPos(&windowPoint))
break;
// Get the screen coordinates of the window.
GetWindowRect(hWnd, &windowRect);
// Get the position of the inserted button.
NcAreaGetButtonRect(context, &windowRect);
// Check that the mouse is within the inserted button.
context->Pushed = PtInRect(&windowRect, windowPoint);
RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
}
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
HBITMAP LoadImageFromResources(
_In_ UINT Width,
_In_ UINT Height,
_In_ PCWSTR Name,
_In_ BOOLEAN RGBAImage
)
{
UINT frameCount = 0;
BOOLEAN success = FALSE;
ULONG resourceLength = 0;
HGLOBAL resourceHandle = NULL;
HRSRC resourceHandleSource = NULL;
WICInProcPointer resourceBuffer = NULL;
HDC screenHdc = NULL;
HDC bufferDc = NULL;
BITMAPINFO bitmapInfo = { 0 };
HBITMAP bitmapHandle = NULL;
PBYTE bitmapBuffer = NULL;
IWICStream* wicStream = NULL;
IWICBitmapSource* wicBitmapSource = NULL;
IWICBitmapDecoder* wicDecoder = NULL;
IWICBitmapFrameDecode* wicFrame = NULL;
IWICImagingFactory* wicFactory = NULL;
IWICBitmapScaler* wicScaler = NULL;
WICPixelFormatGUID pixelFormat;
WICRect rect = { 0, 0, Width, Height };
// Create the ImagingFactory
if (FAILED(CoCreateInstance(&CLSID_WICImagingFactory1, NULL, CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, &wicFactory)))
goto CleanupExit;
if ((resourceHandleSource = FindResource(PluginInstance->DllBase, Name, L"PNG")) == NULL)
goto CleanupExit;
resourceLength = SizeofResource(PluginInstance->DllBase, resourceHandleSource);
if ((resourceHandle = LoadResource(PluginInstance->DllBase, resourceHandleSource)) == NULL)
goto CleanupExit;
if ((resourceBuffer = (WICInProcPointer)LockResource(resourceHandle)) == NULL)
goto CleanupExit;
if (FAILED(IWICImagingFactory_CreateStream(wicFactory, &wicStream)))
goto CleanupExit;
if (FAILED(IWICStream_InitializeFromMemory(wicStream, resourceBuffer, resourceLength)))
goto CleanupExit;
if (FAILED(IWICImagingFactory_CreateDecoder(wicFactory, &GUID_ContainerFormatPng, NULL, &wicDecoder)))
goto CleanupExit;
if (FAILED(IWICBitmapDecoder_Initialize(wicDecoder, (IStream*)wicStream, WICDecodeMetadataCacheOnLoad)))
goto CleanupExit;
if (FAILED(IWICBitmapDecoder_GetFrameCount(wicDecoder, &frameCount)) || frameCount < 1)
goto CleanupExit;
if (FAILED(IWICBitmapDecoder_GetFrame(wicDecoder, 0, &wicFrame)))
goto CleanupExit;
if (FAILED(IWICBitmapFrameDecode_GetPixelFormat(wicFrame, &pixelFormat)))
goto CleanupExit;
// Check if the image format is supported
if (IsEqualGUID(&pixelFormat, RGBAImage ? &GUID_WICPixelFormat32bppPRGBA : &GUID_WICPixelFormat32bppPBGRA))
{
wicBitmapSource = (IWICBitmapSource*)wicFrame;
}
else
{
IWICFormatConverter* wicFormatConverter = NULL;
if (FAILED(IWICImagingFactory_CreateFormatConverter(wicFactory, &wicFormatConverter)))
goto CleanupExit;
if (FAILED(IWICFormatConverter_Initialize(
wicFormatConverter,
(IWICBitmapSource*)wicFrame,
RGBAImage ? &GUID_WICPixelFormat32bppPRGBA : &GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.0,
WICBitmapPaletteTypeCustom
)))
{
IWICFormatConverter_Release(wicFormatConverter);
goto CleanupExit;
}
// Convert the image to the correct format
IWICFormatConverter_QueryInterface(wicFormatConverter, &IID_IWICBitmapSource, &wicBitmapSource);
IWICFormatConverter_Release(wicFormatConverter);
// Dispose the old frame now that the converted frame is in wicBitmapSource
IWICBitmapFrameDecode_Release(wicFrame);
}
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = rect.Width;
bitmapInfo.bmiHeader.biHeight = -((LONG)rect.Height);
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
screenHdc = CreateIC(L"DISPLAY", NULL, NULL, NULL);
bufferDc = CreateCompatibleDC(screenHdc);
bitmapHandle = CreateDIBSection(screenHdc, &bitmapInfo, DIB_RGB_COLORS, (PVOID*)&bitmapBuffer, NULL, 0);
// Check if it's the same rect as the requested size.
//if (width != rect.Width || height != rect.Height)
if (FAILED(IWICImagingFactory_CreateBitmapScaler(wicFactory, &wicScaler)))
goto CleanupExit;
if (FAILED(IWICBitmapScaler_Initialize(wicScaler, wicBitmapSource, rect.Width, rect.Height, WICBitmapInterpolationModeFant)))
goto CleanupExit;
if (FAILED(IWICBitmapScaler_CopyPixels(wicScaler, &rect, rect.Width * 4, rect.Width * rect.Height * 4, bitmapBuffer)))
goto CleanupExit;
success = TRUE;
CleanupExit:
// Cleanup resources in the same order they were created.
if (wicScaler)
{
IWICBitmapScaler_Release(wicScaler);
}
if (bufferDc)
{
DeleteDC(bufferDc);
}
if (screenHdc)
{
DeleteDC(screenHdc);
}
if (wicBitmapSource)
{
IWICBitmapSource_Release(wicBitmapSource);
}
if (wicStream)
{
IWICStream_Release(wicStream);
}
if (wicDecoder)
{
IWICBitmapDecoder_Release(wicDecoder);
}
if (wicFactory)
{
IWICImagingFactory_Release(wicFactory);
}
if (resourceHandle)
{
FreeResource(resourceHandle);
}
if (success)
return bitmapHandle;
DeleteObject(bitmapHandle);
return NULL;
}
VOID CreateSearchControl(
_In_ HWND Parent,
_In_ HWND WindowHandle,
_In_ UINT CommandID
)
{
PEDIT_CONTEXT context;
context = (PEDIT_CONTEXT)PhAllocate(sizeof(EDIT_CONTEXT));
memset(context, 0, sizeof(EDIT_CONTEXT));
context->CommandID = CommandID;
context->WindowHandle = WindowHandle;
//NcAreaInitializeTheme(context);
NcAreaInitializeImageList(context);
// Set initial text
Edit_SetCueBannerText(context->WindowHandle, L"Search Plugins (Ctrl+K)");
// Set our window context data.
SetProp(context->WindowHandle, L"SearchBoxContext", (HANDLE)context);
// Subclass the Edit control window procedure.
SetWindowSubclass(context->WindowHandle, NcAreaWndSubclassProc, 0, (ULONG_PTR)context);
// Initialize the theme parameters.
SendMessage(context->WindowHandle, WM_THEMECHANGED, 0, 0);
}

View File

@ -0,0 +1,82 @@
/*
* Process Hacker Plugins -
* Update Checker Plugin
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "..\main.h"
static TASKDIALOG_BUTTON TaskDialogButtonArray[] =
{
{ IDOK, L"Install" }
};
HRESULT CALLBACK CheckForUpdatesCallbackProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ LONG_PTR dwRefData
)
{
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData;
switch (uMsg)
{
case TDN_NAVIGATED:
break;
case TDN_BUTTON_CLICKED:
{
if ((INT)wParam == IDOK)
{
ShowCheckingForUpdatesDialog(context);
return S_FALSE;
}
}
break;
}
return S_OK;
}
VOID ShowCheckForUpdatesDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
TASKDIALOGCONFIG config;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_ENABLE_HYPERLINKS;
config.dwCommonButtons = TDCBF_CLOSE_BUTTON;
config.hMainIcon = Context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker";
config.pszMainInstruction = L"Install ABC??";
//config.pszContent = L"The updater will check for new Process Hacker releases and optionally download and install the update.\r\n\r\nClick the check for updates button to continue.";
config.pszContent = L"Name: ToolStatus.dll\r\nName: ToolStatus.dll\r\nName: ToolStatus.dll\r\nName: ToolStatus.dll\r\n\r\nClick the check for updates button to continue.";
config.cxWidth = 200;
config.pButtons = TaskDialogButtonArray;
config.cButtons = ARRAYSIZE(TaskDialogButtonArray);
config.pfCallback = CheckForUpdatesCallbackProc;
config.lpCallbackData = (LONG_PTR)Context;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}

View File

@ -0,0 +1,71 @@
/*
* Process Hacker Plugins -
* Update Checker Plugin
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "..\main.h"
HRESULT CALLBACK CheckingForUpdatesCallbackProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ LONG_PTR dwRefData
)
{
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData;
switch (uMsg)
{
case TDN_NAVIGATED:
{
SendMessage(hwndDlg, TDM_SET_MARQUEE_PROGRESS_BAR, TRUE, 0);
SendMessage(hwndDlg, TDM_SET_PROGRESS_BAR_MARQUEE, TRUE, 1);
//PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), UpdateCheckThread, context);
}
break;
}
return S_OK;
}
VOID ShowCheckingForUpdatesDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
TASKDIALOGCONFIG config;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_SHOW_MARQUEE_PROGRESS_BAR;
config.dwCommonButtons = TDCBF_CLOSE_BUTTON;
config.hMainIcon = Context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker";
//config.pszMainInstruction = L"Installing ToolStatus plugin";
config.pszContent = L"Checking plugin signature...";
config.cxWidth = 200;
config.pfCallback = CheckingForUpdatesCallbackProc;
config.lpCallbackData = (LONG_PTR)Context;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}

View File

@ -0,0 +1,100 @@
/*
* Process Hacker Plugins -
* Update Checker Plugin
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "..\main.h"
static TASKDIALOG_BUTTON TaskDialogButtonArray[] =
{
{ IDOK, L"Download" }
};
HRESULT CALLBACK ShowAvailableCallbackProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ LONG_PTR dwRefData
)
{
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData;
switch (uMsg)
{
case TDN_NAVIGATED:
break;
case TDN_BUTTON_CLICKED:
{
if ((INT)wParam == IDOK)
{
//if (UpdaterInstalledUsingSetup())
{
ShowProgressDialog(context);
return S_FALSE;
}
//else
{
//PhShellExecute(hwndDlg, L"https://wj32.org/processhacker/downloads.php", NULL);
}
}
}
break;
case TDN_HYPERLINK_CLICKED:
{
//TaskDialogLinkClicked(context);
}
break;
}
return S_OK;
}
VOID ShowAvailableDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
TASKDIALOGCONFIG config;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_ENABLE_HYPERLINKS | TDF_SHOW_PROGRESS_BAR;
config.dwCommonButtons = TDCBF_CANCEL_BUTTON;
config.hMainIcon = Context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker - Plugin Manager";
config.pszMainInstruction = PhIsNullOrEmptyString(Context->Node->Name) ? PhGetStringOrEmpty(Context->Node->InternalName) : PhGetStringOrEmpty(Context->Node->Name);
config.pszContent = PhaFormatString(L"%s\r\n\r\nAuthor: %s\r\nVersion: %s\r\nUpdated: %s",
PhGetStringOrEmpty(Context->Node->Description),
PhGetStringOrEmpty(Context->Node->Author),
PhGetStringOrEmpty(Context->Node->Version),
PhGetStringOrEmpty(Context->Node->UpdatedTime)
)->Buffer;
//config.pszExpandedInformation = L"<A HREF=\"executablestring\">View Changelog</A>";
config.cxWidth = 200;
config.pButtons = TaskDialogButtonArray;
config.cButtons = ARRAYSIZE(TaskDialogButtonArray);
config.lpCallbackData = (LONG_PTR)Context;
config.pfCallback = ShowAvailableCallbackProc;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}

View File

@ -0,0 +1,77 @@
/*
* Process Hacker Plugins -
* Update Checker Plugin
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "..\main.h"
HRESULT CALLBACK ShowProgressCallbackProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ LONG_PTR dwRefData
)
{
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData;
switch (uMsg)
{
case TDN_NAVIGATED:
{
SendMessage(hwndDlg, TDM_SET_MARQUEE_PROGRESS_BAR, TRUE, 0);
SendMessage(hwndDlg, TDM_SET_PROGRESS_BAR_MARQUEE, TRUE, 1);
PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), UpdateDownloadThread, context);
}
break;
case TDN_HYPERLINK_CLICKED:
{
TaskDialogLinkClicked(context);
}
break;
}
return S_OK;
}
VOID ShowProgressDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
TASKDIALOGCONFIG config;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_ENABLE_HYPERLINKS | TDF_SHOW_PROGRESS_BAR;
config.dwCommonButtons = TDCBF_CANCEL_BUTTON;
config.hMainIcon = Context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker - Plugin Manager";
config.pszMainInstruction = L"Downloading 0.0.0.0...";
config.pszContent = L"Downloaded: ~ of ~ (0%)\r\nSpeed: ~ KB/s";
//config.pszExpandedInformation = L"<A HREF=\"executablestring\">View Changelog</A>";
config.cxWidth = 200;
config.lpCallbackData = (LONG_PTR)Context;
config.pfCallback = ShowProgressCallbackProc;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}

View File

@ -0,0 +1,227 @@
/*
* Process Hacker Plugins -
* Update Checker Plugin
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "..\main.h"
#include <shellapi.h>
#include <shlobj.h>
static TASKDIALOG_BUTTON TaskDialogButtonArray[] =
{
{ IDYES, L"Restart" }
};
HRESULT CALLBACK RestartTaskDialogCallbackProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ LONG_PTR dwRefData
)
{
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData;
switch (uMsg)
{
case TDN_BUTTON_CLICKED:
{
if ((INT)wParam == IDYES)
{
SHELLEXECUTEINFO info = { sizeof(SHELLEXECUTEINFO) };
/* if (PhIsNullOrEmptyString(context->SetupFilePath))
break;*/
info.lpFile = L"ProcessHacker.exe";
info.nShow = SW_SHOW;
info.hwnd = hwndDlg;
//info.lpParameters = L"-plugin dmex.ExtraPlugins:INSTALL -plugin dmex.ExtraPlugins:hex64value";
ProcessHacker_PrepareForEarlyShutdown(PhMainWndHandle);
if (ShellExecuteEx(&info))
{
NtTerminateProcess(NtCurrentProcess(), STATUS_SUCCESS);
}
else
{
// Install failed, cancel the shutdown
ProcessHacker_CancelEarlyShutdown(PhMainWndHandle);
// Set button text for next action
//Button_SetText(GetDlgItem(hwndDlg, IDOK), L"Retry");
return S_FALSE;
}
}
}
break;
}
return S_OK;
}
HRESULT CALLBACK FinalTaskDialogCallbackProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ LONG_PTR dwRefData
)
{
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData;
switch (uMsg)
{
case TDN_NAVIGATED:
{
if (!PhGetOwnTokenAttributes().Elevated)
{
SendMessage(hwndDlg, TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, IDYES, TRUE);
}
}
break;
case TDN_BUTTON_CLICKED:
break;
}
return S_OK;
}
VOID ShowInstallRestartDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
TASKDIALOGCONFIG config;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED;
config.dwCommonButtons = TDCBF_CLOSE_BUTTON;
config.hMainIcon = Context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker - Plugin Manager";
config.pszMainInstruction = L"Process Hacker needs to restart";
config.pszContent = L"Changes may require a restart to take effect...";
config.pButtons = TaskDialogButtonArray;
config.cButtons = ARRAYSIZE(TaskDialogButtonArray);
config.cxWidth = 200;
config.pfCallback = RestartTaskDialogCallbackProc;
config.lpCallbackData = (LONG_PTR)Context;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}
VOID ShowUninstallRestartDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
TASKDIALOGCONFIG config;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED;
config.dwCommonButtons = TDCBF_CLOSE_BUTTON;
config.hMainIcon = Context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker - Plugin Manager";
config.pszMainInstruction = L"Process Hacker needs to restart";
config.pszContent = L"Changes may require a restart to take effect...";
config.pButtons = TaskDialogButtonArray;
config.cButtons = ARRAYSIZE(TaskDialogButtonArray);
config.cxWidth = 200;
config.pfCallback = RestartTaskDialogCallbackProc;
config.lpCallbackData = (LONG_PTR)Context;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}
VOID ShowLatestVersionDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
PPH_UPDATER_CONTEXT context;
TASKDIALOGCONFIG config;
context = (PPH_UPDATER_CONTEXT)Context;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED | TDF_ENABLE_HYPERLINKS;
config.dwCommonButtons = TDCBF_CLOSE_BUTTON;
config.hMainIcon = context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker - Plugin Manager";
config.pszMainInstruction = L"You're running the latest version.";
//config.pszContent = PhaFormatString(
// L"Stable release build: v%lu.%lu.%lu\r\n\r\n<A HREF=\"executablestring\">View Changelog</A>",
// context->CurrentMajorVersion,
// context->CurrentMinorVersion,
// context->CurrentRevisionVersion
// )->Buffer;
config.cxWidth = 200;
config.pfCallback = FinalTaskDialogCallbackProc;
config.lpCallbackData = (LONG_PTR)Context;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}
VOID ShowUpdateFailedDialog(
_In_ PPH_UPDATER_CONTEXT Context,
_In_ BOOLEAN HashFailed,
_In_ BOOLEAN SignatureFailed
)
{
TASKDIALOGCONFIG config;
memset(&config, 0, sizeof(TASKDIALOGCONFIG));
config.cbSize = sizeof(TASKDIALOGCONFIG);
//config.pszMainIcon = MAKEINTRESOURCE(65529);
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED;
config.dwCommonButtons = TDCBF_CLOSE_BUTTON | TDCBF_RETRY_BUTTON;
config.hMainIcon = Context->IconLargeHandle;
config.pszWindowTitle = L"Process Hacker - Plugin Manager";
config.pszMainInstruction = L"Error downloading plugin files.";
if (SignatureFailed)
{
config.pszContent = L"Signature check failed. Click Retry to download the plugin again.";
}
else if (HashFailed)
{
config.pszContent = L"Hash check failed. Click Retry to download the plugin again.";
}
else
{
config.pszContent = L"Click Retry to download the plugin again.";
}
config.cxWidth = 200;
config.pfCallback = FinalTaskDialogCallbackProc;
config.lpCallbackData = (LONG_PTR)Context;
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}

View File

@ -0,0 +1,81 @@
#include "..\main.h"
#include <shellapi.h>
#include <shlobj.h>
static TASKDIALOG_BUTTON TaskDialogButtonArray[] =
{
{ IDYES, L"Uninstall" }
};
HRESULT CALLBACK TaskDialogUninstallCallbackProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ LONG_PTR dwRefData
)
{
PPH_UPDATER_CONTEXT context = (PPH_UPDATER_CONTEXT)dwRefData;
switch (uMsg)
{
case TDN_NAVIGATED:
{
//PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), SetupExtractBuild, context);
}
break;
case TDN_BUTTON_CLICKED:
{
if ((INT)wParam == IDYES)
{
PPH_STRING baseNameString;
PPH_STRING fileNameString;
PPH_STRING bakNameString;
context->Node->State = PLUGIN_STATE_RESTART;
fileNameString = PhGetFileName(context->Node->FilePath);
baseNameString = PhGetBaseName(context->Node->FilePath);
bakNameString = PhConcatStrings(2, PhGetString(fileNameString), L".bak");
if (RtlDoesFileExists_U(PhGetString(fileNameString)))
{
MoveFileEx(PhGetString(fileNameString), PhGetString(bakNameString), MOVEFILE_REPLACE_EXISTING);
}
PhDereferenceObject(bakNameString);
PhDereferenceObject(baseNameString);
PhDereferenceObject(fileNameString);
PostMessage(context->DialogHandle, PH_UPDATENEWER, 0, 0);
return S_FALSE;
}
}
break;
}
return S_OK;
}
VOID ShowPluginUninstallDialog(
_In_ PPH_UPDATER_CONTEXT Context
)
{
PPH_UPDATER_CONTEXT context;
TASKDIALOGCONFIG config = { sizeof(TASKDIALOGCONFIG) };
context = (PPH_UPDATER_CONTEXT)Context;
config.cxWidth = 200;
config.pszWindowTitle = L"Process Hacker - Plugin Manager";
config.pszMainInstruction = PhaFormatString(L"Uninstall %s?", PhIsNullOrEmptyString(Context->Node->Name) ? PhGetStringOrEmpty(Context->Node->InternalName) : PhGetStringOrEmpty(Context->Node->Name))->Buffer;
config.dwFlags = TDF_USE_HICON_MAIN | TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED;
config.dwCommonButtons = TDCBF_CLOSE_BUTTON;
config.hMainIcon = context->IconLargeHandle;
config.pfCallback = TaskDialogUninstallCallbackProc;
config.lpCallbackData = (LONG_PTR)Context;
config.pButtons = TaskDialogButtonArray;
config.cButtons = ARRAYSIZE(TaskDialogButtonArray);
SendMessage(Context->DialogHandle, TDM_NAVIGATE_PAGE, 0, (LPARAM)&config);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
#include "..\main.h"
static UCHAR ExtraPluginsPublicKey[] =
{
0x45, 0x43, 0x53, 0x31, 0x20, 0x00, 0x00, 0x00, 0x24, 0x33, 0x0F, 0x97,
0x6B, 0xBA, 0x8B, 0xDD, 0x18, 0x2F, 0x7A, 0xAC, 0x53, 0x8F, 0xE3, 0x2A,
0x30, 0xA8, 0x8A, 0x47, 0x12, 0x3A, 0x4D, 0xCB, 0x11, 0x6A, 0x7E, 0x61,
0x32, 0xEE, 0xF8, 0xE9, 0x6A, 0x9B, 0x85, 0x23, 0x9F, 0x08, 0xEB, 0xC3,
0x8C, 0x60, 0xFD, 0xDE, 0xD3, 0x73, 0xCB, 0xFE, 0x53, 0xF6, 0x08, 0xCB,
0xE6, 0xF9, 0x34, 0x4B, 0x14, 0x37, 0x17, 0x74, 0xAF, 0xFF, 0xCC, 0xAB
};
BOOLEAN UpdaterInitializeHash(
_Out_ PUPDATER_HASH_CONTEXT *Context
)
{
ULONG querySize;
PUPDATER_HASH_CONTEXT hashContext;
hashContext = PhAllocate(sizeof(UPDATER_HASH_CONTEXT));
memset(hashContext, 0, sizeof(UPDATER_HASH_CONTEXT));
if (!NT_SUCCESS(BCryptOpenAlgorithmProvider(
&hashContext->SignAlgHandle,
BCRYPT_ECDSA_P256_ALGORITHM,
NULL,
0
)))
{
goto error;
}
if (!NT_SUCCESS(BCryptImportKeyPair(
hashContext->SignAlgHandle,
NULL,
BCRYPT_ECCPUBLIC_BLOB,
&hashContext->KeyHandle,
ExtraPluginsPublicKey,
sizeof(ExtraPluginsPublicKey),
0
)))
{
goto error;
}
if (!NT_SUCCESS(BCryptOpenAlgorithmProvider(
&hashContext->HashAlgHandle,
BCRYPT_SHA256_ALGORITHM,
NULL,
0
)))
{
goto error;
}
if (!NT_SUCCESS(BCryptGetProperty(
hashContext->HashAlgHandle,
BCRYPT_OBJECT_LENGTH,
(PUCHAR)&hashContext->HashObjectSize,
sizeof(ULONG),
&querySize,
0
)))
{
goto error;
}
if (!NT_SUCCESS(BCryptGetProperty(
hashContext->HashAlgHandle,
BCRYPT_HASH_LENGTH,
(PUCHAR)&hashContext->HashSize,
sizeof(ULONG),
&querySize,
0
)))
{
goto error;
}
if (!(hashContext->HashObject = PhAllocate(hashContext->HashObjectSize)))
goto error;
if (!(hashContext->Hash = PhAllocate(hashContext->HashSize)))
goto error;
if (!NT_SUCCESS(BCryptCreateHash(
hashContext->HashAlgHandle,
&hashContext->HashHandle,
hashContext->HashObject,
hashContext->HashObjectSize,
NULL,
0,
0
)))
{
goto error;
}
*Context = hashContext;
return TRUE;
error:
UpdaterDestroyHash(hashContext);
return FALSE;
}
BOOLEAN UpdaterUpdateHash(
_Inout_ PUPDATER_HASH_CONTEXT Context,
_In_reads_bytes_(Length) PVOID Buffer,
_In_ ULONG Length
)
{
return NT_SUCCESS(BCryptHashData(Context->HashHandle, Buffer, Length, 0));
}
BOOLEAN UpdaterVerifyHash(
_Inout_ PUPDATER_HASH_CONTEXT Context,
_In_ PPH_STRING Sha2Hash
)
{
PPH_STRING sha2HexString;
// Compute the final hash.
if (!NT_SUCCESS(BCryptFinishHash(
Context->HashHandle,
Context->Hash,
Context->HashSize,
0
)))
{
return FALSE;
}
if (!(sha2HexString = PhBufferToHexString(Context->Hash, Context->HashSize)))
return FALSE;
if (!PhEqualString2(sha2HexString, PhGetStringOrEmpty(Sha2Hash), TRUE))
{
PhDereferenceObject(sha2HexString);
return FALSE;
}
PhDereferenceObject(sha2HexString);
return TRUE;
}
BOOLEAN UpdaterVerifySignature(
_Inout_ PUPDATER_HASH_CONTEXT Context,
_In_ PPH_STRING HexSignature
)
{
ULONG signatureLength;
PUCHAR signatureBuffer;
signatureLength = (ULONG)HexSignature->Length / sizeof(WCHAR) / 2;
signatureBuffer = PhAllocate(signatureLength);
if (!PhHexStringToBuffer(&HexSignature->sr, signatureBuffer))
{
PhFree(signatureBuffer);
return FALSE;
}
// Verify the signature.
if (!NT_SUCCESS(BCryptVerifySignature(
Context->KeyHandle,
NULL,
Context->Hash,
Context->HashSize,
signatureBuffer,
signatureLength,
0
)))
{
PhFree(signatureBuffer);
return FALSE;
}
PhFree(signatureBuffer);
return TRUE;
}
VOID UpdaterDestroyHash(
_Inout_ PUPDATER_HASH_CONTEXT Context
)
{
if (Context->HashAlgHandle)
BCryptCloseAlgorithmProvider(Context->HashAlgHandle, 0);
if (Context->SignAlgHandle)
BCryptCloseAlgorithmProvider(Context->SignAlgHandle, 0);
if (Context->HashHandle)
BCryptDestroyHash(Context->HashHandle);
if (Context->KeyHandle)
BCryptDestroyKey(Context->KeyHandle);
if (Context->HashObject)
PhFree(Context->HashObject);
if (Context->Hash)
PhFree(Context->Hash);
PhFree(Context);
}

View File

@ -0,0 +1,574 @@
/*
* Process Hacker Extra Plugins -
* Plugin Manager
*
* Copyright (C) 2016 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
static PH_TN_FILTER_SUPPORT FilterSupport;
BOOLEAN WepWindowNodeHashtableCompareFunction(
_In_ PVOID Entry1,
_In_ PVOID Entry2
);
ULONG WepWindowNodeHashtableHashFunction(
_In_ PVOID Entry
);
VOID WepDestroyWindowNode(
_In_ PPLUGIN_NODE WindowNode
);
BOOLEAN NTAPI WepWindowTreeNewCallback(
_In_ HWND hwnd,
_In_ PH_TREENEW_MESSAGE Message,
__in_opt PVOID Parameter1,
__in_opt PVOID Parameter2,
__in_opt PVOID Context
);
VOID WtcInitializeWindowTree(
_In_ HWND ParentWindowHandle,
_In_ HWND TreeNewHandle,
__out PWCT_TREE_CONTEXT Context
)
{
memset(Context, 0, sizeof(WCT_TREE_CONTEXT));
Context->NodeHashtable = PhCreateHashtable(
sizeof(PPLUGIN_NODE),
WepWindowNodeHashtableCompareFunction,
WepWindowNodeHashtableHashFunction,
100
);
Context->NodeList = PhCreateList(100);
Context->ParentWindowHandle = ParentWindowHandle;
Context->TreeNewHandle = TreeNewHandle;
PhSetControlTheme(TreeNewHandle, L"explorer");
LOGFONT logFont;
if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &logFont, 0))
{
Context->TitleFontHandle = CreateFont(
-PhMultiplyDivideSigned(-14, PhGlobalDpi, 72),
0,
0,
0,
FW_BOLD,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
DEFAULT_PITCH,
logFont.lfFaceName
);
Context->NormalFontHandle = CreateFont(
-PhMultiplyDivideSigned(-10, PhGlobalDpi, 72),
0,
0,
0,
FW_NORMAL,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
DEFAULT_PITCH,
logFont.lfFaceName
);
Context->BoldFontHandle = CreateFont(
-PhMultiplyDivideSigned(-12, PhGlobalDpi, 72),
0,
0,
0,
FW_SEMIBOLD,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
DEFAULT_PITCH,
logFont.lfFaceName
);
}
TreeNew_SetCallback(TreeNewHandle, WepWindowTreeNewCallback, Context);
TreeNew_SetRowHeight(TreeNewHandle, 48);
PhAddTreeNewColumnEx2(TreeNewHandle, TREE_COLUMN_ITEM_NAME, TRUE, L"Plugin", 80, PH_ALIGN_LEFT, TREE_COLUMN_ITEM_NAME, 0, TN_COLUMN_FLAG_CUSTOMDRAW);
PhAddTreeNewColumnEx2(TreeNewHandle, TREE_COLUMN_ITEM_AUTHOR, TRUE, L"Author", 80, PH_ALIGN_LEFT, TREE_COLUMN_ITEM_AUTHOR, 0, 0);
PhAddTreeNewColumnEx2(TreeNewHandle, TREE_COLUMN_ITEM_VERSION, TRUE, L"Version", 80, PH_ALIGN_CENTER, TREE_COLUMN_ITEM_VERSION, DT_CENTER, 0);
TreeNew_SetSort(TreeNewHandle, 0, NoSortOrder);
PPH_STRING settings = PhGetStringSetting(SETTING_NAME_TREE_LIST_COLUMNS);
PhCmLoadSettings(TreeNewHandle, &settings->sr);
PhDereferenceObject(settings);
PhInitializeTreeNewFilterSupport(&FilterSupport, TreeNewHandle, Context->NodeList);
}
VOID WtcDeleteWindowTree(
_In_ PWCT_TREE_CONTEXT Context
)
{
PPH_STRING settings = PhCmSaveSettings(Context->TreeNewHandle);
PhSetStringSetting2(SETTING_NAME_TREE_LIST_COLUMNS, &settings->sr);
PhDereferenceObject(settings);
for (ULONG i = 0; i < Context->NodeList->Count; i++)
{
WepDestroyWindowNode(Context->NodeList->Items[i]);
}
PhDereferenceObject(Context->NodeHashtable);
PhDereferenceObject(Context->NodeList);
}
struct _PH_TN_FILTER_SUPPORT* WtcGetTreeListFilterSupport(
VOID
)
{
return &FilterSupport;
}
BOOLEAN WepWindowNodeHashtableCompareFunction(
_In_ PVOID Entry1,
_In_ PVOID Entry2
)
{
PPLUGIN_NODE windowNode1 = *(PPLUGIN_NODE *)Entry1;
PPLUGIN_NODE windowNode2 = *(PPLUGIN_NODE *)Entry2;
return PhEqualString(windowNode1->InternalName, windowNode2->InternalName, TRUE);
}
ULONG WepWindowNodeHashtableHashFunction(
_In_ PVOID Entry
)
{
return PhHashStringRef(&(*(PPLUGIN_NODE*)Entry)->InternalName->sr, TRUE);
}
VOID CloudAddChildWindowNode(
_In_ PWCT_TREE_CONTEXT Context,
_In_ PPLUGIN_NODE Entry
)
{
PhInitializeTreeNewNode(&Entry->Node);
memset(Entry->TextCache, 0, sizeof(PH_STRINGREF) * TREE_COLUMN_ITEM_MAXIMUM);
Entry->Node.TextCache = Entry->TextCache;
Entry->Node.TextCacheSize = TREE_COLUMN_ITEM_MAXIMUM;
PhAddEntryHashtable(Context->NodeHashtable, &Entry);
PhAddItemList(Context->NodeList, Entry);
if (FilterSupport.NodeList)
{
Entry->Node.Visible = PhApplyTreeNewFiltersToNode(&FilterSupport, &Entry->Node);
}
}
PPLUGIN_NODE FindTreeNode(
_In_ PWCT_TREE_CONTEXT Context,
_In_ TREE_PLUGIN_STATE State,
_In_ PPH_STRING InternalName
)
{
for (ULONG i = 0; i < Context->NodeList->Count; i++)
{
PPLUGIN_NODE entry = Context->NodeList->Items[i];
if (entry->State == State && PhEqualString(entry->InternalName, InternalName, TRUE))
return entry;
}
/*PLUGIN_NODE lookupWindowNode;
PPLUGIN_NODE lookupWindowNodePtr = &lookupWindowNode;
PPLUGIN_NODE *windowNode;
lookupWindowNode.Type = Type;
lookupWindowNode.InternalName = InternalName;
windowNode = (PPLUGIN_NODE*)PhFindEntryHashtable(
Context->NodeHashtable,
&lookupWindowNodePtr
);
if (windowNode)
return *windowNode;
else*/
return NULL;
}
VOID WeRemoveWindowNode(
_In_ PWCT_TREE_CONTEXT Context,
_In_ PPLUGIN_NODE WindowNode
)
{
ULONG index = 0;
// Remove from hashtable/list and cleanup.
PhRemoveEntryHashtable(Context->NodeHashtable, &WindowNode);
if ((index = PhFindItemList(Context->NodeList, WindowNode)) != -1)
{
PhRemoveItemList(Context->NodeList, index);
}
WepDestroyWindowNode(WindowNode);
TreeNew_NodesStructured(Context->TreeNewHandle);
}
VOID WepDestroyWindowNode(
_In_ PPLUGIN_NODE WindowNode
)
{
//if (WindowNode->NameString)
// PhDereferenceObject(WindowNode->NameString);
//if (WindowNode->VersionString)
// PhDereferenceObject(WindowNode->VersionString);
//if (WindowNode->DescriptionString)
// PhDereferenceObject(WindowNode->DescriptionString);
//if (WindowNode->AuthorString)
// PhDereferenceObject(WindowNode->AuthorString);
PhDereferenceObject(WindowNode);
}
#define SORT_FUNCTION(Column) PmPoolTreeNewCompare##Column
#define BEGIN_SORT_FUNCTION(Column) static int __cdecl PmPoolTreeNewCompare##Column( \
_In_ void *_context, \
_In_ const void *_elem1, \
_In_ const void *_elem2 \
) \
{ \
PPLUGIN_NODE node1 = *(PPLUGIN_NODE *)_elem1; \
PPLUGIN_NODE node2 = *(PPLUGIN_NODE *)_elem2; \
int sortResult = 0;
#define END_SORT_FUNCTION \
if (sortResult == 0) \
sortResult = uintptrcmp((ULONG_PTR)node1->Node.Index, (ULONG_PTR)node2->Node.Index); \
\
return PhModifySort(sortResult, ((PWCT_TREE_CONTEXT)_context)->TreeNewSortOrder); \
}
BEGIN_SORT_FUNCTION(Name)
{
sortResult = PhCompareString(node1->Name, node2->Name, FALSE);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(Author)
{
sortResult = PhCompareString(node1->Author, node2->Author, FALSE);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(Version)
{
sortResult = PhCompareString(node1->Version, node2->Version, FALSE);
}
END_SORT_FUNCTION
BOOLEAN NTAPI WepWindowTreeNewCallback(
_In_ HWND hwnd,
_In_ PH_TREENEW_MESSAGE Message,
__in_opt PVOID Parameter1,
__in_opt PVOID Parameter2,
__in_opt PVOID Context
)
{
PWCT_TREE_CONTEXT context;
PPLUGIN_NODE node;
context = Context;
switch (Message)
{
case TreeNewGetChildren:
{
PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
node = (PPLUGIN_NODE)getChildren->Node;
if (!getChildren->Node)
{
static PVOID sortFunctions[] =
{
SORT_FUNCTION(Name),
SORT_FUNCTION(Author),
SORT_FUNCTION(Version),
//SORT_FUNCTION(PagedAlloc),
//SORT_FUNCTION(PagedFree),
//SORT_FUNCTION(PagedCurrent),
//SORT_FUNCTION(PagedTotal),
//SORT_FUNCTION(NonPagedAlloc),
//SORT_FUNCTION(NonPagedFree),
//SORT_FUNCTION(NonPagedCurrent),
//SORT_FUNCTION(NonPagedTotal),
};
int (__cdecl *sortFunction)(void *, const void *, const void *);
if (context->TreeNewSortColumn < TREE_COLUMN_ITEM_MAXIMUM)
sortFunction = sortFunctions[context->TreeNewSortColumn];
else
sortFunction = NULL;
if (sortFunction)
{
qsort_s(context->NodeList->Items, context->NodeList->Count, sizeof(PVOID), sortFunction, context);
}
getChildren->Children = (PPH_TREENEW_NODE *)context->NodeList->Items;
getChildren->NumberOfChildren = context->NodeList->Count;
}
}
return TRUE;
case TreeNewIsLeaf:
{
PPH_TREENEW_IS_LEAF isLeaf = (PPH_TREENEW_IS_LEAF)Parameter1;
node = (PPLUGIN_NODE)isLeaf->Node;
isLeaf->IsLeaf = TRUE;
}
return TRUE;
case TreeNewGetCellText:
{
PPH_TREENEW_GET_CELL_TEXT getCellText = (PPH_TREENEW_GET_CELL_TEXT)Parameter1;
node = (PPLUGIN_NODE)getCellText->Node;
switch (getCellText->Id)
{
case TREE_COLUMN_ITEM_NAME:
getCellText->Text = PhGetStringRef(node->Name);
break;
case TREE_COLUMN_ITEM_AUTHOR:
getCellText->Text = PhGetStringRef(node->Author);
break;
case TREE_COLUMN_ITEM_VERSION:
getCellText->Text = PhGetStringRef(node->Version);
break;
default:
return FALSE;
}
getCellText->Flags = TN_CACHE;
}
return TRUE;
case TreeNewGetNodeColor:
{
PPH_TREENEW_GET_NODE_COLOR getNodeColor = (PPH_TREENEW_GET_NODE_COLOR)Parameter1;
node = (PPLUGIN_NODE)getNodeColor->Node;
getNodeColor->Flags = TN_CACHE;
}
return TRUE;
case TreeNewSortChanged:
{
TreeNew_GetSort(hwnd, &context->TreeNewSortColumn, &context->TreeNewSortOrder);
TreeNew_NodesStructured(hwnd);
}
return TRUE;
case TreeNewKeyDown:
case TreeNewNodeExpanding:
return TRUE;
case TreeNewLeftDoubleClick:
{
SendMessage(context->ParentWindowHandle, WM_COMMAND, WM_ACTION, (LPARAM)context);
}
return TRUE;
case TreeNewContextMenu:
{
PPH_TREENEW_MOUSE_EVENT mouseEvent = (PPH_TREENEW_MOUSE_EVENT)Parameter1;
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_WCTSHOWCONTEXTMENU, MAKELONG(mouseEvent->Location.x, mouseEvent->Location.y));
}
return TRUE;
case TreeNewHeaderRightClick:
{
PH_TN_COLUMN_MENU_DATA data;
data.TreeNewHandle = hwnd;
data.MouseEvent = Parameter1;
data.DefaultSortColumn = 0;
data.DefaultSortOrder = AscendingSortOrder;
PhInitializeTreeNewColumnMenu(&data);
data.Selection = PhShowEMenu(data.Menu, hwnd, PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP, data.MouseEvent->ScreenLocation.x, data.MouseEvent->ScreenLocation.y);
PhHandleTreeNewColumnMenu(&data);
PhDeleteTreeNewColumnMenu(&data);
}
return TRUE;
case TreeNewCustomDraw:
{
PPH_TREENEW_CUSTOM_DRAW customDraw = Parameter1;
RECT rect = customDraw->CellRect;
node = (PPLUGIN_NODE)customDraw->Node;
switch (customDraw->Column->Id)
{
case TREE_COLUMN_ITEM_NAME:
{
PH_STRINGREF text;
SIZE nameSize;
SIZE textSize;
if (node->PluginOptions)
{
if (!node->Icon)
{
HBITMAP bitmapActive;
bitmapActive = LoadImageFromResources(17, 17, MAKEINTRESOURCE(IDB_SETTINGS_PNG), TRUE);
if (bitmapActive)
{
HDC screenDc;
HBITMAP screenBitmap;
ICONINFO iconInfo = { TRUE };
screenDc = CreateIC(L"DISPLAY", NULL, NULL, NULL);
screenBitmap = CreateCompatibleBitmap(screenDc, 17, 17);
iconInfo.hbmColor = bitmapActive;
iconInfo.hbmMask = screenBitmap;
node->Icon = CreateIconIndirect(&iconInfo);
DeleteObject(screenBitmap);
DeleteObject(bitmapActive);
DeleteDC(screenDc);
}
}
if (node->Icon)
{
DrawIconEx(
customDraw->Dc,
rect.left + 5,
rect.top + ((rect.bottom - rect.top) - 17) / 2,
node->Icon,
17,
17,
0,
NULL,
DI_NORMAL
);
}
}
rect.left += 19;
rect.left += 8;
rect.top += 5;
rect.right -= 5;
rect.bottom -= 8;
// top
SetTextColor(customDraw->Dc, RGB(0x0, 0x0, 0x0));
SelectObject(customDraw->Dc, context->TitleFontHandle);
text = PhIsNullOrEmptyString(node->Name) ? PhGetStringRef(node->InternalName) : PhGetStringRef(node->Name);
GetTextExtentPoint32(customDraw->Dc, text.Buffer, (ULONG)text.Length / 2, &nameSize);
DrawText(customDraw->Dc, text.Buffer, (ULONG)text.Length / 2, &rect, DT_TOP | DT_LEFT | DT_END_ELLIPSIS | DT_SINGLELINE);
// bottom
SetTextColor(customDraw->Dc, RGB(0x64, 0x64, 0x64));
SelectObject(customDraw->Dc, context->NormalFontHandle);
text = PhGetStringRef(node->Description);
GetTextExtentPoint32(customDraw->Dc, text.Buffer, (ULONG)text.Length / 2, &textSize);
DrawText(
customDraw->Dc,
text.Buffer,
(ULONG)text.Length / 2,
&rect,
DT_BOTTOM | DT_LEFT | DT_END_ELLIPSIS | DT_SINGLELINE
);
}
break;
}
}
return TRUE;
}
return FALSE;
}
VOID WeClearWindowTree(
_In_ PWCT_TREE_CONTEXT Context
)
{
for (ULONG i = 0; i < Context->NodeList->Count; i++)
WepDestroyWindowNode(Context->NodeList->Items[i]);
PhClearHashtable(Context->NodeHashtable);
PhClearList(Context->NodeList);
TreeNew_NodesStructured(Context->TreeNewHandle);
}
PPLUGIN_NODE WeGetSelectedWindowNode(
_In_ PWCT_TREE_CONTEXT Context
)
{
for (ULONG i = 0; i < Context->NodeList->Count; i++)
{
PPLUGIN_NODE windowNode = Context->NodeList->Items[i];
if (windowNode->Node.Selected)
return windowNode;
}
return NULL;
}
VOID WeGetSelectedWindowNodes(
_In_ PWCT_TREE_CONTEXT Context,
__out PPLUGIN_NODE **Windows,
__out PULONG NumberOfWindows
)
{
PPH_LIST list = PhCreateList(2);
for (ULONG i = 0; i < Context->NodeList->Count; i++)
{
PPLUGIN_NODE node = (PPLUGIN_NODE)Context->NodeList->Items[i];
if (node->Node.Selected)
PhAddItemList(list, node);
}
*Windows = PhAllocateCopy(list->Items, sizeof(PVOID) * list->Count);
*NumberOfWindows = list->Count;
PhDereferenceObject(list);
}

View File

@ -0,0 +1,2 @@
1.0
* Initial release

View File

@ -0,0 +1,150 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0c0904b0"
BEGIN
VALUE "CompanyName", "dmex"
VALUE "FileDescription", "Firewall Monitor plugin for Process Hacker"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "FirewallMonitorPlugin"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "FirewallMonitorPlugin.dll"
VALUE "ProductName", "Firewall Monitor plugin for Process Hacker"
VALUE "ProductVersion", "1.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_FW_MENU MENU
BEGIN
POPUP "Event"
BEGIN
MENUITEM "&Copy\aCtrl+C", ID_EVENT_COPY
MENUITEM SEPARATOR
MENUITEM "Properties", ID_FW_PROPERTIES
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_FWTABERROR DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
EXSTYLE WS_EX_TRANSPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Restart",IDC_RESTART,20,28,50,14
LTEXT "Firewall monitoring requires Process Hacker to be restarted with administrative privileges.",IDC_STATIC,16,14,286,8
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_FWTABERROR, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 302
TOPMARGIN, 7
BOTTOMMARGIN, 169
END
END
#endif // APSTUDIO_INVOKED
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{44A7C3BA-BAD5-40F3-AB70-442D44539053}</ProjectGuid>
<RootNamespace>FirewallMonitorPlugin</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>FirewallMonitorPlugin</ProjectName>
<WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\ExtraPlugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="fwdialog.c" />
<ClCompile Include="fwtab.c" />
<ClCompile Include="main.c" />
<ClCompile Include="monitor.c" />
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="FirewallMonitorPlugin.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="fwtabp.h" />
<ClInclude Include="fwmon.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="fwtab.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="monitor.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="fwdialog.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="FirewallMonitorPlugin.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="fwmon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="fwtabp.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,84 @@
/*
* Process Hacker Extra Plugins -
* Firewall Monitor
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "fwmon.h"
static INT_PTR CALLBACK OptionsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PFW_EVENT_NODE context;
if (uMsg == WM_INITDIALOG)
{
SetProp(hwndDlg, L"Context", (HANDLE)lParam);
context = (PFW_EVENT_NODE)GetProp(hwndDlg, L"Context");
}
else
{
context = (PFW_EVENT_NODE)GetProp(hwndDlg, L"Context");
if (uMsg == WM_DESTROY)
RemoveProp(hwndDlg, L"Context");
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
PhCenterWindow(hwndDlg, PhMainWndHandle);
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
EndDialog(hwndDlg, IDOK);
break;
}
}
break;
}
return FALSE;
}
NTSTATUS NTAPI ShowFwRuleProperties(
_In_ PVOID ThreadParameter
)
{
//DialogBoxParam(
// PluginInstance->DllBase,
// MAKEINTRESOURCE(IDD_PROPDIALOG),
// PhMainWndHandle,
// OptionsDlgProc,
// (LPARAM)ThreadParameter
// );
return STATUS_SUCCESS;
}

View File

@ -0,0 +1,105 @@
#ifndef FWMON_H
#define FWMON_H
#include <phdk.h>
#include "resource.h"
#include <Winsock2.h>
#include <fwpmu.h>
#include <fwpsu.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "fwpuclnt.lib")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "Ws2_32.lib")
#define PLUGIN_NAME L"dmex.FirewallMonitor"
#define SETTING_NAME_FW_TREE_LIST_COLUMNS (PLUGIN_NAME L".TreeListColumns")
#define SETTING_NAME_FW_TREE_LIST_SORT (PLUGIN_NAME L".TreeListSort")
extern PPH_PLUGIN PluginInstance;
extern BOOLEAN FwEnabled;
extern PPH_LIST FwNodeList;
typedef struct _FW_EVENT_ITEM
{
UINT16 LocalPort;
UINT16 RemotePort;
ULONG Index;
PPH_STRING IndexString;
LARGE_INTEGER AddedTime;
PPH_STRING TimeString;
PPH_STRING UserNameString;
PH_STRINGREF ProtocalString;
PPH_STRING ProcessNameString;
PPH_STRING ProcessBaseString;
PH_STRINGREF DirectionString;
PPH_STRING LocalPortString;
PPH_STRING LocalAddressString;
PPH_STRING RemotePortString;
PPH_STRING RemoteAddressString;
//HICON Icon;
PH_STRINGREF FwRuleActionString;
PPH_STRING FwRuleNameString;
PPH_STRING FwRuleDescriptionString;
PPH_STRING FwRuleLayerNameString;
PPH_STRING FwRuleLayerDescriptionString;
} FW_EVENT_ITEM, *PFW_EVENT_ITEM;
#define FWTNC_TIME 0
#define FWTNC_ACTION 1
#define FWTNC_RULENAME 2
#define FWTNC_RULEDESCRIPTION 3
#define FWTNC_PROCESSBASENAME 4
#define FWTNC_PROCESSFILENAME 5
#define FWTNC_USER 6
#define FWTNC_LOCALADDRESS 7
#define FWTNC_LOCALPORT 8
#define FWTNC_REMOTEADDRESS 9
#define FWTNC_REMOTEPORT 10
#define FWTNC_PROTOCOL 11
#define FWTNC_DIRECTION 12
#define FWTNC_INDEX 13
#define FWTNC_MAXIMUM 14
typedef struct _FW_EVENT_NODE
{
PH_TREENEW_NODE Node;
PH_STRINGREF TextCache[FWTNC_MAXIMUM];
PPH_STRING TooltipText;
PFW_EVENT_ITEM EventItem;
} FW_EVENT_NODE, *PFW_EVENT_NODE;
// monitor
extern PH_CALLBACK FwItemAddedEvent;
extern PH_CALLBACK FwItemModifiedEvent;
extern PH_CALLBACK FwItemRemovedEvent;
extern PH_CALLBACK FwItemsUpdatedEvent;
BOOLEAN StartFwMonitor(VOID);
VOID StopFwMonitor(VOID);
VOID InitializeFwTab(VOID);
VOID LoadSettingsFwTreeList(VOID);
VOID SaveSettingsFwTreeList(VOID);
NTSTATUS NTAPI ShowFwRuleProperties(
_In_ PVOID ThreadParameter
);
typedef ULONG (WINAPI* _FwpmNetEventSubscribe1)(
_In_ HANDLE engineHandle,
_In_ const FWPM_NET_EVENT_SUBSCRIPTION0* subscription,
_In_ FWPM_NET_EVENT_CALLBACK1 callback,
_In_opt_ void* context,
_Out_ HANDLE* eventsHandle
);
#endif

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More